1 /*
2  * Copyright 1999-2001 Red Hat, Inc.
3  *
4  * All Rights Reserved.
5  *
6  * The above copyright notice and this permission notice shall be included in
7  * all copies or substantial portions of the Software.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
12  * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
13  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15  *
16  * Except as contained in this notice, the name of Red Hat shall not be
17  * used in advertising or otherwise to promote the sale, use or other dealings
18  * in this Software without prior written authorization from Red Hat.
19  *
20  */
21 
22 #include <arpa/inet.h>
23 #include <errno.h>
24 #include <popt.h>
25 #include <resolv.h>
26 #include <net/if.h>
27 #include <newt.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #ifdef __STANDALONE__
32 #include <netdb.h>
33 #include <libintl.h>
34 #include <locale.h>
35 
36 #define _(String) gettext((String))
37 #define N_(String) String
38 
39 #define LOADER_BACK 2
40 #define LOADER_OK 0
41 #define LOADER_ERROR -1;
42 
43 #include "net.h"
44 #include "pump.h"
45 
46 #else
47 
48 # include "isys/dns.h"
49 
50 #include "kickstart.h"
51 #include "lang.h"
52 #include "loader.h"
53 #include "log.h"
54 #include "net.h"
55 #include "windows.h"
56 
57 #endif /* __STANDALONE__ */
58 
59 struct intfconfig_s {
60     newtComponent ipEntry, nmEntry, gwEntry, nsEntry;
61     char * ip, * nm, * gw, * ns;
62 };
63 
64 typedef int int32;
65 
66 char * hwaddr = NULL;
67 char * desc = NULL;
68 
69 #ifdef __STANDALONE__
70 static FILE * logfile = NULL;
71 
72 #define FL_TESTING(foo) 1
73 
logMessage(const char * s,...)74 void logMessage(const char * s, ...) {
75 	va_list args;
76 
77 	if (!logfile) return;
78 	va_start(args, s);
79 
80 	fprintf(logfile, "* ");
81 	vfprintf(logfile, s, args);
82 	fprintf(logfile, "\n");
83 	fflush(logfile);
84 
85 	va_end(args);
86 
87 	return;
88 }
89 
90 /* yawn. This really should be in newt. */
winStatus(int width,int height,char * title,char * text,...)91 void winStatus(int width, int height, char * title,
92 	                       char * text, ...) {
93 	newtComponent t, f;
94 	char * buf = NULL;
95 	int size = 0;
96 	int i = 0;
97 	va_list args;
98 
99 	va_start(args, text);
100 
101 	do {
102 		size += 1000;
103 		if (buf) free(buf);
104 		buf = malloc(size);
105 		i = vsnprintf(buf, size, text, args);
106 	} while (i == size);
107 
108 	va_end(args);
109 
110 	newtCenteredWindow(width, height, title);
111 
112 	t = newtTextbox(1, 1, width - 2, height - 2, NEWT_TEXTBOX_WRAP);
113 	newtTextboxSetText(t, buf);
114 	f = newtForm(NULL, NULL, 0);
115 
116 	free(buf);
117 
118 	newtFormAddComponent(f, t);
119 
120 	newtDrawForm(f);
121 	newtRefresh();
122 	newtFormDestroy(f);
123 }
124 
125 #endif
126 
ipCallback(newtComponent co,void * dptr)127 static void ipCallback(newtComponent co, void * dptr) {
128     struct intfconfig_s * data = dptr;
129     struct in_addr ipaddr, nmaddr, addr;
130     char * ascii;
131     int broadcast, network;
132 
133     if (co == data->ipEntry) {
134 	if (strlen(data->ip) && !strlen(data->nm)) {
135 	    if (inet_aton(data->ip, &ipaddr)) {
136 		ipaddr.s_addr = ntohl(ipaddr.s_addr);
137 		if (((ipaddr.s_addr & 0xFF000000) >> 24) <= 127)
138 		    ascii = "255.0.0.0";
139 		else if (((ipaddr.s_addr & 0xFF000000) >> 24) <= 191)
140 		    ascii = "255.255.0.0";
141 		else
142 		    ascii = "255.255.255.0";
143 		newtEntrySet(data->nmEntry, ascii, 1);
144 	    }
145 	}
146     } else if (co == data->nmEntry) {
147 	if (!strlen(data->ip) || !strlen(data->nm)) return;
148 	if (!inet_aton(data->ip, &ipaddr)) return;
149 	if (!inet_aton(data->nm, &nmaddr)) return;
150 
151         network = ipaddr.s_addr & nmaddr.s_addr;
152 	broadcast = (ipaddr.s_addr & nmaddr.s_addr) | (~nmaddr.s_addr);
153 
154 	if (!strlen(data->gw)) {
155 	    addr.s_addr = htonl(ntohl(broadcast) - 1);
156 	    newtEntrySet(data->gwEntry, inet_ntoa(addr), 1);
157 	}
158 
159 	if (!strlen(data->ns)) {
160 	    addr.s_addr = htonl(ntohl(network) + 1);
161 	    newtEntrySet(data->nsEntry, inet_ntoa(addr), 1);
162 	}
163     }
164 }
165 
166 #ifndef __STANDALONE__
nfsGetSetup(char ** hostptr,char ** dirptr)167 int nfsGetSetup(char ** hostptr, char ** dirptr) {
168     struct newtWinEntry entries[3];
169     char * newServer = *hostptr ? strdup(*hostptr) : NULL;
170     char * newDir = *dirptr ? strdup(*dirptr) : NULL;
171     int rc;
172 
173     entries[0].text = _("NFS server name:");
174     entries[0].value = &newServer;
175     entries[0].flags = NEWT_FLAG_SCROLL;
176     entries[1].text = _("Red Hat directory:");
177     entries[1].value = &newDir;
178     entries[1].flags = NEWT_FLAG_SCROLL;
179     entries[2].text = NULL;
180     entries[2].value = NULL;
181 
182     rc = newtWinEntries(_("NFS Setup"),
183 		_("Please enter the following information:\n"
184 		  "\n"
185 		  "    o the name or IP number of your NFS server\n"
186 		  "    o the directory on that server containing\n"
187 		  "      Red Hat Linux for your architecture"), 60, 5, 15,
188 		24, entries, _("OK"), _("Back"), NULL);
189 
190     if (rc == 2) {
191 	if (newServer) free(newServer);
192 	if (newDir) free(newDir);
193 	return LOADER_BACK;
194     }
195 
196     if (*hostptr) free(*hostptr);
197     if (*dirptr) free(*dirptr);
198     *hostptr = newServer;
199     *dirptr = newDir;
200 
201     return 0;
202 }
203 #endif
204 
fillInIpInfo(struct networkDeviceConfig * cfg)205 static void fillInIpInfo(struct networkDeviceConfig * cfg) {
206     int32 * i;
207     char * nm;
208 
209     if (!(cfg->dev.set & PUMP_INTFINFO_HAS_NETMASK)) {
210 	i = (int32 *) &cfg->dev.ip;
211 
212 	if (((*i & 0xFF000000) >> 24) <= 127)
213 	    nm = "255.0.0.0";
214 	else if (((*i & 0xFF000000) >> 24) <= 191)
215 	    nm = "255.255.0.0";
216 	else
217 	    nm = "255.255.255.0";
218 
219 	inet_aton(nm, &cfg->dev.netmask);
220 	cfg->dev.set |= PUMP_INTFINFO_HAS_NETMASK;
221     }
222 
223     if (!(cfg->dev.set & PUMP_INTFINFO_HAS_BROADCAST)) {
224 	*((int32 *) &cfg->dev.broadcast) = (*((int32 *) &cfg->dev.ip) &
225 			   *((int32 *) &cfg->dev.netmask)) |
226 			   ~(*((int32 *) &cfg->dev.netmask));
227 	cfg->dev.set |= PUMP_INTFINFO_HAS_BROADCAST;
228     }
229 
230     if (!(cfg->dev.set & PUMP_INTFINFO_HAS_NETWORK)) {
231 	*((int32 *) &cfg->dev.network) =
232 		*((int32 *) &cfg->dev.ip) &
233 		*((int32 *) &cfg->dev.netmask);
234 	cfg->dev.set |= PUMP_INTFINFO_HAS_NETWORK;
235     }
236 }
237 
238 #ifndef __STANDALONE__
initLoopback(void)239 void initLoopback(void) {
240     struct pumpNetIntf dev;
241 
242     strcpy(dev.device, "lo");
243     inet_aton("127.0.0.1", &dev.ip);
244     inet_aton("255.0.0.0", &dev.netmask);
245     inet_aton("127.0.0.0", &dev.network);
246     dev.set = PUMP_INTFINFO_HAS_NETMASK | PUMP_INTFINFO_HAS_IP
247 		| PUMP_INTFINFO_HAS_NETWORK;
248 
249     pumpSetupInterface(&dev);
250 }
251 #endif
252 
dhcpBoxCallback(newtComponent co,void * ptr)253 static void dhcpBoxCallback(newtComponent co, void * ptr) {
254     struct intfconfig_s * c = ptr;
255 
256     newtEntrySetFlags(c->ipEntry, NEWT_FLAG_DISABLED, NEWT_FLAGS_TOGGLE);
257     newtEntrySetFlags(c->gwEntry, NEWT_FLAG_DISABLED, NEWT_FLAGS_TOGGLE);
258     newtEntrySetFlags(c->nmEntry, NEWT_FLAG_DISABLED, NEWT_FLAGS_TOGGLE);
259     newtEntrySetFlags(c->nsEntry, NEWT_FLAG_DISABLED, NEWT_FLAGS_TOGGLE);
260 }
261 
getDnsServers(struct networkDeviceConfig * cfg)262 static int getDnsServers(struct networkDeviceConfig * cfg) {
263     int rc;
264     char * ns = "";
265     struct newtWinEntry entry[] = { { N_("Nameserver IP"), &ns, 0 },
266 				      { NULL, NULL, 0 } };
267 
268     do {
269 	rc = newtWinEntries(_("Nameserver"),
270 		_("Your dynamic IP request returned IP configuration "
271 		  "information, but it did not include a DNS nameserver. "
272 		  "If you know what your nameserver is, please enter it "
273 		  "now. If you don't have this information, you can leave "
274 		  "this field blank and the install will continue."),
275 		40, 5, 10, 25, entry, _("OK"), _("Back"), NULL);
276 
277 	if (rc == 2) return LOADER_BACK;
278 
279 	if (ns && *ns && !inet_aton(ns, &cfg->dev.dnsServers[0])) {
280 	    newtWinMessage(_("Invalid IP Information"), _("Retry"),
281 			_("You entered an invalid IP address."));
282 	    rc = 2;
283 	}
284 
285     } while (rc == 2);
286 
287     cfg->dev.set |= PUMP_NETINFO_HAS_DNS;
288     cfg->dev.numDns = 1;
289 
290     return LOADER_OK;
291 }
292 
readNetConfig(char * device,struct networkDeviceConfig * cfg,int flags)293 int readNetConfig(char * device, struct networkDeviceConfig * cfg, int flags) {
294     newtComponent text, f, okay, back, answer, dhcpCheckbox;
295     newtGrid grid, subgrid, buttons;
296     struct networkDeviceConfig newCfg;
297     struct intfconfig_s c;
298     int i;
299     struct in_addr addr;
300     char dhcpChoice;
301     char * chptr;
302 
303     text = newtTextboxReflowed(-1, -1,
304 		_("Please enter the IP configuration for this machine. Each "
305 		  "item should be entered as an IP address in dotted-decimal "
306 		  "notation (for example, 1.2.3.4)."), 50, 5, 10, 0);
307 
308     subgrid = newtCreateGrid(2, 4);
309     newtGridSetField(subgrid, 0, 0, NEWT_GRID_COMPONENT,
310 		     newtLabel(-1, -1, _("IP address:")),
311 		     0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
312     newtGridSetField(subgrid, 0, 1, NEWT_GRID_COMPONENT,
313     		     newtLabel(-1, -1, _("Netmask:")),
314 		     0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
315     newtGridSetField(subgrid, 0, 2, NEWT_GRID_COMPONENT,
316     		     newtLabel(-1, -1, _("Default gateway (IP):")),
317 		     0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
318     newtGridSetField(subgrid, 0, 3, NEWT_GRID_COMPONENT,
319     		     newtLabel(-1, -1, _("Primary nameserver:")),
320 		     0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
321 
322     c.ipEntry = newtEntry(-1, -1, NULL, 16, &c.ip, 0);
323     c.nmEntry = newtEntry(-1, -1, NULL, 16, &c.nm, 0);
324     c.gwEntry = newtEntry(-1, -1, NULL, 16, &c.gw, 0);
325     c.nsEntry = newtEntry(-1, -1, NULL, 16, &c.ns, 0);
326 
327     if (!cfg->isDynamic) {
328 	if (cfg->dev.set & PUMP_INTFINFO_HAS_IP)
329 	    newtEntrySet(c.ipEntry, inet_ntoa(cfg->dev.ip), 1);
330 
331 	if (cfg->dev.set & PUMP_INTFINFO_HAS_NETMASK)
332 	    newtEntrySet(c.nmEntry, inet_ntoa(cfg->dev.netmask), 1);
333 
334 	if (cfg->dev.set & PUMP_NETINFO_HAS_GATEWAY)
335 	    newtEntrySet(c.gwEntry, inet_ntoa(cfg->dev.gateway), 1);
336 
337 	if (cfg->dev.numDns)
338 	    newtEntrySet(c.nsEntry, inet_ntoa(cfg->dev.dnsServers[0]), 1);
339 
340     	dhcpChoice = ' ';
341     } else {
342     	dhcpChoice = '*';
343     }
344 
345     dhcpCheckbox = newtCheckbox(-1, -1,
346     		_("Use dynamic IP configuration (BOOTP/DHCP)"),
347 		dhcpChoice, NULL, &dhcpChoice);
348     newtComponentAddCallback(dhcpCheckbox, dhcpBoxCallback, &c);
349     if (dhcpChoice == '*') dhcpBoxCallback(dhcpCheckbox, &c);
350 
351     newtGridSetField(subgrid, 1, 0, NEWT_GRID_COMPONENT, c.ipEntry,
352 		     1, 0, 0, 0, 0, 0);
353     newtGridSetField(subgrid, 1, 1, NEWT_GRID_COMPONENT, c.nmEntry,
354 		     1, 0, 0, 0, 0, 0);
355     newtGridSetField(subgrid, 1, 2, NEWT_GRID_COMPONENT, c.gwEntry,
356 		     1, 0, 0, 0, 0, 0);
357     newtGridSetField(subgrid, 1, 3, NEWT_GRID_COMPONENT, c.nsEntry,
358 		     1, 0, 0, 0, 0, 0);
359 
360     buttons = newtButtonBar(_("OK"), &okay, _("Back"), &back, NULL);
361 
362     grid = newtCreateGrid(1, 4);
363     newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
364 		     0, 0, 0, 1, 0, 0);
365     newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, dhcpCheckbox,
366 		     0, 0, 0, 1, 0, 0);
367     newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, subgrid,
368 		     0, 0, 0, 1, 0, 0);
369     newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons,
370 		     0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
371 
372     f = newtForm(NULL, NULL, 0);
373     newtGridAddComponentsToForm(grid, f, 1);
374     newtGridWrappedWindow(grid, _("Configure TCP/IP"));
375     newtGridFree(grid, 1);
376 
377     newtComponentAddCallback(c.ipEntry, ipCallback, &c);
378     newtComponentAddCallback(c.nmEntry, ipCallback, &c);
379 
380     do {
381 	answer = newtRunForm(f);
382 
383 	if (answer == back) {
384 	    newtFormDestroy(f);
385 	    newtPopWindow();
386 	    return LOADER_BACK;
387 	}
388 
389 	if (dhcpChoice == ' ') {
390 	    i = 0;
391 	    memset(&newCfg, 0, sizeof(newCfg));
392 	    if (*c.ip && inet_aton(c.ip, &addr)) {
393 		i++;
394 		newCfg.dev.ip = addr;
395 		newCfg.dev.set |= PUMP_INTFINFO_HAS_IP;
396 	    }
397 
398 	    if (*c.nm && inet_aton(c.nm, &addr)) {
399 		i++;
400 		newCfg.dev.netmask = addr;
401 		newCfg.dev.set |= PUMP_INTFINFO_HAS_NETMASK;
402 	    }
403 
404 	    if (i != 2) {
405 		newtWinMessage(_("Missing Information"), _("Retry"),
406 			    _("You must enter both a valid IP address and a "
407 			      "netmask."));
408 	    }
409 
410 	    strcpy(newCfg.dev.device, device);
411 	    newCfg.isDynamic = 0;
412 	} else {
413 	    if (!FL_TESTING(flags)) {
414 		winStatus(50, 3, _("Dynamic IP"),
415 			  _("Sending request for IP information..."),
416 			    0);
417 		chptr = pumpDhcpRun(device, 0, 0, NULL, &newCfg.dev, NULL);
418 		newtPopWindow();
419 	    } else {
420 	    	chptr = NULL;
421 	    }
422 
423 	    if (!chptr) {
424 		newCfg.isDynamic = 1;
425 #ifdef __STANDALONE__
426 		i = 2;
427 #else
428 		if (!(newCfg.dev.set & PUMP_NETINFO_HAS_DNS)) {
429 		    logMessage("pump worked, but didn't return a DNS server");
430 		    i = getDnsServers(&newCfg);
431 		    i = i ? 0 : 2;
432 		} else {
433 		    i = 2;
434 		}
435 #endif
436 	    } else {
437 		logMessage("pump told us: %s", chptr);
438 		i = 0;
439 	    }
440 	}
441     } while (i != 2);
442 
443 #ifdef __STANDALONE__
444     if (!newCfg.isDynamic)
445 #endif
446     cfg->dev = newCfg.dev;
447     cfg->isDynamic = newCfg.isDynamic;
448 
449     fillInIpInfo(cfg);
450 
451     if (!(cfg->dev.set & PUMP_NETINFO_HAS_GATEWAY)) {
452 	if (*c.gw && inet_aton(c.gw, &addr)) {
453 	    cfg->dev.gateway = addr;
454 	    cfg->dev.set |= PUMP_NETINFO_HAS_GATEWAY;
455 	}
456     }
457 
458     if (!(cfg->dev.numDns)) {
459 	if (*c.ns && inet_aton(c.ns, &addr)) {
460 	    cfg->dev.dnsServers[0] = addr;
461 	    cfg->dev.numDns = 1;
462 	}
463     }
464 
465     newtPopWindow();
466 
467     if (!FL_TESTING(flags)) {
468 	configureNetwork(cfg);
469 	findHostAndDomain(cfg, flags);
470 	writeResolvConf(cfg);
471     }
472 
473 #ifdef __STANDALONE__
474     writeResolvConf(cfg);
475 #endif
476     return 0;
477 }
478 
configureNetwork(struct networkDeviceConfig * dev)479 int configureNetwork(struct networkDeviceConfig * dev) {
480     pumpSetupInterface(&dev->dev);
481 
482     if (dev->dev.set & PUMP_NETINFO_HAS_GATEWAY)
483 	pumpSetupDefaultGateway(&dev->dev.gateway);
484 
485     return 0;
486 }
487 
writeNetInfo(const char * fn,struct networkDeviceConfig * dev,struct knownDevices * kd)488 int writeNetInfo(const char * fn, struct networkDeviceConfig * dev,
489 		 struct knownDevices * kd) {
490     FILE * f;
491 #ifndef __STANDALONE__
492     int i;
493 #endif
494 
495 #ifndef __STANDALONE__
496     for (i = 0; i < kd->numKnown; i++)
497 	if (!strcmp(kd->known[i].name, dev->dev.device)) break;
498 #endif
499 
500     if (!(f = fopen(fn, "w"))) return -1;
501 
502     if (desc) {
503         fprintf(f, "# %s\n", desc);
504     }
505 
506     fprintf(f, "DEVICE=%s\n", dev->dev.device);
507 
508 #ifndef __STANDALONE__
509     if (i < kd->numKnown && kd->known[i].code == CODE_PCMCIA)
510 	fprintf(f, "ONBOOT=no\n");
511     else
512 #endif
513 	fprintf(f, "ONBOOT=yes\n");
514 
515     if (dev->isDynamic) {
516 	fprintf(f, "BOOTPROTO=dhcp\n");
517     } else {
518 	fprintf(f, "BOOTPROTO=static\n");
519 	fprintf(f, "IPADDR=%s\n", inet_ntoa(dev->dev.ip));
520 	fprintf(f, "NETMASK=%s\n", inet_ntoa(dev->dev.netmask));
521 	if (dev->dev.set & PUMP_NETINFO_HAS_GATEWAY)
522 	    fprintf(f, "GATEWAY=%s\n", inet_ntoa(dev->dev.gateway));
523     }
524 
525     if (dev->dev.set & PUMP_NETINFO_HAS_HOSTNAME)
526 	fprintf(f, "HOSTNAME=%s\n", dev->dev.hostname);
527     if (dev->dev.set & PUMP_NETINFO_HAS_DOMAIN)
528 	fprintf(f, "DOMAIN=%s\n", dev->dev.domain);
529 
530     if (hwaddr) {
531 	fprintf(f, "HWADDR=%s\n",hwaddr);
532     }
533 
534     fclose(f);
535 
536     return 0;
537 }
538 
writeResolvConf(struct networkDeviceConfig * net)539 int writeResolvConf(struct networkDeviceConfig * net) {
540     char * filename = "/etc/resolv.conf";
541     FILE * f;
542     int i;
543 
544     if (!(net->dev.set & PUMP_NETINFO_HAS_DOMAIN) && !net->dev.numDns)
545     	return LOADER_ERROR;
546 
547     f = fopen(filename, "w");
548     if (!f) {
549 	logMessage("Cannot create %s: %s\n", filename, strerror(errno));
550 	return LOADER_ERROR;
551     }
552 
553     if (net->dev.set & PUMP_NETINFO_HAS_DOMAIN)
554 	fprintf(f, "search %s\n", net->dev.domain);
555 
556     for (i = 0; i < net->dev.numDns; i++)
557 	fprintf(f, "nameserver %s\n", inet_ntoa(net->dev.dnsServers[i]));
558 
559     fclose(f);
560 
561     res_init();		/* reinit the resolver so DNS changes take affect */
562 
563     return 0;
564 }
565 
findHostAndDomain(struct networkDeviceConfig * dev,int flags)566 int findHostAndDomain(struct networkDeviceConfig * dev, int flags) {
567     char * name, * chptr;
568 #ifdef __STANDALONE__
569     struct hostent * he;
570 #endif
571 
572     if (!FL_TESTING(flags)) {
573 	writeResolvConf(dev);
574     }
575 
576     if (!(dev->dev.set & PUMP_NETINFO_HAS_HOSTNAME)) {
577 	winStatus(40, 3, _("Hostname"),
578 		  _("Determining host name and domain..."));
579 #ifdef __STANDALONE__
580 	he = gethostbyaddr( (char *) &dev->dev.ip, sizeof (dev->dev.ip), AF_INET);
581 	name = he ? he->h_name : 0;
582 #else
583 	name = mygethostbyaddr(inet_ntoa(dev->dev.ip));
584 #endif
585 	newtPopWindow();
586 
587 	if (!name) {
588 	    logMessage("reverse name lookup failed");
589 	    return 1;
590 	}
591 
592 	logMessage("reverse name lookup worked");
593 
594 	dev->dev.hostname = strdup(name);
595 	dev->dev.set |= PUMP_NETINFO_HAS_HOSTNAME;
596     } else {
597         name = dev->dev.hostname;
598     }
599 
600     if (!(dev->dev.set & PUMP_NETINFO_HAS_DOMAIN)) {
601 	for (chptr = name; *chptr && (*chptr != '.'); chptr++) ;
602 	if (*chptr == '.') {
603 	    if (dev->dev.domain) free(dev->dev.domain);
604 	    dev->dev.domain = strdup(chptr + 1);
605 	    dev->dev.set |= PUMP_NETINFO_HAS_DOMAIN;
606 	}
607     }
608 
609     return 0;
610 }
611 
612 #ifndef __STANDALONE__
kickstartNetwork(char ** devicePtr,struct networkDeviceConfig * netDev,char * bootProto,int flags)613 int kickstartNetwork(char ** devicePtr, struct networkDeviceConfig * netDev,
614 		     char * bootProto, int flags) {
615     char ** ksArgv;
616     int ksArgc;
617     int netSet, rc;
618     char * arg, * chptr;
619     char * kshostname=NULL;
620     poptContext optCon;
621     struct in_addr * parseAddress;
622     int noDns = 0;
623     char * device;
624     struct poptOption ksOptions[] = {
625 	    { "bootproto", '\0', POPT_ARG_STRING, &bootProto, 0 },
626 	    { "device", '\0', POPT_ARG_STRING, devicePtr, 0 },
627 	    { "gateway", '\0', POPT_ARG_STRING, NULL, 'g' },
628 	    { "ip", '\0', POPT_ARG_STRING, NULL, 'i' },
629 	    { "nameserver", '\0', POPT_ARG_STRING, NULL, 'n' },
630 	    { "netmask", '\0', POPT_ARG_STRING, NULL, 'm' },
631 	    { "nodns", '\0', POPT_ARG_NONE, &noDns, 0 },
632 	    { "hostname", '\0', POPT_ARG_STRING, NULL, 'h'},
633 	    { 0, 0, 0, 0, 0 }
634     };
635 
636     if (!bootProto) {
637 	if (ksGetCommand(KS_CMD_NETWORK, NULL, &ksArgc, &ksArgv)) {
638 	    /* This is for compatibility with RH 5.0 */
639 	    ksArgv = alloca(sizeof(*ksArgv) * 1);
640 	    ksArgv[0] = "network";
641 	    ksArgc = 1;
642 	}
643 
644 	optCon = poptGetContext(NULL, ksArgc, (const char **) ksArgv, ksOptions, 0);
645 	while ((rc = poptGetNextOpt(optCon)) >= 0) {
646 	    parseAddress = NULL;
647 	    netSet = 0;
648 
649 	    arg = (char *) poptGetOptArg(optCon);
650 
651 	    switch (rc) {
652 	      case 'g':
653 		parseAddress = &netDev->dev.gateway;
654 		netSet = PUMP_NETINFO_HAS_GATEWAY;
655 		break;
656 
657 	      case 'i':
658 		parseAddress = &netDev->dev.ip;
659 		netSet = PUMP_INTFINFO_HAS_IP;
660 		break;
661 
662 	      case 'n':
663 		parseAddress = &netDev->dev.dnsServers[netDev->dev.numDns++];
664 		netSet = PUMP_NETINFO_HAS_DNS;
665 		break;
666 
667 	      case 'm':
668 		parseAddress = &netDev->dev.netmask;
669 		netSet = PUMP_INTFINFO_HAS_NETMASK;
670 		break;
671 
672 	      case 'h':
673 		if (kshostname)
674 		    free(kshostname);
675 		kshostname =  strdup(arg);
676 		logMessage("netDev->dev.hostname = %s", kshostname);
677 		break;
678 	    }
679 
680 	    if (parseAddress && !inet_aton(arg, parseAddress)) {
681 		logMessage("bad ip number in network command: %s", arg);
682 		return -1;
683 	    }
684 
685 	    netDev->dev.set |= netSet;
686 	}
687 
688 	if (rc < -1) {
689 	    newtWinMessage(_("kickstart"),  _("OK"),
690 		       _("bad argument to kickstart network command %s: %s"),
691 		       poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
692 		       poptStrerror(rc));
693 	} else {
694 	    poptFreeContext(optCon);
695 	}
696     }
697 
698     device = *devicePtr;
699 
700     if (!bootProto)
701 	bootProto = "dhcp";
702 
703     if (!strcmp(bootProto, "dhcp") || !strcmp(bootProto, "bootp")) {
704 	logMessage("sending dhcp request through device %s", device);
705 	winStatus(50, 3, _("Dynamic IP"),
706 		  _("Sending request for IP information..."),
707 		    0);
708 
709 	chptr = pumpDhcpRun(device, 0, 0, NULL, &netDev->dev, NULL);
710 	newtPopWindow();
711 	if (chptr) {
712 	    logMessage("pump told us: %s", chptr);
713 	    return -1;
714 	}
715 	netDev->isDynamic = 1;
716     } else if (!strcmp(bootProto, "static")) {
717        strcpy(netDev->dev.device, device);
718     } else if (!strcmp(bootProto, "query")) {
719 	strcpy(netDev->dev.device, device);
720 	readNetConfig("eth0", netDev, flags);
721     } else {
722 	newtWinMessage(_("kickstart"), _("OK"),
723 		    _("Bad bootproto %s specified in network command"),
724 		    bootProto);
725 	return -1;
726     }
727 
728     fillInIpInfo(netDev);
729     configureNetwork(netDev);
730 
731     logMessage("nodns is %d", noDns);
732 
733     if (kshostname) {
734 	logMessage("setting ks specified hostname of %s", kshostname);
735 	netDev->dev.hostname=strdup(kshostname);
736 	netDev->dev.set |= PUMP_NETINFO_HAS_HOSTNAME;
737     }
738 
739     if (!noDns)
740 	findHostAndDomain(netDev, flags);
741 
742     writeResolvConf(netDev);
743 
744     return 0;
745 }
746 #endif
747 
748 #ifdef __STANDALONE__
749 
main(int argc,const char ** argv)750 int main(int argc, const char **argv) {
751     int netSet, rc;
752     int x;
753     int noDns = 0;
754     char * bootProto = NULL;
755     char * device = NULL;
756     char * hostname = NULL;
757     char * domain = NULL;
758     const char * arg;
759     char path[256];
760     char roottext[80];
761     poptContext optCon;
762     struct networkDeviceConfig *netDev;
763     struct in_addr * parseAddress;
764     struct poptOption Options[] = {
765 	    POPT_AUTOHELP
766 	    { "bootproto", '\0', POPT_ARG_STRING, &bootProto, 0,
767 	      _("Boot protocol to use"), "(dhcp|bootp|none)" },
768 	    { "gateway", '\0', POPT_ARG_STRING, NULL, 'g',
769 	      _("Network gateway"), NULL },
770 	    { "ip", '\0', POPT_ARG_STRING, NULL, 'i',
771 	      _("IP address"), NULL },
772 	    { "nameserver", '\0', POPT_ARG_STRING, NULL, 'n',
773 	      _("Nameserver"), NULL },
774 	    { "netmask", '\0', POPT_ARG_STRING, NULL, 'm',
775 	      _("Netmask"), NULL },
776 	    { "hostname", '\0', POPT_ARG_STRING, &hostname, 0,
777 	      _("Hostname"), NULL
778 	    },
779 	    { "domain", '\0', POPT_ARG_STRING, &domain, 0,
780 	      _("Domain name"), NULL
781 	    },
782 	    { "device", 'd', POPT_ARG_STRING, &device, 0,
783 	      _("Network device"), NULL
784 	    },
785 	    { "nodns", '\0', POPT_ARG_NONE, &noDns, 0,
786 	      _("No DNS lookups"), NULL
787 	    },
788 	    { "hwaddr", '\0', POPT_ARG_STRING, &hwaddr, 0,
789 	      _("Ethernet hardware address"), NULL
790 	    },
791 	    { "description", '\0', POPT_ARG_STRING, &desc, 0,
792 	      _("Description of the device"), NULL
793 	    },
794 	    { 0, 0, 0, 0, 0 }
795     };
796 
797     bindtextdomain("pump", "/usr/share/locale");
798     textdomain("pump");
799 
800     netDev = malloc(sizeof(struct networkDeviceConfig));
801     memset(netDev,'\0',sizeof(struct networkDeviceConfig));
802     optCon = poptGetContext("netconfig", argc, argv, Options, 0);
803     while ((rc = poptGetNextOpt(optCon)) >= 0) {
804 	parseAddress = NULL;
805 	netSet = 0;
806 
807 	arg = poptGetOptArg(optCon);
808 
809 	switch (rc) {
810 	  case 'g':
811 	    parseAddress = &netDev->dev.gateway;
812 	    netSet = PUMP_NETINFO_HAS_GATEWAY;
813 	    break;
814 
815 	  case 'i':
816 	    parseAddress = &netDev->dev.ip;
817 	    netSet = PUMP_INTFINFO_HAS_IP;
818 	    break;
819 
820 	  case 'n':
821 	    parseAddress = &netDev->dev.dnsServers[netDev->dev.numDns++];
822 	    netSet = PUMP_NETINFO_HAS_DNS;
823 	    break;
824 
825 	  case 'm':
826 	    parseAddress = &netDev->dev.netmask;
827 	    netSet = PUMP_INTFINFO_HAS_NETMASK;
828 	    break;
829 	}
830 
831 	if (!inet_aton(arg, parseAddress)) {
832 	    logMessage("bad ip number in network command: %s", arg);
833 	    return -1;
834 	}
835 
836 	netDev->dev.set |= netSet;
837     }
838 
839     if (rc < -1) {
840 	fprintf(stderr, "%s: %s\n",
841 		   poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
842 		   poptStrerror(rc));
843     } else {
844 	poptFreeContext(optCon);
845     }
846 
847     if (netDev->dev.set ||
848 	(bootProto && (!strcmp(bootProto, "dhcp") || !strcmp(bootProto, "bootp")))) {
849 	    if (!device) device="eth0";
850 	    if (bootProto && (!strcmp(bootProto, "dhcp") || !strcmp(bootProto, "bootp")))
851 		netDev->isDynamic++;
852 	    strncpy(netDev->dev.device,device,10);
853 	    if (hostname) {
854 		    netDev->dev.hostname=strdup(hostname);
855 		    netDev->dev.set |= PUMP_NETINFO_HAS_HOSTNAME;
856 	    }
857 	    if (domain) {
858 		    netDev->dev.domain=strdup(domain);
859 		    netDev->dev.set |= PUMP_NETINFO_HAS_DOMAIN;
860 	    }
861 	    snprintf(path,256,"/etc/sysconfig/network-scripts/ifcfg-%s",device);
862 	    writeNetInfo(path,netDev, NULL);
863     } else {
864 	    newtInit();
865 	    newtCls();
866 	    newtPushHelpLine(_(" <Tab>/<Alt-Tab> between elements   |   <Space> selects  |   <F12> next screen"));
867 	    snprintf(roottext,80,_("netconfig %s  (C) 1999 Red Hat, Inc."), VERSION);
868 	    newtDrawRootText(0, 0, roottext);
869 	    if (!device) {
870 	        x=newtWinChoice(_("Network configuration"),_("Yes"),_("No"),
871 				_("Would you like to set up networking?"));
872 	        if (x==2) {
873 		    newtFinished();
874 		    exit(0);
875 	        }
876 		device = "eth0";
877 	    }
878 	    strncpy(netDev->dev.device,device,10);
879 	    if (readNetConfig(device,netDev,0) != LOADER_BACK) {
880 		    snprintf(path,256,"/etc/sysconfig/network-scripts/ifcfg-%s",device);
881 		    writeNetInfo(path,netDev, NULL);
882 	    }
883 	    newtFinished();
884     }
885     exit(0);
886 }
887 #endif
888