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