17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <sys/param.h> 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <sys/systm.h> 327c478bd9Sstevel@tonic-gate #include <sys/cred.h> 337c478bd9Sstevel@tonic-gate #include <sys/user.h> 347c478bd9Sstevel@tonic-gate #include <sys/file.h> 357c478bd9Sstevel@tonic-gate #include <sys/stream.h> 367c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 377c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 387c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 397c478bd9Sstevel@tonic-gate #include <sys/debug.h> 407c478bd9Sstevel@tonic-gate #include <sys/tiuser.h> 417c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 427c478bd9Sstevel@tonic-gate #include <sys/socket.h> 437c478bd9Sstevel@tonic-gate #include <sys/t_kuser.h> 447c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 457c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 467c478bd9Sstevel@tonic-gate #include <sys/netconfig.h> 477c478bd9Sstevel@tonic-gate #include <sys/ethernet.h> 487c478bd9Sstevel@tonic-gate #include <sys/dlpi.h> 497c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 507c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 517c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 527c478bd9Sstevel@tonic-gate #include <sys/bootprops.h> 537c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 547c478bd9Sstevel@tonic-gate #include <sys/promif.h> 557c478bd9Sstevel@tonic-gate #include <sys/mount.h> 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate #include <net/if.h> 587c478bd9Sstevel@tonic-gate #include <net/route.h> 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #include <netinet/in.h> 617c478bd9Sstevel@tonic-gate #include <netinet/arp.h> 627c478bd9Sstevel@tonic-gate #include <netinet/dhcp.h> 637c478bd9Sstevel@tonic-gate #include <netinet/inetutil.h> 647c478bd9Sstevel@tonic-gate #include <dhcp_impl.h> 657c478bd9Sstevel@tonic-gate #include <sys/sunos_dhcp_class.h> 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #include <rpc/types.h> 687c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 697c478bd9Sstevel@tonic-gate #include <rpc/xdr.h> 707c478bd9Sstevel@tonic-gate #include <rpc/auth.h> 717c478bd9Sstevel@tonic-gate #include <rpc/clnt.h> 727c478bd9Sstevel@tonic-gate #include <rpc/pmap_clnt.h> 737c478bd9Sstevel@tonic-gate #include <rpc/pmap_rmt.h> 747c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h> 757c478bd9Sstevel@tonic-gate #include <rpc/bootparam.h> 767c478bd9Sstevel@tonic-gate #include <rpc/rpcb_prot.h> 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate #include <nfs/nfs.h> 797c478bd9Sstevel@tonic-gate #include <nfs/nfs4.h> 807c478bd9Sstevel@tonic-gate #include <nfs/nfs_clnt.h> 817c478bd9Sstevel@tonic-gate #include <nfs/mount.h> 827c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate #include <sys/kstr.h> 857c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 867c478bd9Sstevel@tonic-gate #include <sys/sunldi.h> 877c478bd9Sstevel@tonic-gate #include <sys/esunddi.h> 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate #include <sys/errno.h> 907c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * RPC timers and retries 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate #define PMAP_RETRIES 5 967c478bd9Sstevel@tonic-gate #define DEFAULT_RETRIES 3 977c478bd9Sstevel@tonic-gate #define GETFILE_RETRIES 2 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate #define DEFAULT_TIMEO 3 1007c478bd9Sstevel@tonic-gate #define WHOAMI_TIMEO 20 1017c478bd9Sstevel@tonic-gate #define REVARP_TIMEO 5 1027c478bd9Sstevel@tonic-gate #define GETFILE_TIMEO 1 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate * These are from the rpcgen'd version of mount.h XXX 1067c478bd9Sstevel@tonic-gate */ 1077c478bd9Sstevel@tonic-gate #define MOUNTPROG 100005 1087c478bd9Sstevel@tonic-gate #define MOUNTPROC_MNT 1 1097c478bd9Sstevel@tonic-gate #define MOUNTVERS 1 1107c478bd9Sstevel@tonic-gate #define MOUNTVERS_POSIX 2 1117c478bd9Sstevel@tonic-gate #define MOUNTVERS3 3 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate struct fhstatus { 1147c478bd9Sstevel@tonic-gate int fhs_status; 1157c478bd9Sstevel@tonic-gate fhandle_t fhs_fh; 1167c478bd9Sstevel@tonic-gate }; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate #define FHSIZE3 64 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate struct fhandle3 { 1217c478bd9Sstevel@tonic-gate uint_t fhandle3_len; 1227c478bd9Sstevel@tonic-gate char *fhandle3_val; 1237c478bd9Sstevel@tonic-gate }; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate enum mountstat3 { 1267c478bd9Sstevel@tonic-gate MNT_OK = 0, 1277c478bd9Sstevel@tonic-gate MNT3ERR_PERM = 1, 1287c478bd9Sstevel@tonic-gate MNT3ERR_NOENT = 2, 1297c478bd9Sstevel@tonic-gate MNT3ERR_IO = 5, 1307c478bd9Sstevel@tonic-gate MNT3ERR_ACCES = 13, 1317c478bd9Sstevel@tonic-gate MNT3ERR_NOTDIR = 20, 1327c478bd9Sstevel@tonic-gate MNT3ERR_INVAL = 22, 1337c478bd9Sstevel@tonic-gate MNT3ERR_NAMETOOLONG = 63, 1347c478bd9Sstevel@tonic-gate MNT3ERR_NOTSUPP = 10004, 1357c478bd9Sstevel@tonic-gate MNT3ERR_SERVERFAULT = 10006 1367c478bd9Sstevel@tonic-gate }; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate struct mountres3_ok { 1397c478bd9Sstevel@tonic-gate struct fhandle3 fhandle; 1407c478bd9Sstevel@tonic-gate struct { 1417c478bd9Sstevel@tonic-gate uint_t auth_flavors_len; 1427c478bd9Sstevel@tonic-gate int *auth_flavors_val; 1437c478bd9Sstevel@tonic-gate } auth_flavors; 1447c478bd9Sstevel@tonic-gate }; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate struct mountres3 { 1477c478bd9Sstevel@tonic-gate enum mountstat3 fhs_status; 1487c478bd9Sstevel@tonic-gate union { 1497c478bd9Sstevel@tonic-gate struct mountres3_ok mountinfo; 1507c478bd9Sstevel@tonic-gate } mountres3_u; 1517c478bd9Sstevel@tonic-gate }; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* 1547c478bd9Sstevel@tonic-gate * DLPI address format. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate struct dladdr { 1577c478bd9Sstevel@tonic-gate uchar_t dl_phys[6]; 1587c478bd9Sstevel@tonic-gate ushort_t dl_sap; 1597c478bd9Sstevel@tonic-gate }; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 1627c478bd9Sstevel@tonic-gate &mod_miscops, "Boot diskless" 1637c478bd9Sstevel@tonic-gate }; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1667c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL 1677c478bd9Sstevel@tonic-gate }; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate static int dldebug; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate int 1727c478bd9Sstevel@tonic-gate _init(void) 1737c478bd9Sstevel@tonic-gate { 1747c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate int 1787c478bd9Sstevel@tonic-gate _fini(void) 1797c478bd9Sstevel@tonic-gate { 1807c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate int 1847c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 1857c478bd9Sstevel@tonic-gate { 1867c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 189*cc2b7f04Sdduvall 1907c478bd9Sstevel@tonic-gate static enum clnt_stat pmap_rmt_call(struct knetconfig *, struct netbuf *, 1917c478bd9Sstevel@tonic-gate bool_t, rpcprog_t, rpcvers_t, rpcproc_t, xdrproc_t, 1927c478bd9Sstevel@tonic-gate caddr_t, xdrproc_t, caddr_t, struct timeval, 1937c478bd9Sstevel@tonic-gate struct netbuf *); 1947c478bd9Sstevel@tonic-gate static bool_t myxdr_rmtcall_args(XDR *, struct rmtcallargs *); 1957c478bd9Sstevel@tonic-gate static bool_t myxdr_rmtcallres(XDR *, struct rmtcallres *); 1967c478bd9Sstevel@tonic-gate static bool_t myxdr_pmap(XDR *, struct pmap *); 1977c478bd9Sstevel@tonic-gate static bool_t myxdr_fhstatus(XDR *xdrs, struct fhstatus *fhsp); 1987c478bd9Sstevel@tonic-gate static bool_t myxdr_fhandle(XDR *xdrs, fhandle_t *fh); 1997c478bd9Sstevel@tonic-gate static bool_t myxdr_mountres3(XDR *xdrs, struct mountres3 *objp); 2007c478bd9Sstevel@tonic-gate static bool_t myxdr_mountstat3(XDR *xdrs, enum mountstat3 *objp); 2017c478bd9Sstevel@tonic-gate static bool_t myxdr_mountres3_ok(XDR *xdrs, 2027c478bd9Sstevel@tonic-gate struct mountres3_ok *objp); 2037c478bd9Sstevel@tonic-gate static bool_t myxdr_fhandle3(XDR *xdrs, struct fhandle3 *objp); 2047c478bd9Sstevel@tonic-gate static enum clnt_stat pmap_kgetport(struct knetconfig *, struct netbuf *, 2057c478bd9Sstevel@tonic-gate rpcprog_t, rpcvers_t, rpcprot_t); 2067c478bd9Sstevel@tonic-gate static enum clnt_stat mycallrpc(struct knetconfig *, struct netbuf *, 2077c478bd9Sstevel@tonic-gate rpcprog_t, rpcvers_t, rpcproc_t, xdrproc_t, 2087c478bd9Sstevel@tonic-gate char *, xdrproc_t, char *, int, int); 2097c478bd9Sstevel@tonic-gate static int ifioctl(TIUSER *, int, struct netbuf *); 2107c478bd9Sstevel@tonic-gate static int getfile(char *, char *, struct netbuf *, char *); 2117c478bd9Sstevel@tonic-gate static int ping_prog(struct netbuf *, uint_t prog, uint_t vers, 2127c478bd9Sstevel@tonic-gate int proto, enum clnt_stat *); 2137c478bd9Sstevel@tonic-gate static int mountnfs(struct netbuf *, char *, char *, 2147c478bd9Sstevel@tonic-gate fhandle_t *, int *); 2157c478bd9Sstevel@tonic-gate static int mountnfs3(struct netbuf *, char *, char *, 2167c478bd9Sstevel@tonic-gate nfs_fh3 *, int *); 2177c478bd9Sstevel@tonic-gate static int init_mountopts(struct nfs_args *, int, 2187c478bd9Sstevel@tonic-gate struct knetconfig **, int *); 2197c478bd9Sstevel@tonic-gate static int revarp_myaddr(TIUSER *); 2207c478bd9Sstevel@tonic-gate static void revarp_start(ldi_handle_t, struct netbuf *); 2217c478bd9Sstevel@tonic-gate static void revarpinput(ldi_handle_t, struct netbuf *); 2227c478bd9Sstevel@tonic-gate static void init_netbuf(struct netbuf *); 2237c478bd9Sstevel@tonic-gate static void free_netbuf(struct netbuf *); 2247c478bd9Sstevel@tonic-gate static int rtioctl(TIUSER *, int, struct rtentry *); 2257c478bd9Sstevel@tonic-gate static int dl_info(ldi_handle_t, dl_info_ack_t *); 226266095caSszhou extern int dl_attach(ldi_handle_t, int); 227266095caSszhou extern int dl_bind(ldi_handle_t, uint32_t, uint32_t, uint32_t, 2287c478bd9Sstevel@tonic-gate uint32_t); 229266095caSszhou extern int dl_phys_addr(ldi_handle_t, struct ether_addr *); 2307c478bd9Sstevel@tonic-gate static void init_config(void); 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate static void cacheinit(void); 2337c478bd9Sstevel@tonic-gate static int cacheinfo(char *, int, struct netbuf *, char *, int); 2347c478bd9Sstevel@tonic-gate static int dlifconfig(TIUSER *, struct in_addr *, struct in_addr *, 2357c478bd9Sstevel@tonic-gate struct in_addr *); 2367c478bd9Sstevel@tonic-gate static int setifflags(TIUSER *, uint_t); 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate static char *inet_ntoa(struct in_addr); 2397c478bd9Sstevel@tonic-gate static int inet_aton(char *, uchar_t *); 2407c478bd9Sstevel@tonic-gate static int isdigit(int); 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * Should be in some common 2447c478bd9Sstevel@tonic-gate * ethernet source file. 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate static struct ether_addr etherbroadcastaddr = { 2477c478bd9Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 2487c478bd9Sstevel@tonic-gate }; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate static struct ether_addr myether; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate /* 2537c478bd9Sstevel@tonic-gate * "ifname" is the interface name/unit as read from the boot 2547c478bd9Sstevel@tonic-gate * arguments. 2557c478bd9Sstevel@tonic-gate * "ndev" is the major device number of the network interface 2567c478bd9Sstevel@tonic-gate * used to boot from. 2577c478bd9Sstevel@tonic-gate * "ifunit" it the physical point of attachment for the network 2587c478bd9Sstevel@tonic-gate * interface used to boot from. 2597c478bd9Sstevel@tonic-gate * 2607c478bd9Sstevel@tonic-gate * Both of these are initialized in "init_config()". 2617c478bd9Sstevel@tonic-gate */ 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate static char ifname[IFNAMSIZ]; 2647c478bd9Sstevel@tonic-gate static char ndev_path[MAXPATHLEN]; 2657c478bd9Sstevel@tonic-gate static int ifunit; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * XXX these should be shared 2697c478bd9Sstevel@tonic-gate */ 2707c478bd9Sstevel@tonic-gate static struct knetconfig dl_udp_netconf = { 2717c478bd9Sstevel@tonic-gate NC_TPI_CLTS, /* semantics */ 2727c478bd9Sstevel@tonic-gate NC_INET, /* family */ 2737c478bd9Sstevel@tonic-gate NC_UDP, /* protocol */ 2747c478bd9Sstevel@tonic-gate 0, /* device */ 2757c478bd9Sstevel@tonic-gate }; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate static struct knetconfig dl_tcp_netconf = { 2787c478bd9Sstevel@tonic-gate NC_TPI_COTS, /* semantics */ 2797c478bd9Sstevel@tonic-gate NC_INET, /* family */ 2807c478bd9Sstevel@tonic-gate NC_TCP, /* protocol */ 2817c478bd9Sstevel@tonic-gate 0, /* device */ 2827c478bd9Sstevel@tonic-gate }; 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate /* parameters from DHCP or bootparamd */ 2857c478bd9Sstevel@tonic-gate static PKT_LIST *pl = NULL; 2867c478bd9Sstevel@tonic-gate static uchar_t server_ip[4]; 2877c478bd9Sstevel@tonic-gate static uchar_t dhcp_server_ip[4]; 2887c478bd9Sstevel@tonic-gate static char *server_name_c, *server_path_c; 2897c478bd9Sstevel@tonic-gate static char rootopts[256]; 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate /* 2927c478bd9Sstevel@tonic-gate * XXX Until we get the nfsmapid deadlocks all fixed, don't allow 2937c478bd9Sstevel@tonic-gate * XXX a v4 root mount. 2947c478bd9Sstevel@tonic-gate */ 2957c478bd9Sstevel@tonic-gate int nfs4_no_diskless_root_support = 1; 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate int 2987c478bd9Sstevel@tonic-gate mount_root(char *name, char *path, int version, struct nfs_args *args, 2997c478bd9Sstevel@tonic-gate int *vfsflags) 3007c478bd9Sstevel@tonic-gate { 3017c478bd9Sstevel@tonic-gate int rc; 3027c478bd9Sstevel@tonic-gate int proto; 3037c478bd9Sstevel@tonic-gate struct knetconfig *dl_cf; 3047c478bd9Sstevel@tonic-gate static int init_done = 0; 3057c478bd9Sstevel@tonic-gate enum clnt_stat stat; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate if (dldebug) 3087c478bd9Sstevel@tonic-gate printf("mount_root: name=%s\n", name); 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate if (init_done == 0) { 3117c478bd9Sstevel@tonic-gate init_config(); 3127c478bd9Sstevel@tonic-gate init_done = 1; 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate init_netbuf(args->addr); 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate do { 3187c478bd9Sstevel@tonic-gate rc = getfile(name, args->hostname, args->addr, path); 3197c478bd9Sstevel@tonic-gate } while (rc == ETIMEDOUT); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate if (rc) { 3227c478bd9Sstevel@tonic-gate free_netbuf(args->addr); 3237c478bd9Sstevel@tonic-gate return (rc); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate ASSERT(args->knconf->knc_protofmly != NULL); 3277c478bd9Sstevel@tonic-gate ASSERT(args->knconf->knc_proto != NULL); 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate switch (version) { 3307c478bd9Sstevel@tonic-gate case NFS_VERSION: 3317c478bd9Sstevel@tonic-gate rc = mountnfs(args->addr, args->hostname, path, 3327c478bd9Sstevel@tonic-gate (fhandle_t *)args->fh, &proto); 3337c478bd9Sstevel@tonic-gate break; 3347c478bd9Sstevel@tonic-gate case NFS_V3: 3357c478bd9Sstevel@tonic-gate rc = mountnfs3(args->addr, args->hostname, path, 3367c478bd9Sstevel@tonic-gate (nfs_fh3 *)args->fh, &proto); 3377c478bd9Sstevel@tonic-gate break; 3387c478bd9Sstevel@tonic-gate case NFS_V4: 3397c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)args->addr->buf)->sin_port = 3407c478bd9Sstevel@tonic-gate htons(NFS_PORT); 3417c478bd9Sstevel@tonic-gate if (ping_prog(args->addr, NFS_PROGRAM, NFS_V4, IPPROTO_TCP, 3427c478bd9Sstevel@tonic-gate &stat)) { 3437c478bd9Sstevel@tonic-gate proto = IPPROTO_TCP; 3447c478bd9Sstevel@tonic-gate rc = 0; 3457c478bd9Sstevel@tonic-gate } else { 3467c478bd9Sstevel@tonic-gate switch (stat) { 3477c478bd9Sstevel@tonic-gate case RPC_PROGVERSMISMATCH: 3487c478bd9Sstevel@tonic-gate case RPC_XPRTFAILED: 3497c478bd9Sstevel@tonic-gate /* 3507c478bd9Sstevel@tonic-gate * Common failures if v4 unsupported or no TCP 3517c478bd9Sstevel@tonic-gate */ 3527c478bd9Sstevel@tonic-gate rc = EPROTONOSUPPORT; 3537c478bd9Sstevel@tonic-gate break; 3547c478bd9Sstevel@tonic-gate default: 3557c478bd9Sstevel@tonic-gate rc = ENXIO; 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate if (nfs4_no_diskless_root_support) 3597c478bd9Sstevel@tonic-gate rc = EPROTONOSUPPORT; 3607c478bd9Sstevel@tonic-gate break; 3617c478bd9Sstevel@tonic-gate default: 3627c478bd9Sstevel@tonic-gate rc = EPROTONOSUPPORT; 3637c478bd9Sstevel@tonic-gate break; 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if (rc) 3677c478bd9Sstevel@tonic-gate goto errout; 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate switch (proto) { 3707c478bd9Sstevel@tonic-gate case IPPROTO_TCP: 3717c478bd9Sstevel@tonic-gate dl_cf = &dl_tcp_netconf; 3727c478bd9Sstevel@tonic-gate break; 3737c478bd9Sstevel@tonic-gate case IPPROTO_UDP: 3747c478bd9Sstevel@tonic-gate default: 3757c478bd9Sstevel@tonic-gate dl_cf = &dl_udp_netconf; 3767c478bd9Sstevel@tonic-gate break; 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate rc = init_mountopts(args, version, &dl_cf, vfsflags); 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate /* 3827c478bd9Sstevel@tonic-gate * Copy knetconfig information from the template, note that the 3837c478bd9Sstevel@tonic-gate * rdev field has been set by init_config above. 3847c478bd9Sstevel@tonic-gate */ 3857c478bd9Sstevel@tonic-gate args->knconf->knc_semantics = dl_cf->knc_semantics; 3867c478bd9Sstevel@tonic-gate args->knconf->knc_rdev = dl_cf->knc_rdev; 3877c478bd9Sstevel@tonic-gate (void) strcpy(args->knconf->knc_protofmly, dl_cf->knc_protofmly); 3887c478bd9Sstevel@tonic-gate (void) strcpy(args->knconf->knc_proto, dl_cf->knc_proto); 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate errout: 3917c478bd9Sstevel@tonic-gate if (dldebug) { 3927c478bd9Sstevel@tonic-gate if (rc) 3937c478bd9Sstevel@tonic-gate nfs_perror(rc, "mount_root: mount %s:%s failed: %m\n", 3947c478bd9Sstevel@tonic-gate args->hostname, path); 3957c478bd9Sstevel@tonic-gate else 3967c478bd9Sstevel@tonic-gate printf("mount_root: leaving\n"); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate return (rc); 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate /* 4037c478bd9Sstevel@tonic-gate * Call mount daemon on server `sa' to mount path. 4047c478bd9Sstevel@tonic-gate * `port' is set to nfs port and fh is the fhandle 4057c478bd9Sstevel@tonic-gate * returned from the server. 4067c478bd9Sstevel@tonic-gate */ 4077c478bd9Sstevel@tonic-gate static int 4087c478bd9Sstevel@tonic-gate mountnfs(struct netbuf *sa, char *server, 4097c478bd9Sstevel@tonic-gate char *path, fhandle_t *fh, int *proto) 4107c478bd9Sstevel@tonic-gate { 4117c478bd9Sstevel@tonic-gate struct fhstatus fhs; 4127c478bd9Sstevel@tonic-gate enum clnt_stat stat; 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate if (dldebug) 4157c478bd9Sstevel@tonic-gate printf("mountnfs: entered\n"); 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate /* 4187c478bd9Sstevel@tonic-gate * Get the port number for the mount program. 4197c478bd9Sstevel@tonic-gate * pmap_kgetport first tries a SunOS portmapper 4207c478bd9Sstevel@tonic-gate * and, if no reply is received, will try a 4217c478bd9Sstevel@tonic-gate * SVR4 rpcbind. Either way, `sa' is set to 4227c478bd9Sstevel@tonic-gate * the correct address. 4237c478bd9Sstevel@tonic-gate */ 4247c478bd9Sstevel@tonic-gate do { 4257c478bd9Sstevel@tonic-gate stat = pmap_kgetport(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG, 4267c478bd9Sstevel@tonic-gate (rpcvers_t)MOUNTVERS, (rpcprot_t)IPPROTO_UDP); 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate if (stat == RPC_TIMEDOUT) { 4297c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4307c478bd9Sstevel@tonic-gate "mountnfs: %s:%s portmap not responding", 4317c478bd9Sstevel@tonic-gate server, path); 4327c478bd9Sstevel@tonic-gate } else if (stat != RPC_SUCCESS) { 4337c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4347c478bd9Sstevel@tonic-gate "mountnfs: pmap_kgetport RPC error %d (%s).", 4357c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat)); 4367c478bd9Sstevel@tonic-gate return (ENXIO); /* XXX */ 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT); 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate /* 4417c478bd9Sstevel@tonic-gate * The correct port number has been 4427c478bd9Sstevel@tonic-gate * put into `sa' by pmap_kgetport(). 4437c478bd9Sstevel@tonic-gate */ 4447c478bd9Sstevel@tonic-gate do { 4457c478bd9Sstevel@tonic-gate stat = mycallrpc(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG, 4467c478bd9Sstevel@tonic-gate (rpcvers_t)MOUNTVERS, (rpcproc_t)MOUNTPROC_MNT, 4477c478bd9Sstevel@tonic-gate xdr_bp_path_t, (char *)&path, 4487c478bd9Sstevel@tonic-gate myxdr_fhstatus, (char *)&fhs, 4497c478bd9Sstevel@tonic-gate DEFAULT_TIMEO, DEFAULT_RETRIES); 4507c478bd9Sstevel@tonic-gate if (stat == RPC_TIMEDOUT) { 4517c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4527c478bd9Sstevel@tonic-gate "mountnfs: %s:%s mount server not responding", 4537c478bd9Sstevel@tonic-gate server, path); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT); 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) { 4587c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "mountnfs: RPC failed: error %d (%s).", 4597c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat)); 4607c478bd9Sstevel@tonic-gate return (ENXIO); /* XXX */ 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)sa->buf)->sin_port = htons(NFS_PORT); 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate *fh = fhs.fhs_fh; 4667c478bd9Sstevel@tonic-gate if (fhs.fhs_status != 0) { 4677c478bd9Sstevel@tonic-gate if (dldebug) 4687c478bd9Sstevel@tonic-gate printf("mountnfs: fhs_status %d\n", fhs.fhs_status); 4697c478bd9Sstevel@tonic-gate return (ENXIO); /* XXX */ 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate *proto = IPPROTO_UDP; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate if (ping_prog(sa, NFS_PROGRAM, NFS_VERSION, IPPROTO_TCP, NULL)) 4757c478bd9Sstevel@tonic-gate *proto = IPPROTO_TCP; 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate if (dldebug) 4787c478bd9Sstevel@tonic-gate printf("mountnfs: leaving\n"); 4797c478bd9Sstevel@tonic-gate return (0); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* 4837c478bd9Sstevel@tonic-gate * Call mount daemon on server `sa' to mount path. 4847c478bd9Sstevel@tonic-gate * `port' is set to nfs port and fh is the fhandle 4857c478bd9Sstevel@tonic-gate * returned from the server. 4867c478bd9Sstevel@tonic-gate */ 4877c478bd9Sstevel@tonic-gate static int 4887c478bd9Sstevel@tonic-gate mountnfs3(struct netbuf *sa, char *server, 4897c478bd9Sstevel@tonic-gate char *path, nfs_fh3 *fh, int *proto) 4907c478bd9Sstevel@tonic-gate { 4917c478bd9Sstevel@tonic-gate struct mountres3 mountres3; 4927c478bd9Sstevel@tonic-gate enum clnt_stat stat; 4937c478bd9Sstevel@tonic-gate int ret = 0; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate if (dldebug) 4967c478bd9Sstevel@tonic-gate printf("mountnfs3: entered\n"); 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate /* 4997c478bd9Sstevel@tonic-gate * Get the port number for the mount program. 5007c478bd9Sstevel@tonic-gate * pmap_kgetport first tries a SunOS portmapper 5017c478bd9Sstevel@tonic-gate * and, if no reply is received, will try a 5027c478bd9Sstevel@tonic-gate * SVR4 rpcbind. Either way, `sa' is set to 5037c478bd9Sstevel@tonic-gate * the correct address. 5047c478bd9Sstevel@tonic-gate */ 5057c478bd9Sstevel@tonic-gate do { 5067c478bd9Sstevel@tonic-gate stat = pmap_kgetport(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG, 5077c478bd9Sstevel@tonic-gate (rpcvers_t)MOUNTVERS3, (rpcprot_t)IPPROTO_UDP); 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate if (stat == RPC_PROGVERSMISMATCH) { 5107c478bd9Sstevel@tonic-gate if (dldebug) 5117c478bd9Sstevel@tonic-gate printf("mountnfs3: program/version mismatch\n"); 5127c478bd9Sstevel@tonic-gate return (EPROTONOSUPPORT); /* XXX */ 5137c478bd9Sstevel@tonic-gate } else if (stat == RPC_TIMEDOUT) { 5147c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 5157c478bd9Sstevel@tonic-gate "mountnfs3: %s:%s portmap not responding", 5167c478bd9Sstevel@tonic-gate server, path); 5177c478bd9Sstevel@tonic-gate } else if (stat != RPC_SUCCESS) { 5187c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 5197c478bd9Sstevel@tonic-gate "mountnfs3: pmap_kgetport RPC error %d (%s).", 5207c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat)); 5217c478bd9Sstevel@tonic-gate return (ENXIO); /* XXX */ 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT); 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val = NULL; 5267c478bd9Sstevel@tonic-gate mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val = NULL; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate /* 5297c478bd9Sstevel@tonic-gate * The correct port number has been 5307c478bd9Sstevel@tonic-gate * put into `sa' by pmap_kgetport(). 5317c478bd9Sstevel@tonic-gate */ 5327c478bd9Sstevel@tonic-gate do { 5337c478bd9Sstevel@tonic-gate stat = mycallrpc(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG, 5347c478bd9Sstevel@tonic-gate (rpcvers_t)MOUNTVERS3, (rpcproc_t)MOUNTPROC_MNT, 5357c478bd9Sstevel@tonic-gate xdr_bp_path_t, (char *)&path, 5367c478bd9Sstevel@tonic-gate myxdr_mountres3, (char *)&mountres3, 5377c478bd9Sstevel@tonic-gate DEFAULT_TIMEO, DEFAULT_RETRIES); 5387c478bd9Sstevel@tonic-gate if (stat == RPC_TIMEDOUT) { 5397c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 5407c478bd9Sstevel@tonic-gate "mountnfs3: %s:%s mount server not responding", 5417c478bd9Sstevel@tonic-gate server, path); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate if (stat == RPC_PROGVERSMISMATCH) { 5467c478bd9Sstevel@tonic-gate if (dldebug) 5477c478bd9Sstevel@tonic-gate printf("mountnfs3: program/version mismatch\n"); 5487c478bd9Sstevel@tonic-gate ret = EPROTONOSUPPORT; 5497c478bd9Sstevel@tonic-gate goto out; 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) { 5527c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "mountnfs3: RPC failed: error %d (%s).", 5537c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat)); 5547c478bd9Sstevel@tonic-gate ret = ENXIO; /* XXX */ 5557c478bd9Sstevel@tonic-gate goto out; 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate if (mountres3.fhs_status != MNT_OK) { 5597c478bd9Sstevel@tonic-gate if (dldebug) 5607c478bd9Sstevel@tonic-gate printf("mountnfs3: fhs_status %d\n", 5617c478bd9Sstevel@tonic-gate mountres3.fhs_status); 5627c478bd9Sstevel@tonic-gate ret = ENXIO; /* XXX */ 5637c478bd9Sstevel@tonic-gate goto out; 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)sa->buf)->sin_port = htons(NFS_PORT); 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate *proto = IPPROTO_UDP; 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate if (ping_prog(sa, NFS_PROGRAM, NFS_V3, IPPROTO_TCP, NULL)) { 5717c478bd9Sstevel@tonic-gate *proto = IPPROTO_TCP; 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate fh->fh3_length = mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len; 5757c478bd9Sstevel@tonic-gate bcopy(mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val, 5767c478bd9Sstevel@tonic-gate fh->fh3_u.data, fh->fh3_length); 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate out: 5797c478bd9Sstevel@tonic-gate xdr_free(myxdr_mountres3, (caddr_t)&mountres3); 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate if (dldebug) 5827c478bd9Sstevel@tonic-gate printf("mountnfs3: leaving\n"); 5837c478bd9Sstevel@tonic-gate return (ret); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate static int 5877c478bd9Sstevel@tonic-gate ping_prog(struct netbuf *call_addr, uint_t prog, uint_t vers, int proto, 5887c478bd9Sstevel@tonic-gate enum clnt_stat *statp) 5897c478bd9Sstevel@tonic-gate { 5907c478bd9Sstevel@tonic-gate struct knetconfig *knconf; 5917c478bd9Sstevel@tonic-gate enum clnt_stat stat; 5927c478bd9Sstevel@tonic-gate int retries = DEFAULT_RETRIES; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate switch (proto) { 5957c478bd9Sstevel@tonic-gate case IPPROTO_TCP: 5967c478bd9Sstevel@tonic-gate knconf = &dl_tcp_netconf; 5977c478bd9Sstevel@tonic-gate break; 5987c478bd9Sstevel@tonic-gate case IPPROTO_UDP: 5997c478bd9Sstevel@tonic-gate knconf = &dl_udp_netconf; 6007c478bd9Sstevel@tonic-gate break; 6017c478bd9Sstevel@tonic-gate default: 6027c478bd9Sstevel@tonic-gate return (0); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate do { 6067c478bd9Sstevel@tonic-gate stat = mycallrpc(knconf, call_addr, prog, vers, NULLPROC, 6077c478bd9Sstevel@tonic-gate xdr_void, NULL, xdr_void, NULL, 6087c478bd9Sstevel@tonic-gate DEFAULT_TIMEO, DEFAULT_RETRIES); 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate if (dldebug) 6117c478bd9Sstevel@tonic-gate printf("ping_prog: %d return %d (%s)\n", proto, stat, 6127c478bd9Sstevel@tonic-gate clnt_sperrno(stat)); 6137c478bd9Sstevel@tonic-gate /* 6147c478bd9Sstevel@tonic-gate * Special case for TCP, it may "timeout" because it failed 6157c478bd9Sstevel@tonic-gate * to establish an initial connection but it doesn't 6167c478bd9Sstevel@tonic-gate * actually retry, so we do the retry. 6177c478bd9Sstevel@tonic-gate * Persistence pays in diskless. 6187c478bd9Sstevel@tonic-gate */ 6197c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT && proto == IPPROTO_TCP && retries--); 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate if (statp != NULL) 6227c478bd9Sstevel@tonic-gate *statp = stat; 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) 6257c478bd9Sstevel@tonic-gate return (0); 6267c478bd9Sstevel@tonic-gate return (1); 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate static struct netbuf bootparam_addr; 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate /* 6327c478bd9Sstevel@tonic-gate * Returns after filling in the following global variables: 6337c478bd9Sstevel@tonic-gate * bootparam_addr, 6347c478bd9Sstevel@tonic-gate * utsname.nodename, 6357c478bd9Sstevel@tonic-gate * srpc_domain. 6367c478bd9Sstevel@tonic-gate */ 6377c478bd9Sstevel@tonic-gate static int 6387c478bd9Sstevel@tonic-gate whoami(void) 6397c478bd9Sstevel@tonic-gate { 640*cc2b7f04Sdduvall TIUSER *tiptr; 641*cc2b7f04Sdduvall struct netbuf sa; 642*cc2b7f04Sdduvall struct netbuf req; 643*cc2b7f04Sdduvall struct bp_whoami_arg arg; 644*cc2b7f04Sdduvall struct bp_whoami_res res; 645*cc2b7f04Sdduvall struct timeval tv; 646*cc2b7f04Sdduvall enum clnt_stat stat; 647*cc2b7f04Sdduvall int rc; 648*cc2b7f04Sdduvall size_t namelen; 649*cc2b7f04Sdduvall int printed_waiting_msg; 650*cc2b7f04Sdduvall 651*cc2b7f04Sdduvall if ((rc = t_kopen((file_t *)NULL, dl_udp_netconf.knc_rdev, 652*cc2b7f04Sdduvall FREAD|FWRITE, &tiptr, CRED())) != 0) { 6537c478bd9Sstevel@tonic-gate nfs_perror(rc, "whoami: t_kopen udp failed: %m.\n"); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate /* 6577c478bd9Sstevel@tonic-gate * Find out our local (IP) address. 6587c478bd9Sstevel@tonic-gate */ 6597c478bd9Sstevel@tonic-gate if (rc = revarp_myaddr(tiptr)) { 6607c478bd9Sstevel@tonic-gate nfs_perror(rc, "whoami: revarp_myaddr failed: %m.\n"); 6617c478bd9Sstevel@tonic-gate (void) t_kclose(tiptr, 0); 6627c478bd9Sstevel@tonic-gate return (rc); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* explicitly use the limited broadcast address */ 6667c478bd9Sstevel@tonic-gate init_netbuf(&sa); 6677c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)sa.buf)->sin_family = AF_INET; 6687c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)sa.buf)->sin_addr.s_addr = 6697c478bd9Sstevel@tonic-gate htonl(INADDR_BROADCAST); 6707c478bd9Sstevel@tonic-gate sa.len = sizeof (struct sockaddr_in); 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate /* 6737c478bd9Sstevel@tonic-gate * Pick up our local (IP) address. 6747c478bd9Sstevel@tonic-gate */ 6757c478bd9Sstevel@tonic-gate init_netbuf(&req); 6767c478bd9Sstevel@tonic-gate if (rc = ifioctl(tiptr, SIOCGIFADDR, &req)) { 6777c478bd9Sstevel@tonic-gate nfs_perror(rc, 6787c478bd9Sstevel@tonic-gate "whoami: couldn't get my IP address: %m.\n"); 6797c478bd9Sstevel@tonic-gate free_netbuf(&sa); 6807c478bd9Sstevel@tonic-gate free_netbuf(&req); 6817c478bd9Sstevel@tonic-gate (void) t_kclose(tiptr, 0); 6827c478bd9Sstevel@tonic-gate return (rc); 6837c478bd9Sstevel@tonic-gate } 684*cc2b7f04Sdduvall 6857c478bd9Sstevel@tonic-gate /* 6867c478bd9Sstevel@tonic-gate * Set up the arguments expected by bootparamd. 6877c478bd9Sstevel@tonic-gate */ 6887c478bd9Sstevel@tonic-gate arg.client_address.address_type = IP_ADDR_TYPE; 6897c478bd9Sstevel@tonic-gate bcopy(&((struct sockaddr_in *)req.buf)->sin_addr, 6907c478bd9Sstevel@tonic-gate &arg.client_address.bp_address.ip_addr, sizeof (struct in_addr)); 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate free_netbuf(&req); 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate init_netbuf(&bootparam_addr); 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate /* 6977c478bd9Sstevel@tonic-gate * Initial retransmission interval 6987c478bd9Sstevel@tonic-gate */ 6997c478bd9Sstevel@tonic-gate tv.tv_sec = DEFAULT_TIMEO; 7007c478bd9Sstevel@tonic-gate tv.tv_usec = 0; 7017c478bd9Sstevel@tonic-gate res.client_name = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP); 7027c478bd9Sstevel@tonic-gate res.domain_name = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP); 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate /* 7057c478bd9Sstevel@tonic-gate * Do a broadcast call to find a bootparam daemon that 7067c478bd9Sstevel@tonic-gate * will tell us our hostname, domainname and any 7077c478bd9Sstevel@tonic-gate * router that we have to use to talk to our NFS server. 7087c478bd9Sstevel@tonic-gate */ 7097c478bd9Sstevel@tonic-gate printed_waiting_msg = 0; 7107c478bd9Sstevel@tonic-gate do { 7117c478bd9Sstevel@tonic-gate /* 7127c478bd9Sstevel@tonic-gate * pmap_rmt_call will first try the SunOS portmapper 7137c478bd9Sstevel@tonic-gate * and if no reply is received will then try the SVR4 7147c478bd9Sstevel@tonic-gate * rpcbind. 7157c478bd9Sstevel@tonic-gate * Either way, `bootparam_addr' will be set to the 7167c478bd9Sstevel@tonic-gate * correct address for the bootparamd that responds. 7177c478bd9Sstevel@tonic-gate */ 7187c478bd9Sstevel@tonic-gate stat = pmap_rmt_call(&dl_udp_netconf, &sa, TRUE, BOOTPARAMPROG, 7197c478bd9Sstevel@tonic-gate BOOTPARAMVERS, BOOTPARAMPROC_WHOAMI, 7207c478bd9Sstevel@tonic-gate xdr_bp_whoami_arg, (caddr_t)&arg, 7217c478bd9Sstevel@tonic-gate xdr_bp_whoami_res, (caddr_t)&res, 7227c478bd9Sstevel@tonic-gate tv, &bootparam_addr); 7237c478bd9Sstevel@tonic-gate if (stat == RPC_TIMEDOUT && !printed_waiting_msg) { 7247c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 7257c478bd9Sstevel@tonic-gate "No bootparam server responding; still trying"); 7267c478bd9Sstevel@tonic-gate printed_waiting_msg = 1; 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate /* 7297c478bd9Sstevel@tonic-gate * Retransmission interval for second and subsequent tries. 7307c478bd9Sstevel@tonic-gate * We expect first pmap_rmt_call to retransmit and backoff to 7317c478bd9Sstevel@tonic-gate * at least this value. 7327c478bd9Sstevel@tonic-gate */ 7337c478bd9Sstevel@tonic-gate tv.tv_sec = WHOAMI_TIMEO; 7347c478bd9Sstevel@tonic-gate tv.tv_usec = 0; 7357c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT); 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate if (printed_waiting_msg) 7387c478bd9Sstevel@tonic-gate printf("Bootparam response received\n"); 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) { 7417c478bd9Sstevel@tonic-gate /* XXX should get real error here */ 7427c478bd9Sstevel@tonic-gate rc = ENXIO; 7437c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 7447c478bd9Sstevel@tonic-gate "whoami: bootparam RPC failed: error %d (%s).", 7457c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat)); 7467c478bd9Sstevel@tonic-gate goto done; 7477c478bd9Sstevel@tonic-gate } 748*cc2b7f04Sdduvall 7497c478bd9Sstevel@tonic-gate namelen = strlen(res.client_name); 7507c478bd9Sstevel@tonic-gate if (namelen > sizeof (utsname.nodename)) { 7517c478bd9Sstevel@tonic-gate printf("whoami: hostname too long"); 7527c478bd9Sstevel@tonic-gate rc = ENAMETOOLONG; 7537c478bd9Sstevel@tonic-gate goto done; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate if (namelen != 0) { 7567c478bd9Sstevel@tonic-gate bcopy(res.client_name, &utsname.nodename, namelen); 7577c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?hostname: %s\n", utsname.nodename); 7587c478bd9Sstevel@tonic-gate } else { 7597c478bd9Sstevel@tonic-gate printf("whoami: no host name\n"); 7607c478bd9Sstevel@tonic-gate rc = ENXIO; 7617c478bd9Sstevel@tonic-gate goto done; 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate namelen = strlen(res.domain_name); 7657c478bd9Sstevel@tonic-gate if (namelen != 0) { 7667c478bd9Sstevel@tonic-gate if (namelen > SYS_NMLN) { 7677c478bd9Sstevel@tonic-gate printf("whoami: domainname too long"); 7687c478bd9Sstevel@tonic-gate rc = ENAMETOOLONG; 7697c478bd9Sstevel@tonic-gate goto done; 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate bcopy(res.domain_name, &srpc_domain, namelen); 7727c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?domainname: %s\n", srpc_domain); 7737c478bd9Sstevel@tonic-gate } else { 7747c478bd9Sstevel@tonic-gate printf("whoami: no domain name\n"); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate if (res.router_address.address_type == IP_ADDR_TYPE) { 7787c478bd9Sstevel@tonic-gate struct rtentry rtentry; 7797c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 780*cc2b7f04Sdduvall struct in_addr ipaddr; 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate bcopy(&res.router_address.bp_address.ip_addr, &ipaddr, 783*cc2b7f04Sdduvall sizeof (struct in_addr)); 7847c478bd9Sstevel@tonic-gate 785*cc2b7f04Sdduvall if (ipaddr.s_addr != (uint32_t)0) { 7867c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&rtentry.rt_dst; 7877c478bd9Sstevel@tonic-gate bzero(sin, sizeof (*sin)); 7887c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 789*cc2b7f04Sdduvall 7907c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&rtentry.rt_gateway; 7917c478bd9Sstevel@tonic-gate bzero(sin, sizeof (*sin)); 7927c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 793*cc2b7f04Sdduvall sin->sin_addr.s_addr = ipaddr.s_addr; 794*cc2b7f04Sdduvall 7957c478bd9Sstevel@tonic-gate rtentry.rt_flags = RTF_GATEWAY | RTF_UP; 796*cc2b7f04Sdduvall 7977c478bd9Sstevel@tonic-gate if (rc = rtioctl(tiptr, SIOCADDRT, &rtentry)) { 7987c478bd9Sstevel@tonic-gate nfs_perror(rc, 7997c478bd9Sstevel@tonic-gate "whoami: couldn't add route: %m.\n"); 8007c478bd9Sstevel@tonic-gate goto done; 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate } else { 8047c478bd9Sstevel@tonic-gate printf("whoami: unknown gateway addr family %d\n", 8057c478bd9Sstevel@tonic-gate res.router_address.address_type); 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate done: 8087c478bd9Sstevel@tonic-gate kmem_free(res.client_name, MAX_MACHINE_NAME + 1); 8097c478bd9Sstevel@tonic-gate kmem_free(res.domain_name, MAX_MACHINE_NAME + 1); 8107c478bd9Sstevel@tonic-gate free_netbuf(&sa); 8117c478bd9Sstevel@tonic-gate (void) t_kclose(tiptr, 0); 8127c478bd9Sstevel@tonic-gate return (rc); 8137c478bd9Sstevel@tonic-gate } 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate /* 8167c478bd9Sstevel@tonic-gate * Returns: 8177c478bd9Sstevel@tonic-gate * 1) The ascii form of our root servers name in `server_name'. 8187c478bd9Sstevel@tonic-gate * 2) Actual network address of our root server in `server_address'. 8197c478bd9Sstevel@tonic-gate * 3) Whatever BOOTPARAMPROC_GETFILE returns for the fileid key, in 8207c478bd9Sstevel@tonic-gate * `server_path'. If fileid is "root", it is the pathname of our 8217c478bd9Sstevel@tonic-gate * root on the server. 8227c478bd9Sstevel@tonic-gate */ 8237c478bd9Sstevel@tonic-gate static int 8247c478bd9Sstevel@tonic-gate getfile(char *fileid, 8257c478bd9Sstevel@tonic-gate char *server_name, struct netbuf *server_address, char *server_path) 8267c478bd9Sstevel@tonic-gate { 8277c478bd9Sstevel@tonic-gate struct bp_getfile_arg arg; 8287c478bd9Sstevel@tonic-gate struct bp_getfile_res res; 8297c478bd9Sstevel@tonic-gate enum clnt_stat stat; 8307c478bd9Sstevel@tonic-gate int root = FALSE; 8317c478bd9Sstevel@tonic-gate static int using_cache = FALSE; 832*cc2b7f04Sdduvall struct in_addr ipaddr; 8337c478bd9Sstevel@tonic-gate int timeo = DEFAULT_TIMEO; 8347c478bd9Sstevel@tonic-gate int retries = DEFAULT_RETRIES; 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate if (dldebug) 8377c478bd9Sstevel@tonic-gate printf("getfile: entered\n"); 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate /* 8407c478bd9Sstevel@tonic-gate * Call cacheinfo() to see whether we can satisfy this request by using 8417c478bd9Sstevel@tonic-gate * the information cached in memory by the boot program's DHCP 8427c478bd9Sstevel@tonic-gate * implementation or boot properties rather than consult BOOTPARAMS, 8437c478bd9Sstevel@tonic-gate * but while preserving the semantics of getfile(). We know that 8447c478bd9Sstevel@tonic-gate * the server name is SYS_NMLN in length, and server_path is 8457c478bd9Sstevel@tonic-gate * MAXPATHLEN (pn_alloc). 8467c478bd9Sstevel@tonic-gate */ 8477c478bd9Sstevel@tonic-gate if (strcmp(fileid, "root") == 0) { 8487c478bd9Sstevel@tonic-gate if (cacheinfo(server_name, SYS_NMLN, server_address, 8497c478bd9Sstevel@tonic-gate server_path, MAXPATHLEN) == 0) { 8507c478bd9Sstevel@tonic-gate using_cache = TRUE; 8517c478bd9Sstevel@tonic-gate return (0); 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate root = TRUE; 8547c478bd9Sstevel@tonic-gate } 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate /* 8577c478bd9Sstevel@tonic-gate * If using cache, rootopts is already available. 8587c478bd9Sstevel@tonic-gate */ 8597c478bd9Sstevel@tonic-gate if (strcmp(fileid, "rootopts") == 0 && using_cache == TRUE) { 8607c478bd9Sstevel@tonic-gate return (rootopts[0] != 0 ? 0 : ENXIO); 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate if (bootparam_addr.len == 0) { 8647c478bd9Sstevel@tonic-gate return (ENXIO); 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate arg.client_name = (caddr_t)&utsname.nodename; 8677c478bd9Sstevel@tonic-gate arg.file_id = fileid; 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate bzero(&res, sizeof (res)); 8707c478bd9Sstevel@tonic-gate res.server_name = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP); 8717c478bd9Sstevel@tonic-gate res.server_path = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP); 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate /* 8747c478bd9Sstevel@tonic-gate * If we are not looking up the root file, we are looking 8757c478bd9Sstevel@tonic-gate * up a non-critical option that should timeout quickly. 8767c478bd9Sstevel@tonic-gate */ 8777c478bd9Sstevel@tonic-gate if (!root) { 8787c478bd9Sstevel@tonic-gate timeo = GETFILE_TIMEO; 8797c478bd9Sstevel@tonic-gate retries = GETFILE_RETRIES; 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate /* 8837c478bd9Sstevel@tonic-gate * bootparam_addr was filled in by the call to 8847c478bd9Sstevel@tonic-gate * whoami(), so now send an rpc message to the 8857c478bd9Sstevel@tonic-gate * bootparam daemon requesting our server information. 8867c478bd9Sstevel@tonic-gate * Use UDP to talk to bootparms. 8877c478bd9Sstevel@tonic-gate */ 8887c478bd9Sstevel@tonic-gate stat = mycallrpc(&dl_udp_netconf, &bootparam_addr, 8897c478bd9Sstevel@tonic-gate (rpcprog_t)BOOTPARAMPROG, (rpcvers_t)BOOTPARAMVERS, 8907c478bd9Sstevel@tonic-gate (rpcproc_t)BOOTPARAMPROC_GETFILE, 8917c478bd9Sstevel@tonic-gate xdr_bp_getfile_arg, (caddr_t)&arg, 8927c478bd9Sstevel@tonic-gate xdr_bp_getfile_res, (caddr_t)&res, 8937c478bd9Sstevel@tonic-gate timeo, retries); 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate if (stat == RPC_SUCCESS) { 8967c478bd9Sstevel@tonic-gate (void) strcpy(server_name, res.server_name); 8977c478bd9Sstevel@tonic-gate (void) strcpy(server_path, res.server_path); 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate kmem_free(res.server_name, MAX_MACHINE_NAME + 1); 9017c478bd9Sstevel@tonic-gate kmem_free(res.server_path, MAX_MACHINE_NAME + 1); 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) { 9047c478bd9Sstevel@tonic-gate if (root) 9057c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "getfile: RPC failed: error %d (%s).", 9067c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat)); 9077c478bd9Sstevel@tonic-gate return ((stat == RPC_TIMEDOUT) ? ETIMEDOUT : ENXIO); /* XXX */ 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate if (*server_path == '\0') 9117c478bd9Sstevel@tonic-gate return (EINVAL); 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* 9147c478bd9Sstevel@tonic-gate * If the fileid is "root", we must get back a server name, for 9157c478bd9Sstevel@tonic-gate * other parameters a server name is not required 9167c478bd9Sstevel@tonic-gate */ 9177c478bd9Sstevel@tonic-gate if (!root) { 9187c478bd9Sstevel@tonic-gate if (dldebug) 9197c478bd9Sstevel@tonic-gate printf("getfile: leaving: non-root\n"); 9207c478bd9Sstevel@tonic-gate return (0); 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate if (*server_name == '\0') 9247c478bd9Sstevel@tonic-gate return (EINVAL); 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate switch (res.server_address.address_type) { 9277c478bd9Sstevel@tonic-gate case IP_ADDR_TYPE: 9287c478bd9Sstevel@tonic-gate /* 9297c478bd9Sstevel@tonic-gate * server_address is where we will get our root 9307c478bd9Sstevel@tonic-gate * from. 9317c478bd9Sstevel@tonic-gate */ 9327c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)server_address->buf)->sin_family = 9337c478bd9Sstevel@tonic-gate AF_INET; 9347c478bd9Sstevel@tonic-gate bcopy(&res.server_address.bp_address.ip_addr, 9357c478bd9Sstevel@tonic-gate &ipaddr, sizeof (ipaddr)); 936*cc2b7f04Sdduvall if (ipaddr.s_addr == 0) 9377c478bd9Sstevel@tonic-gate return (EINVAL); 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)server_address->buf)->sin_addr.s_addr = 940*cc2b7f04Sdduvall ipaddr.s_addr; 9417c478bd9Sstevel@tonic-gate server_address->len = sizeof (struct sockaddr_in); 9427c478bd9Sstevel@tonic-gate break; 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate default: 9457c478bd9Sstevel@tonic-gate printf("getfile: unknown address type %d\n", 9467c478bd9Sstevel@tonic-gate res.server_address.address_type); 9477c478bd9Sstevel@tonic-gate return (EPROTONOSUPPORT); 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate if (dldebug) 9507c478bd9Sstevel@tonic-gate printf("getfile: leaving\n"); 9517c478bd9Sstevel@tonic-gate return (0); 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate /* 9557c478bd9Sstevel@tonic-gate * If the boot property "bootp-response" exists, then inetboot performed a 9567c478bd9Sstevel@tonic-gate * successful DHCP lease acquisition for us and left the resultant ACK packet 9577c478bd9Sstevel@tonic-gate * encoded at that location. 9587c478bd9Sstevel@tonic-gate * 9597c478bd9Sstevel@tonic-gate * If no such property exists (or the information is incomplete or garbled), 9607c478bd9Sstevel@tonic-gate * the function returns -1. 9617c478bd9Sstevel@tonic-gate */ 9627c478bd9Sstevel@tonic-gate int 9637c478bd9Sstevel@tonic-gate dhcpinit(void) 9647c478bd9Sstevel@tonic-gate { 9657c478bd9Sstevel@tonic-gate int rc, i; 9667c478bd9Sstevel@tonic-gate char *p; 9677c478bd9Sstevel@tonic-gate struct in_addr braddr; 9687c478bd9Sstevel@tonic-gate struct in_addr subnet; 9697c478bd9Sstevel@tonic-gate DHCP_OPT *doptp; 9707c478bd9Sstevel@tonic-gate TIUSER *tiptr; 9717c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 9727c478bd9Sstevel@tonic-gate int true_dhcacklen; 9737c478bd9Sstevel@tonic-gate char *ackp; 9747c478bd9Sstevel@tonic-gate static int once_only = 0; 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate if (once_only == 1) { 9777c478bd9Sstevel@tonic-gate return (0); 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate once_only = 1; 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate if (dhcack == NULL) { 9827c478bd9Sstevel@tonic-gate return (-1); 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate ackp = (char *)(dhcack + IFNAMSIZ); 9867c478bd9Sstevel@tonic-gate true_dhcacklen = strlen(ackp); 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate /* 9897c478bd9Sstevel@tonic-gate * Since we expect the "bootp-response" property to have 9907c478bd9Sstevel@tonic-gate * been encoded via octet_to_hexascii(), its length should 9917c478bd9Sstevel@tonic-gate * always be even. 9927c478bd9Sstevel@tonic-gate */ 9937c478bd9Sstevel@tonic-gate ASSERT((true_dhcacklen % 2) == 0); 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate if (dldebug) { 9967c478bd9Sstevel@tonic-gate printf("dhcp: dhcack %p, len %d\n", (void *)dhcack, 9977c478bd9Sstevel@tonic-gate true_dhcacklen + IFNAMSIZ); 9987c478bd9Sstevel@tonic-gate } 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate pl = kmem_alloc(sizeof (PKT_LIST), KM_SLEEP); 10017c478bd9Sstevel@tonic-gate pl->len = true_dhcacklen / 2; 10027c478bd9Sstevel@tonic-gate pl->pkt = kmem_alloc(pl->len, KM_SLEEP); 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate /* 10057c478bd9Sstevel@tonic-gate * Store our interface name in the reserved block at the 10067c478bd9Sstevel@tonic-gate * head of our packet. For x86, ifname is not initialized 10077c478bd9Sstevel@tonic-gate * in the netinstall case and dhcack interface name is 10087c478bd9Sstevel@tonic-gate * set in strplumb(). So we only copy the name if ifname 10097c478bd9Sstevel@tonic-gate * is set properly. 10107c478bd9Sstevel@tonic-gate */ 10117c478bd9Sstevel@tonic-gate if (ifname[0]) 10127c478bd9Sstevel@tonic-gate (void) strncpy(dhcack, ifname, IFNAMSIZ - 1); 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate /* skip over the interface name section */ 10157c478bd9Sstevel@tonic-gate if (hexascii_to_octet(ackp, true_dhcacklen, (uchar_t *)pl->pkt, 10167c478bd9Sstevel@tonic-gate &(pl->len)) != 0) { 10177c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 10187c478bd9Sstevel@tonic-gate "dhcp: boot dhcp cache is corrupted."); 10197c478bd9Sstevel@tonic-gate kmem_free(pl->pkt, pl->len); 10207c478bd9Sstevel@tonic-gate kmem_free(pl, sizeof (PKT_LIST)); 10217c478bd9Sstevel@tonic-gate pl = NULL; 10227c478bd9Sstevel@tonic-gate return (-1); 10237c478bd9Sstevel@tonic-gate } 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate /* remember the server_ip in dhcack */ 10267c478bd9Sstevel@tonic-gate bcopy((uchar_t *)pl->pkt + 20, dhcp_server_ip, 4); 10277c478bd9Sstevel@tonic-gate bzero(pl->opts, (DHCP_LAST_OPT + 1) * sizeof (DHCP_OPT *)); 10287c478bd9Sstevel@tonic-gate bzero(pl->vs, (VS_OPTION_END - VS_OPTION_START + 1) * 10297c478bd9Sstevel@tonic-gate sizeof (DHCP_OPT *)); 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate if (dhcp_options_scan(pl, B_TRUE) != 0) { 10327c478bd9Sstevel@tonic-gate /* garbled packet */ 10337c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: DHCP packet parsing failed"); 10347c478bd9Sstevel@tonic-gate kmem_free(pl->pkt, pl->len); 10357c478bd9Sstevel@tonic-gate kmem_free(pl, sizeof (PKT_LIST)); 10367c478bd9Sstevel@tonic-gate pl = NULL; 10377c478bd9Sstevel@tonic-gate return (-1); 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* set node name */ 10417c478bd9Sstevel@tonic-gate if (pl->opts[CD_HOSTNAME] != NULL) { 10427c478bd9Sstevel@tonic-gate doptp = pl->opts[CD_HOSTNAME]; 10437c478bd9Sstevel@tonic-gate i = doptp->len; 10447c478bd9Sstevel@tonic-gate if (i >= SYS_NMLN) { 10457c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: Hostname is too long"); 10467c478bd9Sstevel@tonic-gate } else { 10477c478bd9Sstevel@tonic-gate bcopy(doptp->value, utsname.nodename, i); 10487c478bd9Sstevel@tonic-gate utsname.nodename[i] = '\0'; 10497c478bd9Sstevel@tonic-gate if (dldebug) { 10507c478bd9Sstevel@tonic-gate printf("hostname is %s\n", 10517c478bd9Sstevel@tonic-gate utsname.nodename); 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate } 10547c478bd9Sstevel@tonic-gate } 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate /* Set NIS domain name. */ 10577c478bd9Sstevel@tonic-gate p = NULL; 10587c478bd9Sstevel@tonic-gate if (pl->opts[CD_NIS_DOMAIN] != NULL) { 10597c478bd9Sstevel@tonic-gate doptp = pl->opts[CD_NIS_DOMAIN]; 10607c478bd9Sstevel@tonic-gate i = doptp->len; 10617c478bd9Sstevel@tonic-gate p = (caddr_t)doptp->value; 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate if (p != NULL) { 10647c478bd9Sstevel@tonic-gate if (i > SYS_NMLN) { 10657c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 10667c478bd9Sstevel@tonic-gate "dhcp: NIS domainname too long."); 10677c478bd9Sstevel@tonic-gate } else { 10687c478bd9Sstevel@tonic-gate bcopy(p, srpc_domain, i); 10697c478bd9Sstevel@tonic-gate srpc_domain[i] = '\0'; 10707c478bd9Sstevel@tonic-gate if (dldebug) 10717c478bd9Sstevel@tonic-gate printf("dhcp: NIS domain name is %s\n", 10727c478bd9Sstevel@tonic-gate srpc_domain); 10737c478bd9Sstevel@tonic-gate } 10747c478bd9Sstevel@tonic-gate } 10757c478bd9Sstevel@tonic-gate 10767c478bd9Sstevel@tonic-gate /* fetch netmask */ 10777c478bd9Sstevel@tonic-gate if (pl->opts[CD_SUBNETMASK] != NULL) { 10787c478bd9Sstevel@tonic-gate doptp = pl->opts[CD_SUBNETMASK]; 10797c478bd9Sstevel@tonic-gate if (doptp->len != sizeof (struct in_addr)) { 10807c478bd9Sstevel@tonic-gate pl->opts[CD_SUBNETMASK] = NULL; 10817c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: netmask option malformed"); 10827c478bd9Sstevel@tonic-gate } else { 10837c478bd9Sstevel@tonic-gate bcopy(doptp->value, &subnet, sizeof (struct in_addr)); 10847c478bd9Sstevel@tonic-gate if (dldebug) 10857c478bd9Sstevel@tonic-gate printf("dhcp: setting netmask to: %s\n", 10867c478bd9Sstevel@tonic-gate inet_ntoa(subnet)); 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate } else { 10897c478bd9Sstevel@tonic-gate struct in_addr myIPaddr; 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate myIPaddr.s_addr = pl->pkt->yiaddr.s_addr; 10927c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: no subnet mask supplied - inferring"); 10937c478bd9Sstevel@tonic-gate if (IN_CLASSA(ntohl(myIPaddr.s_addr))) 10947c478bd9Sstevel@tonic-gate subnet.s_addr = htonl(IN_CLASSA_NET); 10957c478bd9Sstevel@tonic-gate else if (IN_CLASSB(ntohl(myIPaddr.s_addr))) 10967c478bd9Sstevel@tonic-gate subnet.s_addr = htonl(IN_CLASSB_NET); 10977c478bd9Sstevel@tonic-gate else if (IN_CLASSC(ntohl(myIPaddr.s_addr))) 10987c478bd9Sstevel@tonic-gate subnet.s_addr = htonl(IN_CLASSC_NET); 10997c478bd9Sstevel@tonic-gate else 11007c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: bad IP address (%s)", 11017c478bd9Sstevel@tonic-gate inet_ntoa(myIPaddr)); 11027c478bd9Sstevel@tonic-gate } 11037c478bd9Sstevel@tonic-gate /* and broadcast address */ 11047c478bd9Sstevel@tonic-gate if (pl->opts[CD_BROADCASTADDR] != NULL) { 11057c478bd9Sstevel@tonic-gate doptp = pl->opts[CD_BROADCASTADDR]; 11067c478bd9Sstevel@tonic-gate if (doptp->len != sizeof (struct in_addr)) { 11077c478bd9Sstevel@tonic-gate pl->opts[CD_BROADCASTADDR] = NULL; 11087c478bd9Sstevel@tonic-gate if (dldebug) 11097c478bd9Sstevel@tonic-gate printf("dhcp: broadcast address len %d\n", 11107c478bd9Sstevel@tonic-gate doptp->len); 11117c478bd9Sstevel@tonic-gate } else { 11127c478bd9Sstevel@tonic-gate bcopy(doptp->value, &braddr, sizeof (struct in_addr)); 11137c478bd9Sstevel@tonic-gate if (dldebug) 11147c478bd9Sstevel@tonic-gate printf("dhcp: setting broadcast addr to: %s\n", 11157c478bd9Sstevel@tonic-gate inet_ntoa(braddr)); 11167c478bd9Sstevel@tonic-gate } 11177c478bd9Sstevel@tonic-gate } else { 11187c478bd9Sstevel@tonic-gate if (dldebug) 11197c478bd9Sstevel@tonic-gate printf("dhcp: no broadcast address supplied\n"); 11207c478bd9Sstevel@tonic-gate braddr.s_addr = htonl(INADDR_BROADCAST); 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate /* and plumb and initialize interface */ 11237c478bd9Sstevel@tonic-gate if ((rc = t_kopen((file_t *)NULL, dl_udp_netconf.knc_rdev, 11247c478bd9Sstevel@tonic-gate FREAD|FWRITE, &tiptr, CRED())) == 0) { 11257c478bd9Sstevel@tonic-gate if (rc = dlifconfig(tiptr, &pl->pkt->yiaddr, &subnet, 11267c478bd9Sstevel@tonic-gate &braddr)) { 11277c478bd9Sstevel@tonic-gate nfs_perror(rc, "dhcp: dlifconfig failed: %m\n"); 11287c478bd9Sstevel@tonic-gate kmem_free(pl->pkt, pl->len); 11297c478bd9Sstevel@tonic-gate kmem_free(pl, sizeof (PKT_LIST)); 11307c478bd9Sstevel@tonic-gate pl = NULL; 11317c478bd9Sstevel@tonic-gate (void) t_kclose(tiptr, 0); 11327c478bd9Sstevel@tonic-gate return (-1); 11337c478bd9Sstevel@tonic-gate } 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate /* add routes */ 11367c478bd9Sstevel@tonic-gate if (pl->opts[CD_ROUTER] != NULL) { 11377c478bd9Sstevel@tonic-gate doptp = pl->opts[CD_ROUTER]; 11387c478bd9Sstevel@tonic-gate if ((doptp->len % sizeof (struct in_addr)) != 0) { 11397c478bd9Sstevel@tonic-gate pl->opts[CD_ROUTER] = NULL; 11407c478bd9Sstevel@tonic-gate } else { 11417c478bd9Sstevel@tonic-gate int nrouters; 11427c478bd9Sstevel@tonic-gate uchar_t *tp; 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate nrouters = doptp->len / sizeof (struct in_addr); 11457c478bd9Sstevel@tonic-gate for (tp = doptp->value, i = 0; i < nrouters; 11467c478bd9Sstevel@tonic-gate i++) { 11477c478bd9Sstevel@tonic-gate struct in_addr defr; 11487c478bd9Sstevel@tonic-gate struct rtentry rtentry; 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate bcopy(tp, &defr, 11517c478bd9Sstevel@tonic-gate sizeof (struct in_addr)); 11527c478bd9Sstevel@tonic-gate if (defr.s_addr == 0) 11537c478bd9Sstevel@tonic-gate continue; 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate sin = (struct 11567c478bd9Sstevel@tonic-gate sockaddr_in *)&rtentry.rt_dst; 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate bzero(sin, sizeof (*sin)); 11597c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate sin = (struct 11627c478bd9Sstevel@tonic-gate sockaddr_in *)&rtentry.rt_gateway; 11637c478bd9Sstevel@tonic-gate bzero(sin, sizeof (*sin)); 11647c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 11657c478bd9Sstevel@tonic-gate sin->sin_addr = defr; 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate rtentry.rt_flags = RTF_GATEWAY | RTF_UP; 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate if (rc = rtioctl(tiptr, SIOCADDRT, 11707c478bd9Sstevel@tonic-gate &rtentry)) { 11717c478bd9Sstevel@tonic-gate nfs_perror(rc, 11727c478bd9Sstevel@tonic-gate "dhcp: couldn't add route " 11737c478bd9Sstevel@tonic-gate "to %s: %m.\n", 11747c478bd9Sstevel@tonic-gate inet_ntoa(defr)); 11757c478bd9Sstevel@tonic-gate continue; 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate if (dldebug) { 11787c478bd9Sstevel@tonic-gate printf("dhcp: added route %s\n", 11797c478bd9Sstevel@tonic-gate inet_ntoa(defr)); 11807c478bd9Sstevel@tonic-gate } 11817c478bd9Sstevel@tonic-gate tp += sizeof (struct in_addr); 11827c478bd9Sstevel@tonic-gate } 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate } 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate (void) t_kclose(tiptr, 0); 11877c478bd9Sstevel@tonic-gate } 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate if (dldebug) 11907c478bd9Sstevel@tonic-gate printf("dhcpinit: leaving\n"); 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate return (0); 11937c478bd9Sstevel@tonic-gate } 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate /* 11967c478bd9Sstevel@tonic-gate * Initialize nfs mount info from properties and dhcp response. 11977c478bd9Sstevel@tonic-gate */ 11987c478bd9Sstevel@tonic-gate static void 11997c478bd9Sstevel@tonic-gate cacheinit(void) 12007c478bd9Sstevel@tonic-gate { 12017c478bd9Sstevel@tonic-gate char *str; 12027c478bd9Sstevel@tonic-gate DHCP_OPT *doptp; 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate (void) ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 12057c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, BP_SERVER_PATH, &server_path_c); 12067c478bd9Sstevel@tonic-gate (void) ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 12077c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, BP_SERVER_NAME, &server_name_c); 12087c478bd9Sstevel@tonic-gate if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 12097c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, BP_SERVER_ROOTOPTS, &str) == DDI_SUCCESS) { 12107c478bd9Sstevel@tonic-gate (void) strncpy(rootopts, str, 255); 12117c478bd9Sstevel@tonic-gate ddi_prop_free(str); 12127c478bd9Sstevel@tonic-gate } 12137c478bd9Sstevel@tonic-gate if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 12147c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, BP_SERVER_IP, &str) == DDI_SUCCESS) { 12157c478bd9Sstevel@tonic-gate if (inet_aton(str, server_ip) != 0) 12167c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "server_ipaddr %s is invalid\n", 12177c478bd9Sstevel@tonic-gate str); 12187c478bd9Sstevel@tonic-gate ddi_prop_free(str); 12197c478bd9Sstevel@tonic-gate if (dldebug) 12207c478bd9Sstevel@tonic-gate printf("server ip is %s\n", 12217c478bd9Sstevel@tonic-gate inet_ntoa(*(struct in_addr *)server_ip)); 12227c478bd9Sstevel@tonic-gate } 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate if (pl == NULL) 12257c478bd9Sstevel@tonic-gate return; 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate /* extract root path in server_path */ 12287c478bd9Sstevel@tonic-gate if (server_path_c == NULL) { 12297c478bd9Sstevel@tonic-gate doptp = pl->vs[VS_NFSMNT_ROOTPATH]; 12307c478bd9Sstevel@tonic-gate if (doptp != NULL) { 12317c478bd9Sstevel@tonic-gate server_path_c = kmem_alloc(doptp->len + 1, KM_SLEEP); 12327c478bd9Sstevel@tonic-gate bcopy(doptp->value, server_path_c, doptp->len); 12337c478bd9Sstevel@tonic-gate server_path_c[doptp->len] = '\0'; 12347c478bd9Sstevel@tonic-gate if (dldebug) 12357c478bd9Sstevel@tonic-gate printf("dhcp: root path %s\n", server_path_c); 12367c478bd9Sstevel@tonic-gate } else { 12377c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: root server path missing"); 12387c478bd9Sstevel@tonic-gate } 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate /* set server_name */ 12427c478bd9Sstevel@tonic-gate if (server_name_c == NULL) { 12437c478bd9Sstevel@tonic-gate doptp = pl->vs[VS_NFSMNT_ROOTSRVR_NAME]; 12447c478bd9Sstevel@tonic-gate if (doptp != NULL) { 12457c478bd9Sstevel@tonic-gate server_name_c = kmem_alloc(doptp->len + 1, KM_SLEEP); 12467c478bd9Sstevel@tonic-gate bcopy(doptp->value, server_name_c, doptp->len); 12477c478bd9Sstevel@tonic-gate server_name_c[doptp->len] = '\0'; 12487c478bd9Sstevel@tonic-gate if (dldebug) 12497c478bd9Sstevel@tonic-gate printf("dhcp: root server name %s\n", 12507c478bd9Sstevel@tonic-gate server_name_c); 12517c478bd9Sstevel@tonic-gate } else { 12527c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: root server name missing"); 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate /* set root server_address */ 12577c478bd9Sstevel@tonic-gate if ((*(uint_t *)server_ip) == 0) { 12587c478bd9Sstevel@tonic-gate doptp = pl->vs[VS_NFSMNT_ROOTSRVR_IP]; 12597c478bd9Sstevel@tonic-gate if (doptp) { 12607c478bd9Sstevel@tonic-gate bcopy(doptp->value, server_ip, sizeof (server_ip)); 12617c478bd9Sstevel@tonic-gate if (dldebug) { 12627c478bd9Sstevel@tonic-gate printf("dhcp: root server IP address %s\n", 12637c478bd9Sstevel@tonic-gate inet_ntoa(*(struct in_addr *)server_ip)); 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate } else { 12667c478bd9Sstevel@tonic-gate if (dldebug) 12677c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 12687c478bd9Sstevel@tonic-gate "dhcp: file server ip address missing," 12697c478bd9Sstevel@tonic-gate " fallback to dhcp server as file server"); 12707c478bd9Sstevel@tonic-gate bcopy(dhcp_server_ip, server_ip, sizeof (server_ip)); 12717c478bd9Sstevel@tonic-gate } 12727c478bd9Sstevel@tonic-gate } 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate /* set root file system mount options */ 12757c478bd9Sstevel@tonic-gate if (rootopts[0] == 0) { 12767c478bd9Sstevel@tonic-gate doptp = pl->vs[VS_NFSMNT_ROOTOPTS]; 12777c478bd9Sstevel@tonic-gate if (doptp != NULL && doptp->len < 255) { 12787c478bd9Sstevel@tonic-gate bcopy(doptp->value, rootopts, doptp->len); 12797c478bd9Sstevel@tonic-gate rootopts[doptp->len] = '\0'; 12807c478bd9Sstevel@tonic-gate if (dldebug) 12817c478bd9Sstevel@tonic-gate printf("dhcp: rootopts %s\n", rootopts); 12827c478bd9Sstevel@tonic-gate } else if (dldebug) { 12837c478bd9Sstevel@tonic-gate printf("dhcp: no rootopts or too long\n"); 12847c478bd9Sstevel@tonic-gate /* not an error */ 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate } 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate /* now we are done with pl, just free it */ 12897c478bd9Sstevel@tonic-gate kmem_free(pl->pkt, pl->len); 12907c478bd9Sstevel@tonic-gate kmem_free(pl, sizeof (PKT_LIST)); 12917c478bd9Sstevel@tonic-gate pl = NULL; 12927c478bd9Sstevel@tonic-gate } 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate static int 12957c478bd9Sstevel@tonic-gate cacheinfo(char *name, int namelen, 12967c478bd9Sstevel@tonic-gate struct netbuf *server_address, char *rootpath, int pathlen) 12977c478bd9Sstevel@tonic-gate { 12987c478bd9Sstevel@tonic-gate static int init_done = 0; 12997c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate if (init_done == 0) { 13027c478bd9Sstevel@tonic-gate cacheinit(); 13037c478bd9Sstevel@tonic-gate init_done = 1; 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate /* server_path is a reliable indicator of cache availability */ 13077c478bd9Sstevel@tonic-gate if (server_path_c == NULL) 13087c478bd9Sstevel@tonic-gate return (-1); 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate (void) strncpy(rootpath, server_path_c, pathlen); 13117c478bd9Sstevel@tonic-gate if (server_name_c) { 13127c478bd9Sstevel@tonic-gate (void) strncpy(name, server_name_c, namelen); 13137c478bd9Sstevel@tonic-gate } else { 13147c478bd9Sstevel@tonic-gate (void) strncpy(name, "unknown", namelen); 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)server_address->buf; 13187c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 13197c478bd9Sstevel@tonic-gate server_address->len = sizeof (struct sockaddr_in); 13207c478bd9Sstevel@tonic-gate bcopy(server_ip, &sin->sin_addr, sizeof (struct in_addr)); 13217c478bd9Sstevel@tonic-gate return (0); 13227c478bd9Sstevel@tonic-gate } 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate /* 13257c478bd9Sstevel@tonic-gate * Set this interface's IP address and netmask, and bring it up. 13267c478bd9Sstevel@tonic-gate */ 13277c478bd9Sstevel@tonic-gate static int 13287c478bd9Sstevel@tonic-gate dlifconfig(TIUSER *tiptr, struct in_addr *myIPaddr, struct in_addr *mymask, 13297c478bd9Sstevel@tonic-gate struct in_addr *mybraddr) 13307c478bd9Sstevel@tonic-gate { 13317c478bd9Sstevel@tonic-gate int rc; 13327c478bd9Sstevel@tonic-gate struct netbuf sbuf; 13337c478bd9Sstevel@tonic-gate struct sockaddr_in sin; 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate if (dldebug) { 13367c478bd9Sstevel@tonic-gate printf("dlifconfig: entered\n"); 13377c478bd9Sstevel@tonic-gate printf("dlifconfig: addr %s\n", inet_ntoa(*myIPaddr)); 13387c478bd9Sstevel@tonic-gate printf("dlifconfig: mask %s\n", inet_ntoa(*mymask)); 13397c478bd9Sstevel@tonic-gate printf("dlifconfig: broadcast %s\n", inet_ntoa(*mybraddr)); 13407c478bd9Sstevel@tonic-gate } 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate bcopy(myIPaddr, &sin.sin_addr, sizeof (struct in_addr)); 13437c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET; 13447c478bd9Sstevel@tonic-gate sbuf.buf = (caddr_t)&sin; 13457c478bd9Sstevel@tonic-gate sbuf.maxlen = sbuf.len = sizeof (sin); 13467c478bd9Sstevel@tonic-gate if (rc = ifioctl(tiptr, SIOCSIFADDR, &sbuf)) { 13477c478bd9Sstevel@tonic-gate nfs_perror(rc, 13487c478bd9Sstevel@tonic-gate "dlifconfig: couldn't set interface net address: %m\n"); 13497c478bd9Sstevel@tonic-gate return (rc); 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate if (mybraddr->s_addr != INADDR_BROADCAST) { 13537c478bd9Sstevel@tonic-gate bcopy(mybraddr, &sin.sin_addr, sizeof (struct in_addr)); 13547c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET; 13557c478bd9Sstevel@tonic-gate sbuf.buf = (caddr_t)&sin; 13567c478bd9Sstevel@tonic-gate sbuf.maxlen = sbuf.len = sizeof (sin); 13577c478bd9Sstevel@tonic-gate if (rc = ifioctl(tiptr, SIOCSIFBRDADDR, &sbuf)) { 13587c478bd9Sstevel@tonic-gate nfs_perror(rc, 13597c478bd9Sstevel@tonic-gate "dlifconfig: couldn't set interface broadcast addr: %m\n"); 13607c478bd9Sstevel@tonic-gate return (rc); 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate bcopy(mymask, &sin.sin_addr, sizeof (struct in_addr)); 13657c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET; 13667c478bd9Sstevel@tonic-gate sbuf.buf = (caddr_t)&sin; 13677c478bd9Sstevel@tonic-gate sbuf.maxlen = sbuf.len = sizeof (sin); 13687c478bd9Sstevel@tonic-gate if (rc = ifioctl(tiptr, SIOCSIFNETMASK, &sbuf)) { 13697c478bd9Sstevel@tonic-gate nfs_perror(rc, 13707c478bd9Sstevel@tonic-gate "dlifconfig: couldn't set interface net address: %m\n"); 13717c478bd9Sstevel@tonic-gate return (rc); 13727c478bd9Sstevel@tonic-gate } 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate /* 13757c478bd9Sstevel@tonic-gate * Now turn on the interface. 13767c478bd9Sstevel@tonic-gate */ 13777c478bd9Sstevel@tonic-gate if (rc = setifflags(tiptr, IFF_UP | IFF_DHCPRUNNING)) { 13787c478bd9Sstevel@tonic-gate nfs_perror(rc, 13797c478bd9Sstevel@tonic-gate "dlifconfig: couldn't enable network interface: %m\n"); 13807c478bd9Sstevel@tonic-gate return (rc); 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate if (dldebug) 13847c478bd9Sstevel@tonic-gate printf("dlifconfig: returned\n"); 13857c478bd9Sstevel@tonic-gate return (0); 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate static char * 13897c478bd9Sstevel@tonic-gate inet_ntoa(struct in_addr in) 13907c478bd9Sstevel@tonic-gate { 13917c478bd9Sstevel@tonic-gate static char b[18]; 13927c478bd9Sstevel@tonic-gate unsigned char *p; 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate p = (unsigned char *)∈ 13957c478bd9Sstevel@tonic-gate (void) sprintf(b, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 13967c478bd9Sstevel@tonic-gate return (b); 13977c478bd9Sstevel@tonic-gate } 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate /* We only deal with a.b.c.d decimal format. ip points to 4 byte storage */ 14007c478bd9Sstevel@tonic-gate static int 14017c478bd9Sstevel@tonic-gate inet_aton(char *ipstr, uchar_t *ip) 14027c478bd9Sstevel@tonic-gate { 14037c478bd9Sstevel@tonic-gate int i = 0; 14047c478bd9Sstevel@tonic-gate uchar_t val[4] = {0}; 14057c478bd9Sstevel@tonic-gate char c = *ipstr; 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate for (;;) { 14087c478bd9Sstevel@tonic-gate if (!isdigit(c)) 14097c478bd9Sstevel@tonic-gate return (-1); 14107c478bd9Sstevel@tonic-gate for (;;) { 14117c478bd9Sstevel@tonic-gate if (!isdigit(c)) 14127c478bd9Sstevel@tonic-gate break; 14137c478bd9Sstevel@tonic-gate val[i] = val[i] * 10 + (c - '0'); 14147c478bd9Sstevel@tonic-gate c = *++ipstr; 14157c478bd9Sstevel@tonic-gate } 14167c478bd9Sstevel@tonic-gate i++; 14177c478bd9Sstevel@tonic-gate if (i == 4) 14187c478bd9Sstevel@tonic-gate break; 14197c478bd9Sstevel@tonic-gate if (c != '.') 14207c478bd9Sstevel@tonic-gate return (-1); 14217c478bd9Sstevel@tonic-gate c = *++ipstr; 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate if (c != 0) 14247c478bd9Sstevel@tonic-gate return (-1); 14257c478bd9Sstevel@tonic-gate bcopy(val, ip, 4); 14267c478bd9Sstevel@tonic-gate return (0); 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate #define MAX_ADDR_SIZE 128 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate /* 14327c478bd9Sstevel@tonic-gate * Initialize a netbuf suitable for 14337c478bd9Sstevel@tonic-gate * describing an address for the 14347c478bd9Sstevel@tonic-gate * transport defined by `tiptr'. 14357c478bd9Sstevel@tonic-gate */ 14367c478bd9Sstevel@tonic-gate static void 14377c478bd9Sstevel@tonic-gate init_netbuf(struct netbuf *nbuf) 14387c478bd9Sstevel@tonic-gate { 14397c478bd9Sstevel@tonic-gate nbuf->buf = kmem_zalloc(MAX_ADDR_SIZE, KM_SLEEP); 14407c478bd9Sstevel@tonic-gate nbuf->maxlen = MAX_ADDR_SIZE; 14417c478bd9Sstevel@tonic-gate nbuf->len = 0; 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate static void 14457c478bd9Sstevel@tonic-gate free_netbuf(struct netbuf *nbuf) 14467c478bd9Sstevel@tonic-gate { 14477c478bd9Sstevel@tonic-gate kmem_free(nbuf->buf, nbuf->maxlen); 14487c478bd9Sstevel@tonic-gate nbuf->buf = NULL; 14497c478bd9Sstevel@tonic-gate nbuf->maxlen = 0; 14507c478bd9Sstevel@tonic-gate nbuf->len = 0; 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate static int 14547c478bd9Sstevel@tonic-gate rtioctl(TIUSER *tiptr, int cmd, struct rtentry *rtentry) 14557c478bd9Sstevel@tonic-gate { 14567c478bd9Sstevel@tonic-gate struct strioctl iocb; 14577c478bd9Sstevel@tonic-gate int rc; 14587c478bd9Sstevel@tonic-gate vnode_t *vp; 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate iocb.ic_cmd = cmd; 14617c478bd9Sstevel@tonic-gate iocb.ic_timout = 0; 14627c478bd9Sstevel@tonic-gate iocb.ic_len = sizeof (struct rtentry); 14637c478bd9Sstevel@tonic-gate iocb.ic_dp = (caddr_t)rtentry; 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate vp = tiptr->fp->f_vnode; 14667c478bd9Sstevel@tonic-gate rc = kstr_ioctl(vp, I_STR, (intptr_t)&iocb); 14677c478bd9Sstevel@tonic-gate if (rc) 14687c478bd9Sstevel@tonic-gate nfs_perror(rc, "rtioctl: kstr_ioctl failed: %m\n"); 14697c478bd9Sstevel@tonic-gate return (rc); 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate /* 14737c478bd9Sstevel@tonic-gate * Send an ioctl down the stream defined 14747c478bd9Sstevel@tonic-gate * by `tiptr'. 14757c478bd9Sstevel@tonic-gate * 14767c478bd9Sstevel@tonic-gate * We isolate the ifreq dependencies in here. The 14777c478bd9Sstevel@tonic-gate * ioctl really ought to take a netbuf and be of 14787c478bd9Sstevel@tonic-gate * type TRANSPARENT - one day. 14797c478bd9Sstevel@tonic-gate */ 14807c478bd9Sstevel@tonic-gate static int 14817c478bd9Sstevel@tonic-gate ifioctl(TIUSER *tiptr, int cmd, struct netbuf *nbuf) 14827c478bd9Sstevel@tonic-gate { 14837c478bd9Sstevel@tonic-gate struct strioctl iocb; 14847c478bd9Sstevel@tonic-gate int rc; 14857c478bd9Sstevel@tonic-gate vnode_t *vp; 14867c478bd9Sstevel@tonic-gate struct ifreq ifr; 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate /* 14897c478bd9Sstevel@tonic-gate * Now do the one requested. 14907c478bd9Sstevel@tonic-gate */ 14917c478bd9Sstevel@tonic-gate if (nbuf->len) 14927c478bd9Sstevel@tonic-gate ifr.ifr_addr = *(struct sockaddr *)nbuf->buf; 14937c478bd9Sstevel@tonic-gate (void) strncpy((caddr_t)&ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 14947c478bd9Sstevel@tonic-gate iocb.ic_cmd = cmd; 14957c478bd9Sstevel@tonic-gate iocb.ic_timout = 0; 14967c478bd9Sstevel@tonic-gate iocb.ic_len = sizeof (ifr); 14977c478bd9Sstevel@tonic-gate iocb.ic_dp = (caddr_t)𝔦 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate vp = tiptr->fp->f_vnode; 15007c478bd9Sstevel@tonic-gate rc = kstr_ioctl(vp, I_STR, (intptr_t)&iocb); 15017c478bd9Sstevel@tonic-gate if (rc) { 15027c478bd9Sstevel@tonic-gate nfs_perror(rc, "ifioctl: kstr_ioctl failed: %m\n"); 15037c478bd9Sstevel@tonic-gate return (rc); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate /* 15077c478bd9Sstevel@tonic-gate * Set reply length. 15087c478bd9Sstevel@tonic-gate */ 15097c478bd9Sstevel@tonic-gate if (nbuf->len == 0) { 15107c478bd9Sstevel@tonic-gate /* 15117c478bd9Sstevel@tonic-gate * GET type. 15127c478bd9Sstevel@tonic-gate */ 15137c478bd9Sstevel@tonic-gate nbuf->len = sizeof (struct sockaddr); 15147c478bd9Sstevel@tonic-gate *(struct sockaddr *)nbuf->buf = ifr.ifr_addr; 15157c478bd9Sstevel@tonic-gate } 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate return (0); 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate static int 15217c478bd9Sstevel@tonic-gate setifflags(TIUSER *tiptr, uint_t value) 15227c478bd9Sstevel@tonic-gate { 15237c478bd9Sstevel@tonic-gate struct ifreq ifr; 15247c478bd9Sstevel@tonic-gate int rc; 15257c478bd9Sstevel@tonic-gate struct strioctl iocb; 15267c478bd9Sstevel@tonic-gate 15277c478bd9Sstevel@tonic-gate (void) strncpy((caddr_t)&ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 15287c478bd9Sstevel@tonic-gate iocb.ic_cmd = SIOCGIFFLAGS; 15297c478bd9Sstevel@tonic-gate iocb.ic_timout = 0; 15307c478bd9Sstevel@tonic-gate iocb.ic_len = sizeof (ifr); 15317c478bd9Sstevel@tonic-gate iocb.ic_dp = (caddr_t)𝔦 15327c478bd9Sstevel@tonic-gate if (rc = kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb)) 15337c478bd9Sstevel@tonic-gate return (rc); 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate ifr.ifr_flags |= value; 15367c478bd9Sstevel@tonic-gate iocb.ic_cmd = SIOCSIFFLAGS; 15377c478bd9Sstevel@tonic-gate return (kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb)); 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate /* 15417c478bd9Sstevel@tonic-gate * REVerse Address Resolution Protocol (revarp) 15427c478bd9Sstevel@tonic-gate * is used by a diskless client to find out its 15437c478bd9Sstevel@tonic-gate * IP address when all it knows is its Ethernet address. 15447c478bd9Sstevel@tonic-gate * 15457c478bd9Sstevel@tonic-gate * Open the ethernet driver, attach and bind 15467c478bd9Sstevel@tonic-gate * (DL_BIND_REQ) it, and then format a broadcast RARP 15477c478bd9Sstevel@tonic-gate * message for it to send. We pick up the reply and 15487c478bd9Sstevel@tonic-gate * let the caller set the interface address using SIOCSIFADDR. 15497c478bd9Sstevel@tonic-gate */ 15507c478bd9Sstevel@tonic-gate static int 15517c478bd9Sstevel@tonic-gate revarp_myaddr(TIUSER *tiptr) 15527c478bd9Sstevel@tonic-gate { 15537c478bd9Sstevel@tonic-gate int rc; 15547c478bd9Sstevel@tonic-gate dl_info_ack_t info; 15557c478bd9Sstevel@tonic-gate struct sockaddr_in sin; 15567c478bd9Sstevel@tonic-gate struct netbuf sbuf; 15577c478bd9Sstevel@tonic-gate ldi_handle_t lh; 15587c478bd9Sstevel@tonic-gate ldi_ident_t li; 15597c478bd9Sstevel@tonic-gate struct netbuf myaddr = {0, 0, NULL}; 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate if (dldebug) 15627c478bd9Sstevel@tonic-gate printf("revarp_myaddr: entered\n"); 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate if (rc = ldi_ident_from_mod(&modlinkage, &li)) { 15657c478bd9Sstevel@tonic-gate nfs_perror(rc, 15667c478bd9Sstevel@tonic-gate "revarp_myaddr: ldi_ident_from_mod failed: %m\n"); 15677c478bd9Sstevel@tonic-gate return (rc); 15687c478bd9Sstevel@tonic-gate } 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate rc = ldi_open_by_name(ndev_path, FREAD|FWRITE, CRED(), &lh, li); 15717c478bd9Sstevel@tonic-gate ldi_ident_release(li); 15727c478bd9Sstevel@tonic-gate if (rc) { 15737c478bd9Sstevel@tonic-gate nfs_perror(rc, 15747c478bd9Sstevel@tonic-gate "revarp_myaddr: ldi_open_by_name failed: %m\n"); 15757c478bd9Sstevel@tonic-gate return (rc); 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate if (rc = dl_attach(lh, ifunit)) { 15797c478bd9Sstevel@tonic-gate nfs_perror(rc, "revarp_myaddr: dl_attach failed: %m\n"); 15807c478bd9Sstevel@tonic-gate (void) ldi_close(lh, FREAD|FWRITE, CRED()); 15817c478bd9Sstevel@tonic-gate return (rc); 15827c478bd9Sstevel@tonic-gate } 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate if (rc = dl_bind(lh, ETHERTYPE_REVARP, 0, DL_CLDLS, 0)) { 15857c478bd9Sstevel@tonic-gate nfs_perror(rc, "revarp_myaddr: dl_bind failed: %m\n"); 15867c478bd9Sstevel@tonic-gate (void) ldi_close(lh, FREAD|FWRITE, CRED()); 15877c478bd9Sstevel@tonic-gate return (rc); 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate 15907c478bd9Sstevel@tonic-gate if (rc = dl_info(lh, &info)) { 15917c478bd9Sstevel@tonic-gate nfs_perror(rc, "revarp_myaddr: dl_info failed: %m\n"); 15927c478bd9Sstevel@tonic-gate (void) ldi_close(lh, FREAD|FWRITE, CRED()); 15937c478bd9Sstevel@tonic-gate return (rc); 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate 15967c478bd9Sstevel@tonic-gate /* Initialize myaddr */ 15977c478bd9Sstevel@tonic-gate myaddr.maxlen = info.dl_addr_length; 15987c478bd9Sstevel@tonic-gate myaddr.buf = kmem_alloc(myaddr.maxlen, KM_SLEEP); 15997c478bd9Sstevel@tonic-gate 16007c478bd9Sstevel@tonic-gate revarp_start(lh, &myaddr); 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate bcopy(myaddr.buf, &sin.sin_addr, myaddr.len); 16037c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET; 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate sbuf.buf = (caddr_t)&sin; 16067c478bd9Sstevel@tonic-gate sbuf.maxlen = sbuf.len = sizeof (sin); 16077c478bd9Sstevel@tonic-gate if (rc = ifioctl(tiptr, SIOCSIFADDR, &sbuf)) { 16087c478bd9Sstevel@tonic-gate nfs_perror(rc, 16097c478bd9Sstevel@tonic-gate "revarp_myaddr: couldn't set interface net address: %m\n"); 16107c478bd9Sstevel@tonic-gate (void) ldi_close(lh, FREAD|FWRITE, CRED()); 16117c478bd9Sstevel@tonic-gate kmem_free(myaddr.buf, myaddr.maxlen); 16127c478bd9Sstevel@tonic-gate return (rc); 16137c478bd9Sstevel@tonic-gate } 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate /* Now turn on the interface */ 16167c478bd9Sstevel@tonic-gate if (rc = setifflags(tiptr, IFF_UP)) { 16177c478bd9Sstevel@tonic-gate nfs_perror(rc, 16187c478bd9Sstevel@tonic-gate "revarp_myaddr: couldn't enable network interface: %m\n"); 16197c478bd9Sstevel@tonic-gate } 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate (void) ldi_close(lh, FREAD|FWRITE, CRED()); 16227c478bd9Sstevel@tonic-gate kmem_free(myaddr.buf, myaddr.maxlen); 16237c478bd9Sstevel@tonic-gate return (rc); 16247c478bd9Sstevel@tonic-gate } 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate static void 16277c478bd9Sstevel@tonic-gate revarp_start(ldi_handle_t lh, struct netbuf *myaddr) 16287c478bd9Sstevel@tonic-gate { 16297c478bd9Sstevel@tonic-gate struct ether_arp *ea; 16307c478bd9Sstevel@tonic-gate int rc; 16317c478bd9Sstevel@tonic-gate dl_unitdata_req_t *dl_udata; 16327c478bd9Sstevel@tonic-gate mblk_t *bp; 16337c478bd9Sstevel@tonic-gate mblk_t *mp; 16347c478bd9Sstevel@tonic-gate struct dladdr *dlsap; 16357c478bd9Sstevel@tonic-gate static int done = 0; 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate if (dl_phys_addr(lh, &myether) != 0) { 16387c478bd9Sstevel@tonic-gate /* Fallback using per-node address */ 16397c478bd9Sstevel@tonic-gate (void) localetheraddr((struct ether_addr *)NULL, &myether); 16407c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?DLPI failed to get Ethernet address. Using " 16417c478bd9Sstevel@tonic-gate "system wide Ethernet address %s\n", 16427c478bd9Sstevel@tonic-gate ether_sprintf(&myether)); 16437c478bd9Sstevel@tonic-gate } 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate getreply: 16467c478bd9Sstevel@tonic-gate if (myaddr->len != 0) { 16477c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?Found my IP address: %x (%d.%d.%d.%d)\n", 16487c478bd9Sstevel@tonic-gate *(int *)myaddr->buf, 16497c478bd9Sstevel@tonic-gate (uchar_t)myaddr->buf[0], (uchar_t)myaddr->buf[1], 16507c478bd9Sstevel@tonic-gate (uchar_t)myaddr->buf[2], (uchar_t)myaddr->buf[3]); 16517c478bd9Sstevel@tonic-gate return; 16527c478bd9Sstevel@tonic-gate } 16537c478bd9Sstevel@tonic-gate 16547c478bd9Sstevel@tonic-gate if (done++ == 0) 16557c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?Requesting Internet address for %s\n", 16567c478bd9Sstevel@tonic-gate ether_sprintf(&myether)); 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate /* 16597c478bd9Sstevel@tonic-gate * Send another RARP request. 16607c478bd9Sstevel@tonic-gate */ 16617c478bd9Sstevel@tonic-gate if ((mp = allocb(sizeof (dl_unitdata_req_t) + sizeof (*dlsap), 16627c478bd9Sstevel@tonic-gate BPRI_HI)) == NULL) { 16637c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "revarp_myaddr: allocb no memory"); 16647c478bd9Sstevel@tonic-gate return; 16657c478bd9Sstevel@tonic-gate } 16667c478bd9Sstevel@tonic-gate if ((bp = allocb(sizeof (struct ether_arp), BPRI_HI)) == NULL) { 16677c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "revarp_myaddr: allocb no memory"); 16687c478bd9Sstevel@tonic-gate return; 16697c478bd9Sstevel@tonic-gate } 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate /* 16727c478bd9Sstevel@tonic-gate * Format the transmit request part. 16737c478bd9Sstevel@tonic-gate */ 16747c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 16757c478bd9Sstevel@tonic-gate dl_udata = (dl_unitdata_req_t *)mp->b_wptr; 16767c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (dl_unitdata_req_t) + sizeof (*dlsap); 16777c478bd9Sstevel@tonic-gate dl_udata->dl_primitive = DL_UNITDATA_REQ; 16787c478bd9Sstevel@tonic-gate dl_udata->dl_dest_addr_length = sizeof (*dlsap); 16797c478bd9Sstevel@tonic-gate dl_udata->dl_dest_addr_offset = sizeof (*dl_udata); 16807c478bd9Sstevel@tonic-gate dl_udata->dl_priority.dl_min = 0; 16817c478bd9Sstevel@tonic-gate dl_udata->dl_priority.dl_max = 0; 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate dlsap = (struct dladdr *)(mp->b_rptr + sizeof (*dl_udata)); 16847c478bd9Sstevel@tonic-gate bcopy(ðerbroadcastaddr, &dlsap->dl_phys, 16857c478bd9Sstevel@tonic-gate sizeof (etherbroadcastaddr)); 16867c478bd9Sstevel@tonic-gate dlsap->dl_sap = ETHERTYPE_REVARP; 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate /* 16897c478bd9Sstevel@tonic-gate * Format the actual REVARP request. 16907c478bd9Sstevel@tonic-gate */ 16917c478bd9Sstevel@tonic-gate bzero(bp->b_wptr, sizeof (struct ether_arp)); 16927c478bd9Sstevel@tonic-gate ea = (struct ether_arp *)bp->b_wptr; 16937c478bd9Sstevel@tonic-gate bp->b_wptr += sizeof (struct ether_arp); 16947c478bd9Sstevel@tonic-gate ea->arp_hrd = htons(ARPHRD_ETHER); 16957c478bd9Sstevel@tonic-gate ea->arp_pro = htons(ETHERTYPE_IP); 16967c478bd9Sstevel@tonic-gate ea->arp_hln = sizeof (ea->arp_sha); /* hardware address length */ 16977c478bd9Sstevel@tonic-gate ea->arp_pln = sizeof (ea->arp_spa); /* protocol address length */ 16987c478bd9Sstevel@tonic-gate ea->arp_op = htons(REVARP_REQUEST); 16997c478bd9Sstevel@tonic-gate ether_copy(&myether, &ea->arp_sha); 17007c478bd9Sstevel@tonic-gate ether_copy(&myether, &ea->arp_tha); 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate mp->b_cont = bp; 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate if ((rc = ldi_putmsg(lh, mp)) != 0) { 17057c478bd9Sstevel@tonic-gate nfs_perror(rc, "revarp_start: ldi_putmsg failed: %m\n"); 17067c478bd9Sstevel@tonic-gate return; 17077c478bd9Sstevel@tonic-gate } 17087c478bd9Sstevel@tonic-gate revarpinput(lh, myaddr); 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate goto getreply; 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate /* 17147c478bd9Sstevel@tonic-gate * Client side Reverse-ARP input 17157c478bd9Sstevel@tonic-gate * Server side is handled by user level server 17167c478bd9Sstevel@tonic-gate */ 17177c478bd9Sstevel@tonic-gate static void 17187c478bd9Sstevel@tonic-gate revarpinput(ldi_handle_t lh, struct netbuf *myaddr) 17197c478bd9Sstevel@tonic-gate { 17207c478bd9Sstevel@tonic-gate struct ether_arp *ea; 17217c478bd9Sstevel@tonic-gate mblk_t *bp; 17227c478bd9Sstevel@tonic-gate mblk_t *mp; 17237c478bd9Sstevel@tonic-gate int rc; 17247c478bd9Sstevel@tonic-gate timestruc_t tv, give_up, now; 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate /* 17277c478bd9Sstevel@tonic-gate * Choose the time at which we will give up, and resend our 17287c478bd9Sstevel@tonic-gate * request. 17297c478bd9Sstevel@tonic-gate */ 17307c478bd9Sstevel@tonic-gate gethrestime(&give_up); 17317c478bd9Sstevel@tonic-gate give_up.tv_sec += REVARP_TIMEO; 17327c478bd9Sstevel@tonic-gate wait: 17337c478bd9Sstevel@tonic-gate /* 17347c478bd9Sstevel@tonic-gate * Compute new timeout value. 17357c478bd9Sstevel@tonic-gate */ 17367c478bd9Sstevel@tonic-gate tv = give_up; 17377c478bd9Sstevel@tonic-gate gethrestime(&now); 17387c478bd9Sstevel@tonic-gate timespecsub(&tv, &now); 17397c478bd9Sstevel@tonic-gate /* 17407c478bd9Sstevel@tonic-gate * If we don't have at least one full second remaining, give up. 17417c478bd9Sstevel@tonic-gate * This means we might wait only just over 4.0 seconds, but that's 17427c478bd9Sstevel@tonic-gate * okay. 17437c478bd9Sstevel@tonic-gate */ 17447c478bd9Sstevel@tonic-gate if (tv.tv_sec <= 0) 17457c478bd9Sstevel@tonic-gate return; 17467c478bd9Sstevel@tonic-gate rc = ldi_getmsg(lh, &mp, &tv); 17477c478bd9Sstevel@tonic-gate if (rc == ETIME) { 17487c478bd9Sstevel@tonic-gate goto out; 17497c478bd9Sstevel@tonic-gate } else if (rc != 0) { 17507c478bd9Sstevel@tonic-gate nfs_perror(rc, "revarpinput: ldi_getmsg failed: %m\n"); 17517c478bd9Sstevel@tonic-gate return; 17527c478bd9Sstevel@tonic-gate } 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate if (mp->b_cont == NULL) { 17557c478bd9Sstevel@tonic-gate printf("revarpinput: b_cont == NULL\n"); 17567c478bd9Sstevel@tonic-gate goto out; 17577c478bd9Sstevel@tonic-gate } 17587c478bd9Sstevel@tonic-gate 17597c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type != M_PROTO) { 17607c478bd9Sstevel@tonic-gate printf("revarpinput: bad header type %d\n", 17617c478bd9Sstevel@tonic-gate mp->b_datap->db_type); 17627c478bd9Sstevel@tonic-gate goto out; 17637c478bd9Sstevel@tonic-gate } 17647c478bd9Sstevel@tonic-gate 17657c478bd9Sstevel@tonic-gate bp = mp->b_cont; 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate if (bp->b_wptr - bp->b_rptr < sizeof (*ea)) { 17687c478bd9Sstevel@tonic-gate printf("revarpinput: bad data len %d, expect %d\n", 17697c478bd9Sstevel@tonic-gate (int)(bp->b_wptr - bp->b_rptr), (int)sizeof (*ea)); 17707c478bd9Sstevel@tonic-gate goto out; 17717c478bd9Sstevel@tonic-gate } 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate ea = (struct ether_arp *)bp->b_rptr; 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate if ((ushort_t)ntohs(ea->arp_pro) != ETHERTYPE_IP) { 17767c478bd9Sstevel@tonic-gate /* We could have received another broadcast arp packet. */ 17777c478bd9Sstevel@tonic-gate if (dldebug) 17787c478bd9Sstevel@tonic-gate printf("revarpinput: bad type %x\n", 17797c478bd9Sstevel@tonic-gate (ushort_t)ntohs(ea->arp_pro)); 17807c478bd9Sstevel@tonic-gate freemsg(mp); 17817c478bd9Sstevel@tonic-gate goto wait; 17827c478bd9Sstevel@tonic-gate } 17837c478bd9Sstevel@tonic-gate if ((ushort_t)ntohs(ea->arp_op) != REVARP_REPLY) { 17847c478bd9Sstevel@tonic-gate /* We could have received a broadcast arp request. */ 17857c478bd9Sstevel@tonic-gate if (dldebug) 17867c478bd9Sstevel@tonic-gate printf("revarpinput: bad op %x\n", 17877c478bd9Sstevel@tonic-gate (ushort_t)ntohs(ea->arp_op)); 17887c478bd9Sstevel@tonic-gate freemsg(mp); 17897c478bd9Sstevel@tonic-gate goto wait; 17907c478bd9Sstevel@tonic-gate } 17917c478bd9Sstevel@tonic-gate 17927c478bd9Sstevel@tonic-gate if (!ether_cmp(&ea->arp_tha, &myether)) { 17937c478bd9Sstevel@tonic-gate bcopy(&ea->arp_tpa, myaddr->buf, sizeof (ea->arp_tpa)); 17947c478bd9Sstevel@tonic-gate myaddr->len = sizeof (ea->arp_tpa); 17957c478bd9Sstevel@tonic-gate } else { 17967c478bd9Sstevel@tonic-gate /* We could have gotten a broadcast arp response. */ 17977c478bd9Sstevel@tonic-gate if (dldebug) 17987c478bd9Sstevel@tonic-gate printf("revarpinput: got reply, but not my address\n"); 17997c478bd9Sstevel@tonic-gate freemsg(mp); 18007c478bd9Sstevel@tonic-gate goto wait; 18017c478bd9Sstevel@tonic-gate } 18027c478bd9Sstevel@tonic-gate out: 18037c478bd9Sstevel@tonic-gate freemsg(mp); 18047c478bd9Sstevel@tonic-gate } 18057c478bd9Sstevel@tonic-gate 18067c478bd9Sstevel@tonic-gate /* 18077c478bd9Sstevel@tonic-gate * From rpcsvc/mountxdr.c in SunOS. We can't 18087c478bd9Sstevel@tonic-gate * put this into the rpc directory because 18097c478bd9Sstevel@tonic-gate * it calls xdr_fhandle() which is in a 18107c478bd9Sstevel@tonic-gate * loadable module. 18117c478bd9Sstevel@tonic-gate */ 18127c478bd9Sstevel@tonic-gate static bool_t 18137c478bd9Sstevel@tonic-gate myxdr_fhstatus(XDR *xdrs, struct fhstatus *fhsp) 18147c478bd9Sstevel@tonic-gate { 18157c478bd9Sstevel@tonic-gate 18167c478bd9Sstevel@tonic-gate if (!xdr_int(xdrs, &fhsp->fhs_status)) 18177c478bd9Sstevel@tonic-gate return (FALSE); 18187c478bd9Sstevel@tonic-gate if (fhsp->fhs_status == 0) { 18197c478bd9Sstevel@tonic-gate if (!myxdr_fhandle(xdrs, &fhsp->fhs_fh)) 18207c478bd9Sstevel@tonic-gate return (FALSE); 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate return (TRUE); 18237c478bd9Sstevel@tonic-gate } 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate /* 18267c478bd9Sstevel@tonic-gate * From nfs_xdr.c. 18277c478bd9Sstevel@tonic-gate * 18287c478bd9Sstevel@tonic-gate * File access handle 18297c478bd9Sstevel@tonic-gate * The fhandle struct is treated a opaque data on the wire 18307c478bd9Sstevel@tonic-gate */ 18317c478bd9Sstevel@tonic-gate static bool_t 18327c478bd9Sstevel@tonic-gate myxdr_fhandle(XDR *xdrs, fhandle_t *fh) 18337c478bd9Sstevel@tonic-gate { 18347c478bd9Sstevel@tonic-gate return (xdr_opaque(xdrs, (caddr_t)fh, NFS_FHSIZE)); 18357c478bd9Sstevel@tonic-gate } 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate static bool_t 18387c478bd9Sstevel@tonic-gate myxdr_mountres3(XDR *xdrs, struct mountres3 *objp) 18397c478bd9Sstevel@tonic-gate { 18407c478bd9Sstevel@tonic-gate if (!myxdr_mountstat3(xdrs, &objp->fhs_status)) 18417c478bd9Sstevel@tonic-gate return (FALSE); 18427c478bd9Sstevel@tonic-gate switch (objp->fhs_status) { 18437c478bd9Sstevel@tonic-gate case MNT_OK: 18447c478bd9Sstevel@tonic-gate if (!myxdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo)) 18457c478bd9Sstevel@tonic-gate return (FALSE); 18467c478bd9Sstevel@tonic-gate break; 18477c478bd9Sstevel@tonic-gate default: 18487c478bd9Sstevel@tonic-gate break; 18497c478bd9Sstevel@tonic-gate } 18507c478bd9Sstevel@tonic-gate return (TRUE); 18517c478bd9Sstevel@tonic-gate } 18527c478bd9Sstevel@tonic-gate 18537c478bd9Sstevel@tonic-gate static bool_t 18547c478bd9Sstevel@tonic-gate myxdr_mountstat3(XDR *xdrs, enum mountstat3 *objp) 18557c478bd9Sstevel@tonic-gate { 18567c478bd9Sstevel@tonic-gate return (xdr_enum(xdrs, (enum_t *)objp)); 18577c478bd9Sstevel@tonic-gate } 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate static bool_t 18607c478bd9Sstevel@tonic-gate myxdr_mountres3_ok(XDR *xdrs, struct mountres3_ok *objp) 18617c478bd9Sstevel@tonic-gate { 18627c478bd9Sstevel@tonic-gate if (!myxdr_fhandle3(xdrs, &objp->fhandle)) 18637c478bd9Sstevel@tonic-gate return (FALSE); 18647c478bd9Sstevel@tonic-gate if (!xdr_array(xdrs, (char **)&objp->auth_flavors.auth_flavors_val, 18657c478bd9Sstevel@tonic-gate (uint_t *)&objp->auth_flavors.auth_flavors_len, ~0, 18667c478bd9Sstevel@tonic-gate sizeof (int), (xdrproc_t)xdr_int)) 18677c478bd9Sstevel@tonic-gate return (FALSE); 18687c478bd9Sstevel@tonic-gate return (TRUE); 18697c478bd9Sstevel@tonic-gate } 18707c478bd9Sstevel@tonic-gate 18717c478bd9Sstevel@tonic-gate static bool_t 18727c478bd9Sstevel@tonic-gate myxdr_fhandle3(XDR *xdrs, struct fhandle3 *objp) 18737c478bd9Sstevel@tonic-gate { 18747c478bd9Sstevel@tonic-gate return (xdr_bytes(xdrs, (char **)&objp->fhandle3_val, 18757c478bd9Sstevel@tonic-gate (uint_t *)&objp->fhandle3_len, FHSIZE3)); 18767c478bd9Sstevel@tonic-gate } 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate /* 18797c478bd9Sstevel@tonic-gate * From SunOS pmap_clnt.c 18807c478bd9Sstevel@tonic-gate * 18817c478bd9Sstevel@tonic-gate * Port mapper routines: 18827c478bd9Sstevel@tonic-gate * pmap_kgetport() - get port number. 18837c478bd9Sstevel@tonic-gate * pmap_rmt_call() - indirect call via port mapper. 18847c478bd9Sstevel@tonic-gate * 18857c478bd9Sstevel@tonic-gate */ 18867c478bd9Sstevel@tonic-gate static enum clnt_stat 18877c478bd9Sstevel@tonic-gate pmap_kgetport(struct knetconfig *knconf, struct netbuf *call_addr, 18887c478bd9Sstevel@tonic-gate rpcprog_t prog, rpcvers_t vers, rpcprot_t prot) 18897c478bd9Sstevel@tonic-gate { 18907c478bd9Sstevel@tonic-gate ushort_t port; 18917c478bd9Sstevel@tonic-gate int tries; 18927c478bd9Sstevel@tonic-gate enum clnt_stat stat; 18937c478bd9Sstevel@tonic-gate struct pmap pmap_parms; 18947c478bd9Sstevel@tonic-gate RPCB rpcb_parms; 18957c478bd9Sstevel@tonic-gate char *ua = NULL; 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate port = 0; 18987c478bd9Sstevel@tonic-gate 18997c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)call_addr->buf)->sin_port = htons(PMAPPORT); 19007c478bd9Sstevel@tonic-gate 19017c478bd9Sstevel@tonic-gate pmap_parms.pm_prog = prog; 19027c478bd9Sstevel@tonic-gate pmap_parms.pm_vers = vers; 19037c478bd9Sstevel@tonic-gate pmap_parms.pm_prot = prot; 19047c478bd9Sstevel@tonic-gate pmap_parms.pm_port = 0; 19057c478bd9Sstevel@tonic-gate for (tries = 0; tries < 5; tries++) { 19067c478bd9Sstevel@tonic-gate stat = mycallrpc(knconf, call_addr, 19077c478bd9Sstevel@tonic-gate PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, 19087c478bd9Sstevel@tonic-gate myxdr_pmap, (char *)&pmap_parms, 19097c478bd9Sstevel@tonic-gate xdr_u_short, (char *)&port, 19107c478bd9Sstevel@tonic-gate DEFAULT_TIMEO, DEFAULT_RETRIES); 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate if (stat != RPC_TIMEDOUT) 19137c478bd9Sstevel@tonic-gate break; 19147c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 19157c478bd9Sstevel@tonic-gate "pmap_kgetport: Portmapper not responding; still trying"); 19167c478bd9Sstevel@tonic-gate } 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate if (stat == RPC_PROGUNAVAIL) { 19197c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 19207c478bd9Sstevel@tonic-gate "pmap_kgetport: Portmapper failed - trying rpcbind"); 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate rpcb_parms.r_prog = prog; 19237c478bd9Sstevel@tonic-gate rpcb_parms.r_vers = vers; 19247c478bd9Sstevel@tonic-gate rpcb_parms.r_netid = knconf->knc_proto; 19257c478bd9Sstevel@tonic-gate rpcb_parms.r_addr = rpcb_parms.r_owner = ""; 19267c478bd9Sstevel@tonic-gate 19277c478bd9Sstevel@tonic-gate for (tries = 0; tries < 5; tries++) { 19287c478bd9Sstevel@tonic-gate stat = mycallrpc(knconf, call_addr, 19297c478bd9Sstevel@tonic-gate RPCBPROG, RPCBVERS, RPCBPROC_GETADDR, 19307c478bd9Sstevel@tonic-gate xdr_rpcb, (char *)&rpcb_parms, 19317c478bd9Sstevel@tonic-gate xdr_wrapstring, (char *)&ua, 19327c478bd9Sstevel@tonic-gate DEFAULT_TIMEO, DEFAULT_RETRIES); 19337c478bd9Sstevel@tonic-gate 19347c478bd9Sstevel@tonic-gate if (stat != RPC_TIMEDOUT) 19357c478bd9Sstevel@tonic-gate break; 19367c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 19377c478bd9Sstevel@tonic-gate "pmap_kgetport: rpcbind not responding; still trying"); 19387c478bd9Sstevel@tonic-gate } 19397c478bd9Sstevel@tonic-gate 19407c478bd9Sstevel@tonic-gate if (stat == RPC_SUCCESS) { 19417c478bd9Sstevel@tonic-gate if ((ua != NULL) && (ua[0] != NULL)) { 19427c478bd9Sstevel@tonic-gate port = rpc_uaddr2port(AF_INET, ua); 19437c478bd9Sstevel@tonic-gate } else { 19447c478bd9Sstevel@tonic-gate /* Address unknown */ 19457c478bd9Sstevel@tonic-gate stat = RPC_PROGUNAVAIL; 19467c478bd9Sstevel@tonic-gate } 19477c478bd9Sstevel@tonic-gate } 19487c478bd9Sstevel@tonic-gate } 19497c478bd9Sstevel@tonic-gate 19507c478bd9Sstevel@tonic-gate if (stat == RPC_SUCCESS) 19517c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)call_addr->buf)->sin_port = ntohs(port); 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate return (stat); 19547c478bd9Sstevel@tonic-gate } 19557c478bd9Sstevel@tonic-gate 19567c478bd9Sstevel@tonic-gate /* 19577c478bd9Sstevel@tonic-gate * pmapper remote-call-service interface. 19587c478bd9Sstevel@tonic-gate * This routine is used to call the pmapper remote call service 19597c478bd9Sstevel@tonic-gate * which will look up a service program in the port maps, and then 19607c478bd9Sstevel@tonic-gate * remotely call that routine with the given parameters. This allows 19617c478bd9Sstevel@tonic-gate * programs to do a lookup and call in one step. In addition to the call_addr, 19627c478bd9Sstevel@tonic-gate * the caller provides a boolean hint about the destination address (TRUE if 19637c478bd9Sstevel@tonic-gate * address is a broadcast address, FALSE otherwise). 19647c478bd9Sstevel@tonic-gate * 19657c478bd9Sstevel@tonic-gate * On return, `call addr' contains the port number for the 19667c478bd9Sstevel@tonic-gate * service requested, and `resp_addr' contains its IP address. 19677c478bd9Sstevel@tonic-gate */ 19687c478bd9Sstevel@tonic-gate static enum clnt_stat 19697c478bd9Sstevel@tonic-gate pmap_rmt_call(struct knetconfig *knconf, struct netbuf *call_addr, 19707c478bd9Sstevel@tonic-gate bool_t bcast, rpcprog_t progn, rpcvers_t versn, rpcproc_t procn, 19717c478bd9Sstevel@tonic-gate xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp, 19727c478bd9Sstevel@tonic-gate struct timeval tout, struct netbuf *resp_addr) 19737c478bd9Sstevel@tonic-gate { 19747c478bd9Sstevel@tonic-gate CLIENT *cl; 19757c478bd9Sstevel@tonic-gate enum clnt_stat stat; 19767c478bd9Sstevel@tonic-gate rpcport_t port; 19777c478bd9Sstevel@tonic-gate int rc; 19787c478bd9Sstevel@tonic-gate struct rmtcallargs pmap_args; 19797c478bd9Sstevel@tonic-gate struct rmtcallres pmap_res; 19807c478bd9Sstevel@tonic-gate struct rpcb_rmtcallargs rpcb_args; 19817c478bd9Sstevel@tonic-gate struct rpcb_rmtcallres rpcb_res; 19827c478bd9Sstevel@tonic-gate char ua[100]; /* XXX */ 19837c478bd9Sstevel@tonic-gate 19847c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)call_addr->buf)->sin_port = htons(PMAPPORT); 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate rc = clnt_tli_kcreate(knconf, call_addr, PMAPPROG, PMAPVERS, 19877c478bd9Sstevel@tonic-gate 0, PMAP_RETRIES, CRED(), &cl); 19887c478bd9Sstevel@tonic-gate if (rc != 0) { 19897c478bd9Sstevel@tonic-gate nfs_perror(rc, 19907c478bd9Sstevel@tonic-gate "pmap_rmt_call: clnt_tli_kcreate failed: %m\n"); 19917c478bd9Sstevel@tonic-gate return (RPC_SYSTEMERROR); /* XXX */ 19927c478bd9Sstevel@tonic-gate } 19937c478bd9Sstevel@tonic-gate if (cl == (CLIENT *)NULL) { 19947c478bd9Sstevel@tonic-gate panic("pmap_rmt_call: clnt_tli_kcreate failed"); 19957c478bd9Sstevel@tonic-gate /* NOTREACHED */ 19967c478bd9Sstevel@tonic-gate } 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate (void) CLNT_CONTROL(cl, CLSET_BCAST, (char *)&bcast); 19997c478bd9Sstevel@tonic-gate 20007c478bd9Sstevel@tonic-gate pmap_args.prog = progn; 20017c478bd9Sstevel@tonic-gate pmap_args.vers = versn; 20027c478bd9Sstevel@tonic-gate pmap_args.proc = procn; 20037c478bd9Sstevel@tonic-gate pmap_args.args_ptr = argsp; 20047c478bd9Sstevel@tonic-gate pmap_args.xdr_args = xdrargs; 20057c478bd9Sstevel@tonic-gate pmap_res.port_ptr = &port; 20067c478bd9Sstevel@tonic-gate pmap_res.results_ptr = resp; 20077c478bd9Sstevel@tonic-gate pmap_res.xdr_results = xdrres; 20087c478bd9Sstevel@tonic-gate stat = clnt_clts_kcallit_addr(cl, PMAPPROC_CALLIT, 20097c478bd9Sstevel@tonic-gate myxdr_rmtcall_args, (caddr_t)&pmap_args, 20107c478bd9Sstevel@tonic-gate myxdr_rmtcallres, (caddr_t)&pmap_res, 20117c478bd9Sstevel@tonic-gate tout, resp_addr); 20127c478bd9Sstevel@tonic-gate 20137c478bd9Sstevel@tonic-gate if (stat == RPC_SUCCESS) { 20147c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)resp_addr->buf)->sin_port = 20157c478bd9Sstevel@tonic-gate htons((ushort_t)port); 20167c478bd9Sstevel@tonic-gate } 20177c478bd9Sstevel@tonic-gate CLNT_DESTROY(cl); 20187c478bd9Sstevel@tonic-gate 20197c478bd9Sstevel@tonic-gate if (stat != RPC_PROGUNAVAIL) 20207c478bd9Sstevel@tonic-gate return (stat); 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "pmap_rmt_call: Portmapper failed - trying rpcbind"); 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate rc = clnt_tli_kcreate(knconf, call_addr, RPCBPROG, RPCBVERS, 20257c478bd9Sstevel@tonic-gate 0, PMAP_RETRIES, CRED(), &cl); 20267c478bd9Sstevel@tonic-gate if (rc != 0) { 20277c478bd9Sstevel@tonic-gate nfs_perror(rc, "pmap_rmt_call: clnt_tli_kcreate failed: %m\n"); 20287c478bd9Sstevel@tonic-gate return (RPC_SYSTEMERROR); /* XXX */ 20297c478bd9Sstevel@tonic-gate } 20307c478bd9Sstevel@tonic-gate 20317c478bd9Sstevel@tonic-gate if (cl == NULL) { 20327c478bd9Sstevel@tonic-gate panic("pmap_rmt_call: clnt_tli_kcreate failed"); 20337c478bd9Sstevel@tonic-gate /* NOTREACHED */ 20347c478bd9Sstevel@tonic-gate } 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate rpcb_args.prog = progn; 20377c478bd9Sstevel@tonic-gate rpcb_args.vers = versn; 20387c478bd9Sstevel@tonic-gate rpcb_args.proc = procn; 20397c478bd9Sstevel@tonic-gate rpcb_args.args_ptr = argsp; 20407c478bd9Sstevel@tonic-gate rpcb_args.xdr_args = xdrargs; 20417c478bd9Sstevel@tonic-gate rpcb_res.addr_ptr = ua; 20427c478bd9Sstevel@tonic-gate rpcb_res.results_ptr = resp; 20437c478bd9Sstevel@tonic-gate rpcb_res.xdr_results = xdrres; 20447c478bd9Sstevel@tonic-gate stat = clnt_clts_kcallit_addr(cl, PMAPPROC_CALLIT, 20457c478bd9Sstevel@tonic-gate xdr_rpcb_rmtcallargs, (caddr_t)&rpcb_args, 20467c478bd9Sstevel@tonic-gate xdr_rpcb_rmtcallres, (caddr_t)&rpcb_res, 20477c478bd9Sstevel@tonic-gate tout, resp_addr); 20487c478bd9Sstevel@tonic-gate 20497c478bd9Sstevel@tonic-gate if (stat == RPC_SUCCESS) 20507c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)resp_addr->buf)->sin_port = 20517c478bd9Sstevel@tonic-gate rpc_uaddr2port(AF_INET, ua); 20527c478bd9Sstevel@tonic-gate CLNT_DESTROY(cl); 20537c478bd9Sstevel@tonic-gate 20547c478bd9Sstevel@tonic-gate return (stat); 20557c478bd9Sstevel@tonic-gate } 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate /* 20587c478bd9Sstevel@tonic-gate * XDR remote call arguments 20597c478bd9Sstevel@tonic-gate * written for XDR_ENCODE direction only 20607c478bd9Sstevel@tonic-gate */ 20617c478bd9Sstevel@tonic-gate static bool_t 20627c478bd9Sstevel@tonic-gate myxdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap) 20637c478bd9Sstevel@tonic-gate { 20647c478bd9Sstevel@tonic-gate uint_t lenposition; 20657c478bd9Sstevel@tonic-gate uint_t argposition; 20667c478bd9Sstevel@tonic-gate uint_t position; 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate if (xdr_rpcprog(xdrs, &(cap->prog)) && 20697c478bd9Sstevel@tonic-gate xdr_rpcvers(xdrs, &(cap->vers)) && 20707c478bd9Sstevel@tonic-gate xdr_rpcproc(xdrs, &(cap->proc))) { 20717c478bd9Sstevel@tonic-gate lenposition = XDR_GETPOS(xdrs); 20727c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &cap->arglen)) 20737c478bd9Sstevel@tonic-gate return (FALSE); 20747c478bd9Sstevel@tonic-gate argposition = XDR_GETPOS(xdrs); 20757c478bd9Sstevel@tonic-gate if (!(*(cap->xdr_args))(xdrs, cap->args_ptr)) 20767c478bd9Sstevel@tonic-gate return (FALSE); 20777c478bd9Sstevel@tonic-gate position = XDR_GETPOS(xdrs); 20787c478bd9Sstevel@tonic-gate cap->arglen = (uint_t)position - (uint_t)argposition; 20797c478bd9Sstevel@tonic-gate XDR_SETPOS(xdrs, lenposition); 20807c478bd9Sstevel@tonic-gate if (!xdr_u_int(xdrs, &cap->arglen)) 20817c478bd9Sstevel@tonic-gate return (FALSE); 20827c478bd9Sstevel@tonic-gate XDR_SETPOS(xdrs, position); 20837c478bd9Sstevel@tonic-gate return (TRUE); 20847c478bd9Sstevel@tonic-gate } 20857c478bd9Sstevel@tonic-gate return (FALSE); 20867c478bd9Sstevel@tonic-gate } 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate /* 20897c478bd9Sstevel@tonic-gate * XDR remote call results 20907c478bd9Sstevel@tonic-gate * written for XDR_DECODE direction only 20917c478bd9Sstevel@tonic-gate */ 20927c478bd9Sstevel@tonic-gate static bool_t 20937c478bd9Sstevel@tonic-gate myxdr_rmtcallres(XDR *xdrs, struct rmtcallres *crp) 20947c478bd9Sstevel@tonic-gate { 20957c478bd9Sstevel@tonic-gate caddr_t port_ptr; 20967c478bd9Sstevel@tonic-gate 20977c478bd9Sstevel@tonic-gate port_ptr = (caddr_t)crp->port_ptr; 20987c478bd9Sstevel@tonic-gate if (xdr_reference(xdrs, &port_ptr, sizeof (uint_t), xdr_u_int) && 20997c478bd9Sstevel@tonic-gate xdr_u_int(xdrs, &crp->resultslen)) { 21007c478bd9Sstevel@tonic-gate crp->port_ptr = (rpcport_t *)port_ptr; 21017c478bd9Sstevel@tonic-gate return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); 21027c478bd9Sstevel@tonic-gate } 21037c478bd9Sstevel@tonic-gate return (FALSE); 21047c478bd9Sstevel@tonic-gate } 21057c478bd9Sstevel@tonic-gate 21067c478bd9Sstevel@tonic-gate static bool_t 21077c478bd9Sstevel@tonic-gate myxdr_pmap(XDR *xdrs, struct pmap *regs) 21087c478bd9Sstevel@tonic-gate { 21097c478bd9Sstevel@tonic-gate if (xdr_rpcprog(xdrs, ®s->pm_prog) && 21107c478bd9Sstevel@tonic-gate xdr_rpcvers(xdrs, ®s->pm_vers) && 21117c478bd9Sstevel@tonic-gate xdr_rpcprot(xdrs, ®s->pm_prot)) 21127c478bd9Sstevel@tonic-gate return (xdr_rpcport(xdrs, ®s->pm_port)); 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate return (FALSE); 21157c478bd9Sstevel@tonic-gate } 21167c478bd9Sstevel@tonic-gate 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate /* 21197c478bd9Sstevel@tonic-gate * From SunOS callrpc.c 21207c478bd9Sstevel@tonic-gate */ 21217c478bd9Sstevel@tonic-gate static enum clnt_stat 21227c478bd9Sstevel@tonic-gate mycallrpc(struct knetconfig *knconf, struct netbuf *call_addr, 21237c478bd9Sstevel@tonic-gate rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum, 21247c478bd9Sstevel@tonic-gate xdrproc_t inproc, char *in, xdrproc_t outproc, char *out, 21257c478bd9Sstevel@tonic-gate int timeo, int retries) 21267c478bd9Sstevel@tonic-gate { 21277c478bd9Sstevel@tonic-gate CLIENT *cl; 21287c478bd9Sstevel@tonic-gate struct timeval tv; 21297c478bd9Sstevel@tonic-gate enum clnt_stat cl_stat; 21307c478bd9Sstevel@tonic-gate int rc; 21317c478bd9Sstevel@tonic-gate 21327c478bd9Sstevel@tonic-gate rc = clnt_tli_kcreate(knconf, call_addr, prognum, versnum, 21337c478bd9Sstevel@tonic-gate 0, retries, CRED(), &cl); 21347c478bd9Sstevel@tonic-gate if (rc) { 21357c478bd9Sstevel@tonic-gate nfs_perror(rc, "mycallrpc: clnt_tli_kcreate failed: %m\n"); 21367c478bd9Sstevel@tonic-gate return (RPC_SYSTEMERROR); /* XXX */ 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate tv.tv_sec = timeo; 21397c478bd9Sstevel@tonic-gate tv.tv_usec = 0; 21407c478bd9Sstevel@tonic-gate cl_stat = CLNT_CALL(cl, procnum, inproc, in, outproc, out, tv); 21417c478bd9Sstevel@tonic-gate AUTH_DESTROY(cl->cl_auth); 21427c478bd9Sstevel@tonic-gate CLNT_DESTROY(cl); 21437c478bd9Sstevel@tonic-gate return (cl_stat); 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate static int 21477c478bd9Sstevel@tonic-gate dl_info(ldi_handle_t lh, dl_info_ack_t *info) 21487c478bd9Sstevel@tonic-gate { 21497c478bd9Sstevel@tonic-gate dl_info_req_t *info_req; 21507c478bd9Sstevel@tonic-gate dl_error_ack_t *error_ack; 21517c478bd9Sstevel@tonic-gate union DL_primitives *dl_prim; 21527c478bd9Sstevel@tonic-gate mblk_t *mp; 21537c478bd9Sstevel@tonic-gate int error; 21547c478bd9Sstevel@tonic-gate 21557c478bd9Sstevel@tonic-gate if ((mp = allocb(sizeof (dl_info_req_t), BPRI_MED)) == NULL) { 21567c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dl_info: allocb failed"); 21577c478bd9Sstevel@tonic-gate return (ENOSR); 21587c478bd9Sstevel@tonic-gate } 21597c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 21607c478bd9Sstevel@tonic-gate 21617c478bd9Sstevel@tonic-gate info_req = (dl_info_req_t *)mp->b_wptr; 21627c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (dl_info_req_t); 21637c478bd9Sstevel@tonic-gate info_req->dl_primitive = DL_INFO_REQ; 21647c478bd9Sstevel@tonic-gate 21657c478bd9Sstevel@tonic-gate (void) ldi_putmsg(lh, mp); 21667c478bd9Sstevel@tonic-gate if ((error = ldi_getmsg(lh, &mp, (timestruc_t *)NULL)) != 0) { 21677c478bd9Sstevel@tonic-gate nfs_perror(error, "dl_info: ldi_getmsg failed: %m\n"); 21687c478bd9Sstevel@tonic-gate return (error); 21697c478bd9Sstevel@tonic-gate } 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate dl_prim = (union DL_primitives *)mp->b_rptr; 21727c478bd9Sstevel@tonic-gate switch (dl_prim->dl_primitive) { 21737c478bd9Sstevel@tonic-gate case DL_INFO_ACK: 21747c478bd9Sstevel@tonic-gate if ((mp->b_wptr-mp->b_rptr) < sizeof (dl_info_ack_t)) { 21757c478bd9Sstevel@tonic-gate printf("dl_info: DL_INFO_ACK protocol error\n"); 21767c478bd9Sstevel@tonic-gate break; 21777c478bd9Sstevel@tonic-gate } 21787c478bd9Sstevel@tonic-gate *info = *(dl_info_ack_t *)mp->b_rptr; 21797c478bd9Sstevel@tonic-gate freemsg(mp); 21807c478bd9Sstevel@tonic-gate return (0); 21817c478bd9Sstevel@tonic-gate 21827c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 21837c478bd9Sstevel@tonic-gate if ((mp->b_wptr-mp->b_rptr) < sizeof (dl_error_ack_t)) { 21847c478bd9Sstevel@tonic-gate printf("dl_info: DL_ERROR_ACK protocol error\n"); 21857c478bd9Sstevel@tonic-gate break; 21867c478bd9Sstevel@tonic-gate } 21877c478bd9Sstevel@tonic-gate 21887c478bd9Sstevel@tonic-gate error_ack = (dl_error_ack_t *)dl_prim; 21897c478bd9Sstevel@tonic-gate printf("dl_info: DLPI error %u\n", error_ack->dl_errno); 21907c478bd9Sstevel@tonic-gate break; 21917c478bd9Sstevel@tonic-gate 21927c478bd9Sstevel@tonic-gate default: 21937c478bd9Sstevel@tonic-gate printf("dl_bind: bad ACK header %u\n", dl_prim->dl_primitive); 21947c478bd9Sstevel@tonic-gate break; 21957c478bd9Sstevel@tonic-gate } 21967c478bd9Sstevel@tonic-gate 21977c478bd9Sstevel@tonic-gate /* 21987c478bd9Sstevel@tonic-gate * Error return only. 21997c478bd9Sstevel@tonic-gate */ 22007c478bd9Sstevel@tonic-gate freemsg(mp); 22017c478bd9Sstevel@tonic-gate return (-1); 22027c478bd9Sstevel@tonic-gate } 22037c478bd9Sstevel@tonic-gate 22047c478bd9Sstevel@tonic-gate /* 22057c478bd9Sstevel@tonic-gate * The network device we will use to boot from is plumbed. Extract the details 22067c478bd9Sstevel@tonic-gate * from rootfs. 22077c478bd9Sstevel@tonic-gate */ 22087c478bd9Sstevel@tonic-gate static void 22097c478bd9Sstevel@tonic-gate init_config(void) 22107c478bd9Sstevel@tonic-gate { 22117c478bd9Sstevel@tonic-gate (void) strlcpy(ndev_path, rootfs.bo_devname, sizeof (ndev_path)); 22127c478bd9Sstevel@tonic-gate (void) strlcpy(ifname, rootfs.bo_ifname, sizeof (ifname)); 22137c478bd9Sstevel@tonic-gate ifunit = rootfs.bo_ppa; 22147c478bd9Sstevel@tonic-gate 22157c478bd9Sstevel@tonic-gate /* 22167c478bd9Sstevel@tonic-gate * Assumes only one linkage array element. 22177c478bd9Sstevel@tonic-gate */ 22187c478bd9Sstevel@tonic-gate dl_udp_netconf.knc_rdev = 22197c478bd9Sstevel@tonic-gate makedevice(clone_major, ddi_name_to_major("udp")); 22207c478bd9Sstevel@tonic-gate dl_tcp_netconf.knc_rdev = 22217c478bd9Sstevel@tonic-gate makedevice(clone_major, ddi_name_to_major("tcp")); 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate /* 22247c478bd9Sstevel@tonic-gate * Now we bringup the interface. 22257c478bd9Sstevel@tonic-gate * Try cached dhcp response first. If it fails, do rarp. 22267c478bd9Sstevel@tonic-gate */ 22277c478bd9Sstevel@tonic-gate if (dhcpinit() != 0 && whoami() != 0) 22287c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 22297c478bd9Sstevel@tonic-gate "%s: no response from interface", ifname); 22307c478bd9Sstevel@tonic-gate else if (dldebug) 22317c478bd9Sstevel@tonic-gate printf("init_config: ifname %s is up\n", ifname); 22327c478bd9Sstevel@tonic-gate } 22337c478bd9Sstevel@tonic-gate 22347c478bd9Sstevel@tonic-gate /* 22357c478bd9Sstevel@tonic-gate * These options are duplicated in cmd/fs.d/nfs/mount/mount.c 22367c478bd9Sstevel@tonic-gate * Changes must be made to both lists. 22377c478bd9Sstevel@tonic-gate */ 22387c478bd9Sstevel@tonic-gate static char *optlist[] = { 22397c478bd9Sstevel@tonic-gate #define OPT_RO 0 22407c478bd9Sstevel@tonic-gate MNTOPT_RO, 22417c478bd9Sstevel@tonic-gate #define OPT_RW 1 22427c478bd9Sstevel@tonic-gate MNTOPT_RW, 22437c478bd9Sstevel@tonic-gate #define OPT_QUOTA 2 22447c478bd9Sstevel@tonic-gate MNTOPT_QUOTA, 22457c478bd9Sstevel@tonic-gate #define OPT_NOQUOTA 3 22467c478bd9Sstevel@tonic-gate MNTOPT_NOQUOTA, 22477c478bd9Sstevel@tonic-gate #define OPT_SOFT 4 22487c478bd9Sstevel@tonic-gate MNTOPT_SOFT, 22497c478bd9Sstevel@tonic-gate #define OPT_HARD 5 22507c478bd9Sstevel@tonic-gate MNTOPT_HARD, 22517c478bd9Sstevel@tonic-gate #define OPT_SUID 6 22527c478bd9Sstevel@tonic-gate MNTOPT_SUID, 22537c478bd9Sstevel@tonic-gate #define OPT_NOSUID 7 22547c478bd9Sstevel@tonic-gate MNTOPT_NOSUID, 22557c478bd9Sstevel@tonic-gate #define OPT_GRPID 8 22567c478bd9Sstevel@tonic-gate MNTOPT_GRPID, 22577c478bd9Sstevel@tonic-gate #define OPT_REMOUNT 9 22587c478bd9Sstevel@tonic-gate MNTOPT_REMOUNT, 22597c478bd9Sstevel@tonic-gate #define OPT_NOSUB 10 22607c478bd9Sstevel@tonic-gate MNTOPT_NOSUB, 22617c478bd9Sstevel@tonic-gate #define OPT_INTR 11 22627c478bd9Sstevel@tonic-gate MNTOPT_INTR, 22637c478bd9Sstevel@tonic-gate #define OPT_NOINTR 12 22647c478bd9Sstevel@tonic-gate MNTOPT_NOINTR, 22657c478bd9Sstevel@tonic-gate #define OPT_PORT 13 22667c478bd9Sstevel@tonic-gate MNTOPT_PORT, 22677c478bd9Sstevel@tonic-gate #define OPT_SECURE 14 22687c478bd9Sstevel@tonic-gate MNTOPT_SECURE, 22697c478bd9Sstevel@tonic-gate #define OPT_RSIZE 15 22707c478bd9Sstevel@tonic-gate MNTOPT_RSIZE, 22717c478bd9Sstevel@tonic-gate #define OPT_WSIZE 16 22727c478bd9Sstevel@tonic-gate MNTOPT_WSIZE, 22737c478bd9Sstevel@tonic-gate #define OPT_TIMEO 17 22747c478bd9Sstevel@tonic-gate MNTOPT_TIMEO, 22757c478bd9Sstevel@tonic-gate #define OPT_RETRANS 18 22767c478bd9Sstevel@tonic-gate MNTOPT_RETRANS, 22777c478bd9Sstevel@tonic-gate #define OPT_ACTIMEO 19 22787c478bd9Sstevel@tonic-gate MNTOPT_ACTIMEO, 22797c478bd9Sstevel@tonic-gate #define OPT_ACREGMIN 20 22807c478bd9Sstevel@tonic-gate MNTOPT_ACREGMIN, 22817c478bd9Sstevel@tonic-gate #define OPT_ACREGMAX 21 22827c478bd9Sstevel@tonic-gate MNTOPT_ACREGMAX, 22837c478bd9Sstevel@tonic-gate #define OPT_ACDIRMIN 22 22847c478bd9Sstevel@tonic-gate MNTOPT_ACDIRMIN, 22857c478bd9Sstevel@tonic-gate #define OPT_ACDIRMAX 23 22867c478bd9Sstevel@tonic-gate MNTOPT_ACDIRMAX, 22877c478bd9Sstevel@tonic-gate #define OPT_BG 24 22887c478bd9Sstevel@tonic-gate MNTOPT_BG, 22897c478bd9Sstevel@tonic-gate #define OPT_FG 25 22907c478bd9Sstevel@tonic-gate MNTOPT_FG, 22917c478bd9Sstevel@tonic-gate #define OPT_RETRY 26 22927c478bd9Sstevel@tonic-gate MNTOPT_RETRY, 22937c478bd9Sstevel@tonic-gate #define OPT_NOAC 27 22947c478bd9Sstevel@tonic-gate MNTOPT_NOAC, 22957c478bd9Sstevel@tonic-gate #define OPT_NOCTO 28 22967c478bd9Sstevel@tonic-gate MNTOPT_NOCTO, 22977c478bd9Sstevel@tonic-gate #define OPT_LLOCK 29 22987c478bd9Sstevel@tonic-gate MNTOPT_LLOCK, 22997c478bd9Sstevel@tonic-gate #define OPT_POSIX 30 23007c478bd9Sstevel@tonic-gate MNTOPT_POSIX, 23017c478bd9Sstevel@tonic-gate #define OPT_VERS 31 23027c478bd9Sstevel@tonic-gate MNTOPT_VERS, 23037c478bd9Sstevel@tonic-gate #define OPT_PROTO 32 23047c478bd9Sstevel@tonic-gate MNTOPT_PROTO, 23057c478bd9Sstevel@tonic-gate #define OPT_SEMISOFT 33 23067c478bd9Sstevel@tonic-gate MNTOPT_SEMISOFT, 23077c478bd9Sstevel@tonic-gate #define OPT_NOPRINT 34 23087c478bd9Sstevel@tonic-gate MNTOPT_NOPRINT, 23097c478bd9Sstevel@tonic-gate #define OPT_SEC 35 23107c478bd9Sstevel@tonic-gate MNTOPT_SEC, 23117c478bd9Sstevel@tonic-gate #define OPT_LARGEFILES 36 23127c478bd9Sstevel@tonic-gate MNTOPT_LARGEFILES, 23137c478bd9Sstevel@tonic-gate #define OPT_NOLARGEFILES 37 23147c478bd9Sstevel@tonic-gate MNTOPT_NOLARGEFILES, 23157c478bd9Sstevel@tonic-gate #define OPT_PUBLIC 38 23167c478bd9Sstevel@tonic-gate MNTOPT_PUBLIC, 23177c478bd9Sstevel@tonic-gate #define OPT_DIRECTIO 39 23187c478bd9Sstevel@tonic-gate MNTOPT_FORCEDIRECTIO, 23197c478bd9Sstevel@tonic-gate #define OPT_NODIRECTIO 40 23207c478bd9Sstevel@tonic-gate MNTOPT_NOFORCEDIRECTIO, 23217c478bd9Sstevel@tonic-gate #define OPT_XATTR 41 23227c478bd9Sstevel@tonic-gate MNTOPT_XATTR, 23237c478bd9Sstevel@tonic-gate #define OPT_NOXATTR 42 23247c478bd9Sstevel@tonic-gate MNTOPT_NOXATTR, 23257c478bd9Sstevel@tonic-gate #define OPT_DEVICES 43 23267c478bd9Sstevel@tonic-gate MNTOPT_DEVICES, 23277c478bd9Sstevel@tonic-gate #define OPT_NODEVICES 44 23287c478bd9Sstevel@tonic-gate MNTOPT_NODEVICES, 23297c478bd9Sstevel@tonic-gate #define OPT_SETUID 45 23307c478bd9Sstevel@tonic-gate MNTOPT_SETUID, 23317c478bd9Sstevel@tonic-gate #define OPT_NOSETUID 46 23327c478bd9Sstevel@tonic-gate MNTOPT_NOSETUID, 23337c478bd9Sstevel@tonic-gate #define OPT_EXEC 47 23347c478bd9Sstevel@tonic-gate MNTOPT_EXEC, 23357c478bd9Sstevel@tonic-gate #define OPT_NOEXEC 48 23367c478bd9Sstevel@tonic-gate MNTOPT_NOEXEC, 23377c478bd9Sstevel@tonic-gate NULL 23387c478bd9Sstevel@tonic-gate }; 23397c478bd9Sstevel@tonic-gate 23407c478bd9Sstevel@tonic-gate static int 23417c478bd9Sstevel@tonic-gate isdigit(int ch) 23427c478bd9Sstevel@tonic-gate { 23437c478bd9Sstevel@tonic-gate return (ch >= '0' && ch <= '9'); 23447c478bd9Sstevel@tonic-gate } 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate #define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') 23477c478bd9Sstevel@tonic-gate #define bad(val) (val == NULL || !isdigit(*val)) 23487c478bd9Sstevel@tonic-gate 23497c478bd9Sstevel@tonic-gate static int 23507c478bd9Sstevel@tonic-gate atoi(const char *p) 23517c478bd9Sstevel@tonic-gate { 23527c478bd9Sstevel@tonic-gate int n; 23537c478bd9Sstevel@tonic-gate int c, neg = 0; 23547c478bd9Sstevel@tonic-gate 23557c478bd9Sstevel@tonic-gate if (!isdigit(c = *p)) { 23567c478bd9Sstevel@tonic-gate while (isspace(c)) 23577c478bd9Sstevel@tonic-gate c = *++p; 23587c478bd9Sstevel@tonic-gate switch (c) { 23597c478bd9Sstevel@tonic-gate case '-': 23607c478bd9Sstevel@tonic-gate neg++; 23617c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 23627c478bd9Sstevel@tonic-gate case '+': 23637c478bd9Sstevel@tonic-gate c = *++p; 23647c478bd9Sstevel@tonic-gate } 23657c478bd9Sstevel@tonic-gate if (!isdigit(c)) 23667c478bd9Sstevel@tonic-gate return (0); 23677c478bd9Sstevel@tonic-gate } 23687c478bd9Sstevel@tonic-gate for (n = '0' - c; isdigit(c = *++p); ) { 23697c478bd9Sstevel@tonic-gate n *= 10; /* two steps to avoid unnecessary overflow */ 23707c478bd9Sstevel@tonic-gate n += '0' - c; /* accum neg to avoid surprises at MAX */ 23717c478bd9Sstevel@tonic-gate } 23727c478bd9Sstevel@tonic-gate return (neg ? n : -n); 23737c478bd9Sstevel@tonic-gate } 23747c478bd9Sstevel@tonic-gate 23757c478bd9Sstevel@tonic-gate /* 23767c478bd9Sstevel@tonic-gate * Default root read tsize XXX 23777c478bd9Sstevel@tonic-gate */ 23787c478bd9Sstevel@tonic-gate int nfs_root_rsize = 8 * 1024; /* conservative for dumb NICs */ 23797c478bd9Sstevel@tonic-gate int nfs4_root_rsize = 32 * 1024; /* only runs on TCP be aggressive */ 23807c478bd9Sstevel@tonic-gate 23817c478bd9Sstevel@tonic-gate /* 23827c478bd9Sstevel@tonic-gate * Default flags: NFSMNT_NOCTO|NFSMNT_LLOCK|NFSMNT_INT 23837c478bd9Sstevel@tonic-gate */ 23847c478bd9Sstevel@tonic-gate int nfs_rootopts = NFSMNT_NOCTO|NFSMNT_LLOCK|NFSMNT_INT; 23857c478bd9Sstevel@tonic-gate 23867c478bd9Sstevel@tonic-gate static int 23877c478bd9Sstevel@tonic-gate init_mountopts(struct nfs_args *args, int version, struct knetconfig **dl_cf, 23887c478bd9Sstevel@tonic-gate int *vfsflags) 23897c478bd9Sstevel@tonic-gate { 23907c478bd9Sstevel@tonic-gate char servername[SYS_NMLN]; 23917c478bd9Sstevel@tonic-gate static int first = 0; 23927c478bd9Sstevel@tonic-gate struct netbuf server_address; 23937c478bd9Sstevel@tonic-gate char *opts, *val; 23947c478bd9Sstevel@tonic-gate int vers; 23957c478bd9Sstevel@tonic-gate struct knetconfig *cf = *dl_cf; 23967c478bd9Sstevel@tonic-gate char rootoptsbuf[256]; 23977c478bd9Sstevel@tonic-gate 23987c478bd9Sstevel@tonic-gate /* 23997c478bd9Sstevel@tonic-gate * Set default mount options 24007c478bd9Sstevel@tonic-gate */ 24017c478bd9Sstevel@tonic-gate args->flags = nfs_rootopts; 24027c478bd9Sstevel@tonic-gate args->rsize = 0; 24037c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACREGMIN; 24047c478bd9Sstevel@tonic-gate args->acregmin = ACMINMAX; 24057c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACREGMAX; 24067c478bd9Sstevel@tonic-gate args->acregmax = ACMAXMAX; 24077c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACDIRMIN; 24087c478bd9Sstevel@tonic-gate args->acdirmin = ACMINMAX; 24097c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACDIRMAX; 24107c478bd9Sstevel@tonic-gate args->acdirmax = ACMAXMAX; 24117c478bd9Sstevel@tonic-gate 24127c478bd9Sstevel@tonic-gate *vfsflags = 0; 24137c478bd9Sstevel@tonic-gate 24147c478bd9Sstevel@tonic-gate /* 24157c478bd9Sstevel@tonic-gate * Only look up the rootopts the first time, we store this in 24167c478bd9Sstevel@tonic-gate * a static buffer but we are guaranteed to be single threaded 24177c478bd9Sstevel@tonic-gate * and not reentrant. 24187c478bd9Sstevel@tonic-gate */ 24197c478bd9Sstevel@tonic-gate if (first == 0) { 24207c478bd9Sstevel@tonic-gate first++; 24217c478bd9Sstevel@tonic-gate 24227c478bd9Sstevel@tonic-gate init_netbuf(&server_address); 24237c478bd9Sstevel@tonic-gate 24247c478bd9Sstevel@tonic-gate if (getfile("rootopts", servername, &server_address, 24257c478bd9Sstevel@tonic-gate rootopts)) { 24267c478bd9Sstevel@tonic-gate rootopts[0] = '\0'; 24277c478bd9Sstevel@tonic-gate free_netbuf(&server_address); 24287c478bd9Sstevel@tonic-gate goto sanity; 24297c478bd9Sstevel@tonic-gate } 24307c478bd9Sstevel@tonic-gate free_netbuf(&server_address); 24317c478bd9Sstevel@tonic-gate } 24327c478bd9Sstevel@tonic-gate 24337c478bd9Sstevel@tonic-gate if (dldebug) 24347c478bd9Sstevel@tonic-gate printf("rootopts = %s\n", rootopts); 24357c478bd9Sstevel@tonic-gate 24367c478bd9Sstevel@tonic-gate /* 24377c478bd9Sstevel@tonic-gate * We have to preserve rootopts for second time. 24387c478bd9Sstevel@tonic-gate */ 24397c478bd9Sstevel@tonic-gate (void) strncpy(rootoptsbuf, rootopts, sizeof (rootoptsbuf)); 24407c478bd9Sstevel@tonic-gate rootoptsbuf[sizeof (rootoptsbuf) - 1] = '\0'; 24417c478bd9Sstevel@tonic-gate opts = rootoptsbuf; 24427c478bd9Sstevel@tonic-gate while (*opts) { 24437c478bd9Sstevel@tonic-gate int opt; 24447c478bd9Sstevel@tonic-gate 24457c478bd9Sstevel@tonic-gate switch (opt = getsubopt(&opts, optlist, &val)) { 24467c478bd9Sstevel@tonic-gate /* 24477c478bd9Sstevel@tonic-gate * Options that are defaults or meaningless so ignored 24487c478bd9Sstevel@tonic-gate */ 24497c478bd9Sstevel@tonic-gate case OPT_QUOTA: 24507c478bd9Sstevel@tonic-gate case OPT_NOQUOTA: 24517c478bd9Sstevel@tonic-gate case OPT_SUID: 24527c478bd9Sstevel@tonic-gate case OPT_DEVICES: 24537c478bd9Sstevel@tonic-gate case OPT_SETUID: 24547c478bd9Sstevel@tonic-gate case OPT_BG: 24557c478bd9Sstevel@tonic-gate case OPT_FG: 24567c478bd9Sstevel@tonic-gate case OPT_RETRY: 24577c478bd9Sstevel@tonic-gate case OPT_POSIX: 24587c478bd9Sstevel@tonic-gate case OPT_LARGEFILES: 24597c478bd9Sstevel@tonic-gate case OPT_XATTR: 24607c478bd9Sstevel@tonic-gate case OPT_NOXATTR: 24617c478bd9Sstevel@tonic-gate case OPT_EXEC: 24627c478bd9Sstevel@tonic-gate break; 24637c478bd9Sstevel@tonic-gate case OPT_RO: 24647c478bd9Sstevel@tonic-gate *vfsflags |= MS_RDONLY; 24657c478bd9Sstevel@tonic-gate break; 24667c478bd9Sstevel@tonic-gate case OPT_RW: 24677c478bd9Sstevel@tonic-gate *vfsflags &= ~(MS_RDONLY); 24687c478bd9Sstevel@tonic-gate break; 24697c478bd9Sstevel@tonic-gate case OPT_SOFT: 24707c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SOFT; 24717c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_SEMISOFT); 24727c478bd9Sstevel@tonic-gate break; 24737c478bd9Sstevel@tonic-gate case OPT_SEMISOFT: 24747c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SOFT; 24757c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_SEMISOFT; 24767c478bd9Sstevel@tonic-gate break; 24777c478bd9Sstevel@tonic-gate case OPT_HARD: 24787c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_SOFT); 24797c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_SEMISOFT); 24807c478bd9Sstevel@tonic-gate break; 24817c478bd9Sstevel@tonic-gate case OPT_NOSUID: 24827c478bd9Sstevel@tonic-gate case OPT_NODEVICES: 24837c478bd9Sstevel@tonic-gate case OPT_NOSETUID: 24847c478bd9Sstevel@tonic-gate case OPT_NOEXEC: 24857c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 24867c478bd9Sstevel@tonic-gate "nfs_dlboot: may not set root partition %s", 24877c478bd9Sstevel@tonic-gate optlist[opt]); 24887c478bd9Sstevel@tonic-gate break; 24897c478bd9Sstevel@tonic-gate case OPT_GRPID: 24907c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_GRPID; 24917c478bd9Sstevel@tonic-gate break; 24927c478bd9Sstevel@tonic-gate case OPT_REMOUNT: 24937c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 24947c478bd9Sstevel@tonic-gate "nfs_dlboot: may not remount root partition"); 24957c478bd9Sstevel@tonic-gate break; 24967c478bd9Sstevel@tonic-gate case OPT_INTR: 24977c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_INT; 24987c478bd9Sstevel@tonic-gate break; 24997c478bd9Sstevel@tonic-gate case OPT_NOINTR: 25007c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_INT); 25017c478bd9Sstevel@tonic-gate break; 25027c478bd9Sstevel@tonic-gate case OPT_NOAC: 25037c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NOAC; 25047c478bd9Sstevel@tonic-gate break; 25057c478bd9Sstevel@tonic-gate case OPT_PORT: 25067c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25077c478bd9Sstevel@tonic-gate "nfs_dlboot: may not change root port number"); 25087c478bd9Sstevel@tonic-gate break; 25097c478bd9Sstevel@tonic-gate case OPT_SECURE: 25107c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25117c478bd9Sstevel@tonic-gate "nfs_dlboot: root mounted auth_unix, secure ignored"); 25127c478bd9Sstevel@tonic-gate break; 25137c478bd9Sstevel@tonic-gate case OPT_NOCTO: 25147c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NOCTO; 25157c478bd9Sstevel@tonic-gate break; 25167c478bd9Sstevel@tonic-gate case OPT_RSIZE: 25177c478bd9Sstevel@tonic-gate if (bad(val)) { 25187c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25197c478bd9Sstevel@tonic-gate "nfs_dlboot: invalid option: rsize"); 25207c478bd9Sstevel@tonic-gate break; 25217c478bd9Sstevel@tonic-gate } 25227c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_RSIZE; 25237c478bd9Sstevel@tonic-gate args->rsize = atoi(val); 25247c478bd9Sstevel@tonic-gate break; 25257c478bd9Sstevel@tonic-gate case OPT_WSIZE: 25267c478bd9Sstevel@tonic-gate if (bad(val)) { 25277c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25287c478bd9Sstevel@tonic-gate "nfs_dlboot: invalid option: wsize"); 25297c478bd9Sstevel@tonic-gate break; 25307c478bd9Sstevel@tonic-gate } 25317c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_WSIZE; 25327c478bd9Sstevel@tonic-gate args->wsize = atoi(val); 25337c478bd9Sstevel@tonic-gate break; 25347c478bd9Sstevel@tonic-gate case OPT_TIMEO: 25357c478bd9Sstevel@tonic-gate if (bad(val)) { 25367c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25377c478bd9Sstevel@tonic-gate "nfs_dlboot: invalid option: timeo"); 25387c478bd9Sstevel@tonic-gate break; 25397c478bd9Sstevel@tonic-gate } 25407c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_TIMEO; 25417c478bd9Sstevel@tonic-gate args->timeo = atoi(val); 25427c478bd9Sstevel@tonic-gate break; 25437c478bd9Sstevel@tonic-gate case OPT_RETRANS: 25447c478bd9Sstevel@tonic-gate if (bad(val)) { 25457c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25467c478bd9Sstevel@tonic-gate "nfs_dlboot: invalid option: retrans"); 25477c478bd9Sstevel@tonic-gate break; 25487c478bd9Sstevel@tonic-gate } 25497c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_RETRANS; 25507c478bd9Sstevel@tonic-gate args->retrans = atoi(val); 25517c478bd9Sstevel@tonic-gate break; 25527c478bd9Sstevel@tonic-gate case OPT_ACTIMEO: 25537c478bd9Sstevel@tonic-gate if (bad(val)) { 25547c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25557c478bd9Sstevel@tonic-gate "nfs_dlboot: invalid option: actimeo"); 25567c478bd9Sstevel@tonic-gate break; 25577c478bd9Sstevel@tonic-gate } 25587c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACDIRMAX; 25597c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACREGMAX; 25607c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACDIRMIN; 25617c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACREGMIN; 25627c478bd9Sstevel@tonic-gate args->acdirmin = args->acregmin = args->acdirmax = 25637c478bd9Sstevel@tonic-gate args->acregmax = atoi(val); 25647c478bd9Sstevel@tonic-gate break; 25657c478bd9Sstevel@tonic-gate case OPT_ACREGMIN: 25667c478bd9Sstevel@tonic-gate if (bad(val)) { 25677c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25687c478bd9Sstevel@tonic-gate "nfs_dlboot: invalid option: acregmin"); 25697c478bd9Sstevel@tonic-gate break; 25707c478bd9Sstevel@tonic-gate } 25717c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACREGMIN; 25727c478bd9Sstevel@tonic-gate args->acregmin = atoi(val); 25737c478bd9Sstevel@tonic-gate break; 25747c478bd9Sstevel@tonic-gate case OPT_ACREGMAX: 25757c478bd9Sstevel@tonic-gate if (bad(val)) { 25767c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25777c478bd9Sstevel@tonic-gate "nfs_dlboot: invalid option: acregmax"); 25787c478bd9Sstevel@tonic-gate break; 25797c478bd9Sstevel@tonic-gate } 25807c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACREGMAX; 25817c478bd9Sstevel@tonic-gate args->acregmax = atoi(val); 25827c478bd9Sstevel@tonic-gate break; 25837c478bd9Sstevel@tonic-gate case OPT_ACDIRMIN: 25847c478bd9Sstevel@tonic-gate if (bad(val)) { 25857c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25867c478bd9Sstevel@tonic-gate "nfs_dlboot: invalid option: acdirmin"); 25877c478bd9Sstevel@tonic-gate break; 25887c478bd9Sstevel@tonic-gate } 25897c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACDIRMIN; 25907c478bd9Sstevel@tonic-gate args->acdirmin = atoi(val); 25917c478bd9Sstevel@tonic-gate break; 25927c478bd9Sstevel@tonic-gate case OPT_ACDIRMAX: 25937c478bd9Sstevel@tonic-gate if (bad(val)) { 25947c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 25957c478bd9Sstevel@tonic-gate "nfs_dlboot: invalid option: acdirmax"); 25967c478bd9Sstevel@tonic-gate break; 25977c478bd9Sstevel@tonic-gate } 25987c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_ACDIRMAX; 25997c478bd9Sstevel@tonic-gate args->acdirmax = atoi(val); 26007c478bd9Sstevel@tonic-gate break; 26017c478bd9Sstevel@tonic-gate case OPT_LLOCK: 26027c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_LLOCK; 26037c478bd9Sstevel@tonic-gate break; 26047c478bd9Sstevel@tonic-gate case OPT_VERS: 26057c478bd9Sstevel@tonic-gate if (bad(val)) { 26067c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 26077c478bd9Sstevel@tonic-gate "nfs_dlboot: invalid option: vers"); 26087c478bd9Sstevel@tonic-gate break; 26097c478bd9Sstevel@tonic-gate } 26107c478bd9Sstevel@tonic-gate vers = atoi(val); 26117c478bd9Sstevel@tonic-gate /* 26127c478bd9Sstevel@tonic-gate * If the requested version is less than what we 26137c478bd9Sstevel@tonic-gate * chose, pretend the chosen version doesn't exist 26147c478bd9Sstevel@tonic-gate */ 26157c478bd9Sstevel@tonic-gate if (vers < version) { 26167c478bd9Sstevel@tonic-gate return (EPROTONOSUPPORT); 26177c478bd9Sstevel@tonic-gate } 26187c478bd9Sstevel@tonic-gate if (vers > version) { 26197c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 26207c478bd9Sstevel@tonic-gate "nfs_dlboot: version %d unavailable", 26217c478bd9Sstevel@tonic-gate vers); 26227c478bd9Sstevel@tonic-gate return (EINVAL); 26237c478bd9Sstevel@tonic-gate } 26247c478bd9Sstevel@tonic-gate break; 26257c478bd9Sstevel@tonic-gate case OPT_PROTO: 26267c478bd9Sstevel@tonic-gate /* 26277c478bd9Sstevel@tonic-gate * NFSv4 can only run over TCP, if they requested 26287c478bd9Sstevel@tonic-gate * UDP pretend v4 doesn't exist, they might not have 26297c478bd9Sstevel@tonic-gate * specified a version allowing a fallback to v2 or v3. 26307c478bd9Sstevel@tonic-gate */ 26317c478bd9Sstevel@tonic-gate if (version == NFS_V4 && strcmp(val, NC_UDP) == 0) 26327c478bd9Sstevel@tonic-gate return (EPROTONOSUPPORT); 26337c478bd9Sstevel@tonic-gate /* 26347c478bd9Sstevel@tonic-gate * TCP is always chosen over UDP, so if the 26357c478bd9Sstevel@tonic-gate * requested is the same as the chosen either 26367c478bd9Sstevel@tonic-gate * they chose TCP when available or UDP on a UDP 26377c478bd9Sstevel@tonic-gate * only server. 26387c478bd9Sstevel@tonic-gate */ 26397c478bd9Sstevel@tonic-gate if (strcmp(cf->knc_proto, val) == 0) 26407c478bd9Sstevel@tonic-gate break; 26417c478bd9Sstevel@tonic-gate /* 26427c478bd9Sstevel@tonic-gate * If we chose UDP, they must have requested TCP 26437c478bd9Sstevel@tonic-gate */ 26447c478bd9Sstevel@tonic-gate if (strcmp(cf->knc_proto, NC_TCP) != 0) { 26457c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 26467c478bd9Sstevel@tonic-gate "nfs_dlboot: TCP protocol unavailable"); 26477c478bd9Sstevel@tonic-gate return (EINVAL); 26487c478bd9Sstevel@tonic-gate } 26497c478bd9Sstevel@tonic-gate /* 26507c478bd9Sstevel@tonic-gate * They can only have requested UDP 26517c478bd9Sstevel@tonic-gate */ 26527c478bd9Sstevel@tonic-gate if (strcmp(val, NC_UDP) != 0) { 26537c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 26547c478bd9Sstevel@tonic-gate "nfs_dlboot: unknown protocol"); 26557c478bd9Sstevel@tonic-gate return (EINVAL); 26567c478bd9Sstevel@tonic-gate } 26577c478bd9Sstevel@tonic-gate *dl_cf = &dl_udp_netconf; 26587c478bd9Sstevel@tonic-gate break; 26597c478bd9Sstevel@tonic-gate case OPT_NOPRINT: 26607c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_NOPRINT; 26617c478bd9Sstevel@tonic-gate break; 26627c478bd9Sstevel@tonic-gate case OPT_NOLARGEFILES: 26637c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 26647c478bd9Sstevel@tonic-gate "nfs_dlboot: NFS can't support nolargefiles"); 26657c478bd9Sstevel@tonic-gate break; 26667c478bd9Sstevel@tonic-gate case OPT_SEC: 26677c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 26687c478bd9Sstevel@tonic-gate "nfs_dlboot: root mounted auth_unix, sec ignored"); 26697c478bd9Sstevel@tonic-gate break; 26707c478bd9Sstevel@tonic-gate 26717c478bd9Sstevel@tonic-gate case OPT_DIRECTIO: 26727c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_DIRECTIO; 26737c478bd9Sstevel@tonic-gate break; 26747c478bd9Sstevel@tonic-gate 26757c478bd9Sstevel@tonic-gate case OPT_NODIRECTIO: 26767c478bd9Sstevel@tonic-gate args->flags &= ~(NFSMNT_DIRECTIO); 26777c478bd9Sstevel@tonic-gate break; 26787c478bd9Sstevel@tonic-gate 26797c478bd9Sstevel@tonic-gate default: 26807c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 26817c478bd9Sstevel@tonic-gate "nfs_dlboot: ignoring invalid option \"%s\"", val); 26827c478bd9Sstevel@tonic-gate break; 26837c478bd9Sstevel@tonic-gate } 26847c478bd9Sstevel@tonic-gate } 26857c478bd9Sstevel@tonic-gate sanity: 26867c478bd9Sstevel@tonic-gate /* 26877c478bd9Sstevel@tonic-gate * Set some sane limits on read size 26887c478bd9Sstevel@tonic-gate */ 26897c478bd9Sstevel@tonic-gate if (!(args->flags & NFSMNT_RSIZE) || args->rsize == 0) { 26907c478bd9Sstevel@tonic-gate /* 26917c478bd9Sstevel@tonic-gate * Establish defaults 26927c478bd9Sstevel@tonic-gate */ 26937c478bd9Sstevel@tonic-gate args->flags |= NFSMNT_RSIZE; 26947c478bd9Sstevel@tonic-gate if (version == NFS_V4) 26957c478bd9Sstevel@tonic-gate args->rsize = nfs4_root_rsize; 26967c478bd9Sstevel@tonic-gate else 26977c478bd9Sstevel@tonic-gate args->rsize = nfs_root_rsize; 26987c478bd9Sstevel@tonic-gate return (0); 26997c478bd9Sstevel@tonic-gate } 27007c478bd9Sstevel@tonic-gate /* 27017c478bd9Sstevel@tonic-gate * No less than 512 bytes, otherwise it will take forever to boot 27027c478bd9Sstevel@tonic-gate */ 27037c478bd9Sstevel@tonic-gate if (args->rsize < 512) 27047c478bd9Sstevel@tonic-gate args->rsize = 512; 27057c478bd9Sstevel@tonic-gate /* 27067c478bd9Sstevel@tonic-gate * If we are running over UDP, we cannot exceed 64KB, trim 27077c478bd9Sstevel@tonic-gate * to 56KB to allow room for headers. 27087c478bd9Sstevel@tonic-gate */ 27097c478bd9Sstevel@tonic-gate if (*dl_cf == &dl_udp_netconf && args->rsize > (56 * 1024)) 27107c478bd9Sstevel@tonic-gate args->rsize = 56 * 1024; 27117c478bd9Sstevel@tonic-gate return (0); 27127c478bd9Sstevel@tonic-gate } 2713