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