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