#pragma implementation #include #include #ifdef __GLIBC__ #include #else #include #include #endif #include #include "internal.h" #include "netconf.h" #include "netconf.m" #include #include #include "hostinfo.h" #include NETCONF_HELP_FILE help_ipx("ipx"); static CONFIG_FILE f_ipx_inter (PROC_NET_IPX_INTER,help_ipx ,CONFIGF_PROBED|CONFIGF_OPTIONAL); static const char *tbipxframe[]={ "802.2","802.3","EtherII","snap" }; static const char IPX[]="ipx"; static const char INTERNAL_NETNUM[]="internal_netnum"; static const char INTERNAL_NODENUM[]="internal_nodenum"; static const char PRIMARY_AUTO[]="primary_auto"; static const char FRAME_AUTO[]="frame_auto"; static const char ACTIVE[]="active"; void ipx_saveinter (IPX_INTER_INFO &itf, int nodev) { for (int f=0; fnetnum,fra->active,fra->primary); linuxconf_replace (IPX,buf,val); } } void ipx_loadinter (IPX_INTER_INFO &itf, int nodev) { for (int f=0; fnetnum = 0; fra->primary = 0; fra->active = 0; char buf[20]; // We use ethN as the key even if this is unrelated to // ethernet device. ethN means adaptor N in this context sprintf (buf,"eth%d-%s",nodev,tbipxframe[f]); const char *val = linuxconf_getval (IPX,buf); if (val != NULL){ int active,primary; sscanf (val,"%x %d %d",&fra->netnum,&active,&primary); fra->primary = (char)primary; fra->active = (char)active; } } } /* Load the IPX configuration from /etc/conf.linuxconf */ PUBLIC IPX_INFO::IPX_INFO() { ipx_active = linuxconf_getvalnum (IPX,ACTIVE,0); internal_netnum = linuxconf_getvalnum (IPX,INTERNAL_NETNUM,0); internal_nodenum = linuxconf_getvalnum (IPX,INTERNAL_NODENUM,0); primary_auto = linuxconf_getvalnum (IPX,PRIMARY_AUTO,1); frame_auto = linuxconf_getvalnum (IPX,FRAME_AUTO,1); netconf_loadinfos (info); } /* Probe the IPX's "auto_configuration" flags in the kernel. */ PRIVATE void IPX_INFO::probe_auto() { /* #Specification: netconf / ipx / ioctl SIOCIPXCFGDATA linuxconf use the ioctl SIOCIPXCFGDATA to extract the status of the auto configuration flags of the IPX network. */ ipx_config_data data; int s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); if (s < 0) { xconf_error (MSG_U(E_IPXSOCKET ,"Can't open IPX control socket\n" "Looks ODD to me.\n" "Maybe linuxconf is incompatible with the kernel release")); }else if (ioctl(s, SIOCIPXCFGDATA, &data) == 0){ primary_auto = data.ipxcfg_auto_select_primary != 0; frame_auto = data.ipxcfg_auto_create_interfaces != 0; } } /* Load the IPX configuration from the kernel. */ PUBLIC IPX_INFO::IPX_INFO(CONFIG_FILE &f) { primary_auto = 0; frame_auto = 0; internal_netnum = 0; internal_nodenum = 0; ipx_active = 0; // We read the configuration to get information about the network // device associated with each interface netconf_loadinfos (info); // Then we wipe the information for frame primary_auto = frame_auto = 0; internal_netnum = internal_nodenum = 0; for (int j=0; jframes[f]; fra->active = 0; fra->primary = 0; fra->netnum = 0; } } // Then we load the whole stuff from the kernel FILE_CFG *fin = f.fopen ("r"); if (fin != NULL){ /* #Specification: netconf / ipx / file /proc/net/ipx_interface Linuxconf interprets the file /proc/net/ipx_interface to extract the running configuration in the kernel. The first line of this file is a header. The other lines have the following format. # network node primary dev frame # */ probe_auto(); char buf[300]; int format_err = 1; // Skip the header if (fgets(buf,sizeof(buf)-1,fin)!=NULL){ format_err = 0; while (fgets(buf,sizeof(buf)-1,fin)!=NULL){ char network[100], node[100],primary[100],dev[100],frame[100]; if (sscanf (buf,"%s %s %s %s %s" ,network,node,primary,dev,frame)!=5){ format_err = 1; break; }else if (stricmp(dev,"Internal")==0){ sscanf (network,"%x",&internal_netnum); sscanf (node,"%x",&internal_nodenum); }else{ int i; for (i=0; iframes[f]; fra->active = 1; fra->primary = stricmp(primary,"Yes")==0; sscanf (network,"%x",&fra->netnum); break; } } if (f==NB_IPX_FRAME_TYPE) format_err = 1; break; } } if (i==NB_ETH) format_err = 1; } } } fclose (fin); if (format_err){ xconf_error (MSG_U(E_IPXFORMAT ,"Invalid format of file %s\n" "Can't manage IPX properly\n") ,f_ipx_inter.getpath()); } } } PUBLIC int IPX_INFO::save() { int ret = -1; HOSTS hosts; NETWORKS networks; if (hosts.read()!=-1 && networks.read()!=-1){ linuxconf_setcursys (subsys_netclient); linuxconf_replace (IPX,ACTIVE,ipx_active); linuxconf_replace (IPX,INTERNAL_NETNUM,internal_netnum); linuxconf_replace (IPX,INTERNAL_NODENUM,internal_nodenum); linuxconf_replace (IPX,PRIMARY_AUTO,primary_auto); linuxconf_replace (IPX,FRAME_AUTO,frame_auto); netconf_saveinfos (hosts,networks,info); ret =linuxconf_save(); } return ret; } PUBLIC int IPX_INFO::edit() { DIALOG dia; dia.newf_title (MSG_U(F_CONFIG,"Config"),1,"",MSG_R(F_CONFIG)); dia.newf_chk (MSG_U(F_IPXENABLE,"Enable"),ipx_active ,MSG_U(F_IPXNETWORK,"IPX networking")); char f_primary = primary_auto ? 0 : 100; // 100 is anything different 0 dia.newf_radio (MSG_U(F_IPXAUTOCONFIG,"Autoconfigure") ,f_primary,0,MSG_U(F_PRIMARY,"primary")); dia.newf_chk (MSG_R(F_IPXAUTOCONFIG),frame_auto ,MSG_U(F_FRAMETYPES,"interfaces frame types")); int i; for (i=0; iframes[f]; dia.newf_chk (MSG_U(F_FRAMETYPE,"Frame type"),fra->active,tbipxframe[f]); int id = i*NB_IPX_FRAME_TYPE+f+1; if (fra->primary) f_primary = id; dia.newf_radio ("",f_primary,id,MSG_U(F_ISPRIMARY ,"is the primary interface")); static const char *tbopt[]={MSG_U(I_PROBE,"Probe"),NULL}; static const int tboptv[]={0,0}; dia.newf_chkm_hexnum (MSG_U(F_IPXNETNUM,"Network number (hex)") ,fra->netnum,tboptv,tbopt); } } dia.newf_title (MSG_U(T_IPXINTERNAL,"Internal net") ,1,"",MSG_R(T_IPXINTERNAL)); static const char *tbnone[]={MSG_U(I_NONE,"None"),NULL}; static const int tbnonev[]={0,0}; dia.newf_chkm_hexnum (MSG_U(F_IPXINTERNALNETNUM,"Internal network number") ,internal_netnum,tbnonev,tbnone); dia.newf_chkm_hexnum (MSG_U(F_IPXINTERNALNODENUM,"Internal node number") ,internal_nodenum,tbnonev,tbnone); int nof = 0; int ret = -1; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_IPXCONF,"IPX interface configuration") ,MSG_U(I_IPXCONF,"You must associate a frame type with\n" "a network devices and a network number\n" "For one device, it is possible to have several\n" "combination of frame and network number.\n" "Most linux client machine (IPX client) will be happy\n" "by selecting the \"autoconfigure\" choices.") ,help_ipx ,nof); if (code == MENU_CANCEL || code == MENU_ESCAPE){ dia.restore(); break; }else if (code == MENU_ACCEPT){ ret = 0; //we have to walk the structures to set/unset the primary field //of each potential IPX interface //Ony one can be primary primary_auto = f_primary == 0; for (i=0; iframes[f]; int id = i*NB_IPX_FRAME_TYPE+f+1; fra->primary = f_primary == id; } } break; } } return ret; } void ipx_edit() { IPX_INFO ipx; if (ipx.edit()==0) ipx.save(); } /* Activate/update conditionnally the IPX interface configuration for either all devices or a specific one */ PUBLIC int IPX_INFO::set( const char *dev, SSTRINGS &reconf) // Will contain the list of device to reconfigure // (Usefule for hint mode) { int ret = 0; IPX_INFO cur(f_ipx_inter); if (ipx_active){ if (dev == NULL){ if (primary_auto != cur.primary_auto){ net_hint ("HINT_IPXAUTOPRIMARY" ,primary_auto ? "yes" : "no"); } if (frame_auto != cur.frame_auto){ net_hint ("HINT_IPXAUTOFRAME" ,frame_auto ? "yes" : "no"); } } if (primary_auto != cur.primary_auto || frame_auto != cur.frame_auto){ char buf[100]; sprintf (buf,"--auto_interface=%s --auto_primary=%s" ,frame_auto ? "on" : "off" ,primary_auto ? "on" : "off"); netconf_system_if("ipx_configure",buf); } for (int i=0; iframes[f]; IPX_FRAME_INFO *cur_fra = &cur_itf->frames[f]; /* #Specification: netconf / ipx / managing Activating or not IPX interface is tricky. First we probe the current configuration (running) and compare it with the intend configuration. The problem comes from the fact that IPX interface can configure themselves from network trafic (if frame_auto is on). The idea here is to find out if the configuration of one interface is different from what is currently running. If so, then we must configure or unconfigure the interface. If we must unconfigure the interface we must check first if frame_auto is on. If so, the interface has been configured by itself, and we are not allowed to remove it. */ bool do_something = false; if (fra->active != cur_fra->active){ if (fra->active || !frame_auto){ do_something = true; } }else if (fra->active){ if (fra->netnum != cur_fra->netnum && fra->netnum != 0){ do_something = true; } if (fra->primary != cur_fra->primary && (fra->primary || !primary_auto)){ do_something = true; } } if (do_something){ reconf.add (new SSTRING(devname)); char buf[100]; char framevar[20]; static const char *tbframevar[]={ "802_2","802_3","ETHERII","SNAP" }; sprintf (framevar,"IPXFRAME_%s",tbframevar[f]); if (fra->active){ if (cur_fra->active){ sprintf (buf,"del %s %s",devname,tbipxframe[f]); ret |= netconf_system_if ("ipx_interface",buf); if (dev != NULL) net_hint (framevar,"reconf"); }else{ if (dev != NULL) net_hint (framevar,"add"); } int len = sprintf (buf,"add %s %s %s" ,fra->primary ? "-p" : "" ,devname,tbipxframe[f]); if (fra->netnum != 0){ sprintf (buf+len," %x",fra->netnum); } if (!dev_exist){ ret |= device_insmod (devname); dev_exist = true; // Shut off for next run } }else{ sprintf (buf,"del %s %s",devname,tbipxframe[f]); if (dev != NULL) net_hint (framevar,"del"); } ret |= netconf_system_if ("ipx_interface",buf); } } } if (internal_netnum != cur.internal_netnum || internal_nodenum != cur.internal_nodenum){ if (dev == NULL){ const char *verb = "reconf"; if (cur.internal_netnum == 0){ verb = "add"; }else if (internal_netnum == 0){ verb = "del"; } net_hint ("IPXINTERNALNET",verb); } if (internal_netnum != 0){ char buf[100]; sprintf (buf,"add %x %x",internal_netnum,internal_nodenum); ret |= netconf_system_if ("ipx_internal_net",buf); }else{ ret |= netconf_system_if ("ipx_internal_net","del"); } } } return ret; } int ipx_set ( const char *dev, SSTRINGS &reconf) // Will contain the list of device to reconfigure // (Usefule for hint mode) { IPX_INFO info; return info.set(dev,reconf); }