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/malloc.h> 53#include <sys/mount.h> 54#include <sys/mbuf.h> 55#include <sys/socket.h> 56#include <sys/socketvar.h> 57#include <sys/uio.h> 58 59#include <net/if.h> 60#include <net/route.h> 61 62#include <netinet/in.h> 63#include <net/if_types.h> 64#include <net/if_dl.h> 65 66#include <nfs/rpcv2.h> 67#include <nfs/nfsproto.h> 68#include <nfsclient/nfs.h> 69#include <nfsclient/nfsdiskless.h> 70#include <nfsclient/krpc.h> 71#include <nfs/xdr_subs.h> 72 73 74#define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */ 75 76#ifndef BOOTP_SETTLE_DELAY 77#define BOOTP_SETTLE_DELAY 3 78#endif 79 80/* 81 * What is the longest we will wait before re-sending a request? 82 * Note this is also the frequency of "RPC timeout" messages. 83 * The re-send loop count sup linearly to this maximum, so the 84 * first complaint will happen after (1+2+3+4+5)=15 seconds. 85 */ 86#define MAX_RESEND_DELAY 5 /* seconds */ 87 88/* Definitions from RFC951 */ 89struct bootp_packet { 90 u_int8_t op; 91 u_int8_t htype; 92 u_int8_t hlen; 93 u_int8_t hops; 94 u_int32_t xid; 95 u_int16_t secs; 96 u_int16_t flags; 97 struct in_addr ciaddr; 98 struct in_addr yiaddr; 99 struct in_addr siaddr; 100 struct in_addr giaddr; 101 unsigned char chaddr[16]; 102 char sname[64]; 103 char file[128]; 104 unsigned char vend[1222]; 105}; 106 107struct bootpc_ifcontext { 108 struct bootpc_ifcontext *next; 109 struct bootp_packet call; 110 struct bootp_packet reply; 111 int replylen; 112 int overload; 113 struct socket *so; 114 struct ifreq ireq; 115 struct ifnet *ifp; 116 struct sockaddr_dl *sdl; 117 struct sockaddr_in myaddr; 118 struct sockaddr_in netmask; 119 struct sockaddr_in gw; 120 struct sockaddr_in broadcast; /* Different for each interface */ 121 int gotgw; 122 int gotnetmask; 123 int gotrootpath; 124 int outstanding; 125 int sentmsg; 126 u_int32_t xid; 127 enum { 128 IF_BOOTP_UNRESOLVED, 129 IF_BOOTP_RESOLVED, 130 IF_BOOTP_FAILED, 131 IF_DHCP_UNRESOLVED, 132 IF_DHCP_OFFERED, 133 IF_DHCP_RESOLVED, 134 IF_DHCP_FAILED, 135 } state; 136 int dhcpquerytype; /* dhcp type sent */ 137 struct in_addr dhcpserver; 138 int gotdhcpserver; 139}; 140 141#define TAG_MAXLEN 1024 142struct bootpc_tagcontext { 143 char buf[TAG_MAXLEN + 1]; 144 int overload; 145 int badopt; 146 int badtag; 147 int foundopt; 148 int taglen; 149}; 150 151struct bootpc_globalcontext { 152 struct bootpc_ifcontext *interfaces; 153 struct bootpc_ifcontext *lastinterface; 154 u_int32_t xid; 155 int gotrootpath; 156 int gotswappath; 157 int gotgw; 158 int ifnum; 159 int secs; 160 int starttime; 161 struct bootp_packet reply; 162 int replylen; 163 struct bootpc_ifcontext *setswapfs; 164 struct bootpc_ifcontext *setrootfs; 165 struct bootpc_ifcontext *sethostname; 166 char lookup_path[24]; 167 struct bootpc_tagcontext tmptag; 168 struct bootpc_tagcontext tag; 169}; 170 171#define IPPORT_BOOTPC 68 172#define IPPORT_BOOTPS 67 173 174#define BOOTP_REQUEST 1 175#define BOOTP_REPLY 2 176 177/* Common tags */ 178#define TAG_PAD 0 /* Pad option, implicit length 1 */ 179#define TAG_SUBNETMASK 1 /* RFC 950 subnet mask */ 180#define TAG_ROUTERS 3 /* Routers (in order of preference) */ 181#define TAG_HOSTNAME 12 /* Client host name */ 182#define TAG_ROOT 17 /* Root path */ 183 184/* DHCP specific tags */ 185#define TAG_OVERLOAD 52 /* Option Overload */ 186#define TAG_MAXMSGSIZE 57 /* Maximum DHCP Message Size */ 187 188#define TAG_END 255 /* End Option (i.e. no more options) */ 189 190/* Overload values */ 191#define OVERLOAD_FILE 1 192#define OVERLOAD_SNAME 2 193 194/* Site specific tags: */ 195#define TAG_SWAP 128 196#define TAG_SWAPSIZE 129 197#define TAG_ROOTOPTS 130 198#define TAG_SWAPOPTS 131 199 200#define TAG_DHCP_MSGTYPE 53 201#define TAG_DHCP_REQ_ADDR 50 202#define TAG_DHCP_SERVERID 54 203#define TAG_DHCP_LEASETIME 51 204 205#define DHCP_NOMSG 0 206#define DHCP_DISCOVER 1 207#define DHCP_OFFER 2 208#define DHCP_REQUEST 3 209#define DHCP_ACK 5 210 211/* mountd RPC */ 212static int md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, 213 int *fhsizep, struct nfs_args *args, struct thread *td); 214static int md_lookup_swap(struct sockaddr_in *mdsin, char *path, 215 u_char *fhp, int *fhsizep, struct nfs_args *args, 216 struct thread *td); 217static int setfs(struct sockaddr_in *addr, char *path, char *p); 218static int getdec(char **ptr); 219static char *substr(char *a, char *b); 220static void mountopts(struct nfs_args *args, char *p); 221static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len); 222static int xdr_int_decode(struct mbuf **ptr, int *iptr); 223static void print_in_addr(struct in_addr addr); 224static void print_sin_addr(struct sockaddr_in *addr); 225static void clear_sinaddr(struct sockaddr_in *sin); 226static struct bootpc_ifcontext *allocifctx(struct bootpc_globalcontext *gctx); 227static void bootpc_compose_query(struct bootpc_ifcontext *ifctx, 228 struct bootpc_globalcontext *gctx, struct thread *td); 229static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx, 230 struct bootp_packet *bp, int len, int tag); 231static void bootpc_tag_helper(struct bootpc_tagcontext *tctx, 232 unsigned char *start, int len, int tag); 233 234#ifdef BOOTP_DEBUG 235void bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma); 236void bootpboot_p_ma(struct sockaddr *ma); 237void bootpboot_p_rtentry(struct rtentry *rt); 238void bootpboot_p_tree(struct radix_node *rn); 239void bootpboot_p_rtlist(void); 240void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa); 241void bootpboot_p_iflist(void); 242#endif 243 244static int bootpc_call(struct bootpc_globalcontext *gctx, 245 struct thread *td); 246 247static int bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, 248 struct bootpc_globalcontext *gctx, struct thread *td); 249 250static int bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, 251 struct bootpc_globalcontext *gctx, struct thread *td); 252 253static void bootpc_decode_reply(struct nfsv3_diskless *nd, 254 struct bootpc_ifcontext *ifctx, 255 struct bootpc_globalcontext *gctx); 256 257static int bootpc_received(struct bootpc_globalcontext *gctx, 258 struct bootpc_ifcontext *ifctx); 259 260static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx); 261static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx); 262static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx); 263 264void bootpc_init(void); 265 266/* 267 * In order to have multiple active interfaces with address 0.0.0.0 268 * and be able to send data to a selected interface, we perform 269 * some tricks: 270 * 271 * - The 'broadcast' address is different for each interface. 272 * 273 * - We temporarily add routing pointing 255.255.255.255 to the 274 * selected interface broadcast address, thus the packet sent 275 * goes to that interface. 276 */ 277 278#ifdef BOOTP_DEBUG 279void 280bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma) 281{ 282 283 if (sa == NULL) { 284 printf("(sockaddr *) <null>"); 285 return; 286 } 287 switch (sa->sa_family) { 288 case AF_INET: 289 { 290 struct sockaddr_in *sin; 291 292 sin = (struct sockaddr_in *) sa; 293 printf("inet "); 294 print_sin_addr(sin); 295 if (ma != NULL) { 296 sin = (struct sockaddr_in *) ma; 297 printf(" mask "); 298 print_sin_addr(sin); 299 } 300 } 301 break; 302 case AF_LINK: 303 { 304 struct sockaddr_dl *sli; 305 int i; 306 307 sli = (struct sockaddr_dl *) sa; 308 printf("link %.*s ", sli->sdl_nlen, sli->sdl_data); 309 for (i = 0; i < sli->sdl_alen; i++) { 310 if (i > 0) 311 printf(":"); 312 printf("%x", ((unsigned char *) LLADDR(sli))[i]); 313 } 314 } 315 break; 316 default: 317 printf("af%d", sa->sa_family); 318 } 319} 320 321void 322bootpboot_p_ma(struct sockaddr *ma) 323{ 324 325 if (ma == NULL) { 326 printf("<null>"); 327 return; 328 } 329 printf("%x", *(int *)ma); 330} 331 332void 333bootpboot_p_rtentry(struct rtentry *rt) 334{ 335 336 bootpboot_p_sa(rt_key(rt), rt_mask(rt)); 337 printf(" "); 338 bootpboot_p_ma(rt->rt_genmask); 339 printf(" "); 340 bootpboot_p_sa(rt->rt_gateway, NULL); 341 printf(" "); 342 printf("flags %x", (unsigned short) rt->rt_flags); 343 printf(" %d", (int) rt->rt_rmx.rmx_expire); 344 printf(" %s%d\n", rt->rt_ifp->if_name, rt->rt_ifp->if_unit); 345} 346 347void 348bootpboot_p_tree(struct radix_node *rn) 349{ 350 351 while (rn != NULL) { 352 if (rn->rn_bit < 0) { 353 if ((rn->rn_flags & RNF_ROOT) != 0) { 354 } else { 355 bootpboot_p_rtentry((struct rtentry *) rn); 356 } 357 rn = rn->rn_dupedkey; 358 } else { 359 bootpboot_p_tree(rn->rn_left); 360 bootpboot_p_tree(rn->rn_right); 361 return; 362 } 363 } 364} 365 366void 367bootpboot_p_rtlist(void) 368{ 369 370 printf("Routing table:\n"); 371 bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop); 372} 373 374void 375bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa) 376{ 377 378 printf("%s%d flags %x, addr ", 379 ifp->if_name, 380 ifp->if_unit, 381 (unsigned short) ifp->if_flags); 382 print_sin_addr((struct sockaddr_in *) ifa->ifa_addr); 383 printf(", broadcast "); 384 print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr); 385 printf(", netmask "); 386 print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask); 387 printf("\n"); 388} 389 390void 391bootpboot_p_iflist(void) 392{ 393 struct ifnet *ifp; 394 struct ifaddr *ifa; 395 396 printf("Interface list:\n"); 397 for (ifp = TAILQ_FIRST(&ifnet); 398 ifp != NULL; 399 ifp = TAILQ_NEXT(ifp, if_link)) { 400 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); 401 ifa != NULL; 402 ifa = TAILQ_NEXT(ifa, ifa_link)) 403 if (ifa->ifa_addr->sa_family == AF_INET) 404 bootpboot_p_if(ifp, ifa); 405 } 406} 407#endif /* defined(BOOTP_DEBUG) */ 408 409static void 410clear_sinaddr(struct sockaddr_in *sin) 411{ 412 413 bzero(sin, sizeof(*sin)); 414 sin->sin_len = sizeof(*sin); 415 sin->sin_family = AF_INET; 416 sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */ 417 sin->sin_port = 0; 418} 419 420static struct bootpc_ifcontext * 421allocifctx(struct bootpc_globalcontext *gctx) 422{ 423 struct bootpc_ifcontext *ifctx; 424 ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx), 425 M_TEMP, M_WAITOK); 426 if (ifctx == NULL) 427 panic("Failed to allocate bootp interface context structure"); 428 429 bzero(ifctx, sizeof(*ifctx)); 430 ifctx->xid = gctx->xid; 431#ifdef BOOTP_NO_DHCP 432 ifctx->state = IF_BOOTP_UNRESOLVED; 433#else 434 ifctx->state = IF_DHCP_UNRESOLVED; 435#endif 436 gctx->xid += 0x100; 437 return ifctx; 438} 439 440static __inline int 441bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx) 442{ 443 444 if (ifctx->state == IF_BOOTP_RESOLVED || 445 ifctx->state == IF_DHCP_RESOLVED) 446 return 1; 447 return 0; 448} 449 450static __inline int 451bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx) 452{ 453 454 if (ifctx->state == IF_BOOTP_UNRESOLVED || 455 ifctx->state == IF_DHCP_UNRESOLVED) 456 return 1; 457 return 0; 458} 459 460static __inline int 461bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx) 462{ 463 464 if (ifctx->state == IF_BOOTP_FAILED || 465 ifctx->state == IF_DHCP_FAILED) 466 return 1; 467 return 0; 468} 469 470static int 471bootpc_received(struct bootpc_globalcontext *gctx, 472 struct bootpc_ifcontext *ifctx) 473{ 474 unsigned char dhcpreplytype; 475 char *p; 476 477 /* 478 * Need timeout for fallback to less 479 * desirable alternative. 480 */ 481 482 /* This call used for the side effect (badopt flag) */ 483 (void) bootpc_tag(&gctx->tmptag, &gctx->reply, 484 gctx->replylen, 485 TAG_END); 486 487 /* If packet is invalid, ignore it */ 488 if (gctx->tmptag.badopt != 0) 489 return 0; 490 491 p = bootpc_tag(&gctx->tmptag, &gctx->reply, 492 gctx->replylen, TAG_DHCP_MSGTYPE); 493 if (p != NULL) 494 dhcpreplytype = *p; 495 else 496 dhcpreplytype = DHCP_NOMSG; 497 498 switch (ifctx->dhcpquerytype) { 499 case DHCP_DISCOVER: 500 if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */ 501#ifndef BOOTP_FORCE_DHCP 502 && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */ 503#endif 504 ) 505 return 0; 506 break; 507 case DHCP_REQUEST: 508 if (dhcpreplytype != DHCP_ACK) 509 return 0; 510 case DHCP_NOMSG: 511 } 512 513 /* Ignore packet unless it gives us a root tag we didn't have */ 514 515 if ((ifctx->state == IF_BOOTP_RESOLVED || 516 (ifctx->dhcpquerytype == DHCP_DISCOVER && 517 (ifctx->state == IF_DHCP_OFFERED || 518 ifctx->state == IF_DHCP_RESOLVED))) && 519 (bootpc_tag(&gctx->tmptag, &ifctx->reply, 520 ifctx->replylen, 521 TAG_ROOT) != NULL || 522 bootpc_tag(&gctx->tmptag, &gctx->reply, 523 gctx->replylen, 524 TAG_ROOT) == NULL)) 525 return 0; 526 527 bcopy(&gctx->reply, &ifctx->reply, gctx->replylen); 528 ifctx->replylen = gctx->replylen; 529 530 /* XXX: Only reset if 'perfect' response */ 531 if (ifctx->state == IF_BOOTP_UNRESOLVED) 532 ifctx->state = IF_BOOTP_RESOLVED; 533 else if (ifctx->state == IF_DHCP_UNRESOLVED && 534 ifctx->dhcpquerytype == DHCP_DISCOVER) { 535 if (dhcpreplytype == DHCP_OFFER) 536 ifctx->state = IF_DHCP_OFFERED; 537 else 538 ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */ 539 } else if (ifctx->state == IF_DHCP_OFFERED && 540 ifctx->dhcpquerytype == DHCP_REQUEST) 541 ifctx->state = IF_DHCP_RESOLVED; 542 543 544 if (ifctx->dhcpquerytype == DHCP_DISCOVER && 545 ifctx->state != IF_BOOTP_RESOLVED) { 546 p = bootpc_tag(&gctx->tmptag, &ifctx->reply, 547 ifctx->replylen, TAG_DHCP_SERVERID); 548 if (p != NULL && gctx->tmptag.taglen == 4) { 549 memcpy(&ifctx->dhcpserver, p, 4); 550 ifctx->gotdhcpserver = 1; 551 } else 552 ifctx->gotdhcpserver = 0; 553 return 1; 554 } 555 556 ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 557 ifctx->replylen, 558 TAG_ROOT) != NULL); 559 ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 560 ifctx->replylen, 561 TAG_ROUTERS) != NULL); 562 ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 563 ifctx->replylen, 564 TAG_SUBNETMASK) != NULL); 565 return 1; 566} 567 568static int 569bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td) 570{ 571 struct socket *so; 572 struct sockaddr_in *sin, dst; 573 struct uio auio; 574 struct sockopt sopt; 575 struct iovec aio; 576 int error, on, rcvflg, timo, len; 577 time_t atimo; 578 time_t rtimo; 579 struct timeval tv; 580 struct bootpc_ifcontext *ifctx; 581 int outstanding; 582 int gotrootpath; 583 int retry; 584 const char *s; 585 586 /* 587 * Create socket and set its recieve timeout. 588 */
| 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/malloc.h> 53#include <sys/mount.h> 54#include <sys/mbuf.h> 55#include <sys/socket.h> 56#include <sys/socketvar.h> 57#include <sys/uio.h> 58 59#include <net/if.h> 60#include <net/route.h> 61 62#include <netinet/in.h> 63#include <net/if_types.h> 64#include <net/if_dl.h> 65 66#include <nfs/rpcv2.h> 67#include <nfs/nfsproto.h> 68#include <nfsclient/nfs.h> 69#include <nfsclient/nfsdiskless.h> 70#include <nfsclient/krpc.h> 71#include <nfs/xdr_subs.h> 72 73 74#define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */ 75 76#ifndef BOOTP_SETTLE_DELAY 77#define BOOTP_SETTLE_DELAY 3 78#endif 79 80/* 81 * What is the longest we will wait before re-sending a request? 82 * Note this is also the frequency of "RPC timeout" messages. 83 * The re-send loop count sup linearly to this maximum, so the 84 * first complaint will happen after (1+2+3+4+5)=15 seconds. 85 */ 86#define MAX_RESEND_DELAY 5 /* seconds */ 87 88/* Definitions from RFC951 */ 89struct bootp_packet { 90 u_int8_t op; 91 u_int8_t htype; 92 u_int8_t hlen; 93 u_int8_t hops; 94 u_int32_t xid; 95 u_int16_t secs; 96 u_int16_t flags; 97 struct in_addr ciaddr; 98 struct in_addr yiaddr; 99 struct in_addr siaddr; 100 struct in_addr giaddr; 101 unsigned char chaddr[16]; 102 char sname[64]; 103 char file[128]; 104 unsigned char vend[1222]; 105}; 106 107struct bootpc_ifcontext { 108 struct bootpc_ifcontext *next; 109 struct bootp_packet call; 110 struct bootp_packet reply; 111 int replylen; 112 int overload; 113 struct socket *so; 114 struct ifreq ireq; 115 struct ifnet *ifp; 116 struct sockaddr_dl *sdl; 117 struct sockaddr_in myaddr; 118 struct sockaddr_in netmask; 119 struct sockaddr_in gw; 120 struct sockaddr_in broadcast; /* Different for each interface */ 121 int gotgw; 122 int gotnetmask; 123 int gotrootpath; 124 int outstanding; 125 int sentmsg; 126 u_int32_t xid; 127 enum { 128 IF_BOOTP_UNRESOLVED, 129 IF_BOOTP_RESOLVED, 130 IF_BOOTP_FAILED, 131 IF_DHCP_UNRESOLVED, 132 IF_DHCP_OFFERED, 133 IF_DHCP_RESOLVED, 134 IF_DHCP_FAILED, 135 } state; 136 int dhcpquerytype; /* dhcp type sent */ 137 struct in_addr dhcpserver; 138 int gotdhcpserver; 139}; 140 141#define TAG_MAXLEN 1024 142struct bootpc_tagcontext { 143 char buf[TAG_MAXLEN + 1]; 144 int overload; 145 int badopt; 146 int badtag; 147 int foundopt; 148 int taglen; 149}; 150 151struct bootpc_globalcontext { 152 struct bootpc_ifcontext *interfaces; 153 struct bootpc_ifcontext *lastinterface; 154 u_int32_t xid; 155 int gotrootpath; 156 int gotswappath; 157 int gotgw; 158 int ifnum; 159 int secs; 160 int starttime; 161 struct bootp_packet reply; 162 int replylen; 163 struct bootpc_ifcontext *setswapfs; 164 struct bootpc_ifcontext *setrootfs; 165 struct bootpc_ifcontext *sethostname; 166 char lookup_path[24]; 167 struct bootpc_tagcontext tmptag; 168 struct bootpc_tagcontext tag; 169}; 170 171#define IPPORT_BOOTPC 68 172#define IPPORT_BOOTPS 67 173 174#define BOOTP_REQUEST 1 175#define BOOTP_REPLY 2 176 177/* Common tags */ 178#define TAG_PAD 0 /* Pad option, implicit length 1 */ 179#define TAG_SUBNETMASK 1 /* RFC 950 subnet mask */ 180#define TAG_ROUTERS 3 /* Routers (in order of preference) */ 181#define TAG_HOSTNAME 12 /* Client host name */ 182#define TAG_ROOT 17 /* Root path */ 183 184/* DHCP specific tags */ 185#define TAG_OVERLOAD 52 /* Option Overload */ 186#define TAG_MAXMSGSIZE 57 /* Maximum DHCP Message Size */ 187 188#define TAG_END 255 /* End Option (i.e. no more options) */ 189 190/* Overload values */ 191#define OVERLOAD_FILE 1 192#define OVERLOAD_SNAME 2 193 194/* Site specific tags: */ 195#define TAG_SWAP 128 196#define TAG_SWAPSIZE 129 197#define TAG_ROOTOPTS 130 198#define TAG_SWAPOPTS 131 199 200#define TAG_DHCP_MSGTYPE 53 201#define TAG_DHCP_REQ_ADDR 50 202#define TAG_DHCP_SERVERID 54 203#define TAG_DHCP_LEASETIME 51 204 205#define DHCP_NOMSG 0 206#define DHCP_DISCOVER 1 207#define DHCP_OFFER 2 208#define DHCP_REQUEST 3 209#define DHCP_ACK 5 210 211/* mountd RPC */ 212static int md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, 213 int *fhsizep, struct nfs_args *args, struct thread *td); 214static int md_lookup_swap(struct sockaddr_in *mdsin, char *path, 215 u_char *fhp, int *fhsizep, struct nfs_args *args, 216 struct thread *td); 217static int setfs(struct sockaddr_in *addr, char *path, char *p); 218static int getdec(char **ptr); 219static char *substr(char *a, char *b); 220static void mountopts(struct nfs_args *args, char *p); 221static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len); 222static int xdr_int_decode(struct mbuf **ptr, int *iptr); 223static void print_in_addr(struct in_addr addr); 224static void print_sin_addr(struct sockaddr_in *addr); 225static void clear_sinaddr(struct sockaddr_in *sin); 226static struct bootpc_ifcontext *allocifctx(struct bootpc_globalcontext *gctx); 227static void bootpc_compose_query(struct bootpc_ifcontext *ifctx, 228 struct bootpc_globalcontext *gctx, struct thread *td); 229static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx, 230 struct bootp_packet *bp, int len, int tag); 231static void bootpc_tag_helper(struct bootpc_tagcontext *tctx, 232 unsigned char *start, int len, int tag); 233 234#ifdef BOOTP_DEBUG 235void bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma); 236void bootpboot_p_ma(struct sockaddr *ma); 237void bootpboot_p_rtentry(struct rtentry *rt); 238void bootpboot_p_tree(struct radix_node *rn); 239void bootpboot_p_rtlist(void); 240void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa); 241void bootpboot_p_iflist(void); 242#endif 243 244static int bootpc_call(struct bootpc_globalcontext *gctx, 245 struct thread *td); 246 247static int bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, 248 struct bootpc_globalcontext *gctx, struct thread *td); 249 250static int bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, 251 struct bootpc_globalcontext *gctx, struct thread *td); 252 253static void bootpc_decode_reply(struct nfsv3_diskless *nd, 254 struct bootpc_ifcontext *ifctx, 255 struct bootpc_globalcontext *gctx); 256 257static int bootpc_received(struct bootpc_globalcontext *gctx, 258 struct bootpc_ifcontext *ifctx); 259 260static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx); 261static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx); 262static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx); 263 264void bootpc_init(void); 265 266/* 267 * In order to have multiple active interfaces with address 0.0.0.0 268 * and be able to send data to a selected interface, we perform 269 * some tricks: 270 * 271 * - The 'broadcast' address is different for each interface. 272 * 273 * - We temporarily add routing pointing 255.255.255.255 to the 274 * selected interface broadcast address, thus the packet sent 275 * goes to that interface. 276 */ 277 278#ifdef BOOTP_DEBUG 279void 280bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma) 281{ 282 283 if (sa == NULL) { 284 printf("(sockaddr *) <null>"); 285 return; 286 } 287 switch (sa->sa_family) { 288 case AF_INET: 289 { 290 struct sockaddr_in *sin; 291 292 sin = (struct sockaddr_in *) sa; 293 printf("inet "); 294 print_sin_addr(sin); 295 if (ma != NULL) { 296 sin = (struct sockaddr_in *) ma; 297 printf(" mask "); 298 print_sin_addr(sin); 299 } 300 } 301 break; 302 case AF_LINK: 303 { 304 struct sockaddr_dl *sli; 305 int i; 306 307 sli = (struct sockaddr_dl *) sa; 308 printf("link %.*s ", sli->sdl_nlen, sli->sdl_data); 309 for (i = 0; i < sli->sdl_alen; i++) { 310 if (i > 0) 311 printf(":"); 312 printf("%x", ((unsigned char *) LLADDR(sli))[i]); 313 } 314 } 315 break; 316 default: 317 printf("af%d", sa->sa_family); 318 } 319} 320 321void 322bootpboot_p_ma(struct sockaddr *ma) 323{ 324 325 if (ma == NULL) { 326 printf("<null>"); 327 return; 328 } 329 printf("%x", *(int *)ma); 330} 331 332void 333bootpboot_p_rtentry(struct rtentry *rt) 334{ 335 336 bootpboot_p_sa(rt_key(rt), rt_mask(rt)); 337 printf(" "); 338 bootpboot_p_ma(rt->rt_genmask); 339 printf(" "); 340 bootpboot_p_sa(rt->rt_gateway, NULL); 341 printf(" "); 342 printf("flags %x", (unsigned short) rt->rt_flags); 343 printf(" %d", (int) rt->rt_rmx.rmx_expire); 344 printf(" %s%d\n", rt->rt_ifp->if_name, rt->rt_ifp->if_unit); 345} 346 347void 348bootpboot_p_tree(struct radix_node *rn) 349{ 350 351 while (rn != NULL) { 352 if (rn->rn_bit < 0) { 353 if ((rn->rn_flags & RNF_ROOT) != 0) { 354 } else { 355 bootpboot_p_rtentry((struct rtentry *) rn); 356 } 357 rn = rn->rn_dupedkey; 358 } else { 359 bootpboot_p_tree(rn->rn_left); 360 bootpboot_p_tree(rn->rn_right); 361 return; 362 } 363 } 364} 365 366void 367bootpboot_p_rtlist(void) 368{ 369 370 printf("Routing table:\n"); 371 bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop); 372} 373 374void 375bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa) 376{ 377 378 printf("%s%d flags %x, addr ", 379 ifp->if_name, 380 ifp->if_unit, 381 (unsigned short) ifp->if_flags); 382 print_sin_addr((struct sockaddr_in *) ifa->ifa_addr); 383 printf(", broadcast "); 384 print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr); 385 printf(", netmask "); 386 print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask); 387 printf("\n"); 388} 389 390void 391bootpboot_p_iflist(void) 392{ 393 struct ifnet *ifp; 394 struct ifaddr *ifa; 395 396 printf("Interface list:\n"); 397 for (ifp = TAILQ_FIRST(&ifnet); 398 ifp != NULL; 399 ifp = TAILQ_NEXT(ifp, if_link)) { 400 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); 401 ifa != NULL; 402 ifa = TAILQ_NEXT(ifa, ifa_link)) 403 if (ifa->ifa_addr->sa_family == AF_INET) 404 bootpboot_p_if(ifp, ifa); 405 } 406} 407#endif /* defined(BOOTP_DEBUG) */ 408 409static void 410clear_sinaddr(struct sockaddr_in *sin) 411{ 412 413 bzero(sin, sizeof(*sin)); 414 sin->sin_len = sizeof(*sin); 415 sin->sin_family = AF_INET; 416 sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */ 417 sin->sin_port = 0; 418} 419 420static struct bootpc_ifcontext * 421allocifctx(struct bootpc_globalcontext *gctx) 422{ 423 struct bootpc_ifcontext *ifctx; 424 ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx), 425 M_TEMP, M_WAITOK); 426 if (ifctx == NULL) 427 panic("Failed to allocate bootp interface context structure"); 428 429 bzero(ifctx, sizeof(*ifctx)); 430 ifctx->xid = gctx->xid; 431#ifdef BOOTP_NO_DHCP 432 ifctx->state = IF_BOOTP_UNRESOLVED; 433#else 434 ifctx->state = IF_DHCP_UNRESOLVED; 435#endif 436 gctx->xid += 0x100; 437 return ifctx; 438} 439 440static __inline int 441bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx) 442{ 443 444 if (ifctx->state == IF_BOOTP_RESOLVED || 445 ifctx->state == IF_DHCP_RESOLVED) 446 return 1; 447 return 0; 448} 449 450static __inline int 451bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx) 452{ 453 454 if (ifctx->state == IF_BOOTP_UNRESOLVED || 455 ifctx->state == IF_DHCP_UNRESOLVED) 456 return 1; 457 return 0; 458} 459 460static __inline int 461bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx) 462{ 463 464 if (ifctx->state == IF_BOOTP_FAILED || 465 ifctx->state == IF_DHCP_FAILED) 466 return 1; 467 return 0; 468} 469 470static int 471bootpc_received(struct bootpc_globalcontext *gctx, 472 struct bootpc_ifcontext *ifctx) 473{ 474 unsigned char dhcpreplytype; 475 char *p; 476 477 /* 478 * Need timeout for fallback to less 479 * desirable alternative. 480 */ 481 482 /* This call used for the side effect (badopt flag) */ 483 (void) bootpc_tag(&gctx->tmptag, &gctx->reply, 484 gctx->replylen, 485 TAG_END); 486 487 /* If packet is invalid, ignore it */ 488 if (gctx->tmptag.badopt != 0) 489 return 0; 490 491 p = bootpc_tag(&gctx->tmptag, &gctx->reply, 492 gctx->replylen, TAG_DHCP_MSGTYPE); 493 if (p != NULL) 494 dhcpreplytype = *p; 495 else 496 dhcpreplytype = DHCP_NOMSG; 497 498 switch (ifctx->dhcpquerytype) { 499 case DHCP_DISCOVER: 500 if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */ 501#ifndef BOOTP_FORCE_DHCP 502 && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */ 503#endif 504 ) 505 return 0; 506 break; 507 case DHCP_REQUEST: 508 if (dhcpreplytype != DHCP_ACK) 509 return 0; 510 case DHCP_NOMSG: 511 } 512 513 /* Ignore packet unless it gives us a root tag we didn't have */ 514 515 if ((ifctx->state == IF_BOOTP_RESOLVED || 516 (ifctx->dhcpquerytype == DHCP_DISCOVER && 517 (ifctx->state == IF_DHCP_OFFERED || 518 ifctx->state == IF_DHCP_RESOLVED))) && 519 (bootpc_tag(&gctx->tmptag, &ifctx->reply, 520 ifctx->replylen, 521 TAG_ROOT) != NULL || 522 bootpc_tag(&gctx->tmptag, &gctx->reply, 523 gctx->replylen, 524 TAG_ROOT) == NULL)) 525 return 0; 526 527 bcopy(&gctx->reply, &ifctx->reply, gctx->replylen); 528 ifctx->replylen = gctx->replylen; 529 530 /* XXX: Only reset if 'perfect' response */ 531 if (ifctx->state == IF_BOOTP_UNRESOLVED) 532 ifctx->state = IF_BOOTP_RESOLVED; 533 else if (ifctx->state == IF_DHCP_UNRESOLVED && 534 ifctx->dhcpquerytype == DHCP_DISCOVER) { 535 if (dhcpreplytype == DHCP_OFFER) 536 ifctx->state = IF_DHCP_OFFERED; 537 else 538 ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */ 539 } else if (ifctx->state == IF_DHCP_OFFERED && 540 ifctx->dhcpquerytype == DHCP_REQUEST) 541 ifctx->state = IF_DHCP_RESOLVED; 542 543 544 if (ifctx->dhcpquerytype == DHCP_DISCOVER && 545 ifctx->state != IF_BOOTP_RESOLVED) { 546 p = bootpc_tag(&gctx->tmptag, &ifctx->reply, 547 ifctx->replylen, TAG_DHCP_SERVERID); 548 if (p != NULL && gctx->tmptag.taglen == 4) { 549 memcpy(&ifctx->dhcpserver, p, 4); 550 ifctx->gotdhcpserver = 1; 551 } else 552 ifctx->gotdhcpserver = 0; 553 return 1; 554 } 555 556 ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 557 ifctx->replylen, 558 TAG_ROOT) != NULL); 559 ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 560 ifctx->replylen, 561 TAG_ROUTERS) != NULL); 562 ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 563 ifctx->replylen, 564 TAG_SUBNETMASK) != NULL); 565 return 1; 566} 567 568static int 569bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td) 570{ 571 struct socket *so; 572 struct sockaddr_in *sin, dst; 573 struct uio auio; 574 struct sockopt sopt; 575 struct iovec aio; 576 int error, on, rcvflg, timo, len; 577 time_t atimo; 578 time_t rtimo; 579 struct timeval tv; 580 struct bootpc_ifcontext *ifctx; 581 int outstanding; 582 int gotrootpath; 583 int retry; 584 const char *s; 585 586 /* 587 * Create socket and set its recieve timeout. 588 */
|
975 if (error != 0) 976 panic("nfs_boot: socreate, error=%d", error); 977 978 ireq = &ifctx->ireq; 979 so = ifctx->so; 980 981 /* 982 * Bring up the interface. 983 * 984 * Get the old interface flags and or IFF_UP into them; if 985 * IFF_UP set blindly, interface selection can be clobbered. 986 */ 987 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 988 if (error != 0) 989 panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); 990 ireq->ifr_flags |= IFF_UP; 991 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 992 if (error != 0) 993 panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); 994 995 /* 996 * Do enough of ifconfig(8) so that the chosen interface 997 * can talk to the servers. (just set the address) 998 */ 999 1000 /* addr is 0.0.0.0 */ 1001 1002 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1003 clear_sinaddr(sin); 1004 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1005 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1006 panic("bootpc_fakeup_interface: " 1007 "set if addr, error=%d", error); 1008 1009 /* netmask is 255.0.0.0 */ 1010 1011 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1012 clear_sinaddr(sin); 1013 sin->sin_addr.s_addr = htonl(0xff000000u); 1014 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td); 1015 if (error != 0) 1016 panic("bootpc_fakeup_interface: set if netmask, error=%d", 1017 error); 1018 1019 /* Broadcast is 255.255.255.255 */ 1020 1021 sin = (struct sockaddr_in *)&ireq->ifr_addr; 1022 clear_sinaddr(sin); 1023 clear_sinaddr(&ifctx->broadcast); 1024 sin->sin_addr.s_addr = htonl(INADDR_BROADCAST); 1025 ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr; 1026 1027 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td); 1028 if (error != 0) 1029 panic("bootpc_fakeup_interface: " 1030 "set if broadcast addr, error=%d", 1031 error); 1032 1033 /* Get HW address */ 1034 1035 sdl = NULL; 1036 for (ifa = TAILQ_FIRST(&ifctx->ifp->if_addrhead); 1037 ifa != NULL; 1038 ifa = TAILQ_NEXT(ifa, ifa_link)) 1039 if (ifa->ifa_addr->sa_family == AF_LINK && 1040 (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) != NULL && 1041 sdl->sdl_type == IFT_ETHER) 1042 break; 1043 1044 if (sdl == NULL) 1045 panic("bootpc: Unable to find HW address for %s", 1046 ifctx->ireq.ifr_name); 1047 ifctx->sdl = sdl; 1048 1049 return error; 1050} 1051 1052 1053static int 1054bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, 1055 struct bootpc_globalcontext *gctx, struct thread *td) 1056{ 1057 int error; 1058 struct sockaddr_in defdst; 1059 struct sockaddr_in defmask; 1060 struct sockaddr_in *sin; 1061 struct ifreq *ireq; 1062 struct socket *so; 1063 struct sockaddr_in *myaddr; 1064 struct sockaddr_in *netmask; 1065 struct sockaddr_in *gw; 1066 1067 ireq = &ifctx->ireq; 1068 so = ifctx->so; 1069 myaddr = &ifctx->myaddr; 1070 netmask = &ifctx->netmask; 1071 gw = &ifctx->gw; 1072 1073 if (bootpc_ifctx_isresolved(ifctx) == 0) { 1074 1075 /* Shutdown interfaces where BOOTP failed */ 1076 1077 printf("Shutdown interface %s\n", ifctx->ireq.ifr_name); 1078 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 1079 if (error != 0) 1080 panic("bootpc_adjust_interface: " 1081 "SIOCGIFFLAGS, error=%d", error); 1082 ireq->ifr_flags &= ~IFF_UP; 1083 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 1084 if (error != 0) 1085 panic("bootpc_adjust_interface: " 1086 "SIOCSIFFLAGS, error=%d", error); 1087 1088 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1089 clear_sinaddr(sin); 1090 error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td); 1091 if (error != 0 && (error != EEXIST || 1092 ifctx == gctx->interfaces)) 1093 panic("bootpc_adjust_interface: " 1094 "SIOCDIFADDR, error=%d", error); 1095 1096 return 0; 1097 } 1098 1099 printf("Adjusted interface %s\n", ifctx->ireq.ifr_name); 1100 /* 1101 * Do enough of ifconfig(8) so that the chosen interface 1102 * can talk to the servers. (just set the address) 1103 */ 1104 bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask)); 1105 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td); 1106 if (error != 0) 1107 panic("bootpc_adjust_interface: " 1108 "set if netmask, error=%d", error); 1109 1110 /* Broadcast is with host part of IP address all 1's */ 1111 1112 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1113 clear_sinaddr(sin); 1114 sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | 1115 ~ netmask->sin_addr.s_addr; 1116 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td); 1117 if (error != 0) 1118 panic("bootpc_adjust_interface: " 1119 "set if broadcast addr, error=%d", error); 1120 1121 bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr)); 1122 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1123 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1124 panic("bootpc_adjust_interface: " 1125 "set if addr, error=%d", error); 1126 1127 /* Add new default route */ 1128 1129 if (ifctx->gotgw != 0 || gctx->gotgw == 0) { 1130 clear_sinaddr(&defdst); 1131 clear_sinaddr(&defmask); 1132 error = rtrequest(RTM_ADD, 1133 (struct sockaddr *) &defdst, 1134 (struct sockaddr *) gw, 1135 (struct sockaddr *) &defmask, 1136 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); 1137 if (error != 0) { 1138 printf("bootpc_adjust_interface: " 1139 "add net route, error=%d\n", error); 1140 return error; 1141 } 1142 } 1143 1144 return 0; 1145} 1146 1147static int 1148setfs(struct sockaddr_in *addr, char *path, char *p) 1149{ 1150 unsigned int ip; 1151 int val; 1152 1153 ip = 0; 1154 if (((val = getdec(&p)) < 0) || (val > 255)) 1155 return 0; 1156 ip = val << 24; 1157 if (*p != '.') 1158 return 0; 1159 p++; 1160 if (((val = getdec(&p)) < 0) || (val > 255)) 1161 return 0; 1162 ip |= (val << 16); 1163 if (*p != '.') 1164 return 0; 1165 p++; 1166 if (((val = getdec(&p)) < 0) || (val > 255)) 1167 return 0; 1168 ip |= (val << 8); 1169 if (*p != '.') 1170 return 0; 1171 p++; 1172 if (((val = getdec(&p)) < 0) || (val > 255)) 1173 return 0; 1174 ip |= val; 1175 if (*p != ':') 1176 return 0; 1177 p++; 1178 1179 addr->sin_addr.s_addr = htonl(ip); 1180 addr->sin_len = sizeof(struct sockaddr_in); 1181 addr->sin_family = AF_INET; 1182 1183 strncpy(path, p, MNAMELEN - 1); 1184 return 1; 1185} 1186 1187static int 1188getdec(char **ptr) 1189{ 1190 char *p; 1191 int ret; 1192 1193 p = *ptr; 1194 ret = 0; 1195 if ((*p < '0') || (*p > '9')) 1196 return -1; 1197 while ((*p >= '0') && (*p <= '9')) { 1198 ret = ret * 10 + (*p - '0'); 1199 p++; 1200 } 1201 *ptr = p; 1202 return ret; 1203} 1204 1205static char * 1206substr(char *a, char *b) 1207{ 1208 char *loc1; 1209 char *loc2; 1210 1211 while (*a != '\0') { 1212 loc1 = a; 1213 loc2 = b; 1214 while (*loc1 == *loc2++) { 1215 if (*loc1 == '\0') 1216 return 0; 1217 loc1++; 1218 if (*loc2 == '\0') 1219 return loc1; 1220 } 1221 a++; 1222 } 1223 return 0; 1224} 1225 1226static void 1227mountopts(struct nfs_args *args, char *p) 1228{ 1229 char *tmp; 1230 1231 args->version = NFS_ARGSVERSION; 1232 args->rsize = 8192; 1233 args->wsize = 8192; 1234 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT; 1235 args->sotype = SOCK_DGRAM; 1236 if (p == NULL) 1237 return; 1238 if ((tmp = (char *)substr(p, "rsize="))) 1239 args->rsize = getdec(&tmp); 1240 if ((tmp = (char *)substr(p, "wsize="))) 1241 args->wsize = getdec(&tmp); 1242 if ((tmp = (char *)substr(p, "intr"))) 1243 args->flags |= NFSMNT_INT; 1244 if ((tmp = (char *)substr(p, "soft"))) 1245 args->flags |= NFSMNT_SOFT; 1246 if ((tmp = (char *)substr(p, "noconn"))) 1247 args->flags |= NFSMNT_NOCONN; 1248 if ((tmp = (char *)substr(p, "tcp"))) 1249 args->sotype = SOCK_STREAM; 1250} 1251 1252static int 1253xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) 1254{ 1255 struct mbuf *m; 1256 int alignedlen; 1257 1258 m = *mptr; 1259 alignedlen = ( len + 3 ) & ~3; 1260 1261 if (m->m_len < alignedlen) { 1262 m = m_pullup(m, alignedlen); 1263 if (m == NULL) { 1264 *mptr = NULL; 1265 return EBADRPC; 1266 } 1267 } 1268 bcopy(mtod(m, u_char *), buf, len); 1269 m_adj(m, alignedlen); 1270 *mptr = m; 1271 return 0; 1272} 1273 1274static int 1275xdr_int_decode(struct mbuf **mptr, int *iptr) 1276{ 1277 u_int32_t i; 1278 1279 if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) 1280 return EBADRPC; 1281 *iptr = fxdr_unsigned(u_int32_t, i); 1282 return 0; 1283} 1284 1285static void 1286print_sin_addr(struct sockaddr_in *sin) 1287{ 1288 1289 print_in_addr(sin->sin_addr); 1290} 1291 1292static void 1293print_in_addr(struct in_addr addr) 1294{ 1295 unsigned int ip; 1296 1297 ip = ntohl(addr.s_addr); 1298 printf("%d.%d.%d.%d", 1299 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); 1300} 1301 1302static void 1303bootpc_compose_query(struct bootpc_ifcontext *ifctx, 1304 struct bootpc_globalcontext *gctx, struct thread *td) 1305{ 1306 unsigned char *vendp; 1307 uint32_t leasetime; 1308 1309 ifctx->gotrootpath = 0; 1310 1311 bzero((caddr_t) &ifctx->call, sizeof(ifctx->call)); 1312 1313 /* bootpc part */ 1314 ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */ 1315 ifctx->call.htype = 1; /* 10mb ethernet */ 1316 ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */ 1317 ifctx->call.hops = 0; 1318 if (bootpc_ifctx_isunresolved(ifctx) != 0) 1319 ifctx->xid++; 1320 ifctx->call.xid = txdr_unsigned(ifctx->xid); 1321 bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen); 1322 1323 vendp = ifctx->call.vend; 1324 *vendp++ = 99; /* RFC1048 cookie */ 1325 *vendp++ = 130; 1326 *vendp++ = 83; 1327 *vendp++ = 99; 1328 *vendp++ = TAG_MAXMSGSIZE; 1329 *vendp++ = 2; 1330 *vendp++ = (sizeof(struct bootp_packet) >> 8) & 255; 1331 *vendp++ = sizeof(struct bootp_packet) & 255; 1332 ifctx->dhcpquerytype = DHCP_NOMSG; 1333 switch (ifctx->state) { 1334 case IF_DHCP_UNRESOLVED: 1335 *vendp++ = TAG_DHCP_MSGTYPE; 1336 *vendp++ = 1; 1337 *vendp++ = DHCP_DISCOVER; 1338 ifctx->dhcpquerytype = DHCP_DISCOVER; 1339 ifctx->gotdhcpserver = 0; 1340 break; 1341 case IF_DHCP_OFFERED: 1342 *vendp++ = TAG_DHCP_MSGTYPE; 1343 *vendp++ = 1; 1344 *vendp++ = DHCP_REQUEST; 1345 ifctx->dhcpquerytype = DHCP_REQUEST; 1346 *vendp++ = TAG_DHCP_REQ_ADDR; 1347 *vendp++ = 4; 1348 memcpy(vendp, &ifctx->reply.yiaddr, 4); 1349 vendp += 4; 1350 if (ifctx->gotdhcpserver != 0) { 1351 *vendp++ = TAG_DHCP_SERVERID; 1352 *vendp++ = 4; 1353 memcpy(vendp, &ifctx->dhcpserver, 4); 1354 vendp += 4; 1355 } 1356 *vendp++ = TAG_DHCP_LEASETIME; 1357 *vendp++ = 4; 1358 leasetime = htonl(300); 1359 memcpy(vendp, &leasetime, 4); 1360 vendp += 4; 1361 default: 1362 ; 1363 } 1364 *vendp = TAG_END; 1365 1366 ifctx->call.secs = 0; 1367 ifctx->call.flags = htons(0x8000); /* We need an broadcast answer */ 1368} 1369 1370static int 1371bootpc_hascookie(struct bootp_packet *bp) 1372{ 1373 1374 return (bp->vend[0] == 99 && bp->vend[1] == 130 && 1375 bp->vend[2] == 83 && bp->vend[3] == 99); 1376} 1377 1378static void 1379bootpc_tag_helper(struct bootpc_tagcontext *tctx, 1380 unsigned char *start, int len, int tag) 1381{ 1382 unsigned char *j; 1383 unsigned char *ej; 1384 unsigned char code; 1385 1386 if (tctx->badtag != 0 || tctx->badopt != 0) 1387 return; 1388 1389 j = start; 1390 ej = j + len; 1391 1392 while (j < ej) { 1393 code = *j++; 1394 if (code == TAG_PAD) 1395 continue; 1396 if (code == TAG_END) 1397 return; 1398 if (j >= ej || j + *j + 1 > ej) { 1399 tctx->badopt = 1; 1400 return; 1401 } 1402 len = *j++; 1403 if (code == tag) { 1404 if (tctx->taglen + len > TAG_MAXLEN) { 1405 tctx->badtag = 1; 1406 return; 1407 } 1408 tctx->foundopt = 1; 1409 if (len > 0) 1410 memcpy(tctx->buf + tctx->taglen, 1411 j, len); 1412 tctx->taglen += len; 1413 } 1414 if (code == TAG_OVERLOAD) 1415 tctx->overload = *j; 1416 1417 j += len; 1418 } 1419} 1420 1421static unsigned char * 1422bootpc_tag(struct bootpc_tagcontext *tctx, 1423 struct bootp_packet *bp, int len, int tag) 1424{ 1425 unsigned char *j; 1426 unsigned char *ej; 1427 1428 tctx->overload = 0; 1429 tctx->badopt = 0; 1430 tctx->badtag = 0; 1431 tctx->foundopt = 0; 1432 tctx->taglen = 0; 1433 1434 if (bootpc_hascookie(bp) == 0) 1435 return NULL; 1436 1437 j = &bp->vend[4]; 1438 ej = (unsigned char *) bp + len; 1439 1440 bootpc_tag_helper(tctx, &bp->vend[4], 1441 (unsigned char *) bp + len - &bp->vend[4], tag); 1442 1443 if ((tctx->overload & OVERLOAD_FILE) != 0) 1444 bootpc_tag_helper(tctx, 1445 (unsigned char *) bp->file, 1446 sizeof(bp->file), 1447 tag); 1448 if ((tctx->overload & OVERLOAD_SNAME) != 0) 1449 bootpc_tag_helper(tctx, 1450 (unsigned char *) bp->sname, 1451 sizeof(bp->sname), 1452 tag); 1453 1454 if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0) 1455 return NULL; 1456 tctx->buf[tctx->taglen] = '\0'; 1457 return tctx->buf; 1458} 1459 1460static void 1461bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx, 1462 struct bootpc_globalcontext *gctx) 1463{ 1464 char *p; 1465 unsigned int ip; 1466 1467 ifctx->gotgw = 0; 1468 ifctx->gotnetmask = 0; 1469 1470 clear_sinaddr(&ifctx->myaddr); 1471 clear_sinaddr(&ifctx->netmask); 1472 clear_sinaddr(&ifctx->gw); 1473 1474 ifctx->myaddr.sin_addr = ifctx->reply.yiaddr; 1475 1476 ip = ntohl(ifctx->myaddr.sin_addr.s_addr); 1477 snprintf(gctx->lookup_path, sizeof(gctx->lookup_path), 1478 "swap.%d.%d.%d.%d", 1479 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); 1480 1481 printf("%s at ", ifctx->ireq.ifr_name); 1482 print_sin_addr(&ifctx->myaddr); 1483 printf(" server "); 1484 print_in_addr(ifctx->reply.siaddr); 1485 1486 ifctx->gw.sin_addr = ifctx->reply.giaddr; 1487 if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) { 1488 printf(" via gateway "); 1489 print_in_addr(ifctx->reply.giaddr); 1490 } 1491 1492 /* This call used for the side effect (overload flag) */ 1493 (void) bootpc_tag(&gctx->tmptag, 1494 &ifctx->reply, ifctx->replylen, TAG_END); 1495 1496 if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0) 1497 if (ifctx->reply.sname[0] != '\0') 1498 printf(" server name %s", ifctx->reply.sname); 1499 if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0) 1500 if (ifctx->reply.file[0] != '\0') 1501 printf(" boot file %s", ifctx->reply.file); 1502 1503 printf("\n"); 1504 1505 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1506 TAG_SUBNETMASK); 1507 if (p != NULL) { 1508 if (gctx->tag.taglen != 4) 1509 panic("bootpc: subnet mask len is %d", 1510 gctx->tag.taglen); 1511 bcopy(p, &ifctx->netmask.sin_addr, 4); 1512 ifctx->gotnetmask = 1; 1513 printf("subnet mask "); 1514 print_sin_addr(&ifctx->netmask); 1515 printf(" "); 1516 } 1517 1518 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1519 TAG_ROUTERS); 1520 if (p != NULL) { 1521 /* Routers */ 1522 if (gctx->tag.taglen % 4) 1523 panic("bootpc: Router Len is %d", gctx->tag.taglen); 1524 if (gctx->tag.taglen > 0) { 1525 bcopy(p, &ifctx->gw.sin_addr, 4); 1526 printf("router "); 1527 print_sin_addr(&ifctx->gw); 1528 printf(" "); 1529 ifctx->gotgw = 1; 1530 gctx->gotgw = 1; 1531 } 1532 } 1533 1534 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1535 TAG_ROOT); 1536 if (p != NULL) { 1537 if (gctx->setrootfs != NULL) { 1538 printf("rootfs %s (ignored) ", p); 1539 } else if (setfs(&nd->root_saddr, 1540 nd->root_hostnam, p)) { 1541 printf("rootfs %s ", p); 1542 gctx->gotrootpath = 1; 1543 ifctx->gotrootpath = 1; 1544 gctx->setrootfs = ifctx; 1545 1546 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1547 ifctx->replylen, 1548 TAG_ROOTOPTS); 1549 if (p != NULL) { 1550 mountopts(&nd->root_args, p); 1551 printf("rootopts %s ", p); 1552 } 1553 } else 1554 panic("Failed to set rootfs to %s", p); 1555 } 1556 1557 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1558 TAG_SWAP); 1559 if (p != NULL) { 1560 if (gctx->setswapfs != NULL) { 1561 printf("swapfs %s (ignored) ", p); 1562 } else if (setfs(&nd->swap_saddr, 1563 nd->swap_hostnam, p)) { 1564 gctx->gotswappath = 1; 1565 gctx->setswapfs = ifctx; 1566 printf("swapfs %s ", p); 1567 1568 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1569 ifctx->replylen, 1570 TAG_SWAPOPTS); 1571 if (p != NULL) { 1572 /* swap mount options */ 1573 mountopts(&nd->swap_args, p); 1574 printf("swapopts %s ", p); 1575 } 1576 1577 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1578 ifctx->replylen, 1579 TAG_SWAPSIZE); 1580 if (p != NULL) { 1581 int swaplen; 1582 if (gctx->tag.taglen != 4) 1583 panic("bootpc: " 1584 "Expected 4 bytes for swaplen, " 1585 "not %d bytes", 1586 gctx->tag.taglen); 1587 bcopy(p, &swaplen, 4); 1588 nd->swap_nblks = ntohl(swaplen); 1589 printf("swapsize %d KB ", 1590 nd->swap_nblks); 1591 } 1592 } else 1593 panic("Failed to set swapfs to %s", p); 1594 } 1595 1596 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1597 TAG_HOSTNAME); 1598 if (p != NULL) { 1599 if (gctx->tag.taglen >= MAXHOSTNAMELEN) 1600 panic("bootpc: hostname >= %d bytes", 1601 MAXHOSTNAMELEN); 1602 if (gctx->sethostname != NULL) { 1603 printf("hostname %s (ignored) ", p); 1604 } else { 1605 strcpy(nd->my_hostnam, p); 1606 strcpy(hostname, p); 1607 printf("hostname %s ", hostname); 1608 gctx->sethostname = ifctx; 1609 } 1610 } 1611 1612 printf("\n"); 1613 1614 if (ifctx->gotnetmask == 0) { 1615 if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1616 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); 1617 else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1618 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); 1619 else 1620 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); 1621 } 1622 if (ifctx->gotgw == 0) { 1623 /* Use proxyarp */ 1624 ifctx->gw.sin_addr.s_addr = ifctx->myaddr.sin_addr.s_addr; 1625 } 1626} 1627 1628void 1629bootpc_init(void) 1630{ 1631 struct bootpc_ifcontext *ifctx, *nctx; /* Interface BOOTP contexts */ 1632 struct bootpc_globalcontext *gctx; /* Global BOOTP context */ 1633 struct ifnet *ifp; 1634 int error; 1635 struct nfsv3_diskless *nd; 1636 struct thread *td; 1637 1638 nd = &nfsv3_diskless; 1639 td = curthread; 1640 1641 /* 1642 * If already filled in, don't touch it here 1643 */ 1644 if (nfs_diskless_valid != 0) 1645 return; 1646 1647 /* 1648 * Wait until arp entries can be handled. 1649 */ 1650 while (time_second == 0) 1651 tsleep(&time_second, PZERO + 8, "arpkludge", 10); 1652 1653 gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK); 1654 if (gctx == NULL) 1655 panic("Failed to allocate bootp global context structure"); 1656 1657 bzero(gctx, sizeof(*gctx)); 1658 gctx->xid = ~0xFFFF; 1659 gctx->starttime = time_second; 1660 1661 ifctx = allocifctx(gctx); 1662 1663 /* 1664 * Find a network interface. 1665 */ 1666#ifdef BOOTP_WIRED_TO 1667 printf("bootpc_init: wired to interface '%s'\n", 1668 __XSTRING(BOOTP_WIRED_TO)); 1669#endif 1670 bzero(&ifctx->ireq, sizeof(ifctx->ireq)); 1671 for (ifp = TAILQ_FIRST(&ifnet); 1672 ifp != NULL; 1673 ifp = TAILQ_NEXT(ifp, if_link)) { 1674 snprintf(ifctx->ireq.ifr_name, sizeof(ifctx->ireq.ifr_name), 1675 "%s%d", ifp->if_name, ifp->if_unit); 1676#ifdef BOOTP_WIRED_TO 1677 if (strcmp(ifctx->ireq.ifr_name, 1678 __XSTRING(BOOTP_WIRED_TO)) != 0) 1679 continue; 1680#else 1681 if ((ifp->if_flags & 1682 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1683 IFF_BROADCAST) 1684 continue; 1685#endif 1686 if (gctx->interfaces != NULL) 1687 gctx->lastinterface->next = ifctx; 1688 else 1689 gctx->interfaces = ifctx; 1690 ifctx->ifp = ifp; 1691 gctx->lastinterface = ifctx; 1692 ifctx = allocifctx(gctx); 1693 } 1694 free(ifctx, M_TEMP); 1695 1696 if (gctx->interfaces == NULL) { 1697#ifdef BOOTP_WIRED_TO 1698 panic("bootpc_init: Could not find interface specified " 1699 "by BOOTP_WIRED_TO: " 1700 __XSTRING(BOOTP_WIRED_TO)); 1701#else 1702 panic("bootpc_init: no suitable interface"); 1703#endif 1704 } 1705 1706 gctx->gotrootpath = 0; 1707 gctx->gotswappath = 0; 1708 gctx->gotgw = 0; 1709 1710 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1711 bootpc_fakeup_interface(ifctx, gctx, td); 1712 1713 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1714 bootpc_compose_query(ifctx, gctx, td); 1715 1716 ifctx = gctx->interfaces; 1717 error = bootpc_call(gctx, td); 1718 1719 if (error != 0) { 1720#ifdef BOOTP_NFSROOT 1721 panic("BOOTP call failed"); 1722#else 1723 printf("BOOTP call failed\n"); 1724#endif 1725 } 1726 1727 mountopts(&nd->root_args, NULL); 1728 1729 mountopts(&nd->swap_args, NULL); 1730 1731 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1732 if (bootpc_ifctx_isresolved(ifctx) != 0) 1733 bootpc_decode_reply(nd, ifctx, gctx); 1734 1735 if (gctx->gotswappath == 0) 1736 nd->swap_nblks = 0; 1737#ifdef BOOTP_NFSROOT 1738 if (gctx->gotrootpath == 0) 1739 panic("bootpc: No root path offered"); 1740#endif 1741 1742 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 1743 bootpc_adjust_interface(ifctx, gctx, td); 1744 1745 soclose(ifctx->so); 1746 } 1747 1748 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1749 if (ifctx->gotrootpath != 0) 1750 break; 1751 if (ifctx == NULL) { 1752 for (ifctx = gctx->interfaces; 1753 ifctx != NULL; 1754 ifctx = ifctx->next) 1755 if (bootpc_ifctx_isresolved(ifctx) != 0) 1756 break; 1757 } 1758 if (ifctx == NULL) 1759 goto out; 1760 1761 if (gctx->gotrootpath != 0) { 1762 1763 error = md_mount(&nd->root_saddr, nd->root_hostnam, 1764 nd->root_fh, &nd->root_fhsize, 1765 &nd->root_args, td); 1766 if (error != 0) 1767 panic("nfs_boot: mountd root, error=%d", error); 1768 1769 if (gctx->gotswappath != 0) { 1770 1771 error = md_mount(&nd->swap_saddr, 1772 nd->swap_hostnam, 1773 nd->swap_fh, &nd->swap_fhsize, 1774 &nd->swap_args, td); 1775 if (error != 0) 1776 panic("nfs_boot: mountd swap, error=%d", 1777 error); 1778 1779 error = md_lookup_swap(&nd->swap_saddr, 1780 gctx->lookup_path, 1781 nd->swap_fh, &nd->swap_fhsize, 1782 &nd->swap_args, td); 1783 if (error != 0) 1784 panic("nfs_boot: lookup swap, error=%d", 1785 error); 1786 } 1787 nfs_diskless_valid = 3; 1788 } 1789 1790 strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name); 1791 bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr)); 1792 bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr)); 1793 ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = 1794 ifctx->myaddr.sin_addr.s_addr | 1795 ~ ifctx->netmask.sin_addr.s_addr; 1796 bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask)); 1797 1798out: 1799 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) { 1800 nctx = ifctx->next; 1801 free(ifctx, M_TEMP); 1802 } 1803 free(gctx, M_TEMP); 1804} 1805 1806/* 1807 * RPC: mountd/mount 1808 * Given a server pathname, get an NFS file handle. 1809 * Also, sets sin->sin_port to the NFS service port. 1810 */ 1811static int 1812md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, 1813 struct nfs_args *args, struct thread *td) 1814{ 1815 struct mbuf *m; 1816 int error; 1817 int authunixok; 1818 int authcount; 1819 int authver; 1820 1821#ifdef BOOTP_NFSV3 1822 /* First try NFS v3 */ 1823 /* Get port number for MOUNTD. */ 1824 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1825 &mdsin->sin_port, td); 1826 if (error == 0) { 1827 m = xdr_string_encode(path, strlen(path)); 1828 1829 /* Do RPC to mountd. */ 1830 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1831 RPCMNT_MOUNT, &m, NULL, td); 1832 } 1833 if (error == 0) { 1834 args->flags |= NFSMNT_NFSV3; 1835 } else { 1836#endif 1837 /* Fallback to NFS v2 */ 1838 1839 /* Get port number for MOUNTD. */ 1840 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1841 &mdsin->sin_port, td); 1842 if (error != 0) 1843 return error; 1844 1845 m = xdr_string_encode(path, strlen(path)); 1846 1847 /* Do RPC to mountd. */ 1848 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1849 RPCMNT_MOUNT, &m, NULL, td); 1850 if (error != 0) 1851 return error; /* message already freed */ 1852 1853#ifdef BOOTP_NFSV3 1854 } 1855#endif 1856 1857 if (xdr_int_decode(&m, &error) != 0 || error != 0) 1858 goto bad; 1859 1860 if ((args->flags & NFSMNT_NFSV3) != 0) { 1861 if (xdr_int_decode(&m, fhsizep) != 0 || 1862 *fhsizep > NFSX_V3FHMAX || 1863 *fhsizep <= 0) 1864 goto bad; 1865 } else 1866 *fhsizep = NFSX_V2FH; 1867 1868 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 1869 goto bad; 1870 1871 if (args->flags & NFSMNT_NFSV3) { 1872 if (xdr_int_decode(&m, &authcount) != 0) 1873 goto bad; 1874 authunixok = 0; 1875 if (authcount < 0 || authcount > 100) 1876 goto bad; 1877 while (authcount > 0) { 1878 if (xdr_int_decode(&m, &authver) != 0) 1879 goto bad; 1880 if (authver == RPCAUTH_UNIX) 1881 authunixok = 1; 1882 authcount--; 1883 } 1884 if (authunixok == 0) 1885 goto bad; 1886 } 1887 1888 /* Set port number for NFS use. */ 1889 error = krpc_portmap(mdsin, NFS_PROG, 1890 (args->flags & 1891 NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2, 1892 &mdsin->sin_port, td); 1893 1894 goto out; 1895 1896bad: 1897 error = EBADRPC; 1898 1899out: 1900 m_freem(m); 1901 return error; 1902} 1903 1904static int 1905md_lookup_swap(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, 1906 struct nfs_args *args, struct thread *td) 1907{ 1908 struct mbuf *m; 1909 int error; 1910 int size = -1; 1911 int attribs_present; 1912 int status; 1913 union { 1914 u_int32_t v2[17]; 1915 u_int32_t v3[21]; 1916 } fattribs; 1917 1918 m = m_get(M_TRYWAIT, MT_DATA); 1919 if (m == NULL) 1920 return ENOBUFS; 1921 1922 if ((args->flags & NFSMNT_NFSV3) != 0) { 1923 *mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep); 1924 bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep); 1925 m->m_len = *fhsizep + sizeof(u_int32_t); 1926 } else { 1927 bcopy(fhp, mtod(m, u_char *), NFSX_V2FH); 1928 m->m_len = NFSX_V2FH; 1929 } 1930 1931 m->m_next = xdr_string_encode(path, strlen(path)); 1932 if (m->m_next == NULL) { 1933 error = ENOBUFS; 1934 goto out; 1935 } 1936 1937 /* Do RPC to nfsd. */ 1938 if ((args->flags & NFSMNT_NFSV3) != 0) 1939 error = krpc_call(mdsin, NFS_PROG, NFS_VER3, 1940 NFSPROC_LOOKUP, &m, NULL, td); 1941 else 1942 error = krpc_call(mdsin, NFS_PROG, NFS_VER2, 1943 NFSV2PROC_LOOKUP, &m, NULL, td); 1944 if (error != 0) 1945 return error; /* message already freed */ 1946 1947 if (xdr_int_decode(&m, &status) != 0) 1948 goto bad; 1949 if (status != 0) { 1950 error = ENOENT; 1951 goto out; 1952 } 1953 1954 if ((args->flags & NFSMNT_NFSV3) != 0) { 1955 if (xdr_int_decode(&m, fhsizep) != 0 || 1956 *fhsizep > NFSX_V3FHMAX || 1957 *fhsizep <= 0) 1958 goto bad; 1959 } else 1960 *fhsizep = NFSX_V2FH; 1961 1962 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 1963 goto bad; 1964 1965 if ((args->flags & NFSMNT_NFSV3) != 0) { 1966 if (xdr_int_decode(&m, &attribs_present) != 0) 1967 goto bad; 1968 if (attribs_present != 0) { 1969 if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3, 1970 sizeof(u_int32_t) * 21) != 0) 1971 goto bad; 1972 size = fxdr_unsigned(u_int32_t, fattribs.v3[6]); 1973 } 1974 } else { 1975 if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2, 1976 sizeof(u_int32_t) * 17) != 0) 1977 goto bad; 1978 size = fxdr_unsigned(u_int32_t, fattribs.v2[5]); 1979 } 1980 1981 if (nfsv3_diskless.swap_nblks == 0 && size != -1) { 1982 nfsv3_diskless.swap_nblks = size / 1024; 1983 printf("md_lookup_swap: Swap size is %d KB\n", 1984 nfsv3_diskless.swap_nblks); 1985 } 1986 1987 goto out; 1988 1989bad: 1990 error = EBADRPC; 1991 1992out: 1993 m_freem(m); 1994 return error; 1995}
| 977 if (error != 0) 978 panic("nfs_boot: socreate, error=%d", error); 979 980 ireq = &ifctx->ireq; 981 so = ifctx->so; 982 983 /* 984 * Bring up the interface. 985 * 986 * Get the old interface flags and or IFF_UP into them; if 987 * IFF_UP set blindly, interface selection can be clobbered. 988 */ 989 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 990 if (error != 0) 991 panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); 992 ireq->ifr_flags |= IFF_UP; 993 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 994 if (error != 0) 995 panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); 996 997 /* 998 * Do enough of ifconfig(8) so that the chosen interface 999 * can talk to the servers. (just set the address) 1000 */ 1001 1002 /* addr is 0.0.0.0 */ 1003 1004 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1005 clear_sinaddr(sin); 1006 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1007 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1008 panic("bootpc_fakeup_interface: " 1009 "set if addr, error=%d", error); 1010 1011 /* netmask is 255.0.0.0 */ 1012 1013 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1014 clear_sinaddr(sin); 1015 sin->sin_addr.s_addr = htonl(0xff000000u); 1016 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td); 1017 if (error != 0) 1018 panic("bootpc_fakeup_interface: set if netmask, error=%d", 1019 error); 1020 1021 /* Broadcast is 255.255.255.255 */ 1022 1023 sin = (struct sockaddr_in *)&ireq->ifr_addr; 1024 clear_sinaddr(sin); 1025 clear_sinaddr(&ifctx->broadcast); 1026 sin->sin_addr.s_addr = htonl(INADDR_BROADCAST); 1027 ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr; 1028 1029 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td); 1030 if (error != 0) 1031 panic("bootpc_fakeup_interface: " 1032 "set if broadcast addr, error=%d", 1033 error); 1034 1035 /* Get HW address */ 1036 1037 sdl = NULL; 1038 for (ifa = TAILQ_FIRST(&ifctx->ifp->if_addrhead); 1039 ifa != NULL; 1040 ifa = TAILQ_NEXT(ifa, ifa_link)) 1041 if (ifa->ifa_addr->sa_family == AF_LINK && 1042 (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) != NULL && 1043 sdl->sdl_type == IFT_ETHER) 1044 break; 1045 1046 if (sdl == NULL) 1047 panic("bootpc: Unable to find HW address for %s", 1048 ifctx->ireq.ifr_name); 1049 ifctx->sdl = sdl; 1050 1051 return error; 1052} 1053 1054 1055static int 1056bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, 1057 struct bootpc_globalcontext *gctx, struct thread *td) 1058{ 1059 int error; 1060 struct sockaddr_in defdst; 1061 struct sockaddr_in defmask; 1062 struct sockaddr_in *sin; 1063 struct ifreq *ireq; 1064 struct socket *so; 1065 struct sockaddr_in *myaddr; 1066 struct sockaddr_in *netmask; 1067 struct sockaddr_in *gw; 1068 1069 ireq = &ifctx->ireq; 1070 so = ifctx->so; 1071 myaddr = &ifctx->myaddr; 1072 netmask = &ifctx->netmask; 1073 gw = &ifctx->gw; 1074 1075 if (bootpc_ifctx_isresolved(ifctx) == 0) { 1076 1077 /* Shutdown interfaces where BOOTP failed */ 1078 1079 printf("Shutdown interface %s\n", ifctx->ireq.ifr_name); 1080 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 1081 if (error != 0) 1082 panic("bootpc_adjust_interface: " 1083 "SIOCGIFFLAGS, error=%d", error); 1084 ireq->ifr_flags &= ~IFF_UP; 1085 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 1086 if (error != 0) 1087 panic("bootpc_adjust_interface: " 1088 "SIOCSIFFLAGS, error=%d", error); 1089 1090 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1091 clear_sinaddr(sin); 1092 error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td); 1093 if (error != 0 && (error != EEXIST || 1094 ifctx == gctx->interfaces)) 1095 panic("bootpc_adjust_interface: " 1096 "SIOCDIFADDR, error=%d", error); 1097 1098 return 0; 1099 } 1100 1101 printf("Adjusted interface %s\n", ifctx->ireq.ifr_name); 1102 /* 1103 * Do enough of ifconfig(8) so that the chosen interface 1104 * can talk to the servers. (just set the address) 1105 */ 1106 bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask)); 1107 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td); 1108 if (error != 0) 1109 panic("bootpc_adjust_interface: " 1110 "set if netmask, error=%d", error); 1111 1112 /* Broadcast is with host part of IP address all 1's */ 1113 1114 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1115 clear_sinaddr(sin); 1116 sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | 1117 ~ netmask->sin_addr.s_addr; 1118 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td); 1119 if (error != 0) 1120 panic("bootpc_adjust_interface: " 1121 "set if broadcast addr, error=%d", error); 1122 1123 bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr)); 1124 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1125 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1126 panic("bootpc_adjust_interface: " 1127 "set if addr, error=%d", error); 1128 1129 /* Add new default route */ 1130 1131 if (ifctx->gotgw != 0 || gctx->gotgw == 0) { 1132 clear_sinaddr(&defdst); 1133 clear_sinaddr(&defmask); 1134 error = rtrequest(RTM_ADD, 1135 (struct sockaddr *) &defdst, 1136 (struct sockaddr *) gw, 1137 (struct sockaddr *) &defmask, 1138 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); 1139 if (error != 0) { 1140 printf("bootpc_adjust_interface: " 1141 "add net route, error=%d\n", error); 1142 return error; 1143 } 1144 } 1145 1146 return 0; 1147} 1148 1149static int 1150setfs(struct sockaddr_in *addr, char *path, char *p) 1151{ 1152 unsigned int ip; 1153 int val; 1154 1155 ip = 0; 1156 if (((val = getdec(&p)) < 0) || (val > 255)) 1157 return 0; 1158 ip = val << 24; 1159 if (*p != '.') 1160 return 0; 1161 p++; 1162 if (((val = getdec(&p)) < 0) || (val > 255)) 1163 return 0; 1164 ip |= (val << 16); 1165 if (*p != '.') 1166 return 0; 1167 p++; 1168 if (((val = getdec(&p)) < 0) || (val > 255)) 1169 return 0; 1170 ip |= (val << 8); 1171 if (*p != '.') 1172 return 0; 1173 p++; 1174 if (((val = getdec(&p)) < 0) || (val > 255)) 1175 return 0; 1176 ip |= val; 1177 if (*p != ':') 1178 return 0; 1179 p++; 1180 1181 addr->sin_addr.s_addr = htonl(ip); 1182 addr->sin_len = sizeof(struct sockaddr_in); 1183 addr->sin_family = AF_INET; 1184 1185 strncpy(path, p, MNAMELEN - 1); 1186 return 1; 1187} 1188 1189static int 1190getdec(char **ptr) 1191{ 1192 char *p; 1193 int ret; 1194 1195 p = *ptr; 1196 ret = 0; 1197 if ((*p < '0') || (*p > '9')) 1198 return -1; 1199 while ((*p >= '0') && (*p <= '9')) { 1200 ret = ret * 10 + (*p - '0'); 1201 p++; 1202 } 1203 *ptr = p; 1204 return ret; 1205} 1206 1207static char * 1208substr(char *a, char *b) 1209{ 1210 char *loc1; 1211 char *loc2; 1212 1213 while (*a != '\0') { 1214 loc1 = a; 1215 loc2 = b; 1216 while (*loc1 == *loc2++) { 1217 if (*loc1 == '\0') 1218 return 0; 1219 loc1++; 1220 if (*loc2 == '\0') 1221 return loc1; 1222 } 1223 a++; 1224 } 1225 return 0; 1226} 1227 1228static void 1229mountopts(struct nfs_args *args, char *p) 1230{ 1231 char *tmp; 1232 1233 args->version = NFS_ARGSVERSION; 1234 args->rsize = 8192; 1235 args->wsize = 8192; 1236 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT; 1237 args->sotype = SOCK_DGRAM; 1238 if (p == NULL) 1239 return; 1240 if ((tmp = (char *)substr(p, "rsize="))) 1241 args->rsize = getdec(&tmp); 1242 if ((tmp = (char *)substr(p, "wsize="))) 1243 args->wsize = getdec(&tmp); 1244 if ((tmp = (char *)substr(p, "intr"))) 1245 args->flags |= NFSMNT_INT; 1246 if ((tmp = (char *)substr(p, "soft"))) 1247 args->flags |= NFSMNT_SOFT; 1248 if ((tmp = (char *)substr(p, "noconn"))) 1249 args->flags |= NFSMNT_NOCONN; 1250 if ((tmp = (char *)substr(p, "tcp"))) 1251 args->sotype = SOCK_STREAM; 1252} 1253 1254static int 1255xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) 1256{ 1257 struct mbuf *m; 1258 int alignedlen; 1259 1260 m = *mptr; 1261 alignedlen = ( len + 3 ) & ~3; 1262 1263 if (m->m_len < alignedlen) { 1264 m = m_pullup(m, alignedlen); 1265 if (m == NULL) { 1266 *mptr = NULL; 1267 return EBADRPC; 1268 } 1269 } 1270 bcopy(mtod(m, u_char *), buf, len); 1271 m_adj(m, alignedlen); 1272 *mptr = m; 1273 return 0; 1274} 1275 1276static int 1277xdr_int_decode(struct mbuf **mptr, int *iptr) 1278{ 1279 u_int32_t i; 1280 1281 if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) 1282 return EBADRPC; 1283 *iptr = fxdr_unsigned(u_int32_t, i); 1284 return 0; 1285} 1286 1287static void 1288print_sin_addr(struct sockaddr_in *sin) 1289{ 1290 1291 print_in_addr(sin->sin_addr); 1292} 1293 1294static void 1295print_in_addr(struct in_addr addr) 1296{ 1297 unsigned int ip; 1298 1299 ip = ntohl(addr.s_addr); 1300 printf("%d.%d.%d.%d", 1301 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); 1302} 1303 1304static void 1305bootpc_compose_query(struct bootpc_ifcontext *ifctx, 1306 struct bootpc_globalcontext *gctx, struct thread *td) 1307{ 1308 unsigned char *vendp; 1309 uint32_t leasetime; 1310 1311 ifctx->gotrootpath = 0; 1312 1313 bzero((caddr_t) &ifctx->call, sizeof(ifctx->call)); 1314 1315 /* bootpc part */ 1316 ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */ 1317 ifctx->call.htype = 1; /* 10mb ethernet */ 1318 ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */ 1319 ifctx->call.hops = 0; 1320 if (bootpc_ifctx_isunresolved(ifctx) != 0) 1321 ifctx->xid++; 1322 ifctx->call.xid = txdr_unsigned(ifctx->xid); 1323 bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen); 1324 1325 vendp = ifctx->call.vend; 1326 *vendp++ = 99; /* RFC1048 cookie */ 1327 *vendp++ = 130; 1328 *vendp++ = 83; 1329 *vendp++ = 99; 1330 *vendp++ = TAG_MAXMSGSIZE; 1331 *vendp++ = 2; 1332 *vendp++ = (sizeof(struct bootp_packet) >> 8) & 255; 1333 *vendp++ = sizeof(struct bootp_packet) & 255; 1334 ifctx->dhcpquerytype = DHCP_NOMSG; 1335 switch (ifctx->state) { 1336 case IF_DHCP_UNRESOLVED: 1337 *vendp++ = TAG_DHCP_MSGTYPE; 1338 *vendp++ = 1; 1339 *vendp++ = DHCP_DISCOVER; 1340 ifctx->dhcpquerytype = DHCP_DISCOVER; 1341 ifctx->gotdhcpserver = 0; 1342 break; 1343 case IF_DHCP_OFFERED: 1344 *vendp++ = TAG_DHCP_MSGTYPE; 1345 *vendp++ = 1; 1346 *vendp++ = DHCP_REQUEST; 1347 ifctx->dhcpquerytype = DHCP_REQUEST; 1348 *vendp++ = TAG_DHCP_REQ_ADDR; 1349 *vendp++ = 4; 1350 memcpy(vendp, &ifctx->reply.yiaddr, 4); 1351 vendp += 4; 1352 if (ifctx->gotdhcpserver != 0) { 1353 *vendp++ = TAG_DHCP_SERVERID; 1354 *vendp++ = 4; 1355 memcpy(vendp, &ifctx->dhcpserver, 4); 1356 vendp += 4; 1357 } 1358 *vendp++ = TAG_DHCP_LEASETIME; 1359 *vendp++ = 4; 1360 leasetime = htonl(300); 1361 memcpy(vendp, &leasetime, 4); 1362 vendp += 4; 1363 default: 1364 ; 1365 } 1366 *vendp = TAG_END; 1367 1368 ifctx->call.secs = 0; 1369 ifctx->call.flags = htons(0x8000); /* We need an broadcast answer */ 1370} 1371 1372static int 1373bootpc_hascookie(struct bootp_packet *bp) 1374{ 1375 1376 return (bp->vend[0] == 99 && bp->vend[1] == 130 && 1377 bp->vend[2] == 83 && bp->vend[3] == 99); 1378} 1379 1380static void 1381bootpc_tag_helper(struct bootpc_tagcontext *tctx, 1382 unsigned char *start, int len, int tag) 1383{ 1384 unsigned char *j; 1385 unsigned char *ej; 1386 unsigned char code; 1387 1388 if (tctx->badtag != 0 || tctx->badopt != 0) 1389 return; 1390 1391 j = start; 1392 ej = j + len; 1393 1394 while (j < ej) { 1395 code = *j++; 1396 if (code == TAG_PAD) 1397 continue; 1398 if (code == TAG_END) 1399 return; 1400 if (j >= ej || j + *j + 1 > ej) { 1401 tctx->badopt = 1; 1402 return; 1403 } 1404 len = *j++; 1405 if (code == tag) { 1406 if (tctx->taglen + len > TAG_MAXLEN) { 1407 tctx->badtag = 1; 1408 return; 1409 } 1410 tctx->foundopt = 1; 1411 if (len > 0) 1412 memcpy(tctx->buf + tctx->taglen, 1413 j, len); 1414 tctx->taglen += len; 1415 } 1416 if (code == TAG_OVERLOAD) 1417 tctx->overload = *j; 1418 1419 j += len; 1420 } 1421} 1422 1423static unsigned char * 1424bootpc_tag(struct bootpc_tagcontext *tctx, 1425 struct bootp_packet *bp, int len, int tag) 1426{ 1427 unsigned char *j; 1428 unsigned char *ej; 1429 1430 tctx->overload = 0; 1431 tctx->badopt = 0; 1432 tctx->badtag = 0; 1433 tctx->foundopt = 0; 1434 tctx->taglen = 0; 1435 1436 if (bootpc_hascookie(bp) == 0) 1437 return NULL; 1438 1439 j = &bp->vend[4]; 1440 ej = (unsigned char *) bp + len; 1441 1442 bootpc_tag_helper(tctx, &bp->vend[4], 1443 (unsigned char *) bp + len - &bp->vend[4], tag); 1444 1445 if ((tctx->overload & OVERLOAD_FILE) != 0) 1446 bootpc_tag_helper(tctx, 1447 (unsigned char *) bp->file, 1448 sizeof(bp->file), 1449 tag); 1450 if ((tctx->overload & OVERLOAD_SNAME) != 0) 1451 bootpc_tag_helper(tctx, 1452 (unsigned char *) bp->sname, 1453 sizeof(bp->sname), 1454 tag); 1455 1456 if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0) 1457 return NULL; 1458 tctx->buf[tctx->taglen] = '\0'; 1459 return tctx->buf; 1460} 1461 1462static void 1463bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx, 1464 struct bootpc_globalcontext *gctx) 1465{ 1466 char *p; 1467 unsigned int ip; 1468 1469 ifctx->gotgw = 0; 1470 ifctx->gotnetmask = 0; 1471 1472 clear_sinaddr(&ifctx->myaddr); 1473 clear_sinaddr(&ifctx->netmask); 1474 clear_sinaddr(&ifctx->gw); 1475 1476 ifctx->myaddr.sin_addr = ifctx->reply.yiaddr; 1477 1478 ip = ntohl(ifctx->myaddr.sin_addr.s_addr); 1479 snprintf(gctx->lookup_path, sizeof(gctx->lookup_path), 1480 "swap.%d.%d.%d.%d", 1481 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); 1482 1483 printf("%s at ", ifctx->ireq.ifr_name); 1484 print_sin_addr(&ifctx->myaddr); 1485 printf(" server "); 1486 print_in_addr(ifctx->reply.siaddr); 1487 1488 ifctx->gw.sin_addr = ifctx->reply.giaddr; 1489 if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) { 1490 printf(" via gateway "); 1491 print_in_addr(ifctx->reply.giaddr); 1492 } 1493 1494 /* This call used for the side effect (overload flag) */ 1495 (void) bootpc_tag(&gctx->tmptag, 1496 &ifctx->reply, ifctx->replylen, TAG_END); 1497 1498 if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0) 1499 if (ifctx->reply.sname[0] != '\0') 1500 printf(" server name %s", ifctx->reply.sname); 1501 if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0) 1502 if (ifctx->reply.file[0] != '\0') 1503 printf(" boot file %s", ifctx->reply.file); 1504 1505 printf("\n"); 1506 1507 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1508 TAG_SUBNETMASK); 1509 if (p != NULL) { 1510 if (gctx->tag.taglen != 4) 1511 panic("bootpc: subnet mask len is %d", 1512 gctx->tag.taglen); 1513 bcopy(p, &ifctx->netmask.sin_addr, 4); 1514 ifctx->gotnetmask = 1; 1515 printf("subnet mask "); 1516 print_sin_addr(&ifctx->netmask); 1517 printf(" "); 1518 } 1519 1520 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1521 TAG_ROUTERS); 1522 if (p != NULL) { 1523 /* Routers */ 1524 if (gctx->tag.taglen % 4) 1525 panic("bootpc: Router Len is %d", gctx->tag.taglen); 1526 if (gctx->tag.taglen > 0) { 1527 bcopy(p, &ifctx->gw.sin_addr, 4); 1528 printf("router "); 1529 print_sin_addr(&ifctx->gw); 1530 printf(" "); 1531 ifctx->gotgw = 1; 1532 gctx->gotgw = 1; 1533 } 1534 } 1535 1536 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1537 TAG_ROOT); 1538 if (p != NULL) { 1539 if (gctx->setrootfs != NULL) { 1540 printf("rootfs %s (ignored) ", p); 1541 } else if (setfs(&nd->root_saddr, 1542 nd->root_hostnam, p)) { 1543 printf("rootfs %s ", p); 1544 gctx->gotrootpath = 1; 1545 ifctx->gotrootpath = 1; 1546 gctx->setrootfs = ifctx; 1547 1548 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1549 ifctx->replylen, 1550 TAG_ROOTOPTS); 1551 if (p != NULL) { 1552 mountopts(&nd->root_args, p); 1553 printf("rootopts %s ", p); 1554 } 1555 } else 1556 panic("Failed to set rootfs to %s", p); 1557 } 1558 1559 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1560 TAG_SWAP); 1561 if (p != NULL) { 1562 if (gctx->setswapfs != NULL) { 1563 printf("swapfs %s (ignored) ", p); 1564 } else if (setfs(&nd->swap_saddr, 1565 nd->swap_hostnam, p)) { 1566 gctx->gotswappath = 1; 1567 gctx->setswapfs = ifctx; 1568 printf("swapfs %s ", p); 1569 1570 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1571 ifctx->replylen, 1572 TAG_SWAPOPTS); 1573 if (p != NULL) { 1574 /* swap mount options */ 1575 mountopts(&nd->swap_args, p); 1576 printf("swapopts %s ", p); 1577 } 1578 1579 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1580 ifctx->replylen, 1581 TAG_SWAPSIZE); 1582 if (p != NULL) { 1583 int swaplen; 1584 if (gctx->tag.taglen != 4) 1585 panic("bootpc: " 1586 "Expected 4 bytes for swaplen, " 1587 "not %d bytes", 1588 gctx->tag.taglen); 1589 bcopy(p, &swaplen, 4); 1590 nd->swap_nblks = ntohl(swaplen); 1591 printf("swapsize %d KB ", 1592 nd->swap_nblks); 1593 } 1594 } else 1595 panic("Failed to set swapfs to %s", p); 1596 } 1597 1598 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1599 TAG_HOSTNAME); 1600 if (p != NULL) { 1601 if (gctx->tag.taglen >= MAXHOSTNAMELEN) 1602 panic("bootpc: hostname >= %d bytes", 1603 MAXHOSTNAMELEN); 1604 if (gctx->sethostname != NULL) { 1605 printf("hostname %s (ignored) ", p); 1606 } else { 1607 strcpy(nd->my_hostnam, p); 1608 strcpy(hostname, p); 1609 printf("hostname %s ", hostname); 1610 gctx->sethostname = ifctx; 1611 } 1612 } 1613 1614 printf("\n"); 1615 1616 if (ifctx->gotnetmask == 0) { 1617 if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1618 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); 1619 else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1620 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); 1621 else 1622 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); 1623 } 1624 if (ifctx->gotgw == 0) { 1625 /* Use proxyarp */ 1626 ifctx->gw.sin_addr.s_addr = ifctx->myaddr.sin_addr.s_addr; 1627 } 1628} 1629 1630void 1631bootpc_init(void) 1632{ 1633 struct bootpc_ifcontext *ifctx, *nctx; /* Interface BOOTP contexts */ 1634 struct bootpc_globalcontext *gctx; /* Global BOOTP context */ 1635 struct ifnet *ifp; 1636 int error; 1637 struct nfsv3_diskless *nd; 1638 struct thread *td; 1639 1640 nd = &nfsv3_diskless; 1641 td = curthread; 1642 1643 /* 1644 * If already filled in, don't touch it here 1645 */ 1646 if (nfs_diskless_valid != 0) 1647 return; 1648 1649 /* 1650 * Wait until arp entries can be handled. 1651 */ 1652 while (time_second == 0) 1653 tsleep(&time_second, PZERO + 8, "arpkludge", 10); 1654 1655 gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK); 1656 if (gctx == NULL) 1657 panic("Failed to allocate bootp global context structure"); 1658 1659 bzero(gctx, sizeof(*gctx)); 1660 gctx->xid = ~0xFFFF; 1661 gctx->starttime = time_second; 1662 1663 ifctx = allocifctx(gctx); 1664 1665 /* 1666 * Find a network interface. 1667 */ 1668#ifdef BOOTP_WIRED_TO 1669 printf("bootpc_init: wired to interface '%s'\n", 1670 __XSTRING(BOOTP_WIRED_TO)); 1671#endif 1672 bzero(&ifctx->ireq, sizeof(ifctx->ireq)); 1673 for (ifp = TAILQ_FIRST(&ifnet); 1674 ifp != NULL; 1675 ifp = TAILQ_NEXT(ifp, if_link)) { 1676 snprintf(ifctx->ireq.ifr_name, sizeof(ifctx->ireq.ifr_name), 1677 "%s%d", ifp->if_name, ifp->if_unit); 1678#ifdef BOOTP_WIRED_TO 1679 if (strcmp(ifctx->ireq.ifr_name, 1680 __XSTRING(BOOTP_WIRED_TO)) != 0) 1681 continue; 1682#else 1683 if ((ifp->if_flags & 1684 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1685 IFF_BROADCAST) 1686 continue; 1687#endif 1688 if (gctx->interfaces != NULL) 1689 gctx->lastinterface->next = ifctx; 1690 else 1691 gctx->interfaces = ifctx; 1692 ifctx->ifp = ifp; 1693 gctx->lastinterface = ifctx; 1694 ifctx = allocifctx(gctx); 1695 } 1696 free(ifctx, M_TEMP); 1697 1698 if (gctx->interfaces == NULL) { 1699#ifdef BOOTP_WIRED_TO 1700 panic("bootpc_init: Could not find interface specified " 1701 "by BOOTP_WIRED_TO: " 1702 __XSTRING(BOOTP_WIRED_TO)); 1703#else 1704 panic("bootpc_init: no suitable interface"); 1705#endif 1706 } 1707 1708 gctx->gotrootpath = 0; 1709 gctx->gotswappath = 0; 1710 gctx->gotgw = 0; 1711 1712 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1713 bootpc_fakeup_interface(ifctx, gctx, td); 1714 1715 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1716 bootpc_compose_query(ifctx, gctx, td); 1717 1718 ifctx = gctx->interfaces; 1719 error = bootpc_call(gctx, td); 1720 1721 if (error != 0) { 1722#ifdef BOOTP_NFSROOT 1723 panic("BOOTP call failed"); 1724#else 1725 printf("BOOTP call failed\n"); 1726#endif 1727 } 1728 1729 mountopts(&nd->root_args, NULL); 1730 1731 mountopts(&nd->swap_args, NULL); 1732 1733 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1734 if (bootpc_ifctx_isresolved(ifctx) != 0) 1735 bootpc_decode_reply(nd, ifctx, gctx); 1736 1737 if (gctx->gotswappath == 0) 1738 nd->swap_nblks = 0; 1739#ifdef BOOTP_NFSROOT 1740 if (gctx->gotrootpath == 0) 1741 panic("bootpc: No root path offered"); 1742#endif 1743 1744 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 1745 bootpc_adjust_interface(ifctx, gctx, td); 1746 1747 soclose(ifctx->so); 1748 } 1749 1750 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1751 if (ifctx->gotrootpath != 0) 1752 break; 1753 if (ifctx == NULL) { 1754 for (ifctx = gctx->interfaces; 1755 ifctx != NULL; 1756 ifctx = ifctx->next) 1757 if (bootpc_ifctx_isresolved(ifctx) != 0) 1758 break; 1759 } 1760 if (ifctx == NULL) 1761 goto out; 1762 1763 if (gctx->gotrootpath != 0) { 1764 1765 error = md_mount(&nd->root_saddr, nd->root_hostnam, 1766 nd->root_fh, &nd->root_fhsize, 1767 &nd->root_args, td); 1768 if (error != 0) 1769 panic("nfs_boot: mountd root, error=%d", error); 1770 1771 if (gctx->gotswappath != 0) { 1772 1773 error = md_mount(&nd->swap_saddr, 1774 nd->swap_hostnam, 1775 nd->swap_fh, &nd->swap_fhsize, 1776 &nd->swap_args, td); 1777 if (error != 0) 1778 panic("nfs_boot: mountd swap, error=%d", 1779 error); 1780 1781 error = md_lookup_swap(&nd->swap_saddr, 1782 gctx->lookup_path, 1783 nd->swap_fh, &nd->swap_fhsize, 1784 &nd->swap_args, td); 1785 if (error != 0) 1786 panic("nfs_boot: lookup swap, error=%d", 1787 error); 1788 } 1789 nfs_diskless_valid = 3; 1790 } 1791 1792 strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name); 1793 bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr)); 1794 bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr)); 1795 ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = 1796 ifctx->myaddr.sin_addr.s_addr | 1797 ~ ifctx->netmask.sin_addr.s_addr; 1798 bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask)); 1799 1800out: 1801 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) { 1802 nctx = ifctx->next; 1803 free(ifctx, M_TEMP); 1804 } 1805 free(gctx, M_TEMP); 1806} 1807 1808/* 1809 * RPC: mountd/mount 1810 * Given a server pathname, get an NFS file handle. 1811 * Also, sets sin->sin_port to the NFS service port. 1812 */ 1813static int 1814md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, 1815 struct nfs_args *args, struct thread *td) 1816{ 1817 struct mbuf *m; 1818 int error; 1819 int authunixok; 1820 int authcount; 1821 int authver; 1822 1823#ifdef BOOTP_NFSV3 1824 /* First try NFS v3 */ 1825 /* Get port number for MOUNTD. */ 1826 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1827 &mdsin->sin_port, td); 1828 if (error == 0) { 1829 m = xdr_string_encode(path, strlen(path)); 1830 1831 /* Do RPC to mountd. */ 1832 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1833 RPCMNT_MOUNT, &m, NULL, td); 1834 } 1835 if (error == 0) { 1836 args->flags |= NFSMNT_NFSV3; 1837 } else { 1838#endif 1839 /* Fallback to NFS v2 */ 1840 1841 /* Get port number for MOUNTD. */ 1842 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1843 &mdsin->sin_port, td); 1844 if (error != 0) 1845 return error; 1846 1847 m = xdr_string_encode(path, strlen(path)); 1848 1849 /* Do RPC to mountd. */ 1850 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1851 RPCMNT_MOUNT, &m, NULL, td); 1852 if (error != 0) 1853 return error; /* message already freed */ 1854 1855#ifdef BOOTP_NFSV3 1856 } 1857#endif 1858 1859 if (xdr_int_decode(&m, &error) != 0 || error != 0) 1860 goto bad; 1861 1862 if ((args->flags & NFSMNT_NFSV3) != 0) { 1863 if (xdr_int_decode(&m, fhsizep) != 0 || 1864 *fhsizep > NFSX_V3FHMAX || 1865 *fhsizep <= 0) 1866 goto bad; 1867 } else 1868 *fhsizep = NFSX_V2FH; 1869 1870 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 1871 goto bad; 1872 1873 if (args->flags & NFSMNT_NFSV3) { 1874 if (xdr_int_decode(&m, &authcount) != 0) 1875 goto bad; 1876 authunixok = 0; 1877 if (authcount < 0 || authcount > 100) 1878 goto bad; 1879 while (authcount > 0) { 1880 if (xdr_int_decode(&m, &authver) != 0) 1881 goto bad; 1882 if (authver == RPCAUTH_UNIX) 1883 authunixok = 1; 1884 authcount--; 1885 } 1886 if (authunixok == 0) 1887 goto bad; 1888 } 1889 1890 /* Set port number for NFS use. */ 1891 error = krpc_portmap(mdsin, NFS_PROG, 1892 (args->flags & 1893 NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2, 1894 &mdsin->sin_port, td); 1895 1896 goto out; 1897 1898bad: 1899 error = EBADRPC; 1900 1901out: 1902 m_freem(m); 1903 return error; 1904} 1905 1906static int 1907md_lookup_swap(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, 1908 struct nfs_args *args, struct thread *td) 1909{ 1910 struct mbuf *m; 1911 int error; 1912 int size = -1; 1913 int attribs_present; 1914 int status; 1915 union { 1916 u_int32_t v2[17]; 1917 u_int32_t v3[21]; 1918 } fattribs; 1919 1920 m = m_get(M_TRYWAIT, MT_DATA); 1921 if (m == NULL) 1922 return ENOBUFS; 1923 1924 if ((args->flags & NFSMNT_NFSV3) != 0) { 1925 *mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep); 1926 bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep); 1927 m->m_len = *fhsizep + sizeof(u_int32_t); 1928 } else { 1929 bcopy(fhp, mtod(m, u_char *), NFSX_V2FH); 1930 m->m_len = NFSX_V2FH; 1931 } 1932 1933 m->m_next = xdr_string_encode(path, strlen(path)); 1934 if (m->m_next == NULL) { 1935 error = ENOBUFS; 1936 goto out; 1937 } 1938 1939 /* Do RPC to nfsd. */ 1940 if ((args->flags & NFSMNT_NFSV3) != 0) 1941 error = krpc_call(mdsin, NFS_PROG, NFS_VER3, 1942 NFSPROC_LOOKUP, &m, NULL, td); 1943 else 1944 error = krpc_call(mdsin, NFS_PROG, NFS_VER2, 1945 NFSV2PROC_LOOKUP, &m, NULL, td); 1946 if (error != 0) 1947 return error; /* message already freed */ 1948 1949 if (xdr_int_decode(&m, &status) != 0) 1950 goto bad; 1951 if (status != 0) { 1952 error = ENOENT; 1953 goto out; 1954 } 1955 1956 if ((args->flags & NFSMNT_NFSV3) != 0) { 1957 if (xdr_int_decode(&m, fhsizep) != 0 || 1958 *fhsizep > NFSX_V3FHMAX || 1959 *fhsizep <= 0) 1960 goto bad; 1961 } else 1962 *fhsizep = NFSX_V2FH; 1963 1964 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 1965 goto bad; 1966 1967 if ((args->flags & NFSMNT_NFSV3) != 0) { 1968 if (xdr_int_decode(&m, &attribs_present) != 0) 1969 goto bad; 1970 if (attribs_present != 0) { 1971 if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3, 1972 sizeof(u_int32_t) * 21) != 0) 1973 goto bad; 1974 size = fxdr_unsigned(u_int32_t, fattribs.v3[6]); 1975 } 1976 } else { 1977 if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2, 1978 sizeof(u_int32_t) * 17) != 0) 1979 goto bad; 1980 size = fxdr_unsigned(u_int32_t, fattribs.v2[5]); 1981 } 1982 1983 if (nfsv3_diskless.swap_nblks == 0 && size != -1) { 1984 nfsv3_diskless.swap_nblks = size / 1024; 1985 printf("md_lookup_swap: Swap size is %d KB\n", 1986 nfsv3_diskless.swap_nblks); 1987 } 1988 1989 goto out; 1990 1991bad: 1992 error = EBADRPC; 1993 1994out: 1995 m_freem(m); 1996 return error; 1997}
|