home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 13 / CDA13.ISO / MISC / SRC / INSTALL / NET.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-24  |  27.3 KB  |  1,098 lines

  1. #include <linux/if.h>
  2. #include <linux/route.h>
  3. #include <sys/ioctl.h>
  4. #include <sys/time.h>
  5. #include <sys/types.h>
  6.  
  7. #include <ctype.h>
  8. #include <errno.h>
  9. #include <netinet/in.h>
  10. #include <netinet/ip.h>
  11. #include <arpa/inet.h>
  12. #include <resolv.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17.  
  18. #include "bootpc.h"
  19. #include "devices.h"
  20. #include "install.h"
  21. #include "log.h"
  22. #include "newt.h"
  23. #include "net.h"
  24. #include "perror.h"
  25. #include "windows.h"
  26.  
  27. struct intfconfig_s {
  28.     newtComponent ipLabel, nmLabel, gwLabel, nsLabel;
  29.     newtComponent ipEntry, nmEntry, gwEntry, nsEntry;
  30.     char * ip, * nm, * gw, * ns;
  31.     char * bootpState;
  32. };
  33.  
  34. struct netconfig_s {
  35.     newtComponent nsLabels[3], hnLabel, dnLabel;
  36.     newtComponent nsEntrys[3], hnEntry, dnEntry;
  37.     char * ns[3], * gw, * hn, * dn;
  38. };
  39.  
  40. static void ipCallback(newtComponent co, void * data);
  41. static void hnCallback(newtComponent co, void * data);
  42.  
  43. /* It's a bit gross, but setupNetworkInterface() will setup your general
  44.    networking information if bootp is used */
  45. static int setupNetworkInterface(char * device, struct netInterface * intf,
  46.                  struct netConfig * netc,
  47.                      struct driversLoaded ** dl, int justConfig);
  48. static int doBringUpNetworking(struct netInterface * intf, 
  49.                    struct netConfig * netc,
  50.                    struct driversLoaded ** dl, int justConfig);
  51. static int configureNetDevice(struct netInterface * intf);
  52. /* intf in configureNetwork is optional */
  53. static int configureNetwork(struct netConfig * netc, 
  54.                 struct netInterface * intf);
  55.  
  56. static int doBootp(char * device, struct netInterface * intf,
  57.            struct netConfig * netc) {
  58.     struct netInterface minInterface;
  59.     int rc;
  60.  
  61.     if (testing) return 1;
  62.  
  63.     /* This is a bit of a hack, but it lets us use Jon Peatfield's bootp
  64.         code w/o hacking at it */
  65.  
  66.     logMessage("using bootp for device %s", device);
  67.  
  68.     minInterface.ip = minInterface.netmask = minInterface.network = 0;
  69.     minInterface.broadcast = 0xffffffff; 
  70.     strcpy(minInterface.dev, device);
  71.  
  72.     if (configureNetDevice(&minInterface)) {
  73.     logMessage("failed to setup minimal bootp interface %s", device);
  74.     return 1;
  75.     }
  76.  
  77.     winStatus(40, 3, "BOOTP", "Sending BOOTP request...");
  78.     rc = performBootp(device, "255.255.255.255", "", 10, 0, NULL, 0, 1,
  79.             BP_PUT_ENV);
  80.     newtPopWindow();
  81.  
  82.     if (rc) {
  83.     logMessage("performBootp() failed w/ return %d", rc);
  84.     return 1;
  85.     }
  86.  
  87.     if (!getenv("BOOTP_IPADDR")) {
  88.     errorWindow("bootp query did not return an IP address");
  89.     return 1;
  90.     }
  91.     
  92.     /* These will be generated by bootpc.c even if they're not in the
  93.        bootp reply */
  94.  
  95.     inet_aton(getenv("BOOTP_IPADDR"), (struct in_addr *) &intf->ip);
  96.     inet_aton(getenv("BOOTP_NETMASK"), (struct in_addr *) &intf->netmask);
  97.     inet_aton(getenv("BOOTP_BROADCAST"), (struct in_addr *) 
  98.             &intf->broadcast);
  99.     inet_aton(getenv("BOOTP_NETWORK"), (struct in_addr *) 
  100.             &intf->network);
  101.  
  102.     intf->useBootp = 1;
  103.     intf->isConfigured = 1;
  104.     strcpy(intf->dev, device);
  105.  
  106.     if (getenv("BOOTP_GATEWAYS_1")) {
  107.     strcpy(netc->defaultGateway, getenv("BOOTP_GATEWAYS_1"));
  108.     netc->isConfigured = 1;
  109.     }
  110.  
  111.     if (getenv("BOOTP_DNSSRVS_1")) {
  112.     netc->nameserver[0] = strdup(getenv("BOOTP_DNSSRVS_1"));
  113.     netc->isConfigured = 1;
  114.     if (getenv("BOOTP_DNSSRVS_2"))  {
  115.         netc->nameserver[1] = strdup(getenv("BOOTP_DNSSRVS_2"));
  116.         if (getenv("BOOTP_DNSSRVS_3")) 
  117.         netc->nameserver[2] = strdup(getenv("BOOTP_DNSSRVS_3"));
  118.     }
  119.     }
  120.  
  121.     /* 
  122.     If bootp gave us a hostname and domain, use those. Otherwise,
  123.     we'll try and query the nameserver a bit later on. If that fails
  124.     as well, we'll try and use just the hostname BOOTP gave us.
  125.     */
  126.  
  127.     if (getenv("BOOTP_HOSTNAME") && getenv("BOOTP_DOMAIN")) {
  128.     logMessage("bootp returned hostname and domain name");
  129.     strcpy(netc->hostname, getenv("BOOTP_HOSTNAME"));
  130.     netc->isConfigured = 1;
  131.  
  132.     strcpy(netc->domainname, getenv("BOOTP_DOMAIN"));
  133.  
  134.     if (strcmp(netc->hostname, netc->domainname) &&
  135.         !strstr(netc->hostname, netc->domainname)) {
  136.         strcat(netc->hostname, ".");
  137.         strcat(netc->hostname, netc->domainname);
  138.     }
  139.     } 
  140.  
  141.     return 0;
  142. }
  143.  
  144. /* The interface/gateway needs to be configured before this will work! */
  145. static int guessHostname(struct netInterface * intf, struct netConfig * netc) {
  146.     struct in_addr addr;
  147.     char ips[50];
  148.  
  149.     if (intf->isUp && netc->nameserver[0]) {
  150.     logMessage("using nameserver to find host and domain name");
  151.     writeResolvConf("/etc", netc);
  152.     memcpy(&addr, &intf->ip, sizeof(addr));
  153.     strcpy(ips, inet_ntoa(addr));
  154.     winStatus(40, 3, "Hostname", "Determing host name and domain...");
  155.         if (in2host(ips, BP_PUT_ENV)) {
  156.         newtPopWindow();
  157.         logMessage("reverse name lookup failed");
  158.  
  159.         if (getenv("BOOTP_HOSTNAME")) {
  160.         strcpy(netc->hostname, getenv("BOOTP_HOSTNAME"));
  161.         } 
  162.     } else {
  163.         newtPopWindow();
  164.         logMessage("reverse name lookup worked");
  165.         strcpy(netc->hostname, getenv("BOOTP_HOSTFULL"));
  166.         strcpy(netc->domainname, getenv("BOOTP_HOSTDOMAIN"));
  167.     }
  168.     }
  169.  
  170.     return 0;
  171. }
  172.  
  173. int addDefaultRoute(struct netConfig netc) {
  174.     int s;
  175.     struct rtentry route;
  176.     struct sockaddr_in addr;
  177.  
  178.     if (testing) return 0;
  179.  
  180.     if (!strlen(netc.defaultGateway)) return 0;
  181.  
  182.     s = socket(AF_INET, SOCK_DGRAM, 0);
  183.     if (s < 0) {
  184.     close(s);
  185.     errorWindow("socket: %s");
  186.     return 1;
  187.     }
  188.  
  189.     memset(&route, 0, sizeof(route));
  190.  
  191.     addr.sin_family = AF_INET;
  192.     addr.sin_port = 0;
  193.     inet_aton(netc.defaultGateway, &addr.sin_addr);
  194.     memcpy(&route.rt_gateway, &addr, sizeof(addr));
  195.  
  196.     addr.sin_addr.s_addr = INADDR_ANY;
  197.     memcpy(&route.rt_dst, &addr, sizeof(addr));
  198.     memcpy(&route.rt_genmask, &addr, sizeof(addr));
  199.  
  200.     route.rt_flags = RTF_UP | RTF_GATEWAY;
  201.     route.rt_metric = 0;
  202.  
  203.     if (ioctl(s, SIOCADDRT, &route)) {
  204.     close(s);
  205.     errorWindow("SIOCADDRT: %s");
  206.     return 1;
  207.     }
  208.  
  209.     return 0;
  210. }
  211.  
  212. static int configureNetDevice(struct netInterface * intf) {
  213.     struct ifreq req;
  214.     struct rtentry route;
  215.     int s;
  216.     struct sockaddr_in addr;
  217.     struct in_addr ia;
  218.     char ip[20], nm[20], nw[20], bc[20];
  219.  
  220.     addr.sin_family = AF_INET;
  221.     addr.sin_port = 0;
  222.  
  223.     memcpy(&ia, &intf->ip, sizeof(intf->ip));
  224.     strcpy(ip, inet_ntoa(ia));
  225.  
  226.     memcpy(&ia, &intf->netmask, sizeof(intf->netmask));
  227.     strcpy(nm, inet_ntoa(ia));
  228.  
  229.     memcpy(&ia, &intf->broadcast, sizeof(intf->broadcast));
  230.     strcpy(bc, inet_ntoa(ia));
  231.  
  232.     memcpy(&ia, &intf->network, sizeof(intf->network));
  233.     strcpy(nw, inet_ntoa(ia));
  234.  
  235.     logMessage("configuring %s ip: %s nm: %s nw: %s bc: %s", intf->dev,
  236.         ip, nm, nw, bc);
  237.  
  238.     if (testing) return 0;
  239.     
  240.     strcpy(req.ifr_name, intf->dev);
  241.     addr.sin_family = AF_INET;
  242.     addr.sin_port = 0;
  243.     memcpy(&addr.sin_addr, &intf->ip, sizeof(intf->ip));
  244.  
  245.     s = socket(AF_INET, SOCK_DGRAM, 0);
  246.     if (s < 0) {
  247.     errorWindow("socket: %s");
  248.     return 1;
  249.     }
  250.  
  251.     memcpy(&req.ifr_addr, &addr, sizeof(addr));
  252.     if (ioctl(s, SIOCSIFADDR, &req)) {
  253.     close(s);
  254.     errorWindow("SIOCSIFADDR: %s");
  255.     return 1;
  256.     }
  257.  
  258.     memcpy(&addr.sin_addr, &intf->broadcast, sizeof(intf->broadcast));
  259.     memcpy(&req.ifr_broadaddr, &addr, sizeof(addr));
  260.     if (ioctl(s, SIOCSIFBRDADDR, &req)) {
  261.     close(s);
  262.     errorWindow("SIOCSIFNETMASK: %s");
  263.     return 1;
  264.     }
  265.  
  266.     memcpy(&addr.sin_addr, &intf->netmask, sizeof(intf->netmask));
  267.     memcpy(&req.ifr_netmask, &addr, sizeof(addr));
  268.     if (ioctl(s, SIOCSIFNETMASK, &req)) {
  269.     close(s);
  270.     errorWindow("SIOCSIFNETMASK: %s");
  271.     return 1;
  272.     }
  273.  
  274.     req.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
  275.     if (ioctl(s, SIOCSIFFLAGS, &req)) {
  276.     close(s);
  277.     errorWindow("SIOCSIFFLAGS: %s");
  278.     return 1;
  279.     }
  280.  
  281.     memset(&route, 0, sizeof(route));
  282.     route.rt_dev = intf->dev;
  283.     route.rt_flags = RTF_UP;
  284.  
  285.     memcpy(&addr.sin_addr, &intf->network, sizeof(intf->netmask));
  286.     memcpy(&route.rt_dst, &addr, sizeof(addr));
  287.  
  288.     memcpy(&addr.sin_addr, &intf->netmask, sizeof(intf->netmask));
  289.     memcpy(&route.rt_genmask, &addr, sizeof(addr));
  290.  
  291.     if (ioctl(s, SIOCADDRT, &route)) {
  292.     close(s);
  293.     errorWindow("SIOCADDRT: %s");
  294.     return 1;
  295.     }
  296.  
  297.     intf->isUp = 1;
  298.  
  299.     return 0;
  300. }
  301.  
  302. int netDeviceAvailable(char * device) {
  303.     struct ifreq req;
  304.     int s;
  305.     
  306.     s = socket(AF_INET, SOCK_DGRAM, 0);
  307.     if (s < 0) {
  308.     close(s);
  309.     errorWindow("socket: %s");
  310.     return 1;
  311.     }
  312.  
  313.     strcpy(req.ifr_name, device);
  314.  
  315.     if (ioctl(s, SIOCGIFFLAGS, &req)) {
  316.     /* if we can't get the flags, the networking device isn't available */
  317.     close(s);
  318.     return 0;
  319.     }
  320.   
  321.     return 1;
  322. }
  323.  
  324. static void interfaceConfigToggle(newtComponent co, void * arg) {
  325.     struct intfconfig_s * info = arg;
  326.     int sense = NEWT_FLAGS_SET;
  327.  
  328.     if (*info->bootpState == ' ') 
  329.     sense = NEWT_FLAGS_RESET;
  330.  
  331.     newtEntrySetFlags(info->ipEntry, NEWT_ENTRY_DISABLED, sense);
  332.     newtEntrySetFlags(info->nmEntry, NEWT_ENTRY_DISABLED, sense);
  333.     newtEntrySetFlags(info->gwEntry, NEWT_ENTRY_DISABLED, sense);
  334.     newtEntrySetFlags(info->nsEntry, NEWT_ENTRY_DISABLED, sense);
  335.  
  336.     newtRefresh();
  337. }
  338.  
  339. static int setupNetworkInterface(char * device, struct netInterface * intf,
  340.                  struct netConfig * netc,
  341.                      struct driversLoaded ** dl, int justConfig) {
  342.     newtComponent okay, cancel, bootp, f, answer;
  343.     int top = 4;
  344.     struct intfconfig_s c;
  345.     struct in_addr addr;
  346.     int rc;
  347.     int done = 0;
  348.     char useBootp;
  349.  
  350.     if (!netDeviceAvailable(device)) {
  351.     if ((rc = loadDeviceDriver(DRIVER_ETHERNET, dl)))
  352.         return rc;
  353.     }
  354.  
  355.     newtOpenWindow(15, 4, 50, 15, "Configure TCP/IP");
  356.  
  357.     c.ipLabel = newtLabel(1, top + 2, "IP address:");
  358.     c.nmLabel = newtLabel(1, top + 3, "Netmask:");
  359.     c.gwLabel = newtLabel(1, top + 4, "Default gateway (IP):");
  360.     c.nsLabel = newtLabel(1, top + 5, "Primary nameserver:");
  361.    
  362.     if (!intf->ip){
  363.     c.ipEntry = newtEntry(25, top + 2, "", 16, &c.ip, 0);
  364.     } else {
  365.     memcpy(&addr, &intf->ip, sizeof(intf->ip));
  366.     c.ipEntry = newtEntry(25, top + 2, inet_ntoa(addr), 16, &c.ip, 0);
  367.     }
  368.  
  369.     if (!intf->netmask){
  370.     c.nmEntry = newtEntry(25, top + 3, "", 16, &c.nm, 0);
  371.     } else {
  372.     memcpy(&addr, &intf->netmask, sizeof(intf->netmask));
  373.     c.nmEntry = newtEntry(25, top + 3, inet_ntoa(addr), 16, &c.nm, 0);
  374.     }
  375.  
  376.     if (!netc->defaultGateway) 
  377.     c.gwEntry = newtEntry(25, top + 4, "", 16, &c.gw, 0);
  378.     else
  379.     c.gwEntry = newtEntry(25, top + 4, netc->defaultGateway, 16, &c.gw, 0);
  380.  
  381.  
  382.     if (!netc->nameserver[0]) 
  383.     c.nsEntry = newtEntry(25, top + 5, "", 16, &c.ns, 0);
  384.     else
  385.     c.nsEntry = newtEntry(25, top + 5, netc->nameserver[0], 16, &c.gw, 0);
  386.     
  387.     c.bootpState = &useBootp;
  388.    
  389.     f = newtForm(NULL, NULL, 0);
  390.  
  391.     bootp = newtCheckbox(1, top, "Configure device with bootp", 
  392.              (intf->isConfigured && intf->useBootp) ? '*' : ' ', 
  393.              NULL, &useBootp);
  394.  
  395.     newtComponentAddCallback(bootp, interfaceConfigToggle, &c);
  396.  
  397.     newtFormAddComponents(f, bootp, c.ipLabel, c.nmLabel, c.gwLabel, c.nsLabel, 
  398.                  c.ipEntry, c.nmEntry, c.gwEntry, c.nsEntry, NULL);
  399.  
  400.     if (c.bootpState)
  401.     newtFormSetCurrent(f, c.ipEntry);
  402.  
  403.     newtComponentAddCallback(c.ipEntry, ipCallback, &c);
  404.     newtComponentAddCallback(c.nmEntry, ipCallback, &c);
  405.  
  406.     okay = newtButton(8, top + 7, "Ok");
  407.     cancel = newtButton(28, top + 7, "Cancel");
  408.  
  409.     newtFormAddComponents(f, okay, cancel, NULL);
  410.  
  411.     do {
  412.     answer = newtRunForm(f);
  413.  
  414.     if (answer == cancel) {
  415.         newtFormDestroy(f);
  416.         newtPopWindow();
  417.  
  418.         return INST_CANCEL;
  419.     }
  420.  
  421.     if (useBootp != ' ') {
  422.         logMessage("Configuring device %s via bootp", device);
  423.         if (justConfig) {
  424.         done = 1;
  425.         } else if (!doBootp(device, intf, netc)) {
  426.         done = 1;
  427.         }
  428.     } else {
  429.         strcpy(intf->dev, device);
  430.         inet_aton(c.ip, (struct in_addr *) &intf->ip);
  431.         inet_aton(c.nm, (struct in_addr *) &intf->netmask);
  432.         intf->network = intf->ip & intf->netmask;
  433.         intf->broadcast = (intf->ip & intf->netmask) | (~intf->netmask);
  434.  
  435.         intf->isConfigured = 1;
  436.  
  437.         strcpy(netc->defaultGateway, c.gw);
  438.  
  439.         if (netc->nameserver[0]) free(netc->nameserver[0]);
  440.  
  441.         if (strlen(c.ns))
  442.         netc->nameserver[0] = strdup(c.ns);
  443.         else
  444.         netc->nameserver[0] = NULL;
  445.         
  446.         netc->isConfigured = 1;
  447.  
  448.         done = 1;
  449.     }
  450.     } while (!done);
  451.  
  452.     newtFormDestroy(f);
  453.     newtPopWindow();
  454.  
  455.     if (!justConfig) {
  456.     if (configureNetDevice(intf)) return INST_ERROR;
  457.     if (addDefaultRoute(*netc)) return INST_ERROR;
  458.     }
  459.  
  460.     return 0;
  461.  
  462. static void hnCallback(newtComponent co, void * dptr) {
  463.     char * buf;
  464.     struct netconfig_s * data = dptr;
  465.  
  466.     if (strlen(data->hn)) return;
  467.     if (!strlen(data->dn)) return;
  468.  
  469.     buf = alloca(strlen(data->dn) + 5);
  470.     strcpy(buf, ".");
  471.     strcat(buf, data->dn);
  472.     
  473.     newtEntrySet(data->hnEntry, buf, 0);
  474. }
  475.  
  476. static void ipCallback(newtComponent co, void * dptr) {
  477.     struct intfconfig_s * data = dptr;
  478.     struct in_addr ipaddr, nmaddr, addr;
  479.     char * ascii;
  480.     int32 broadcast, network;
  481.  
  482.     if (co == data->ipEntry) {
  483.     if (strlen(data->ip) && !strlen(data->nm)) {
  484.         if (inet_aton(data->ip, &ipaddr)) {
  485.         ipaddr.s_addr = ntohl(ipaddr.s_addr);
  486.         if (((ipaddr.s_addr & 0xFF000000) >> 24) <= 127)
  487.             ascii = "255.0.0.0";
  488.         else if (((ipaddr.s_addr & 0xFF000000) >> 24) <= 191)
  489.             ascii = "255.255.0.0";
  490.         else 
  491.             ascii = "255.255.255.0";
  492.         newtEntrySet(data->nmEntry, ascii, 1);
  493.         }
  494.     }
  495.     } else if (co == data->nmEntry) {
  496.     if (!strlen(data->ip) || !strlen(data->nm)) return;
  497.     if (!inet_aton(data->ip, &ipaddr)) return;
  498.     if (!inet_aton(data->nm, &nmaddr)) return;
  499.  
  500.         network = ipaddr.s_addr & nmaddr.s_addr;
  501.     broadcast = (ipaddr.s_addr & nmaddr.s_addr) | (~nmaddr.s_addr);
  502.  
  503.     addr.s_addr = htonl(ntohl(broadcast) - 1);
  504.     newtEntrySet(data->gwEntry, inet_ntoa(addr), 1);
  505.  
  506.     /* I'm such a lazy bastard */
  507.     if ((ntohl(network) & 0xFFFFFF00) == 0xc7b71800) {
  508.         newtEntrySet(data->nsEntry, "199.183.24.1", 1);
  509.     } else {
  510.         addr.s_addr = htonl(ntohl(network) + 1);
  511.         newtEntrySet(data->nsEntry, inet_ntoa(addr), 1);
  512.     }
  513.     }
  514. }
  515.  
  516. int writeNetConfig(char * prefix, struct netConfig * netc, 
  517.            struct netInterface * gwdev, int verbose) {
  518.     char filename[100];
  519.     FILE * f;
  520.  
  521.     if (testing) return 0;
  522.  
  523.     sprintf(filename, "%s/network", prefix);
  524.  
  525.     f = fopen(filename, "w");
  526.     if (!f) {
  527.     errorWindow("cannot create network config file: %s");
  528.     return INST_ERROR;
  529.     }
  530.  
  531.     fprintf(f, "NETWORKING=yes\n");
  532.  
  533.     logMessage("writing network information to %s", filename);
  534.  
  535.     if (netc->hostname && strlen(netc->hostname)) {
  536.     logMessage("\tnetwork is configured, writing complete information");
  537.     fprintf(f, "HOSTNAME=%s\n", netc->hostname);
  538.     fprintf(f, "DOMAINNAME=%s\n", netc->domainname);
  539.  
  540.     if (gwdev && strlen(netc->defaultGateway)) {
  541.         fprintf(f, "GATEWAY=%s\n", netc->defaultGateway);
  542.         fprintf(f, "GATEWAYDEV=%s\n", gwdev->dev);
  543.     }
  544.  
  545.     if (verbose) {
  546.         if (netc->nameserver[0])
  547.         fprintf(f, "NS1=%s\n", netc->nameserver[0]);
  548.         
  549.         if (netc->nameserver[1])
  550.         fprintf(f, "NS2=%s\n", netc->nameserver[1]);
  551.         
  552.         if (netc->nameserver[2])
  553.         fprintf(f, "NS3=%s\n", netc->nameserver[2]);
  554.     }
  555.     } else {
  556.     logMessage("\tnetwork is not configured");
  557.     fprintf(f, "HOSTNAME=localhost.localdomain\n");
  558.     }
  559.  
  560.     fclose(f);
  561.  
  562.     return 0;
  563. }
  564.  
  565. int writeHosts(char * prefix, struct netConfig * netc, 
  566.            struct netInterface * intf) {
  567.     char filename[100];
  568.     FILE * f;
  569.     struct in_addr * addrptr;
  570.     char * nickname;
  571.     int i;
  572.  
  573.     if (testing) return 1;
  574.  
  575.     sprintf(filename, "%s/hosts", prefix);
  576.  
  577.     /* if /etc/hosts already exists, don't bother creating one */
  578.     if (!access(filename, R_OK)) {
  579.     logMessage("%s already exists -- won't crunch it", filename);
  580.     return 0;
  581.     }
  582.     logMessage("%s doesn not exist -- creating", filename);
  583.  
  584.     f = fopen(filename, "w");
  585.     if (!f) {
  586.     errorWindow("cannot create /etc/hosts: %s");
  587.     return INST_ERROR;
  588.     }
  589.  
  590.     logMessage("writing host information to %s", filename);
  591.  
  592.     fprintf(f, "127.0.0.1\t\tlocalhost localhost.localdomain\n");
  593.     if (netc->hostname && strlen(netc->hostname)) {
  594.     addrptr = (struct in_addr *) &intf->ip;
  595.     i = strlen(netc->hostname) - strlen(netc->domainname);
  596.     if (i > 1 && !strcmp(netc->hostname + i, netc->domainname)
  597.         && netc->hostname[i - 1] == '.') {
  598.         nickname = strdup(netc->hostname);
  599.         nickname[i - 1] = '\0';
  600.         fprintf(f, "%s\t\t%s %s\n", inet_ntoa(*addrptr),
  601.             netc->hostname, nickname);
  602.         free(nickname);
  603.     } else {
  604.         fprintf(f, "%s\t\t%s\n", inet_ntoa(*addrptr),
  605.             netc->hostname);
  606.     }
  607.  
  608.     sethostname(netc->hostname, strlen(netc->hostname));
  609.     }
  610.  
  611.     fclose(f);
  612.  
  613.     res_init();        /* reinit the resolver so DNS changes take affect */
  614.  
  615.     return 0;
  616. }
  617.  
  618. int writeResolvConf(char * prefix, struct netConfig * netc) {
  619.     char filename[100];
  620.     FILE * f;
  621.  
  622.     if (testing) return 1;
  623.  
  624.     if (!netc->domainname && !netc->nameserver[0]) {
  625.     logMessage("networking is not configured - not writing resolv.conf");
  626.     return 0;
  627.     }
  628.  
  629.     sprintf(filename, "%s/resolv.conf", prefix);
  630.  
  631.     f = fopen(filename, "w");
  632.     if (!f) {
  633.     errorWindow("cannot create resolv.conf: %s");
  634.     return INST_ERROR;
  635.     }
  636.  
  637.     logMessage("writing nameservices information to %s", filename);
  638.  
  639.     if (netc->domainname)
  640.     fprintf(f, "search %s\n", netc->domainname);
  641.  
  642.     if (netc->nameserver[0])
  643.     fprintf(f, "nameserver %s\n", netc->nameserver[0]);
  644.     
  645.     if (netc->nameserver[1])
  646.     fprintf(f, "nameserver %s\n", netc->nameserver[1]);
  647.     
  648.     if (netc->nameserver[2])
  649.     fprintf(f, "nameserver %s\n", netc->nameserver[2]);
  650.  
  651.     fclose(f);
  652.  
  653.     res_init();        /* reinit the resolver so DNS changes take affect */
  654.  
  655.     return 0;
  656. }
  657.  
  658. int writeNetInterfaceConfig(char * prefix, struct netInterface * intf) {
  659.     char filename[100];
  660.     FILE * f;
  661.     struct in_addr * addrptr;
  662.  
  663.     if (testing) return 0;
  664.  
  665.     if (!intf->isConfigured) {
  666.     logMessage("network interface is not configured - not creating "
  667.            "ifcfg-*");
  668.     return(0);
  669.     }
  670.  
  671.     sprintf(filename, "%s/ifcfg-%s", prefix, intf->dev);
  672.  
  673.     f = fopen(filename, "w");
  674.     if (!f) {
  675.     errorWindow("cannot create network device config file: %s");
  676.     return INST_ERROR;
  677.     }
  678.  
  679.     logMessage("writing network information to %s", filename);
  680.     
  681.     fprintf(f, "DEVICE=%s\n", intf->dev);
  682.  
  683.     if (intf->useBootp) fprintf(f, "BOOTP=yes\n");
  684.  
  685.     addrptr = (struct in_addr *) &intf->ip;
  686.     fprintf(f, "IPADDR=%s\n", inet_ntoa(*addrptr));
  687.  
  688.     addrptr = (struct in_addr *) &intf->netmask;
  689.     fprintf(f, "NETMASK=%s\n", inet_ntoa(*addrptr));
  690.  
  691.     addrptr = (struct in_addr *) &intf->network;
  692.     fprintf(f, "NETWORK=%s\n", inet_ntoa(*addrptr));
  693.  
  694.     addrptr = (struct in_addr *) &intf->broadcast;
  695.     fprintf(f, "BROADCAST=%s\n", inet_ntoa(*addrptr));
  696.  
  697.     fprintf(f, "ONBOOT=yes\n");
  698.  
  699.     fclose(f);
  700.  
  701.     return 0;
  702. }
  703.  
  704. int readNetInterfaceConfig(char * prefix, char * device, 
  705.                   struct netInterface * intf) {
  706.     FILE * f;
  707.     char * start, * end;
  708.     char buf[250];
  709.     int line = 0;
  710.  
  711.     intf->isConfigured = 0;
  712.  
  713.     if (testing) {
  714.     return 0;
  715.     }
  716.  
  717.     sprintf(buf, "%s/ifcfg-%s", prefix, device);
  718.  
  719.     f = fopen(buf, "r");
  720.     if (!f) {
  721.     if (errno != ENOENT) {
  722.         errorWindow("cannot open file: %s");
  723.         return INST_ERROR;
  724.     } else {
  725.         intf->ip = 0;
  726.         return 0;
  727.     }
  728.     }
  729.  
  730.     while (fgets(buf, sizeof(buf) - 1, f)) {
  731.     line++;
  732.  
  733.     start = buf;
  734.  
  735.     /* skipping leading spaces */
  736.     while (*start && isspace(*start)) start++;
  737.     if (!*start) continue;
  738.  
  739.     /* skip comments */
  740.     if (*start == '#') continue;
  741.  
  742.     /* cut off trailing spaces and \n */
  743.     end = start + strlen(start) - 2;
  744.     while (isspace(*end)) end--;
  745.     end++;
  746.     *end = '\0';    
  747.     end--;
  748.     
  749.     if (!strncmp("IPADDR=", start, 7)) {
  750.         start += 7;
  751.         inet_aton(start, (struct in_addr *) &intf->ip);
  752.     } else if (!strncmp("BOOTP=", start, 6)) {
  753.         intf->useBootp = 1;
  754.     } else if (!strncmp("NETMASK=", start, 8)) {
  755.         start += 8;
  756.         inet_aton(start, (struct in_addr *) &intf->netmask);
  757.     } else if (!strncmp("NETWORK=", start, 8)) {
  758.         start += 8;
  759.         inet_aton(start, (struct in_addr *) &intf->network);
  760.     } else if (!strncmp("BROADCAST=", start, 10)) {
  761.         start += 10;
  762.         inet_aton(start, (struct in_addr *) &intf->broadcast);
  763.     }
  764.     }
  765.  
  766.     fclose(f);
  767.  
  768.     strcpy(intf->dev, device);
  769.  
  770.     intf->isConfigured = 1;
  771.  
  772.     return 0;
  773. }
  774.  
  775. int configureNetwork(struct netConfig * netc, 
  776.              struct netInterface * intf) {
  777.     struct netconfig_s n;
  778.     int top = 3;
  779.     newtComponent f, okay, cancel, answer;
  780.     char * chptr;
  781.     int i;
  782.  
  783.     newtOpenWindow(15, 4, 50, 15, "Configure Network");
  784.  
  785.     n.dnLabel = newtLabel(1, top    , "Domain name:");
  786.     n.hnLabel = newtLabel(1, top + 1, "Host name:");
  787.     n.nsLabels[1] = newtLabel(1, top + 2, "Secondary nameserver (IP):");
  788.     n.nsLabels[2] = newtLabel(1, top + 3, "Tertiary nameserver (IP):");
  789.  
  790.     n.dnEntry = newtEntry(28, top    , "", 20, &n.dn, NEWT_ENTRY_SCROLL);
  791.     n.hnEntry = newtEntry(28, top + 1, "", 20, &n.hn, NEWT_ENTRY_SCROLL);
  792.     n.nsEntrys[1] = newtEntry(28, top + 2, "", 20, &n.ns[1], NEWT_ENTRY_SCROLL);
  793.     n.nsEntrys[2] = newtEntry(28, top + 3, "", 20, &n.ns[2], NEWT_ENTRY_SCROLL);
  794.  
  795.     if (!strlen(netc->hostname) && !strlen(netc->domainname) && intf->isUp && 
  796.     netc->nameserver[0]) {
  797.     guessHostname(intf, netc);
  798.     } 
  799.  
  800.     if (netc->hostname)
  801.     newtEntrySet(n.hnEntry, netc->hostname, 0);
  802.  
  803.     if (netc->domainname)
  804.     newtEntrySet(n.dnEntry, netc->domainname, 0);
  805.  
  806.     if (netc->nameserver[1])
  807.     newtEntrySet(n.nsEntrys[1], netc->nameserver[1], 0);
  808.     if (netc->nameserver[2])
  809.     newtEntrySet(n.nsEntrys[2], netc->nameserver[2], 0);
  810.  
  811.     newtComponentAddCallback(n.dnEntry, hnCallback, &n);
  812.  
  813.     f = newtForm(NULL, NULL, 0);
  814.     newtFormAddComponents(f, n.dnLabel, n.hnLabel, n.nsLabels[1], 
  815.               n.nsLabels[2], NULL);
  816.     newtFormAddComponents(f, n.dnEntry, n.hnEntry, n.nsEntrys[1], 
  817.               n.nsEntrys[2], NULL);
  818.  
  819.     okay = newtButton(11, 11, "Ok");
  820.     cancel = newtButton(30, 11, "Cancel");
  821.  
  822.     newtFormAddComponents(f, okay, cancel, NULL);
  823.  
  824.     answer = newtRunForm(f);
  825.  
  826.     strcpy(netc->hostname, n.hn);
  827.     strcpy(netc->domainname, n.dn);
  828.  
  829.     for (i = 1; i < 3; i++) {
  830.     if (netc->nameserver[i]) 
  831.         free(netc->nameserver[i]);
  832.     netc->nameserver[i] = *n.ns[i] ? strdup(n.ns[i]) : NULL;
  833.     }
  834.  
  835.     newtFormDestroy(f);
  836.     newtPopWindow();
  837.  
  838.     if (answer == cancel) return INST_CANCEL;
  839.  
  840.     netc->isConfigured = 1;
  841.  
  842.     return 0;
  843. }
  844.  
  845. int readNetConfig(char * prefix, struct netConfig * netc) {
  846.     FILE * f;
  847.     char * start, * end;
  848.     char buf[250];
  849.     int line = 0;
  850.  
  851.     if (testing) {
  852.     return 0;
  853.     }
  854.  
  855.     sprintf(buf, "%s/network", prefix);
  856.  
  857.     f = fopen(buf, "r");
  858.     if (!f) {
  859.     if (errno != ENOENT) {
  860.         errorWindow("cannot open file: %s");
  861.         return INST_ERROR;
  862.     } else {
  863.         netc->hostname[0] = '\0';
  864.         return 0;
  865.     }
  866.     }
  867.  
  868.     memset(netc, 0, sizeof(*netc));
  869.  
  870.     while (fgets(buf, sizeof(buf) - 1, f)) {
  871.     line++;
  872.  
  873.     start = buf;
  874.  
  875.     /* skipping leading spaces */
  876.     while (*start && isspace(*start)) start++;
  877.     if (!*start) continue;
  878.  
  879.     /* skip comments */
  880.     if (*start == '#') continue;
  881.  
  882.     /* cut off trailing spaces and \n */
  883.     end = start + strlen(start) - 2;
  884.     while (isspace(*end)) end--;
  885.     end++;
  886.     *end = '\0';    
  887.     end--;
  888.     
  889.     if (!strncmp("HOSTNAME=", start, 9)) {
  890.         start += 9;
  891.         strcpy(netc->hostname, start);
  892.     } else if (!strncmp("DOMAINNAME=", start, 11)) {
  893.         start += 11;
  894.         strcpy(netc->domainname, start);
  895.     } else if (!strncmp("GATEWAY=", start, 8)) {
  896.         start += 8;
  897.         strcpy(netc->defaultGateway, start);
  898.     } else if (!strncmp("NS1=", start, 4)) {
  899.         start += 4;
  900.         netc->nameserver[0] = strdup(start);
  901.     } else if (!strncmp("NS2=", start, 4)) {
  902.         start += 4;
  903.         netc->nameserver[1] = strdup(start);
  904.     } else if (!strncmp("NS3=", start, 4)) {
  905.         start += 4;
  906.         netc->nameserver[2] = strdup(start);
  907.     }
  908.     }
  909.  
  910.     fclose(f);
  911.  
  912.     netc->isConfigured = 1;
  913.  
  914.     return 0;
  915. }
  916.  
  917.  
  918. int bringUpNetworking(struct netInterface * intf, struct netConfig * netc,
  919.               struct driversLoaded ** dl) {
  920.     return doBringUpNetworking(intf, netc, dl, 0);
  921. }
  922.  
  923. #define BRINGUP_NET     1
  924. #define BRINGUP_CONF    2
  925. #define BRINGUP_ROUTE    3
  926. #define BRINGUP_DONE    4
  927.  
  928. static int doBringUpNetworking(struct netInterface * intf, 
  929.                    struct netConfig * netc,
  930.                    struct driversLoaded ** dl, int justConfig) {
  931.     int where = BRINGUP_NET;
  932.     int rc;
  933.  
  934.     while (where != BRINGUP_DONE) {
  935.     switch (where) {
  936.       case BRINGUP_NET:
  937.         rc = setupNetworkInterface("eth0", intf, netc, dl, justConfig);
  938.         if (rc) return rc;
  939.         where = BRINGUP_CONF;
  940.         break;
  941.  
  942.       case BRINGUP_CONF:
  943.         rc = configureNetwork(netc, intf);
  944.         if (rc == INST_CANCEL)
  945.         where = BRINGUP_NET;
  946.         else if (rc)
  947.         return INST_ERROR;
  948.         else
  949.         where = BRINGUP_ROUTE;
  950.         break;
  951.  
  952.       case BRINGUP_ROUTE:
  953.         if (justConfig)
  954.         rc = 0;
  955.         else
  956.         rc = addDefaultRoute(*netc);
  957.  
  958.         if (rc) return rc;
  959.         where = BRINGUP_DONE;
  960.         break;
  961.     }
  962.     }
  963.  
  964.     /* write out the /etc/resolv.conf, as we'll need that to use name services
  965.        properly */
  966.     writeResolvConf("/etc", netc);
  967.  
  968.     return 0;
  969. }
  970.  
  971. #define CHECKNET_CONFIG        1
  972. #define CHECKNET_KEEP        2
  973. #define CHECKNET_NONE        3
  974. #define CHECKNET_NOBOOTP    4
  975.  
  976. static int checkNetConfigPanel(int isConfigured, int useBootp, int * choice) {
  977.     newtComponent text, okay, cancel;
  978.     newtComponent f, answer, yes, no, listbox;
  979.     int which;
  980.  
  981.     if (isConfigured) {
  982.     newtOpenWindow(18, 5, 42, 13, "Network Configuration");
  983.     text = newtTextbox(1, 1, 40, 2, NEWT_TEXTBOX_WRAP);
  984.     newtTextboxSetText(text,
  985.         "LAN networking has already been configured. Do you "
  986.         "want to:");
  987.  
  988.     listbox = newtListbox(8, 4, 0, NEWT_LISTBOX_RETURNEXIT);
  989.  
  990.     if (useBootp) {
  991.         newtListboxAddEntry(listbox, "Use bootp at startup", (void *) 1);
  992.         newtListboxAddEntry(listbox, "Use the current IP information", 
  993.                       (void *) 4);
  994.         newtListboxAddEntry(listbox, "Reconfigure network now",
  995.                       (void *) 2);
  996.         newtListboxAddEntry(listbox, "Don't setup networking", (void *) 3);
  997.     } else {
  998.         newtListboxAddEntry(listbox, "Keep this setup", (void *) 1);
  999.         newtListboxAddEntry(listbox, "Reconfigure network now",
  1000.                       (void *) 2);
  1001.         newtListboxAddEntry(listbox, "Don't setup networking", (void *) 3);
  1002.     }
  1003.  
  1004.     okay = newtButton(6, 9, "Ok");
  1005.     cancel = newtButton(23, 9, "Cancel");
  1006.  
  1007.     f = newtForm(NULL, NULL, 0);
  1008.  
  1009.     newtFormAddComponents(f, text, listbox, okay, cancel, NULL);
  1010.  
  1011.     answer = newtRunForm(f);
  1012.     if (answer == cancel) {
  1013.         newtPopWindow();
  1014.         newtFormDestroy(f);
  1015.  
  1016.         return INST_CANCEL;
  1017.     }
  1018.  
  1019.     which = (int) newtListboxGetCurrent(listbox);
  1020.  
  1021.     newtPopWindow();
  1022.     newtFormDestroy(f);
  1023.  
  1024.     if (which == 1)
  1025.         *choice = CHECKNET_KEEP;
  1026.     else if (which == 3)
  1027.         *choice = CHECKNET_NONE;
  1028.     else if (which == 4)
  1029.         *choice = CHECKNET_NOBOOTP;
  1030.     else
  1031.         *choice = CHECKNET_CONFIG;
  1032.     } else {
  1033.     newtOpenWindow(18, 6, 42, 10, "Network Configuration");
  1034.  
  1035.     text = newtTextbox(1, 1, 40, 3, NEWT_TEXTBOX_WRAP);
  1036.     newtTextboxSetText(text,
  1037.         "Do you want to configure LAN (not dialup) networking "
  1038.         "for your installed system?");
  1039.  
  1040.     yes = newtButton(3, 6, " Yes ");
  1041.     no = newtButton(16, 6, "  No  ");
  1042.     cancel = newtButton(29, 6, "Cancel");
  1043.  
  1044.     f = newtForm(NULL, NULL, 0);
  1045.     newtFormAddComponents(f, text, yes, no, cancel, NULL);
  1046.  
  1047.     answer = newtRunForm(f);
  1048.     if (answer == f) 
  1049.         answer = newtFormGetCurrent(f);
  1050.  
  1051.     newtPopWindow();
  1052.     newtFormDestroy(f);
  1053.  
  1054.     if (answer == yes) {
  1055.         *choice = CHECKNET_CONFIG;
  1056.     } else if (answer == cancel) {
  1057.         return INST_CANCEL;
  1058.     } else {
  1059.         *choice = CHECKNET_NONE;
  1060.     }
  1061.     }
  1062.  
  1063.     return 0;
  1064. }
  1065.  
  1066. int checkNetConfig(struct netInterface * intf, struct netConfig * netc,
  1067.            struct driversLoaded ** dl) {
  1068.     int choice, rc;
  1069.  
  1070.     /* this doesn't handle cancel very well as the dl makes it difficult :-( */
  1071.  
  1072.     do {
  1073.     rc = checkNetConfigPanel(netc->isConfigured && intf->isConfigured,
  1074.                  intf->useBootp, &choice);
  1075.     if (rc) return rc;
  1076.  
  1077.     switch (choice) {
  1078.       case CHECKNET_NOBOOTP:
  1079.         intf->useBootp = 0;
  1080.         rc = 0;
  1081.         break;
  1082.  
  1083.       case CHECKNET_CONFIG:
  1084.         rc = doBringUpNetworking(intf, netc, dl, 1);
  1085.         if (rc == INST_ERROR) return rc;
  1086.         break;
  1087.  
  1088.       case CHECKNET_NONE:
  1089.         intf->isConfigured = netc->isConfigured = 0;
  1090.         rc = 0;
  1091.         break;
  1092.     }
  1093.     } while (rc);
  1094.  
  1095.     return 0;
  1096. }
  1097.