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