#pragma implementation #include #include #include #include "../askrunlevel/askrunlevel.h" #include #include "hostinfo.h" #include "netconf.h" static const char K_IINFO[]="IINFO"; static const char K_NETCONFMODE[]="netconfmode"; static const char K_NETPCMCIA[]="netpcmcia"; static const char K_NETENABLE[]="netenable"; static const char K_NETWORK[]="network"; static const char K_HOSTNAME[]="hostname"; static const char K_NETMASK[]="netmask"; static const char K_IPADDR[]="ipaddr"; /* Get the network device name associated to one adaptor configuration */ static const char *host_getadaptordev(int n) { char key[9]; sprintf (key,"device%d",n); return linuxconf_getval(K_IINFO,key); } /* Get the network device name associated to one adaptor configuration */ static const char *host_getadaptordev(int n, char defval[6]) { sprintf (defval,"eth%d",n); const char *ret = host_getadaptordev(n); if (ret == NULL) ret = defval; return ret; } /* Tell if a network device is enabled or not */ static bool host_isdevenabled(int n) { char key[9]; sprintf (key,"device%d",n); return linuxconf_getvalnum (K_NETENABLE,key,1); } /* Set the special alias names used to recover device info from /etc/hosts */ void hostinfo_setnames (DEVICE_NAME_INFO &nm, int nodev) { sprintf (nm.host,"eth%d_loghost",nodev); if (nodev == 0) strcpy (nm.host,"loghost"); sprintf (nm.net,"eth%d_network",nodev); sprintf (nm.mask,"eth%d_netmask",nodev); sprintf (nm.bcast,"eth%d_broadcast",nodev); } static int (*fct_load)(HOSTS &, HOSTINFO &); static int (*fct_save)(HOSTS &, HOSTINFO &); /* Register the hook for the distribution dependant device registry */ void hostinfo_sethook ( int (*fload)(HOSTS &,HOSTINFO &), int (*fsave)(HOSTS &,HOSTINFO &)) { fct_load = fload; fct_save = fsave; } static void hostinfo_fixother( INTER_INFO &itf, HOST *hst, const char *spcalias) { // It is possible that an entry only have the alias name // There is no way to tell this just by reading /etc/hosts // The primary name is simply the first of the list // If the primary name is the special alias (loghost), we // organise things here. const char *name1 = hst->getname1(); if (strcmp(name1,spcalias)==0){ itf.others.append (" "); itf.others.append (spcalias); }else{ itf.name.setfrom (name1); itf.others.setfrom(hst->getothers()); } } static int hostinfo_loadinfo ( INTER_INFO &itf, HOSTS &hosts, NETWORKS &networks, int nodev) { int ret = -1; DEVICE_NAME_INFO nm; hostinfo_setnames (nm,nodev); char ad[20]; sprintf (ad,"adaptor%d",nodev); const char *ip = linuxconf_getval (K_IPADDR,ad); if (ip != NULL){ if (ip[0] != '\0'){ itf.ipaddr.setfrom (ip); itf.netmask.setfrom (linuxconf_getval(K_NETMASK,ad)); HOST *hst = hosts.getbyip (ip); if (hst != NULL){ hostinfo_fixother (itf,hst,nm.host); } ret = 0; } }else{ HOST *hst = hosts.getitem (nm.host); HOST *net = networks.getitem (nm.net); HOST *msk = networks.getitem (nm.mask); HOST *bcast = networks.getitem (nm.bcast); if (hst != NULL){ itf.ipaddr.setfrom(hst->getipnum()); hostinfo_fixother (itf,hst,nm.host); ret = 0; } if (net != NULL) itf.network.setfrom(net->getipnum()); if (msk != NULL) itf.netmask.setfrom(msk->getipnum()); if (bcast != NULL) itf.bcast.setfrom(bcast->getipnum()); } return ret; } void hostinfo_saveinfo(INTER_INFO &itf, int nodev) { char ad[20]; sprintf (ad,"adaptor%d",nodev); linuxconf_setcursys (subsys_stationid); linuxconf_replace (K_IPADDR,ad,itf.ipaddr); linuxconf_replace (K_NETMASK,ad,itf.netmask); } /* Load all basic information for all the adaptor from /etc/sysconfig/network-scripts and /etc/hosts and /etc/networks Return -1 if any error. */ int netconf_loadinfos( HOSTS &hosts, NETWORKS &networks, HOSTINFO &info) { int ret = -1; if (hosts.read () != -1 && networks.read() != -1){ /* #Specification: linuxconf vs distributions / network devices setting Linuxconf store the information about network devices in a combination of files. The IP number associated with the device goes in /etc/hosts, using a special alias. The netmask, network number and broadcast address are stored in /etc/networks. The network device and other setting such as the configuration mode (manual,bootp,dhcp) and the fact that the device is a PCMCIA are stored in /etc/conf.linuxconf. Distributions have their own solutions to this and to allows easier migration from their user base to linuxconf, linuxconf must be able to use and maintain those files. It must do so completly. So mostly, linuxconf has a strategy to migrate its own configurations to the distribution native one. The strategy to achieve that transparently is this. When reading: The linuxconf strategy has priority if data is available. In that case, the distribution specific file are ignored. When writing (updating) The distribution specific file are updated and the linuxconf specific information are erased. Next time, the distribution specific files will be used. In the case of network device, the key is the "device name" associated with a setting (eth0, eth1). If this information is available in conf.linuxconf, then linuxconf settings have priority. If they are missing, the distribution files are used. */ INTER_INFO *tbi[NB_ETH]; // To sort the interface later for (int j=0; jconfmode = INTER_MANUAL; pti->pcmcia = 0; pti->enable = (char)(j==0); IPX_INTER_INFO *itf = &pti->ipx; for (int f=0; fframes[f]; fra->netnum = 0; fra->primary = 0; fra->active = 0; } } if (fct_load != NULL && host_getadaptordev(0)==NULL){ // Read from distribution specific files ret = (*fct_load)(hosts,info); }else{ // Read device info using the generic linuxconf solution const char *hostname = linuxconf_getval (K_NETWORK,K_HOSTNAME,NULL); if (hostname == NULL){ /* #Specification: netconf / hostname storage Linuxconf used to store the hostname right in /etc/hosts. It was tagging the definition of the first adaptor with the alias "loghost". Unfortunatly, for bootp device, there is not always a name. Linuxconf now stores the hostname in /etc/conf.linuxconf, except on some distributions where the distribution specific strategy is used. */ HOST *h = hosts.getitem("loghost"); if (h != NULL){ hostname = h->getname1(); } } info.hostname.setfrom (hostname); info.nbdev = NB_ETH; for (int i=0; idevice.setfrom (device); char key[9]; sprintf (key,"device%d",i); pti->confmode = linuxconf_getvalnum (K_NETCONFMODE,key,0); pti->pcmcia = linuxconf_getvalnum (K_NETPCMCIA,key,0); pti->enable = host_isdevenabled(i); ipx_loadinter (pti->ipx,i); } } ret = 0; } SSTRINGS tbmodules; qsort (tbi,NB_ETH,sizeof(INTER_INFO*),host_cmp_inter); for (int i=0; idevice.get(); if (device[0] != '\0'){ modules_getsetting (device,pti->module ,pti->modio,pti->modirq); const char *module = pti->module.get(); if (module[0] != '\0'){ if (tbmodules.lookup(module)!=-1){ // We have already seen this module, so we clear // the settings. We do this because we will end up // with duplication at write time. // The real solution would be to spread the definition // This would be tricky and potentially unreliable // because one is not force to have an "alias" // statement in /etc/modules.conf for each net device // associated with a kernel module. pti->modio.setfrom(""); pti->modirq.setfrom(""); }else{ tbmodules.add (new SSTRING(module)); } } } } } return ret; } /* Load all basic information for all the adaptors from /etc/hosts and /etc/networks Return -1 if any error. */ int netconf_loadinfos(HOSTINFO &info) { HOSTS hosts; NETWORKS networks; return netconf_loadinfos(hosts,networks,info); } /* Save the information in distribution specific format Return true if this was saved so linuxconf does not have to save it in its own format */ bool hostinfo_saveindist (HOSTS &hosts, HOSTINFO &info) { if (fct_save != NULL) (*fct_save)(hosts,info); return fct_save != NULL; } void hostinfo_savehostname(HOSTINFO &info) { linuxconf_setcursys (subsys_stationid); linuxconf_replace (K_NETWORK,K_HOSTNAME,info.hostname); } void hostinfo_savefeatures(HOSTINFO &info, int nodev) { char key[9]; sprintf (key,"device%d",nodev); if (fct_save != NULL){ linuxconf_removeall (K_IINFO,key); linuxconf_removeall (K_NETPCMCIA,key); linuxconf_removeall (K_NETENABLE,key); linuxconf_removeall (K_NETCONFMODE,key); }else{ linuxconf_setcursys (subsys_hardware); linuxconf_replace (K_IINFO,key,info.a[nodev].device); linuxconf_replace (K_NETPCMCIA,key,info.a[nodev].pcmcia); linuxconf_setcursys (subsys_netclient); linuxconf_replace (K_NETENABLE,key,info.a[nodev].enable); linuxconf_replace (K_NETCONFMODE,key,info.a[nodev].confmode); linuxconf_setcursys (subsys_hardware); } } /* Record the configuration name and domain and IP of this host. This function is used by automated installation scripts which extract some information from distribution specific area and try to preset linuxconf */ void host_setdevdef( int nodev, // 0 ... 3 const char *name, // Fully qualified name const char *ip, const char *netmask, const char *device) { HOSTS hosts; NETWORKS networks; if (nodev >= 0 && nodev < 4 && hosts.read()!=-1 && networks.read()!=-1){ INTER_INFO itf; itf.name.setfrom (name); itf.ipaddr.setfrom (ip); itf.netmask.setfrom (netmask); // Extract the host name without domain char tmp[200]; strcpy (tmp,name); char *pt = strchr(tmp,'.'); if (pt != NULL){ *pt = '\0'; itf.others.setfrom (tmp); } DEVICE_NAME_INFO nm; hostinfo_setnames (nm,nodev); netconf_saveinfo (itf,hosts,networks ,nm.host,nm.net,nm.mask,nm.bcast); hosts.write(); networks.write (); linuxconf_setcursys (subsys_hardware); char devbuf[10]; sprintf (devbuf,"device%d",nodev); if (device[0] != '\0'){ linuxconf_replace (K_IINFO,devbuf,device); }else{ linuxconf_removeall (K_IINFO,devbuf); } linuxconf_save(); } }