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