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