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