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