bootp_subr.c revision 301057
1/*- 2 * Copyright (c) 1995 Gordon Ross, Adam Glass 3 * Copyright (c) 1992 Regents of the University of California. 4 * All rights reserved. 5 * 6 * This software was developed by the Computer Systems Engineering group 7 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 8 * contributed to Berkeley. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Lawrence Berkeley Laboratory and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * based on: 39 * nfs/krpc_subr.c 40 * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ 41 */ 42 43#include <sys/cdefs.h> 44__FBSDID("$FreeBSD: stable/10/sys/nfs/bootp_subr.c 301057 2016-05-31 17:15:57Z ian $"); 45 46#include "opt_bootp.h" 47#include "opt_nfs.h" 48#include "opt_rootdevname.h" 49 50#include <sys/param.h> 51#include <sys/systm.h> 52#include <sys/endian.h> 53#include <sys/jail.h> 54#include <sys/kernel.h> 55#include <sys/sockio.h> 56#include <sys/malloc.h> 57#include <sys/mount.h> 58#include <sys/mbuf.h> 59#include <sys/proc.h> 60#include <sys/reboot.h> 61#include <sys/socket.h> 62#include <sys/socketvar.h> 63#include <sys/sysctl.h> 64#include <sys/uio.h> 65 66#include <net/if.h> 67#include <net/route.h> 68 69#include <netinet/in.h> 70#include <netinet/in_var.h> 71#include <net/if_types.h> 72#include <net/if_dl.h> 73#include <net/vnet.h> 74 75#include <nfs/nfsproto.h> 76#include <nfsclient/nfs.h> 77#include <nfs/nfsdiskless.h> 78#include <nfs/krpc.h> 79#include <nfs/xdr_subs.h> 80 81 82#define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */ 83 84#ifndef BOOTP_SETTLE_DELAY 85#define BOOTP_SETTLE_DELAY 3 86#endif 87 88/* 89 * Wait 10 seconds for interface appearance 90 * USB ethernet adapters might require some time to pop up 91 */ 92#ifndef BOOTP_IFACE_WAIT_TIMEOUT 93#define BOOTP_IFACE_WAIT_TIMEOUT 10 94#endif 95 96/* 97 * What is the longest we will wait before re-sending a request? 98 * Note this is also the frequency of "RPC timeout" messages. 99 * The re-send loop count sup linearly to this maximum, so the 100 * first complaint will happen after (1+2+3+4+5)=15 seconds. 101 */ 102#define MAX_RESEND_DELAY 5 /* seconds */ 103 104/* Definitions from RFC951 */ 105struct bootp_packet { 106 u_int8_t op; 107 u_int8_t htype; 108 u_int8_t hlen; 109 u_int8_t hops; 110 u_int32_t xid; 111 u_int16_t secs; 112 u_int16_t flags; 113 struct in_addr ciaddr; 114 struct in_addr yiaddr; 115 struct in_addr siaddr; 116 struct in_addr giaddr; 117 unsigned char chaddr[16]; 118 char sname[64]; 119 char file[128]; 120 unsigned char vend[1222]; 121}; 122 123struct bootpc_ifcontext { 124 STAILQ_ENTRY(bootpc_ifcontext) next; 125 struct bootp_packet call; 126 struct bootp_packet reply; 127 int replylen; 128 int overload; 129 union { 130 struct ifreq _ifreq; 131 struct in_aliasreq _in_alias_req; 132 } _req; 133#define ireq _req._ifreq 134#define iareq _req._in_alias_req 135 struct ifnet *ifp; 136 struct sockaddr_dl *sdl; 137 struct sockaddr_in myaddr; 138 struct sockaddr_in netmask; 139 struct sockaddr_in gw; 140 int gotgw; 141 int gotnetmask; 142 int gotrootpath; 143 int outstanding; 144 int sentmsg; 145 u_int32_t xid; 146 enum { 147 IF_BOOTP_UNRESOLVED, 148 IF_BOOTP_RESOLVED, 149 IF_BOOTP_FAILED, 150 IF_DHCP_UNRESOLVED, 151 IF_DHCP_OFFERED, 152 IF_DHCP_RESOLVED, 153 IF_DHCP_FAILED, 154 } state; 155 int dhcpquerytype; /* dhcp type sent */ 156 struct in_addr dhcpserver; 157 int gotdhcpserver; 158 uint16_t mtu; 159}; 160 161#define TAG_MAXLEN 1024 162struct bootpc_tagcontext { 163 char buf[TAG_MAXLEN + 1]; 164 int overload; 165 int badopt; 166 int badtag; 167 int foundopt; 168 int taglen; 169}; 170 171struct bootpc_globalcontext { 172 STAILQ_HEAD(, bootpc_ifcontext) interfaces; 173 u_int32_t xid; 174 int any_root_overrides; 175 int gotrootpath; 176 int gotgw; 177 int ifnum; 178 int secs; 179 int starttime; 180 struct bootp_packet reply; 181 int replylen; 182 struct bootpc_ifcontext *setrootfs; 183 struct bootpc_ifcontext *sethostname; 184 struct bootpc_tagcontext tmptag; 185 struct bootpc_tagcontext tag; 186}; 187 188#define IPPORT_BOOTPC 68 189#define IPPORT_BOOTPS 67 190 191#define BOOTP_REQUEST 1 192#define BOOTP_REPLY 2 193 194/* Common tags */ 195#define TAG_PAD 0 /* Pad option, implicit length 1 */ 196#define TAG_SUBNETMASK 1 /* RFC 950 subnet mask */ 197#define TAG_ROUTERS 3 /* Routers (in order of preference) */ 198#define TAG_HOSTNAME 12 /* Client host name */ 199#define TAG_ROOT 17 /* Root path */ 200#define TAG_INTF_MTU 26 /* Interface MTU Size (RFC2132) */ 201 202/* DHCP specific tags */ 203#define TAG_OVERLOAD 52 /* Option Overload */ 204#define TAG_MAXMSGSIZE 57 /* Maximum DHCP Message Size */ 205 206#define TAG_END 255 /* End Option (i.e. no more options) */ 207 208/* Overload values */ 209#define OVERLOAD_FILE 1 210#define OVERLOAD_SNAME 2 211 212/* Site specific tags: */ 213#define TAG_ROOTOPTS 130 214#define TAG_COOKIE 134 /* ascii info for userland, via sysctl */ 215 216#define TAG_DHCP_MSGTYPE 53 217#define TAG_DHCP_REQ_ADDR 50 218#define TAG_DHCP_SERVERID 54 219#define TAG_DHCP_LEASETIME 51 220 221#define TAG_VENDOR_INDENTIFIER 60 222 223#define DHCP_NOMSG 0 224#define DHCP_DISCOVER 1 225#define DHCP_OFFER 2 226#define DHCP_REQUEST 3 227#define DHCP_ACK 5 228 229/* NFS read/write block size */ 230#ifndef BOOTP_BLOCKSIZE 231#define BOOTP_BLOCKSIZE 8192 232#endif 233 234static char bootp_cookie[128]; 235static struct socket *bootp_so; 236SYSCTL_STRING(_kern, OID_AUTO, bootp_cookie, CTLFLAG_RD, 237 bootp_cookie, 0, "Cookie (T134) supplied by bootp server"); 238 239/* mountd RPC */ 240static int md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, 241 int *fhsizep, struct nfs_args *args, struct thread *td); 242static int setfs(struct sockaddr_in *addr, char *path, char *p, 243 const struct in_addr *siaddr); 244static int getdec(char **ptr); 245static int getip(char **ptr, struct in_addr *ip); 246static void mountopts(struct nfs_args *args, char *p); 247static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len); 248static int xdr_int_decode(struct mbuf **ptr, int *iptr); 249static void print_in_addr(struct in_addr addr); 250static void print_sin_addr(struct sockaddr_in *addr); 251static void clear_sinaddr(struct sockaddr_in *sin); 252static void allocifctx(struct bootpc_globalcontext *gctx); 253static void bootpc_compose_query(struct bootpc_ifcontext *ifctx, 254 struct thread *td); 255static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx, 256 struct bootp_packet *bp, int len, int tag); 257static void bootpc_tag_helper(struct bootpc_tagcontext *tctx, 258 unsigned char *start, int len, int tag); 259 260#ifdef BOOTP_DEBUG 261void bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma); 262void bootpboot_p_rtentry(struct rtentry *rt); 263void bootpboot_p_tree(struct radix_node *rn); 264void bootpboot_p_rtlist(void); 265void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa); 266void bootpboot_p_iflist(void); 267#endif 268 269static int bootpc_call(struct bootpc_globalcontext *gctx, 270 struct thread *td); 271 272static void bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, 273 struct thread *td); 274 275static void bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, 276 struct bootpc_globalcontext *gctx, struct thread *td); 277 278static void bootpc_decode_reply(struct nfsv3_diskless *nd, 279 struct bootpc_ifcontext *ifctx, 280 struct bootpc_globalcontext *gctx); 281 282static int bootpc_received(struct bootpc_globalcontext *gctx, 283 struct bootpc_ifcontext *ifctx); 284 285static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx); 286static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx); 287static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx); 288 289/* 290 * In order to have multiple active interfaces with address 0.0.0.0 291 * and be able to send data to a selected interface, we first set 292 * mask to /8 on all interfaces, and temporarily set it to /0 when 293 * doing sosend(). 294 */ 295 296#ifdef BOOTP_DEBUG 297void 298bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma) 299{ 300 301 if (sa == NULL) { 302 printf("(sockaddr *) <null>"); 303 return; 304 } 305 switch (sa->sa_family) { 306 case AF_INET: 307 { 308 struct sockaddr_in *sin; 309 310 sin = (struct sockaddr_in *) sa; 311 printf("inet "); 312 print_sin_addr(sin); 313 if (ma != NULL) { 314 sin = (struct sockaddr_in *) ma; 315 printf(" mask "); 316 print_sin_addr(sin); 317 } 318 } 319 break; 320 case AF_LINK: 321 { 322 struct sockaddr_dl *sli; 323 int i; 324 325 sli = (struct sockaddr_dl *) sa; 326 printf("link %.*s ", sli->sdl_nlen, sli->sdl_data); 327 for (i = 0; i < sli->sdl_alen; i++) { 328 if (i > 0) 329 printf(":"); 330 printf("%x", ((unsigned char *) LLADDR(sli))[i]); 331 } 332 } 333 break; 334 default: 335 printf("af%d", sa->sa_family); 336 } 337} 338 339void 340bootpboot_p_rtentry(struct rtentry *rt) 341{ 342 343 bootpboot_p_sa(rt_key(rt), rt_mask(rt)); 344 printf(" "); 345 bootpboot_p_sa(rt->rt_gateway, NULL); 346 printf(" "); 347 printf("flags %x", (unsigned short) rt->rt_flags); 348 printf(" %d", (int) rt->rt_expire); 349 printf(" %s\n", rt->rt_ifp->if_xname); 350} 351 352void 353bootpboot_p_tree(struct radix_node *rn) 354{ 355 356 while (rn != NULL) { 357 if (rn->rn_bit < 0) { 358 if ((rn->rn_flags & RNF_ROOT) != 0) { 359 } else { 360 bootpboot_p_rtentry((struct rtentry *) rn); 361 } 362 rn = rn->rn_dupedkey; 363 } else { 364 bootpboot_p_tree(rn->rn_left); 365 bootpboot_p_tree(rn->rn_right); 366 return; 367 } 368 } 369} 370 371void 372bootpboot_p_rtlist(void) 373{ 374 struct radix_node_head *rnh; 375 376 printf("Routing table:\n"); 377 rnh = rt_tables_get_rnh(0, AF_INET); 378 if (rnh == NULL) 379 return; 380 RADIX_NODE_HEAD_RLOCK(rnh); /* could sleep XXX */ 381 bootpboot_p_tree(rnh->rnh_treetop); 382 RADIX_NODE_HEAD_RUNLOCK(rnh); 383} 384 385void 386bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa) 387{ 388 389 printf("%s flags %x, addr ", 390 ifp->if_xname, ifp->if_flags); 391 print_sin_addr((struct sockaddr_in *) ifa->ifa_addr); 392 printf(", broadcast "); 393 print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr); 394 printf(", netmask "); 395 print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask); 396 printf("\n"); 397} 398 399void 400bootpboot_p_iflist(void) 401{ 402 struct ifnet *ifp; 403 struct ifaddr *ifa; 404 405 printf("Interface list:\n"); 406 IFNET_RLOCK(); 407 for (ifp = TAILQ_FIRST(&V_ifnet); 408 ifp != NULL; 409 ifp = TAILQ_NEXT(ifp, if_link)) { 410 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); 411 ifa != NULL; 412 ifa = TAILQ_NEXT(ifa, ifa_link)) 413 if (ifa->ifa_addr->sa_family == AF_INET) 414 bootpboot_p_if(ifp, ifa); 415 } 416 IFNET_RUNLOCK(); 417} 418#endif /* defined(BOOTP_DEBUG) */ 419 420static void 421clear_sinaddr(struct sockaddr_in *sin) 422{ 423 424 bzero(sin, sizeof(*sin)); 425 sin->sin_len = sizeof(*sin); 426 sin->sin_family = AF_INET; 427 sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */ 428 sin->sin_port = 0; 429} 430 431static void 432allocifctx(struct bootpc_globalcontext *gctx) 433{ 434 struct bootpc_ifcontext *ifctx; 435 436 ifctx = malloc(sizeof(*ifctx), M_TEMP, M_WAITOK | M_ZERO); 437 ifctx->xid = gctx->xid; 438#ifdef BOOTP_NO_DHCP 439 ifctx->state = IF_BOOTP_UNRESOLVED; 440#else 441 ifctx->state = IF_DHCP_UNRESOLVED; 442#endif 443 gctx->xid += 0x100; 444 STAILQ_INSERT_TAIL(&gctx->interfaces, ifctx, next); 445} 446 447static __inline int 448bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx) 449{ 450 451 if (ifctx->state == IF_BOOTP_RESOLVED || 452 ifctx->state == IF_DHCP_RESOLVED) 453 return 1; 454 return 0; 455} 456 457static __inline int 458bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx) 459{ 460 461 if (ifctx->state == IF_BOOTP_UNRESOLVED || 462 ifctx->state == IF_DHCP_UNRESOLVED) 463 return 1; 464 return 0; 465} 466 467static __inline int 468bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx) 469{ 470 471 if (ifctx->state == IF_BOOTP_FAILED || 472 ifctx->state == IF_DHCP_FAILED) 473 return 1; 474 return 0; 475} 476 477static int 478bootpc_received(struct bootpc_globalcontext *gctx, 479 struct bootpc_ifcontext *ifctx) 480{ 481 unsigned char dhcpreplytype; 482 char *p; 483 484 /* 485 * Need timeout for fallback to less 486 * desirable alternative. 487 */ 488 489 /* This call used for the side effect (badopt flag) */ 490 (void) bootpc_tag(&gctx->tmptag, &gctx->reply, 491 gctx->replylen, 492 TAG_END); 493 494 /* If packet is invalid, ignore it */ 495 if (gctx->tmptag.badopt != 0) 496 return 0; 497 498 p = bootpc_tag(&gctx->tmptag, &gctx->reply, 499 gctx->replylen, TAG_DHCP_MSGTYPE); 500 if (p != NULL) 501 dhcpreplytype = *p; 502 else 503 dhcpreplytype = DHCP_NOMSG; 504 505 switch (ifctx->dhcpquerytype) { 506 case DHCP_DISCOVER: 507 if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */ 508#ifndef BOOTP_FORCE_DHCP 509 && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */ 510#endif 511 ) 512 return 0; 513 break; 514 case DHCP_REQUEST: 515 if (dhcpreplytype != DHCP_ACK) 516 return 0; 517 case DHCP_NOMSG: 518 break; 519 } 520 521 /* Ignore packet unless it gives us a root tag we didn't have */ 522 523 if ((ifctx->state == IF_BOOTP_RESOLVED || 524 (ifctx->dhcpquerytype == DHCP_DISCOVER && 525 (ifctx->state == IF_DHCP_OFFERED || 526 ifctx->state == IF_DHCP_RESOLVED))) && 527 (bootpc_tag(&gctx->tmptag, &ifctx->reply, 528 ifctx->replylen, 529 TAG_ROOT) != NULL || 530 bootpc_tag(&gctx->tmptag, &gctx->reply, 531 gctx->replylen, 532 TAG_ROOT) == NULL)) 533 return 0; 534 535 bcopy(&gctx->reply, &ifctx->reply, gctx->replylen); 536 ifctx->replylen = gctx->replylen; 537 538 /* XXX: Only reset if 'perfect' response */ 539 if (ifctx->state == IF_BOOTP_UNRESOLVED) 540 ifctx->state = IF_BOOTP_RESOLVED; 541 else if (ifctx->state == IF_DHCP_UNRESOLVED && 542 ifctx->dhcpquerytype == DHCP_DISCOVER) { 543 if (dhcpreplytype == DHCP_OFFER) 544 ifctx->state = IF_DHCP_OFFERED; 545 else 546 ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */ 547 } else if (ifctx->state == IF_DHCP_OFFERED && 548 ifctx->dhcpquerytype == DHCP_REQUEST) 549 ifctx->state = IF_DHCP_RESOLVED; 550 551 552 if (ifctx->dhcpquerytype == DHCP_DISCOVER && 553 ifctx->state != IF_BOOTP_RESOLVED) { 554 p = bootpc_tag(&gctx->tmptag, &ifctx->reply, 555 ifctx->replylen, TAG_DHCP_SERVERID); 556 if (p != NULL && gctx->tmptag.taglen == 4) { 557 memcpy(&ifctx->dhcpserver, p, 4); 558 ifctx->gotdhcpserver = 1; 559 } else 560 ifctx->gotdhcpserver = 0; 561 return 1; 562 } 563 564 ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 565 ifctx->replylen, 566 TAG_ROOT) != NULL); 567 ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 568 ifctx->replylen, 569 TAG_ROUTERS) != NULL); 570 ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 571 ifctx->replylen, 572 TAG_SUBNETMASK) != NULL); 573 return 1; 574} 575 576static int 577bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td) 578{ 579 struct sockaddr_in *sin, dst; 580 struct uio auio; 581 struct sockopt sopt; 582 struct iovec aio; 583 int error, on, rcvflg, timo, len; 584 time_t atimo; 585 time_t rtimo; 586 struct timeval tv; 587 struct bootpc_ifcontext *ifctx; 588 int outstanding; 589 int gotrootpath; 590 int retry; 591 const char *s; 592 593 tv.tv_sec = 1; 594 tv.tv_usec = 0; 595 bzero(&sopt, sizeof(sopt)); 596 sopt.sopt_dir = SOPT_SET; 597 sopt.sopt_level = SOL_SOCKET; 598 sopt.sopt_name = SO_RCVTIMEO; 599 sopt.sopt_val = &tv; 600 sopt.sopt_valsize = sizeof tv; 601 602 error = sosetopt(bootp_so, &sopt); 603 if (error != 0) 604 goto out; 605 606 /* 607 * Enable broadcast. 608 */ 609 on = 1; 610 sopt.sopt_name = SO_BROADCAST; 611 sopt.sopt_val = &on; 612 sopt.sopt_valsize = sizeof on; 613 614 error = sosetopt(bootp_so, &sopt); 615 if (error != 0) 616 goto out; 617 618 /* 619 * Disable routing. 620 */ 621 622 on = 1; 623 sopt.sopt_name = SO_DONTROUTE; 624 sopt.sopt_val = &on; 625 sopt.sopt_valsize = sizeof on; 626 627 error = sosetopt(bootp_so, &sopt); 628 if (error != 0) 629 goto out; 630 631 /* 632 * Bind the local endpoint to a bootp client port. 633 */ 634 sin = &dst; 635 clear_sinaddr(sin); 636 sin->sin_port = htons(IPPORT_BOOTPC); 637 error = sobind(bootp_so, (struct sockaddr *)sin, td); 638 if (error != 0) { 639 printf("bind failed\n"); 640 goto out; 641 } 642 643 /* 644 * Setup socket address for the server. 645 */ 646 sin = &dst; 647 clear_sinaddr(sin); 648 sin->sin_addr.s_addr = INADDR_BROADCAST; 649 sin->sin_port = htons(IPPORT_BOOTPS); 650 651 /* 652 * Send it, repeatedly, until a reply is received, 653 * but delay each re-send by an increasing amount. 654 * If the delay hits the maximum, start complaining. 655 */ 656 timo = 0; 657 rtimo = 0; 658 for (;;) { 659 660 outstanding = 0; 661 gotrootpath = 0; 662 663 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) { 664 if (bootpc_ifctx_isresolved(ifctx) != 0 && 665 bootpc_tag(&gctx->tmptag, &ifctx->reply, 666 ifctx->replylen, 667 TAG_ROOT) != NULL) 668 gotrootpath = 1; 669 } 670 671 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) { 672 struct in_aliasreq *ifra = &ifctx->iareq; 673 sin = (struct sockaddr_in *)&ifra->ifra_mask; 674 675 ifctx->outstanding = 0; 676 if (bootpc_ifctx_isresolved(ifctx) != 0 && 677 gotrootpath != 0) { 678 continue; 679 } 680 if (bootpc_ifctx_isfailed(ifctx) != 0) 681 continue; 682 683 outstanding++; 684 ifctx->outstanding = 1; 685 686 /* Proceed to next step in DHCP negotiation */ 687 if ((ifctx->state == IF_DHCP_OFFERED && 688 ifctx->dhcpquerytype != DHCP_REQUEST) || 689 (ifctx->state == IF_DHCP_UNRESOLVED && 690 ifctx->dhcpquerytype != DHCP_DISCOVER) || 691 (ifctx->state == IF_BOOTP_UNRESOLVED && 692 ifctx->dhcpquerytype != DHCP_NOMSG)) { 693 ifctx->sentmsg = 0; 694 bootpc_compose_query(ifctx, td); 695 } 696 697 /* Send BOOTP request (or re-send). */ 698 699 if (ifctx->sentmsg == 0) { 700 switch(ifctx->dhcpquerytype) { 701 case DHCP_DISCOVER: 702 s = "DHCP Discover"; 703 break; 704 case DHCP_REQUEST: 705 s = "DHCP Request"; 706 break; 707 case DHCP_NOMSG: 708 default: 709 s = "BOOTP Query"; 710 break; 711 } 712 printf("Sending %s packet from " 713 "interface %s (%*D)\n", 714 s, 715 ifctx->ireq.ifr_name, 716 ifctx->sdl->sdl_alen, 717 (unsigned char *) LLADDR(ifctx->sdl), 718 ":"); 719 ifctx->sentmsg = 1; 720 } 721 722 aio.iov_base = (caddr_t) &ifctx->call; 723 aio.iov_len = sizeof(ifctx->call); 724 725 auio.uio_iov = &aio; 726 auio.uio_iovcnt = 1; 727 auio.uio_segflg = UIO_SYSSPACE; 728 auio.uio_rw = UIO_WRITE; 729 auio.uio_offset = 0; 730 auio.uio_resid = sizeof(ifctx->call); 731 auio.uio_td = td; 732 733 /* Set netmask to 0.0.0.0 */ 734 clear_sinaddr(sin); 735 error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, 736 td); 737 if (error != 0) 738 panic("%s: SIOCAIFADDR, error=%d", __func__, 739 error); 740 741 error = sosend(bootp_so, (struct sockaddr *) &dst, 742 &auio, NULL, NULL, 0, td); 743 if (error != 0) 744 printf("%s: sosend: %d state %08x\n", __func__, 745 error, (int )bootp_so->so_state); 746 747 /* Set netmask to 255.0.0.0 */ 748 sin->sin_addr.s_addr = htonl(IN_CLASSA_NET); 749 error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, 750 td); 751 if (error != 0) 752 panic("%s: SIOCAIFADDR, error=%d", __func__, 753 error); 754 } 755 756 if (outstanding == 0 && 757 (rtimo == 0 || time_second >= rtimo)) { 758 error = 0; 759 goto out; 760 } 761 762 /* Determine new timeout. */ 763 if (timo < MAX_RESEND_DELAY) 764 timo++; 765 else { 766 printf("DHCP/BOOTP timeout for server "); 767 print_sin_addr(&dst); 768 printf("\n"); 769 } 770 771 /* 772 * Wait for up to timo seconds for a reply. 773 * The socket receive timeout was set to 1 second. 774 */ 775 atimo = timo + time_second; 776 while (time_second < atimo) { 777 aio.iov_base = (caddr_t) &gctx->reply; 778 aio.iov_len = sizeof(gctx->reply); 779 780 auio.uio_iov = &aio; 781 auio.uio_iovcnt = 1; 782 auio.uio_segflg = UIO_SYSSPACE; 783 auio.uio_rw = UIO_READ; 784 auio.uio_offset = 0; 785 auio.uio_resid = sizeof(gctx->reply); 786 auio.uio_td = td; 787 788 rcvflg = 0; 789 error = soreceive(bootp_so, NULL, &auio, 790 NULL, NULL, &rcvflg); 791 gctx->secs = time_second - gctx->starttime; 792 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) { 793 if (bootpc_ifctx_isresolved(ifctx) != 0 || 794 bootpc_ifctx_isfailed(ifctx) != 0) 795 continue; 796 797 ifctx->call.secs = htons(gctx->secs); 798 } 799 if (error == EWOULDBLOCK) 800 continue; 801 if (error != 0) 802 goto out; 803 len = sizeof(gctx->reply) - auio.uio_resid; 804 805 /* Do we have the required number of bytes ? */ 806 if (len < BOOTP_MIN_LEN) 807 continue; 808 gctx->replylen = len; 809 810 /* Is it a reply? */ 811 if (gctx->reply.op != BOOTP_REPLY) 812 continue; 813 814 /* Is this an answer to our query */ 815 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) { 816 if (gctx->reply.xid != ifctx->call.xid) 817 continue; 818 819 /* Same HW address size ? */ 820 if (gctx->reply.hlen != ifctx->call.hlen) 821 continue; 822 823 /* Correct HW address ? */ 824 if (bcmp(gctx->reply.chaddr, 825 ifctx->call.chaddr, 826 ifctx->call.hlen) != 0) 827 continue; 828 829 break; 830 } 831 832 if (ifctx != NULL) { 833 s = bootpc_tag(&gctx->tmptag, 834 &gctx->reply, 835 gctx->replylen, 836 TAG_DHCP_MSGTYPE); 837 if (s != NULL) { 838 switch (*s) { 839 case DHCP_OFFER: 840 s = "DHCP Offer"; 841 break; 842 case DHCP_ACK: 843 s = "DHCP Ack"; 844 break; 845 default: 846 s = "DHCP (unexpected)"; 847 break; 848 } 849 } else 850 s = "BOOTP Reply"; 851 852 printf("Received %s packet" 853 " on %s from ", 854 s, 855 ifctx->ireq.ifr_name); 856 print_in_addr(gctx->reply.siaddr); 857 if (gctx->reply.giaddr.s_addr != 858 htonl(INADDR_ANY)) { 859 printf(" via "); 860 print_in_addr(gctx->reply.giaddr); 861 } 862 if (bootpc_received(gctx, ifctx) != 0) { 863 printf(" (accepted)"); 864 if (ifctx->outstanding) { 865 ifctx->outstanding = 0; 866 outstanding--; 867 } 868 /* Network settle delay */ 869 if (outstanding == 0) 870 atimo = time_second + 871 BOOTP_SETTLE_DELAY; 872 } else 873 printf(" (ignored)"); 874 if (ifctx->gotrootpath || 875 gctx->any_root_overrides) { 876 gotrootpath = 1; 877 rtimo = time_second + 878 BOOTP_SETTLE_DELAY; 879 if (ifctx->gotrootpath) 880 printf(" (got root path)"); 881 } 882 printf("\n"); 883 } 884 } /* while secs */ 885#ifdef BOOTP_TIMEOUT 886 if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0) 887 break; 888#endif 889 /* Force a retry if halfway in DHCP negotiation */ 890 retry = 0; 891 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) 892 if (ifctx->state == IF_DHCP_OFFERED) { 893 if (ifctx->dhcpquerytype == DHCP_DISCOVER) 894 retry = 1; 895 else 896 ifctx->state = IF_DHCP_UNRESOLVED; 897 } 898 899 if (retry != 0) 900 continue; 901 902 if (gotrootpath != 0) { 903 gctx->gotrootpath = gotrootpath; 904 if (rtimo != 0 && time_second >= rtimo) 905 break; 906 } 907 } /* forever send/receive */ 908 909 /* 910 * XXX: These are errors of varying seriousness being silently 911 * ignored 912 */ 913 914 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) 915 if (bootpc_ifctx_isresolved(ifctx) == 0) { 916 printf("%s timeout for interface %s\n", 917 ifctx->dhcpquerytype != DHCP_NOMSG ? 918 "DHCP" : "BOOTP", 919 ifctx->ireq.ifr_name); 920 } 921 922 if (gctx->gotrootpath != 0) { 923#if 0 924 printf("Got a root path, ignoring remaining timeout\n"); 925#endif 926 error = 0; 927 goto out; 928 } 929#ifndef BOOTP_NFSROOT 930 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) 931 if (bootpc_ifctx_isresolved(ifctx) != 0) { 932 error = 0; 933 goto out; 934 } 935#endif 936 error = ETIMEDOUT; 937 938out: 939 return (error); 940} 941 942static void 943bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, struct thread *td) 944{ 945 struct ifreq *ifr; 946 struct in_aliasreq *ifra; 947 struct sockaddr_in *sin; 948 int error; 949 950 ifr = &ifctx->ireq; 951 ifra = &ifctx->iareq; 952 953 /* 954 * Bring up the interface. 955 * 956 * Get the old interface flags and or IFF_UP into them; if 957 * IFF_UP set blindly, interface selection can be clobbered. 958 */ 959 error = ifioctl(bootp_so, SIOCGIFFLAGS, (caddr_t)ifr, td); 960 if (error != 0) 961 panic("%s: SIOCGIFFLAGS, error=%d", __func__, error); 962 ifr->ifr_flags |= IFF_UP; 963 error = ifioctl(bootp_so, SIOCSIFFLAGS, (caddr_t)ifr, td); 964 if (error != 0) 965 panic("%s: SIOCSIFFLAGS, error=%d", __func__, error); 966 967 /* 968 * Do enough of ifconfig(8) so that the chosen interface 969 * can talk to the servers. Set address to 0.0.0.0/8 and 970 * broadcast address to local broadcast. 971 */ 972 sin = (struct sockaddr_in *)&ifra->ifra_addr; 973 clear_sinaddr(sin); 974 sin = (struct sockaddr_in *)&ifra->ifra_mask; 975 clear_sinaddr(sin); 976 sin->sin_addr.s_addr = htonl(IN_CLASSA_NET); 977 sin = (struct sockaddr_in *)&ifra->ifra_broadaddr; 978 clear_sinaddr(sin); 979 sin->sin_addr.s_addr = htonl(INADDR_BROADCAST); 980 error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, td); 981 if (error != 0) 982 panic("%s: SIOCAIFADDR, error=%d", __func__, error); 983} 984 985static void 986bootpc_shutdown_interface(struct bootpc_ifcontext *ifctx, struct thread *td) 987{ 988 struct ifreq *ifr; 989 struct sockaddr_in *sin; 990 int error; 991 992 ifr = &ifctx->ireq; 993 994 printf("Shutdown interface %s\n", ifctx->ireq.ifr_name); 995 error = ifioctl(bootp_so, SIOCGIFFLAGS, (caddr_t)ifr, td); 996 if (error != 0) 997 panic("%s: SIOCGIFFLAGS, error=%d", __func__, error); 998 ifr->ifr_flags &= ~IFF_UP; 999 error = ifioctl(bootp_so, SIOCSIFFLAGS, (caddr_t)ifr, td); 1000 if (error != 0) 1001 panic("%s: SIOCSIFFLAGS, error=%d", __func__, error); 1002 1003 sin = (struct sockaddr_in *) &ifr->ifr_addr; 1004 clear_sinaddr(sin); 1005 error = ifioctl(bootp_so, SIOCDIFADDR, (caddr_t) ifr, td); 1006 if (error != 0) 1007 panic("%s: SIOCDIFADDR, error=%d", __func__, error); 1008} 1009 1010static void 1011bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, 1012 struct bootpc_globalcontext *gctx, struct thread *td) 1013{ 1014 int error; 1015 struct sockaddr_in *sin; 1016 struct ifreq *ifr; 1017 struct in_aliasreq *ifra; 1018 struct sockaddr_in *myaddr; 1019 struct sockaddr_in *netmask; 1020 1021 ifr = &ifctx->ireq; 1022 ifra = &ifctx->iareq; 1023 myaddr = &ifctx->myaddr; 1024 netmask = &ifctx->netmask; 1025 1026 if (bootpc_ifctx_isresolved(ifctx) == 0) { 1027 /* Shutdown interfaces where BOOTP failed */ 1028 bootpc_shutdown_interface(ifctx, td); 1029 return; 1030 } 1031 1032 printf("Adjusted interface %s", ifctx->ireq.ifr_name); 1033 1034 /* Do BOOTP interface options */ 1035 if (ifctx->mtu != 0) { 1036 printf(" (MTU=%d%s)", ifctx->mtu, 1037 (ifctx->mtu > 1514) ? "/JUMBO" : ""); 1038 ifr->ifr_mtu = ifctx->mtu; 1039 error = ifioctl(bootp_so, SIOCSIFMTU, (caddr_t) ifr, td); 1040 if (error != 0) 1041 panic("%s: SIOCSIFMTU, error=%d", __func__, error); 1042 } 1043 printf("\n"); 1044 1045 /* 1046 * Do enough of ifconfig(8) so that the chosen interface 1047 * can talk to the servers. (just set the address) 1048 */ 1049 sin = (struct sockaddr_in *) &ifr->ifr_addr; 1050 clear_sinaddr(sin); 1051 error = ifioctl(bootp_so, SIOCDIFADDR, (caddr_t) ifr, td); 1052 if (error != 0) 1053 panic("%s: SIOCDIFADDR, error=%d", __func__, error); 1054 1055 bcopy(myaddr, &ifra->ifra_addr, sizeof(*myaddr)); 1056 bcopy(netmask, &ifra->ifra_mask, sizeof(*netmask)); 1057 clear_sinaddr(&ifra->ifra_broadaddr); 1058 ifra->ifra_broadaddr.sin_addr.s_addr = myaddr->sin_addr.s_addr | 1059 ~netmask->sin_addr.s_addr; 1060 1061 error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, td); 1062 if (error != 0) 1063 panic("%s: SIOCAIFADDR, error=%d", __func__, error); 1064} 1065 1066static void 1067bootpc_add_default_route(struct bootpc_ifcontext *ifctx) 1068{ 1069 int error; 1070 struct sockaddr_in defdst; 1071 struct sockaddr_in defmask; 1072 1073 if (ifctx->gw.sin_addr.s_addr == htonl(INADDR_ANY)) 1074 return; 1075 1076 clear_sinaddr(&defdst); 1077 clear_sinaddr(&defmask); 1078 1079 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&defdst, 1080 (struct sockaddr *) &ifctx->gw, (struct sockaddr *)&defmask, 1081 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, RT_DEFAULT_FIB); 1082 if (error != 0) { 1083 printf("%s: RTM_ADD, error=%d\n", __func__, error); 1084 } 1085} 1086 1087static void 1088bootpc_remove_default_route(struct bootpc_ifcontext *ifctx) 1089{ 1090 int error; 1091 struct sockaddr_in defdst; 1092 struct sockaddr_in defmask; 1093 1094 if (ifctx->gw.sin_addr.s_addr == htonl(INADDR_ANY)) 1095 return; 1096 1097 clear_sinaddr(&defdst); 1098 clear_sinaddr(&defmask); 1099 1100 error = rtrequest_fib(RTM_DELETE, (struct sockaddr *)&defdst, 1101 (struct sockaddr *) &ifctx->gw, (struct sockaddr *)&defmask, 1102 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, RT_DEFAULT_FIB); 1103 if (error != 0) { 1104 printf("%s: RTM_DELETE, error=%d\n", __func__, error); 1105 } 1106} 1107 1108static int 1109setfs(struct sockaddr_in *addr, char *path, char *p, 1110 const struct in_addr *siaddr) 1111{ 1112 1113 if (getip(&p, &addr->sin_addr) == 0) { 1114 if (siaddr != NULL && *p == '/') 1115 bcopy(siaddr, &addr->sin_addr, sizeof(struct in_addr)); 1116 else 1117 return 0; 1118 } else { 1119 if (*p != ':') 1120 return 0; 1121 p++; 1122 } 1123 1124 addr->sin_len = sizeof(struct sockaddr_in); 1125 addr->sin_family = AF_INET; 1126 1127 strlcpy(path, p, MNAMELEN); 1128 return 1; 1129} 1130 1131static int 1132getip(char **ptr, struct in_addr *addr) 1133{ 1134 char *p; 1135 unsigned int ip; 1136 int val; 1137 1138 p = *ptr; 1139 ip = 0; 1140 if (((val = getdec(&p)) < 0) || (val > 255)) 1141 return 0; 1142 ip = val << 24; 1143 if (*p != '.') 1144 return 0; 1145 p++; 1146 if (((val = getdec(&p)) < 0) || (val > 255)) 1147 return 0; 1148 ip |= (val << 16); 1149 if (*p != '.') 1150 return 0; 1151 p++; 1152 if (((val = getdec(&p)) < 0) || (val > 255)) 1153 return 0; 1154 ip |= (val << 8); 1155 if (*p != '.') 1156 return 0; 1157 p++; 1158 if (((val = getdec(&p)) < 0) || (val > 255)) 1159 return 0; 1160 ip |= val; 1161 1162 addr->s_addr = htonl(ip); 1163 *ptr = p; 1164 return 1; 1165} 1166 1167static int 1168getdec(char **ptr) 1169{ 1170 char *p; 1171 int ret; 1172 1173 p = *ptr; 1174 ret = 0; 1175 if ((*p < '0') || (*p > '9')) 1176 return -1; 1177 while ((*p >= '0') && (*p <= '9')) { 1178 ret = ret * 10 + (*p - '0'); 1179 p++; 1180 } 1181 *ptr = p; 1182 return ret; 1183} 1184 1185static void 1186mountopts(struct nfs_args *args, char *p) 1187{ 1188 args->version = NFS_ARGSVERSION; 1189 args->rsize = BOOTP_BLOCKSIZE; 1190 args->wsize = BOOTP_BLOCKSIZE; 1191 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT; 1192 args->sotype = SOCK_DGRAM; 1193 if (p != NULL) 1194 nfs_parse_options(p, args); 1195} 1196 1197static int 1198xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) 1199{ 1200 struct mbuf *m; 1201 int alignedlen; 1202 1203 m = *mptr; 1204 alignedlen = ( len + 3 ) & ~3; 1205 1206 if (m->m_len < alignedlen) { 1207 m = m_pullup(m, alignedlen); 1208 if (m == NULL) { 1209 *mptr = NULL; 1210 return EBADRPC; 1211 } 1212 } 1213 bcopy(mtod(m, u_char *), buf, len); 1214 m_adj(m, alignedlen); 1215 *mptr = m; 1216 return 0; 1217} 1218 1219static int 1220xdr_int_decode(struct mbuf **mptr, int *iptr) 1221{ 1222 u_int32_t i; 1223 1224 if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) 1225 return EBADRPC; 1226 *iptr = fxdr_unsigned(u_int32_t, i); 1227 return 0; 1228} 1229 1230static void 1231print_sin_addr(struct sockaddr_in *sin) 1232{ 1233 1234 print_in_addr(sin->sin_addr); 1235} 1236 1237static void 1238print_in_addr(struct in_addr addr) 1239{ 1240 unsigned int ip; 1241 1242 ip = ntohl(addr.s_addr); 1243 printf("%d.%d.%d.%d", 1244 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); 1245} 1246 1247static void 1248bootpc_compose_query(struct bootpc_ifcontext *ifctx, struct thread *td) 1249{ 1250 unsigned char *vendp; 1251 unsigned char vendor_client[64]; 1252 uint32_t leasetime; 1253 uint8_t vendor_client_len; 1254 1255 ifctx->gotrootpath = 0; 1256 1257 bzero((caddr_t) &ifctx->call, sizeof(ifctx->call)); 1258 1259 /* bootpc part */ 1260 ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */ 1261 ifctx->call.htype = 1; /* 10mb ethernet */ 1262 ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */ 1263 ifctx->call.hops = 0; 1264 if (bootpc_ifctx_isunresolved(ifctx) != 0) 1265 ifctx->xid++; 1266 ifctx->call.xid = txdr_unsigned(ifctx->xid); 1267 bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen); 1268 1269 vendp = ifctx->call.vend; 1270 *vendp++ = 99; /* RFC1048 cookie */ 1271 *vendp++ = 130; 1272 *vendp++ = 83; 1273 *vendp++ = 99; 1274 *vendp++ = TAG_MAXMSGSIZE; 1275 *vendp++ = 2; 1276 *vendp++ = (sizeof(struct bootp_packet) >> 8) & 255; 1277 *vendp++ = sizeof(struct bootp_packet) & 255; 1278 1279 snprintf(vendor_client, sizeof(vendor_client), "%s:%s:%s", 1280 ostype, MACHINE, osrelease); 1281 vendor_client_len = strlen(vendor_client); 1282 *vendp++ = TAG_VENDOR_INDENTIFIER; 1283 *vendp++ = vendor_client_len; 1284 memcpy(vendp, vendor_client, vendor_client_len); 1285 vendp += vendor_client_len; 1286 ifctx->dhcpquerytype = DHCP_NOMSG; 1287 switch (ifctx->state) { 1288 case IF_DHCP_UNRESOLVED: 1289 *vendp++ = TAG_DHCP_MSGTYPE; 1290 *vendp++ = 1; 1291 *vendp++ = DHCP_DISCOVER; 1292 ifctx->dhcpquerytype = DHCP_DISCOVER; 1293 ifctx->gotdhcpserver = 0; 1294 break; 1295 case IF_DHCP_OFFERED: 1296 *vendp++ = TAG_DHCP_MSGTYPE; 1297 *vendp++ = 1; 1298 *vendp++ = DHCP_REQUEST; 1299 ifctx->dhcpquerytype = DHCP_REQUEST; 1300 *vendp++ = TAG_DHCP_REQ_ADDR; 1301 *vendp++ = 4; 1302 memcpy(vendp, &ifctx->reply.yiaddr, 4); 1303 vendp += 4; 1304 if (ifctx->gotdhcpserver != 0) { 1305 *vendp++ = TAG_DHCP_SERVERID; 1306 *vendp++ = 4; 1307 memcpy(vendp, &ifctx->dhcpserver, 4); 1308 vendp += 4; 1309 } 1310 *vendp++ = TAG_DHCP_LEASETIME; 1311 *vendp++ = 4; 1312 leasetime = htonl(300); 1313 memcpy(vendp, &leasetime, 4); 1314 vendp += 4; 1315 break; 1316 default: 1317 break; 1318 } 1319 *vendp = TAG_END; 1320 1321 ifctx->call.secs = 0; 1322 ifctx->call.flags = htons(0x8000); /* We need a broadcast answer */ 1323} 1324 1325static int 1326bootpc_hascookie(struct bootp_packet *bp) 1327{ 1328 1329 return (bp->vend[0] == 99 && bp->vend[1] == 130 && 1330 bp->vend[2] == 83 && bp->vend[3] == 99); 1331} 1332 1333static void 1334bootpc_tag_helper(struct bootpc_tagcontext *tctx, 1335 unsigned char *start, int len, int tag) 1336{ 1337 unsigned char *j; 1338 unsigned char *ej; 1339 unsigned char code; 1340 1341 if (tctx->badtag != 0 || tctx->badopt != 0) 1342 return; 1343 1344 j = start; 1345 ej = j + len; 1346 1347 while (j < ej) { 1348 code = *j++; 1349 if (code == TAG_PAD) 1350 continue; 1351 if (code == TAG_END) 1352 return; 1353 if (j >= ej || j + *j + 1 > ej) { 1354 tctx->badopt = 1; 1355 return; 1356 } 1357 len = *j++; 1358 if (code == tag) { 1359 if (tctx->taglen + len > TAG_MAXLEN) { 1360 tctx->badtag = 1; 1361 return; 1362 } 1363 tctx->foundopt = 1; 1364 if (len > 0) 1365 memcpy(tctx->buf + tctx->taglen, 1366 j, len); 1367 tctx->taglen += len; 1368 } 1369 if (code == TAG_OVERLOAD) 1370 tctx->overload = *j; 1371 1372 j += len; 1373 } 1374} 1375 1376static unsigned char * 1377bootpc_tag(struct bootpc_tagcontext *tctx, 1378 struct bootp_packet *bp, int len, int tag) 1379{ 1380 tctx->overload = 0; 1381 tctx->badopt = 0; 1382 tctx->badtag = 0; 1383 tctx->foundopt = 0; 1384 tctx->taglen = 0; 1385 1386 if (bootpc_hascookie(bp) == 0) 1387 return NULL; 1388 1389 bootpc_tag_helper(tctx, &bp->vend[4], 1390 (unsigned char *) bp + len - &bp->vend[4], tag); 1391 1392 if ((tctx->overload & OVERLOAD_FILE) != 0) 1393 bootpc_tag_helper(tctx, 1394 (unsigned char *) bp->file, 1395 sizeof(bp->file), 1396 tag); 1397 if ((tctx->overload & OVERLOAD_SNAME) != 0) 1398 bootpc_tag_helper(tctx, 1399 (unsigned char *) bp->sname, 1400 sizeof(bp->sname), 1401 tag); 1402 1403 if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0) 1404 return NULL; 1405 tctx->buf[tctx->taglen] = '\0'; 1406 return tctx->buf; 1407} 1408 1409static void 1410bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx, 1411 struct bootpc_globalcontext *gctx) 1412{ 1413 char *p, *s; 1414 unsigned int ip; 1415 1416 ifctx->gotgw = 0; 1417 ifctx->gotnetmask = 0; 1418 1419 clear_sinaddr(&ifctx->myaddr); 1420 clear_sinaddr(&ifctx->netmask); 1421 clear_sinaddr(&ifctx->gw); 1422 1423 ifctx->myaddr.sin_addr = ifctx->reply.yiaddr; 1424 1425 ip = ntohl(ifctx->myaddr.sin_addr.s_addr); 1426 1427 printf("%s at ", ifctx->ireq.ifr_name); 1428 print_sin_addr(&ifctx->myaddr); 1429 printf(" server "); 1430 print_in_addr(ifctx->reply.siaddr); 1431 1432 ifctx->gw.sin_addr = ifctx->reply.giaddr; 1433 if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) { 1434 printf(" via gateway "); 1435 print_in_addr(ifctx->reply.giaddr); 1436 } 1437 1438 /* This call used for the side effect (overload flag) */ 1439 (void) bootpc_tag(&gctx->tmptag, 1440 &ifctx->reply, ifctx->replylen, TAG_END); 1441 1442 if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0) 1443 if (ifctx->reply.sname[0] != '\0') 1444 printf(" server name %s", ifctx->reply.sname); 1445 if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0) 1446 if (ifctx->reply.file[0] != '\0') 1447 printf(" boot file %s", ifctx->reply.file); 1448 1449 printf("\n"); 1450 1451 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1452 TAG_SUBNETMASK); 1453 if (p != NULL) { 1454 if (gctx->tag.taglen != 4) 1455 panic("bootpc: subnet mask len is %d", 1456 gctx->tag.taglen); 1457 bcopy(p, &ifctx->netmask.sin_addr, 4); 1458 ifctx->gotnetmask = 1; 1459 printf("subnet mask "); 1460 print_sin_addr(&ifctx->netmask); 1461 printf(" "); 1462 } 1463 1464 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1465 TAG_ROUTERS); 1466 if (p != NULL) { 1467 /* Routers */ 1468 if (gctx->tag.taglen % 4) 1469 panic("bootpc: Router Len is %d", gctx->tag.taglen); 1470 if (gctx->tag.taglen > 0) { 1471 bcopy(p, &ifctx->gw.sin_addr, 4); 1472 printf("router "); 1473 print_sin_addr(&ifctx->gw); 1474 printf(" "); 1475 ifctx->gotgw = 1; 1476 gctx->gotgw = 1; 1477 } 1478 } 1479 1480 /* 1481 * Choose a root filesystem. If a value is forced in the environment 1482 * and it contains "nfs:", use it unconditionally. Otherwise, if the 1483 * kernel is compiled with the ROOTDEVNAME option, then use it if: 1484 * - The server doesn't provide a pathname. 1485 * - The boothowto flags include RB_DFLTROOT (user said to override 1486 * the server value). 1487 */ 1488 p = NULL; 1489 if ((s = getenv("vfs.root.mountfrom")) != NULL) { 1490 if ((p = strstr(s, "nfs:")) != NULL) 1491 p = strdup(p + 4, M_TEMP); 1492 freeenv(s); 1493 } 1494 if (p == NULL) { 1495 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1496 TAG_ROOT); 1497 if (p != NULL) 1498 ifctx->gotrootpath = 1; 1499 } 1500#ifdef ROOTDEVNAME 1501 if ((p == NULL || (boothowto & RB_DFLTROOT) != 0) && 1502 (p = strstr(ROOTDEVNAME, "nfs:")) != NULL) { 1503 p += 4; 1504 } 1505#endif 1506 if (p != NULL) { 1507 if (gctx->setrootfs != NULL) { 1508 printf("rootfs %s (ignored) ", p); 1509 } else if (setfs(&nd->root_saddr, 1510 nd->root_hostnam, p, &ifctx->reply.siaddr)) { 1511 if (*p == '/') { 1512 printf("root_server "); 1513 print_sin_addr(&nd->root_saddr); 1514 printf(" "); 1515 } 1516 printf("rootfs %s ", p); 1517 gctx->gotrootpath = 1; 1518 gctx->setrootfs = ifctx; 1519 1520 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1521 ifctx->replylen, 1522 TAG_ROOTOPTS); 1523 if (p != NULL) { 1524 mountopts(&nd->root_args, p); 1525 printf("rootopts %s ", p); 1526 } 1527 } else 1528 panic("Failed to set rootfs to %s", p); 1529 } 1530 1531 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1532 TAG_HOSTNAME); 1533 if (p != NULL) { 1534 if (gctx->tag.taglen >= MAXHOSTNAMELEN) 1535 panic("bootpc: hostname >= %d bytes", 1536 MAXHOSTNAMELEN); 1537 if (gctx->sethostname != NULL) { 1538 printf("hostname %s (ignored) ", p); 1539 } else { 1540 strcpy(nd->my_hostnam, p); 1541 mtx_lock(&prison0.pr_mtx); 1542 strcpy(prison0.pr_hostname, p); 1543 mtx_unlock(&prison0.pr_mtx); 1544 printf("hostname %s ", p); 1545 gctx->sethostname = ifctx; 1546 } 1547 } 1548 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1549 TAG_COOKIE); 1550 if (p != NULL) { /* store in a sysctl variable */ 1551 int i, l = sizeof(bootp_cookie) - 1; 1552 for (i = 0; i < l && p[i] != '\0'; i++) 1553 bootp_cookie[i] = p[i]; 1554 p[i] = '\0'; 1555 } 1556 1557 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1558 TAG_INTF_MTU); 1559 if (p != NULL) { 1560 ifctx->mtu = be16dec(p); 1561 } 1562 1563 printf("\n"); 1564 1565 if (ifctx->gotnetmask == 0) { 1566 if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1567 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); 1568 else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1569 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); 1570 else 1571 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); 1572 } 1573} 1574 1575void 1576bootpc_init(void) 1577{ 1578 struct bootpc_ifcontext *ifctx; /* Interface BOOTP contexts */ 1579 struct bootpc_globalcontext *gctx; /* Global BOOTP context */ 1580 struct ifnet *ifp; 1581 struct sockaddr_dl *sdl; 1582 struct ifaddr *ifa; 1583 int error; 1584#ifndef BOOTP_WIRED_TO 1585 int ifcnt; 1586#endif 1587 struct nfsv3_diskless *nd; 1588 struct thread *td; 1589 int timeout; 1590 int delay; 1591 1592 timeout = BOOTP_IFACE_WAIT_TIMEOUT * hz; 1593 delay = hz / 10; 1594 1595 nd = &nfsv3_diskless; 1596 td = curthread; 1597 1598 /* 1599 * If already filled in, don't touch it here 1600 */ 1601 if (nfs_diskless_valid != 0) 1602 return; 1603 1604 gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO); 1605 STAILQ_INIT(&gctx->interfaces); 1606 gctx->xid = ~0xFFFF; 1607 gctx->starttime = time_second; 1608 1609 /* 1610 * If ROOTDEVNAME is defined or vfs.root.mountfrom is set then we have 1611 * root-path overrides that can potentially let us boot even if we don't 1612 * get a root path from the server, so we can treat that as a non-error. 1613 */ 1614#ifdef ROOTDEVNAME 1615 gctx->any_root_overrides = 1; 1616#else 1617 gctx->any_root_overrides = testenv("vfs.root.mountfrom"); 1618#endif 1619 1620 /* 1621 * Find a network interface. 1622 */ 1623 CURVNET_SET(TD_TO_VNET(td)); 1624#ifdef BOOTP_WIRED_TO 1625 printf("%s: wired to interface '%s'\n", __func__, 1626 __XSTRING(BOOTP_WIRED_TO)); 1627 allocifctx(gctx); 1628#else 1629 /* 1630 * Preallocate interface context storage, if another interface 1631 * attaches and wins the race, it won't be eligible for bootp. 1632 */ 1633 ifcnt = 0; 1634 IFNET_RLOCK(); 1635 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 1636 if ((ifp->if_flags & 1637 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1638 IFF_BROADCAST) 1639 continue; 1640 switch (ifp->if_alloctype) { 1641 case IFT_ETHER: 1642 case IFT_FDDI: 1643 case IFT_ISO88025: 1644 break; 1645 default: 1646 continue; 1647 } 1648 ifcnt++; 1649 } 1650 IFNET_RUNLOCK(); 1651 if (ifcnt == 0) 1652 panic("%s: no eligible interfaces", __func__); 1653 for (; ifcnt > 0; ifcnt--) 1654 allocifctx(gctx); 1655#endif 1656 1657retry: 1658 ifctx = STAILQ_FIRST(&gctx->interfaces); 1659 IFNET_RLOCK(); 1660 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 1661 if (ifctx == NULL) 1662 break; 1663#ifdef BOOTP_WIRED_TO 1664 if (strcmp(ifp->if_xname, __XSTRING(BOOTP_WIRED_TO)) != 0) 1665 continue; 1666#else 1667 if ((ifp->if_flags & 1668 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1669 IFF_BROADCAST) 1670 continue; 1671 switch (ifp->if_alloctype) { 1672 case IFT_ETHER: 1673 case IFT_FDDI: 1674 case IFT_ISO88025: 1675 break; 1676 default: 1677 continue; 1678 } 1679#endif 1680 strlcpy(ifctx->ireq.ifr_name, ifp->if_xname, 1681 sizeof(ifctx->ireq.ifr_name)); 1682 ifctx->ifp = ifp; 1683 1684 /* Get HW address */ 1685 sdl = NULL; 1686 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 1687 if (ifa->ifa_addr->sa_family == AF_LINK) { 1688 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 1689 if (sdl->sdl_type == IFT_ETHER) 1690 break; 1691 } 1692 if (sdl == NULL) 1693 panic("bootpc: Unable to find HW address for %s", 1694 ifctx->ireq.ifr_name); 1695 ifctx->sdl = sdl; 1696 1697 ifctx = STAILQ_NEXT(ifctx, next); 1698 } 1699 IFNET_RUNLOCK(); 1700 CURVNET_RESTORE(); 1701 1702 if (STAILQ_EMPTY(&gctx->interfaces) || 1703 STAILQ_FIRST(&gctx->interfaces)->ifp == NULL) { 1704 if (timeout > 0) { 1705 pause("bootpc", delay); 1706 timeout -= delay; 1707 goto retry; 1708 } 1709#ifdef BOOTP_WIRED_TO 1710 panic("%s: Could not find interface specified " 1711 "by BOOTP_WIRED_TO: " 1712 __XSTRING(BOOTP_WIRED_TO), __func__); 1713#else 1714 panic("%s: no suitable interface", __func__); 1715#endif 1716 } 1717 1718 error = socreate(AF_INET, &bootp_so, SOCK_DGRAM, 0, td->td_ucred, td); 1719 if (error != 0) 1720 panic("%s: socreate, error=%d", __func__, error); 1721 1722 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) 1723 bootpc_fakeup_interface(ifctx, td); 1724 1725 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) 1726 bootpc_compose_query(ifctx, td); 1727 1728 error = bootpc_call(gctx, td); 1729 if (error != 0) { 1730 printf("BOOTP call failed\n"); 1731 } 1732 1733 mountopts(&nd->root_args, NULL); 1734 1735 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) 1736 if (bootpc_ifctx_isresolved(ifctx) != 0) 1737 bootpc_decode_reply(nd, ifctx, gctx); 1738 1739#ifdef BOOTP_NFSROOT 1740 if (gctx->gotrootpath == 0 && gctx->any_root_overrides == 0) 1741 panic("bootpc: No root path offered"); 1742#endif 1743 1744 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) 1745 bootpc_adjust_interface(ifctx, gctx, td); 1746 1747 soclose(bootp_so); 1748 1749 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) 1750 if (ifctx->gotrootpath != 0) 1751 break; 1752 if (ifctx == NULL) { 1753 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) 1754 if (bootpc_ifctx_isresolved(ifctx) != 0) 1755 break; 1756 } 1757 if (ifctx == NULL) 1758 goto out; 1759 1760 if (gctx->gotrootpath != 0) { 1761 1762 setenv("boot.netif.name", ifctx->ifp->if_xname); 1763 1764 bootpc_add_default_route(ifctx); 1765 error = md_mount(&nd->root_saddr, nd->root_hostnam, 1766 nd->root_fh, &nd->root_fhsize, 1767 &nd->root_args, td); 1768 bootpc_remove_default_route(ifctx); 1769 if (error != 0) { 1770 if (gctx->any_root_overrides == 0) 1771 panic("nfs_boot: mount root, error=%d", error); 1772 else 1773 goto out; 1774 } 1775 rootdevnames[0] = "nfs:"; 1776#ifdef NFSCLIENT 1777 rootdevnames[1] = "oldnfs:"; 1778#endif 1779 nfs_diskless_valid = 3; 1780 } 1781 1782 strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name); 1783 bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr)); 1784 bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr)); 1785 ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = 1786 ifctx->myaddr.sin_addr.s_addr | 1787 ~ ifctx->netmask.sin_addr.s_addr; 1788 bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask)); 1789 bcopy(&ifctx->gw, &nd->mygateway, sizeof(ifctx->gw)); 1790 1791out: 1792 while((ifctx = STAILQ_FIRST(&gctx->interfaces)) != NULL) { 1793 STAILQ_REMOVE_HEAD(&gctx->interfaces, next); 1794 free(ifctx, M_TEMP); 1795 } 1796 free(gctx, M_TEMP); 1797} 1798 1799/* 1800 * RPC: mountd/mount 1801 * Given a server pathname, get an NFS file handle. 1802 * Also, sets sin->sin_port to the NFS service port. 1803 */ 1804static int 1805md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, 1806 struct nfs_args *args, struct thread *td) 1807{ 1808 struct mbuf *m; 1809 int error; 1810 int authunixok; 1811 int authcount; 1812 int authver; 1813 1814#define RPCPROG_MNT 100005 1815#define RPCMNT_VER1 1 1816#define RPCMNT_VER3 3 1817#define RPCMNT_MOUNT 1 1818#define AUTH_SYS 1 /* unix style (uid, gids) */ 1819#define AUTH_UNIX AUTH_SYS 1820 1821 /* XXX honor v2/v3 flags in args->flags? */ 1822#ifdef BOOTP_NFSV3 1823 /* First try NFS v3 */ 1824 /* Get port number for MOUNTD. */ 1825 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1826 &mdsin->sin_port, td); 1827 if (error == 0) { 1828 m = xdr_string_encode(path, strlen(path)); 1829 1830 /* Do RPC to mountd. */ 1831 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1832 RPCMNT_MOUNT, &m, NULL, td); 1833 } 1834 if (error == 0) { 1835 args->flags |= NFSMNT_NFSV3; 1836 } else { 1837#endif 1838 /* Fallback to NFS v2 */ 1839 1840 /* Get port number for MOUNTD. */ 1841 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1842 &mdsin->sin_port, td); 1843 if (error != 0) 1844 return error; 1845 1846 m = xdr_string_encode(path, strlen(path)); 1847 1848 /* Do RPC to mountd. */ 1849 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1850 RPCMNT_MOUNT, &m, NULL, td); 1851 if (error != 0) 1852 return error; /* message already freed */ 1853 1854#ifdef BOOTP_NFSV3 1855 } 1856#endif 1857 1858 if (xdr_int_decode(&m, &error) != 0 || error != 0) 1859 goto bad; 1860 1861 if ((args->flags & NFSMNT_NFSV3) != 0) { 1862 if (xdr_int_decode(&m, fhsizep) != 0 || 1863 *fhsizep > NFSX_V3FHMAX || 1864 *fhsizep <= 0) 1865 goto bad; 1866 } else 1867 *fhsizep = NFSX_V2FH; 1868 1869 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 1870 goto bad; 1871 1872 if (args->flags & NFSMNT_NFSV3) { 1873 if (xdr_int_decode(&m, &authcount) != 0) 1874 goto bad; 1875 authunixok = 0; 1876 if (authcount < 0 || authcount > 100) 1877 goto bad; 1878 while (authcount > 0) { 1879 if (xdr_int_decode(&m, &authver) != 0) 1880 goto bad; 1881 if (authver == AUTH_UNIX) 1882 authunixok = 1; 1883 authcount--; 1884 } 1885 if (authunixok == 0) 1886 goto bad; 1887 } 1888 1889 /* Set port number for NFS use. */ 1890 error = krpc_portmap(mdsin, NFS_PROG, 1891 (args->flags & 1892 NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2, 1893 &mdsin->sin_port, td); 1894 1895 goto out; 1896 1897bad: 1898 error = EBADRPC; 1899 1900out: 1901 m_freem(m); 1902 return error; 1903} 1904 1905SYSINIT(bootp_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, bootpc_init, NULL); 1906