Annotation of kernel/bsd/netinet/in_bootp.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.