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