1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/param.h> 30 #include <sys/types.h> 31 #include <sys/systm.h> 32 #include <sys/cred.h> 33 #include <sys/user.h> 34 #include <sys/file.h> 35 #include <sys/stream.h> 36 #include <sys/strsubr.h> 37 #include <sys/stropts.h> 38 #include <sys/strsun.h> 39 #include <sys/debug.h> 40 #include <sys/tiuser.h> 41 #include <sys/sockio.h> 42 #include <sys/socket.h> 43 #include <sys/t_kuser.h> 44 #include <sys/utsname.h> 45 #include <sys/systeminfo.h> 46 #include <sys/netconfig.h> 47 #include <sys/ethernet.h> 48 #include <sys/dlpi.h> 49 #include <sys/vfs.h> 50 #include <sys/sysmacros.h> 51 #include <sys/bootconf.h> 52 #include <sys/bootprops.h> 53 #include <sys/cmn_err.h> 54 #include <sys/promif.h> 55 #include <sys/mount.h> 56 57 #include <net/if.h> 58 #include <net/route.h> 59 60 #include <inet/common.h> 61 #include <inet/ip.h> 62 63 #include <netinet/in.h> 64 #include <netinet/arp.h> 65 #include <netinet/dhcp.h> 66 #include <netinet/inetutil.h> 67 #include <dhcp_impl.h> 68 #include <sys/sunos_dhcp_class.h> 69 70 #include <rpc/types.h> 71 #include <rpc/rpc.h> 72 #include <rpc/xdr.h> 73 #include <rpc/auth.h> 74 #include <rpc/clnt.h> 75 #include <rpc/pmap_clnt.h> 76 #include <rpc/pmap_rmt.h> 77 #include <rpc/pmap_prot.h> 78 #include <rpc/bootparam.h> 79 #include <rpc/rpcb_prot.h> 80 81 #include <nfs/nfs.h> 82 #include <nfs/nfs4.h> 83 #include <nfs/nfs_clnt.h> 84 #include <nfs/mount.h> 85 #include <sys/mntent.h> 86 87 #include <sys/kstr.h> 88 #include <sys/sunddi.h> 89 #include <sys/sunldi.h> 90 #include <sys/esunddi.h> 91 92 #include <sys/errno.h> 93 #include <sys/modctl.h> 94 95 /* 96 * RPC timers and retries 97 */ 98 #define PMAP_RETRIES 5 99 #define DEFAULT_RETRIES 3 100 #define GETFILE_RETRIES 2 101 102 #define DEFAULT_TIMEO 3 103 #define WHOAMI_TIMEO 20 104 #define REVARP_TIMEO 5 105 #define GETFILE_TIMEO 1 106 107 /* 108 * These are from the rpcgen'd version of mount.h XXX 109 */ 110 #define MOUNTPROG 100005 111 #define MOUNTPROC_MNT 1 112 #define MOUNTVERS 1 113 #define MOUNTVERS_POSIX 2 114 #define MOUNTVERS3 3 115 116 struct fhstatus { 117 int fhs_status; 118 fhandle_t fhs_fh; 119 }; 120 121 #define FHSIZE3 64 122 123 struct fhandle3 { 124 uint_t fhandle3_len; 125 char *fhandle3_val; 126 }; 127 128 enum mountstat3 { 129 MNT_OK = 0, 130 MNT3ERR_PERM = 1, 131 MNT3ERR_NOENT = 2, 132 MNT3ERR_IO = 5, 133 MNT3ERR_ACCES = 13, 134 MNT3ERR_NOTDIR = 20, 135 MNT3ERR_INVAL = 22, 136 MNT3ERR_NAMETOOLONG = 63, 137 MNT3ERR_NOTSUPP = 10004, 138 MNT3ERR_SERVERFAULT = 10006 139 }; 140 141 struct mountres3_ok { 142 struct fhandle3 fhandle; 143 struct { 144 uint_t auth_flavors_len; 145 int *auth_flavors_val; 146 } auth_flavors; 147 }; 148 149 struct mountres3 { 150 enum mountstat3 fhs_status; 151 union { 152 struct mountres3_ok mountinfo; 153 } mountres3_u; 154 }; 155 156 /* 157 * DLPI address format. 158 */ 159 struct dladdr { 160 uchar_t dl_phys[6]; 161 ushort_t dl_sap; 162 }; 163 164 static struct modlmisc modlmisc = { 165 &mod_miscops, "Boot diskless" 166 }; 167 168 static struct modlinkage modlinkage = { 169 MODREV_1, (void *)&modlmisc, NULL 170 }; 171 172 static int dldebug; 173 174 int 175 _init(void) 176 { 177 return (mod_install(&modlinkage)); 178 } 179 180 int 181 _fini(void) 182 { 183 return (mod_remove(&modlinkage)); 184 } 185 186 int 187 _info(struct modinfo *modinfop) 188 { 189 return (mod_info(&modlinkage, modinfop)); 190 } 191 192 static in_addr_t get_approxnetmask(in_addr_t, in_addr_t); 193 static int set_ifnetmask(TIUSER *, in_addr_t); 194 static enum clnt_stat pmap_rmt_call(struct knetconfig *, struct netbuf *, 195 bool_t, rpcprog_t, rpcvers_t, rpcproc_t, xdrproc_t, 196 caddr_t, xdrproc_t, caddr_t, struct timeval, 197 struct netbuf *); 198 static bool_t myxdr_rmtcall_args(XDR *, struct rmtcallargs *); 199 static bool_t myxdr_rmtcallres(XDR *, struct rmtcallres *); 200 static bool_t myxdr_pmap(XDR *, struct pmap *); 201 static bool_t myxdr_fhstatus(XDR *xdrs, struct fhstatus *fhsp); 202 static bool_t myxdr_fhandle(XDR *xdrs, fhandle_t *fh); 203 static bool_t myxdr_mountres3(XDR *xdrs, struct mountres3 *objp); 204 static bool_t myxdr_mountstat3(XDR *xdrs, enum mountstat3 *objp); 205 static bool_t myxdr_mountres3_ok(XDR *xdrs, 206 struct mountres3_ok *objp); 207 static bool_t myxdr_fhandle3(XDR *xdrs, struct fhandle3 *objp); 208 static enum clnt_stat pmap_kgetport(struct knetconfig *, struct netbuf *, 209 rpcprog_t, rpcvers_t, rpcprot_t); 210 static enum clnt_stat mycallrpc(struct knetconfig *, struct netbuf *, 211 rpcprog_t, rpcvers_t, rpcproc_t, xdrproc_t, 212 char *, xdrproc_t, char *, int, int); 213 static int ifioctl(TIUSER *, int, struct netbuf *); 214 static int getfile(char *, char *, struct netbuf *, char *); 215 static int ping_prog(struct netbuf *, uint_t prog, uint_t vers, 216 int proto, enum clnt_stat *); 217 static int mountnfs(struct netbuf *, char *, char *, 218 fhandle_t *, int *); 219 static int mountnfs3(struct netbuf *, char *, char *, 220 nfs_fh3 *, int *); 221 static int init_mountopts(struct nfs_args *, int, 222 struct knetconfig **, int *); 223 static int revarp_myaddr(TIUSER *); 224 static void revarp_start(ldi_handle_t, struct netbuf *); 225 static void revarpinput(ldi_handle_t, struct netbuf *); 226 static void init_netbuf(struct netbuf *); 227 static void free_netbuf(struct netbuf *); 228 static int rtioctl(TIUSER *, int, struct rtentry *); 229 static int dl_info(ldi_handle_t, dl_info_ack_t *); 230 extern int dl_attach(ldi_handle_t, int); 231 extern int dl_bind(ldi_handle_t, uint32_t, uint32_t, uint32_t, 232 uint32_t); 233 extern int dl_phys_addr(ldi_handle_t, struct ether_addr *); 234 static void init_config(void); 235 236 static void cacheinit(void); 237 static int cacheinfo(char *, int, struct netbuf *, char *, int); 238 static int dlifconfig(TIUSER *, struct in_addr *, struct in_addr *, 239 struct in_addr *); 240 static int setifflags(TIUSER *, uint_t); 241 242 static char *inet_ntoa(struct in_addr); 243 static int inet_aton(char *, uchar_t *); 244 static int isdigit(int); 245 246 /* 247 * Should be in some common 248 * ethernet source file. 249 */ 250 static struct ether_addr etherbroadcastaddr = { 251 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 252 }; 253 254 static struct ether_addr myether; 255 256 /* 257 * "ifname" is the interface name/unit as read from the boot 258 * arguments. 259 * "ndev" is the major device number of the network interface 260 * used to boot from. 261 * "ifunit" it the physical point of attachment for the network 262 * interface used to boot from. 263 * 264 * Both of these are initialized in "init_config()". 265 */ 266 267 static char ifname[IFNAMSIZ]; 268 static char ndev_path[MAXPATHLEN]; 269 static int ifunit; 270 271 /* 272 * XXX these should be shared 273 */ 274 static struct knetconfig dl_udp_netconf = { 275 NC_TPI_CLTS, /* semantics */ 276 NC_INET, /* family */ 277 NC_UDP, /* protocol */ 278 0, /* device */ 279 }; 280 281 static struct knetconfig dl_tcp_netconf = { 282 NC_TPI_COTS, /* semantics */ 283 NC_INET, /* family */ 284 NC_TCP, /* protocol */ 285 0, /* device */ 286 }; 287 288 /* parameters from DHCP or bootparamd */ 289 static PKT_LIST *pl = NULL; 290 static uchar_t server_ip[4]; 291 static uchar_t dhcp_server_ip[4]; 292 static char *server_name_c, *server_path_c; 293 static char rootopts[256]; 294 295 /* 296 * XXX Until we get the nfsmapid deadlocks all fixed, don't allow 297 * XXX a v4 root mount. 298 */ 299 int nfs4_no_diskless_root_support = 1; 300 301 int 302 mount_root(char *name, char *path, int version, struct nfs_args *args, 303 int *vfsflags) 304 { 305 int rc; 306 int proto; 307 struct knetconfig *dl_cf; 308 static int init_done = 0; 309 enum clnt_stat stat; 310 311 if (dldebug) 312 printf("mount_root: name=%s\n", name); 313 314 if (init_done == 0) { 315 init_config(); 316 init_done = 1; 317 } 318 319 init_netbuf(args->addr); 320 321 do { 322 rc = getfile(name, args->hostname, args->addr, path); 323 } while (rc == ETIMEDOUT); 324 325 if (rc) { 326 free_netbuf(args->addr); 327 return (rc); 328 } 329 330 ASSERT(args->knconf->knc_protofmly != NULL); 331 ASSERT(args->knconf->knc_proto != NULL); 332 333 switch (version) { 334 case NFS_VERSION: 335 rc = mountnfs(args->addr, args->hostname, path, 336 (fhandle_t *)args->fh, &proto); 337 break; 338 case NFS_V3: 339 rc = mountnfs3(args->addr, args->hostname, path, 340 (nfs_fh3 *)args->fh, &proto); 341 break; 342 case NFS_V4: 343 ((struct sockaddr_in *)args->addr->buf)->sin_port = 344 htons(NFS_PORT); 345 if (ping_prog(args->addr, NFS_PROGRAM, NFS_V4, IPPROTO_TCP, 346 &stat)) { 347 proto = IPPROTO_TCP; 348 rc = 0; 349 } else { 350 switch (stat) { 351 case RPC_PROGVERSMISMATCH: 352 case RPC_XPRTFAILED: 353 /* 354 * Common failures if v4 unsupported or no TCP 355 */ 356 rc = EPROTONOSUPPORT; 357 break; 358 default: 359 rc = ENXIO; 360 } 361 } 362 if (nfs4_no_diskless_root_support) 363 rc = EPROTONOSUPPORT; 364 break; 365 default: 366 rc = EPROTONOSUPPORT; 367 break; 368 } 369 370 if (rc) 371 goto errout; 372 373 switch (proto) { 374 case IPPROTO_TCP: 375 dl_cf = &dl_tcp_netconf; 376 break; 377 case IPPROTO_UDP: 378 default: 379 dl_cf = &dl_udp_netconf; 380 break; 381 } 382 383 rc = init_mountopts(args, version, &dl_cf, vfsflags); 384 385 /* 386 * Copy knetconfig information from the template, note that the 387 * rdev field has been set by init_config above. 388 */ 389 args->knconf->knc_semantics = dl_cf->knc_semantics; 390 args->knconf->knc_rdev = dl_cf->knc_rdev; 391 (void) strcpy(args->knconf->knc_protofmly, dl_cf->knc_protofmly); 392 (void) strcpy(args->knconf->knc_proto, dl_cf->knc_proto); 393 394 errout: 395 if (dldebug) { 396 if (rc) 397 nfs_perror(rc, "mount_root: mount %s:%s failed: %m\n", 398 args->hostname, path); 399 else 400 printf("mount_root: leaving\n"); 401 } 402 403 return (rc); 404 } 405 406 /* 407 * Call mount daemon on server `sa' to mount path. 408 * `port' is set to nfs port and fh is the fhandle 409 * returned from the server. 410 */ 411 static int 412 mountnfs(struct netbuf *sa, char *server, 413 char *path, fhandle_t *fh, int *proto) 414 { 415 struct fhstatus fhs; 416 enum clnt_stat stat; 417 418 if (dldebug) 419 printf("mountnfs: entered\n"); 420 421 /* 422 * Get the port number for the mount program. 423 * pmap_kgetport first tries a SunOS portmapper 424 * and, if no reply is received, will try a 425 * SVR4 rpcbind. Either way, `sa' is set to 426 * the correct address. 427 */ 428 do { 429 stat = pmap_kgetport(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG, 430 (rpcvers_t)MOUNTVERS, (rpcprot_t)IPPROTO_UDP); 431 432 if (stat == RPC_TIMEDOUT) { 433 cmn_err(CE_WARN, 434 "mountnfs: %s:%s portmap not responding", 435 server, path); 436 } else if (stat != RPC_SUCCESS) { 437 cmn_err(CE_WARN, 438 "mountnfs: pmap_kgetport RPC error %d (%s).", 439 stat, clnt_sperrno(stat)); 440 return (ENXIO); /* XXX */ 441 } 442 } while (stat == RPC_TIMEDOUT); 443 444 /* 445 * The correct port number has been 446 * put into `sa' by pmap_kgetport(). 447 */ 448 do { 449 stat = mycallrpc(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG, 450 (rpcvers_t)MOUNTVERS, (rpcproc_t)MOUNTPROC_MNT, 451 xdr_bp_path_t, (char *)&path, 452 myxdr_fhstatus, (char *)&fhs, 453 DEFAULT_TIMEO, DEFAULT_RETRIES); 454 if (stat == RPC_TIMEDOUT) { 455 cmn_err(CE_WARN, 456 "mountnfs: %s:%s mount server not responding", 457 server, path); 458 } 459 } while (stat == RPC_TIMEDOUT); 460 461 if (stat != RPC_SUCCESS) { 462 cmn_err(CE_WARN, "mountnfs: RPC failed: error %d (%s).", 463 stat, clnt_sperrno(stat)); 464 return (ENXIO); /* XXX */ 465 } 466 467 ((struct sockaddr_in *)sa->buf)->sin_port = htons(NFS_PORT); 468 469 *fh = fhs.fhs_fh; 470 if (fhs.fhs_status != 0) { 471 if (dldebug) 472 printf("mountnfs: fhs_status %d\n", fhs.fhs_status); 473 return (ENXIO); /* XXX */ 474 } 475 476 *proto = IPPROTO_UDP; 477 478 if (ping_prog(sa, NFS_PROGRAM, NFS_VERSION, IPPROTO_TCP, NULL)) 479 *proto = IPPROTO_TCP; 480 481 if (dldebug) 482 printf("mountnfs: leaving\n"); 483 return (0); 484 } 485 486 /* 487 * Call mount daemon on server `sa' to mount path. 488 * `port' is set to nfs port and fh is the fhandle 489 * returned from the server. 490 */ 491 static int 492 mountnfs3(struct netbuf *sa, char *server, 493 char *path, nfs_fh3 *fh, int *proto) 494 { 495 struct mountres3 mountres3; 496 enum clnt_stat stat; 497 int ret = 0; 498 499 if (dldebug) 500 printf("mountnfs3: entered\n"); 501 502 /* 503 * Get the port number for the mount program. 504 * pmap_kgetport first tries a SunOS portmapper 505 * and, if no reply is received, will try a 506 * SVR4 rpcbind. Either way, `sa' is set to 507 * the correct address. 508 */ 509 do { 510 stat = pmap_kgetport(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG, 511 (rpcvers_t)MOUNTVERS3, (rpcprot_t)IPPROTO_UDP); 512 513 if (stat == RPC_PROGVERSMISMATCH) { 514 if (dldebug) 515 printf("mountnfs3: program/version mismatch\n"); 516 return (EPROTONOSUPPORT); /* XXX */ 517 } else if (stat == RPC_TIMEDOUT) { 518 cmn_err(CE_WARN, 519 "mountnfs3: %s:%s portmap not responding", 520 server, path); 521 } else if (stat != RPC_SUCCESS) { 522 cmn_err(CE_WARN, 523 "mountnfs3: pmap_kgetport RPC error %d (%s).", 524 stat, clnt_sperrno(stat)); 525 return (ENXIO); /* XXX */ 526 } 527 } while (stat == RPC_TIMEDOUT); 528 529 mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val = NULL; 530 mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val = NULL; 531 532 /* 533 * The correct port number has been 534 * put into `sa' by pmap_kgetport(). 535 */ 536 do { 537 stat = mycallrpc(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG, 538 (rpcvers_t)MOUNTVERS3, (rpcproc_t)MOUNTPROC_MNT, 539 xdr_bp_path_t, (char *)&path, 540 myxdr_mountres3, (char *)&mountres3, 541 DEFAULT_TIMEO, DEFAULT_RETRIES); 542 if (stat == RPC_TIMEDOUT) { 543 cmn_err(CE_WARN, 544 "mountnfs3: %s:%s mount server not responding", 545 server, path); 546 } 547 } while (stat == RPC_TIMEDOUT); 548 549 if (stat == RPC_PROGVERSMISMATCH) { 550 if (dldebug) 551 printf("mountnfs3: program/version mismatch\n"); 552 ret = EPROTONOSUPPORT; 553 goto out; 554 } 555 if (stat != RPC_SUCCESS) { 556 cmn_err(CE_WARN, "mountnfs3: RPC failed: error %d (%s).", 557 stat, clnt_sperrno(stat)); 558 ret = ENXIO; /* XXX */ 559 goto out; 560 } 561 562 if (mountres3.fhs_status != MNT_OK) { 563 if (dldebug) 564 printf("mountnfs3: fhs_status %d\n", 565 mountres3.fhs_status); 566 ret = ENXIO; /* XXX */ 567 goto out; 568 } 569 570 ((struct sockaddr_in *)sa->buf)->sin_port = htons(NFS_PORT); 571 572 *proto = IPPROTO_UDP; 573 574 if (ping_prog(sa, NFS_PROGRAM, NFS_V3, IPPROTO_TCP, NULL)) { 575 *proto = IPPROTO_TCP; 576 } 577 578 fh->fh3_length = mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len; 579 bcopy(mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val, 580 fh->fh3_u.data, fh->fh3_length); 581 582 out: 583 xdr_free(myxdr_mountres3, (caddr_t)&mountres3); 584 585 if (dldebug) 586 printf("mountnfs3: leaving\n"); 587 return (ret); 588 } 589 590 static int 591 ping_prog(struct netbuf *call_addr, uint_t prog, uint_t vers, int proto, 592 enum clnt_stat *statp) 593 { 594 struct knetconfig *knconf; 595 enum clnt_stat stat; 596 int retries = DEFAULT_RETRIES; 597 598 switch (proto) { 599 case IPPROTO_TCP: 600 knconf = &dl_tcp_netconf; 601 break; 602 case IPPROTO_UDP: 603 knconf = &dl_udp_netconf; 604 break; 605 default: 606 return (0); 607 } 608 609 do { 610 stat = mycallrpc(knconf, call_addr, prog, vers, NULLPROC, 611 xdr_void, NULL, xdr_void, NULL, 612 DEFAULT_TIMEO, DEFAULT_RETRIES); 613 614 if (dldebug) 615 printf("ping_prog: %d return %d (%s)\n", proto, stat, 616 clnt_sperrno(stat)); 617 /* 618 * Special case for TCP, it may "timeout" because it failed 619 * to establish an initial connection but it doesn't 620 * actually retry, so we do the retry. 621 * Persistence pays in diskless. 622 */ 623 } while (stat == RPC_TIMEDOUT && proto == IPPROTO_TCP && retries--); 624 625 if (statp != NULL) 626 *statp = stat; 627 628 if (stat != RPC_SUCCESS) 629 return (0); 630 return (1); 631 } 632 633 static struct netbuf bootparam_addr; 634 static bool_t router_exists = B_FALSE; 635 static in_addr_t client_ip; 636 static in_addr_t client_netmask; 637 638 /* 639 * Returns after filling in the following global variables: 640 * bootparam_addr, 641 * utsname.nodename, 642 * srpc_domain. 643 */ 644 static int 645 whoami(void) 646 { 647 TIUSER *tiptr; 648 struct netbuf sa; 649 struct netbuf req; 650 struct bp_whoami_arg arg; 651 struct bp_whoami_res res; 652 struct timeval tv; 653 enum clnt_stat stat; 654 int rc; 655 size_t namelen; 656 int printed_waiting_msg; 657 in_addr_t boot_serv; 658 659 if ((rc = t_kopen(NULL, dl_udp_netconf.knc_rdev, FREAD|FWRITE, 660 &tiptr, CRED())) != 0) { 661 nfs_perror(rc, "whoami: t_kopen udp failed: %m.\n"); 662 return (rc); 663 } 664 665 /* 666 * Find out our local (IP) address. 667 */ 668 if (rc = revarp_myaddr(tiptr)) { 669 nfs_perror(rc, "whoami: revarp_myaddr failed: %m.\n"); 670 (void) t_kclose(tiptr, 0); 671 return (rc); 672 } 673 674 /* explicitly use the limited broadcast address */ 675 init_netbuf(&sa); 676 ((struct sockaddr_in *)sa.buf)->sin_family = AF_INET; 677 ((struct sockaddr_in *)sa.buf)->sin_addr.s_addr = 678 htonl(INADDR_BROADCAST); 679 sa.len = sizeof (struct sockaddr_in); 680 681 /* 682 * Pick up our local (IP) address. 683 */ 684 init_netbuf(&req); 685 if (rc = ifioctl(tiptr, SIOCGIFADDR, &req)) { 686 nfs_perror(rc, 687 "whoami: couldn't get my IP address: %m.\n"); 688 free_netbuf(&sa); 689 free_netbuf(&req); 690 (void) t_kclose(tiptr, 0); 691 return (rc); 692 } 693 /* 694 * store client's IP address 695 */ 696 client_ip = ((struct sockaddr_in *)req.buf)->sin_addr.s_addr; 697 /* 698 * Set up the arguments expected by bootparamd. 699 */ 700 arg.client_address.address_type = IP_ADDR_TYPE; 701 bcopy(&((struct sockaddr_in *)req.buf)->sin_addr, 702 &arg.client_address.bp_address.ip_addr, sizeof (struct in_addr)); 703 704 free_netbuf(&req); 705 706 init_netbuf(&bootparam_addr); 707 708 /* 709 * Initial retransmission interval 710 */ 711 tv.tv_sec = DEFAULT_TIMEO; 712 tv.tv_usec = 0; 713 res.client_name = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP); 714 res.domain_name = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP); 715 716 /* 717 * Do a broadcast call to find a bootparam daemon that 718 * will tell us our hostname, domainname and any 719 * router that we have to use to talk to our NFS server. 720 */ 721 printed_waiting_msg = 0; 722 do { 723 /* 724 * pmap_rmt_call will first try the SunOS portmapper 725 * and if no reply is received will then try the SVR4 726 * rpcbind. 727 * Either way, `bootparam_addr' will be set to the 728 * correct address for the bootparamd that responds. 729 */ 730 stat = pmap_rmt_call(&dl_udp_netconf, &sa, TRUE, BOOTPARAMPROG, 731 BOOTPARAMVERS, BOOTPARAMPROC_WHOAMI, 732 xdr_bp_whoami_arg, (caddr_t)&arg, 733 xdr_bp_whoami_res, (caddr_t)&res, 734 tv, &bootparam_addr); 735 if (stat == RPC_TIMEDOUT && !printed_waiting_msg) { 736 cmn_err(CE_WARN, 737 "No bootparam server responding; still trying"); 738 printed_waiting_msg = 1; 739 } 740 /* 741 * Retransmission interval for second and subsequent tries. 742 * We expect first pmap_rmt_call to retransmit and backoff to 743 * at least this value. 744 */ 745 tv.tv_sec = WHOAMI_TIMEO; 746 tv.tv_usec = 0; 747 } while (stat == RPC_TIMEDOUT); 748 749 if (printed_waiting_msg) 750 printf("Bootparam response received\n"); 751 752 if (stat != RPC_SUCCESS) { 753 /* XXX should get real error here */ 754 rc = ENXIO; 755 cmn_err(CE_WARN, 756 "whoami: bootparam RPC failed: error %d (%s).", 757 stat, clnt_sperrno(stat)); 758 goto done; 759 } 760 /* 761 * store the boot server IP address 762 */ 763 boot_serv = ((struct sockaddr_in *) 764 bootparam_addr.buf)->sin_addr.s_addr; 765 namelen = strlen(res.client_name); 766 if (namelen > sizeof (utsname.nodename)) { 767 printf("whoami: hostname too long"); 768 rc = ENAMETOOLONG; 769 goto done; 770 } 771 if (namelen != 0) { 772 bcopy(res.client_name, &utsname.nodename, namelen); 773 cmn_err(CE_CONT, "?hostname: %s\n", utsname.nodename); 774 } else { 775 printf("whoami: no host name\n"); 776 rc = ENXIO; 777 goto done; 778 } 779 780 namelen = strlen(res.domain_name); 781 if (namelen != 0) { 782 if (namelen > SYS_NMLN) { 783 printf("whoami: domainname too long"); 784 rc = ENAMETOOLONG; 785 goto done; 786 } 787 bcopy(res.domain_name, &srpc_domain, namelen); 788 cmn_err(CE_CONT, "?domainname: %s\n", srpc_domain); 789 } else { 790 printf("whoami: no domain name\n"); 791 } 792 793 if (res.router_address.address_type == IP_ADDR_TYPE) { 794 struct rtentry rtentry; 795 struct sockaddr_in *sin; 796 in_addr_t ipaddr; 797 798 bcopy(&res.router_address.bp_address.ip_addr, &ipaddr, 799 sizeof (ipaddr)); 800 801 if (ipaddr != (uint32_t)0) { 802 /* 803 * get the netmask for given combination of 804 * router and local ip for a given network. 805 * This is done because at this point client 806 * has no idea of the netmask in the case of 807 * a subnetted or supernetted network. 808 */ 809 client_netmask = get_approxnetmask(ipaddr, client_ip); 810 if ((rc = set_ifnetmask(tiptr, client_netmask)) != 0) { 811 nfs_perror(rc, "whoami: failed to set netmask: " 812 "%m.\n"); 813 goto done; 814 } 815 router_exists = B_TRUE; 816 817 sin = (struct sockaddr_in *)&rtentry.rt_dst; 818 bzero(sin, sizeof (*sin)); 819 sin->sin_family = AF_INET; 820 sin = (struct sockaddr_in *)&rtentry.rt_gateway; 821 bzero(sin, sizeof (*sin)); 822 sin->sin_family = AF_INET; 823 sin->sin_addr.s_addr = ipaddr; 824 rtentry.rt_flags = RTF_GATEWAY | RTF_UP; 825 if (rc = rtioctl(tiptr, SIOCADDRT, &rtentry)) { 826 nfs_perror(rc, 827 "whoami: couldn't add route: %m.\n"); 828 goto done; 829 } 830 } 831 } else { 832 printf("whoami: unknown gateway addr family %d\n", 833 res.router_address.address_type); 834 } 835 if (!router_exists) { 836 /* 837 * router's IP address was not obtained in 838 * WHOAMI RPC request or we could not set 839 * interface netmask by now. Use the client's 840 * and boot server's IP addresses to get the 841 * netmask which will work for this supernet 842 * or subnet. 843 */ 844 client_netmask = get_approxnetmask(boot_serv, client_ip); 845 if ((rc = set_ifnetmask(tiptr, client_netmask)) != 0) { 846 nfs_perror(rc, "whoami: failed to set netmask: %m.\n"); 847 } 848 } 849 850 done: 851 kmem_free(res.client_name, MAX_MACHINE_NAME + 1); 852 kmem_free(res.domain_name, MAX_MACHINE_NAME + 1); 853 free_netbuf(&sa); 854 (void) t_kclose(tiptr, 0); 855 return (rc); 856 } 857 858 /* 859 * set netmask for the interface. 860 */ 861 static int 862 set_ifnetmask(TIUSER *tptr, in_addr_t netmask) 863 { 864 struct sockaddr_in sin; 865 struct netbuf sbuf; 866 TIUSER *tiptr = tptr; 867 int rc; 868 869 if (tptr == NULL) { 870 if ((rc = t_kopen(NULL, dl_udp_netconf.knc_rdev, 871 FREAD|FWRITE, &tiptr, CRED())) != 0) { 872 nfs_perror(rc, "set_ifnetmask: " 873 "t_kopen udp failed: %m.\n"); 874 return (rc); 875 } 876 } 877 sin.sin_addr.s_addr = netmask; 878 sin.sin_family = AF_INET; 879 sbuf.buf = (caddr_t)&sin; 880 sbuf.maxlen = sbuf.len = sizeof (sin); 881 if ((rc = ifioctl(tiptr, SIOCSIFNETMASK, &sbuf)) != 0) { 882 nfs_perror(rc, "set_ifnetmask: cannot set interface " 883 "netmask: %m.\n"); 884 } 885 if (tptr == NULL) { 886 (void) t_kclose(tiptr, 0); 887 } 888 return (rc); 889 } 890 891 /* 892 * guess an approximate netmask for the combination of two IP addresses 893 * within the net. 894 */ 895 static in_addr_t 896 get_approxnetmask(in_addr_t ip1, in_addr_t ip2) 897 { 898 int bit; 899 in_addr_t netmask = 0; 900 901 for (bit = IP_ABITS - 1; bit != 0; bit--) { 902 if ((ip1 >> bit) != (ip2 >> bit)) { 903 break; 904 } 905 netmask |= (1 << bit); 906 } 907 return (netmask); 908 } 909 910 /* 911 * Returns: 912 * 1) The ascii form of our root servers name in `server_name'. 913 * 2) Actual network address of our root server in `server_address'. 914 * 3) Whatever BOOTPARAMPROC_GETFILE returns for the fileid key, in 915 * `server_path'. If fileid is "root", it is the pathname of our 916 * root on the server. 917 */ 918 static int 919 getfile(char *fileid, 920 char *server_name, struct netbuf *server_address, char *server_path) 921 { 922 struct bp_getfile_arg arg; 923 struct bp_getfile_res res; 924 enum clnt_stat stat; 925 int root = FALSE; 926 static int using_cache = FALSE; 927 in_addr_t ipaddr; 928 int timeo = DEFAULT_TIMEO; 929 int retries = DEFAULT_RETRIES; 930 int rc; 931 932 if (dldebug) 933 printf("getfile: entered\n"); 934 935 /* 936 * Call cacheinfo() to see whether we can satisfy this request by using 937 * the information cached in memory by the boot program's DHCP 938 * implementation or boot properties rather than consult BOOTPARAMS, 939 * but while preserving the semantics of getfile(). We know that 940 * the server name is SYS_NMLN in length, and server_path is 941 * MAXPATHLEN (pn_alloc). 942 */ 943 if (strcmp(fileid, "root") == 0) { 944 if (cacheinfo(server_name, SYS_NMLN, server_address, 945 server_path, MAXPATHLEN) == 0) { 946 using_cache = TRUE; 947 return (0); 948 } 949 root = TRUE; 950 } 951 952 /* 953 * If using cache, rootopts is already available. 954 */ 955 if (strcmp(fileid, "rootopts") == 0 && using_cache == TRUE) { 956 return (rootopts[0] != 0 ? 0 : ENXIO); 957 } 958 959 if (bootparam_addr.len == 0) { 960 return (ENXIO); 961 } 962 arg.client_name = (caddr_t)&utsname.nodename; 963 arg.file_id = fileid; 964 965 bzero(&res, sizeof (res)); 966 res.server_name = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP); 967 res.server_path = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP); 968 969 /* 970 * If we are not looking up the root file, we are looking 971 * up a non-critical option that should timeout quickly. 972 */ 973 if (!root) { 974 timeo = GETFILE_TIMEO; 975 retries = GETFILE_RETRIES; 976 } 977 978 /* 979 * bootparam_addr was filled in by the call to 980 * whoami(), so now send an rpc message to the 981 * bootparam daemon requesting our server information. 982 * Use UDP to talk to bootparms. 983 */ 984 stat = mycallrpc(&dl_udp_netconf, &bootparam_addr, 985 (rpcprog_t)BOOTPARAMPROG, (rpcvers_t)BOOTPARAMVERS, 986 (rpcproc_t)BOOTPARAMPROC_GETFILE, 987 xdr_bp_getfile_arg, (caddr_t)&arg, 988 xdr_bp_getfile_res, (caddr_t)&res, 989 timeo, retries); 990 991 if (stat == RPC_SUCCESS) { 992 (void) strcpy(server_name, res.server_name); 993 (void) strcpy(server_path, res.server_path); 994 } 995 996 kmem_free(res.server_name, MAX_MACHINE_NAME + 1); 997 kmem_free(res.server_path, MAX_MACHINE_NAME + 1); 998 999 if (stat != RPC_SUCCESS) { 1000 if (root) 1001 cmn_err(CE_WARN, "getfile: RPC failed: error %d (%s).", 1002 stat, clnt_sperrno(stat)); 1003 return ((stat == RPC_TIMEDOUT) ? ETIMEDOUT : ENXIO); /* XXX */ 1004 } 1005 1006 if (*server_path == '\0') 1007 return (EINVAL); 1008 1009 /* 1010 * If the fileid is "root", we must get back a server name, for 1011 * other parameters a server name is not required 1012 */ 1013 if (!root) { 1014 if (dldebug) 1015 printf("getfile: leaving: non-root\n"); 1016 return (0); 1017 } 1018 1019 if (*server_name == '\0') 1020 return (EINVAL); 1021 1022 switch (res.server_address.address_type) { 1023 case IP_ADDR_TYPE: 1024 /* 1025 * server_address is where we will get our root 1026 * from. 1027 */ 1028 ((struct sockaddr_in *)server_address->buf)->sin_family = 1029 AF_INET; 1030 bcopy(&res.server_address.bp_address.ip_addr, 1031 &ipaddr, sizeof (ipaddr)); 1032 if (ipaddr == 0) 1033 return (EINVAL); 1034 1035 ((struct sockaddr_in *)server_address->buf)->sin_addr.s_addr = 1036 ipaddr; 1037 server_address->len = sizeof (struct sockaddr_in); 1038 /* 1039 * If the router does not exist and root server doesn't 1040 * logically fall in the client's subnet, get the netmask 1041 * from the combination of client & root server IP's. 1042 */ 1043 if (!router_exists && ((client_ip & client_netmask) != 1044 (ipaddr & client_netmask))) { 1045 client_netmask = get_approxnetmask(ipaddr, client_ip); 1046 if ((rc = set_ifnetmask(NULL, client_netmask)) != 0) { 1047 nfs_perror(rc, "getfile: failed to set " 1048 "netmask: %m.\n"); 1049 return (rc); 1050 } 1051 } 1052 break; 1053 1054 default: 1055 printf("getfile: unknown address type %d\n", 1056 res.server_address.address_type); 1057 return (EPROTONOSUPPORT); 1058 } 1059 if (dldebug) 1060 printf("getfile: leaving\n"); 1061 return (0); 1062 } 1063 1064 /* 1065 * If the boot property "bootp-response" exists, then inetboot performed a 1066 * successful DHCP lease acquisition for us and left the resultant ACK packet 1067 * encoded at that location. 1068 * 1069 * If no such property exists (or the information is incomplete or garbled), 1070 * the function returns -1. 1071 */ 1072 int 1073 dhcpinit(void) 1074 { 1075 int rc, i; 1076 char *p; 1077 struct in_addr braddr; 1078 struct in_addr subnet; 1079 DHCP_OPT *doptp; 1080 TIUSER *tiptr; 1081 struct sockaddr_in *sin; 1082 int true_dhcacklen; 1083 char *ackp; 1084 static int once_only = 0; 1085 1086 if (once_only == 1) { 1087 return (0); 1088 } 1089 once_only = 1; 1090 1091 if (dhcack == NULL) { 1092 return (-1); 1093 } 1094 1095 ackp = (char *)(dhcack + IFNAMSIZ); 1096 true_dhcacklen = strlen(ackp); 1097 1098 /* 1099 * Since we expect the "bootp-response" property to have 1100 * been encoded via octet_to_hexascii(), its length should 1101 * always be even. 1102 */ 1103 ASSERT((true_dhcacklen % 2) == 0); 1104 1105 if (dldebug) { 1106 printf("dhcp: dhcack %p, len %d\n", (void *)dhcack, 1107 true_dhcacklen + IFNAMSIZ); 1108 } 1109 1110 pl = kmem_alloc(sizeof (PKT_LIST), KM_SLEEP); 1111 pl->len = true_dhcacklen / 2; 1112 pl->pkt = kmem_alloc(pl->len, KM_SLEEP); 1113 1114 /* 1115 * Store our interface name in the reserved block at the 1116 * head of our packet. For x86, ifname is not initialized 1117 * in the netinstall case and dhcack interface name is 1118 * set in strplumb(). So we only copy the name if ifname 1119 * is set properly. 1120 */ 1121 if (ifname[0]) 1122 (void) strncpy(dhcack, ifname, IFNAMSIZ - 1); 1123 1124 /* skip over the interface name section */ 1125 if (hexascii_to_octet(ackp, true_dhcacklen, (uchar_t *)pl->pkt, 1126 &(pl->len)) != 0) { 1127 cmn_err(CE_WARN, 1128 "dhcp: boot dhcp cache is corrupted."); 1129 kmem_free(pl->pkt, pl->len); 1130 kmem_free(pl, sizeof (PKT_LIST)); 1131 pl = NULL; 1132 return (-1); 1133 } 1134 1135 /* remember the server_ip in dhcack */ 1136 bcopy((uchar_t *)pl->pkt + 20, dhcp_server_ip, 4); 1137 bzero(pl->opts, (DHCP_LAST_OPT + 1) * sizeof (DHCP_OPT *)); 1138 bzero(pl->vs, (VS_OPTION_END - VS_OPTION_START + 1) * 1139 sizeof (DHCP_OPT *)); 1140 1141 if (dhcp_options_scan(pl, B_TRUE) != 0) { 1142 /* garbled packet */ 1143 cmn_err(CE_WARN, "dhcp: DHCP packet parsing failed"); 1144 kmem_free(pl->pkt, pl->len); 1145 kmem_free(pl, sizeof (PKT_LIST)); 1146 pl = NULL; 1147 return (-1); 1148 } 1149 1150 /* set node name */ 1151 if (pl->opts[CD_HOSTNAME] != NULL) { 1152 doptp = pl->opts[CD_HOSTNAME]; 1153 i = doptp->len; 1154 if (i >= SYS_NMLN) { 1155 cmn_err(CE_WARN, "dhcp: Hostname is too long"); 1156 } else { 1157 bcopy(doptp->value, utsname.nodename, i); 1158 utsname.nodename[i] = '\0'; 1159 if (dldebug) { 1160 printf("hostname is %s\n", 1161 utsname.nodename); 1162 } 1163 } 1164 } 1165 1166 /* Set NIS domain name. */ 1167 p = NULL; 1168 if (pl->opts[CD_NIS_DOMAIN] != NULL) { 1169 doptp = pl->opts[CD_NIS_DOMAIN]; 1170 i = doptp->len; 1171 p = (caddr_t)doptp->value; 1172 } 1173 if (p != NULL) { 1174 if (i > SYS_NMLN) { 1175 cmn_err(CE_WARN, 1176 "dhcp: NIS domainname too long."); 1177 } else { 1178 bcopy(p, srpc_domain, i); 1179 srpc_domain[i] = '\0'; 1180 if (dldebug) 1181 printf("dhcp: NIS domain name is %s\n", 1182 srpc_domain); 1183 } 1184 } 1185 1186 /* fetch netmask */ 1187 if (pl->opts[CD_SUBNETMASK] != NULL) { 1188 doptp = pl->opts[CD_SUBNETMASK]; 1189 if (doptp->len != sizeof (struct in_addr)) { 1190 pl->opts[CD_SUBNETMASK] = NULL; 1191 cmn_err(CE_WARN, "dhcp: netmask option malformed"); 1192 } else { 1193 bcopy(doptp->value, &subnet, sizeof (struct in_addr)); 1194 if (dldebug) 1195 printf("dhcp: setting netmask to: %s\n", 1196 inet_ntoa(subnet)); 1197 } 1198 } else { 1199 struct in_addr myIPaddr; 1200 1201 myIPaddr.s_addr = pl->pkt->yiaddr.s_addr; 1202 cmn_err(CE_WARN, "dhcp: no subnet mask supplied - inferring"); 1203 if (IN_CLASSA(ntohl(myIPaddr.s_addr))) 1204 subnet.s_addr = htonl(IN_CLASSA_NET); 1205 else if (IN_CLASSB(ntohl(myIPaddr.s_addr))) 1206 subnet.s_addr = htonl(IN_CLASSB_NET); 1207 else if (IN_CLASSC(ntohl(myIPaddr.s_addr))) 1208 subnet.s_addr = htonl(IN_CLASSC_NET); 1209 else 1210 cmn_err(CE_WARN, "dhcp: bad IP address (%s)", 1211 inet_ntoa(myIPaddr)); 1212 } 1213 /* and broadcast address */ 1214 if (pl->opts[CD_BROADCASTADDR] != NULL) { 1215 doptp = pl->opts[CD_BROADCASTADDR]; 1216 if (doptp->len != sizeof (struct in_addr)) { 1217 pl->opts[CD_BROADCASTADDR] = NULL; 1218 if (dldebug) 1219 printf("dhcp: broadcast address len %d\n", 1220 doptp->len); 1221 } else { 1222 bcopy(doptp->value, &braddr, sizeof (struct in_addr)); 1223 if (dldebug) 1224 printf("dhcp: setting broadcast addr to: %s\n", 1225 inet_ntoa(braddr)); 1226 } 1227 } else { 1228 if (dldebug) 1229 printf("dhcp: no broadcast address supplied\n"); 1230 braddr.s_addr = htonl(INADDR_BROADCAST); 1231 } 1232 /* and plumb and initialize interface */ 1233 if ((rc = t_kopen((file_t *)NULL, dl_udp_netconf.knc_rdev, 1234 FREAD|FWRITE, &tiptr, CRED())) == 0) { 1235 if (rc = dlifconfig(tiptr, &pl->pkt->yiaddr, &subnet, 1236 &braddr)) { 1237 nfs_perror(rc, "dhcp: dlifconfig failed: %m\n"); 1238 kmem_free(pl->pkt, pl->len); 1239 kmem_free(pl, sizeof (PKT_LIST)); 1240 pl = NULL; 1241 (void) t_kclose(tiptr, 0); 1242 return (-1); 1243 } 1244 1245 /* add routes */ 1246 if (pl->opts[CD_ROUTER] != NULL) { 1247 doptp = pl->opts[CD_ROUTER]; 1248 if ((doptp->len % sizeof (struct in_addr)) != 0) { 1249 pl->opts[CD_ROUTER] = NULL; 1250 } else { 1251 int nrouters; 1252 uchar_t *tp; 1253 1254 nrouters = doptp->len / sizeof (struct in_addr); 1255 for (tp = doptp->value, i = 0; i < nrouters; 1256 i++) { 1257 struct in_addr defr; 1258 struct rtentry rtentry; 1259 1260 bcopy(tp, &defr, 1261 sizeof (struct in_addr)); 1262 if (defr.s_addr == 0) 1263 continue; 1264 1265 sin = (struct 1266 sockaddr_in *)&rtentry.rt_dst; 1267 1268 bzero(sin, sizeof (*sin)); 1269 sin->sin_family = AF_INET; 1270 1271 sin = (struct 1272 sockaddr_in *)&rtentry.rt_gateway; 1273 bzero(sin, sizeof (*sin)); 1274 sin->sin_family = AF_INET; 1275 sin->sin_addr = defr; 1276 1277 rtentry.rt_flags = RTF_GATEWAY | RTF_UP; 1278 1279 if (rc = rtioctl(tiptr, SIOCADDRT, 1280 &rtentry)) { 1281 nfs_perror(rc, 1282 "dhcp: couldn't add route " 1283 "to %s: %m.\n", 1284 inet_ntoa(defr)); 1285 continue; 1286 } 1287 if (dldebug) { 1288 printf("dhcp: added route %s\n", 1289 inet_ntoa(defr)); 1290 } 1291 tp += sizeof (struct in_addr); 1292 } 1293 } 1294 } 1295 1296 (void) t_kclose(tiptr, 0); 1297 } 1298 1299 if (dldebug) 1300 printf("dhcpinit: leaving\n"); 1301 1302 return (0); 1303 } 1304 1305 /* 1306 * Initialize nfs mount info from properties and dhcp response. 1307 */ 1308 static void 1309 cacheinit(void) 1310 { 1311 char *str; 1312 DHCP_OPT *doptp; 1313 1314 (void) ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 1315 DDI_PROP_DONTPASS, BP_SERVER_PATH, &server_path_c); 1316 (void) ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 1317 DDI_PROP_DONTPASS, BP_SERVER_NAME, &server_name_c); 1318 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 1319 DDI_PROP_DONTPASS, BP_SERVER_ROOTOPTS, &str) == DDI_SUCCESS) { 1320 (void) strncpy(rootopts, str, 255); 1321 ddi_prop_free(str); 1322 } 1323 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 1324 DDI_PROP_DONTPASS, BP_SERVER_IP, &str) == DDI_SUCCESS) { 1325 if (inet_aton(str, server_ip) != 0) 1326 cmn_err(CE_NOTE, "server_ipaddr %s is invalid\n", 1327 str); 1328 ddi_prop_free(str); 1329 if (dldebug) 1330 printf("server ip is %s\n", 1331 inet_ntoa(*(struct in_addr *)server_ip)); 1332 } 1333 1334 if (pl == NULL) 1335 return; 1336 1337 /* extract root path in server_path */ 1338 if (server_path_c == NULL) { 1339 doptp = pl->vs[VS_NFSMNT_ROOTPATH]; 1340 if (doptp != NULL) { 1341 server_path_c = kmem_alloc(doptp->len + 1, KM_SLEEP); 1342 bcopy(doptp->value, server_path_c, doptp->len); 1343 server_path_c[doptp->len] = '\0'; 1344 if (dldebug) 1345 printf("dhcp: root path %s\n", server_path_c); 1346 } else { 1347 cmn_err(CE_WARN, "dhcp: root server path missing"); 1348 } 1349 } 1350 1351 /* set server_name */ 1352 if (server_name_c == NULL) { 1353 doptp = pl->vs[VS_NFSMNT_ROOTSRVR_NAME]; 1354 if (doptp != NULL) { 1355 server_name_c = kmem_alloc(doptp->len + 1, KM_SLEEP); 1356 bcopy(doptp->value, server_name_c, doptp->len); 1357 server_name_c[doptp->len] = '\0'; 1358 if (dldebug) 1359 printf("dhcp: root server name %s\n", 1360 server_name_c); 1361 } else { 1362 cmn_err(CE_WARN, "dhcp: root server name missing"); 1363 } 1364 } 1365 1366 /* set root server_address */ 1367 if ((*(uint_t *)server_ip) == 0) { 1368 doptp = pl->vs[VS_NFSMNT_ROOTSRVR_IP]; 1369 if (doptp) { 1370 bcopy(doptp->value, server_ip, sizeof (server_ip)); 1371 if (dldebug) { 1372 printf("dhcp: root server IP address %s\n", 1373 inet_ntoa(*(struct in_addr *)server_ip)); 1374 } 1375 } else { 1376 if (dldebug) 1377 cmn_err(CE_CONT, 1378 "dhcp: file server ip address missing," 1379 " fallback to dhcp server as file server"); 1380 bcopy(dhcp_server_ip, server_ip, sizeof (server_ip)); 1381 } 1382 } 1383 1384 /* set root file system mount options */ 1385 if (rootopts[0] == 0) { 1386 doptp = pl->vs[VS_NFSMNT_ROOTOPTS]; 1387 if (doptp != NULL && doptp->len < 255) { 1388 bcopy(doptp->value, rootopts, doptp->len); 1389 rootopts[doptp->len] = '\0'; 1390 if (dldebug) 1391 printf("dhcp: rootopts %s\n", rootopts); 1392 } else if (dldebug) { 1393 printf("dhcp: no rootopts or too long\n"); 1394 /* not an error */ 1395 } 1396 } 1397 1398 /* now we are done with pl, just free it */ 1399 kmem_free(pl->pkt, pl->len); 1400 kmem_free(pl, sizeof (PKT_LIST)); 1401 pl = NULL; 1402 } 1403 1404 static int 1405 cacheinfo(char *name, int namelen, 1406 struct netbuf *server_address, char *rootpath, int pathlen) 1407 { 1408 static int init_done = 0; 1409 struct sockaddr_in *sin; 1410 1411 if (init_done == 0) { 1412 cacheinit(); 1413 init_done = 1; 1414 } 1415 1416 /* server_path is a reliable indicator of cache availability */ 1417 if (server_path_c == NULL) 1418 return (-1); 1419 1420 (void) strncpy(rootpath, server_path_c, pathlen); 1421 if (server_name_c) { 1422 (void) strncpy(name, server_name_c, namelen); 1423 } else { 1424 (void) strncpy(name, "unknown", namelen); 1425 } 1426 1427 sin = (struct sockaddr_in *)server_address->buf; 1428 sin->sin_family = AF_INET; 1429 server_address->len = sizeof (struct sockaddr_in); 1430 bcopy(server_ip, &sin->sin_addr, sizeof (struct in_addr)); 1431 return (0); 1432 } 1433 1434 /* 1435 * Set this interface's IP address and netmask, and bring it up. 1436 */ 1437 static int 1438 dlifconfig(TIUSER *tiptr, struct in_addr *myIPaddr, struct in_addr *mymask, 1439 struct in_addr *mybraddr) 1440 { 1441 int rc; 1442 struct netbuf sbuf; 1443 struct sockaddr_in sin; 1444 1445 if (dldebug) { 1446 printf("dlifconfig: entered\n"); 1447 printf("dlifconfig: addr %s\n", inet_ntoa(*myIPaddr)); 1448 printf("dlifconfig: mask %s\n", inet_ntoa(*mymask)); 1449 printf("dlifconfig: broadcast %s\n", inet_ntoa(*mybraddr)); 1450 } 1451 1452 bcopy(myIPaddr, &sin.sin_addr, sizeof (struct in_addr)); 1453 sin.sin_family = AF_INET; 1454 sbuf.buf = (caddr_t)&sin; 1455 sbuf.maxlen = sbuf.len = sizeof (sin); 1456 if (rc = ifioctl(tiptr, SIOCSIFADDR, &sbuf)) { 1457 nfs_perror(rc, 1458 "dlifconfig: couldn't set interface net address: %m\n"); 1459 return (rc); 1460 } 1461 1462 if (mybraddr->s_addr != INADDR_BROADCAST) { 1463 bcopy(mybraddr, &sin.sin_addr, sizeof (struct in_addr)); 1464 sin.sin_family = AF_INET; 1465 sbuf.buf = (caddr_t)&sin; 1466 sbuf.maxlen = sbuf.len = sizeof (sin); 1467 if (rc = ifioctl(tiptr, SIOCSIFBRDADDR, &sbuf)) { 1468 nfs_perror(rc, 1469 "dlifconfig: couldn't set interface broadcast addr: %m\n"); 1470 return (rc); 1471 } 1472 } 1473 1474 bcopy(mymask, &sin.sin_addr, sizeof (struct in_addr)); 1475 sin.sin_family = AF_INET; 1476 sbuf.buf = (caddr_t)&sin; 1477 sbuf.maxlen = sbuf.len = sizeof (sin); 1478 if (rc = ifioctl(tiptr, SIOCSIFNETMASK, &sbuf)) { 1479 nfs_perror(rc, 1480 "dlifconfig: couldn't set interface net address: %m\n"); 1481 return (rc); 1482 } 1483 1484 /* 1485 * Now turn on the interface. 1486 */ 1487 if (rc = setifflags(tiptr, IFF_UP | IFF_DHCPRUNNING)) { 1488 nfs_perror(rc, 1489 "dlifconfig: couldn't enable network interface: %m\n"); 1490 return (rc); 1491 } 1492 1493 if (dldebug) 1494 printf("dlifconfig: returned\n"); 1495 return (0); 1496 } 1497 1498 static char * 1499 inet_ntoa(struct in_addr in) 1500 { 1501 static char b[18]; 1502 unsigned char *p; 1503 1504 p = (unsigned char *)∈ 1505 (void) sprintf(b, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 1506 return (b); 1507 } 1508 1509 /* We only deal with a.b.c.d decimal format. ip points to 4 byte storage */ 1510 static int 1511 inet_aton(char *ipstr, uchar_t *ip) 1512 { 1513 int i = 0; 1514 uchar_t val[4] = {0}; 1515 char c = *ipstr; 1516 1517 for (;;) { 1518 if (!isdigit(c)) 1519 return (-1); 1520 for (;;) { 1521 if (!isdigit(c)) 1522 break; 1523 val[i] = val[i] * 10 + (c - '0'); 1524 c = *++ipstr; 1525 } 1526 i++; 1527 if (i == 4) 1528 break; 1529 if (c != '.') 1530 return (-1); 1531 c = *++ipstr; 1532 } 1533 if (c != 0) 1534 return (-1); 1535 bcopy(val, ip, 4); 1536 return (0); 1537 } 1538 1539 #define MAX_ADDR_SIZE 128 1540 1541 /* 1542 * Initialize a netbuf suitable for 1543 * describing an address for the 1544 * transport defined by `tiptr'. 1545 */ 1546 static void 1547 init_netbuf(struct netbuf *nbuf) 1548 { 1549 nbuf->buf = kmem_zalloc(MAX_ADDR_SIZE, KM_SLEEP); 1550 nbuf->maxlen = MAX_ADDR_SIZE; 1551 nbuf->len = 0; 1552 } 1553 1554 static void 1555 free_netbuf(struct netbuf *nbuf) 1556 { 1557 kmem_free(nbuf->buf, nbuf->maxlen); 1558 nbuf->buf = NULL; 1559 nbuf->maxlen = 0; 1560 nbuf->len = 0; 1561 } 1562 1563 static int 1564 rtioctl(TIUSER *tiptr, int cmd, struct rtentry *rtentry) 1565 { 1566 struct strioctl iocb; 1567 int rc; 1568 vnode_t *vp; 1569 1570 iocb.ic_cmd = cmd; 1571 iocb.ic_timout = 0; 1572 iocb.ic_len = sizeof (struct rtentry); 1573 iocb.ic_dp = (caddr_t)rtentry; 1574 1575 vp = tiptr->fp->f_vnode; 1576 rc = kstr_ioctl(vp, I_STR, (intptr_t)&iocb); 1577 if (rc) 1578 nfs_perror(rc, "rtioctl: kstr_ioctl failed: %m\n"); 1579 return (rc); 1580 } 1581 1582 /* 1583 * Send an ioctl down the stream defined 1584 * by `tiptr'. 1585 * 1586 * We isolate the ifreq dependencies in here. The 1587 * ioctl really ought to take a netbuf and be of 1588 * type TRANSPARENT - one day. 1589 */ 1590 static int 1591 ifioctl(TIUSER *tiptr, int cmd, struct netbuf *nbuf) 1592 { 1593 struct strioctl iocb; 1594 int rc; 1595 vnode_t *vp; 1596 struct ifreq ifr; 1597 1598 /* 1599 * Now do the one requested. 1600 */ 1601 if (nbuf->len) 1602 ifr.ifr_addr = *(struct sockaddr *)nbuf->buf; 1603 (void) strncpy((caddr_t)&ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 1604 iocb.ic_cmd = cmd; 1605 iocb.ic_timout = 0; 1606 iocb.ic_len = sizeof (ifr); 1607 iocb.ic_dp = (caddr_t)𝔦 1608 1609 vp = tiptr->fp->f_vnode; 1610 rc = kstr_ioctl(vp, I_STR, (intptr_t)&iocb); 1611 if (rc) { 1612 nfs_perror(rc, "ifioctl: kstr_ioctl failed: %m\n"); 1613 return (rc); 1614 } 1615 1616 /* 1617 * Set reply length. 1618 */ 1619 if (nbuf->len == 0) { 1620 /* 1621 * GET type. 1622 */ 1623 nbuf->len = sizeof (struct sockaddr); 1624 *(struct sockaddr *)nbuf->buf = ifr.ifr_addr; 1625 } 1626 1627 return (0); 1628 } 1629 1630 static int 1631 setifflags(TIUSER *tiptr, uint_t value) 1632 { 1633 struct ifreq ifr; 1634 int rc; 1635 struct strioctl iocb; 1636 1637 (void) strncpy((caddr_t)&ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 1638 iocb.ic_cmd = SIOCGIFFLAGS; 1639 iocb.ic_timout = 0; 1640 iocb.ic_len = sizeof (ifr); 1641 iocb.ic_dp = (caddr_t)𝔦 1642 if (rc = kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb)) 1643 return (rc); 1644 1645 ifr.ifr_flags |= value; 1646 iocb.ic_cmd = SIOCSIFFLAGS; 1647 return (kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb)); 1648 } 1649 1650 /* 1651 * REVerse Address Resolution Protocol (revarp) 1652 * is used by a diskless client to find out its 1653 * IP address when all it knows is its Ethernet address. 1654 * 1655 * Open the ethernet driver, attach and bind 1656 * (DL_BIND_REQ) it, and then format a broadcast RARP 1657 * message for it to send. We pick up the reply and 1658 * let the caller set the interface address using SIOCSIFADDR. 1659 */ 1660 static int 1661 revarp_myaddr(TIUSER *tiptr) 1662 { 1663 int rc; 1664 dl_info_ack_t info; 1665 struct sockaddr_in sin; 1666 struct netbuf sbuf; 1667 ldi_handle_t lh; 1668 ldi_ident_t li; 1669 struct netbuf myaddr = {0, 0, NULL}; 1670 1671 if (dldebug) 1672 printf("revarp_myaddr: entered\n"); 1673 1674 if (rc = ldi_ident_from_mod(&modlinkage, &li)) { 1675 nfs_perror(rc, 1676 "revarp_myaddr: ldi_ident_from_mod failed: %m\n"); 1677 return (rc); 1678 } 1679 1680 rc = ldi_open_by_name(ndev_path, FREAD|FWRITE, CRED(), &lh, li); 1681 ldi_ident_release(li); 1682 if (rc) { 1683 nfs_perror(rc, 1684 "revarp_myaddr: ldi_open_by_name failed: %m\n"); 1685 return (rc); 1686 } 1687 1688 if (rc = dl_attach(lh, ifunit)) { 1689 nfs_perror(rc, "revarp_myaddr: dl_attach failed: %m\n"); 1690 (void) ldi_close(lh, FREAD|FWRITE, CRED()); 1691 return (rc); 1692 } 1693 1694 if (rc = dl_bind(lh, ETHERTYPE_REVARP, 0, DL_CLDLS, 0)) { 1695 nfs_perror(rc, "revarp_myaddr: dl_bind failed: %m\n"); 1696 (void) ldi_close(lh, FREAD|FWRITE, CRED()); 1697 return (rc); 1698 } 1699 1700 if (rc = dl_info(lh, &info)) { 1701 nfs_perror(rc, "revarp_myaddr: dl_info failed: %m\n"); 1702 (void) ldi_close(lh, FREAD|FWRITE, CRED()); 1703 return (rc); 1704 } 1705 1706 /* Initialize myaddr */ 1707 myaddr.maxlen = info.dl_addr_length; 1708 myaddr.buf = kmem_alloc(myaddr.maxlen, KM_SLEEP); 1709 1710 revarp_start(lh, &myaddr); 1711 1712 bcopy(myaddr.buf, &sin.sin_addr, myaddr.len); 1713 sin.sin_family = AF_INET; 1714 1715 sbuf.buf = (caddr_t)&sin; 1716 sbuf.maxlen = sbuf.len = sizeof (sin); 1717 if (rc = ifioctl(tiptr, SIOCSIFADDR, &sbuf)) { 1718 nfs_perror(rc, 1719 "revarp_myaddr: couldn't set interface net address: %m\n"); 1720 (void) ldi_close(lh, FREAD|FWRITE, CRED()); 1721 kmem_free(myaddr.buf, myaddr.maxlen); 1722 return (rc); 1723 } 1724 1725 /* Now turn on the interface */ 1726 if (rc = setifflags(tiptr, IFF_UP)) { 1727 nfs_perror(rc, 1728 "revarp_myaddr: couldn't enable network interface: %m\n"); 1729 } 1730 1731 (void) ldi_close(lh, FREAD|FWRITE, CRED()); 1732 kmem_free(myaddr.buf, myaddr.maxlen); 1733 return (rc); 1734 } 1735 1736 static void 1737 revarp_start(ldi_handle_t lh, struct netbuf *myaddr) 1738 { 1739 struct ether_arp *ea; 1740 int rc; 1741 dl_unitdata_req_t *dl_udata; 1742 mblk_t *bp; 1743 mblk_t *mp; 1744 struct dladdr *dlsap; 1745 static int done = 0; 1746 1747 if (dl_phys_addr(lh, &myether) != 0) { 1748 /* Fallback using per-node address */ 1749 (void) localetheraddr((struct ether_addr *)NULL, &myether); 1750 cmn_err(CE_CONT, "?DLPI failed to get Ethernet address. Using " 1751 "system wide Ethernet address %s\n", 1752 ether_sprintf(&myether)); 1753 } 1754 1755 getreply: 1756 if (myaddr->len != 0) { 1757 cmn_err(CE_CONT, "?Found my IP address: %x (%d.%d.%d.%d)\n", 1758 *(int *)myaddr->buf, 1759 (uchar_t)myaddr->buf[0], (uchar_t)myaddr->buf[1], 1760 (uchar_t)myaddr->buf[2], (uchar_t)myaddr->buf[3]); 1761 return; 1762 } 1763 1764 if (done++ == 0) 1765 cmn_err(CE_CONT, "?Requesting Internet address for %s\n", 1766 ether_sprintf(&myether)); 1767 1768 /* 1769 * Send another RARP request. 1770 */ 1771 if ((mp = allocb(sizeof (dl_unitdata_req_t) + sizeof (*dlsap), 1772 BPRI_HI)) == NULL) { 1773 cmn_err(CE_WARN, "revarp_myaddr: allocb no memory"); 1774 return; 1775 } 1776 if ((bp = allocb(sizeof (struct ether_arp), BPRI_HI)) == NULL) { 1777 cmn_err(CE_WARN, "revarp_myaddr: allocb no memory"); 1778 return; 1779 } 1780 1781 /* 1782 * Format the transmit request part. 1783 */ 1784 mp->b_datap->db_type = M_PROTO; 1785 dl_udata = (dl_unitdata_req_t *)mp->b_wptr; 1786 mp->b_wptr += sizeof (dl_unitdata_req_t) + sizeof (*dlsap); 1787 dl_udata->dl_primitive = DL_UNITDATA_REQ; 1788 dl_udata->dl_dest_addr_length = sizeof (*dlsap); 1789 dl_udata->dl_dest_addr_offset = sizeof (*dl_udata); 1790 dl_udata->dl_priority.dl_min = 0; 1791 dl_udata->dl_priority.dl_max = 0; 1792 1793 dlsap = (struct dladdr *)(mp->b_rptr + sizeof (*dl_udata)); 1794 bcopy(ðerbroadcastaddr, &dlsap->dl_phys, 1795 sizeof (etherbroadcastaddr)); 1796 dlsap->dl_sap = ETHERTYPE_REVARP; 1797 1798 /* 1799 * Format the actual REVARP request. 1800 */ 1801 bzero(bp->b_wptr, sizeof (struct ether_arp)); 1802 ea = (struct ether_arp *)bp->b_wptr; 1803 bp->b_wptr += sizeof (struct ether_arp); 1804 ea->arp_hrd = htons(ARPHRD_ETHER); 1805 ea->arp_pro = htons(ETHERTYPE_IP); 1806 ea->arp_hln = sizeof (ea->arp_sha); /* hardware address length */ 1807 ea->arp_pln = sizeof (ea->arp_spa); /* protocol address length */ 1808 ea->arp_op = htons(REVARP_REQUEST); 1809 ether_copy(&myether, &ea->arp_sha); 1810 ether_copy(&myether, &ea->arp_tha); 1811 1812 mp->b_cont = bp; 1813 1814 if ((rc = ldi_putmsg(lh, mp)) != 0) { 1815 nfs_perror(rc, "revarp_start: ldi_putmsg failed: %m\n"); 1816 return; 1817 } 1818 revarpinput(lh, myaddr); 1819 1820 goto getreply; 1821 } 1822 1823 /* 1824 * Client side Reverse-ARP input 1825 * Server side is handled by user level server 1826 */ 1827 static void 1828 revarpinput(ldi_handle_t lh, struct netbuf *myaddr) 1829 { 1830 struct ether_arp *ea; 1831 mblk_t *bp; 1832 mblk_t *mp; 1833 int rc; 1834 timestruc_t tv, give_up, now; 1835 1836 /* 1837 * Choose the time at which we will give up, and resend our 1838 * request. 1839 */ 1840 gethrestime(&give_up); 1841 give_up.tv_sec += REVARP_TIMEO; 1842 wait: 1843 /* 1844 * Compute new timeout value. 1845 */ 1846 tv = give_up; 1847 gethrestime(&now); 1848 timespecsub(&tv, &now); 1849 /* 1850 * If we don't have at least one full second remaining, give up. 1851 * This means we might wait only just over 4.0 seconds, but that's 1852 * okay. 1853 */ 1854 if (tv.tv_sec <= 0) 1855 return; 1856 rc = ldi_getmsg(lh, &mp, &tv); 1857 if (rc == ETIME) { 1858 goto out; 1859 } else if (rc != 0) { 1860 nfs_perror(rc, "revarpinput: ldi_getmsg failed: %m\n"); 1861 return; 1862 } 1863 1864 if (mp->b_cont == NULL) { 1865 printf("revarpinput: b_cont == NULL\n"); 1866 goto out; 1867 } 1868 1869 if (mp->b_datap->db_type != M_PROTO) { 1870 printf("revarpinput: bad header type %d\n", 1871 mp->b_datap->db_type); 1872 goto out; 1873 } 1874 1875 bp = mp->b_cont; 1876 1877 if (bp->b_wptr - bp->b_rptr < sizeof (*ea)) { 1878 printf("revarpinput: bad data len %d, expect %d\n", 1879 (int)(bp->b_wptr - bp->b_rptr), (int)sizeof (*ea)); 1880 goto out; 1881 } 1882 1883 ea = (struct ether_arp *)bp->b_rptr; 1884 1885 if ((ushort_t)ntohs(ea->arp_pro) != ETHERTYPE_IP) { 1886 /* We could have received another broadcast arp packet. */ 1887 if (dldebug) 1888 printf("revarpinput: bad type %x\n", 1889 (ushort_t)ntohs(ea->arp_pro)); 1890 freemsg(mp); 1891 goto wait; 1892 } 1893 if ((ushort_t)ntohs(ea->arp_op) != REVARP_REPLY) { 1894 /* We could have received a broadcast arp request. */ 1895 if (dldebug) 1896 printf("revarpinput: bad op %x\n", 1897 (ushort_t)ntohs(ea->arp_op)); 1898 freemsg(mp); 1899 goto wait; 1900 } 1901 1902 if (!ether_cmp(&ea->arp_tha, &myether)) { 1903 bcopy(&ea->arp_tpa, myaddr->buf, sizeof (ea->arp_tpa)); 1904 myaddr->len = sizeof (ea->arp_tpa); 1905 } else { 1906 /* We could have gotten a broadcast arp response. */ 1907 if (dldebug) 1908 printf("revarpinput: got reply, but not my address\n"); 1909 freemsg(mp); 1910 goto wait; 1911 } 1912 out: 1913 freemsg(mp); 1914 } 1915 1916 /* 1917 * From rpcsvc/mountxdr.c in SunOS. We can't 1918 * put this into the rpc directory because 1919 * it calls xdr_fhandle() which is in a 1920 * loadable module. 1921 */ 1922 static bool_t 1923 myxdr_fhstatus(XDR *xdrs, struct fhstatus *fhsp) 1924 { 1925 1926 if (!xdr_int(xdrs, &fhsp->fhs_status)) 1927 return (FALSE); 1928 if (fhsp->fhs_status == 0) { 1929 if (!myxdr_fhandle(xdrs, &fhsp->fhs_fh)) 1930 return (FALSE); 1931 } 1932 return (TRUE); 1933 } 1934 1935 /* 1936 * From nfs_xdr.c. 1937 * 1938 * File access handle 1939 * The fhandle struct is treated a opaque data on the wire 1940 */ 1941 static bool_t 1942 myxdr_fhandle(XDR *xdrs, fhandle_t *fh) 1943 { 1944 return (xdr_opaque(xdrs, (caddr_t)fh, NFS_FHSIZE)); 1945 } 1946 1947 static bool_t 1948 myxdr_mountres3(XDR *xdrs, struct mountres3 *objp) 1949 { 1950 if (!myxdr_mountstat3(xdrs, &objp->fhs_status)) 1951 return (FALSE); 1952 switch (objp->fhs_status) { 1953 case MNT_OK: 1954 if (!myxdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo)) 1955 return (FALSE); 1956 break; 1957 default: 1958 break; 1959 } 1960 return (TRUE); 1961 } 1962 1963 static bool_t 1964 myxdr_mountstat3(XDR *xdrs, enum mountstat3 *objp) 1965 { 1966 return (xdr_enum(xdrs, (enum_t *)objp)); 1967 } 1968 1969 static bool_t 1970 myxdr_mountres3_ok(XDR *xdrs, struct mountres3_ok *objp) 1971 { 1972 if (!myxdr_fhandle3(xdrs, &objp->fhandle)) 1973 return (FALSE); 1974 if (!xdr_array(xdrs, (char **)&objp->auth_flavors.auth_flavors_val, 1975 (uint_t *)&objp->auth_flavors.auth_flavors_len, ~0, 1976 sizeof (int), (xdrproc_t)xdr_int)) 1977 return (FALSE); 1978 return (TRUE); 1979 } 1980 1981 static bool_t 1982 myxdr_fhandle3(XDR *xdrs, struct fhandle3 *objp) 1983 { 1984 return (xdr_bytes(xdrs, (char **)&objp->fhandle3_val, 1985 (uint_t *)&objp->fhandle3_len, FHSIZE3)); 1986 } 1987 1988 /* 1989 * From SunOS pmap_clnt.c 1990 * 1991 * Port mapper routines: 1992 * pmap_kgetport() - get port number. 1993 * pmap_rmt_call() - indirect call via port mapper. 1994 * 1995 */ 1996 static enum clnt_stat 1997 pmap_kgetport(struct knetconfig *knconf, struct netbuf *call_addr, 1998 rpcprog_t prog, rpcvers_t vers, rpcprot_t prot) 1999 { 2000 ushort_t port; 2001 int tries; 2002 enum clnt_stat stat; 2003 struct pmap pmap_parms; 2004 RPCB rpcb_parms; 2005 char *ua = NULL; 2006 2007 port = 0; 2008 2009 ((struct sockaddr_in *)call_addr->buf)->sin_port = htons(PMAPPORT); 2010 2011 pmap_parms.pm_prog = prog; 2012 pmap_parms.pm_vers = vers; 2013 pmap_parms.pm_prot = prot; 2014 pmap_parms.pm_port = 0; 2015 for (tries = 0; tries < 5; tries++) { 2016 stat = mycallrpc(knconf, call_addr, 2017 PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, 2018 myxdr_pmap, (char *)&pmap_parms, 2019 xdr_u_short, (char *)&port, 2020 DEFAULT_TIMEO, DEFAULT_RETRIES); 2021 2022 if (stat != RPC_TIMEDOUT) 2023 break; 2024 cmn_err(CE_WARN, 2025 "pmap_kgetport: Portmapper not responding; still trying"); 2026 } 2027 2028 if (stat == RPC_PROGUNAVAIL) { 2029 cmn_err(CE_WARN, 2030 "pmap_kgetport: Portmapper failed - trying rpcbind"); 2031 2032 rpcb_parms.r_prog = prog; 2033 rpcb_parms.r_vers = vers; 2034 rpcb_parms.r_netid = knconf->knc_proto; 2035 rpcb_parms.r_addr = rpcb_parms.r_owner = ""; 2036 2037 for (tries = 0; tries < 5; tries++) { 2038 stat = mycallrpc(knconf, call_addr, 2039 RPCBPROG, RPCBVERS, RPCBPROC_GETADDR, 2040 xdr_rpcb, (char *)&rpcb_parms, 2041 xdr_wrapstring, (char *)&ua, 2042 DEFAULT_TIMEO, DEFAULT_RETRIES); 2043 2044 if (stat != RPC_TIMEDOUT) 2045 break; 2046 cmn_err(CE_WARN, 2047 "pmap_kgetport: rpcbind not responding; still trying"); 2048 } 2049 2050 if (stat == RPC_SUCCESS) { 2051 if ((ua != NULL) && (ua[0] != NULL)) { 2052 port = rpc_uaddr2port(AF_INET, ua); 2053 } else { 2054 /* Address unknown */ 2055 stat = RPC_PROGUNAVAIL; 2056 } 2057 } 2058 } 2059 2060 if (stat == RPC_SUCCESS) 2061 ((struct sockaddr_in *)call_addr->buf)->sin_port = ntohs(port); 2062 2063 return (stat); 2064 } 2065 2066 /* 2067 * pmapper remote-call-service interface. 2068 * This routine is used to call the pmapper remote call service 2069 * which will look up a service program in the port maps, and then 2070 * remotely call that routine with the given parameters. This allows 2071 * programs to do a lookup and call in one step. In addition to the call_addr, 2072 * the caller provides a boolean hint about the destination address (TRUE if 2073 * address is a broadcast address, FALSE otherwise). 2074 * 2075 * On return, `call addr' contains the port number for the 2076 * service requested, and `resp_addr' contains its IP address. 2077 */ 2078 static enum clnt_stat 2079 pmap_rmt_call(struct knetconfig *knconf, struct netbuf *call_addr, 2080 bool_t bcast, rpcprog_t progn, rpcvers_t versn, rpcproc_t procn, 2081 xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp, 2082 struct timeval tout, struct netbuf *resp_addr) 2083 { 2084 CLIENT *cl; 2085 enum clnt_stat stat; 2086 rpcport_t port; 2087 int rc; 2088 struct rmtcallargs pmap_args; 2089 struct rmtcallres pmap_res; 2090 struct rpcb_rmtcallargs rpcb_args; 2091 struct rpcb_rmtcallres rpcb_res; 2092 char ua[100]; /* XXX */ 2093 2094 ((struct sockaddr_in *)call_addr->buf)->sin_port = htons(PMAPPORT); 2095 2096 rc = clnt_tli_kcreate(knconf, call_addr, PMAPPROG, PMAPVERS, 2097 0, PMAP_RETRIES, CRED(), &cl); 2098 if (rc != 0) { 2099 nfs_perror(rc, 2100 "pmap_rmt_call: clnt_tli_kcreate failed: %m\n"); 2101 return (RPC_SYSTEMERROR); /* XXX */ 2102 } 2103 if (cl == (CLIENT *)NULL) { 2104 panic("pmap_rmt_call: clnt_tli_kcreate failed"); 2105 /* NOTREACHED */ 2106 } 2107 2108 (void) CLNT_CONTROL(cl, CLSET_BCAST, (char *)&bcast); 2109 2110 pmap_args.prog = progn; 2111 pmap_args.vers = versn; 2112 pmap_args.proc = procn; 2113 pmap_args.args_ptr = argsp; 2114 pmap_args.xdr_args = xdrargs; 2115 pmap_res.port_ptr = &port; 2116 pmap_res.results_ptr = resp; 2117 pmap_res.xdr_results = xdrres; 2118 stat = clnt_clts_kcallit_addr(cl, PMAPPROC_CALLIT, 2119 myxdr_rmtcall_args, (caddr_t)&pmap_args, 2120 myxdr_rmtcallres, (caddr_t)&pmap_res, 2121 tout, resp_addr); 2122 2123 if (stat == RPC_SUCCESS) { 2124 ((struct sockaddr_in *)resp_addr->buf)->sin_port = 2125 htons((ushort_t)port); 2126 } 2127 CLNT_DESTROY(cl); 2128 2129 if (stat != RPC_PROGUNAVAIL) 2130 return (stat); 2131 2132 cmn_err(CE_WARN, "pmap_rmt_call: Portmapper failed - trying rpcbind"); 2133 2134 rc = clnt_tli_kcreate(knconf, call_addr, RPCBPROG, RPCBVERS, 2135 0, PMAP_RETRIES, CRED(), &cl); 2136 if (rc != 0) { 2137 nfs_perror(rc, "pmap_rmt_call: clnt_tli_kcreate failed: %m\n"); 2138 return (RPC_SYSTEMERROR); /* XXX */ 2139 } 2140 2141 if (cl == NULL) { 2142 panic("pmap_rmt_call: clnt_tli_kcreate failed"); 2143 /* NOTREACHED */ 2144 } 2145 2146 rpcb_args.prog = progn; 2147 rpcb_args.vers = versn; 2148 rpcb_args.proc = procn; 2149 rpcb_args.args_ptr = argsp; 2150 rpcb_args.xdr_args = xdrargs; 2151 rpcb_res.addr_ptr = ua; 2152 rpcb_res.results_ptr = resp; 2153 rpcb_res.xdr_results = xdrres; 2154 stat = clnt_clts_kcallit_addr(cl, PMAPPROC_CALLIT, 2155 xdr_rpcb_rmtcallargs, (caddr_t)&rpcb_args, 2156 xdr_rpcb_rmtcallres, (caddr_t)&rpcb_res, 2157 tout, resp_addr); 2158 2159 if (stat == RPC_SUCCESS) 2160 ((struct sockaddr_in *)resp_addr->buf)->sin_port = 2161 rpc_uaddr2port(AF_INET, ua); 2162 CLNT_DESTROY(cl); 2163 2164 return (stat); 2165 } 2166 2167 /* 2168 * XDR remote call arguments 2169 * written for XDR_ENCODE direction only 2170 */ 2171 static bool_t 2172 myxdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap) 2173 { 2174 uint_t lenposition; 2175 uint_t argposition; 2176 uint_t position; 2177 2178 if (xdr_rpcprog(xdrs, &(cap->prog)) && 2179 xdr_rpcvers(xdrs, &(cap->vers)) && 2180 xdr_rpcproc(xdrs, &(cap->proc))) { 2181 lenposition = XDR_GETPOS(xdrs); 2182 if (!xdr_u_int(xdrs, &cap->arglen)) 2183 return (FALSE); 2184 argposition = XDR_GETPOS(xdrs); 2185 if (!(*(cap->xdr_args))(xdrs, cap->args_ptr)) 2186 return (FALSE); 2187 position = XDR_GETPOS(xdrs); 2188 cap->arglen = (uint_t)position - (uint_t)argposition; 2189 XDR_SETPOS(xdrs, lenposition); 2190 if (!xdr_u_int(xdrs, &cap->arglen)) 2191 return (FALSE); 2192 XDR_SETPOS(xdrs, position); 2193 return (TRUE); 2194 } 2195 return (FALSE); 2196 } 2197 2198 /* 2199 * XDR remote call results 2200 * written for XDR_DECODE direction only 2201 */ 2202 static bool_t 2203 myxdr_rmtcallres(XDR *xdrs, struct rmtcallres *crp) 2204 { 2205 caddr_t port_ptr; 2206 2207 port_ptr = (caddr_t)crp->port_ptr; 2208 if (xdr_reference(xdrs, &port_ptr, sizeof (uint_t), xdr_u_int) && 2209 xdr_u_int(xdrs, &crp->resultslen)) { 2210 crp->port_ptr = (rpcport_t *)port_ptr; 2211 return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); 2212 } 2213 return (FALSE); 2214 } 2215 2216 static bool_t 2217 myxdr_pmap(XDR *xdrs, struct pmap *regs) 2218 { 2219 if (xdr_rpcprog(xdrs, ®s->pm_prog) && 2220 xdr_rpcvers(xdrs, ®s->pm_vers) && 2221 xdr_rpcprot(xdrs, ®s->pm_prot)) 2222 return (xdr_rpcport(xdrs, ®s->pm_port)); 2223 2224 return (FALSE); 2225 } 2226 2227 2228 /* 2229 * From SunOS callrpc.c 2230 */ 2231 static enum clnt_stat 2232 mycallrpc(struct knetconfig *knconf, struct netbuf *call_addr, 2233 rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum, 2234 xdrproc_t inproc, char *in, xdrproc_t outproc, char *out, 2235 int timeo, int retries) 2236 { 2237 CLIENT *cl; 2238 struct timeval tv; 2239 enum clnt_stat cl_stat; 2240 int rc; 2241 2242 rc = clnt_tli_kcreate(knconf, call_addr, prognum, versnum, 2243 0, retries, CRED(), &cl); 2244 if (rc) { 2245 nfs_perror(rc, "mycallrpc: clnt_tli_kcreate failed: %m\n"); 2246 return (RPC_SYSTEMERROR); /* XXX */ 2247 } 2248 tv.tv_sec = timeo; 2249 tv.tv_usec = 0; 2250 cl_stat = CLNT_CALL(cl, procnum, inproc, in, outproc, out, tv); 2251 AUTH_DESTROY(cl->cl_auth); 2252 CLNT_DESTROY(cl); 2253 return (cl_stat); 2254 } 2255 2256 static int 2257 dl_info(ldi_handle_t lh, dl_info_ack_t *info) 2258 { 2259 dl_info_req_t *info_req; 2260 dl_error_ack_t *error_ack; 2261 union DL_primitives *dl_prim; 2262 mblk_t *mp; 2263 int error; 2264 2265 if ((mp = allocb(sizeof (dl_info_req_t), BPRI_MED)) == NULL) { 2266 cmn_err(CE_WARN, "dl_info: allocb failed"); 2267 return (ENOSR); 2268 } 2269 mp->b_datap->db_type = M_PROTO; 2270 2271 info_req = (dl_info_req_t *)mp->b_wptr; 2272 mp->b_wptr += sizeof (dl_info_req_t); 2273 info_req->dl_primitive = DL_INFO_REQ; 2274 2275 (void) ldi_putmsg(lh, mp); 2276 if ((error = ldi_getmsg(lh, &mp, (timestruc_t *)NULL)) != 0) { 2277 nfs_perror(error, "dl_info: ldi_getmsg failed: %m\n"); 2278 return (error); 2279 } 2280 2281 dl_prim = (union DL_primitives *)mp->b_rptr; 2282 switch (dl_prim->dl_primitive) { 2283 case DL_INFO_ACK: 2284 if ((mp->b_wptr-mp->b_rptr) < sizeof (dl_info_ack_t)) { 2285 printf("dl_info: DL_INFO_ACK protocol error\n"); 2286 break; 2287 } 2288 *info = *(dl_info_ack_t *)mp->b_rptr; 2289 freemsg(mp); 2290 return (0); 2291 2292 case DL_ERROR_ACK: 2293 if ((mp->b_wptr-mp->b_rptr) < sizeof (dl_error_ack_t)) { 2294 printf("dl_info: DL_ERROR_ACK protocol error\n"); 2295 break; 2296 } 2297 2298 error_ack = (dl_error_ack_t *)dl_prim; 2299 printf("dl_info: DLPI error %u\n", error_ack->dl_errno); 2300 break; 2301 2302 default: 2303 printf("dl_bind: bad ACK header %u\n", dl_prim->dl_primitive); 2304 break; 2305 } 2306 2307 /* 2308 * Error return only. 2309 */ 2310 freemsg(mp); 2311 return (-1); 2312 } 2313 2314 /* 2315 * The network device we will use to boot from is plumbed. Extract the details 2316 * from rootfs. 2317 */ 2318 static void 2319 init_config(void) 2320 { 2321 (void) strlcpy(ndev_path, rootfs.bo_devname, sizeof (ndev_path)); 2322 (void) strlcpy(ifname, rootfs.bo_ifname, sizeof (ifname)); 2323 ifunit = rootfs.bo_ppa; 2324 2325 /* 2326 * Assumes only one linkage array element. 2327 */ 2328 dl_udp_netconf.knc_rdev = 2329 makedevice(clone_major, ddi_name_to_major("udp")); 2330 dl_tcp_netconf.knc_rdev = 2331 makedevice(clone_major, ddi_name_to_major("tcp")); 2332 2333 /* 2334 * Now we bringup the interface. 2335 * Try cached dhcp response first. If it fails, do rarp. 2336 */ 2337 if (dhcpinit() != 0 && whoami() != 0) 2338 cmn_err(CE_WARN, 2339 "%s: no response from interface", ifname); 2340 else if (dldebug) 2341 printf("init_config: ifname %s is up\n", ifname); 2342 } 2343 2344 /* 2345 * These options are duplicated in cmd/fs.d/nfs/mount/mount.c 2346 * Changes must be made to both lists. 2347 */ 2348 static char *optlist[] = { 2349 #define OPT_RO 0 2350 MNTOPT_RO, 2351 #define OPT_RW 1 2352 MNTOPT_RW, 2353 #define OPT_QUOTA 2 2354 MNTOPT_QUOTA, 2355 #define OPT_NOQUOTA 3 2356 MNTOPT_NOQUOTA, 2357 #define OPT_SOFT 4 2358 MNTOPT_SOFT, 2359 #define OPT_HARD 5 2360 MNTOPT_HARD, 2361 #define OPT_SUID 6 2362 MNTOPT_SUID, 2363 #define OPT_NOSUID 7 2364 MNTOPT_NOSUID, 2365 #define OPT_GRPID 8 2366 MNTOPT_GRPID, 2367 #define OPT_REMOUNT 9 2368 MNTOPT_REMOUNT, 2369 #define OPT_NOSUB 10 2370 MNTOPT_NOSUB, 2371 #define OPT_INTR 11 2372 MNTOPT_INTR, 2373 #define OPT_NOINTR 12 2374 MNTOPT_NOINTR, 2375 #define OPT_PORT 13 2376 MNTOPT_PORT, 2377 #define OPT_SECURE 14 2378 MNTOPT_SECURE, 2379 #define OPT_RSIZE 15 2380 MNTOPT_RSIZE, 2381 #define OPT_WSIZE 16 2382 MNTOPT_WSIZE, 2383 #define OPT_TIMEO 17 2384 MNTOPT_TIMEO, 2385 #define OPT_RETRANS 18 2386 MNTOPT_RETRANS, 2387 #define OPT_ACTIMEO 19 2388 MNTOPT_ACTIMEO, 2389 #define OPT_ACREGMIN 20 2390 MNTOPT_ACREGMIN, 2391 #define OPT_ACREGMAX 21 2392 MNTOPT_ACREGMAX, 2393 #define OPT_ACDIRMIN 22 2394 MNTOPT_ACDIRMIN, 2395 #define OPT_ACDIRMAX 23 2396 MNTOPT_ACDIRMAX, 2397 #define OPT_BG 24 2398 MNTOPT_BG, 2399 #define OPT_FG 25 2400 MNTOPT_FG, 2401 #define OPT_RETRY 26 2402 MNTOPT_RETRY, 2403 #define OPT_NOAC 27 2404 MNTOPT_NOAC, 2405 #define OPT_NOCTO 28 2406 MNTOPT_NOCTO, 2407 #define OPT_LLOCK 29 2408 MNTOPT_LLOCK, 2409 #define OPT_POSIX 30 2410 MNTOPT_POSIX, 2411 #define OPT_VERS 31 2412 MNTOPT_VERS, 2413 #define OPT_PROTO 32 2414 MNTOPT_PROTO, 2415 #define OPT_SEMISOFT 33 2416 MNTOPT_SEMISOFT, 2417 #define OPT_NOPRINT 34 2418 MNTOPT_NOPRINT, 2419 #define OPT_SEC 35 2420 MNTOPT_SEC, 2421 #define OPT_LARGEFILES 36 2422 MNTOPT_LARGEFILES, 2423 #define OPT_NOLARGEFILES 37 2424 MNTOPT_NOLARGEFILES, 2425 #define OPT_PUBLIC 38 2426 MNTOPT_PUBLIC, 2427 #define OPT_DIRECTIO 39 2428 MNTOPT_FORCEDIRECTIO, 2429 #define OPT_NODIRECTIO 40 2430 MNTOPT_NOFORCEDIRECTIO, 2431 #define OPT_XATTR 41 2432 MNTOPT_XATTR, 2433 #define OPT_NOXATTR 42 2434 MNTOPT_NOXATTR, 2435 #define OPT_DEVICES 43 2436 MNTOPT_DEVICES, 2437 #define OPT_NODEVICES 44 2438 MNTOPT_NODEVICES, 2439 #define OPT_SETUID 45 2440 MNTOPT_SETUID, 2441 #define OPT_NOSETUID 46 2442 MNTOPT_NOSETUID, 2443 #define OPT_EXEC 47 2444 MNTOPT_EXEC, 2445 #define OPT_NOEXEC 48 2446 MNTOPT_NOEXEC, 2447 NULL 2448 }; 2449 2450 static int 2451 isdigit(int ch) 2452 { 2453 return (ch >= '0' && ch <= '9'); 2454 } 2455 2456 #define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') 2457 #define bad(val) (val == NULL || !isdigit(*val)) 2458 2459 static int 2460 atoi(const char *p) 2461 { 2462 int n; 2463 int c, neg = 0; 2464 2465 if (!isdigit(c = *p)) { 2466 while (isspace(c)) 2467 c = *++p; 2468 switch (c) { 2469 case '-': 2470 neg++; 2471 /* FALLTHROUGH */ 2472 case '+': 2473 c = *++p; 2474 } 2475 if (!isdigit(c)) 2476 return (0); 2477 } 2478 for (n = '0' - c; isdigit(c = *++p); ) { 2479 n *= 10; /* two steps to avoid unnecessary overflow */ 2480 n += '0' - c; /* accum neg to avoid surprises at MAX */ 2481 } 2482 return (neg ? n : -n); 2483 } 2484 2485 /* 2486 * Default root read tsize XXX 2487 */ 2488 int nfs_root_rsize = 8 * 1024; /* conservative for dumb NICs */ 2489 int nfs4_root_rsize = 32 * 1024; /* only runs on TCP be aggressive */ 2490 2491 /* 2492 * Default flags: NFSMNT_NOCTO|NFSMNT_LLOCK|NFSMNT_INT 2493 */ 2494 int nfs_rootopts = NFSMNT_NOCTO|NFSMNT_LLOCK|NFSMNT_INT; 2495 2496 static int 2497 init_mountopts(struct nfs_args *args, int version, struct knetconfig **dl_cf, 2498 int *vfsflags) 2499 { 2500 char servername[SYS_NMLN]; 2501 static int first = 0; 2502 struct netbuf server_address; 2503 char *opts, *val; 2504 int vers; 2505 struct knetconfig *cf = *dl_cf; 2506 char rootoptsbuf[256]; 2507 2508 /* 2509 * Set default mount options 2510 */ 2511 args->flags = nfs_rootopts; 2512 args->rsize = 0; 2513 args->flags |= NFSMNT_ACREGMIN; 2514 args->acregmin = ACMINMAX; 2515 args->flags |= NFSMNT_ACREGMAX; 2516 args->acregmax = ACMAXMAX; 2517 args->flags |= NFSMNT_ACDIRMIN; 2518 args->acdirmin = ACMINMAX; 2519 args->flags |= NFSMNT_ACDIRMAX; 2520 args->acdirmax = ACMAXMAX; 2521 2522 *vfsflags = 0; 2523 2524 /* 2525 * Only look up the rootopts the first time, we store this in 2526 * a static buffer but we are guaranteed to be single threaded 2527 * and not reentrant. 2528 */ 2529 if (first == 0) { 2530 first++; 2531 2532 init_netbuf(&server_address); 2533 2534 if (getfile("rootopts", servername, &server_address, 2535 rootopts)) { 2536 rootopts[0] = '\0'; 2537 free_netbuf(&server_address); 2538 goto sanity; 2539 } 2540 free_netbuf(&server_address); 2541 } 2542 2543 if (dldebug) 2544 printf("rootopts = %s\n", rootopts); 2545 2546 /* 2547 * We have to preserve rootopts for second time. 2548 */ 2549 (void) strncpy(rootoptsbuf, rootopts, sizeof (rootoptsbuf)); 2550 rootoptsbuf[sizeof (rootoptsbuf) - 1] = '\0'; 2551 opts = rootoptsbuf; 2552 while (*opts) { 2553 int opt; 2554 2555 switch (opt = getsubopt(&opts, optlist, &val)) { 2556 /* 2557 * Options that are defaults or meaningless so ignored 2558 */ 2559 case OPT_QUOTA: 2560 case OPT_NOQUOTA: 2561 case OPT_SUID: 2562 case OPT_DEVICES: 2563 case OPT_SETUID: 2564 case OPT_BG: 2565 case OPT_FG: 2566 case OPT_RETRY: 2567 case OPT_POSIX: 2568 case OPT_LARGEFILES: 2569 case OPT_XATTR: 2570 case OPT_NOXATTR: 2571 case OPT_EXEC: 2572 break; 2573 case OPT_RO: 2574 *vfsflags |= MS_RDONLY; 2575 break; 2576 case OPT_RW: 2577 *vfsflags &= ~(MS_RDONLY); 2578 break; 2579 case OPT_SOFT: 2580 args->flags |= NFSMNT_SOFT; 2581 args->flags &= ~(NFSMNT_SEMISOFT); 2582 break; 2583 case OPT_SEMISOFT: 2584 args->flags |= NFSMNT_SOFT; 2585 args->flags |= NFSMNT_SEMISOFT; 2586 break; 2587 case OPT_HARD: 2588 args->flags &= ~(NFSMNT_SOFT); 2589 args->flags &= ~(NFSMNT_SEMISOFT); 2590 break; 2591 case OPT_NOSUID: 2592 case OPT_NODEVICES: 2593 case OPT_NOSETUID: 2594 case OPT_NOEXEC: 2595 cmn_err(CE_WARN, 2596 "nfs_dlboot: may not set root partition %s", 2597 optlist[opt]); 2598 break; 2599 case OPT_GRPID: 2600 args->flags |= NFSMNT_GRPID; 2601 break; 2602 case OPT_REMOUNT: 2603 cmn_err(CE_WARN, 2604 "nfs_dlboot: may not remount root partition"); 2605 break; 2606 case OPT_INTR: 2607 args->flags |= NFSMNT_INT; 2608 break; 2609 case OPT_NOINTR: 2610 args->flags &= ~(NFSMNT_INT); 2611 break; 2612 case OPT_NOAC: 2613 args->flags |= NFSMNT_NOAC; 2614 break; 2615 case OPT_PORT: 2616 cmn_err(CE_WARN, 2617 "nfs_dlboot: may not change root port number"); 2618 break; 2619 case OPT_SECURE: 2620 cmn_err(CE_WARN, 2621 "nfs_dlboot: root mounted auth_unix, secure ignored"); 2622 break; 2623 case OPT_NOCTO: 2624 args->flags |= NFSMNT_NOCTO; 2625 break; 2626 case OPT_RSIZE: 2627 if (bad(val)) { 2628 cmn_err(CE_WARN, 2629 "nfs_dlboot: invalid option: rsize"); 2630 break; 2631 } 2632 args->flags |= NFSMNT_RSIZE; 2633 args->rsize = atoi(val); 2634 break; 2635 case OPT_WSIZE: 2636 if (bad(val)) { 2637 cmn_err(CE_WARN, 2638 "nfs_dlboot: invalid option: wsize"); 2639 break; 2640 } 2641 args->flags |= NFSMNT_WSIZE; 2642 args->wsize = atoi(val); 2643 break; 2644 case OPT_TIMEO: 2645 if (bad(val)) { 2646 cmn_err(CE_WARN, 2647 "nfs_dlboot: invalid option: timeo"); 2648 break; 2649 } 2650 args->flags |= NFSMNT_TIMEO; 2651 args->timeo = atoi(val); 2652 break; 2653 case OPT_RETRANS: 2654 if (bad(val)) { 2655 cmn_err(CE_WARN, 2656 "nfs_dlboot: invalid option: retrans"); 2657 break; 2658 } 2659 args->flags |= NFSMNT_RETRANS; 2660 args->retrans = atoi(val); 2661 break; 2662 case OPT_ACTIMEO: 2663 if (bad(val)) { 2664 cmn_err(CE_WARN, 2665 "nfs_dlboot: invalid option: actimeo"); 2666 break; 2667 } 2668 args->flags |= NFSMNT_ACDIRMAX; 2669 args->flags |= NFSMNT_ACREGMAX; 2670 args->flags |= NFSMNT_ACDIRMIN; 2671 args->flags |= NFSMNT_ACREGMIN; 2672 args->acdirmin = args->acregmin = args->acdirmax = 2673 args->acregmax = atoi(val); 2674 break; 2675 case OPT_ACREGMIN: 2676 if (bad(val)) { 2677 cmn_err(CE_WARN, 2678 "nfs_dlboot: invalid option: acregmin"); 2679 break; 2680 } 2681 args->flags |= NFSMNT_ACREGMIN; 2682 args->acregmin = atoi(val); 2683 break; 2684 case OPT_ACREGMAX: 2685 if (bad(val)) { 2686 cmn_err(CE_WARN, 2687 "nfs_dlboot: invalid option: acregmax"); 2688 break; 2689 } 2690 args->flags |= NFSMNT_ACREGMAX; 2691 args->acregmax = atoi(val); 2692 break; 2693 case OPT_ACDIRMIN: 2694 if (bad(val)) { 2695 cmn_err(CE_WARN, 2696 "nfs_dlboot: invalid option: acdirmin"); 2697 break; 2698 } 2699 args->flags |= NFSMNT_ACDIRMIN; 2700 args->acdirmin = atoi(val); 2701 break; 2702 case OPT_ACDIRMAX: 2703 if (bad(val)) { 2704 cmn_err(CE_WARN, 2705 "nfs_dlboot: invalid option: acdirmax"); 2706 break; 2707 } 2708 args->flags |= NFSMNT_ACDIRMAX; 2709 args->acdirmax = atoi(val); 2710 break; 2711 case OPT_LLOCK: 2712 args->flags |= NFSMNT_LLOCK; 2713 break; 2714 case OPT_VERS: 2715 if (bad(val)) { 2716 cmn_err(CE_WARN, 2717 "nfs_dlboot: invalid option: vers"); 2718 break; 2719 } 2720 vers = atoi(val); 2721 /* 2722 * If the requested version is less than what we 2723 * chose, pretend the chosen version doesn't exist 2724 */ 2725 if (vers < version) { 2726 return (EPROTONOSUPPORT); 2727 } 2728 if (vers > version) { 2729 cmn_err(CE_WARN, 2730 "nfs_dlboot: version %d unavailable", 2731 vers); 2732 return (EINVAL); 2733 } 2734 break; 2735 case OPT_PROTO: 2736 /* 2737 * NFSv4 can only run over TCP, if they requested 2738 * UDP pretend v4 doesn't exist, they might not have 2739 * specified a version allowing a fallback to v2 or v3. 2740 */ 2741 if (version == NFS_V4 && strcmp(val, NC_UDP) == 0) 2742 return (EPROTONOSUPPORT); 2743 /* 2744 * TCP is always chosen over UDP, so if the 2745 * requested is the same as the chosen either 2746 * they chose TCP when available or UDP on a UDP 2747 * only server. 2748 */ 2749 if (strcmp(cf->knc_proto, val) == 0) 2750 break; 2751 /* 2752 * If we chose UDP, they must have requested TCP 2753 */ 2754 if (strcmp(cf->knc_proto, NC_TCP) != 0) { 2755 cmn_err(CE_WARN, 2756 "nfs_dlboot: TCP protocol unavailable"); 2757 return (EINVAL); 2758 } 2759 /* 2760 * They can only have requested UDP 2761 */ 2762 if (strcmp(val, NC_UDP) != 0) { 2763 cmn_err(CE_WARN, 2764 "nfs_dlboot: unknown protocol"); 2765 return (EINVAL); 2766 } 2767 *dl_cf = &dl_udp_netconf; 2768 break; 2769 case OPT_NOPRINT: 2770 args->flags |= NFSMNT_NOPRINT; 2771 break; 2772 case OPT_NOLARGEFILES: 2773 cmn_err(CE_WARN, 2774 "nfs_dlboot: NFS can't support nolargefiles"); 2775 break; 2776 case OPT_SEC: 2777 cmn_err(CE_WARN, 2778 "nfs_dlboot: root mounted auth_unix, sec ignored"); 2779 break; 2780 2781 case OPT_DIRECTIO: 2782 args->flags |= NFSMNT_DIRECTIO; 2783 break; 2784 2785 case OPT_NODIRECTIO: 2786 args->flags &= ~(NFSMNT_DIRECTIO); 2787 break; 2788 2789 default: 2790 cmn_err(CE_WARN, 2791 "nfs_dlboot: ignoring invalid option \"%s\"", val); 2792 break; 2793 } 2794 } 2795 sanity: 2796 /* 2797 * Set some sane limits on read size 2798 */ 2799 if (!(args->flags & NFSMNT_RSIZE) || args->rsize == 0) { 2800 /* 2801 * Establish defaults 2802 */ 2803 args->flags |= NFSMNT_RSIZE; 2804 if (version == NFS_V4) 2805 args->rsize = nfs4_root_rsize; 2806 else 2807 args->rsize = nfs_root_rsize; 2808 return (0); 2809 } 2810 /* 2811 * No less than 512 bytes, otherwise it will take forever to boot 2812 */ 2813 if (args->rsize < 512) 2814 args->rsize = 512; 2815 /* 2816 * If we are running over UDP, we cannot exceed 64KB, trim 2817 * to 56KB to allow room for headers. 2818 */ 2819 if (*dl_cf == &dl_udp_netconf && args->rsize > (56 * 1024)) 2820 args->rsize = 56 * 1024; 2821 return (0); 2822 } 2823