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

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  *  Copyright (c) 1988-1999 Apple Computer, Inc. All Rights Reserved 
                     24:  */
                     25: 
                     26: /*
                     27:  * bootp.c
                     28:  * - be a BOOTP client over a particular interface to retrieve
                     29:  *   the IP address, netmask, and router
                     30:  */
                     31: 
                     32: /* 
                     33:  * Modification History
                     34:  *
                     35:  * February 19, 1999   Dieter Siegmund ([email protected])
                     36:  * - completely rewritten
                     37:  */
                     38: 
                     39: #include <sys/param.h>
                     40: #include <sys/types.h>
                     41: #include <mach/boolean.h>
                     42: #include <sys/kernel.h>
                     43: #include <sys/errno.h>
                     44: #include <sys/file.h>
                     45: #include <sys/uio.h>
                     46: #include <sys/ioctl.h>
                     47: #include <sys/time.h>
                     48: #include <sys/mbuf.h>
                     49: #include <sys/vnode.h>
                     50: #include <sys/socket.h>
                     51: #include <sys/socketvar.h>
                     52: #include <net/if.h>
                     53: #include <net/if_dl.h>
                     54: #include <net/if_types.h>
                     55: #include <net/route.h>
                     56: #include <netinet/in.h>
                     57: #include <netinet/in_systm.h>
                     58: #include <netinet/if_ether.h>
                     59: #include <netinet/ip.h>
                     60: #include <netinet/ip_var.h>
                     61: #include <netinet/udp.h>
                     62: #include <netinet/udp_var.h>
                     63: #include <netinet/ip_icmp.h>
                     64: #include <netinet/bootp.h>
                     65: #include <sys/systm.h>
                     66: #include <sys/malloc.h>
                     67: 
                     68: //#define BOOTP_DEBUG
                     69: 
                     70: #ifdef BOOTP_DEBUG
                     71: #define        dprintf(x) printf x;
                     72: #else  BOOTP_DEBUG
                     73: #define        dprintf(x)
                     74: #endif BOOTP_DEBUG
                     75: 
                     76: /* ip address formatting macros */
                     77: #define IP_FORMAT      "%d.%d.%d.%d"
                     78: #define IP_CH(ip)      ((u_char *)ip)
                     79: #define IP_LIST(ip)    IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3]
                     80: 
                     81: /* tag values (from RFC 2132) */
                     82: #define TAG_PAD                        0
                     83: #define TAG_END                        255
                     84: #define TAG_SUBNET_MASK                1
                     85: #define TAG_ROUTER             3
                     86: #define RFC_OPTIONS_MAGIC      { 99, 130, 83, 99 }
                     87: static unsigned char           rfc_magic[4] = RFC_OPTIONS_MAGIC;
                     88: 
                     89: 
                     90: static struct sockaddr_in      blank_sin = { sizeof(struct sockaddr_in),
                     91:                                              AF_INET };
                     92: 
                     93: static __inline__ void
                     94: print_reply(struct bootp *bp, int bp_len)
                     95: {
                     96:        int i, j, len;
                     97: 
                     98:        printf("bp_op = ");
                     99:        if (bp->bp_op == BOOTREQUEST) printf("BOOTREQUEST\n");
                    100:        else if (bp->bp_op == BOOTREPLY) printf("BOOTREPLY\n");
                    101:        else
                    102:        {
                    103:                i = bp->bp_op;
                    104:                printf("%d\n", i);
                    105:        }
                    106: 
                    107:        i = bp->bp_htype;
                    108:        printf("bp_htype = %d\n", i);
                    109: 
                    110:        len = bp->bp_hlen;
                    111:        printf("bp_hlen = %d\n", len);
                    112: 
                    113:        i = bp->bp_hops;
                    114:        printf("bp_hops = %d\n", i);
                    115: 
                    116:        printf("bp_xid = %lu\n", bp->bp_xid);
                    117: 
                    118:        printf("bp_secs = %u\n", bp->bp_secs);
                    119: 
                    120:        printf("bp_ciaddr = " IP_FORMAT "\n", IP_LIST(&bp->bp_ciaddr));
                    121:        printf("bp_yiaddr = " IP_FORMAT "\n", IP_LIST(&bp->bp_yiaddr));
                    122:        printf("bp_siaddr = " IP_FORMAT "\n", IP_LIST(&bp->bp_siaddr));
                    123:        printf("bp_giaddr = " IP_FORMAT "\n", IP_LIST(&bp->bp_giaddr));
                    124: 
                    125:        printf("bp_chaddr = ");
                    126:        for (j = 0; j < len; j++)
                    127:        {
                    128:                i = bp->bp_chaddr[j];
                    129:                printf("%0x", i);
                    130:                if (j < (len - 1)) printf(":");
                    131:        }
                    132:        printf("\n");
                    133: 
                    134:        printf("bp_sname = %s\n", bp->bp_sname);
                    135:        printf("bp_file = %s\n", bp->bp_file);
                    136: }
                    137: 
                    138: static __inline__ void
                    139: print_reply_short(struct bootp *bp, int bp_len)
                    140: {
                    141:        printf("bp_yiaddr = " IP_FORMAT "\n", IP_LIST(&bp->bp_yiaddr));
                    142:        printf("bp_sname = %s\n", bp->bp_sname);
                    143: }
                    144: 
                    145: 
                    146: static __inline__ long
                    147: random_range(long bottom, long top)
                    148: {
                    149:     long number = top - bottom + 1;
                    150:     long range_size = LONG_MAX / number;
                    151:     return (((long)random()) / range_size + bottom);
                    152: }
                    153: 
                    154: /*
                    155:  * Function: make_bootp_request
                    156:  * Purpose:
                    157:  *   Create a "blank" bootp packet.
                    158:  */
                    159: static void
                    160: make_bootp_request(struct bootp_packet * pkt, 
                    161:                   u_char * hwaddr, u_char hwtype, u_char hwlen)
                    162: {
                    163:     bzero(pkt, sizeof (*pkt));
                    164:     pkt->bp_ip.ip_v = IPVERSION;
                    165:     pkt->bp_ip.ip_hl = sizeof (struct ip) >> 2;
                    166:     pkt->bp_ip.ip_id = htons(ip_id++);
                    167:     pkt->bp_ip.ip_ttl = MAXTTL;
                    168:     pkt->bp_ip.ip_p = IPPROTO_UDP;
                    169:     pkt->bp_ip.ip_src.s_addr = 0;
                    170:     pkt->bp_ip.ip_dst.s_addr = htonl(INADDR_BROADCAST);
                    171:     pkt->bp_udp.uh_sport = htons(IPPORT_BOOTPC);
                    172:     pkt->bp_udp.uh_dport = htons(IPPORT_BOOTPS);
                    173:     pkt->bp_udp.uh_sum = 0;
                    174:     pkt->bp_bootp.bp_op = BOOTREQUEST;
                    175:     pkt->bp_bootp.bp_htype = hwtype;
                    176:     pkt->bp_bootp.bp_hlen = hwlen;
                    177:     pkt->bp_bootp.bp_ciaddr.s_addr = 0;
                    178:     bcopy(hwaddr, pkt->bp_bootp.bp_chaddr, hwlen);
                    179:     bcopy(rfc_magic, pkt->bp_bootp.bp_vend, sizeof(rfc_magic));
                    180:     pkt->bp_bootp.bp_vend[4] = TAG_END;
                    181:     pkt->bp_udp.uh_ulen = htons(sizeof(pkt->bp_udp) + sizeof(pkt->bp_bootp));
                    182:     pkt->bp_ip.ip_len = htons(sizeof(struct ip) + ntohs(pkt->bp_udp.uh_ulen));
                    183:     pkt->bp_ip.ip_sum = 0;
                    184:     return;
                    185: }
                    186: 
                    187: /*
                    188:  * Function: ip_pkt_to_mbuf
                    189:  * Purpose:
                    190:  *   Put the given IP packet into an mbuf, calculate the
                    191:  *   IP checksum.
                    192:  */
                    193: struct mbuf *
                    194: ip_pkt_to_mbuf(caddr_t pkt, int pktsize)
                    195: {
                    196:     struct ip *                ip;
                    197:     struct mbuf        *       m;
                    198:     
                    199:     m = (struct mbuf *)m_devget(pkt, pktsize, 0, 0, 0);
                    200:     if (m == 0) {
                    201:        printf("bootp: ip_pkt_to_mbuf: m_devget failed\n");
                    202:        return 0;
                    203:     }
                    204:     m->m_flags |= M_BCAST;
                    205:     /* Compute the checksum */
                    206:     ip = mtod(m, struct ip *);
                    207:     ip->ip_sum = 0;
                    208:     ip->ip_sum = in_cksum(m, sizeof (struct ip));
                    209:     return (m);
                    210: }
                    211: 
                    212: static __inline__ u_char *
                    213: link_address(struct sockaddr_dl * dl_p)
                    214: {
                    215:     return (dl_p->sdl_data + dl_p->sdl_nlen);
                    216: }
                    217: 
                    218: static __inline__ void
                    219: link_print(struct sockaddr_dl * dl_p)
                    220: {
                    221:     int i;
                    222: 
                    223: #if 0
                    224:     printf("len %d index %d family %d type 0x%x nlen %d alen %d"
                    225:           " slen %d addr ", dl_p->sdl_len, 
                    226:           dl_p->sdl_index,  dl_p->sdl_family, dl_p->sdl_type,
                    227:           dl_p->sdl_nlen, dl_p->sdl_alen, dl_p->sdl_slen);
                    228: #endif 0
                    229:     for (i = 0; i < dl_p->sdl_alen; i++) 
                    230:        printf("%s%x", i ? ":" : "", 
                    231:               (link_address(dl_p))[i]);
                    232:     printf("\n");
                    233:     return;
                    234: }
                    235: 
                    236: static struct sockaddr_dl *
                    237: link_from_ifnet(struct ifnet * ifp)
                    238: {
                    239:     struct ifaddr * addr;
                    240: 
                    241: /*    for (addr = ifp->if_addrlist; addr; addr = addr->ifa_next) */
                    242: 
                    243:     TAILQ_FOREACH(addr, &ifp->if_addrhead, ifa_link) {
                    244:        if (addr->ifa_addr->sa_family == AF_LINK) {
                    245:            struct sockaddr_dl * dl_p = (struct sockaddr_dl *)(addr->ifa_addr);
                    246:            
                    247:            return (dl_p);
                    248:        }
                    249:     }
                    250:     return (NULL);
                    251: }
                    252: 
                    253: /*
                    254:  * Function: send_bootp_request
                    255:  * Purpose:
                    256:  *     Send the request by calling the interface's output routine
                    257:  *     bypassing routing code.
                    258:  */
                    259: static int
                    260: send_bootp_request(struct ifnet * ifp, struct socket * so,
                    261:                   struct bootp_packet * pkt)
                    262: {
                    263:     struct mbuf        *       m;
                    264:     struct sockaddr_in sin;
                    265:     
                    266:     /* Address to send to */
                    267:     sin = blank_sin;
                    268:     sin.sin_port = htons(IPPORT_BOOTPS);
                    269:     sin.sin_addr.s_addr = INADDR_BROADCAST;
                    270:     
                    271:     m = ip_pkt_to_mbuf((caddr_t)pkt, sizeof(*pkt));
                    272:     return (dlil_output((u_long) ifp, m, 0, (struct sockaddr *)&sin, 0));
                    273: }
                    274: 
                    275: /*
                    276:  * Function: receive_packet
                    277:  * Purpose:
                    278:  *   Return a received packet or an error if none available.
                    279:  */
                    280: int
                    281: receive_packet(struct socket * so, caddr_t pp, int psize)
                    282: {
                    283:     struct iovec       aiov;
                    284:     struct uio         auio;
                    285:     int                        rcvflg;
                    286:     int                        error;
                    287: 
                    288:     aiov.iov_base = pp;
                    289:     aiov.iov_len = psize;
                    290:     auio.uio_iov = &aiov;
                    291:     auio.uio_iovcnt = 1;
                    292:     auio.uio_segflg = UIO_SYSSPACE;
                    293:     auio.uio_offset = 0;
                    294:     auio.uio_resid = psize;
                    295:     auio.uio_rw = UIO_READ;
                    296:     rcvflg = MSG_WAITALL;
                    297:     
                    298:     error = soreceive(so, (struct sockaddr **) 0, &auio, 0, 0, &rcvflg);
                    299:     return (error);
                    300: }
                    301: 
                    302: /*
                    303:  * Function: bootp_timeout
                    304:  * Purpose:
                    305:  *   Wakeup the process waiting for something on a socket.
                    306:  */
                    307: static void
                    308: bootp_timeout(struct socket * * socketflag)
                    309: {
                    310:     struct socket * so = *socketflag;
                    311:     
                    312:     dprintf(("bootp: timeout\n"));
                    313: 
                    314:     *socketflag = NULL;
                    315:     sowakeup(so, &so->so_rcv);
                    316:     return;
                    317: }
                    318: 
                    319: #define TAG_OFFSET     0
                    320: #define LEN_OFFSET     1
                    321: #define OPTION_OFFSET  2
                    322: 
                    323: void *
                    324: packet_option(struct bootp * pkt, u_char t) 
                    325: {
                    326:     void *             buffer = pkt->bp_vend + sizeof(rfc_magic);
                    327:     int                        len;
                    328:     unsigned char      option_len;
                    329:     void *             ret = NULL;
                    330:     unsigned char *    scan;
                    331:     unsigned char      tag = TAG_PAD;
                    332: 
                    333:     len = sizeof(pkt->bp_vend) - sizeof(rfc_magic);
                    334:     for (scan = buffer; len > 0; ) {
                    335:        tag = scan[TAG_OFFSET];
                    336:        if (tag == TAG_END) /* we hit the end of the options */
                    337:            break;
                    338:        if (tag == TAG_PAD) { /* discard pad characters */
                    339:            scan++;
                    340:            len--;
                    341:        }
                    342:        else {
                    343:            if (t == tag && ret == NULL)
                    344:                ret = scan + OPTION_OFFSET;
                    345:            option_len = scan[LEN_OFFSET];
                    346:            len -= (option_len + 2);
                    347:            scan += (option_len + 2);
                    348:        }
                    349:     }
                    350:     if (len < 0 || tag != TAG_END) { /* we ran off the end */
                    351:        if (len < 0) {
                    352:            dprintf(("bootp: error parsing options\n"));
                    353:        }
                    354:        else {
                    355:            dprintf(("bootp: end tag missing\n"));
                    356:        }
                    357:        ret = NULL;
                    358:     }
                    359:     return (ret);
                    360: }
                    361: 
                    362: /*
                    363:  * Function: rate_packet
                    364:  * Purpose:
                    365:  *   Return an integer point rating value for the given bootp packet.
                    366:  *   If yiaddr non-zero, the packet gets a rating of 1.
                    367:  *   Another point is given if the packet contains the subnet mask,
                    368:  *   and another if the router is present.
                    369:  */
                    370: #define GOOD_RATING    3
                    371: static __inline__ int 
                    372: rate_packet(struct bootp * pkt)
                    373: {
                    374:     int rating = 0;
                    375: 
                    376:     if (pkt->bp_yiaddr.s_addr) {
                    377:        struct in_addr * ip;
                    378: 
                    379:        rating++;
                    380:        ip = (struct in_addr *)packet_option(pkt, TAG_SUBNET_MASK);
                    381:        if (ip)
                    382:            rating++;
                    383:        ip = (struct in_addr *)packet_option(pkt, TAG_ROUTER);
                    384:        if (ip)
                    385:            rating++;
                    386:     }
                    387:     return (rating);
                    388: }
                    389: 
                    390: #define INITIAL_WAIT_SECS              4
                    391: #define MAX_WAIT_SECS                  64
                    392: #define GATHER_TIME_SECS               2
                    393: #define RAND_TICKS                     (hz)    /* one second */
                    394: 
                    395: /*
                    396:  * Function: bootp_loop
                    397:  * Purpose:
                    398:  *   Do the actual BOOTP protocol.
                    399:  *   The algorithm sends out a packet, waits for a response.
                    400:  *   We try max_try times, waiting in an exponentially increasing
                    401:  *   amount of time.  Once we receive a good response, we start
                    402:  *   a new time period called the "gather time", during which we
                    403:  *   either find the perfect packet (one that has ip, mask and router)
                    404:  *   or we continue to gather responses.  At the end of the gather period,
                    405:  *   we use the best response gathered.
                    406:  */
                    407: static int
                    408: bootp_loop(struct socket * so, struct ifnet * ifp, int max_try,
                    409:           struct in_addr * iaddr_p, struct in_addr * netmask_p,
                    410:           struct in_addr * router_p)
                    411: {
                    412:     struct timeval             current_time;
                    413:     struct sockaddr_dl *       dl_p;
                    414:     int                                error = 0;
                    415:     char *                     hwaddr;
                    416:     int                                hwlen;
                    417:     char                       hwtype = 0;
                    418:     struct bootp_packet *      request = NULL;
                    419:     struct bootp *             reply = NULL;
                    420:     struct bootp *             saved_reply = NULL;
                    421:     struct timeval             start_time;
                    422:     u_long                     xid;
                    423:     int                                retry;
                    424:     struct socket *            timeflag;
                    425:     int                                wait_ticks = INITIAL_WAIT_SECS * hz;
                    426: 
                    427:     /* get the hardware address from the interface */
                    428:     dl_p = link_from_ifnet(ifp);
                    429:     if (dl_p == NULL) {
                    430:        printf("bootp: can't get link address\n");
                    431:        return (ENXIO);
                    432:     }
                    433: 
                    434:     printf("bootp: h/w addr ");
                    435:     link_print(dl_p);
                    436: 
                    437:     hwaddr = link_address(dl_p);
                    438:     hwlen = dl_p->sdl_alen;
                    439:     switch (dl_p->sdl_type) {
                    440:         case IFT_ETHER:
                    441:            hwtype = ARPHRD_ETHER;
                    442:            break;
                    443:         default:
                    444:            printf("bootp: hardware type %d not supported\n",
                    445:                   dl_p->sdl_type);
                    446:            panic("bootp: hardware type not supported");
                    447:            break;
                    448:     }
                    449: 
                    450:     /* set transaction id and remember the start time */
                    451:     microtime(&start_time);
                    452:     current_time = start_time;
                    453:     xid = random();
                    454:     
                    455:     /* make a request/reply packet */
                    456:     request = (struct bootp_packet *)kalloc(sizeof(*request));
                    457:     make_bootp_request(request, hwaddr, hwtype, hwlen);
                    458:     reply = (struct bootp *)kalloc(sizeof(*reply));
                    459:     saved_reply = (struct bootp *)kalloc(sizeof(*saved_reply));
                    460:     iaddr_p->s_addr = 0;
                    461:     printf("bootp: sending request");
                    462:     for (retry = 0; retry < max_try; retry++) {
                    463:        int             gather_count = 0;
                    464:        int             last_rating = 0;
                    465: 
                    466:        /* Send the request */
                    467:        printf(".");
                    468:        request->bp_bootp.bp_secs = htons((u_short)(current_time.tv_sec 
                    469:                                                    - start_time.tv_sec));
                    470:        request->bp_bootp.bp_xid = htonl(xid);
                    471:        error = send_bootp_request(ifp, so, request);
                    472:        if (error)
                    473:            goto cleanup;
                    474: 
                    475:        timeflag = so;
                    476:        wait_ticks += random_range(-RAND_TICKS, RAND_TICKS);
                    477:        dprintf(("bootp: waiting %d ticks\n", wait_ticks));
                    478:        timeout(bootp_timeout, &timeflag, wait_ticks);
                    479: 
                    480:        while (TRUE) {
                    481:            error = receive_packet(so, (caddr_t)reply, sizeof(*reply));
                    482:            if (error == 0) {
                    483:                dprintf(("\nbootp: received packet\n"));
                    484:                if (ntohl(reply->bp_xid) == xid
                    485:                    && reply->bp_yiaddr.s_addr
                    486:                    && bcmp(reply->bp_chaddr, hwaddr, hwlen) == 0) {
                    487:                    int rating;
                    488: #ifdef BOOTP_DEBUG
                    489:                    print_reply_short(reply, sizeof(*reply));
                    490: #endif BOOTP_DEBUG
                    491:                    rating = rate_packet(reply);
                    492:                    if (rating > last_rating)
                    493:                        *saved_reply = *reply;
                    494:                    if (rating >= GOOD_RATING) {
                    495:                        untimeout(bootp_timeout, &timeflag);
                    496:                        goto save_values;
                    497:                    }
                    498:                    if (gather_count == 0) {
                    499:                        untimeout(bootp_timeout, &timeflag);
                    500:                        timeflag = so;
                    501:                        timeout(bootp_timeout, &timeflag, 
                    502:                                hz * GATHER_TIME_SECS);
                    503:                    }
                    504:                    gather_count++;
                    505:                }
                    506:                else {
                    507:                    dprintf(("bootp: packet ignored\n"));
                    508:                }
                    509:            }
                    510:            else if ((error != EWOULDBLOCK)) {
                    511:                break;
                    512:            }
                    513:            else if (timeflag == NULL) { /* timed out */
                    514:                if (gather_count) {
                    515:                    dprintf(("bootp: gathering time has expired"));
                    516:                    goto save_values; /* we have a packet */
                    517:                }
                    518:                break; /* retry */
                    519:            }
                    520:            else
                    521:                sbwait(&so->so_rcv);
                    522:        }
                    523:        if (error && (error != EWOULDBLOCK)) {
                    524:            dprintf(("bootp: failed to receive packets: %d\n", error));
                    525:            untimeout(bootp_timeout, &timeflag);
                    526:            goto cleanup;
                    527:        }
                    528:        wait_ticks *= 2;
                    529:        if (wait_ticks > (MAX_WAIT_SECS * hz))
                    530:            wait_ticks = MAX_WAIT_SECS * hz;
                    531:        xid++;
                    532:        microtime(&current_time);
                    533:     }
                    534:     error = ETIMEDOUT;
                    535:     goto cleanup;
                    536: 
                    537:  save_values:
                    538:     error = 0;
                    539:     printf("\nbootp: got response from %s (" IP_FORMAT ")\n", 
                    540:           saved_reply->bp_sname, IP_LIST(&saved_reply->bp_siaddr));
                    541:     /* return the ip address */
                    542:     *iaddr_p = saved_reply->bp_yiaddr;
                    543:     {
                    544:        struct in_addr * ip;
                    545:        ip = (struct in_addr *)packet_option(saved_reply, TAG_SUBNET_MASK);
                    546:        if (ip)
                    547:            *netmask_p = *ip;
                    548:        ip = (struct in_addr *)packet_option(saved_reply, TAG_ROUTER);
                    549:        if (ip)
                    550:            *router_p = *ip;
                    551:     }
                    552: 
                    553:  cleanup:
                    554:     if (request)
                    555:        kfree((caddr_t)request, sizeof (*request));
                    556:     if (reply)
                    557:        kfree((caddr_t)reply, sizeof(*reply));
                    558:     if (saved_reply)
                    559:        kfree((caddr_t)saved_reply, sizeof(*saved_reply));
                    560:     return (error);
                    561: }
                    562: 
                    563: /*
                    564:  * Routine: bootp
                    565:  * Function:
                    566:  *     Use the BOOTP protocol to resolve what our IP address should be
                    567:  *     on a particular interface.
                    568:  */
                    569: int bootp(struct ifnet * ifp, struct in_addr * iaddr_p, int max_try,
                    570:          struct in_addr * netmask_p, struct in_addr * router_p,
                    571:          struct proc * procp)
                    572: {
                    573:     boolean_t                  addr_set = FALSE;
                    574:     struct ifreq               ifr;
                    575:     int                                error;
                    576:     struct socket *            so = NULL;
                    577: 
                    578:     /* get a socket */
                    579:     error = socreate(AF_INET, &so, SOCK_DGRAM, 0);
                    580:     if (error) {
                    581:        dprintf(("bootp: socreate failed %d\n", error));
                    582:        return (error);
                    583:     }
                    584: 
                    585:     /* assign the all-zeroes address */
                    586:     bzero(&ifr, sizeof(ifr));
                    587:     sprintf(ifr.ifr_name, "%s%d", ifp->if_name, ifp->if_unit);
                    588:     *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin;
                    589:     error = ifioctl(so, SIOCSIFADDR, (caddr_t)&ifr, procp);
                    590:     if (error) {
                    591:        dprintf(("bootp: SIOCSIFADDR all-zeroes IP failed: %d\n",
                    592:                 error));
                    593:        goto cleanup;
                    594:     }
                    595:     dprintf(("bootp: all-zeroes IP address assigned\n"));
                    596:     addr_set = TRUE;
                    597:     
                    598:     { /* bind the socket */
                    599:        struct sockaddr_in * sin;
                    600: 
                    601:        sin = _MALLOC(sizeof(struct sockaddr_in), M_IFADDR, M_NOWAIT);
                    602:        sin->sin_len = sizeof(struct sockaddr_in);
                    603:        sin->sin_family = AF_INET;
                    604:        sin->sin_port = htons(IPPORT_BOOTPC);
                    605:        sin->sin_addr.s_addr = INADDR_ANY;
                    606:        error = sobind(so, (struct sockaddr *) sin);
                    607: 
                    608:        FREE(sin, M_IFADDR);
                    609:        if (error) {
                    610:            dprintf(("bootp: sobind failed, %d\n", error));
                    611:            goto cleanup;
                    612:        }
                    613:        so->so_state |= SS_NBIO;
                    614:     }
                    615:     /* do the protocol */
                    616:     error = bootp_loop(so, ifp, max_try, iaddr_p, netmask_p, router_p);
                    617:     
                    618:  cleanup:
                    619:     if (so) {
                    620:        if (addr_set) {
                    621:            (void) ifioctl(so, SIOCDIFADDR, (caddr_t) &ifr, procp);
                    622:        }
                    623:        soclose(so);
                    624:     }
                    625:     return (error);
                    626: }
                    627: 
                    628: /*
                    629:  * Function: in_bootp
                    630:  * Purpose: 
                    631:  *   This is deprecated API.  Once SIOCAUTOADDR is eliminated from
                    632:  *   the system (IOEthernet class as well), this routine can be removed.
                    633:  */
                    634: int
                    635: in_bootp(struct ifnet * ifp, struct sockaddr_in * sin, u_char my_enaddr[6])
                    636: {
                    637:     return (EOPNOTSUPP);
                    638: }

unix.superglobalmegacorp.com

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