1 /* $FreeBSD$ */ 2 3 /* 4 * Copyright (c) 1995 Gordon Ross, Adam Glass 5 * Copyright (c) 1992 Regents of the University of California. 6 * All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Lawrence Berkeley Laboratory and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * based on: 41 * nfs/krpc_subr.c 42 * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ 43 */ 44 45 #include "opt_bootp.h" 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/kernel.h> 50 #include <sys/sockio.h> 51 #include <sys/proc.h> 52 #include <sys/mount.h> 53 #include <sys/mbuf.h> 54 #include <sys/socket.h> 55 #include <sys/socketvar.h> 56 #include <sys/uio.h> 57 58 #include <net/if.h> 59 #include <net/route.h> 60 61 #include <netinet/in.h> 62 #include <net/if_types.h> 63 #include <net/if_dl.h> 64 65 #include <nfs/rpcv2.h> 66 #include <nfs/nfsproto.h> 67 #include <nfs/nfs.h> 68 #include <nfs/nfsdiskless.h> 69 #include <nfs/krpc.h> 70 #include <nfs/xdr_subs.h> 71 72 73 #define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */ 74 75 /* 76 * What is the longest we will wait before re-sending a request? 77 * Note this is also the frequency of "RPC timeout" messages. 78 * The re-send loop count sup linearly to this maximum, so the 79 * first complaint will happen after (1+2+3+4+5)=15 seconds. 80 */ 81 #define MAX_RESEND_DELAY 5 /* seconds */ 82 83 /* Definitions from RFC951 */ 84 struct bootp_packet { 85 u_int8_t op; 86 u_int8_t htype; 87 u_int8_t hlen; 88 u_int8_t hops; 89 u_int32_t xid; 90 u_int16_t secs; 91 u_int16_t flags; 92 struct in_addr ciaddr; 93 struct in_addr yiaddr; 94 struct in_addr siaddr; 95 struct in_addr giaddr; 96 unsigned char chaddr[16]; 97 char sname[64]; 98 char file[128]; 99 unsigned char vend[256]; 100 }; 101 102 #define IPPORT_BOOTPC 68 103 #define IPPORT_BOOTPS 67 104 105 extern int nfs_diskless_valid; 106 extern struct nfsv3_diskless nfsv3_diskless; 107 108 /* mountd RPC */ 109 static int md_mount __P((struct sockaddr_in *mdsin, char *path, 110 u_char *fhp, int *fhsizep, struct nfs_args *args,struct proc *procp)); 111 static int md_lookup_swap __P((struct sockaddr_in *mdsin,char *path, 112 u_char *fhp, int *fhsizep, 113 struct nfs_args *args, 114 struct proc *procp)); 115 static int setfs __P((struct sockaddr_in *addr, char *path, char *p)); 116 static int getdec __P((char **ptr)); 117 static char *substr __P((char *a,char *b)); 118 static void mountopts __P((struct nfs_args *args, char *p)); 119 static int xdr_opaque_decode __P((struct mbuf **ptr,u_char *buf, 120 int len)); 121 static int xdr_int_decode __P((struct mbuf **ptr,int *iptr)); 122 static void printip __P((char *prefix,struct in_addr addr)); 123 124 #ifdef BOOTP_DEBUG 125 void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma); 126 void bootpboot_p_ma(struct sockaddr *ma); 127 void bootpboot_p_rtentry(struct rtentry *rt); 128 void bootpboot_p_tree(struct radix_node *rn); 129 void bootpboot_p_rtlist(void); 130 void bootpboot_p_iflist(void); 131 #endif 132 133 static int bootpc_call(struct bootp_packet *call, 134 struct bootp_packet *reply, 135 struct proc *procp); 136 137 static int bootpc_fakeup_interface(struct ifreq *ireq, 138 struct socket *so, 139 struct proc *procp); 140 141 static int 142 bootpc_adjust_interface(struct ifreq *ireq,struct socket *so, 143 struct sockaddr_in *myaddr, 144 struct sockaddr_in *netmask, 145 struct sockaddr_in *gw, 146 struct proc *procp); 147 148 void bootpc_init(void); 149 150 #ifdef BOOTP_DEBUG 151 void bootpboot_p_sa(sa,ma) 152 struct sockaddr *sa; 153 struct sockaddr *ma; 154 { 155 if (!sa) { 156 printf("(sockaddr *) <null>"); 157 return; 158 } 159 switch (sa->sa_family) { 160 case AF_INET: 161 { 162 struct sockaddr_in *sin = (struct sockaddr_in *) sa; 163 printf("inet %x",ntohl(sin->sin_addr.s_addr)); 164 if (ma) { 165 struct sockaddr_in *sin = (struct sockaddr_in *) ma; 166 printf(" mask %x",ntohl(sin->sin_addr.s_addr)); 167 } 168 } 169 break; 170 case AF_LINK: 171 { 172 struct sockaddr_dl *sli = (struct sockaddr_dl *) sa; 173 int i; 174 printf("link %.*s ",sli->sdl_nlen,sli->sdl_data); 175 for (i=0;i<sli->sdl_alen;i++) { 176 if (i>0) 177 printf(":"); 178 printf("%x",(unsigned char) sli->sdl_data[i+sli->sdl_nlen]); 179 } 180 } 181 break; 182 default: 183 printf("af%d",sa->sa_family); 184 } 185 } 186 187 void bootpboot_p_ma(ma) 188 struct sockaddr *ma; 189 { 190 if (!ma) { 191 printf("<null>"); 192 return; 193 } 194 printf("%x",*(int*)ma); 195 } 196 197 void bootpboot_p_rtentry(rt) 198 struct rtentry *rt; 199 { 200 bootpboot_p_sa(rt_key(rt),rt_mask(rt)); 201 printf(" "); 202 bootpboot_p_ma(rt->rt_genmask); 203 printf(" "); 204 bootpboot_p_sa(rt->rt_gateway,NULL); 205 printf(" "); 206 printf("flags %x",(unsigned short) rt->rt_flags); 207 printf(" %d",rt->rt_rmx.rmx_expire); 208 printf(" %s%d\n",rt->rt_ifp->if_name,rt->rt_ifp->if_unit); 209 } 210 void bootpboot_p_tree(rn) 211 struct radix_node *rn; 212 { 213 while (rn) { 214 if (rn->rn_b < 0) { 215 if (rn->rn_flags & RNF_ROOT) { 216 } else { 217 bootpboot_p_rtentry((struct rtentry *) rn); 218 } 219 rn = rn->rn_dupedkey; 220 } else { 221 bootpboot_p_tree(rn->rn_l); 222 bootpboot_p_tree(rn->rn_r); 223 return; 224 } 225 226 } 227 } 228 229 void bootpboot_p_rtlist(void) 230 { 231 printf("Routing table:\n"); 232 bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop); 233 } 234 235 void bootpboot_p_iflist(void) 236 { 237 struct ifnet *ifp; 238 struct ifaddr *ifa; 239 printf("Interface list:\n"); 240 for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link)) 241 { 242 for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa; 243 ifa=TAILQ_NEXT(ifa,ifa_link)) 244 if (ifa->ifa_addr->sa_family == AF_INET ) { 245 printf("%s%d flags %x, addr %x, bcast %x, net %x\n", 246 ifp->if_name,ifp->if_unit, 247 (unsigned short) ifp->if_flags, 248 ntohl(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr), 249 ntohl(((struct sockaddr_in *) ifa->ifa_dstaddr)->sin_addr.s_addr), 250 ntohl(((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr) 251 ); 252 } 253 } 254 } 255 #endif 256 257 static int 258 bootpc_call(call,reply,procp) 259 struct bootp_packet *call; 260 struct bootp_packet *reply; /* output */ 261 struct proc *procp; 262 { 263 struct socket *so; 264 struct sockaddr_in *sin, sa; 265 struct uio auio; 266 struct sockopt sopt; 267 struct iovec aio; 268 struct timeval tv; 269 int error, on, len, rcvflg, secs, timo; 270 271 /* 272 * Create socket and set its recieve timeout. 273 */ 274 if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp))) 275 goto out; 276 277 tv.tv_sec = 1; 278 tv.tv_usec = 0; 279 bzero(&sopt, sizeof sopt); 280 sopt.sopt_level = SOL_SOCKET; 281 sopt.sopt_name = SO_RCVTIMEO; 282 sopt.sopt_val = &tv; 283 sopt.sopt_valsize = sizeof tv; 284 285 if ((error = sosetopt(so, &sopt)) != 0) 286 goto out; 287 288 /* 289 * Enable broadcast. 290 */ 291 on = 1; 292 sopt.sopt_val = &on; 293 sopt.sopt_valsize = sizeof on; 294 sopt.sopt_name = SO_BROADCAST; 295 if ((error = sosetopt(so, &sopt)) != 0) 296 goto out; 297 298 /* 299 * Bind the local endpoint to a bootp client port. 300 */ 301 sin = &sa; 302 bzero(sin, sizeof *sin); 303 sin->sin_len = sizeof(*sin); 304 sin->sin_family = AF_INET; 305 sin->sin_addr.s_addr = INADDR_ANY; 306 sin->sin_port = htons(IPPORT_BOOTPC); 307 error = sobind(so, (struct sockaddr *)sin, procp); 308 if (error) { 309 printf("bind failed\n"); 310 goto out; 311 } 312 313 /* 314 * Setup socket address for the server. 315 */ 316 sin = &sa; 317 bzero(sin, sizeof *sin); 318 sin->sin_len = sizeof(*sin); 319 sin->sin_family = AF_INET; 320 sin->sin_addr.s_addr = INADDR_BROADCAST; 321 sin->sin_port = htons(IPPORT_BOOTPS); 322 323 /* 324 * Send it, repeatedly, until a reply is received, 325 * but delay each re-send by an increasing amount. 326 * If the delay hits the maximum, start complaining. 327 */ 328 timo = 0; 329 for (;;) { 330 /* Send BOOTP request (or re-send). */ 331 332 aio.iov_base = (caddr_t) call; 333 aio.iov_len = sizeof(*call); 334 335 auio.uio_iov = &aio; 336 auio.uio_iovcnt = 1; 337 auio.uio_segflg = UIO_SYSSPACE; 338 auio.uio_rw = UIO_WRITE; 339 auio.uio_offset = 0; 340 auio.uio_resid = sizeof(*call); 341 auio.uio_procp = procp; 342 343 error = sosend(so, (struct sockaddr *)sin, &auio, NULL, 344 NULL, 0, procp); 345 if (error) { 346 printf("bootpc_call: sosend: %d state %08x\n", error, (int)so->so_state); 347 goto out; 348 } 349 350 /* Determine new timeout. */ 351 if (timo < MAX_RESEND_DELAY) 352 timo++; 353 else 354 printf("BOOTP timeout for server 0x%lx\n", 355 (u_long)ntohl(sin->sin_addr.s_addr)); 356 357 /* 358 * Wait for up to timo seconds for a reply. 359 * The socket receive timeout was set to 1 second. 360 */ 361 secs = timo; 362 while (secs > 0) { 363 aio.iov_base = (caddr_t) reply; 364 aio.iov_len = sizeof(*reply); 365 366 auio.uio_iov = &aio; 367 auio.uio_iovcnt = 1; 368 auio.uio_segflg = UIO_SYSSPACE; 369 auio.uio_rw = UIO_READ; 370 auio.uio_offset = 0; 371 auio.uio_resid = sizeof(*reply); 372 auio.uio_procp = procp; 373 374 rcvflg = 0; 375 error = soreceive(so, NULL, &auio, NULL, NULL, &rcvflg); 376 if (error == EWOULDBLOCK) { 377 secs--; 378 call->secs=htons(ntohs(call->secs)+1); 379 continue; 380 } 381 if (error) 382 goto out; 383 len = sizeof(*reply) - auio.uio_resid; 384 385 /* Do we have the required number of bytes ? */ 386 if (len < BOOTP_MIN_LEN) 387 continue; 388 389 /* Is it the right reply? */ 390 if (reply->op != 2) 391 continue; 392 393 if (reply->xid != call->xid) 394 continue; 395 396 if (reply->hlen != call->hlen) 397 continue; 398 399 if (bcmp(reply->chaddr,call->chaddr,call->hlen)) 400 continue; 401 402 goto gotreply; /* break two levels */ 403 404 } /* while secs */ 405 } /* forever send/receive */ 406 407 error = ETIMEDOUT; 408 goto out; 409 410 gotreply: 411 out: 412 soclose(so); 413 return error; 414 } 415 416 static int 417 bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so, 418 struct proc *procp) 419 { 420 struct sockaddr_in *sin; 421 int error; 422 struct sockaddr_in dst; 423 struct sockaddr_in gw; 424 struct sockaddr_in mask; 425 426 /* 427 * Bring up the interface. 428 * 429 * Get the old interface flags and or IFF_UP into them; if 430 * IFF_UP set blindly, interface selection can be clobbered. 431 */ 432 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp); 433 if (error) 434 panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); 435 ireq->ifr_flags |= IFF_UP; 436 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp); 437 if (error) 438 panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); 439 440 /* 441 * Do enough of ifconfig(8) so that the chosen interface 442 * can talk to the servers. (just set the address) 443 */ 444 445 /* addr is 0.0.0.0 */ 446 447 sin = (struct sockaddr_in *)&ireq->ifr_addr; 448 bzero((caddr_t)sin, sizeof(*sin)); 449 sin->sin_len = sizeof(*sin); 450 sin->sin_family = AF_INET; 451 sin->sin_addr.s_addr = INADDR_ANY; 452 error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); 453 if (error) 454 panic("bootpc_fakeup_interface: set if addr, error=%d", error); 455 456 /* netmask is 0.0.0.0 */ 457 458 sin = (struct sockaddr_in *)&ireq->ifr_addr; 459 bzero((caddr_t)sin, sizeof(*sin)); 460 sin->sin_len = sizeof(*sin); 461 sin->sin_family = AF_INET; 462 sin->sin_addr.s_addr = INADDR_ANY; 463 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); 464 if (error) 465 panic("bootpc_fakeup_interface: set if net addr, error=%d", error); 466 467 /* Broadcast is 255.255.255.255 */ 468 469 sin = (struct sockaddr_in *)&ireq->ifr_addr; 470 bzero((caddr_t)sin, sizeof(*sin)); 471 sin->sin_len = sizeof(*sin); 472 sin->sin_family = AF_INET; 473 sin->sin_addr.s_addr = INADDR_BROADCAST; 474 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); 475 if (error) 476 panic("bootpc_fakeup_interface: set if broadcast addr, error=%d", error); 477 478 /* Add default route to 0.0.0.0 so we can send data */ 479 480 bzero((caddr_t) &dst, sizeof(dst)); 481 dst.sin_len=sizeof(dst); 482 dst.sin_family=AF_INET; 483 dst.sin_addr.s_addr = htonl(0); 484 485 bzero((caddr_t) &gw, sizeof(gw)); 486 gw.sin_len=sizeof(gw); 487 gw.sin_family=AF_INET; 488 gw.sin_addr.s_addr = htonl(0x0); 489 490 bzero((caddr_t) &mask, sizeof(mask)); 491 mask.sin_len=sizeof(mask); 492 mask.sin_family=AF_INET; 493 mask.sin_addr.s_addr = htonl(0); 494 495 error = rtrequest(RTM_ADD, 496 (struct sockaddr *) &dst, 497 (struct sockaddr *) &gw, 498 (struct sockaddr *) &mask, 499 RTF_UP | RTF_STATIC 500 , NULL); 501 if (error) 502 printf("bootpc_fakeup_interface: add default route, error=%d\n", error); 503 return error; 504 } 505 506 static int 507 bootpc_adjust_interface(struct ifreq *ireq,struct socket *so, 508 struct sockaddr_in *myaddr, 509 struct sockaddr_in *netmask, 510 struct sockaddr_in *gw, 511 struct proc *procp) 512 { 513 int error; 514 struct sockaddr_in oldgw; 515 struct sockaddr_in olddst; 516 struct sockaddr_in oldmask; 517 struct sockaddr_in *sin; 518 519 /* Remove old default route to 0.0.0.0 */ 520 521 bzero((caddr_t) &olddst, sizeof(olddst)); 522 olddst.sin_len=sizeof(olddst); 523 olddst.sin_family=AF_INET; 524 olddst.sin_addr.s_addr = INADDR_ANY; 525 526 bzero((caddr_t) &oldgw, sizeof(oldgw)); 527 oldgw.sin_len=sizeof(oldgw); 528 oldgw.sin_family=AF_INET; 529 oldgw.sin_addr.s_addr = INADDR_ANY; 530 531 bzero((caddr_t) &oldmask, sizeof(oldmask)); 532 oldmask.sin_len=sizeof(oldmask); 533 oldmask.sin_family=AF_INET; 534 oldmask.sin_addr.s_addr = INADDR_ANY; 535 536 error = rtrequest(RTM_DELETE, 537 (struct sockaddr *) &olddst, 538 (struct sockaddr *) &oldgw, 539 (struct sockaddr *) &oldmask, 540 (RTF_UP | RTF_STATIC), NULL); 541 if (error) { 542 printf("nfs_boot: del default route, error=%d\n", error); 543 return error; 544 } 545 546 /* 547 * Do enough of ifconfig(8) so that the chosen interface 548 * can talk to the servers. (just set the address) 549 */ 550 bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask)); 551 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); 552 if (error) 553 panic("nfs_boot: set if netmask, error=%d", error); 554 555 /* Broadcast is with host part of IP address all 1's */ 556 557 sin = (struct sockaddr_in *)&ireq->ifr_addr; 558 bzero((caddr_t)sin, sizeof(*sin)); 559 sin->sin_len = sizeof(*sin); 560 sin->sin_family = AF_INET; 561 sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr; 562 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); 563 if (error) 564 panic("bootpc_call: set if broadcast addr, error=%d", error); 565 566 bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr)); 567 error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); 568 if (error) 569 panic("nfs_boot: set if addr, error=%d", error); 570 571 /* Add new default route */ 572 573 error = rtrequest(RTM_ADD, 574 (struct sockaddr *) &olddst, 575 (struct sockaddr *) gw, 576 (struct sockaddr *) &oldmask, 577 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); 578 if (error) { 579 printf("nfs_boot: add net route, error=%d\n", error); 580 return error; 581 } 582 583 return 0; 584 } 585 586 static int setfs(addr, path, p) 587 struct sockaddr_in *addr; 588 char *path; 589 char *p; 590 { 591 unsigned ip = 0; 592 int val; 593 594 if (((val = getdec(&p)) < 0) || (val > 255)) return(0); 595 ip = val << 24; 596 if (*p != '.') return(0); 597 p++; 598 if (((val = getdec(&p)) < 0) || (val > 255)) return(0); 599 ip |= (val << 16); 600 if (*p != '.') return(0); 601 p++; 602 if (((val = getdec(&p)) < 0) || (val > 255)) return(0); 603 ip |= (val << 8); 604 if (*p != '.') return(0); 605 p++; 606 if (((val = getdec(&p)) < 0) || (val > 255)) return(0); 607 ip |= val; 608 if (*p != ':') return(0); 609 p++; 610 611 addr->sin_addr.s_addr = htonl(ip); 612 addr->sin_len = sizeof(struct sockaddr_in); 613 addr->sin_family = AF_INET; 614 615 strncpy(path,p,MNAMELEN-1); 616 return(1); 617 } 618 619 static int getdec(ptr) 620 char **ptr; 621 { 622 char *p = *ptr; 623 int ret=0; 624 if ((*p < '0') || (*p > '9')) return(-1); 625 while ((*p >= '0') && (*p <= '9')) { 626 ret = ret*10 + (*p - '0'); 627 p++; 628 } 629 *ptr = p; 630 return(ret); 631 } 632 633 static char *substr(a,b) 634 char *a,*b; 635 { 636 char *loc1; 637 char *loc2; 638 639 while (*a != '\0') { 640 loc1 = a; 641 loc2 = b; 642 while (*loc1 == *loc2++) { 643 if (*loc1 == '\0') return (0); 644 loc1++; 645 if (*loc2 == '\0') return (loc1); 646 } 647 a++; 648 } 649 return (0); 650 } 651 652 static void mountopts(args,p) 653 struct nfs_args *args; 654 char *p; 655 { 656 char *tmp; 657 658 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT; 659 args->sotype = SOCK_DGRAM; 660 if ((tmp = (char *)substr(p,"rsize="))) 661 args->rsize=getdec(&tmp); 662 if ((tmp = (char *)substr(p,"wsize="))) 663 args->wsize=getdec(&tmp); 664 if ((tmp = (char *)substr(p,"intr"))) 665 args->flags |= NFSMNT_INT; 666 if ((tmp = (char *)substr(p,"soft"))) 667 args->flags |= NFSMNT_SOFT; 668 if ((tmp = (char *)substr(p,"noconn"))) 669 args->flags |= NFSMNT_NOCONN; 670 if ((tmp = (char *)substr(p, "tcp"))) 671 args->sotype = SOCK_STREAM; 672 } 673 674 static int xdr_opaque_decode(mptr,buf,len) 675 struct mbuf **mptr; 676 u_char *buf; 677 int len; 678 { 679 struct mbuf *m; 680 int alignedlen; 681 682 m = *mptr; 683 alignedlen = ( len + 3 ) & ~3; 684 685 if (m->m_len < alignedlen) { 686 m = m_pullup(m,alignedlen); 687 if (m == NULL) { 688 *mptr = NULL; 689 return EBADRPC; 690 } 691 } 692 bcopy(mtod(m,u_char *),buf,len); 693 m_adj(m,alignedlen); 694 *mptr = m; 695 return 0; 696 } 697 698 static int xdr_int_decode(mptr,iptr) 699 struct mbuf **mptr; 700 int *iptr; 701 { 702 u_int32_t i; 703 if (xdr_opaque_decode(mptr,(u_char *) &i,sizeof(u_int32_t))) 704 return EBADRPC; 705 *iptr = fxdr_unsigned(u_int32_t,i); 706 return 0; 707 } 708 709 static void printip(char *prefix,struct in_addr addr) 710 { 711 unsigned int ip; 712 713 ip = ntohl(addr.s_addr); 714 715 printf("%s is %d.%d.%d.%d\n",prefix, 716 ip >> 24, (ip >> 16) & 255 ,(ip >> 8) & 255 ,ip & 255 ); 717 } 718 719 void 720 bootpc_init(void) 721 { 722 struct bootp_packet call; 723 struct bootp_packet reply; 724 static u_int32_t xid = ~0xFF; 725 726 struct ifreq ireq; 727 struct ifnet *ifp; 728 struct socket *so; 729 int error; 730 int code,ncode,len; 731 int j; 732 char *p; 733 unsigned int ip; 734 735 struct sockaddr_in myaddr; 736 struct sockaddr_in netmask; 737 struct sockaddr_in gw; 738 int gotgw=0; 739 int gotnetmask=0; 740 int gotrootpath=0; 741 int gotswappath=0; 742 char lookup_path[24]; 743 744 #define EALEN 6 745 struct ifaddr *ifa; 746 struct sockaddr_dl *sdl = NULL; 747 char *delim; 748 749 struct nfsv3_diskless *nd = &nfsv3_diskless; 750 struct proc *procp = curproc; 751 752 /* 753 * If already filled in, don't touch it here 754 */ 755 if (nfs_diskless_valid) 756 return; 757 758 /* 759 * Wait until arp entries can be handled. 760 */ 761 while (time_second == 0) 762 tsleep(&time_second, PZERO+8, "arpkludge", 10); 763 764 /* 765 * Find a network interface. 766 */ 767 #ifdef BOOTP_WIRED_TO 768 printf("bootpc_init: wired to interface '%s'\n", 769 __XSTRING(BOOTP_WIRED_TO)); 770 #endif 771 bzero(&ireq, sizeof(ireq)); 772 for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link)) 773 { 774 snprintf(ireq.ifr_name, sizeof(ireq.ifr_name), 775 "%s%d", ifp->if_name, ifp->if_unit); 776 #ifdef BOOTP_WIRED_TO 777 if (strcmp(ireq.ifr_name, __XSTRING(BOOTP_WIRED_TO)) == 0) 778 break; 779 #else 780 if ((ifp->if_flags & 781 (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0) 782 break; 783 #endif 784 } 785 if (ifp == NULL) 786 panic("bootpc_init: no suitable interface"); 787 strcpy(nd->myif.ifra_name,ireq.ifr_name); 788 printf("bootpc_init: using network interface '%s'\n", 789 ireq.ifr_name); 790 791 if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0) 792 panic("nfs_boot: socreate, error=%d", error); 793 794 bootpc_fakeup_interface(&ireq,so,procp); 795 796 printf("Bootpc testing starting\n"); 797 798 /* Get HW address */ 799 800 for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa; 801 ifa=TAILQ_NEXT(ifa,ifa_link)) 802 if (ifa->ifa_addr->sa_family == AF_LINK && 803 (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) && 804 sdl->sdl_type == IFT_ETHER) 805 break; 806 807 if (!sdl) 808 panic("bootpc: Unable to find HW address"); 809 if (sdl->sdl_alen != EALEN ) 810 panic("bootpc: HW address len is %d, expected value is %d", 811 sdl->sdl_alen,EALEN); 812 813 printf("bootpc hw address is "); 814 delim=""; 815 for (j=0;j<sdl->sdl_alen;j++) { 816 printf("%s%x",delim,((unsigned char *)LLADDR(sdl))[j]); 817 delim=":"; 818 } 819 printf("\n"); 820 821 #if 0 822 bootpboot_p_iflist(); 823 bootpboot_p_rtlist(); 824 #endif 825 826 bzero((caddr_t) &call, sizeof(call)); 827 828 /* bootpc part */ 829 call.op = 1; /* BOOTREQUEST */ 830 call.htype= 1; /* 10mb ethernet */ 831 call.hlen=sdl->sdl_alen; /* Hardware address length */ 832 call.hops=0; 833 xid++; 834 call.xid = txdr_unsigned(xid); 835 bcopy(LLADDR(sdl),&call.chaddr,sdl->sdl_alen); 836 837 j = 0; 838 call.vend[j++]=99; 839 call.vend[j++]=130; 840 call.vend[j++]=83; 841 call.vend[j++]=99; 842 843 /* 844 * We send an RFC 1533 "Maximum DHCP Message Size" option, saying we 845 * can do 1200 bytes. If we don't ISC DHCPD will limit the answer to 846 * 64 bytes and root/swap and similar will be dropped. 847 */ 848 call.vend[j++]=57; 849 call.vend[j++]=2; 850 call.vend[j++]=(1200) % 256; 851 call.vend[j++]=(1200) / 256; 852 853 call.vend[j++]=255; 854 855 call.secs = 0; 856 call.flags = htons(0x8000); /* We need an broadcast answer */ 857 858 error = bootpc_call(&call,&reply,procp); 859 860 if (error) { 861 #ifdef BOOTP_NFSROOT 862 panic("BOOTP call failed"); 863 #endif 864 return; 865 } 866 867 bzero(&myaddr,sizeof(myaddr)); 868 bzero(&netmask,sizeof(netmask)); 869 bzero(&gw,sizeof(gw)); 870 871 myaddr.sin_len = sizeof(myaddr); 872 myaddr.sin_family = AF_INET; 873 874 netmask.sin_len = sizeof(netmask); 875 netmask.sin_family = AF_INET; 876 877 gw.sin_len = sizeof(gw); 878 gw.sin_family= AF_INET; 879 880 nd->root_args.version = NFS_ARGSVERSION; 881 nd->root_args.rsize = 8192; 882 nd->root_args.wsize = 8192; 883 nd->root_args.sotype = SOCK_DGRAM; 884 nd->root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT); 885 886 nd->swap_saddr.sin_len = sizeof(gw); 887 nd->swap_saddr.sin_family = AF_INET; 888 889 nd->swap_args.version = NFS_ARGSVERSION; 890 nd->swap_args.rsize = 8192; 891 nd->swap_args.wsize = 8192; 892 nd->swap_args.sotype = SOCK_DGRAM; 893 nd->swap_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT); 894 895 myaddr.sin_addr = reply.yiaddr; 896 897 ip = ntohl(myaddr.sin_addr.s_addr); 898 snprintf(lookup_path, sizeof(lookup_path), "swap.%d.%d.%d.%d", 899 ip >> 24, (ip >> 16) & 255 ,(ip >> 8) & 255 ,ip & 255 ); 900 901 printip("My ip address",myaddr.sin_addr); 902 903 printip("Server ip address",reply.siaddr); 904 905 gw.sin_addr = reply.giaddr; 906 printip("Gateway ip address",reply.giaddr); 907 908 if (reply.sname[0]) 909 printf("Server name is %s\n",reply.sname); 910 if (reply.file[0]) 911 printf("boot file is %s\n",reply.file); 912 if (reply.vend[0]==99 && reply.vend[1]==130 && 913 reply.vend[2]==83 && reply.vend[3]==99) { 914 j=4; 915 ncode = reply.vend[j]; 916 while (j<sizeof(reply.vend)) { 917 code = reply.vend[j] = ncode; 918 if (code==255) 919 break; 920 if (code==0) { 921 j++; 922 continue; 923 } 924 len = reply.vend[j+1]; 925 j+=2; 926 if (len+j>=sizeof(reply.vend)) { 927 printf("Truncated field"); 928 break; 929 } 930 ncode = reply.vend[j+len]; 931 reply.vend[j+len]='\0'; 932 p = &reply.vend[j]; 933 switch (code) { 934 case 1: 935 if (len!=4) 936 panic("bootpc: subnet mask len is %d",len); 937 bcopy(&reply.vend[j],&netmask.sin_addr,4); 938 gotnetmask=1; 939 printip("Subnet mask",netmask.sin_addr); 940 break; 941 case 6: /* Domain Name servers. Unused */ 942 case 16: /* Swap server IP address. unused */ 943 case 2: 944 /* Time offset */ 945 break; 946 case 3: 947 /* Routers */ 948 if (len % 4) 949 panic("bootpc: Router Len is %d",len); 950 if (len > 0) { 951 bcopy(&reply.vend[j],&gw.sin_addr,4); 952 printip("Router",gw.sin_addr); 953 gotgw=1; 954 } 955 break; 956 case 17: 957 if (setfs(&nd->root_saddr, nd->root_hostnam, p)) { 958 printf("rootfs is %s\n",p); 959 gotrootpath=1; 960 } else 961 panic("Failed to set rootfs to %s",p); 962 break; 963 case 12: 964 if (len>=MAXHOSTNAMELEN) 965 panic("bootpc: hostname >=%d bytes",MAXHOSTNAMELEN); 966 strncpy(nd->my_hostnam,&reply.vend[j],len); 967 nd->my_hostnam[len]=0; 968 strncpy(hostname,&reply.vend[j],len); 969 hostname[len]=0; 970 printf("Hostname is %s\n",hostname); 971 break; 972 case 128: 973 if (setfs(&nd->swap_saddr, nd->swap_hostnam, p)) { 974 gotswappath=1; 975 printf("swapfs is %s\n",p); 976 } else 977 panic("Failed to set swapfs to %s",p); 978 break; 979 case 129: 980 { 981 int swaplen; 982 if (len!=4) 983 panic("bootpc: Expected 4 bytes for swaplen, not %d bytes",len); 984 bcopy(&reply.vend[j],&swaplen,4); 985 nd->swap_nblks = ntohl(swaplen); 986 printf("bootpc: Swap size is %d KB\n",nd->swap_nblks); 987 } 988 break; 989 case 130: /* root mount options */ 990 mountopts(&nd->root_args,p); 991 break; 992 case 131: /* swap mount options */ 993 mountopts(&nd->swap_args,p); 994 break; 995 default: 996 printf("Ignoring field type %d\n",code); 997 } 998 j+=len; 999 } 1000 } 1001 1002 if (!gotswappath) 1003 nd->swap_nblks = 0; 1004 #ifdef BOOTP_NFSROOT 1005 if (!gotrootpath) 1006 panic("bootpc: No root path offered"); 1007 #endif 1008 1009 if (!gotnetmask) { 1010 if (IN_CLASSA(ntohl(myaddr.sin_addr.s_addr))) 1011 netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); 1012 else if (IN_CLASSB(ntohl(myaddr.sin_addr.s_addr))) 1013 netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); 1014 else 1015 netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); 1016 } 1017 if (!gotgw) { 1018 /* Use proxyarp */ 1019 gw.sin_addr.s_addr = myaddr.sin_addr.s_addr; 1020 } 1021 1022 #if 0 1023 bootpboot_p_iflist(); 1024 bootpboot_p_rtlist(); 1025 #endif 1026 error = bootpc_adjust_interface(&ireq,so, 1027 &myaddr,&netmask,&gw,procp); 1028 1029 soclose(so); 1030 1031 #if 0 1032 bootpboot_p_iflist(); 1033 bootpboot_p_rtlist(); 1034 #endif 1035 1036 if (gotrootpath) { 1037 1038 error = md_mount(&nd->root_saddr, nd->root_hostnam, 1039 nd->root_fh, &nd->root_fhsize, 1040 &nd->root_args,procp); 1041 if (error) 1042 panic("nfs_boot: mountd root, error=%d", error); 1043 1044 if (gotswappath) { 1045 1046 error = md_mount(&nd->swap_saddr, 1047 nd->swap_hostnam, 1048 nd->swap_fh, &nd->swap_fhsize,&nd->swap_args,procp); 1049 if (error) 1050 panic("nfs_boot: mountd swap, error=%d", error); 1051 1052 error = md_lookup_swap(&nd->swap_saddr,lookup_path,nd->swap_fh, 1053 &nd->swap_fhsize, &nd->swap_args,procp); 1054 if (error) 1055 panic("nfs_boot: lookup swap, error=%d", error); 1056 } 1057 nfs_diskless_valid = 3; 1058 } 1059 1060 1061 bcopy(&myaddr,&nd->myif.ifra_addr,sizeof(myaddr)); 1062 bcopy(&myaddr,&nd->myif.ifra_broadaddr,sizeof(myaddr)); 1063 ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = 1064 myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr; 1065 bcopy(&netmask,&nd->myif.ifra_mask,sizeof(netmask)); 1066 1067 #if 0 1068 bootpboot_p_iflist(); 1069 bootpboot_p_rtlist(); 1070 #endif 1071 return; 1072 } 1073 1074 /* 1075 * RPC: mountd/mount 1076 * Given a server pathname, get an NFS file handle. 1077 * Also, sets sin->sin_port to the NFS service port. 1078 */ 1079 static int 1080 md_mount(mdsin, path, fhp, fhsizep, args, procp) 1081 struct sockaddr_in *mdsin; /* mountd server address */ 1082 char *path; 1083 u_char *fhp; 1084 int *fhsizep; 1085 struct nfs_args *args; 1086 struct proc *procp; 1087 { 1088 struct mbuf *m; 1089 int error; 1090 int authunixok; 1091 int authcount; 1092 int authver; 1093 1094 #ifdef BOOTP_NFSV3 1095 /* First try NFS v3 */ 1096 /* Get port number for MOUNTD. */ 1097 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1098 &mdsin->sin_port, procp); 1099 if (!error) { 1100 m = xdr_string_encode(path, strlen(path)); 1101 1102 /* Do RPC to mountd. */ 1103 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1104 RPCMNT_MOUNT, &m, NULL, curproc); 1105 } 1106 if (!error) { 1107 args->flags |= NFSMNT_NFSV3; 1108 } else { 1109 #endif 1110 /* Fallback to NFS v2 */ 1111 1112 /* Get port number for MOUNTD. */ 1113 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1114 &mdsin->sin_port, procp); 1115 if (error) return error; 1116 1117 m = xdr_string_encode(path, strlen(path)); 1118 1119 /* Do RPC to mountd. */ 1120 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1121 RPCMNT_MOUNT, &m, NULL, curproc); 1122 if (error) 1123 return error; /* message already freed */ 1124 1125 #ifdef BOOTP_NFSV3 1126 } 1127 #endif 1128 1129 if (xdr_int_decode(&m,&error) || error) 1130 goto bad; 1131 1132 if (args->flags & NFSMNT_NFSV3) { 1133 if (xdr_int_decode(&m,fhsizep) || 1134 *fhsizep > NFSX_V3FHMAX || *fhsizep <= 0 ) 1135 goto bad; 1136 } else 1137 *fhsizep = NFSX_V2FH; 1138 1139 if (xdr_opaque_decode(&m,fhp,*fhsizep)) 1140 goto bad; 1141 1142 if (args->flags & NFSMNT_NFSV3) { 1143 if (xdr_int_decode(&m,&authcount)) 1144 goto bad; 1145 authunixok = 0; 1146 if (authcount<0 || authcount>100) 1147 goto bad; 1148 while (authcount>0) { 1149 if (xdr_int_decode(&m,&authver)) 1150 goto bad; 1151 if (authver == RPCAUTH_UNIX) 1152 authunixok = 1; 1153 authcount--; 1154 } 1155 if (!authunixok) 1156 goto bad; 1157 } 1158 1159 /* Set port number for NFS use. */ 1160 error = krpc_portmap(mdsin, NFS_PROG, 1161 (args->flags & NFSMNT_NFSV3)?NFS_VER3:NFS_VER2, 1162 &mdsin->sin_port, procp); 1163 1164 goto out; 1165 1166 bad: 1167 error = EBADRPC; 1168 1169 out: 1170 m_freem(m); 1171 return error; 1172 } 1173 1174 1175 static int md_lookup_swap(mdsin, path, fhp, fhsizep, args, procp) 1176 struct sockaddr_in *mdsin; /* mountd server address */ 1177 char *path; 1178 u_char *fhp; 1179 int *fhsizep; 1180 struct nfs_args *args; 1181 struct proc *procp; 1182 { 1183 struct mbuf *m; 1184 int error; 1185 int size = -1; 1186 int attribs_present; 1187 int status; 1188 union { 1189 u_int32_t v2[17]; 1190 u_int32_t v3[21]; 1191 } fattribs; 1192 1193 m = m_get(M_WAIT,MT_DATA); 1194 if (!m) 1195 return ENOBUFS; 1196 1197 if (args->flags & NFSMNT_NFSV3) { 1198 *mtod(m,u_int32_t *) = txdr_unsigned(*fhsizep); 1199 bcopy(fhp,mtod(m,u_char *)+sizeof(u_int32_t),*fhsizep); 1200 m->m_len = *fhsizep + sizeof(u_int32_t); 1201 } else { 1202 bcopy(fhp,mtod(m,u_char *),NFSX_V2FH); 1203 m->m_len = NFSX_V2FH; 1204 } 1205 1206 m->m_next = xdr_string_encode(path, strlen(path)); 1207 if (!m->m_next) { 1208 error = ENOBUFS; 1209 goto out; 1210 } 1211 1212 /* Do RPC to nfsd. */ 1213 if (args->flags & NFSMNT_NFSV3) 1214 error = krpc_call(mdsin, NFS_PROG, NFS_VER3, 1215 NFSPROC_LOOKUP, &m, NULL, procp); 1216 else 1217 error = krpc_call(mdsin, NFS_PROG, NFS_VER2, 1218 NFSV2PROC_LOOKUP, &m, NULL, procp); 1219 if (error) 1220 return error; /* message already freed */ 1221 1222 if (xdr_int_decode(&m,&status)) 1223 goto bad; 1224 if (status) { 1225 error = ENOENT; 1226 goto out; 1227 } 1228 1229 if (args->flags & NFSMNT_NFSV3) { 1230 if (xdr_int_decode(&m,fhsizep) || 1231 *fhsizep > NFSX_V3FHMAX || *fhsizep <= 0 ) 1232 goto bad; 1233 } else 1234 *fhsizep = NFSX_V2FH; 1235 1236 if (xdr_opaque_decode(&m, fhp, *fhsizep)) 1237 goto bad; 1238 1239 if (args->flags & NFSMNT_NFSV3) { 1240 if (xdr_int_decode(&m,&attribs_present)) 1241 goto bad; 1242 if (attribs_present) { 1243 if (xdr_opaque_decode(&m,(u_char *) &fattribs.v3, 1244 sizeof(u_int32_t)*21)) 1245 goto bad; 1246 size = fxdr_unsigned(u_int32_t, fattribs.v3[6]); 1247 } 1248 } else { 1249 if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2, 1250 sizeof(u_int32_t)*17)) 1251 goto bad; 1252 size = fxdr_unsigned(u_int32_t, fattribs.v2[5]); 1253 } 1254 1255 if (!nfsv3_diskless.swap_nblks && size!= -1) { 1256 nfsv3_diskless.swap_nblks = size/1024; 1257 printf("md_lookup_swap: Swap size is %d KB\n", 1258 nfsv3_diskless.swap_nblks); 1259 } 1260 1261 goto out; 1262 1263 bad: 1264 error = EBADRPC; 1265 1266 out: 1267 m_freem(m); 1268 return error; 1269 } 1270