|
|
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(¤t_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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.