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