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