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