home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 February
/
CHIP_2_98.iso
/
misc
/
src
/
install
/
net.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-10-24
|
31KB
|
1,220 lines
#include <net/if.h>
#include <net/route.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "bootpc.h"
#include "devices.h"
#include "install.h"
#include "log.h"
#include "newt.h"
#include "net.h"
#include "perror.h"
#include "windows.h"
struct intfconfig_s {
newtComponent ipLabel, nmLabel, gwLabel, nsLabel;
newtComponent ipEntry, nmEntry, gwEntry, nsEntry;
char * ip, * nm, * gw, * ns;
char * bootpState;
};
struct netconfig_s {
newtComponent nsLabels[3], hnLabel, dnLabel;
newtComponent nsEntrys[3], hnEntry, dnEntry;
char * ns[3], * gw, * hn, * dn;
};
static void ipCallback(newtComponent co, void * data);
static void hnCallback(newtComponent co, void * data);
/* It's a bit gross, but setupNetworkInterface() will setup your general
networking information if bootp is used */
static int setupNetworkInterface(struct netInterface * intf,
struct netConfig * netc,
struct driversLoaded ** dl, int justConfig);
static int doBringUpNetworking(struct netInterface * intf,
struct netConfig * netc,
struct driversLoaded ** dl, int justConfig);
static int configureNetDevice(struct netInterface * intf);
/* intf in configureNetwork is optional */
static int configureNetwork(struct netConfig * netc,
struct netInterface * intf);
static char * findAvailableNetDevice(void);
static int doBootp(char * device, struct netInterface * intf,
struct netConfig * netc) {
struct netInterface minInterface;
int rc;
/* This is a bit of a hack, but it lets us use Jon Peatfield's bootp
code w/o hacking at it. It's written to allow test mode to work
as long as the runner sets the proper magic env variables. */
if (!testing) {
logMessage("using bootp for device %s", device);
minInterface.ip = minInterface.netmask = minInterface.network = 0;
minInterface.broadcast = 0xffffffff;
strcpy(minInterface.dev, device);
if (configureNetDevice(&minInterface)) {
logMessage("failed to setup minimal bootp interface %s", device);
return 1;
}
winStatus(40, 3, "BOOTP", "Sending BOOTP request...");
rc = performBootp(device, "255.255.255.255", "", 10, 0, NULL, 0, 1,
BP_PUT_ENV);
newtPopWindow();
if (rc) {
logMessage("performBootp() failed w/ return %d", rc);
return 1;
}
}
if (!getenv("BOOTP_IPADDR")) {
errorWindow("bootp query did not return an IP address");
return 1;
}
/* These will be generated by bootpc.c even if they're not in the
bootp reply */
inet_aton(getenv("BOOTP_IPADDR"), (struct in_addr *) &intf->ip);
inet_aton(getenv("BOOTP_NETMASK"), (struct in_addr *) &intf->netmask);
inet_aton(getenv("BOOTP_BROADCAST"), (struct in_addr *)
&intf->broadcast);
inet_aton(getenv("BOOTP_NETWORK"), (struct in_addr *)
&intf->network);
intf->useBootp = 1;
intf->isConfigured = 1;
strcpy(intf->dev, device);
if (getenv("BOOTP_GATEWAYS_1")) {
strcpy(netc->defaultGateway, getenv("BOOTP_GATEWAYS_1"));
netc->isConfigured = 1;
}
if (getenv("BOOTP_DNSSRVS_1")) {
netc->nameserver[0] = strdup(getenv("BOOTP_DNSSRVS_1"));
netc->isConfigured = 1;
if (getenv("BOOTP_DNSSRVS_2")) {
netc->nameserver[1] = strdup(getenv("BOOTP_DNSSRVS_2"));
if (getenv("BOOTP_DNSSRVS_3"))
netc->nameserver[2] = strdup(getenv("BOOTP_DNSSRVS_3"));
}
}
/*
If bootp gave us a hostname and domain, use those. Otherwise,
we'll try and query the nameserver a bit later on. If that fails
as well, we'll try and use just the hostname BOOTP gave us.
*/
if (getenv("BOOTP_HOSTNAME") && getenv("BOOTP_DOMAIN")) {
logMessage("bootp returned hostname and domain name");
strcpy(netc->hostname, getenv("BOOTP_HOSTNAME"));
netc->isConfigured = 1;
strcpy(netc->domainname, getenv("BOOTP_DOMAIN"));
if (strcmp(netc->hostname, netc->domainname) &&
!strstr(netc->hostname, netc->domainname)) {
strcat(netc->hostname, ".");
strcat(netc->hostname, netc->domainname);
}
}
return 0;
}
/* The interface/gateway needs to be configured before this will work! */
static int guessHostname(struct netInterface * intf, struct netConfig * netc) {
struct in_addr addr;
char ips[50];
if ((testing || intf->isUp) && netc->nameserver[0]) {
logMessage("using nameserver to find host and domain name");
writeResolvConf("/etc", netc);
memcpy(&addr, &intf->ip, sizeof(addr));
strcpy(ips, inet_ntoa(addr));
winStatus(40, 3, "Hostname", "Determing host name and domain...");
if (in2host(ips, BP_PUT_ENV)) {
newtPopWindow();
logMessage("reverse name lookup failed");
if (getenv("BOOTP_HOSTNAME")) {
strcpy(netc->hostname, getenv("BOOTP_HOSTNAME"));
}
return 1;
} else {
newtPopWindow();
logMessage("reverse name lookup worked");
strcpy(netc->hostname, getenv("BOOTP_HOSTFULL"));
strcpy(netc->domainname, getenv("BOOTP_HOSTDOMAIN"));
return 0;
}
}
return 1;
}
int addDefaultRoute(struct netConfig netc) {
int s;
struct rtentry route;
struct sockaddr_in addr;
if (testing) return 0;
if (!strlen(netc.defaultGateway)) return 0;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
close(s);
errorWindow("socket: %s");
return 1;
}
memset(&route, 0, sizeof(route));
addr.sin_family = AF_INET;
addr.sin_port = 0;
inet_aton(netc.defaultGateway, &addr.sin_addr);
memcpy(&route.rt_gateway, &addr, sizeof(addr));
addr.sin_addr.s_addr = INADDR_ANY;
memcpy(&route.rt_dst, &addr, sizeof(addr));
memcpy(&route.rt_genmask, &addr, sizeof(addr));
route.rt_flags = RTF_UP | RTF_GATEWAY;
route.rt_metric = 0;
if (ioctl(s, SIOCADDRT, &route)) {
close(s);
errorWindow("SIOCADDRT: %s");
return 1;
}
return 0;
}
static int configureNetDevice(struct netInterface * intf) {
struct ifreq req;
struct rtentry route;
int s;
struct sockaddr_in addr;
struct in_addr ia;
char ip[20], nm[20], nw[20], bc[20];
addr.sin_family = AF_INET;
addr.sin_port = 0;
memcpy(&ia, &intf->ip, sizeof(intf->ip));
strcpy(ip, inet_ntoa(ia));
memcpy(&ia, &intf->netmask, sizeof(intf->netmask));
strcpy(nm, inet_ntoa(ia));
memcpy(&ia, &intf->broadcast, sizeof(intf->broadcast));
strcpy(bc, inet_ntoa(ia));
memcpy(&ia, &intf->network, sizeof(intf->network));
strcpy(nw, inet_ntoa(ia));
logMessage("configuring %s ip: %s nm: %s nw: %s bc: %s", intf->dev,
ip, nm, nw, bc);
if (testing) return 0;
strcpy(req.ifr_name, intf->dev);
addr.sin_family = AF_INET;
addr.sin_port = 0;
memcpy(&addr.sin_addr, &intf->ip, sizeof(intf->ip));
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
errorWindow("socket: %s");
return 1;
}
memcpy(&req.ifr_addr, &addr, sizeof(addr));
if (ioctl(s, SIOCSIFADDR, &req)) {
close(s);
errorWindow("SIOCSIFADDR: %s");
return 1;
}
memcpy(&addr.sin_addr, &intf->broadcast, sizeof(intf->broadcast));
memcpy(&req.ifr_broadaddr, &addr, sizeof(addr));
if (ioctl(s, SIOCSIFBRDADDR, &req)) {
close(s);
errorWindow("SIOCSIFNETMASK: %s");
return 1;
}
memcpy(&addr.sin_addr, &intf->netmask, sizeof(intf->netmask));
memcpy(&req.ifr_netmask, &addr, sizeof(addr));
if (ioctl(s, SIOCSIFNETMASK, &req)) {
close(s);
errorWindow("SIOCSIFNETMASK: %s");
return 1;
}
if (intf->isPtp)
req.ifr_flags = IFF_UP | IFF_RUNNING | IFF_POINTOPOINT | IFF_NOARP;
else
req.ifr_flags = IFF_UP | IFF_RUNNING | IFF_BROADCAST;
if (ioctl(s, SIOCSIFFLAGS, &req)) {
close(s);
errorWindow("SIOCSIFFLAGS: %s");
return 1;
}
memset(&route, 0, sizeof(route));
route.rt_dev = intf->dev;
route.rt_flags = RTF_UP;
memcpy(&addr.sin_addr, &intf->network, sizeof(intf->netmask));
memcpy(&route.rt_dst, &addr, sizeof(addr));
memcpy(&addr.sin_addr, &intf->netmask, sizeof(intf->netmask));
memcpy(&route.rt_genmask, &addr, sizeof(addr));
if (ioctl(s, SIOCADDRT, &route)) {
close(s);
errorWindow("SIOCADDRT: %s");
return 1;
}
intf->isUp = 1;
return 0;
}
int netDeviceAvailable(char * device) {
struct ifreq req;
int s;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
close(s);
errorWindow("socket: %s");
return 1;
}
strcpy(req.ifr_name, device);
if (ioctl(s, SIOCGIFFLAGS, &req)) {
/* if we can't get the flags, the networking device isn't available */
close(s);
return 0;
}
return 1;
}
static void interfaceConfigToggle(newtComponent co, void * arg) {
struct intfconfig_s * info = arg;
int sense = NEWT_FLAGS_SET;
if (*info->bootpState == ' ')
sense = NEWT_FLAGS_RESET;
newtEntrySetFlags(info->ipEntry, NEWT_ENTRY_DISABLED, sense);
newtEntrySetFlags(info->nmEntry, NEWT_ENTRY_DISABLED, sense);
newtEntrySetFlags(info->gwEntry, NEWT_ENTRY_DISABLED, sense);
newtEntrySetFlags(info->nsEntry, NEWT_ENTRY_DISABLED, sense);
newtRefresh();
}
static char * findAvailableNetDevice(void) {
char * devices[] = { "eth0", "tr0", "plip0", "plip1", "plip2",
"fddi0", NULL };
char * device = NULL;
char ** deviceptr;
/* I should probably ask which device to use if multiple ones are
available -- oh well :-( */
for (deviceptr = devices; *deviceptr; deviceptr++) {
if (netDeviceAvailable(*deviceptr)) {
device = *deviceptr;
logMessage("%s is available -- using it for networking", device);
break;
}
}
return device;
}
static int setupNetworkInterface(struct netInterface * intf,
struct netConfig * netc,
struct driversLoaded ** dl, int justConfig) {
newtComponent okay, cancel, bootp, f, answer;
int top = 4;
struct intfconfig_s c;
struct in_addr addr;
int32 ptpNetmask;
int rc;
int done = 0;
char useBootp;
char * device;
struct driversLoaded * adriver;
device = findAvailableNetDevice();
if (!device) {
if ((rc = loadDeviceDriver(DRIVER_NET, dl, 0)))
return rc;
for (adriver = *dl; adriver && adriver->type != DRIVER_NET;
adriver = adriver->next);
if (!adriver) {
logMessage("ack! loadDriveDriver() worked but didn't load a "
"DRIVE_NET!!");
return INST_ERROR;
}
switch (adriver->minor) {
case DRIVER_MINOR_ETHERNET: device = "eth0"; break;
case DRIVER_MINOR_TR: device = "tr0"; break;
case DRIVER_MINOR_PLIP: device = getPlipDeviceName(); break;
default: exit(1); /* ack! */
}
}
newtCenteredWindow(50, 15, "Configure TCP/IP");
c.ipLabel = newtLabel(1, top + 2, "IP address:");
c.nmLabel = newtLabel(1, top + 3, "Netmask:");
c.gwLabel = newtLabel(1, top + 4, "Default gateway (IP):");
c.nsLabel = newtLabel(1, top + 5, "Primary nameserver:");
if (!intf->ip){
c.ipEntry = newtEntry(25, top + 2, "", 16, &c.ip, 0);
} else {
memcpy(&addr, &intf->ip, sizeof(intf->ip));
c.ipEntry = newtEntry(25, top + 2, inet_ntoa(addr), 16, &c.ip, 0);
}
if (!intf->netmask){
c.nmEntry = newtEntry(25, top + 3, "", 16, &c.nm, 0);
} else {
memcpy(&addr, &intf->netmask, sizeof(intf->netmask));
c.nmEntry = newtEntry(25, top + 3, inet_ntoa(addr), 16, &c.nm, 0);
}
if (!netc->defaultGateway)
c.gwEntry = newtEntry(25, top + 4, "", 16, &c.gw, 0);
else
c.gwEntry = newtEntry(25, top + 4, netc->defaultGateway, 16, &c.gw, 0);
if (!netc->nameserver[0])
c.nsEntry = newtEntry(25, top + 5, "", 16, &c.ns, 0);
else
c.nsEntry = newtEntry(25, top + 5, netc->nameserver[0], 16, &c.ns, 0);
c.bootpState = &useBootp;
f = newtForm(NULL, NULL, 0);
bootp = newtCheckbox(1, top, "Configure device with bootp",
(intf->isConfigured && intf->useBootp) ? '*' : ' ',
NULL, &useBootp);
newtComponentAddCallback(bootp, interfaceConfigToggle, &c);
newtFormAddComponents(f, bootp, c.ipLabel, c.nmLabel, c.gwLabel, c.nsLabel,
c.ipEntry, c.nmEntry, c.gwEntry, c.nsEntry, NULL);
if (c.bootpState)
newtFormSetCurrent(f, c.ipEntry);
newtComponentAddCallback(c.ipEntry, ipCallback, &c);
newtComponentAddCallback(c.nmEntry, ipCallback, &c);
okay = newtButton(8, top + 7, "Ok");
cancel = newtButton(28, top + 7, "Cancel");
newtFormAddComponents(f, okay, cancel, NULL);
do {
answer = newtRunForm(f);
if (answer == cancel) {
newtFormDestroy(f);
newtPopWindow();
return INST_CANCEL;
}
if (useBootp != ' ') {
logMessage("Configuring device %s via bootp", device);
if (justConfig) {
done = 1;
intf->useBootp = 1;
intf->isConfigured = 1;
} else if (!doBootp(device, intf, netc)) {
done = 1;
}
} else {
strcpy(intf->dev, device);
inet_aton(c.ip, (struct in_addr *) &intf->ip);
inet_aton(c.nm, (struct in_addr *) &intf->netmask);
intf->broadcast = (intf->ip & intf->netmask) | (~intf->netmask);
inet_aton("255.255.255.255", (struct in_addr *) &ptpNetmask);
if (ptpNetmask == intf->netmask) {
logMessage("configuring point to point device");
inet_aton(c.gw, (struct in_addr *) &intf->network);
intf->isPtp = 1;
} else {
intf->network = intf->ip & intf->netmask;
intf->isPtp = 0;
}
intf->isConfigured = 1;
intf->useBootp = 0;
strcpy(netc->defaultGateway, c.gw);
if (netc->nameserver[0]) free(netc->nameserver[0]);
if (strlen(c.ns))
netc->nameserver[0] = strdup(c.ns);
else
netc->nameserver[0] = NULL;
netc->isConfigured = 1;
done = 1;
}
} while (!done);
newtFormDestroy(f);
newtPopWindow();
if (!justConfig) {
if (configureNetDevice(intf)) return INST_ERROR;
if (addDefaultRoute(*netc)) return INST_ERROR;
}
return 0;
}
static void hnCallback(newtComponent co, void * dptr) {
char * buf;
struct netconfig_s * data = dptr;
if (strlen(data->hn)) return;
if (!strlen(data->dn)) return;
buf = alloca(strlen(data->dn) + 5);
strcpy(buf, ".");
strcat(buf, data->dn);
newtEntrySet(data->hnEntry, buf, 0);
}
static void ipCallback(newtComponent co, void * dptr) {
struct intfconfig_s * data = dptr;
struct in_addr ipaddr, nmaddr, addr;
char * ascii;
int32 broadcast, network;
if (co == data->ipEntry) {
if (strlen(data->ip) && !strlen(data->nm)) {
if (inet_aton(data->ip, &ipaddr)) {
ipaddr.s_addr = ntohl(ipaddr.s_addr);
if (((ipaddr.s_addr & 0xFF000000) >> 24) <= 127)
ascii = "255.0.0.0";
else if (((ipaddr.s_addr & 0xFF000000) >> 24) <= 191)
ascii = "255.255.0.0";
else
ascii = "255.255.255.0";
newtEntrySet(data->nmEntry, ascii, 1);
}
}
} else if (co == data->nmEntry) {
if (!strlen(data->ip) || !strlen(data->nm)) return;
if (!inet_aton(data->ip, &ipaddr)) return;
if (!inet_aton(data->nm, &nmaddr)) return;
network = ipaddr.s_addr & nmaddr.s_addr;
broadcast = (ipaddr.s_addr & nmaddr.s_addr) | (~nmaddr.s_addr);
addr.s_addr = htonl(ntohl(broadcast) - 1);
newtEntrySet(data->gwEntry, inet_ntoa(addr), 1);
/* I'm such a lazy bastard */
if ((ntohl(network) & 0xFFFFFF00) == 0xc7b71800) {
newtEntrySet(data->nsEntry, "199.183.24.1", 1);
} else {
addr.s_addr = htonl(ntohl(network) + 1);
newtEntrySet(data->nsEntry, inet_ntoa(addr), 1);
}
}
}
int writeNetConfig(char * prefix, struct netConfig * netc,
struct netInterface * gwdev, int verbose) {
char filename[100];
FILE * f;
if (testing) return 0;
sprintf(filename, "%s/network", prefix);
f = fopen(filename, "w");
if (!f) {
errorWindow("cannot create network config file: %s");
return INST_ERROR;
}
fprintf(f, "NETWORKING=yes\n");
fprintf(f, "FORWARD_IPV4=false\n");
logMessage("writing network information to %s", filename);
if (netc->hostname && strlen(netc->hostname)) {
logMessage("\tnetwork is configured, writing complete information");
fprintf(f, "HOSTNAME=%s\n", netc->hostname);
fprintf(f, "DOMAINNAME=%s\n", netc->domainname);
if (gwdev && strlen(netc->defaultGateway)) {
fprintf(f, "GATEWAY=%s\n", netc->defaultGateway);
fprintf(f, "GATEWAYDEV=%s\n", gwdev->dev);
}
if (verbose) {
if (netc->nameserver[0])
fprintf(f, "NS1=%s\n", netc->nameserver[0]);
if (netc->nameserver[1])
fprintf(f, "NS2=%s\n", netc->nameserver[1]);
if (netc->nameserver[2])
fprintf(f, "NS3=%s\n", netc->nameserver[2]);
}
} else {
logMessage("\tnetwork is not configured");
fprintf(f, "HOSTNAME=localhost.localdomain\n");
}
fclose(f);
return 0;
}
int writeHosts(char * prefix, struct netConfig * netc,
struct netInterface * intf) {
char filename[100];
FILE * f;
struct in_addr * addrptr;
char * nickname;
int i;
if (testing) return 1;
sprintf(filename, "%s/hosts", prefix);
/* if /etc/hosts already exists, don't bother creating one */
if (!access(filename, R_OK)) {
logMessage("%s already exists -- won't crunch it", filename);
return 0;
}
logMessage("%s doesn not exist -- creating", filename);
f = fopen(filename, "w");
if (!f) {
errorWindow("cannot create /etc/hosts: %s");
return INST_ERROR;
}
logMessage("writing host information to %s", filename);
fprintf(f, "127.0.0.1\t\tlocalhost localhost.localdomain\n");
if (netc->hostname && strlen(netc->hostname)) {
addrptr = (struct in_addr *) &intf->ip;
i = strlen(netc->hostname) - strlen(netc->domainname);
if (i > 1 && !strcmp(netc->hostname + i, netc->domainname)
&& netc->hostname[i - 1] == '.') {
nickname = strdup(netc->hostname);
nickname[i - 1] = '\0';
fprintf(f, "%s\t\t%s %s\n", inet_ntoa(*addrptr),
netc->hostname, nickname);
free(nickname);
} else {
fprintf(f, "%s\t\t%s\n", inet_ntoa(*addrptr),
netc->hostname);
}
sethostname(netc->hostname, strlen(netc->hostname));
}
fclose(f);
res_init(); /* reinit the resolver so DNS changes take affect */
return 0;
}
int writeResolvConf(char * prefix, struct netConfig * netc) {
char filename[100];
FILE * f;
if (testing) return 1;
if (!netc->domainname && !netc->nameserver[0]) {
logMessage("networking is not configured - not writing resolv.conf");
return 0;
}
sprintf(filename, "%s/resolv.conf", prefix);
f = fopen(filename, "w");
if (!f) {
errorWindow("cannot create resolv.conf: %s");
return INST_ERROR;
}
logMessage("writing nameservices information to %s", filename);
if (netc->domainname)
fprintf(f, "search %s\n", netc->domainname);
if (netc->nameserver[0])
fprintf(f, "nameserver %s\n", netc->nameserver[0]);
if (netc->nameserver[1])
fprintf(f, "nameserver %s\n", netc->nameserver[1]);
if (netc->nameserver[2])
fprintf(f, "nameserver %s\n", netc->nameserver[2]);
fclose(f);
res_init(); /* reinit the resolver so DNS changes take affect */
return 0;
}
int writeNetInterfaceConfig(char * prefix, struct netInterface * intf) {
char filename[100];
FILE * f;
struct in_addr * addrptr;
if (testing) return 0;
if (!intf->isConfigured) {
logMessage("network interface is not configured - not creating "
"ifcfg-*");
return(0);
}
sprintf(filename, "%s/ifcfg-%s", prefix, intf->dev);
f = fopen(filename, "w");
if (!f) {
errorWindow("cannot create network device config file: %s");
return INST_ERROR;
}
logMessage("writing network information to %s", filename);
fprintf(f, "DEVICE=%s\n", intf->dev);
if (intf->useBootp)
fprintf(f, "BOOTPROTO=bootp\n");
if (!strcmp(prefix, "/tmp") || !intf->useBootp) {
addrptr = (struct in_addr *) &intf->ip;
fprintf(f, "IPADDR=%s\n", inet_ntoa(*addrptr));
addrptr = (struct in_addr *) &intf->netmask;
fprintf(f, "NETMASK=%s\n", inet_ntoa(*addrptr));
addrptr = (struct in_addr *) &intf->network;
fprintf(f, "NETWORK=%s\n", inet_ntoa(*addrptr));
addrptr = (struct in_addr *) &intf->broadcast;
fprintf(f, "BROADCAST=%s\n", inet_ntoa(*addrptr));
}
fprintf(f, "ONBOOT=yes\n");
fclose(f);
return 0;
}
int readNetInterfaceConfig(char * prefix, char * device,
struct netInterface * intf) {
FILE * f;
char * start, * end;
char buf[250];
int line = 0;
intf->isConfigured = 0;
if (testing) {
return 0;
}
sprintf(buf, "%s/ifcfg-%s", prefix, device);
f = fopen(buf, "r");
if (!f) {
if (errno != ENOENT) {
errorWindow("cannot open file: %s");
return INST_ERROR;
} else {
intf->ip = 0;
return 0;
}
}
while (fgets(buf, sizeof(buf) - 1, f)) {
line++;
start = buf;
/* skipping leading spaces */
while (*start && isspace(*start)) start++;
if (!*start) continue;
/* skip comments */
if (*start == '#') continue;
/* cut off trailing spaces and \n */
end = start + strlen(start) - 2;
while (isspace(*end)) end--;
end++;
*end = '\0';
end--;
if (!strncmp("IPADDR=", start, 7)) {
start += 7;
inet_aton(start, (struct in_addr *) &intf->ip);
} else if (!strncmp("DEVICE=", start, 7)) {
start += 7;
strcpy(intf->dev, start);
} else if (!strncmp("BOOTPROTO=bootp", start, 15)) {
intf->useBootp = 1;
} else if (!strncmp("NETMASK=", start, 8)) {
start += 8;
inet_aton(start, (struct in_addr *) &intf->netmask);
} else if (!strncmp("NETWORK=", start, 8)) {
start += 8;
inet_aton(start, (struct in_addr *) &intf->network);
if (!strcmp(start, "255.255.255.255"))
intf->isPtp = 1;
} else if (!strncmp("BROADCAST=", start, 10)) {
start += 10;
inet_aton(start, (struct in_addr *) &intf->broadcast);
}
}
fclose(f);
intf->isConfigured = 1;
return 0;
}
int configureNetwork(struct netConfig * netc,
struct netInterface * intf) {
struct netconfig_s n;
int top = 3;
newtComponent f, okay, cancel, answer;
int i;
n.dnLabel = newtLabel(1, top , "Domain name:");
n.hnLabel = newtLabel(1, top + 1, "Host name:");
n.nsLabels[1] = newtLabel(1, top + 2, "Secondary nameserver (IP):");
n.nsLabels[2] = newtLabel(1, top + 3, "Tertiary nameserver (IP):");
n.dnEntry = newtEntry(28, top , "", 20, &n.dn, NEWT_ENTRY_SCROLL);
n.hnEntry = newtEntry(28, top + 1, "", 20, &n.hn, NEWT_ENTRY_SCROLL);
n.nsEntrys[1] = newtEntry(28, top + 2, "", 20, &n.ns[1], NEWT_ENTRY_SCROLL);
n.nsEntrys[2] = newtEntry(28, top + 3, "", 20, &n.ns[2], NEWT_ENTRY_SCROLL);
if (!strlen(netc->hostname) && !strlen(netc->domainname) &&
(testing || intf->isUp) && netc->nameserver[0]) {
guessHostname(intf, netc);
if (netc->hostname[0] && netc->domainname[0] && !expert) {
logMessage("reverse name lookup worked; skipping hostname config");
return 0;
}
}
newtCenteredWindow(50, 15, "Configure Network");
if (netc->hostname)
newtEntrySet(n.hnEntry, netc->hostname, 0);
if (netc->domainname)
newtEntrySet(n.dnEntry, netc->domainname, 0);
if (netc->nameserver[1])
newtEntrySet(n.nsEntrys[1], netc->nameserver[1], 0);
if (netc->nameserver[2])
newtEntrySet(n.nsEntrys[2], netc->nameserver[2], 0);
newtComponentAddCallback(n.dnEntry, hnCallback, &n);
f = newtForm(NULL, NULL, 0);
newtFormAddComponents(f, n.dnLabel, n.hnLabel, n.nsLabels[1],
n.nsLabels[2], NULL);
newtFormAddComponents(f, n.dnEntry, n.hnEntry, n.nsEntrys[1],
n.nsEntrys[2], NULL);
okay = newtButton(11, 11, "Ok");
cancel = newtButton(30, 11, "Cancel");
newtFormAddComponents(f, okay, cancel, NULL);
answer = newtRunForm(f);
strcpy(netc->hostname, n.hn);
strcpy(netc->domainname, n.dn);
for (i = 1; i < 3; i++) {
if (netc->nameserver[i])
free(netc->nameserver[i]);
netc->nameserver[i] = *n.ns[i] ? strdup(n.ns[i]) : NULL;
}
newtFormDestroy(f);
newtPopWindow();
if (answer == cancel) return INST_CANCEL;
netc->isConfigured = 1;
return 0;
}
int readNetConfig(char * prefix, struct netConfig * netc) {
FILE * f;
char * start, * end;
char buf[250];
int line = 0;
if (testing) {
return 0;
}
sprintf(buf, "%s/network", prefix);
f = fopen(buf, "r");
if (!f) {
if (errno != ENOENT) {
errorWindow("cannot open file: %s");
return INST_ERROR;
} else {
netc->hostname[0] = '\0';
return 0;
}
}
memset(netc, 0, sizeof(*netc));
while (fgets(buf, sizeof(buf) - 1, f)) {
line++;
start = buf;
/* skipping leading spaces */
while (*start && isspace(*start)) start++;
if (!*start) continue;
/* skip comments */
if (*start == '#') continue;
/* cut off trailing spaces and \n */
end = start + strlen(start) - 2;
while (isspace(*end)) end--;
end++;
*end = '\0';
end--;
if (!strncmp("HOSTNAME=", start, 9)) {
start += 9;
strcpy(netc->hostname, start);
} else if (!strncmp("DOMAINNAME=", start, 11)) {
start += 11;
strcpy(netc->domainname, start);
} else if (!strncmp("GATEWAY=", start, 8)) {
start += 8;
strcpy(netc->defaultGateway, start);
} else if (!strncmp("NS1=", start, 4)) {
start += 4;
netc->nameserver[0] = strdup(start);
} else if (!strncmp("NS2=", start, 4)) {
start += 4;
netc->nameserver[1] = strdup(start);
} else if (!strncmp("NS3=", start, 4)) {
start += 4;
netc->nameserver[2] = strdup(start);
}
}
fclose(f);
netc->isConfigured = 1;
return 0;
}
int bringUpNetworking(struct netInterface * intf, struct netConfig * netc,
struct driversLoaded ** dl) {
return doBringUpNetworking(intf, netc, dl, 0);
}
#define BRINGUP_NET 1
#define BRINGUP_CONF 2
#define BRINGUP_ROUTE 3
#define BRINGUP_DONE 4
static int doBringUpNetworking(struct netInterface * intf,
struct netConfig * netc,
struct driversLoaded ** dl, int justConfig) {
int where = BRINGUP_NET;
int rc;
char * device;
if (kickstart) {
if (intf->isConfigured && netc->isConfigured) return 0;
/* justConfig must be zero, we have to actually do something for this
to happen automatically */
device = findAvailableNetDevice();
if (!device) {
if ((rc = loadDeviceDriver(DRIVER_NET, dl, 1))) {
newtWinMessage("Ethernet Probe", "Ok",
"The Ethernet probe failed "
"to find a card on your system. Press <Enter> to manually "
"configure one.");
while (setupNetworkInterface(intf, netc, dl, 0)) ;
}
if (!(device = findAvailableNetDevice())) {
newtWinMessage("Network Failed", "Hang", "No networking "
"devices are available. You should never "
"have gotten this far.");
}
}
while (doBootp(device, intf, netc)) {
newtWinMessage("Bootp Failed", "Retry", "Bootp failed to find an "
"IP address. Press <Enter> to retry.");
}
configureNetDevice(intf);
addDefaultRoute(*netc);
while (guessHostname(intf, netc)) {
newtWinMessage("Hostname Lookup", "Retry",
"I cannot find by hostname via DNS. Press <Enter> to retry.");
}
return addDefaultRoute(*netc);
}
while (where != BRINGUP_DONE) {
switch (where) {
case BRINGUP_NET:
rc = setupNetworkInterface(intf, netc, dl, justConfig);
if (rc) return rc;
where = BRINGUP_CONF;
break;
case BRINGUP_CONF:
rc = configureNetwork(netc, intf);
if (rc == INST_CANCEL)
where = BRINGUP_NET;
else if (rc)
return INST_ERROR;
else
where = BRINGUP_ROUTE;
break;
case BRINGUP_ROUTE:
if (justConfig)
rc = 0;
else
rc = addDefaultRoute(*netc);
if (rc) return rc;
where = BRINGUP_DONE;
break;
}
}
/* write out the /etc/resolv.conf, as we'll need that to use name services
properly */
writeResolvConf("/etc", netc);
return 0;
}
#define CHECKNET_CONFIG 1
#define CHECKNET_KEEP 2
#define CHECKNET_NONE 3
#define CHECKNET_NOBOOTP 4
static int checkNetConfigPanel(int isConfigured, int useBootp, int * choice) {
newtComponent text, okay, cancel;
newtComponent f, answer, yes, no, listbox;
int which;
if (isConfigured && kickstart) {
*choice = CHECKNET_KEEP;
return 0;
} else if (isConfigured) {
newtCenteredWindow(42, 13, "Network Configuration");
text = newtTextbox(1, 1, 40, 2, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text,
"LAN networking has already been configured. Do you "
"want to:");
listbox = newtListbox(8, 4, 0, NEWT_LISTBOX_RETURNEXIT);
if (useBootp) {
newtListboxAddEntry(listbox, "Use bootp at startup", (void *) 1);
newtListboxAddEntry(listbox, "Use the current IP information",
(void *) 4);
newtListboxAddEntry(listbox, "Reconfigure network now",
(void *) 2);
newtListboxAddEntry(listbox, "Don't setup networking", (void *) 3);
} else {
newtListboxAddEntry(listbox, "Keep this setup", (void *) 1);
newtListboxAddEntry(listbox, "Reconfigure network now",
(void *) 2);
newtListboxAddEntry(listbox, "Don't setup networking", (void *) 3);
}
okay = newtButton(6, 9, "Ok");
cancel = newtButton(23, 9, "Cancel");
f = newtForm(NULL, NULL, 0);
newtFormAddComponents(f, text, listbox, okay, cancel, NULL);
answer = newtRunForm(f);
if (answer == cancel) {
newtPopWindow();
newtFormDestroy(f);
return INST_CANCEL;
}
which = (int) newtListboxGetCurrent(listbox);
newtPopWindow();
newtFormDestroy(f);
if (which == 1)
*choice = CHECKNET_KEEP;
else if (which == 3)
*choice = CHECKNET_NONE;
else if (which == 4)
*choice = CHECKNET_NOBOOTP;
else
*choice = CHECKNET_CONFIG;
} else if (kickstart) {
/* XXX this ought to be configurable */
*choice = CHECKNET_NONE;
} else {
newtCenteredWindow(42, 10, "Network Configuration");
text = newtTextbox(1, 1, 40, 3, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text,
"Do you want to configure LAN (not dialup) networking "
"for your installed system?");
yes = newtButton(3, 6, " Yes ");
no = newtButton(16, 6, " No ");
cancel = newtButton(29, 6, "Cancel");
f = newtForm(NULL, NULL, 0);
newtFormAddComponents(f, text, yes, no, cancel, NULL);
answer = newtRunForm(f);
if (answer == f)
answer = newtFormGetCurrent(f);
newtPopWindow();
newtFormDestroy(f);
if (answer == yes) {
*choice = CHECKNET_CONFIG;
} else if (answer == cancel) {
return INST_CANCEL;
} else {
*choice = CHECKNET_NONE;
}
}
return 0;
}
int checkNetConfig(struct netInterface * intf, struct netConfig * netc,
struct driversLoaded ** dl) {
int choice, rc;
/* this doesn't handle cancel very well as the dl makes it difficult :-( */
do {
rc = checkNetConfigPanel(netc->isConfigured && intf->isConfigured,
intf->useBootp, &choice);
if (rc) return rc;
switch (choice) {
case CHECKNET_NOBOOTP:
intf->useBootp = 0;
rc = 0;
break;
case CHECKNET_CONFIG:
rc = doBringUpNetworking(intf, netc, dl, 1);
if (rc == INST_ERROR) return rc;
break;
case CHECKNET_NONE:
intf->isConfigured = netc->isConfigured = 0;
rc = 0;
break;
}
} while (rc);
return 0;
}