tcpip.c revision 73322
1/* 2 * $FreeBSD: head/usr.sbin/sysinstall/tcpip.c 73322 2001-03-02 08:15:41Z peter $ 3 * 4 * Copyright (c) 1995 5 * Gary J Palmer. All rights reserved. 6 * Copyright (c) 1996 7 * Jordan K. Hubbard. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer, 14 * verbatim and that no modifications are made prior to this 15 * point in the file. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 26 * OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 28 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 */ 32 33/* 34 * All kinds of hacking also performed by jkh on this code. Don't 35 * blame Gary for every bogosity you see here.. :-) 36 * 37 * -jkh 38 */ 39 40#include "sysinstall.h" 41#include <sys/param.h> 42#include <sys/sysctl.h> 43#include <sys/socket.h> 44#include <netinet/in.h> 45#include <netdb.h> 46 47/* The help file for the TCP/IP setup screen */ 48#define TCP_HELPFILE "tcp" 49 50/* These are nasty, but they make the layout structure a lot easier ... */ 51 52static char hostname[HOSTNAME_FIELD_LEN], domainname[HOSTNAME_FIELD_LEN], 53 gateway[IPADDR_FIELD_LEN], nameserver[INET6_ADDRSTRLEN]; 54static int okbutton, cancelbutton; 55static char ipaddr[IPADDR_FIELD_LEN], netmask[IPADDR_FIELD_LEN], extras[EXTRAS_FIELD_LEN]; 56static char ipv6addr[INET6_ADDRSTRLEN]; 57 58/* What the screen size is meant to be */ 59#define TCP_DIALOG_Y 0 60#define TCP_DIALOG_X 8 61#define TCP_DIALOG_WIDTH COLS - 16 62#define TCP_DIALOG_HEIGHT LINES - 2 63 64static Layout layout[] = { 65#define LAYOUT_HOSTNAME 0 66 { 1, 2, 25, HOSTNAME_FIELD_LEN - 1, 67 "Host:", "Your fully-qualified hostname, e.g. foo.bar.com", 68 hostname, STRINGOBJ, NULL }, 69#define LAYOUT_DOMAINNAME 1 70 { 1, 35, 20, HOSTNAME_FIELD_LEN - 1, 71 "Domain:", 72 "The name of the domain that your machine is in, e.g. bar.com", 73 domainname, STRINGOBJ, NULL }, 74#define LAYOUT_GATEWAY 2 75 { 5, 2, 18, IPADDR_FIELD_LEN - 1, 76 "IPv4 Gateway:", 77 "IPv4 address of host forwarding packets to non-local destinations", 78 gateway, STRINGOBJ, NULL }, 79#define LAYOUT_NAMESERVER 3 80 { 5, 35, 18, INET6_ADDRSTRLEN - 1, 81 "Name server:", "IPv4 or IPv6 address of your local DNS server", 82 nameserver, STRINGOBJ, NULL }, 83#define LAYOUT_IPADDR 4 84 { 10, 10, 18, IPADDR_FIELD_LEN - 1, 85 "IPv4 Address:", 86 "The IPv4 address to be used for this interface", 87 ipaddr, STRINGOBJ, NULL }, 88#define LAYOUT_NETMASK 5 89 { 10, 35, 18, IPADDR_FIELD_LEN - 1, 90 "Netmask:", 91 "The netmask for this interface, e.g. 0xffffff00 for a class C network", 92 netmask, STRINGOBJ, NULL }, 93#define LAYOUT_EXTRAS 6 94 { 14, 10, 37, HOSTNAME_FIELD_LEN - 1, 95 "Extra options to ifconfig:", 96 "Any interface-specific options to ifconfig you would like to add", 97 extras, STRINGOBJ, NULL }, 98#define LAYOUT_OKBUTTON 7 99 { 19, 15, 0, 0, 100 "OK", "Select this if you are happy with these settings", 101 &okbutton, BUTTONOBJ, NULL }, 102#define LAYOUT_CANCELBUTTON 8 103 { 19, 35, 0, 0, 104 "CANCEL", "Select this if you wish to cancel this screen", 105 &cancelbutton, BUTTONOBJ, NULL }, 106 { NULL }, 107}; 108 109#define _validByte(b) ((b) >= 0 && (b) <= 255) 110 111/* whine */ 112static void 113feepout(char *msg) 114{ 115 beep(); 116 msgConfirm(msg); 117} 118 119/* Verify IP address integrity */ 120static int 121verifyIP(char *ip, unsigned long *out) 122{ 123 long a, b, c, d; 124 char *endptr; 125 126 if (ip == NULL) 127 return 0; 128 a = strtol(ip, &endptr, 10); 129 if (*endptr++ != '.') 130 return 0; 131 b = strtol(endptr, &endptr, 10); 132 if (*endptr++ != '.') 133 return 0; 134 c = strtol(endptr, &endptr, 10); 135 if (*endptr++ != '.') 136 return 0; 137 d = strtol(endptr, &endptr, 10); 138 if (*endptr != '\0') 139 return 0; 140 /* Both 0 and 255 are technically valid in nets that are larger 141 than class C, but at least MS' TCP/IP stacks freak out if they see 142 them. */ 143 if (!_validByte(a) || !_validByte(b) || !_validByte(c) || 144 !_validByte(d) || (d == 0) || (d == 255)) 145 return 0; 146 if (out) 147 *out = (a << 24) | (b << 16) | (c << 8) | d; 148 return 1; 149} 150 151static int 152verifyIP6(char *ip) 153{ 154 struct addrinfo hints, *res; 155 156 memset(&hints, 0, sizeof(hints)); 157 hints.ai_family = AF_INET6; 158 hints.ai_socktype = SOCK_STREAM; 159 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 160 if (getaddrinfo(ip, NULL, &hints, &res) == 0) { 161 freeaddrinfo(res); 162 return 1; 163 } 164 return 0; 165} 166 167/* Verify IPv4 netmask as being well-formed as 168 a 0x or AAA.BBB.CCC.DDD mask */ 169static int 170verifyNetmask(const char *netmask, unsigned long *out) 171{ 172 unsigned long mask; 173 unsigned long tmp; 174 char *endptr; 175 176 if (netmask[0] == '0' && (netmask[1] == 'x' || netmask[1] == 'X')) { 177 /* Parse out hex mask */ 178 mask = strtoul(netmask, &endptr, 0); 179 if (*endptr != '\0') 180 return 0; 181 } else { 182 /* Parse out quad decimal mask */ 183 mask = strtoul(netmask, &endptr, 10); 184 if (!_validByte(mask) || *endptr++ != '.') 185 return 0; 186 tmp = strtoul(endptr, &endptr, 10); 187 if (!_validByte(tmp) || *endptr++ != '.') 188 return 0; 189 mask = (mask << 8) + tmp; 190 tmp = strtoul(endptr, &endptr, 10); 191 if (!_validByte(tmp) || *endptr++ != '.') 192 return 0; 193 mask = (mask << 8) + tmp; 194 tmp = strtoul(endptr, &endptr, 10); 195 if (!_validByte(tmp) || *endptr++ != '\0') 196 return 0; 197 mask = (mask << 8) + tmp; 198 } 199 /* Verify that we have a continous netmask */ 200 if ((((-mask & mask) - 1) | mask) != 0xffffffff) 201 return 0; 202 if (out) 203 *out = mask; 204 return 1; 205} 206 207static int 208verifyGW(char *gw, unsigned long *ip, unsigned long *mask) 209{ 210 unsigned long parsedgw; 211 212 if (!verifyIP(gw, &parsedgw)) 213 return 0; 214 /* Gateway needs to be within the set of IPs reachable through the 215 interface */ 216 if (ip && mask && ((parsedgw & *mask) != (*ip & *mask))) 217 return 0; 218 return 1; 219} 220 221/* Check for the settings on the screen - the per-interface stuff is 222 moved to the main handling code now to do it on the fly - sigh */ 223static int 224verifySettings(void) 225{ 226 unsigned long parsedip; 227 unsigned long parsednetmask; 228 229 if (!hostname[0]) 230 feepout("Must specify a host name of some sort!"); 231 else if (nameserver[0] && !verifyIP(nameserver, NULL) && 232 !verifyIP6(nameserver)) 233 feepout("Invalid name server IP address specified"); 234 else if (ipaddr[0] && !verifyIP(ipaddr, &parsedip)) 235 feepout("Invalid IPv4 address"); 236 else if (netmask[0] && !verifyNetmask(netmask, &parsednetmask)) 237 feepout("Invalid netmask value"); 238 else if (gateway[0] && strcmp(gateway, "NO") && 239 !verifyGW(gateway, ipaddr[0] ? &parsedip : NULL, 240 netmask[0] ? &parsednetmask : NULL)) 241 feepout("Invalid gateway IPv4 address specified"); 242 else 243 return 1; 244 return 0; 245} 246 247static void 248dhcpGetInfo(Device *devp) 249{ 250 /* If it fails, do it the old-fashioned way */ 251 if (dhcpParseLeases("/var/db/dhclient.leases", hostname, domainname, 252 nameserver, ipaddr, gateway, netmask) == -1) { 253 FILE *ifp; 254 char *cp, cmd[256], data[2048]; 255 int i, j; 256 257 /* Bah, now we have to kludge getting the information from ifconfig */ 258 snprintf(cmd, sizeof cmd, "ifconfig %s", devp->name); 259 ifp = popen(cmd, "r"); 260 if (ifp) { 261 j = fread(data, 1, sizeof(data), ifp); 262 fclose(ifp); 263 if (j < 0) /* paranoia */ 264 j = 0; 265 data[j] = '\0'; 266 if (isDebug()) 267 msgDebug("DHCP configured interface returns %s\n", data); 268 /* XXX This is gross as it assumes a certain ordering to 269 ifconfig's output! XXX */ 270 if ((cp = strstr(data, "inet ")) != NULL) { 271 i = 0; 272 cp += 5; /* move over keyword */ 273 while (*cp != ' ') 274 ipaddr[i++] = *(cp++); 275 ipaddr[i] = '\0'; 276 if (!strncmp(++cp, "netmask", 7)) { 277 i = 0; 278 cp += 8; 279 while (*cp != ' ') 280 netmask[i++] = *(cp++); 281 netmask[i] = '\0'; 282 } 283 } 284 } 285 } 286 287 /* If we didn't get a name server value, hunt for it in resolv.conf */ 288 if (!nameserver[0] && file_readable("/etc/resolv.conf")) 289 configEnvironmentResolv("/etc/resolv.conf"); 290 if (hostname[0]) 291 variable_set2(VAR_HOSTNAME, hostname, 0); 292} 293 294static void 295rtsolGetInfo(Device *devp) 296{ 297 FILE *ifp; 298 char *cp, cmd[256], data[2048]; 299 int i; 300 301 snprintf(cmd, sizeof cmd, "ifconfig %s", devp->name); 302 if ((ifp = popen(cmd, "r")) == NULL) 303 return; 304 while (fgets(data, sizeof(data), ifp) != NULL) { 305 if (isDebug()) 306 msgDebug("RTSOL configured interface returns %s", data); 307 if ((cp = strstr(data, "inet6 ")) != NULL) { 308 cp += 6; /* move over keyword */ 309 if (strncmp(cp, "fe80:", 5)) { 310 i = 0; 311 while (*cp != ' ') 312 ipv6addr[i++] = *(cp++); 313 ipv6addr[i] = '\0'; 314 } 315 } 316 } 317 fclose(ifp); 318} 319 320/* This is it - how to get TCP setup values */ 321int 322tcpOpenDialog(Device *devp) 323{ 324 WINDOW *ds_win, *save = NULL; 325 ComposeObj *obj = NULL; 326 int n = 0, filled = 0, cancel = FALSE; 327 int max, ret = DITEM_SUCCESS; 328 int use_dhcp = FALSE; 329 int use_rtsol = FALSE; 330 char *tmp; 331 char title[80]; 332 333 save = savescr(); 334 /* Initialise vars from previous device values */ 335 if (devp->private) { 336 DevInfo *di = (DevInfo *)devp->private; 337 338 SAFE_STRCPY(ipaddr, di->ipaddr); 339 SAFE_STRCPY(netmask, di->netmask); 340 SAFE_STRCPY(extras, di->extras); 341 use_dhcp = di->use_dhcp; 342 use_rtsol = di->use_rtsol; 343 } 344 else { /* See if there are any defaults */ 345 char *cp; 346 347 /* Try a RTSOL scan if such behavior is desired */ 348 if (!variable_cmp(VAR_TRY_RTSOL, "YES") || 349 ((!variable_cmp(VAR_TRY_RTSOL, "NO")) && (!msgNoYes("Do you want to try IPv6 configuration of the interface?")))) { 350 int i; 351 int len; 352 353 i = 0; 354 sysctlbyname("net.inet6.ip6.forwarding", NULL, 0, &i, sizeof(i)); 355 i = 1; 356 sysctlbyname("net.inet6.ip6.accept_rtadv", NULL, 0, &i, sizeof(i)); 357 vsystem("ifconfig %s up", devp->name); 358 len = sizeof(i); 359 sysctlbyname("net.inet6.ip6.dad_count", &i, &len, NULL, 0); 360 sleep(i + 1); 361 Mkdir("/var/run"); 362 msgNotify("Scanning for RA servers..."); 363 if (0 == vsystem("rtsol %s", devp->name)) { 364 len = sizeof(i); 365 sysctlbyname("net.inet6.ip6.dad_count", &i, &len, NULL, 0); 366 sleep(i + 1); 367 rtsolGetInfo(devp); 368 use_rtsol = TRUE; 369 } else 370 use_rtsol = FALSE; 371 } 372 373 /* First try a DHCP scan if such behavior is desired */ 374 if (!variable_cmp(VAR_TRY_DHCP, "YES") || 375 ((!variable_cmp(VAR_TRY_DHCP, "NO")) && (!msgNoYes("Do you want to try DHCP configuration of the interface?")))) { 376 Mkdir("/var/db"); 377 Mkdir("/var/run"); 378 Mkdir("/tmp"); 379 msgNotify("Scanning for DHCP servers..."); 380 if (0 == vsystem("dhclient -1 %s", devp->name)) { 381 dhcpGetInfo(devp); 382 use_dhcp = TRUE; 383 } 384 else 385 use_dhcp = FALSE; 386 } 387 388 /* Special hack so it doesn't show up oddly in the tcpip setup menu */ 389 if (!strcmp(gateway, "NO")) 390 gateway[0] = '\0'; 391 392 /* Get old IP address from variable space, if available */ 393 if (!ipaddr[0]) { 394 if ((cp = variable_get(VAR_IPADDR)) != NULL) 395 SAFE_STRCPY(ipaddr, cp); 396 else if ((cp = variable_get(string_concat3(devp->name, "_", VAR_IPADDR))) != NULL) 397 SAFE_STRCPY(ipaddr, cp); 398 } 399 400 /* Get old netmask from variable space, if available */ 401 if (!netmask[0]) { 402 if ((cp = variable_get(VAR_NETMASK)) != NULL) 403 SAFE_STRCPY(netmask, cp); 404 else if ((cp = variable_get(string_concat3(devp->name, "_", VAR_NETMASK))) != NULL) 405 SAFE_STRCPY(netmask, cp); 406 } 407 408 /* Get old extras string from variable space, if available */ 409 if (!extras[0]) { 410 if ((cp = variable_get(VAR_EXTRAS)) != NULL) 411 SAFE_STRCPY(extras, cp); 412 else if ((cp = variable_get(string_concat3(devp->name, "_", VAR_EXTRAS))) != NULL) 413 SAFE_STRCPY(extras, cp); 414 } 415 } 416 417 /* Look up values already recorded with the system, or blank the string variables ready to accept some new data */ 418 if (!hostname[0]) { 419 tmp = variable_get(VAR_HOSTNAME); 420 if (tmp) 421 SAFE_STRCPY(hostname, tmp); 422 } 423 if (!domainname[0]) { 424 tmp = variable_get(VAR_DOMAINNAME); 425 if (tmp) 426 SAFE_STRCPY(domainname, tmp); 427 } 428 if (!gateway[0]) { 429 tmp = variable_get(VAR_GATEWAY); 430 if (tmp && strcmp(tmp, "NO")) 431 SAFE_STRCPY(gateway, tmp); 432 } 433 if (!nameserver[0]) { 434 tmp = variable_get(VAR_NAMESERVER); 435 if (tmp) 436 SAFE_STRCPY(nameserver, tmp); 437 } 438 439 /* If non-interactive, jump straight over the dialog crap and into config section */ 440 if (variable_get(VAR_NONINTERACTIVE) && 441 !variable_get(VAR_NETINTERACTIVE)) { 442 if (!hostname[0]) 443 msgConfirm("WARNING: hostname variable not set and is a non-optional\n" 444 "parameter. Please add this to your installation script\n" 445 "or set the netInteractive variable (see sysinstall man page)"); 446 else 447 goto netconfig; 448 } 449 450 /* Now do all the screen I/O */ 451 dialog_clear_norefresh(); 452 453 /* We need a curses window */ 454 tmp = " Network Configuration "; 455 if (ipv6addr[0]) 456 tmp = string_concat(tmp, "(IPv6 ready) "); 457 if (!(ds_win = openLayoutDialog(TCP_HELPFILE, tmp, 458 TCP_DIALOG_X, TCP_DIALOG_Y, TCP_DIALOG_WIDTH, TCP_DIALOG_HEIGHT))) { 459 beep(); 460 msgConfirm("Cannot open TCP/IP dialog window!!"); 461 restorescr(save); 462 return DITEM_FAILURE; 463 } 464 465 /* Draw interface configuration box */ 466 draw_box(ds_win, TCP_DIALOG_Y + 9, TCP_DIALOG_X + 8, TCP_DIALOG_HEIGHT - 13, TCP_DIALOG_WIDTH - 17, 467 dialog_attr, border_attr); 468 wattrset(ds_win, dialog_attr); 469 sprintf(title, " Configuration for Interface %s ", devp->name); 470 mvwaddstr(ds_win, TCP_DIALOG_Y + 9, TCP_DIALOG_X + 14, title); 471 472 /* Some more initialisation before we go into the main input loop */ 473 obj = initLayoutDialog(ds_win, layout, TCP_DIALOG_X, TCP_DIALOG_Y, &max); 474 475reenter: 476 cancelbutton = okbutton = 0; 477 while (layoutDialogLoop(ds_win, layout, &obj, &n, max, &cancelbutton, &cancel)) { 478 /* Prevent this from being irritating if user really means NO */ 479 if (filled < 3) { 480 /* Insert a default value for the netmask, 0xffffff00 is 481 * the most appropriate one (entire class C, or subnetted 482 * class A/B network). 483 */ 484 if (!netmask[0]) { 485 strcpy(netmask, "255.255.255.0"); 486 RefreshStringObj(layout[LAYOUT_NETMASK].obj); 487 ++filled; 488 } 489 if (!index(hostname, '.') && domainname[0]) { 490 strcat(hostname, "."); 491 strcat(hostname, domainname); 492 RefreshStringObj(layout[LAYOUT_HOSTNAME].obj); 493 ++filled; 494 } 495 else if (((tmp = index(hostname, '.')) != NULL) && !domainname[0]) { 496 SAFE_STRCPY(domainname, tmp + 1); 497 RefreshStringObj(layout[LAYOUT_DOMAINNAME].obj); 498 ++filled; 499 } 500 } 501 } 502 if (!cancel && !verifySettings()) 503 goto reenter; 504 505 /* Clear this crap off the screen */ 506 delwin(ds_win); 507 dialog_clear_norefresh(); 508 use_helpfile(NULL); 509 510 /* We actually need to inform the rest of sysinstall about this 511 data now if the user hasn't selected cancel. Save the stuff 512 out to the environment via the variable_set() mechanism */ 513 514netconfig: 515 if (!cancel) { 516 DevInfo *di; 517 char temp[512], ifn[255]; 518 char *pccard; 519 int ipv4_enable = FALSE; 520 521 if (hostname[0]) { 522 variable_set2(VAR_HOSTNAME, hostname, 1); 523 sethostname(hostname, strlen(hostname)); 524 } 525 if (domainname[0]) 526 variable_set2(VAR_DOMAINNAME, domainname, 0); 527 if (gateway[0]) 528 variable_set2(VAR_GATEWAY, gateway, use_dhcp ? 0 : 1); 529 if (nameserver[0]) 530 variable_set2(VAR_NAMESERVER, nameserver, 0); 531 if (ipaddr[0]) 532 variable_set2(VAR_IPADDR, ipaddr, 0); 533 if (ipv6addr[0]) 534 variable_set2(VAR_IPV6ADDR, ipv6addr, 0); 535 536 if (!devp->private) 537 devp->private = (DevInfo *)safe_malloc(sizeof(DevInfo)); 538 di = devp->private; 539 SAFE_STRCPY(di->ipaddr, ipaddr); 540 SAFE_STRCPY(di->netmask, netmask); 541 SAFE_STRCPY(di->extras, extras); 542 di->use_dhcp = use_dhcp; 543 di->use_rtsol = use_rtsol; 544 545 if (use_dhcp || ipaddr[0]) 546 ipv4_enable = TRUE; 547 if (ipv4_enable) { 548 sprintf(ifn, "%s%s", VAR_IFCONFIG, devp->name); 549 if (use_dhcp) 550 sprintf(temp, "DHCP"); 551 else 552 sprintf(temp, "inet %s %s netmask %s", 553 ipaddr, extras, netmask); 554 variable_set2(ifn, temp, 1); 555 } 556 pccard = variable_get("_pccard_install"); 557 if (pccard && strcmp(pccard, "YES") == 0 && ipv4_enable) { 558 variable_set2("pccard_ifconfig", temp, 1); 559 } 560 if (use_rtsol) 561 variable_set2(VAR_IPV6_ENABLE, "YES", 1); 562 if (!use_dhcp) 563 configResolv(NULL); /* XXX this will do it on the MFS copy XXX */ 564 ret = DITEM_SUCCESS; 565 } 566 else 567 ret = DITEM_FAILURE; 568 restorescr(save); 569 return ret; 570} 571 572static Device *NetDev; 573 574static int 575netHook(dialogMenuItem *self) 576{ 577 Device **devs; 578 579 devs = deviceFindDescr(self->prompt, self->title, DEVICE_TYPE_NETWORK); 580 if (devs) { 581 if (DITEM_STATUS(tcpOpenDialog(devs[0])) != DITEM_FAILURE) 582 NetDev = devs[0]; 583 else 584 NetDev = NULL; 585 } 586 return devs ? DITEM_LEAVE_MENU : DITEM_FAILURE; 587} 588 589/* Get a network device */ 590Device * 591tcpDeviceSelect(void) 592{ 593 DMenu *menu; 594 Device **devs, *rval; 595 int cnt; 596 597 devs = deviceFind(NULL, DEVICE_TYPE_NETWORK); 598 cnt = deviceCount(devs); 599 rval = NULL; 600 601 if (!cnt) { 602 msgConfirm("No network devices available!"); 603 return NULL; 604 } 605 else if ((!RunningAsInit) && (variable_check("NETWORK_CONFIGURED=NO") != TRUE)) { 606 if (!msgYesNo("Running multi-user, assume that the network is already configured?")) 607 return devs[0]; 608 } 609 if (cnt == 1) { 610 if (DITEM_STATUS(tcpOpenDialog(devs[0]) == DITEM_SUCCESS)) 611 rval = devs[0]; 612 } 613 else if (variable_get(VAR_NONINTERACTIVE) && variable_get(VAR_NETWORK_DEVICE)) { 614 devs = deviceFind(variable_get(VAR_NETWORK_DEVICE), DEVICE_TYPE_NETWORK); 615 cnt = deviceCount(devs); 616 if (cnt) { 617 if (DITEM_STATUS(tcpOpenDialog(devs[0]) == DITEM_SUCCESS)) 618 rval = devs[0]; 619 } 620 } 621 else { 622 int status; 623 624 menu = deviceCreateMenu(&MenuNetworkDevice, DEVICE_TYPE_NETWORK, netHook, NULL); 625 if (!menu) 626 msgFatal("Unable to create network device menu! Argh!"); 627 status = dmenuOpenSimple(menu, FALSE); 628 free(menu); 629 if (status) 630 rval = NetDev; 631 } 632 return rval; 633} 634 635/* Do it from a menu that doesn't care about status */ 636int 637tcpMenuSelect(dialogMenuItem *self) 638{ 639 Device *tmp; 640 WINDOW *save; 641 642 variable_set("NETWORK_CONFIGURED=NO",0); 643 tmp = tcpDeviceSelect(); 644 variable_unset("NETWORK_CONFIGURED"); 645 save = savescr(); 646 if (tmp && tmp->private && !((DevInfo *)tmp->private)->use_dhcp && !msgYesNo("Would you like to bring the %s interface up right now?", tmp->name)) 647 if (!tmp->init(tmp)) 648 msgConfirm("Initialization of %s device failed.", tmp->name); 649 restorescr(save); 650 return DITEM_SUCCESS; 651} 652