17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5843e1988Sjohnlev * Common Development and Distribution License (the "License").
6843e1988Sjohnlev * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22d62bc4baSyz * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
2615c07adcSJohn Levon /*
2715c07adcSJohn Levon * Copyright (c) 2018, Joyent, Inc.
2815c07adcSJohn Levon */
2915c07adcSJohn Levon
307c478bd9Sstevel@tonic-gate #include <sys/param.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/systm.h>
337c478bd9Sstevel@tonic-gate #include <sys/cred.h>
347c478bd9Sstevel@tonic-gate #include <sys/user.h>
357c478bd9Sstevel@tonic-gate #include <sys/file.h>
367c478bd9Sstevel@tonic-gate #include <sys/stream.h>
377c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
387c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
397c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
407c478bd9Sstevel@tonic-gate #include <sys/debug.h>
417c478bd9Sstevel@tonic-gate #include <sys/tiuser.h>
427c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
437c478bd9Sstevel@tonic-gate #include <sys/socket.h>
447c478bd9Sstevel@tonic-gate #include <sys/t_kuser.h>
457c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
467c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
477c478bd9Sstevel@tonic-gate #include <sys/netconfig.h>
487c478bd9Sstevel@tonic-gate #include <sys/ethernet.h>
497c478bd9Sstevel@tonic-gate #include <sys/dlpi.h>
507c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
517c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
527c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
537c478bd9Sstevel@tonic-gate #include <sys/bootprops.h>
547c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
557c478bd9Sstevel@tonic-gate #include <sys/promif.h>
567c478bd9Sstevel@tonic-gate #include <sys/mount.h>
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate #include <net/if.h>
597c478bd9Sstevel@tonic-gate #include <net/route.h>
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate #include <netinet/in.h>
627c478bd9Sstevel@tonic-gate #include <netinet/arp.h>
637c478bd9Sstevel@tonic-gate #include <netinet/dhcp.h>
647c478bd9Sstevel@tonic-gate #include <netinet/inetutil.h>
657c478bd9Sstevel@tonic-gate #include <dhcp_impl.h>
667c478bd9Sstevel@tonic-gate #include <sys/sunos_dhcp_class.h>
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate #include <rpc/types.h>
697c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
707c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
717c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
727c478bd9Sstevel@tonic-gate #include <rpc/clnt.h>
737c478bd9Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
747c478bd9Sstevel@tonic-gate #include <rpc/pmap_rmt.h>
757c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h>
767c478bd9Sstevel@tonic-gate #include <rpc/bootparam.h>
777c478bd9Sstevel@tonic-gate #include <rpc/rpcb_prot.h>
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
807c478bd9Sstevel@tonic-gate #include <nfs/nfs4.h>
817c478bd9Sstevel@tonic-gate #include <nfs/nfs_clnt.h>
827c478bd9Sstevel@tonic-gate #include <nfs/mount.h>
837c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate #include <sys/kstr.h>
867c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
877c478bd9Sstevel@tonic-gate #include <sys/sunldi.h>
887c478bd9Sstevel@tonic-gate #include <sys/esunddi.h>
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate #include <sys/errno.h>
917c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate /*
947c478bd9Sstevel@tonic-gate * RPC timers and retries
957c478bd9Sstevel@tonic-gate */
967c478bd9Sstevel@tonic-gate #define PMAP_RETRIES 5
977c478bd9Sstevel@tonic-gate #define DEFAULT_RETRIES 3
987c478bd9Sstevel@tonic-gate #define GETFILE_RETRIES 2
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate #define DEFAULT_TIMEO 3
1017c478bd9Sstevel@tonic-gate #define WHOAMI_TIMEO 20
1027c478bd9Sstevel@tonic-gate #define REVARP_TIMEO 5
1037c478bd9Sstevel@tonic-gate #define GETFILE_TIMEO 1
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate * These are from the rpcgen'd version of mount.h XXX
1077c478bd9Sstevel@tonic-gate */
1087c478bd9Sstevel@tonic-gate #define MOUNTPROG 100005
1097c478bd9Sstevel@tonic-gate #define MOUNTPROC_MNT 1
1107c478bd9Sstevel@tonic-gate #define MOUNTVERS 1
1117c478bd9Sstevel@tonic-gate #define MOUNTVERS_POSIX 2
1127c478bd9Sstevel@tonic-gate #define MOUNTVERS3 3
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate struct fhstatus {
1157c478bd9Sstevel@tonic-gate int fhs_status;
1167c478bd9Sstevel@tonic-gate fhandle_t fhs_fh;
1177c478bd9Sstevel@tonic-gate };
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate #define FHSIZE3 64
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate struct fhandle3 {
1227c478bd9Sstevel@tonic-gate uint_t fhandle3_len;
1237c478bd9Sstevel@tonic-gate char *fhandle3_val;
1247c478bd9Sstevel@tonic-gate };
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate enum mountstat3 {
1277c478bd9Sstevel@tonic-gate MNT_OK = 0,
1287c478bd9Sstevel@tonic-gate MNT3ERR_PERM = 1,
1297c478bd9Sstevel@tonic-gate MNT3ERR_NOENT = 2,
1307c478bd9Sstevel@tonic-gate MNT3ERR_IO = 5,
1317c478bd9Sstevel@tonic-gate MNT3ERR_ACCES = 13,
1327c478bd9Sstevel@tonic-gate MNT3ERR_NOTDIR = 20,
1337c478bd9Sstevel@tonic-gate MNT3ERR_INVAL = 22,
1347c478bd9Sstevel@tonic-gate MNT3ERR_NAMETOOLONG = 63,
1357c478bd9Sstevel@tonic-gate MNT3ERR_NOTSUPP = 10004,
1367c478bd9Sstevel@tonic-gate MNT3ERR_SERVERFAULT = 10006
1377c478bd9Sstevel@tonic-gate };
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate struct mountres3_ok {
1407c478bd9Sstevel@tonic-gate struct fhandle3 fhandle;
1417c478bd9Sstevel@tonic-gate struct {
1427c478bd9Sstevel@tonic-gate uint_t auth_flavors_len;
1437c478bd9Sstevel@tonic-gate int *auth_flavors_val;
1447c478bd9Sstevel@tonic-gate } auth_flavors;
1457c478bd9Sstevel@tonic-gate };
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate struct mountres3 {
1487c478bd9Sstevel@tonic-gate enum mountstat3 fhs_status;
1497c478bd9Sstevel@tonic-gate union {
1507c478bd9Sstevel@tonic-gate struct mountres3_ok mountinfo;
1517c478bd9Sstevel@tonic-gate } mountres3_u;
1527c478bd9Sstevel@tonic-gate };
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate /*
1557c478bd9Sstevel@tonic-gate * DLPI address format.
1567c478bd9Sstevel@tonic-gate */
1577c478bd9Sstevel@tonic-gate struct dladdr {
1587c478bd9Sstevel@tonic-gate uchar_t dl_phys[6];
1597c478bd9Sstevel@tonic-gate ushort_t dl_sap;
1607c478bd9Sstevel@tonic-gate };
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = {
1637c478bd9Sstevel@tonic-gate &mod_miscops, "Boot diskless"
1647c478bd9Sstevel@tonic-gate };
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1677c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL
1687c478bd9Sstevel@tonic-gate };
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate static int dldebug;
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate int
_init(void)1737c478bd9Sstevel@tonic-gate _init(void)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage));
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate int
_fini(void)1797c478bd9Sstevel@tonic-gate _fini(void)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage));
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1857c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate
190cc2b7f04Sdduvall
1917c478bd9Sstevel@tonic-gate static enum clnt_stat pmap_rmt_call(struct knetconfig *, struct netbuf *,
1927c478bd9Sstevel@tonic-gate bool_t, rpcprog_t, rpcvers_t, rpcproc_t, xdrproc_t,
1937c478bd9Sstevel@tonic-gate caddr_t, xdrproc_t, caddr_t, struct timeval,
1947c478bd9Sstevel@tonic-gate struct netbuf *);
1957c478bd9Sstevel@tonic-gate static bool_t myxdr_rmtcall_args(XDR *, struct rmtcallargs *);
1967c478bd9Sstevel@tonic-gate static bool_t myxdr_rmtcallres(XDR *, struct rmtcallres *);
1977c478bd9Sstevel@tonic-gate static bool_t myxdr_pmap(XDR *, struct pmap *);
1987c478bd9Sstevel@tonic-gate static bool_t myxdr_fhstatus(XDR *xdrs, struct fhstatus *fhsp);
1997c478bd9Sstevel@tonic-gate static bool_t myxdr_fhandle(XDR *xdrs, fhandle_t *fh);
2007c478bd9Sstevel@tonic-gate static bool_t myxdr_mountres3(XDR *xdrs, struct mountres3 *objp);
2017c478bd9Sstevel@tonic-gate static bool_t myxdr_mountstat3(XDR *xdrs, enum mountstat3 *objp);
2027c478bd9Sstevel@tonic-gate static bool_t myxdr_mountres3_ok(XDR *xdrs,
2037c478bd9Sstevel@tonic-gate struct mountres3_ok *objp);
2047c478bd9Sstevel@tonic-gate static bool_t myxdr_fhandle3(XDR *xdrs, struct fhandle3 *objp);
2057c478bd9Sstevel@tonic-gate static enum clnt_stat pmap_kgetport(struct knetconfig *, struct netbuf *,
2067c478bd9Sstevel@tonic-gate rpcprog_t, rpcvers_t, rpcprot_t);
2077c478bd9Sstevel@tonic-gate static enum clnt_stat mycallrpc(struct knetconfig *, struct netbuf *,
2087c478bd9Sstevel@tonic-gate rpcprog_t, rpcvers_t, rpcproc_t, xdrproc_t,
2097c478bd9Sstevel@tonic-gate char *, xdrproc_t, char *, int, int);
2107c478bd9Sstevel@tonic-gate static int ifioctl(TIUSER *, int, struct netbuf *);
2117c478bd9Sstevel@tonic-gate static int getfile(char *, char *, struct netbuf *, char *);
2127c478bd9Sstevel@tonic-gate static int ping_prog(struct netbuf *, uint_t prog, uint_t vers,
2137c478bd9Sstevel@tonic-gate int proto, enum clnt_stat *);
2147c478bd9Sstevel@tonic-gate static int mountnfs(struct netbuf *, char *, char *,
2157c478bd9Sstevel@tonic-gate fhandle_t *, int *);
2167c478bd9Sstevel@tonic-gate static int mountnfs3(struct netbuf *, char *, char *,
2177c478bd9Sstevel@tonic-gate nfs_fh3 *, int *);
2187c478bd9Sstevel@tonic-gate static int init_mountopts(struct nfs_args *, int,
2197c478bd9Sstevel@tonic-gate struct knetconfig **, int *);
2207c478bd9Sstevel@tonic-gate static int revarp_myaddr(TIUSER *);
2217c478bd9Sstevel@tonic-gate static void revarp_start(ldi_handle_t, struct netbuf *);
2227c478bd9Sstevel@tonic-gate static void revarpinput(ldi_handle_t, struct netbuf *);
2237c478bd9Sstevel@tonic-gate static void init_netbuf(struct netbuf *);
2247c478bd9Sstevel@tonic-gate static void free_netbuf(struct netbuf *);
2257c478bd9Sstevel@tonic-gate static int rtioctl(TIUSER *, int, struct rtentry *);
2267c478bd9Sstevel@tonic-gate static void init_config(void);
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate static void cacheinit(void);
2297c478bd9Sstevel@tonic-gate static int cacheinfo(char *, int, struct netbuf *, char *, int);
2307c478bd9Sstevel@tonic-gate static int dlifconfig(TIUSER *, struct in_addr *, struct in_addr *,
231843e1988Sjohnlev struct in_addr *, uint_t);
2327c478bd9Sstevel@tonic-gate static int setifflags(TIUSER *, uint_t);
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate static char *inet_ntoa(struct in_addr);
2357c478bd9Sstevel@tonic-gate static int inet_aton(char *, uchar_t *);
2367c478bd9Sstevel@tonic-gate static int isdigit(int);
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate * Should be in some common
2407c478bd9Sstevel@tonic-gate * ethernet source file.
2417c478bd9Sstevel@tonic-gate */
2427c478bd9Sstevel@tonic-gate static struct ether_addr etherbroadcastaddr = {
2437c478bd9Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
2447c478bd9Sstevel@tonic-gate };
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate static struct ether_addr myether;
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate * "ifname" is the interface name/unit as read from the boot
2507c478bd9Sstevel@tonic-gate * arguments.
2517c478bd9Sstevel@tonic-gate * "ndev" is the major device number of the network interface
2527c478bd9Sstevel@tonic-gate * used to boot from.
2537c478bd9Sstevel@tonic-gate * "ifunit" it the physical point of attachment for the network
2547c478bd9Sstevel@tonic-gate * interface used to boot from.
2557c478bd9Sstevel@tonic-gate *
2567c478bd9Sstevel@tonic-gate * Both of these are initialized in "init_config()".
2577c478bd9Sstevel@tonic-gate */
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate static char ifname[IFNAMSIZ];
2607c478bd9Sstevel@tonic-gate static char ndev_path[MAXPATHLEN];
2617c478bd9Sstevel@tonic-gate static int ifunit;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate /*
2647c478bd9Sstevel@tonic-gate * XXX these should be shared
2657c478bd9Sstevel@tonic-gate */
2667c478bd9Sstevel@tonic-gate static struct knetconfig dl_udp_netconf = {
2677c478bd9Sstevel@tonic-gate NC_TPI_CLTS, /* semantics */
2687c478bd9Sstevel@tonic-gate NC_INET, /* family */
2697c478bd9Sstevel@tonic-gate NC_UDP, /* protocol */
2707c478bd9Sstevel@tonic-gate 0, /* device */
2717c478bd9Sstevel@tonic-gate };
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate static struct knetconfig dl_tcp_netconf = {
2747c478bd9Sstevel@tonic-gate NC_TPI_COTS, /* semantics */
2757c478bd9Sstevel@tonic-gate NC_INET, /* family */
2767c478bd9Sstevel@tonic-gate NC_TCP, /* protocol */
2777c478bd9Sstevel@tonic-gate 0, /* device */
2787c478bd9Sstevel@tonic-gate };
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate /* parameters from DHCP or bootparamd */
2817c478bd9Sstevel@tonic-gate static PKT_LIST *pl = NULL;
2827c478bd9Sstevel@tonic-gate static uchar_t server_ip[4];
2837c478bd9Sstevel@tonic-gate static uchar_t dhcp_server_ip[4];
2847c478bd9Sstevel@tonic-gate static char *server_name_c, *server_path_c;
2857c478bd9Sstevel@tonic-gate static char rootopts[256];
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate /*
2887c478bd9Sstevel@tonic-gate * XXX Until we get the nfsmapid deadlocks all fixed, don't allow
2897c478bd9Sstevel@tonic-gate * XXX a v4 root mount.
2907c478bd9Sstevel@tonic-gate */
2917c478bd9Sstevel@tonic-gate int nfs4_no_diskless_root_support = 1;
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate int
mount_root(char * name,char * path,int version,struct nfs_args * args,int * vfsflags)2947c478bd9Sstevel@tonic-gate mount_root(char *name, char *path, int version, struct nfs_args *args,
295f3de0dd9SToomas Soome int *vfsflags)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate int rc;
2987c478bd9Sstevel@tonic-gate int proto;
2997c478bd9Sstevel@tonic-gate struct knetconfig *dl_cf;
3007c478bd9Sstevel@tonic-gate static int init_done = 0;
3017c478bd9Sstevel@tonic-gate enum clnt_stat stat;
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate if (dldebug)
3047c478bd9Sstevel@tonic-gate printf("mount_root: name=%s\n", name);
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate if (init_done == 0) {
3077c478bd9Sstevel@tonic-gate init_config();
3087c478bd9Sstevel@tonic-gate init_done = 1;
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate init_netbuf(args->addr);
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate do {
3147c478bd9Sstevel@tonic-gate rc = getfile(name, args->hostname, args->addr, path);
3157c478bd9Sstevel@tonic-gate } while (rc == ETIMEDOUT);
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate if (rc) {
3187c478bd9Sstevel@tonic-gate free_netbuf(args->addr);
3197c478bd9Sstevel@tonic-gate return (rc);
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate ASSERT(args->knconf->knc_protofmly != NULL);
3237c478bd9Sstevel@tonic-gate ASSERT(args->knconf->knc_proto != NULL);
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate switch (version) {
3267c478bd9Sstevel@tonic-gate case NFS_VERSION:
3277c478bd9Sstevel@tonic-gate rc = mountnfs(args->addr, args->hostname, path,
3287c478bd9Sstevel@tonic-gate (fhandle_t *)args->fh, &proto);
3297c478bd9Sstevel@tonic-gate break;
3307c478bd9Sstevel@tonic-gate case NFS_V3:
3317c478bd9Sstevel@tonic-gate rc = mountnfs3(args->addr, args->hostname, path,
3327c478bd9Sstevel@tonic-gate (nfs_fh3 *)args->fh, &proto);
3337c478bd9Sstevel@tonic-gate break;
3347c478bd9Sstevel@tonic-gate case NFS_V4:
3357c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)args->addr->buf)->sin_port =
336843e1988Sjohnlev htons(NFS_PORT);
3377c478bd9Sstevel@tonic-gate if (ping_prog(args->addr, NFS_PROGRAM, NFS_V4, IPPROTO_TCP,
338843e1988Sjohnlev &stat)) {
3397c478bd9Sstevel@tonic-gate proto = IPPROTO_TCP;
3407c478bd9Sstevel@tonic-gate rc = 0;
3417c478bd9Sstevel@tonic-gate } else {
3427c478bd9Sstevel@tonic-gate switch (stat) {
3437c478bd9Sstevel@tonic-gate case RPC_PROGVERSMISMATCH:
3447c478bd9Sstevel@tonic-gate case RPC_XPRTFAILED:
3457c478bd9Sstevel@tonic-gate /*
3467c478bd9Sstevel@tonic-gate * Common failures if v4 unsupported or no TCP
3477c478bd9Sstevel@tonic-gate */
3487c478bd9Sstevel@tonic-gate rc = EPROTONOSUPPORT;
3497c478bd9Sstevel@tonic-gate break;
3507c478bd9Sstevel@tonic-gate default:
3517c478bd9Sstevel@tonic-gate rc = ENXIO;
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate if (nfs4_no_diskless_root_support)
3557c478bd9Sstevel@tonic-gate rc = EPROTONOSUPPORT;
3567c478bd9Sstevel@tonic-gate break;
3577c478bd9Sstevel@tonic-gate default:
3587c478bd9Sstevel@tonic-gate rc = EPROTONOSUPPORT;
3597c478bd9Sstevel@tonic-gate break;
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate if (rc)
3637c478bd9Sstevel@tonic-gate goto errout;
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate switch (proto) {
3667c478bd9Sstevel@tonic-gate case IPPROTO_TCP:
3677c478bd9Sstevel@tonic-gate dl_cf = &dl_tcp_netconf;
3687c478bd9Sstevel@tonic-gate break;
3697c478bd9Sstevel@tonic-gate case IPPROTO_UDP:
3707c478bd9Sstevel@tonic-gate default:
3717c478bd9Sstevel@tonic-gate dl_cf = &dl_udp_netconf;
3727c478bd9Sstevel@tonic-gate break;
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate rc = init_mountopts(args, version, &dl_cf, vfsflags);
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate * Copy knetconfig information from the template, note that the
3797c478bd9Sstevel@tonic-gate * rdev field has been set by init_config above.
3807c478bd9Sstevel@tonic-gate */
3817c478bd9Sstevel@tonic-gate args->knconf->knc_semantics = dl_cf->knc_semantics;
3827c478bd9Sstevel@tonic-gate args->knconf->knc_rdev = dl_cf->knc_rdev;
3837c478bd9Sstevel@tonic-gate (void) strcpy(args->knconf->knc_protofmly, dl_cf->knc_protofmly);
3847c478bd9Sstevel@tonic-gate (void) strcpy(args->knconf->knc_proto, dl_cf->knc_proto);
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate errout:
3877c478bd9Sstevel@tonic-gate if (dldebug) {
3887c478bd9Sstevel@tonic-gate if (rc)
3897c478bd9Sstevel@tonic-gate nfs_perror(rc, "mount_root: mount %s:%s failed: %m\n",
3907c478bd9Sstevel@tonic-gate args->hostname, path);
3917c478bd9Sstevel@tonic-gate else
3927c478bd9Sstevel@tonic-gate printf("mount_root: leaving\n");
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate return (rc);
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate /*
3997c478bd9Sstevel@tonic-gate * Call mount daemon on server `sa' to mount path.
4007c478bd9Sstevel@tonic-gate * `port' is set to nfs port and fh is the fhandle
4017c478bd9Sstevel@tonic-gate * returned from the server.
4027c478bd9Sstevel@tonic-gate */
4037c478bd9Sstevel@tonic-gate static int
mountnfs(struct netbuf * sa,char * server,char * path,fhandle_t * fh,int * proto)4047c478bd9Sstevel@tonic-gate mountnfs(struct netbuf *sa, char *server,
405f3de0dd9SToomas Soome char *path, fhandle_t *fh, int *proto)
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate struct fhstatus fhs;
4087c478bd9Sstevel@tonic-gate enum clnt_stat stat;
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate if (dldebug)
4117c478bd9Sstevel@tonic-gate printf("mountnfs: entered\n");
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate /*
4147c478bd9Sstevel@tonic-gate * Get the port number for the mount program.
4157c478bd9Sstevel@tonic-gate * pmap_kgetport first tries a SunOS portmapper
4167c478bd9Sstevel@tonic-gate * and, if no reply is received, will try a
4177c478bd9Sstevel@tonic-gate * SVR4 rpcbind. Either way, `sa' is set to
4187c478bd9Sstevel@tonic-gate * the correct address.
4197c478bd9Sstevel@tonic-gate */
4207c478bd9Sstevel@tonic-gate do {
4217c478bd9Sstevel@tonic-gate stat = pmap_kgetport(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG,
4227c478bd9Sstevel@tonic-gate (rpcvers_t)MOUNTVERS, (rpcprot_t)IPPROTO_UDP);
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate if (stat == RPC_TIMEDOUT) {
4257c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
4267c478bd9Sstevel@tonic-gate "mountnfs: %s:%s portmap not responding",
4277c478bd9Sstevel@tonic-gate server, path);
4287c478bd9Sstevel@tonic-gate } else if (stat != RPC_SUCCESS) {
4297c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
4307c478bd9Sstevel@tonic-gate "mountnfs: pmap_kgetport RPC error %d (%s).",
4317c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat));
4327c478bd9Sstevel@tonic-gate return (ENXIO); /* XXX */
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT);
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate /*
4377c478bd9Sstevel@tonic-gate * The correct port number has been
4387c478bd9Sstevel@tonic-gate * put into `sa' by pmap_kgetport().
4397c478bd9Sstevel@tonic-gate */
4407c478bd9Sstevel@tonic-gate do {
4417c478bd9Sstevel@tonic-gate stat = mycallrpc(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG,
4427c478bd9Sstevel@tonic-gate (rpcvers_t)MOUNTVERS, (rpcproc_t)MOUNTPROC_MNT,
4437c478bd9Sstevel@tonic-gate xdr_bp_path_t, (char *)&path,
4447c478bd9Sstevel@tonic-gate myxdr_fhstatus, (char *)&fhs,
4457c478bd9Sstevel@tonic-gate DEFAULT_TIMEO, DEFAULT_RETRIES);
4467c478bd9Sstevel@tonic-gate if (stat == RPC_TIMEDOUT) {
4477c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
4487c478bd9Sstevel@tonic-gate "mountnfs: %s:%s mount server not responding",
4497c478bd9Sstevel@tonic-gate server, path);
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT);
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) {
4547c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "mountnfs: RPC failed: error %d (%s).",
4557c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat));
4567c478bd9Sstevel@tonic-gate return (ENXIO); /* XXX */
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)sa->buf)->sin_port = htons(NFS_PORT);
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate *fh = fhs.fhs_fh;
4627c478bd9Sstevel@tonic-gate if (fhs.fhs_status != 0) {
4637c478bd9Sstevel@tonic-gate if (dldebug)
4647c478bd9Sstevel@tonic-gate printf("mountnfs: fhs_status %d\n", fhs.fhs_status);
4657c478bd9Sstevel@tonic-gate return (ENXIO); /* XXX */
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate *proto = IPPROTO_UDP;
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate if (ping_prog(sa, NFS_PROGRAM, NFS_VERSION, IPPROTO_TCP, NULL))
4717c478bd9Sstevel@tonic-gate *proto = IPPROTO_TCP;
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate if (dldebug)
4747c478bd9Sstevel@tonic-gate printf("mountnfs: leaving\n");
4757c478bd9Sstevel@tonic-gate return (0);
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate /*
4797c478bd9Sstevel@tonic-gate * Call mount daemon on server `sa' to mount path.
4807c478bd9Sstevel@tonic-gate * `port' is set to nfs port and fh is the fhandle
4817c478bd9Sstevel@tonic-gate * returned from the server.
4827c478bd9Sstevel@tonic-gate */
4837c478bd9Sstevel@tonic-gate static int
mountnfs3(struct netbuf * sa,char * server,char * path,nfs_fh3 * fh,int * proto)4847c478bd9Sstevel@tonic-gate mountnfs3(struct netbuf *sa, char *server,
485f3de0dd9SToomas Soome char *path, nfs_fh3 *fh, int *proto)
4867c478bd9Sstevel@tonic-gate {
4877c478bd9Sstevel@tonic-gate struct mountres3 mountres3;
4887c478bd9Sstevel@tonic-gate enum clnt_stat stat;
4897c478bd9Sstevel@tonic-gate int ret = 0;
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate if (dldebug)
4927c478bd9Sstevel@tonic-gate printf("mountnfs3: entered\n");
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate /*
4957c478bd9Sstevel@tonic-gate * Get the port number for the mount program.
4967c478bd9Sstevel@tonic-gate * pmap_kgetport first tries a SunOS portmapper
4977c478bd9Sstevel@tonic-gate * and, if no reply is received, will try a
4987c478bd9Sstevel@tonic-gate * SVR4 rpcbind. Either way, `sa' is set to
4997c478bd9Sstevel@tonic-gate * the correct address.
5007c478bd9Sstevel@tonic-gate */
5017c478bd9Sstevel@tonic-gate do {
5027c478bd9Sstevel@tonic-gate stat = pmap_kgetport(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG,
5037c478bd9Sstevel@tonic-gate (rpcvers_t)MOUNTVERS3, (rpcprot_t)IPPROTO_UDP);
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate if (stat == RPC_PROGVERSMISMATCH) {
5067c478bd9Sstevel@tonic-gate if (dldebug)
5077c478bd9Sstevel@tonic-gate printf("mountnfs3: program/version mismatch\n");
5087c478bd9Sstevel@tonic-gate return (EPROTONOSUPPORT); /* XXX */
5097c478bd9Sstevel@tonic-gate } else if (stat == RPC_TIMEDOUT) {
5107c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
5117c478bd9Sstevel@tonic-gate "mountnfs3: %s:%s portmap not responding",
5127c478bd9Sstevel@tonic-gate server, path);
5137c478bd9Sstevel@tonic-gate } else if (stat != RPC_SUCCESS) {
5147c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
5157c478bd9Sstevel@tonic-gate "mountnfs3: pmap_kgetport RPC error %d (%s).",
5167c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat));
5177c478bd9Sstevel@tonic-gate return (ENXIO); /* XXX */
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT);
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val = NULL;
5227c478bd9Sstevel@tonic-gate mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val = NULL;
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate /*
5257c478bd9Sstevel@tonic-gate * The correct port number has been
5267c478bd9Sstevel@tonic-gate * put into `sa' by pmap_kgetport().
5277c478bd9Sstevel@tonic-gate */
5287c478bd9Sstevel@tonic-gate do {
5297c478bd9Sstevel@tonic-gate stat = mycallrpc(&dl_udp_netconf, sa, (rpcprog_t)MOUNTPROG,
5307c478bd9Sstevel@tonic-gate (rpcvers_t)MOUNTVERS3, (rpcproc_t)MOUNTPROC_MNT,
5317c478bd9Sstevel@tonic-gate xdr_bp_path_t, (char *)&path,
5327c478bd9Sstevel@tonic-gate myxdr_mountres3, (char *)&mountres3,
5337c478bd9Sstevel@tonic-gate DEFAULT_TIMEO, DEFAULT_RETRIES);
5347c478bd9Sstevel@tonic-gate if (stat == RPC_TIMEDOUT) {
5357c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
5367c478bd9Sstevel@tonic-gate "mountnfs3: %s:%s mount server not responding",
5377c478bd9Sstevel@tonic-gate server, path);
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT);
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate if (stat == RPC_PROGVERSMISMATCH) {
5427c478bd9Sstevel@tonic-gate if (dldebug)
5437c478bd9Sstevel@tonic-gate printf("mountnfs3: program/version mismatch\n");
5447c478bd9Sstevel@tonic-gate ret = EPROTONOSUPPORT;
5457c478bd9Sstevel@tonic-gate goto out;
5467c478bd9Sstevel@tonic-gate }
5477c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) {
5487c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "mountnfs3: RPC failed: error %d (%s).",
5497c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat));
5507c478bd9Sstevel@tonic-gate ret = ENXIO; /* XXX */
5517c478bd9Sstevel@tonic-gate goto out;
5527c478bd9Sstevel@tonic-gate }
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate if (mountres3.fhs_status != MNT_OK) {
5557c478bd9Sstevel@tonic-gate if (dldebug)
5567c478bd9Sstevel@tonic-gate printf("mountnfs3: fhs_status %d\n",
557843e1988Sjohnlev mountres3.fhs_status);
5587c478bd9Sstevel@tonic-gate ret = ENXIO; /* XXX */
5597c478bd9Sstevel@tonic-gate goto out;
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)sa->buf)->sin_port = htons(NFS_PORT);
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate *proto = IPPROTO_UDP;
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate if (ping_prog(sa, NFS_PROGRAM, NFS_V3, IPPROTO_TCP, NULL)) {
5677c478bd9Sstevel@tonic-gate *proto = IPPROTO_TCP;
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate fh->fh3_length = mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len;
5717c478bd9Sstevel@tonic-gate bcopy(mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val,
5727c478bd9Sstevel@tonic-gate fh->fh3_u.data, fh->fh3_length);
5737c478bd9Sstevel@tonic-gate
5747c478bd9Sstevel@tonic-gate out:
5757c478bd9Sstevel@tonic-gate xdr_free(myxdr_mountres3, (caddr_t)&mountres3);
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate if (dldebug)
5787c478bd9Sstevel@tonic-gate printf("mountnfs3: leaving\n");
5797c478bd9Sstevel@tonic-gate return (ret);
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate static int
ping_prog(struct netbuf * call_addr,uint_t prog,uint_t vers,int proto,enum clnt_stat * statp)5837c478bd9Sstevel@tonic-gate ping_prog(struct netbuf *call_addr, uint_t prog, uint_t vers, int proto,
584f3de0dd9SToomas Soome enum clnt_stat *statp)
5857c478bd9Sstevel@tonic-gate {
5867c478bd9Sstevel@tonic-gate struct knetconfig *knconf;
5877c478bd9Sstevel@tonic-gate enum clnt_stat stat;
5887c478bd9Sstevel@tonic-gate int retries = DEFAULT_RETRIES;
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate switch (proto) {
5917c478bd9Sstevel@tonic-gate case IPPROTO_TCP:
5927c478bd9Sstevel@tonic-gate knconf = &dl_tcp_netconf;
5937c478bd9Sstevel@tonic-gate break;
5947c478bd9Sstevel@tonic-gate case IPPROTO_UDP:
5957c478bd9Sstevel@tonic-gate knconf = &dl_udp_netconf;
5967c478bd9Sstevel@tonic-gate break;
5977c478bd9Sstevel@tonic-gate default:
5987c478bd9Sstevel@tonic-gate return (0);
5997c478bd9Sstevel@tonic-gate }
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate do {
6027c478bd9Sstevel@tonic-gate stat = mycallrpc(knconf, call_addr, prog, vers, NULLPROC,
6037c478bd9Sstevel@tonic-gate xdr_void, NULL, xdr_void, NULL,
6047c478bd9Sstevel@tonic-gate DEFAULT_TIMEO, DEFAULT_RETRIES);
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate if (dldebug)
6077c478bd9Sstevel@tonic-gate printf("ping_prog: %d return %d (%s)\n", proto, stat,
6087c478bd9Sstevel@tonic-gate clnt_sperrno(stat));
6097c478bd9Sstevel@tonic-gate /*
6107c478bd9Sstevel@tonic-gate * Special case for TCP, it may "timeout" because it failed
6117c478bd9Sstevel@tonic-gate * to establish an initial connection but it doesn't
6127c478bd9Sstevel@tonic-gate * actually retry, so we do the retry.
6137c478bd9Sstevel@tonic-gate * Persistence pays in diskless.
6147c478bd9Sstevel@tonic-gate */
6157c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT && proto == IPPROTO_TCP && retries--);
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate if (statp != NULL)
6187c478bd9Sstevel@tonic-gate *statp = stat;
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS)
6217c478bd9Sstevel@tonic-gate return (0);
6227c478bd9Sstevel@tonic-gate return (1);
6237c478bd9Sstevel@tonic-gate }
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate static struct netbuf bootparam_addr;
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate /*
6287c478bd9Sstevel@tonic-gate * Returns after filling in the following global variables:
6297c478bd9Sstevel@tonic-gate * bootparam_addr,
6307c478bd9Sstevel@tonic-gate * utsname.nodename,
6317c478bd9Sstevel@tonic-gate * srpc_domain.
6327c478bd9Sstevel@tonic-gate */
6337c478bd9Sstevel@tonic-gate static int
whoami(void)6347c478bd9Sstevel@tonic-gate whoami(void)
6357c478bd9Sstevel@tonic-gate {
636cc2b7f04Sdduvall TIUSER *tiptr;
637cc2b7f04Sdduvall struct netbuf sa;
638cc2b7f04Sdduvall struct netbuf req;
639cc2b7f04Sdduvall struct bp_whoami_arg arg;
640cc2b7f04Sdduvall struct bp_whoami_res res;
641cc2b7f04Sdduvall struct timeval tv;
642cc2b7f04Sdduvall enum clnt_stat stat;
643cc2b7f04Sdduvall int rc;
644cc2b7f04Sdduvall size_t namelen;
645cc2b7f04Sdduvall int printed_waiting_msg;
646cc2b7f04Sdduvall
647cc2b7f04Sdduvall if ((rc = t_kopen((file_t *)NULL, dl_udp_netconf.knc_rdev,
648cc2b7f04Sdduvall FREAD|FWRITE, &tiptr, CRED())) != 0) {
6497c478bd9Sstevel@tonic-gate nfs_perror(rc, "whoami: t_kopen udp failed: %m.\n");
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate
6527c478bd9Sstevel@tonic-gate /*
6537c478bd9Sstevel@tonic-gate * Find out our local (IP) address.
6547c478bd9Sstevel@tonic-gate */
6557c478bd9Sstevel@tonic-gate if (rc = revarp_myaddr(tiptr)) {
6567c478bd9Sstevel@tonic-gate nfs_perror(rc, "whoami: revarp_myaddr failed: %m.\n");
6577c478bd9Sstevel@tonic-gate (void) t_kclose(tiptr, 0);
6587c478bd9Sstevel@tonic-gate return (rc);
6597c478bd9Sstevel@tonic-gate }
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate /* explicitly use the limited broadcast address */
6627c478bd9Sstevel@tonic-gate init_netbuf(&sa);
6637c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)sa.buf)->sin_family = AF_INET;
6647c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)sa.buf)->sin_addr.s_addr =
6657c478bd9Sstevel@tonic-gate htonl(INADDR_BROADCAST);
6667c478bd9Sstevel@tonic-gate sa.len = sizeof (struct sockaddr_in);
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate /*
6697c478bd9Sstevel@tonic-gate * Pick up our local (IP) address.
6707c478bd9Sstevel@tonic-gate */
6717c478bd9Sstevel@tonic-gate init_netbuf(&req);
6727c478bd9Sstevel@tonic-gate if (rc = ifioctl(tiptr, SIOCGIFADDR, &req)) {
6737c478bd9Sstevel@tonic-gate nfs_perror(rc,
6747c478bd9Sstevel@tonic-gate "whoami: couldn't get my IP address: %m.\n");
6757c478bd9Sstevel@tonic-gate free_netbuf(&sa);
6767c478bd9Sstevel@tonic-gate free_netbuf(&req);
6777c478bd9Sstevel@tonic-gate (void) t_kclose(tiptr, 0);
6787c478bd9Sstevel@tonic-gate return (rc);
6797c478bd9Sstevel@tonic-gate }
680cc2b7f04Sdduvall
6817c478bd9Sstevel@tonic-gate /*
6827c478bd9Sstevel@tonic-gate * Set up the arguments expected by bootparamd.
6837c478bd9Sstevel@tonic-gate */
6847c478bd9Sstevel@tonic-gate arg.client_address.address_type = IP_ADDR_TYPE;
6857c478bd9Sstevel@tonic-gate bcopy(&((struct sockaddr_in *)req.buf)->sin_addr,
6867c478bd9Sstevel@tonic-gate &arg.client_address.bp_address.ip_addr, sizeof (struct in_addr));
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate free_netbuf(&req);
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate init_netbuf(&bootparam_addr);
6917c478bd9Sstevel@tonic-gate
6927c478bd9Sstevel@tonic-gate /*
6937c478bd9Sstevel@tonic-gate * Initial retransmission interval
6947c478bd9Sstevel@tonic-gate */
6957c478bd9Sstevel@tonic-gate tv.tv_sec = DEFAULT_TIMEO;
6967c478bd9Sstevel@tonic-gate tv.tv_usec = 0;
6977c478bd9Sstevel@tonic-gate res.client_name = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP);
6987c478bd9Sstevel@tonic-gate res.domain_name = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP);
6997c478bd9Sstevel@tonic-gate
7007c478bd9Sstevel@tonic-gate /*
7017c478bd9Sstevel@tonic-gate * Do a broadcast call to find a bootparam daemon that
7027c478bd9Sstevel@tonic-gate * will tell us our hostname, domainname and any
7037c478bd9Sstevel@tonic-gate * router that we have to use to talk to our NFS server.
7047c478bd9Sstevel@tonic-gate */
7057c478bd9Sstevel@tonic-gate printed_waiting_msg = 0;
7067c478bd9Sstevel@tonic-gate do {
7077c478bd9Sstevel@tonic-gate /*
7087c478bd9Sstevel@tonic-gate * pmap_rmt_call will first try the SunOS portmapper
7097c478bd9Sstevel@tonic-gate * and if no reply is received will then try the SVR4
7107c478bd9Sstevel@tonic-gate * rpcbind.
7117c478bd9Sstevel@tonic-gate * Either way, `bootparam_addr' will be set to the
7127c478bd9Sstevel@tonic-gate * correct address for the bootparamd that responds.
7137c478bd9Sstevel@tonic-gate */
7147c478bd9Sstevel@tonic-gate stat = pmap_rmt_call(&dl_udp_netconf, &sa, TRUE, BOOTPARAMPROG,
7157c478bd9Sstevel@tonic-gate BOOTPARAMVERS, BOOTPARAMPROC_WHOAMI,
7167c478bd9Sstevel@tonic-gate xdr_bp_whoami_arg, (caddr_t)&arg,
7177c478bd9Sstevel@tonic-gate xdr_bp_whoami_res, (caddr_t)&res,
7187c478bd9Sstevel@tonic-gate tv, &bootparam_addr);
7197c478bd9Sstevel@tonic-gate if (stat == RPC_TIMEDOUT && !printed_waiting_msg) {
7207c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
7217c478bd9Sstevel@tonic-gate "No bootparam server responding; still trying");
7227c478bd9Sstevel@tonic-gate printed_waiting_msg = 1;
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate /*
7257c478bd9Sstevel@tonic-gate * Retransmission interval for second and subsequent tries.
7267c478bd9Sstevel@tonic-gate * We expect first pmap_rmt_call to retransmit and backoff to
7277c478bd9Sstevel@tonic-gate * at least this value.
7287c478bd9Sstevel@tonic-gate */
7297c478bd9Sstevel@tonic-gate tv.tv_sec = WHOAMI_TIMEO;
7307c478bd9Sstevel@tonic-gate tv.tv_usec = 0;
7317c478bd9Sstevel@tonic-gate } while (stat == RPC_TIMEDOUT);
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate if (printed_waiting_msg)
7347c478bd9Sstevel@tonic-gate printf("Bootparam response received\n");
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) {
7377c478bd9Sstevel@tonic-gate /* XXX should get real error here */
7387c478bd9Sstevel@tonic-gate rc = ENXIO;
7397c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
7407c478bd9Sstevel@tonic-gate "whoami: bootparam RPC failed: error %d (%s).",
7417c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat));
7427c478bd9Sstevel@tonic-gate goto done;
7437c478bd9Sstevel@tonic-gate }
744cc2b7f04Sdduvall
7457c478bd9Sstevel@tonic-gate namelen = strlen(res.client_name);
7467c478bd9Sstevel@tonic-gate if (namelen > sizeof (utsname.nodename)) {
7477c478bd9Sstevel@tonic-gate printf("whoami: hostname too long");
7487c478bd9Sstevel@tonic-gate rc = ENAMETOOLONG;
7497c478bd9Sstevel@tonic-gate goto done;
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate if (namelen != 0) {
7527c478bd9Sstevel@tonic-gate bcopy(res.client_name, &utsname.nodename, namelen);
7537c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?hostname: %s\n", utsname.nodename);
7547c478bd9Sstevel@tonic-gate } else {
7557c478bd9Sstevel@tonic-gate printf("whoami: no host name\n");
7567c478bd9Sstevel@tonic-gate rc = ENXIO;
7577c478bd9Sstevel@tonic-gate goto done;
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate namelen = strlen(res.domain_name);
7617c478bd9Sstevel@tonic-gate if (namelen != 0) {
7627c478bd9Sstevel@tonic-gate if (namelen > SYS_NMLN) {
7637c478bd9Sstevel@tonic-gate printf("whoami: domainname too long");
7647c478bd9Sstevel@tonic-gate rc = ENAMETOOLONG;
7657c478bd9Sstevel@tonic-gate goto done;
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate bcopy(res.domain_name, &srpc_domain, namelen);
7687c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?domainname: %s\n", srpc_domain);
7697c478bd9Sstevel@tonic-gate } else {
7707c478bd9Sstevel@tonic-gate printf("whoami: no domain name\n");
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate
7737c478bd9Sstevel@tonic-gate if (res.router_address.address_type == IP_ADDR_TYPE) {
7747c478bd9Sstevel@tonic-gate struct rtentry rtentry;
7757c478bd9Sstevel@tonic-gate struct sockaddr_in *sin;
776cc2b7f04Sdduvall struct in_addr ipaddr;
7777c478bd9Sstevel@tonic-gate
7787c478bd9Sstevel@tonic-gate bcopy(&res.router_address.bp_address.ip_addr, &ipaddr,
779cc2b7f04Sdduvall sizeof (struct in_addr));
7807c478bd9Sstevel@tonic-gate
781cc2b7f04Sdduvall if (ipaddr.s_addr != (uint32_t)0) {
7827c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&rtentry.rt_dst;
7837c478bd9Sstevel@tonic-gate bzero(sin, sizeof (*sin));
7847c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET;
785cc2b7f04Sdduvall
7867c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&rtentry.rt_gateway;
7877c478bd9Sstevel@tonic-gate bzero(sin, sizeof (*sin));
7887c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET;
789cc2b7f04Sdduvall sin->sin_addr.s_addr = ipaddr.s_addr;
790cc2b7f04Sdduvall
7917c478bd9Sstevel@tonic-gate rtentry.rt_flags = RTF_GATEWAY | RTF_UP;
792cc2b7f04Sdduvall
7937c478bd9Sstevel@tonic-gate if (rc = rtioctl(tiptr, SIOCADDRT, &rtentry)) {
7947c478bd9Sstevel@tonic-gate nfs_perror(rc,
7957c478bd9Sstevel@tonic-gate "whoami: couldn't add route: %m.\n");
7967c478bd9Sstevel@tonic-gate goto done;
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate } else {
8007c478bd9Sstevel@tonic-gate printf("whoami: unknown gateway addr family %d\n",
8017c478bd9Sstevel@tonic-gate res.router_address.address_type);
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate done:
8047c478bd9Sstevel@tonic-gate kmem_free(res.client_name, MAX_MACHINE_NAME + 1);
8057c478bd9Sstevel@tonic-gate kmem_free(res.domain_name, MAX_MACHINE_NAME + 1);
8067c478bd9Sstevel@tonic-gate free_netbuf(&sa);
8077c478bd9Sstevel@tonic-gate (void) t_kclose(tiptr, 0);
8087c478bd9Sstevel@tonic-gate return (rc);
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gate /*
8127c478bd9Sstevel@tonic-gate * Returns:
8137c478bd9Sstevel@tonic-gate * 1) The ascii form of our root servers name in `server_name'.
8147c478bd9Sstevel@tonic-gate * 2) Actual network address of our root server in `server_address'.
8157c478bd9Sstevel@tonic-gate * 3) Whatever BOOTPARAMPROC_GETFILE returns for the fileid key, in
8167c478bd9Sstevel@tonic-gate * `server_path'. If fileid is "root", it is the pathname of our
8177c478bd9Sstevel@tonic-gate * root on the server.
8187c478bd9Sstevel@tonic-gate */
8197c478bd9Sstevel@tonic-gate static int
getfile(char * fileid,char * server_name,struct netbuf * server_address,char * server_path)8207c478bd9Sstevel@tonic-gate getfile(char *fileid,
821f3de0dd9SToomas Soome char *server_name, struct netbuf *server_address, char *server_path)
8227c478bd9Sstevel@tonic-gate {
8237c478bd9Sstevel@tonic-gate struct bp_getfile_arg arg;
8247c478bd9Sstevel@tonic-gate struct bp_getfile_res res;
8257c478bd9Sstevel@tonic-gate enum clnt_stat stat;
8267c478bd9Sstevel@tonic-gate int root = FALSE;
8277c478bd9Sstevel@tonic-gate static int using_cache = FALSE;
828cc2b7f04Sdduvall struct in_addr ipaddr;
8297c478bd9Sstevel@tonic-gate int timeo = DEFAULT_TIMEO;
8307c478bd9Sstevel@tonic-gate int retries = DEFAULT_RETRIES;
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate if (dldebug)
8337c478bd9Sstevel@tonic-gate printf("getfile: entered\n");
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate /*
8367c478bd9Sstevel@tonic-gate * Call cacheinfo() to see whether we can satisfy this request by using
8377c478bd9Sstevel@tonic-gate * the information cached in memory by the boot program's DHCP
8387c478bd9Sstevel@tonic-gate * implementation or boot properties rather than consult BOOTPARAMS,
8397c478bd9Sstevel@tonic-gate * but while preserving the semantics of getfile(). We know that
8407c478bd9Sstevel@tonic-gate * the server name is SYS_NMLN in length, and server_path is
8417c478bd9Sstevel@tonic-gate * MAXPATHLEN (pn_alloc).
8427c478bd9Sstevel@tonic-gate */
8437c478bd9Sstevel@tonic-gate if (strcmp(fileid, "root") == 0) {
8447c478bd9Sstevel@tonic-gate if (cacheinfo(server_name, SYS_NMLN, server_address,
8457c478bd9Sstevel@tonic-gate server_path, MAXPATHLEN) == 0) {
8467c478bd9Sstevel@tonic-gate using_cache = TRUE;
8477c478bd9Sstevel@tonic-gate return (0);
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate root = TRUE;
8507c478bd9Sstevel@tonic-gate }
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate /*
8537c478bd9Sstevel@tonic-gate * If using cache, rootopts is already available.
8547c478bd9Sstevel@tonic-gate */
8557c478bd9Sstevel@tonic-gate if (strcmp(fileid, "rootopts") == 0 && using_cache == TRUE) {
8567c478bd9Sstevel@tonic-gate return (rootopts[0] != 0 ? 0 : ENXIO);
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate if (bootparam_addr.len == 0) {
8607c478bd9Sstevel@tonic-gate return (ENXIO);
8617c478bd9Sstevel@tonic-gate }
8627c478bd9Sstevel@tonic-gate arg.client_name = (caddr_t)&utsname.nodename;
8637c478bd9Sstevel@tonic-gate arg.file_id = fileid;
8647c478bd9Sstevel@tonic-gate
8657c478bd9Sstevel@tonic-gate bzero(&res, sizeof (res));
8667c478bd9Sstevel@tonic-gate res.server_name = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP);
8677c478bd9Sstevel@tonic-gate res.server_path = kmem_alloc(MAX_MACHINE_NAME + 1, KM_SLEEP);
8687c478bd9Sstevel@tonic-gate
8697c478bd9Sstevel@tonic-gate /*
8707c478bd9Sstevel@tonic-gate * If we are not looking up the root file, we are looking
8717c478bd9Sstevel@tonic-gate * up a non-critical option that should timeout quickly.
8727c478bd9Sstevel@tonic-gate */
8737c478bd9Sstevel@tonic-gate if (!root) {
8747c478bd9Sstevel@tonic-gate timeo = GETFILE_TIMEO;
8757c478bd9Sstevel@tonic-gate retries = GETFILE_RETRIES;
8767c478bd9Sstevel@tonic-gate }
8777c478bd9Sstevel@tonic-gate
8787c478bd9Sstevel@tonic-gate /*
8797c478bd9Sstevel@tonic-gate * bootparam_addr was filled in by the call to
8807c478bd9Sstevel@tonic-gate * whoami(), so now send an rpc message to the
8817c478bd9Sstevel@tonic-gate * bootparam daemon requesting our server information.
8827c478bd9Sstevel@tonic-gate * Use UDP to talk to bootparms.
8837c478bd9Sstevel@tonic-gate */
8847c478bd9Sstevel@tonic-gate stat = mycallrpc(&dl_udp_netconf, &bootparam_addr,
8857c478bd9Sstevel@tonic-gate (rpcprog_t)BOOTPARAMPROG, (rpcvers_t)BOOTPARAMVERS,
8867c478bd9Sstevel@tonic-gate (rpcproc_t)BOOTPARAMPROC_GETFILE,
8877c478bd9Sstevel@tonic-gate xdr_bp_getfile_arg, (caddr_t)&arg,
8887c478bd9Sstevel@tonic-gate xdr_bp_getfile_res, (caddr_t)&res,
8897c478bd9Sstevel@tonic-gate timeo, retries);
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate if (stat == RPC_SUCCESS) {
8927c478bd9Sstevel@tonic-gate (void) strcpy(server_name, res.server_name);
8937c478bd9Sstevel@tonic-gate (void) strcpy(server_path, res.server_path);
8947c478bd9Sstevel@tonic-gate }
8957c478bd9Sstevel@tonic-gate
8967c478bd9Sstevel@tonic-gate kmem_free(res.server_name, MAX_MACHINE_NAME + 1);
8977c478bd9Sstevel@tonic-gate kmem_free(res.server_path, MAX_MACHINE_NAME + 1);
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) {
9007c478bd9Sstevel@tonic-gate if (root)
9017c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "getfile: RPC failed: error %d (%s).",
9027c478bd9Sstevel@tonic-gate stat, clnt_sperrno(stat));
9037c478bd9Sstevel@tonic-gate return ((stat == RPC_TIMEDOUT) ? ETIMEDOUT : ENXIO); /* XXX */
9047c478bd9Sstevel@tonic-gate }
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate if (*server_path == '\0')
9077c478bd9Sstevel@tonic-gate return (EINVAL);
9087c478bd9Sstevel@tonic-gate
9097c478bd9Sstevel@tonic-gate /*
9107c478bd9Sstevel@tonic-gate * If the fileid is "root", we must get back a server name, for
9117c478bd9Sstevel@tonic-gate * other parameters a server name is not required
9127c478bd9Sstevel@tonic-gate */
9137c478bd9Sstevel@tonic-gate if (!root) {
9147c478bd9Sstevel@tonic-gate if (dldebug)
9157c478bd9Sstevel@tonic-gate printf("getfile: leaving: non-root\n");
9167c478bd9Sstevel@tonic-gate return (0);
9177c478bd9Sstevel@tonic-gate }
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate if (*server_name == '\0')
9207c478bd9Sstevel@tonic-gate return (EINVAL);
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate switch (res.server_address.address_type) {
9237c478bd9Sstevel@tonic-gate case IP_ADDR_TYPE:
9247c478bd9Sstevel@tonic-gate /*
9257c478bd9Sstevel@tonic-gate * server_address is where we will get our root
9267c478bd9Sstevel@tonic-gate * from.
9277c478bd9Sstevel@tonic-gate */
9287c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)server_address->buf)->sin_family =
9297c478bd9Sstevel@tonic-gate AF_INET;
9307c478bd9Sstevel@tonic-gate bcopy(&res.server_address.bp_address.ip_addr,
9317c478bd9Sstevel@tonic-gate &ipaddr, sizeof (ipaddr));
932cc2b7f04Sdduvall if (ipaddr.s_addr == 0)
9337c478bd9Sstevel@tonic-gate return (EINVAL);
9347c478bd9Sstevel@tonic-gate
9357c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)server_address->buf)->sin_addr.s_addr =
936cc2b7f04Sdduvall ipaddr.s_addr;
9377c478bd9Sstevel@tonic-gate server_address->len = sizeof (struct sockaddr_in);
9387c478bd9Sstevel@tonic-gate break;
9397c478bd9Sstevel@tonic-gate
9407c478bd9Sstevel@tonic-gate default:
9417c478bd9Sstevel@tonic-gate printf("getfile: unknown address type %d\n",
9427c478bd9Sstevel@tonic-gate res.server_address.address_type);
9437c478bd9Sstevel@tonic-gate return (EPROTONOSUPPORT);
9447c478bd9Sstevel@tonic-gate }
9457c478bd9Sstevel@tonic-gate if (dldebug)
9467c478bd9Sstevel@tonic-gate printf("getfile: leaving\n");
9477c478bd9Sstevel@tonic-gate return (0);
9487c478bd9Sstevel@tonic-gate }
9497c478bd9Sstevel@tonic-gate
9507c478bd9Sstevel@tonic-gate /*
951986fd29aSsetje * If the boot property "bootp-response" exists, then OBP performed a
9527c478bd9Sstevel@tonic-gate * successful DHCP lease acquisition for us and left the resultant ACK packet
9537c478bd9Sstevel@tonic-gate * encoded at that location.
9547c478bd9Sstevel@tonic-gate *
9557c478bd9Sstevel@tonic-gate * If no such property exists (or the information is incomplete or garbled),
9567c478bd9Sstevel@tonic-gate * the function returns -1.
9577c478bd9Sstevel@tonic-gate */
9587c478bd9Sstevel@tonic-gate int
dhcpinit(void)9597c478bd9Sstevel@tonic-gate dhcpinit(void)
9607c478bd9Sstevel@tonic-gate {
9617c478bd9Sstevel@tonic-gate int rc, i;
9627c478bd9Sstevel@tonic-gate char *p;
9637c478bd9Sstevel@tonic-gate struct in_addr braddr;
9647c478bd9Sstevel@tonic-gate struct in_addr subnet;
9657c478bd9Sstevel@tonic-gate DHCP_OPT *doptp;
9667c478bd9Sstevel@tonic-gate TIUSER *tiptr;
9677c478bd9Sstevel@tonic-gate struct sockaddr_in *sin;
9687c478bd9Sstevel@tonic-gate static int once_only = 0;
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate if (once_only == 1) {
9717c478bd9Sstevel@tonic-gate return (0);
9727c478bd9Sstevel@tonic-gate }
9737c478bd9Sstevel@tonic-gate once_only = 1;
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate if (dhcack == NULL) {
9767c478bd9Sstevel@tonic-gate return (-1);
9777c478bd9Sstevel@tonic-gate }
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate if (dldebug) {
9807c478bd9Sstevel@tonic-gate printf("dhcp: dhcack %p, len %d\n", (void *)dhcack,
981986fd29aSsetje dhcacklen);
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate
9847c478bd9Sstevel@tonic-gate pl = kmem_alloc(sizeof (PKT_LIST), KM_SLEEP);
985986fd29aSsetje pl->len = dhcacklen;
9867c478bd9Sstevel@tonic-gate pl->pkt = kmem_alloc(pl->len, KM_SLEEP);
987986fd29aSsetje bcopy(dhcack, pl->pkt, dhcacklen);
9887c478bd9Sstevel@tonic-gate
9897c478bd9Sstevel@tonic-gate /*
990986fd29aSsetje * For x86, ifname is not initialized
9917c478bd9Sstevel@tonic-gate * in the netinstall case and dhcack interface name is
9927c478bd9Sstevel@tonic-gate * set in strplumb(). So we only copy the name if ifname
9937c478bd9Sstevel@tonic-gate * is set properly.
9947c478bd9Sstevel@tonic-gate */
9957c478bd9Sstevel@tonic-gate if (ifname[0])
996986fd29aSsetje (void) strlcpy(dhcifname, ifname, sizeof (dhcifname));
9977c478bd9Sstevel@tonic-gate
9987c478bd9Sstevel@tonic-gate /* remember the server_ip in dhcack */
9997c478bd9Sstevel@tonic-gate bcopy((uchar_t *)pl->pkt + 20, dhcp_server_ip, 4);
10007c478bd9Sstevel@tonic-gate bzero(pl->opts, (DHCP_LAST_OPT + 1) * sizeof (DHCP_OPT *));
10017c478bd9Sstevel@tonic-gate bzero(pl->vs, (VS_OPTION_END - VS_OPTION_START + 1) *
10027c478bd9Sstevel@tonic-gate sizeof (DHCP_OPT *));
10037c478bd9Sstevel@tonic-gate
10047c478bd9Sstevel@tonic-gate if (dhcp_options_scan(pl, B_TRUE) != 0) {
10057c478bd9Sstevel@tonic-gate /* garbled packet */
10067c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: DHCP packet parsing failed");
10077c478bd9Sstevel@tonic-gate kmem_free(pl->pkt, pl->len);
10087c478bd9Sstevel@tonic-gate kmem_free(pl, sizeof (PKT_LIST));
10097c478bd9Sstevel@tonic-gate pl = NULL;
10107c478bd9Sstevel@tonic-gate return (-1);
10117c478bd9Sstevel@tonic-gate }
10127c478bd9Sstevel@tonic-gate
10137c478bd9Sstevel@tonic-gate /* set node name */
10147c478bd9Sstevel@tonic-gate if (pl->opts[CD_HOSTNAME] != NULL) {
10157c478bd9Sstevel@tonic-gate doptp = pl->opts[CD_HOSTNAME];
10167c478bd9Sstevel@tonic-gate i = doptp->len;
10177c478bd9Sstevel@tonic-gate if (i >= SYS_NMLN) {
10187c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: Hostname is too long");
10197c478bd9Sstevel@tonic-gate } else {
10207c478bd9Sstevel@tonic-gate bcopy(doptp->value, utsname.nodename, i);
10217c478bd9Sstevel@tonic-gate utsname.nodename[i] = '\0';
10227c478bd9Sstevel@tonic-gate if (dldebug) {
10237c478bd9Sstevel@tonic-gate printf("hostname is %s\n",
10247c478bd9Sstevel@tonic-gate utsname.nodename);
10257c478bd9Sstevel@tonic-gate }
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate }
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate /* Set NIS domain name. */
10307c478bd9Sstevel@tonic-gate p = NULL;
10317c478bd9Sstevel@tonic-gate if (pl->opts[CD_NIS_DOMAIN] != NULL) {
10327c478bd9Sstevel@tonic-gate doptp = pl->opts[CD_NIS_DOMAIN];
10337c478bd9Sstevel@tonic-gate i = doptp->len;
10347c478bd9Sstevel@tonic-gate p = (caddr_t)doptp->value;
10357c478bd9Sstevel@tonic-gate }
10367c478bd9Sstevel@tonic-gate if (p != NULL) {
10377c478bd9Sstevel@tonic-gate if (i > SYS_NMLN) {
10387c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
10397c478bd9Sstevel@tonic-gate "dhcp: NIS domainname too long.");
10407c478bd9Sstevel@tonic-gate } else {
10417c478bd9Sstevel@tonic-gate bcopy(p, srpc_domain, i);
10427c478bd9Sstevel@tonic-gate srpc_domain[i] = '\0';
10437c478bd9Sstevel@tonic-gate if (dldebug)
10447c478bd9Sstevel@tonic-gate printf("dhcp: NIS domain name is %s\n",
10457c478bd9Sstevel@tonic-gate srpc_domain);
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate /* fetch netmask */
10507c478bd9Sstevel@tonic-gate if (pl->opts[CD_SUBNETMASK] != NULL) {
10517c478bd9Sstevel@tonic-gate doptp = pl->opts[CD_SUBNETMASK];
10527c478bd9Sstevel@tonic-gate if (doptp->len != sizeof (struct in_addr)) {
10537c478bd9Sstevel@tonic-gate pl->opts[CD_SUBNETMASK] = NULL;
10547c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: netmask option malformed");
10557c478bd9Sstevel@tonic-gate } else {
10567c478bd9Sstevel@tonic-gate bcopy(doptp->value, &subnet, sizeof (struct in_addr));
10577c478bd9Sstevel@tonic-gate if (dldebug)
10587c478bd9Sstevel@tonic-gate printf("dhcp: setting netmask to: %s\n",
10597c478bd9Sstevel@tonic-gate inet_ntoa(subnet));
10607c478bd9Sstevel@tonic-gate }
10617c478bd9Sstevel@tonic-gate } else {
10627c478bd9Sstevel@tonic-gate struct in_addr myIPaddr;
10637c478bd9Sstevel@tonic-gate
10647c478bd9Sstevel@tonic-gate myIPaddr.s_addr = pl->pkt->yiaddr.s_addr;
10657c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: no subnet mask supplied - inferring");
10667c478bd9Sstevel@tonic-gate if (IN_CLASSA(ntohl(myIPaddr.s_addr)))
10677c478bd9Sstevel@tonic-gate subnet.s_addr = htonl(IN_CLASSA_NET);
10687c478bd9Sstevel@tonic-gate else if (IN_CLASSB(ntohl(myIPaddr.s_addr)))
10697c478bd9Sstevel@tonic-gate subnet.s_addr = htonl(IN_CLASSB_NET);
10707c478bd9Sstevel@tonic-gate else if (IN_CLASSC(ntohl(myIPaddr.s_addr)))
10717c478bd9Sstevel@tonic-gate subnet.s_addr = htonl(IN_CLASSC_NET);
10722a9459bdSsangeeta else if (IN_CLASSD(ntohl(myIPaddr.s_addr)))
10737c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "dhcp: bad IP address (%s)",
10747c478bd9Sstevel@tonic-gate inet_ntoa(myIPaddr));
10752a9459bdSsangeeta else
10762a9459bdSsangeeta subnet.s_addr = htonl(IN_CLASSE_NET);
10777c478bd9Sstevel@tonic-gate }
10787c478bd9Sstevel@tonic-gate /* and broadcast address */
10797c478bd9Sstevel@tonic-gate if (pl->opts[CD_BROADCASTADDR] != NULL) {
10807c478bd9Sstevel@tonic-gate doptp = pl->opts[CD_BROADCASTADDR];
10817c478bd9Sstevel@tonic-gate if (doptp->len != sizeof (struct in_addr)) {
10827c478bd9Sstevel@tonic-gate pl->opts[CD_BROADCASTADDR] = NULL;
10837c478bd9Sstevel@tonic-gate if (dldebug)
10847c478bd9Sstevel@tonic-gate printf("dhcp: broadcast address len %d\n",
10857c478bd9Sstevel@tonic-gate doptp->len);
10867c478bd9Sstevel@tonic-gate } else {
10877c478bd9Sstevel@tonic-gate bcopy(doptp->value, &braddr, sizeof (struct in_addr));
10887c478bd9Sstevel@tonic-gate if (dldebug)
10897c478bd9Sstevel@tonic-gate printf("dhcp: setting broadcast addr to: %s\n",
10907c478bd9Sstevel@tonic-gate inet_ntoa(braddr));
10917c478bd9Sstevel@tonic-gate }
10927c478bd9Sstevel@tonic-gate } else {
10937c478bd9Sstevel@tonic-gate if (dldebug)
10947c478bd9Sstevel@tonic-gate printf("dhcp: no broadcast address supplied\n");
10957c478bd9Sstevel@tonic-gate braddr.s_addr = htonl(INADDR_BROADCAST);
10967c478bd9Sstevel@tonic-gate }
10977c478bd9Sstevel@tonic-gate /* and plumb and initialize interface */
10987c478bd9Sstevel@tonic-gate if ((rc = t_kopen((file_t *)NULL, dl_udp_netconf.knc_rdev,
10997c478bd9Sstevel@tonic-gate FREAD|FWRITE, &tiptr, CRED())) == 0) {
11007c478bd9Sstevel@tonic-gate if (rc = dlifconfig(tiptr, &pl->pkt->yiaddr, &subnet,
1101843e1988Sjohnlev &braddr, IFF_DHCPRUNNING)) {
11027c478bd9Sstevel@tonic-gate nfs_perror(