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