|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: #if NEXT ! 26: /* ! 27: * Copyright (c) 1988, by NeXT Inc. ! 28: * ! 29: ********************************************************************** ! 30: * HISTORY ! 31: * Tue Mar 18 11:49:14 PST 1997 Dieter Siegmund (dieter) at NeXT ! 32: * Ported from 4.3 to 4.4Lite (Teflon) ! 33: * ! 34: * Mon Jan 10 15:13:33 PST 1994 Matt Watson (mwatson) at NeXT ! 35: * Allow "Sexy Net Init"(tm) while netbooting ! 36: * Function prototype cleanup ! 37: * ! 38: * 09-Apr-90 Bradley Taylor (btaylor) at NeXT ! 39: * Changes because of new network API (netbuf and netif) ! 40: * ! 41: * 25-May-89 Peter King (king) at NeXT ! 42: * Added support for "Sexy Net Init" -- NeXT vendor protocol 1. ! 43: * ! 44: * 15-Aug-88 Peter King (king) at NeXT, Inc. ! 45: * Created. ! 46: ********************************************************************** ! 47: */ ! 48: ! 49: #if m68k ! 50: #else ! 51: ! 52: #import <machine/spl.h> ! 53: #import <machine/label_t.h> ! 54: #import <sys/param.h> ! 55: #import <sys/types.h> ! 56: #import <mach/boolean.h> ! 57: #import <sys/kernel.h> ! 58: #import <sys/errno.h> ! 59: #import <sys/file.h> ! 60: #import <sys/uio.h> ! 61: #import <sys/ioctl.h> ! 62: #import <sys/time.h> ! 63: #import <sys/mbuf.h> ! 64: #import <sys/vnode.h> ! 65: #import <sys/socket.h> ! 66: #import <sys/socketvar.h> ! 67: #import <net/if.h> ! 68: #import <net/route.h> ! 69: #import <netinet/in.h> ! 70: #import <netinet/in_systm.h> ! 71: //#import <netinet/in_pcb.h> ! 72: #import <netinet/if_ether.h> ! 73: #import <netinet/ip.h> ! 74: #import <netinet/ip_var.h> ! 75: #import <netinet/udp.h> ! 76: #import <netinet/udp_var.h> ! 77: #import <netinet/ip_icmp.h> ! 78: #import <netinet/bootp.h> ! 79: #import <dev/kmreg_com.h> ! 80: ! 81: #define CONSOLE "/dev/console" ! 82: ! 83: #define BOOTP_DEBUG 0 ! 84: #if BOOTP_DEBUG ! 85: #define dprintf(x) printf x; ! 86: #else BOOTP_DEBUG ! 87: #define dprintf(x) ! 88: #endif BOOTP_DEBUG ! 89: ! 90: static int in_bootp_initnet(volatile struct ifnet *ifp, struct ifreq *ifr, ! 91: struct socket **sop); ! 92: ! 93: static struct bootp_packet * in_bootp_buildpacket(volatile struct ifnet *ifp, ! 94: struct sockaddr_in *sin, u_char my_enaddr[6]); ! 95: ! 96: struct mbuf * in_bootp_bptombuf(struct bootp_packet *bp); ! 97: ! 98: static void in_bootp_timeout(struct socket **socketflag); ! 99: ! 100: static int in_bootp_promisctimeout(boolean_t *ignoreflag); ! 101: ! 102: static int in_bootp_getpacket(struct socket *so, caddr_t pp, int psize); ! 103: ! 104: static int in_bootp_sendrequest(volatile struct ifnet *ifp, ! 105: struct socket *so, struct bootp_packet *bp_s, struct bootp *bp_r, ! 106: u_char my_enaddr[6], struct vnode **console_vpp); ! 107: ! 108: static int in_bootp_openconsole(struct vnode **vpp); ! 109: ! 110: static void in_bootp_closeconsole(struct vnode *vp); ! 111: ! 112: static int in_bootp_processreply(struct vnode *vp, struct bootp_packet *bp_s, ! 113: struct bootp *bp_r); ! 114: ! 115: static int in_bootp_setaddress(volatile struct ifnet *ifp, struct ifreq *ifr, ! 116: struct socket *so, struct in_addr *addr); ! 117: ! 118: static struct ifreq in_bootp_makeifreq(volatile struct ifnet *ifp, ! 119: struct sockaddr_in *sin); ! 120: ! 121: static void kmgets(char *cp, char *lp, boolean_t silent); ! 122: ! 123: static boolean_t alertShowing = FALSE; ! 124: ! 125: /* ! 126: * Routine: in_bootp ! 127: * Function: ! 128: * Use the BOOTP protocol to resolve what our IP address should be ! 129: * on a particular interface. ! 130: * Note: ! 131: * The ifreq structure returns the newly configured address. If there ! 132: * is an error, it can be full of bogus information. ! 133: * ! 134: * This is called from driver level ioctl routines to assure that ! 135: * the interface is a 10Meg Ethernet. ! 136: */ ! 137: int ! 138: in_bootp( ! 139: volatile struct ifnet *ifp, ! 140: struct sockaddr_in *sin, ! 141: u_char my_enaddr[6] ! 142: ) ! 143: { ! 144: struct mbuf *m; ! 145: struct socket *so; ! 146: register int error; ! 147: struct bootp_packet *bp_s = NULL; ! 148: struct bootp *bp_r = NULL; ! 149: struct vnode *vp = NULL; ! 150: struct nextvend *nv_s; ! 151: struct nextvend *nv_r; ! 152: struct ifreq ifr; ! 153: struct proc * procp = current_proc(); /* XXX */ ! 154: ! 155: dprintf(("in_bootp() entered\n")); ! 156: ! 157: ifr = in_bootp_makeifreq(ifp, sin); ! 158: if (error = in_bootp_initnet(ifp, &ifr, &so)) { ! 159: if (error == -1) { ! 160: /* ! 161: * This means the interface was already ! 162: * autoconfigured. Reset the address to make ! 163: * sure the netmask is right. ! 164: */ ! 165: error = ifioctl(so, SIOCSIFADDR, (caddr_t)&ifr, ! 166: procp); ! 167: if (error == 0) { ! 168: bcopy(&ifr.ifr_addr, sin, sizeof(*sin)); ! 169: } ! 170: soclose(so); ! 171: return (error); ! 172: } ! 173: dprintf(("in_bootp() in_bootp_initnet failed: %d\n", error)); ! 174: goto errout; ! 175: } ! 176: ! 177: /* Build a packet */ ! 178: bp_s = in_bootp_buildpacket(ifp, ! 179: sin, ! 180: my_enaddr); ! 181: nv_s = (struct nextvend *)&bp_s->bp_bootp.bp_vend; ! 182: ! 183: /* Set up place to receive BOOTP response */ ! 184: bp_r = (struct bootp *)kalloc(sizeof (*bp_r)); ! 185: nv_r = (struct nextvend *)&bp_r->bp_vend; ! 186: ! 187: while (TRUE) { ! 188: /* Send the request */ ! 189: dprintf(("in_bootp() trying to send request\n")); ! 190: if (error = in_bootp_sendrequest(ifp, so, bp_s, bp_r, ! 191: my_enaddr, &vp)) { ! 192: goto errout; ! 193: } ! 194: if (nv_r->nv_opcode == BPOP_OK) { ! 195: break; ! 196: } ! 197: dprintf(("in_bootp() trying to open console\n")); ! 198: if (vp == NULL && (error = in_bootp_openconsole(&vp))) { ! 199: goto errout; ! 200: } ! 201: dprintf(("in_bootp() trying to process reply\n")); ! 202: if (error = in_bootp_processreply(vp, bp_s, bp_r)) { ! 203: goto errout; ! 204: } ! 205: } ! 206: ! 207: /* It's for us. */ ! 208: dprintf(("in_bootp() got a response!\n")); ! 209: if (vp) { ! 210: (void) in_bootp_closeconsole(vp); ! 211: vp = NULL; ! 212: } ! 213: ! 214: error = in_bootp_setaddress(ifp, &ifr, so, ! 215: (struct in_addr *)&bp_r->bp_yiaddr); ! 216: if (error == 0) { ! 217: bcopy(&ifr.ifr_addr, sin, sizeof(*sin)); ! 218: } ! 219: ! 220: errout: ! 221: if (error && so) { ! 222: /* Make sure the interface is shut down */ ! 223: (void) ifioctl(so, SIOCDIFADDR, (caddr_t) &ifr, procp); ! 224: ifr.ifr_flags = ifp->if_flags & ~(IFF_UP); ! 225: (void) ifioctl(so, SIOCSIFFLAGS, (caddr_t) &ifr, procp); ! 226: } ! 227: ifp->if_eflags &= ~(IFEF_AUTOCONF); ! 228: if (so) { ! 229: soclose(so); ! 230: } ! 231: if (bp_s) { ! 232: kfree((caddr_t)bp_s, sizeof (*bp_s)); ! 233: } ! 234: if (bp_r) { ! 235: kfree((caddr_t)bp_r, sizeof (*bp_r)); ! 236: } ! 237: if (!error) { ! 238: (void) in_bootp_closeconsole(vp); ! 239: } ! 240: dprintf(("in_bootp() returning: %d\n", error)); ! 241: ! 242: return (error); ! 243: } ! 244: ! 245: /* ! 246: * Routine: in_bootp_initnet ! 247: * Function: ! 248: * Set up the interface to handle BOOTP packets. Return the interface ! 249: * address in ifr. ! 250: * Returns: ! 251: * -1: interface previously autoconfigured ! 252: * 0: success ! 253: * >0: unix error ! 254: */ ! 255: int ! 256: in_bootp_initnet(ifp, ifr, sop) ! 257: register volatile struct ifnet *ifp; ! 258: register struct ifreq *ifr; ! 259: struct socket **sop; ! 260: { ! 261: struct sockaddr_in lsin; ! 262: struct sockaddr_in *sin; ! 263: struct mbuf *m; ! 264: int error; ! 265: struct proc * procp = current_proc(); /* XXX */ ! 266: ! 267: dprintf((" in_bootp_initnet() entered\n")); ! 268: ! 269: /* ! 270: * Get a socket (wouldn't it be nice to make system calls from ! 271: * within the kernel?) ! 272: */ ! 273: dprintf((" in_bootp_initnet() socreate...")); ! 274: if (error = socreate(AF_INET, sop, SOCK_DGRAM, 0)) { ! 275: *sop = NULL; ! 276: dprintf(("failed: %d\n", error)); ! 277: return (error); ! 278: } ! 279: dprintf(("ok\n")); ! 280: ! 281: /* ! 282: * Bring the interface up if neccessary. ! 283: */ ! 284: if ((ifp->if_flags & IFF_UP) == 0) { ! 285: /* Turn off trailers here, otherwise the server ARP reply ! 286: will cause the booting client the issue its own ARP ! 287: reply enabling trailers. ! 288: */ ! 289: ifr->ifr_flags = ifp->if_flags | IFF_UP | IFF_NOTRAILERS; ! 290: dprintf((" in_bootp_initnet() SIOCSIFFLAGS...")); ! 291: if (error = ifioctl(*sop, SIOCSIFFLAGS, (caddr_t)ifr, procp)) { ! 292: dprintf(("failed: %d\n", error)); ! 293: return (error); ! 294: } ! 295: dprintf(("ok\n")); ! 296: } ! 297: else { ! 298: if (ifp->if_eflags & IFEF_AUTOCONF_DONE) { ! 299: /* If the interface was previously autoconfigured, return */ ! 300: dprintf((" in_bootp_initnet() already done:")); ! 301: if ((error = ifioctl(*sop, SIOCGIFADDR, ! 302: (caddr_t)ifr, procp))) { ! 303: dprintf((" %d\n", error)); ! 304: return (error); ! 305: } ! 306: ifp->if_eflags &= ~(IFEF_AUTOCONF); ! 307: dprintf((" -1\n")); ! 308: return(-1); ! 309: } ! 310: } ! 311: ! 312: /* ! 313: * Assign the all-zeroes address to the interface. ! 314: */ ! 315: bzero((caddr_t)&lsin, sizeof(lsin)); ! 316: lsin.sin_family = AF_INET; ! 317: ifr->ifr_addr = *(struct sockaddr *)&lsin; ! 318: ! 319: dprintf((" in_bootp_initnet() SIOCSIFADDR...")); ! 320: if (error = ifioctl(*sop, SIOCSIFADDR, (caddr_t)ifr, procp)) { ! 321: dprintf(("failed: %d\n", ! 322: error)); ! 323: return (error); ! 324: } ! 325: dprintf(("ok\n")); ! 326: ! 327: /* ! 328: * Now set up the socket to receive the BOOTP response, i.e. bind ! 329: * a name to it. ! 330: */ ! 331: dprintf((" in_bootp_initnet() m_get...")); ! 332: m = m_get(M_WAIT, MT_SONAME); ! 333: if (m == NULL) { ! 334: error = ENOBUFS; ! 335: dprintf(("failed: %d\n", error)); ! 336: return (error); ! 337: } ! 338: dprintf(("ok\n")); ! 339: ! 340: m->m_len = sizeof (struct sockaddr_in); ! 341: sin = mtod(m, struct sockaddr_in *); ! 342: sin->sin_family = AF_INET; ! 343: sin->sin_port = htons(IPPORT_BOOTPC); ! 344: sin->sin_addr.s_addr = INADDR_ANY; ! 345: ! 346: dprintf((" in_bootp_initnet() sobind...")); ! 347: error = sobind(*sop, m); ! 348: m_freem(m); ! 349: if (error) { ! 350: dprintf(("failed: %d\n", error)); ! 351: return (error); ! 352: } ! 353: dprintf(("ok\n")); ! 354: ! 355: /* We will be doing non-blocking IO on this socket */ ! 356: (*sop)->so_state |= SS_NBIO; ! 357: ! 358: dprintf((" in_bootp_initnet() exiting normally\n")); ! 359: return (0); ! 360: } ! 361: ! 362: /* ! 363: * Routine: in_bootp_buildpacket ! 364: * Function: ! 365: * Put together a BOOTP request packet. RFC951. ! 366: */ ! 367: struct bootp_packet * ! 368: in_bootp_buildpacket( ! 369: volatile struct ifnet *ifp, /* Interface */ ! 370: struct sockaddr_in *sin, /* Local IP address */ ! 371: u_char my_enaddr[6] /* Local EN address */ ! 372: ) ! 373: { ! 374: struct bootp_packet *bp_s; ! 375: struct nextvend *nv; ! 376: ! 377: dprintf((" in_bootp_buildpacket() entered\n")); ! 378: ! 379: bp_s = (struct bootp_packet *)kalloc(sizeof (*bp_s)); ! 380: nv = (struct nextvend *)&bp_s->bp_bootp.bp_vend; ! 381: ! 382: bzero(bp_s, sizeof (*bp_s)); ! 383: bp_s->bp_ip.ip_v = IPVERSION; ! 384: bp_s->bp_ip.ip_hl = sizeof (struct ip) >> 2; ! 385: bp_s->bp_ip.ip_id = htons(ip_id++); ! 386: bp_s->bp_ip.ip_ttl = MAXTTL; ! 387: bp_s->bp_ip.ip_p = IPPROTO_UDP; ! 388: bp_s->bp_ip.ip_src.s_addr = sin->sin_addr.s_addr; ! 389: bp_s->bp_ip.ip_dst.s_addr = INADDR_BROADCAST; ! 390: bp_s->bp_udp.uh_sport = htons(IPPORT_BOOTPC); ! 391: bp_s->bp_udp.uh_dport = htons(IPPORT_BOOTPS); ! 392: bp_s->bp_udp.uh_sum = 0; ! 393: bp_s->bp_bootp.bp_op = BOOTREQUEST; ! 394: bp_s->bp_bootp.bp_htype = ARPHRD_ETHER; ! 395: bp_s->bp_bootp.bp_hlen = 6; ! 396: bp_s->bp_bootp.bp_ciaddr.s_addr = 0; ! 397: bcopy((caddr_t)my_enaddr, bp_s->bp_bootp.bp_chaddr, 6); ! 398: bcopy(VM_NEXT, &nv->nv_magic, 4); ! 399: ! 400: nv->nv_version = 1; ! 401: nv->nv_opcode = BPOP_OK; ! 402: bp_s->bp_udp.uh_ulen = htons(sizeof (bp_s->bp_udp) + ! 403: sizeof (bp_s->bp_bootp)); ! 404: bp_s->bp_ip.ip_len = htons(sizeof (struct ip) + ! 405: ntohs(bp_s->bp_udp.uh_ulen)); ! 406: bp_s->bp_ip.ip_sum = 0; ! 407: ! 408: dprintf((" in_bootp_buildpacket() exiting\n")); ! 409: ! 410: return (bp_s); ! 411: } ! 412: ! 413: /* ! 414: * Routine: in_bootp_bptombuf ! 415: * Function: ! 416: * Put the outgoing BOOTP packet into an mbuf chain. ! 417: */ ! 418: struct mbuf * ! 419: in_bootp_bptombuf(bp) ! 420: struct bootp_packet *bp; ! 421: { ! 422: register struct ip *ip; ! 423: struct mbuf *m; ! 424: int resid = sizeof (*bp); ! 425: caddr_t cp = (caddr_t) bp; ! 426: ! 427: m = (struct mbuf *)m_devget(bp, sizeof(*bp), 0, 0, 0); ! 428: ! 429: if (m == 0) { ! 430: printf("in_bootp_bptombuf: m_devget failed\n"); ! 431: return 0; ! 432: } ! 433: m->m_flags |= M_BCAST; ! 434: ! 435: /* Compute the checksum */ ! 436: ip = mtod(m, struct ip *); ! 437: ip->ip_sum = 0; ! 438: ip->ip_sum = in_cksum(m, sizeof (struct ip)); ! 439: return (m); ! 440: } ! 441: ! 442: /* ! 443: * Routine: in_bootp_timeout ! 444: * Function: ! 445: * Wakeup the process waiting to receive something on a socket. ! 446: * Boy wouldn't it be nice if we could do system calls from the ! 447: * kernel. Then I could do a select! ! 448: */ ! 449: void ! 450: in_bootp_timeout(socketflag) ! 451: struct socket **socketflag; ! 452: { ! 453: struct socket *so = *socketflag; ! 454: ! 455: dprintf(("\n---->in_bootp_timeout()\n")); ! 456: ! 457: *socketflag = NULL; ! 458: sowakeup(so, &so->so_rcv); ! 459: } ! 460: ! 461: /* ! 462: * Routine: in_bootp_promisctimeout ! 463: * Function: ! 464: * Flag that it is ok to accept a response from a promiscuous BOOTP ! 465: * server. ! 466: */ ! 467: int ! 468: in_bootp_promisctimeout(ignoreflag) ! 469: boolean_t *ignoreflag; ! 470: { ! 471: dprintf(("\n---->in_bootp_promisctimeout()\n")); ! 472: ! 473: *ignoreflag = FALSE; ! 474: return 0; ! 475: } ! 476: ! 477: /* ! 478: * Routine: in_bootp_getpacket ! 479: * Function: ! 480: * Wait for an incoming packet on the socket. ! 481: */ ! 482: int ! 483: in_bootp_getpacket(so, pp, psize) ! 484: struct socket *so; ! 485: caddr_t pp; ! 486: int psize; ! 487: { ! 488: struct iovec aiov; ! 489: struct uio auio; ! 490: int rcvflg; ! 491: ! 492: aiov.iov_base = pp; ! 493: aiov.iov_len = psize; ! 494: auio.uio_iov = &aiov; ! 495: auio.uio_iovcnt = 1; ! 496: auio.uio_segflg = UIO_SYSSPACE; ! 497: auio.uio_offset = 0; ! 498: auio.uio_resid = psize; ! 499: auio.uio_rw = UIO_READ; ! 500: rcvflg = MSG_WAITALL; ! 501: ! 502: return (soreceive(so, 0, &auio, 0, 0, &rcvflg)); ! 503: } ! 504: ! 505: #define INITIAL_DEADLINE 5 ! 506: /* ! 507: * Routine: in_bootp_sendrequest ! 508: * Function: ! 509: * Do the actual work of sending a BOOTP request and getting the ! 510: * response. ! 511: */ ! 512: int ! 513: in_bootp_sendrequest( ! 514: volatile struct ifnet *ifp, ! 515: struct socket *so, ! 516: struct bootp_packet *bp_s, ! 517: struct bootp *bp_r, ! 518: u_char my_enaddr[6], ! 519: struct vnode **console_vpp ! 520: ) { ! 521: struct mbuf *m; ! 522: register int error; ! 523: int xid; ! 524: struct timeval tv; ! 525: int timeo; ! 526: int timecount; ! 527: unsigned long totaltime; ! 528: unsigned long deadline; ! 529: struct socket *timeflag; ! 530: label_t jmpbuf; ! 531: struct sockaddr_in lsin; ! 532: struct nextvend *nv_s = ! 533: (struct nextvend *) &bp_s->bp_bootp.bp_vend; ! 534: struct nextvend *nv_r = (struct nextvend *)&bp_r->bp_vend; ! 535: boolean_t promisc_rcvd = FALSE; ! 536: boolean_t promisc_ignore; ! 537: ! 538: dprintf((" in_bootp_sendrequest() entered\n")); ! 539: ! 540: /* Create a transaction ID */ ! 541: microtime(&tv); ! 542: xid = my_enaddr[5] ^ tv.tv_sec; ! 543: bp_s->bp_bootp.bp_xid = xid; ! 544: ! 545: /* Address to send to */ ! 546: lsin.sin_family = AF_INET; ! 547: lsin.sin_port = htons(IPPORT_BOOTPS); ! 548: lsin.sin_addr.s_addr = INADDR_BROADCAST; ! 549: ! 550: /* ! 551: * timeout/retry policy: ! 552: * Before a server has responded we retransmit at a random time ! 553: * in a binary window which is doubled each transmission. This ! 554: * avoids flooding the net after, say, a power failure when all ! 555: * machines are trying to reboot simultaneously. ! 556: */ ! 557: timeo = 1; ! 558: timecount = 0; ! 559: totaltime = 0; ! 560: deadline = INITIAL_DEADLINE; ! 561: ! 562: while (TRUE) { ! 563: if (timecount == 0) { ! 564: /* Put the outgoing packet in an mbuf */ ! 565: m = in_bootp_bptombuf(bp_s); ! 566: dprintf((" in_bootp_sendrequest() if_output ")); ! 567: if (error = (*ifp->if_output)(ifp, m, ! 568: (struct sockaddr *)&lsin, 0)) { ! 569: dprintf(("failed: %d\n", error)); ! 570: goto errout; ! 571: } ! 572: dprintf(("ok\n")); ! 573: } ! 574: ! 575: /* ! 576: * Sleep for a second and then check for the abort ! 577: * character again. ! 578: */ ! 579: timeflag = so; ! 580: timeout(in_bootp_timeout, &timeflag, hz); ! 581: keepwaiting: ! 582: dprintf((" in_bootp_sendrequest(): in_bootp_getpacket...")); ! 583: while (((error = in_bootp_getpacket(so, (caddr_t)bp_r, sizeof (*bp_r))) ! 584: == EWOULDBLOCK) && (timeflag == so)) { ! 585: /* dprintf(("waiting (spl = 0x%x)...", curspl())); */ ! 586: sbwait(&so->so_rcv); ! 587: } ! 588: if (error && (error != EWOULDBLOCK)) { ! 589: dprintf(("failed: %d\n", error)); ! 590: untimeout(in_bootp_timeout, &timeflag); ! 591: goto errout; ! 592: } ! 593: if (timeflag == NULL) { ! 594: dprintf((" in_bootp_sendrequest(): " ! 595: "in_bootp_getpacket...timed out\n")); ! 596: if ((deadline > INITIAL_DEADLINE) && (timecount & 1)) ! 597: printf("."); ! 598: timecount++; ! 599: totaltime++; ! 600: if (timecount == timeo) { ! 601: if (timeo < 64) { ! 602: timeo <<= 1; ! 603: } ! 604: timecount = 0; ! 605: } ! 606: if (totaltime == deadline) { ! 607: register c = 0; ! 608: ! 609: if (error=in_bootp_openconsole(console_vpp)) { ! 610: goto errout; ! 611: } ! 612: printf("\nServer %snot responding.\n" ! 613: "Continue without network? (y/n) ", ! 614: (deadline == INITIAL_DEADLINE) ? "is " : "still "); ! 615: while (1) { ! 616: c = kmgetc_silent(0) & 0177; ! 617: if (c == 'y' || c == 'Y') { ! 618: printf("%c\n", c); ! 619: psignal(current_proc(), SIGINT); ! 620: error = EINTR; ! 621: in_bootp_closeconsole(*console_vpp); ! 622: goto errout; ! 623: } ! 624: else if (c == 'n' || c == 'N') { ! 625: break; ! 626: } ! 627: } ! 628: printf("%c\nWaiting for response.", c); ! 629: deadline += 30; ! 630: } ! 631: ! 632: continue; ! 633: } ! 634: ! 635: dprintf(("received packet!\n")); ! 636: ! 637: /* We have a packet. Check it out. */ ! 638: if (bp_r->bp_xid != xid || ! 639: bp_r->bp_op != BOOTREPLY || ! 640: bcmp(bp_r->bp_chaddr, my_enaddr, 6) != 0) { ! 641: dprintf((" in_bootp_sendrequest() not for us\n")); ! 642: goto keepwaiting; ! 643: } ! 644: ! 645: /* ! 646: * It's for us. If it is not an authoritative answer, ! 647: * wait for a while (10 secs) to see if there is an ! 648: * authoritative server out there. ! 649: */ ! 650: if (nv_s->nv_opcode == BPOP_OK && nv_r->nv_opcode != BPOP_OK) { ! 651: if (!promisc_rcvd) { ! 652: promisc_rcvd = TRUE; ! 653: promisc_ignore = TRUE; ! 654: timeout(in_bootp_promisctimeout, ! 655: &promisc_ignore, 10 * hz); ! 656: dprintf((" in_bootp_sendrequest() " ! 657: "ignoring 1st promisc response\n")); ! 658: goto keepwaiting; ! 659: } ! 660: if (promisc_ignore == TRUE) { ! 661: dprintf((" in_bootp_sendrequest() " ! 662: "ignoring promisc response\n")); ! 663: goto keepwaiting; ! 664: } ! 665: } ! 666: ! 667: ! 668: /* OK, it's for us */ ! 669: dprintf((" in_bootp_sendrequest() it's for us!\n")); ! 670: ! 671: untimeout(in_bootp_timeout, &timeflag); ! 672: ! 673: if (alertShowing) { ! 674: printf("Network responded!\n"); ! 675: } ! 676: error = 0; ! 677: goto errout; ! 678: } ! 679: ! 680: /* We aborted. Return appropriate error */ ! 681: error = ETIMEDOUT; ! 682: ! 683: errout: ! 684: dprintf((" in_bootp_sendrequest() returning %d\n", error)); ! 685: ! 686: untimeout(in_bootp_promisctimeout, &promisc_ignore); ! 687: return (error); ! 688: } ! 689: ! 690: /* ! 691: * Routine: in_bootp_openconsole ! 692: * Function: ! 693: * Pop up a console window so that we can do some user I/O to ! 694: * answer the server's questions. ! 695: */ ! 696: int ! 697: in_bootp_openconsole(vpp) ! 698: struct vnode **vpp; ! 699: { ! 700: int ret = 0; ! 701: struct proc * procp = current_proc(); /* XXX */ ! 702: ! 703: if (alertShowing == FALSE) { ! 704: ret = alert(60, 8, "Configuring Network", "%L", 0, 0, 0, 0, 0, 0, 0); ! 705: alertShowing = TRUE; ! 706: } ! 707: dprintf(("in_bootp_openconsole() returning: %d\n", ret)); ! 708: return(ret); ! 709: } ! 710: ! 711: /* ! 712: * Routine: in_bootp_closeconsole ! 713: * Function: ! 714: * Restore and close and the console window. ! 715: */ ! 716: void ! 717: in_bootp_closeconsole(vp) ! 718: struct vnode *vp; ! 719: { ! 720: if (alertShowing) ! 721: alert_done(); ! 722: alertShowing = FALSE; ! 723: } ! 724: ! 725: /* ! 726: * Routine: in_bootp_processreply ! 727: * Function: ! 728: * The heart of "Sexy Net Init". This routine handles requests from ! 729: * the BOOTP server to interact with the user. ! 730: */ ! 731: int ! 732: in_bootp_processreply(vp, bp_s, bp_r) ! 733: struct vnode *vp; ! 734: struct bootp_packet *bp_s; ! 735: struct bootp *bp_r; ! 736: { ! 737: struct nextvend *nv_s = ! 738: (struct nextvend *) &bp_s->bp_bootp.bp_vend; ! 739: struct nextvend *nv_r = (struct nextvend *)&bp_r->bp_vend; ! 740: int resid; ! 741: int error; ! 742: int flush = FREAD; ! 743: boolean_t noecho = FALSE; ! 744: char *cp; ! 745: ! 746: /* Truncate text if needed */ ! 747: if (strlen(nv_r->nv_text) > NVMAXTEXT) { ! 748: nv_r->nv_null = '\0'; ! 749: } ! 750: ! 751: /* Write out the server message */ ! 752: printf("%s", nv_r->nv_text); ! 753: ! 754: if (error = kmioctl(0, TIOCFLUSH, &flush, 0)) { ! 755: goto errout; ! 756: } ! 757: switch (nv_r->nv_opcode) { ! 758: case BPOP_QUERY_NE: ! 759: noecho = TRUE; ! 760: /* Fall through */ ! 761: ! 762: case BPOP_QUERY: ! 763: error = 0; ! 764: /* Read in the user response */ ! 765: kmgets(nv_s->nv_text, nv_s->nv_text, noecho); ! 766: ! 767: /* If we are not echoing, move the cursor to the next line */ ! 768: if (noecho) { ! 769: printf("\n"); ! 770: } ! 771: ! 772: /* Get rid of the CR or LF if either exists. */ ! 773: for (cp = (char *)nv_s->nv_text; *cp; cp++) { ! 774: if (*cp == '\n' || *cp == '\r') { ! 775: *cp = '\0'; ! 776: break; ! 777: } ! 778: } ! 779: ! 780: /* Set the destination, opcode and xid */ ! 781: bp_s->bp_ip.ip_dst = *(struct in_addr *)&bp_r->bp_siaddr; ! 782: nv_s->nv_opcode = nv_r->nv_opcode; ! 783: nv_s->nv_xid = nv_r->nv_xid; ! 784: break; ! 785: ! 786: case BPOP_ERROR: ! 787: /* Reset the destination, opcode and xid */ ! 788: bp_s->bp_ip.ip_dst.s_addr = INADDR_BROADCAST; ! 789: nv_s->nv_opcode = BPOP_OK; ! 790: nv_s->nv_xid = 0; ! 791: break; ! 792: } ! 793: errout: ! 794: return (error); ! 795: } ! 796: ! 797: /* ! 798: * Routine: in_bootp_setaddress ! 799: * Function: ! 800: * Set the address of the interface. Leave the new address in ifr ! 801: * to be returned to the user. ! 802: */ ! 803: int ! 804: in_bootp_setaddress(ifp, ifr, so, addr) ! 805: register volatile struct ifnet *ifp; ! 806: register struct ifreq *ifr; ! 807: struct socket *so; ! 808: struct in_addr *addr; ! 809: { ! 810: struct sockaddr_in *sin; ! 811: int error; ! 812: struct proc * procp = current_proc(); /* XXX */ ! 813: ! 814: dprintf((" in_bootp_setaddress() entered\n")); ! 815: ! 816: ifr->ifr_flags = ifp->if_flags & ~(IFF_UP); ! 817: if (error = ifioctl(so, SIOCSIFFLAGS, (caddr_t) ifr, procp)) { ! 818: dprintf((" in_bootp_setaddress() SIOCSIFFLAGS failed: %d\n", ! 819: error)); ! 820: return (error); ! 821: } ! 822: ! 823: /* Clear the netmask first */ ! 824: sin = (struct sockaddr_in *)&(ifr->ifr_addr); ! 825: bzero((caddr_t)sin, sizeof(struct sockaddr_in)); ! 826: sin->sin_len = sizeof(*sin); ! 827: sin->sin_family = AF_INET; ! 828: if (error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ifr, procp)) { ! 829: dprintf((" in_bootp_setaddress() SIOCSIFNETMASK failed: %d\n", ! 830: error)); ! 831: return (error); ! 832: } ! 833: ! 834: /* Now set the new address */ ! 835: sin->sin_addr.s_addr = addr->s_addr; ! 836: if (error = ifioctl(so, SIOCSIFADDR, (caddr_t)ifr, procp)) { ! 837: dprintf((" in_bootp_setaddress() SIOCSIFADDR failed: %d\n", ! 838: error)); ! 839: return (error); ! 840: } ! 841: ! 842: /* Flag that we have autoconfigured */ ! 843: ifp->if_eflags |= IFEF_AUTOCONF_DONE; ! 844: ! 845: dprintf((" in_bootp_setaddress() exiting\n")); ! 846: ! 847: return (0); ! 848: } ! 849: ! 850: /* ! 851: * Routine: in_bootp_makeifreq ! 852: * Function: ! 853: * Make a valid ifreq struct from interface pointer and an address ! 854: */ ! 855: struct ifreq ! 856: in_bootp_makeifreq( ! 857: volatile struct ifnet *ifp, ! 858: struct sockaddr_in *sin ! 859: ) ! 860: { ! 861: struct ifreq ifr; ! 862: char *p; ! 863: ! 864: strcpy(ifr.ifr_name, ifp->if_name); ! 865: for (p = ifr.ifr_name; *p; p++) { ! 866: } ! 867: *p++ = ifp->if_unit + '0'; ! 868: *p = 0; ! 869: bcopy(sin, &ifr.ifr_addr, sizeof(*sin)); ! 870: return (ifr); ! 871: } ! 872: ! 873: /* ! 874: * Routine: kmgets (mostly stolen from swapgeneric.{c,m} ! 875: * Function: ! 876: * Allows printing echoed or non-echoed text. ! 877: */ ! 878: void ! 879: kmgets(cp, lp, silent) ! 880: char *cp, *lp; ! 881: boolean_t silent; ! 882: { ! 883: register c = 0; ! 884: ! 885: for (;;) { ! 886: if (silent) { ! 887: c = kmgetc_silent(0) & 0177; ! 888: } else { ! 889: c = kmgetc(0) & 0177; ! 890: } ! 891: switch (c) { ! 892: case '\n': ! 893: case '\r': ! 894: *lp++ = '\0'; ! 895: return; ! 896: case '\177': ! 897: if (lp == cp) { ! 898: cnputc('\b'); ! 899: continue; ! 900: } ! 901: cnputc('\b'); ! 902: cnputc('\b'); ! 903: /* fall into ... */ ! 904: case '\b': ! 905: if (lp == cp) { ! 906: cnputc('\b'); ! 907: continue; ! 908: } ! 909: cnputc(' '); ! 910: cnputc('\b'); ! 911: lp--; ! 912: continue; ! 913: case '@': ! 914: case 'u'&037: ! 915: lp = cp; ! 916: cnputc('\n'); ! 917: continue; ! 918: default: ! 919: *lp++ = c; ! 920: } ! 921: } ! 922: } ! 923: ! 924: #endif ! 925: #endif NEXT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.