xref: /onnv-gate/usr/src/lib/libwanboot/common/bootinfo_aux.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <stdlib.h>
31*0Sstevel@tonic-gate #include <dhcp_impl.h>
32*0Sstevel@tonic-gate #include <netinet/inetutil.h>
33*0Sstevel@tonic-gate #include <sys/systeminfo.h>
34*0Sstevel@tonic-gate #include <netinet/in.h>
35*0Sstevel@tonic-gate #include <strings.h>
36*0Sstevel@tonic-gate #include <net/if.h>
37*0Sstevel@tonic-gate #include <libdevinfo.h>
38*0Sstevel@tonic-gate #include <sys/isa_defs.h>
39*0Sstevel@tonic-gate #include <unistd.h>
40*0Sstevel@tonic-gate #include <fcntl.h>
41*0Sstevel@tonic-gate #include <netdb.h>
42*0Sstevel@tonic-gate #include <alloca.h>
43*0Sstevel@tonic-gate #include <stdio.h>
44*0Sstevel@tonic-gate #include <sys/sockio.h>
45*0Sstevel@tonic-gate #include <sys/statvfs.h>
46*0Sstevel@tonic-gate #include <sys/utsname.h>
47*0Sstevel@tonic-gate #include <bootinfo.h>
48*0Sstevel@tonic-gate #include <bootinfo_aux.h>
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate #define	MAXIFS	256	/* default max number of interfaces */
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate /*
53*0Sstevel@tonic-gate  * Callback structure used when walking the device tree.
54*0Sstevel@tonic-gate  */
55*0Sstevel@tonic-gate typedef struct {
56*0Sstevel@tonic-gate 	char		*cb_path;	/* device path we want to match */
57*0Sstevel@tonic-gate 	di_node_t	cb_node;	/* found leaf node of device path */
58*0Sstevel@tonic-gate } cb_t;
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate /*
61*0Sstevel@tonic-gate  * Handles on devinfo stuff.
62*0Sstevel@tonic-gate  */
63*0Sstevel@tonic-gate static di_node_t	root_node = DI_NODE_NIL;
64*0Sstevel@tonic-gate static di_prom_handle_t	phdl = DI_PROM_HANDLE_NIL;
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate /*
67*0Sstevel@tonic-gate  * Root filesystem type string.
68*0Sstevel@tonic-gate  */
69*0Sstevel@tonic-gate static char *rootfs_type = NULL;
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate /*
72*0Sstevel@tonic-gate  * Handles on DHCP's packet list and interface-name.
73*0Sstevel@tonic-gate  */
74*0Sstevel@tonic-gate static PKT_LIST	*dhcp_pl = NULL;
75*0Sstevel@tonic-gate static char	dhcp_ifn[IFNAMSIZ + 1];
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate /*
78*0Sstevel@tonic-gate  * Deallocate dhcp_pl.
79*0Sstevel@tonic-gate  */
80*0Sstevel@tonic-gate static void
dhcp_info_end(void)81*0Sstevel@tonic-gate dhcp_info_end(void)
82*0Sstevel@tonic-gate {
83*0Sstevel@tonic-gate 	if (dhcp_pl != NULL) {
84*0Sstevel@tonic-gate 		free(dhcp_pl->pkt);
85*0Sstevel@tonic-gate 		free(dhcp_pl);
86*0Sstevel@tonic-gate 	}
87*0Sstevel@tonic-gate 	dhcp_pl = NULL;
88*0Sstevel@tonic-gate 	dhcp_ifn[0] = '\0';
89*0Sstevel@tonic-gate }
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate /*
92*0Sstevel@tonic-gate  * Determine whether the kernel has a cached DHCP ACK, and if so
93*0Sstevel@tonic-gate  * initialize dhcp_pl and dhcp_ifn.
94*0Sstevel@tonic-gate  */
95*0Sstevel@tonic-gate static boolean_t
dhcp_info_init(void)96*0Sstevel@tonic-gate dhcp_info_init(void)
97*0Sstevel@tonic-gate {
98*0Sstevel@tonic-gate 	boolean_t	ret = B_FALSE;
99*0Sstevel@tonic-gate 	char		dummy;
100*0Sstevel@tonic-gate 	char		*dhcack = NULL;
101*0Sstevel@tonic-gate 	long		dhcacksz;
102*0Sstevel@tonic-gate 	char		*ackp;
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 	/*
105*0Sstevel@tonic-gate 	 * See whether the kernel has a cached DHCP ACK, and if so get it.
106*0Sstevel@tonic-gate 	 * If there is no DHCP ACK, then the returned length is equal to
107*0Sstevel@tonic-gate 	 * the size of an empty string.
108*0Sstevel@tonic-gate 	 */
109*0Sstevel@tonic-gate 	if ((dhcacksz = sysinfo(SI_DHCP_CACHE, &dummy,
110*0Sstevel@tonic-gate 	    sizeof (dummy))) == sizeof ("")) {
111*0Sstevel@tonic-gate 		return (B_TRUE);
112*0Sstevel@tonic-gate 	}
113*0Sstevel@tonic-gate 	if ((dhcack = malloc(dhcacksz)) == NULL) {
114*0Sstevel@tonic-gate 		goto cleanup;
115*0Sstevel@tonic-gate 	}
116*0Sstevel@tonic-gate 	if ((dhcp_pl = calloc(1, sizeof (PKT_LIST))) == NULL) {
117*0Sstevel@tonic-gate 		goto cleanup;
118*0Sstevel@tonic-gate 	}
119*0Sstevel@tonic-gate 	(void) sysinfo(SI_DHCP_CACHE, (caddr_t)dhcack, dhcacksz);
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	/*
122*0Sstevel@tonic-gate 	 * The first IFNAMSIZ bytes are reserved for the interface name;
123*0Sstevel@tonic-gate 	 * the ACK follows.
124*0Sstevel@tonic-gate 	 */
125*0Sstevel@tonic-gate 	ackp = &dhcack[IFNAMSIZ];
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 	/*
128*0Sstevel@tonic-gate 	 * Convert and scan the options.
129*0Sstevel@tonic-gate 	 */
130*0Sstevel@tonic-gate 	dhcp_pl->len = strlen(ackp) / 2;
131*0Sstevel@tonic-gate 	if ((dhcp_pl->pkt = malloc(dhcp_pl->len)) == NULL) {
132*0Sstevel@tonic-gate 		goto cleanup;
133*0Sstevel@tonic-gate 	}
134*0Sstevel@tonic-gate 	if (hexascii_to_octet(ackp, dhcp_pl->len * 2,
135*0Sstevel@tonic-gate 	    dhcp_pl->pkt, &dhcp_pl->len) != 0) {
136*0Sstevel@tonic-gate 		goto cleanup;
137*0Sstevel@tonic-gate 	}
138*0Sstevel@tonic-gate 	if (dhcp_options_scan(dhcp_pl, B_TRUE) != 0) {
139*0Sstevel@tonic-gate 		goto cleanup;
140*0Sstevel@tonic-gate 	}
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	/*
143*0Sstevel@tonic-gate 	 * Set the interface-name.
144*0Sstevel@tonic-gate 	 */
145*0Sstevel@tonic-gate 	(void) strlcpy(dhcp_ifn, dhcack, sizeof (dhcp_ifn));
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate 	ret = B_TRUE;
148*0Sstevel@tonic-gate cleanup:
149*0Sstevel@tonic-gate 	if (!ret) {
150*0Sstevel@tonic-gate 		dhcp_info_end();
151*0Sstevel@tonic-gate 	}
152*0Sstevel@tonic-gate 	if (dhcack != NULL) {
153*0Sstevel@tonic-gate 		free(dhcack);
154*0Sstevel@tonic-gate 	}
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 	return (ret);
157*0Sstevel@tonic-gate }
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate /*
160*0Sstevel@tonic-gate  * Deallocate devinfo stuff.
161*0Sstevel@tonic-gate  */
162*0Sstevel@tonic-gate static void
destroy_snapshot(void)163*0Sstevel@tonic-gate destroy_snapshot(void)
164*0Sstevel@tonic-gate {
165*0Sstevel@tonic-gate 	if (phdl != DI_PROM_HANDLE_NIL) {
166*0Sstevel@tonic-gate 		di_prom_fini(phdl);
167*0Sstevel@tonic-gate 	}
168*0Sstevel@tonic-gate 	phdl = DI_PROM_HANDLE_NIL;
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	if (root_node != DI_NODE_NIL) {
171*0Sstevel@tonic-gate 		di_fini(root_node);
172*0Sstevel@tonic-gate 	}
173*0Sstevel@tonic-gate 	root_node = DI_NODE_NIL;
174*0Sstevel@tonic-gate }
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate /*
177*0Sstevel@tonic-gate  * Take a snapshot of the device tree, i.e. get a devinfo handle and
178*0Sstevel@tonic-gate  * a PROM handle.
179*0Sstevel@tonic-gate  */
180*0Sstevel@tonic-gate static boolean_t
snapshot_devtree(void)181*0Sstevel@tonic-gate snapshot_devtree(void)
182*0Sstevel@tonic-gate {
183*0Sstevel@tonic-gate 	/*
184*0Sstevel@tonic-gate 	 * Deallocate any existing devinfo stuff first.
185*0Sstevel@tonic-gate 	 */
186*0Sstevel@tonic-gate 	destroy_snapshot();
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL ||
189*0Sstevel@tonic-gate 	    (phdl = di_prom_init()) == DI_PROM_HANDLE_NIL) {
190*0Sstevel@tonic-gate 		destroy_snapshot();
191*0Sstevel@tonic-gate 		return (B_FALSE);
192*0Sstevel@tonic-gate 	}
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 	return (B_TRUE);
195*0Sstevel@tonic-gate }
196*0Sstevel@tonic-gate 
197*0Sstevel@tonic-gate /*
198*0Sstevel@tonic-gate  * Get the value of the named property on the named node in root.
199*0Sstevel@tonic-gate  */
200*0Sstevel@tonic-gate static char *
get_prop(const char * nodename,const char * propname,size_t * lenp)201*0Sstevel@tonic-gate get_prop(const char *nodename, const char *propname, size_t *lenp)
202*0Sstevel@tonic-gate {
203*0Sstevel@tonic-gate 	di_node_t		node;
204*0Sstevel@tonic-gate 	di_prom_prop_t		pp;
205*0Sstevel@tonic-gate 	char			*val = NULL;
206*0Sstevel@tonic-gate 	int			len;
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate 	/*
209*0Sstevel@tonic-gate 	 * Locate nodename within '/'.
210*0Sstevel@tonic-gate 	 */
211*0Sstevel@tonic-gate 	for (node = di_child_node(root_node);
212*0Sstevel@tonic-gate 	    node != DI_NODE_NIL;
213*0Sstevel@tonic-gate 	    node = di_sibling_node(node)) {
214*0Sstevel@tonic-gate 		if (strcmp(di_node_name(node), nodename) == 0) {
215*0Sstevel@tonic-gate 			break;
216*0Sstevel@tonic-gate 		}
217*0Sstevel@tonic-gate 	}
218*0Sstevel@tonic-gate 	if (node == DI_NODE_NIL) {
219*0Sstevel@tonic-gate 		return (NULL);
220*0Sstevel@tonic-gate 	}
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate 	/*
223*0Sstevel@tonic-gate 	 * Scan all properties of /nodename for the 'propname' property.
224*0Sstevel@tonic-gate 	 */
225*0Sstevel@tonic-gate 	for (pp = di_prom_prop_next(phdl, node, DI_PROM_PROP_NIL);
226*0Sstevel@tonic-gate 	    pp != DI_PROM_PROP_NIL;
227*0Sstevel@tonic-gate 	    pp = di_prom_prop_next(phdl, node, pp)) {
228*0Sstevel@tonic-gate 		if (strcmp(propname, di_prom_prop_name(pp)) == 0) {
229*0Sstevel@tonic-gate 			break;
230*0Sstevel@tonic-gate 		}
231*0Sstevel@tonic-gate 	}
232*0Sstevel@tonic-gate 	if (pp == DI_PROM_PROP_NIL) {
233*0Sstevel@tonic-gate 		return (NULL);
234*0Sstevel@tonic-gate 	}
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate 	/*
237*0Sstevel@tonic-gate 	 * Found the property; copy out its length and return its value.
238*0Sstevel@tonic-gate 	 */
239*0Sstevel@tonic-gate 	len = di_prom_prop_data(pp, (uchar_t **)&val);
240*0Sstevel@tonic-gate 	if (lenp != NULL) {
241*0Sstevel@tonic-gate 		*lenp = len;
242*0Sstevel@tonic-gate 	}
243*0Sstevel@tonic-gate 	return (val);
244*0Sstevel@tonic-gate }
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate /*
247*0Sstevel@tonic-gate  * Strip any trailing arguments from a device path.
248*0Sstevel@tonic-gate  * Returned memory must be freed by caller.
249*0Sstevel@tonic-gate  */
250*0Sstevel@tonic-gate static char *
strip_args(char * path,size_t len)251*0Sstevel@tonic-gate strip_args(char *path, size_t len)
252*0Sstevel@tonic-gate {
253*0Sstevel@tonic-gate 	char	*stripped_path = NULL;
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate 	if (path != NULL && len != 0 &&
256*0Sstevel@tonic-gate 	    (stripped_path = calloc(len + 1, sizeof (char))) != NULL) {
257*0Sstevel@tonic-gate 		char	*p;
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 		(void) memcpy(stripped_path, path, len);
260*0Sstevel@tonic-gate 		if ((p = strchr(stripped_path, ':')) != NULL) {
261*0Sstevel@tonic-gate 			*p = '\0';
262*0Sstevel@tonic-gate 		}
263*0Sstevel@tonic-gate 	}
264*0Sstevel@tonic-gate 	return (stripped_path);
265*0Sstevel@tonic-gate }
266*0Sstevel@tonic-gate 
267*0Sstevel@tonic-gate /*
268*0Sstevel@tonic-gate  * Return the "bootpath" property (sans arguments) from /chosen.
269*0Sstevel@tonic-gate  * Returned memory must be freed by caller.
270*0Sstevel@tonic-gate  */
271*0Sstevel@tonic-gate static char *
get_bootpath(void)272*0Sstevel@tonic-gate get_bootpath(void)
273*0Sstevel@tonic-gate {
274*0Sstevel@tonic-gate 	char	*path;
275*0Sstevel@tonic-gate 	size_t	len;
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate 	path = get_prop("chosen", "bootpath", &len);
278*0Sstevel@tonic-gate 	return (strip_args(path, len));
279*0Sstevel@tonic-gate }
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate /*
282*0Sstevel@tonic-gate  * Return the "net" property (sans arguments) from /aliases.
283*0Sstevel@tonic-gate  * Returned memory must be freed by caller.
284*0Sstevel@tonic-gate  */
285*0Sstevel@tonic-gate static char *
get_netalias(void)286*0Sstevel@tonic-gate get_netalias(void)
287*0Sstevel@tonic-gate {
288*0Sstevel@tonic-gate 	char	*path;
289*0Sstevel@tonic-gate 	size_t	len;
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 	path = get_prop("aliases", "net", &len);
292*0Sstevel@tonic-gate 	return (strip_args(path, len));
293*0Sstevel@tonic-gate }
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate /*
296*0Sstevel@tonic-gate  * Callback used by path2node().
297*0Sstevel@tonic-gate  */
298*0Sstevel@tonic-gate static int
p2n_cb(di_node_t node,void * arg)299*0Sstevel@tonic-gate p2n_cb(di_node_t node, void *arg)
300*0Sstevel@tonic-gate {
301*0Sstevel@tonic-gate 	int	ret = DI_WALK_CONTINUE;
302*0Sstevel@tonic-gate 	cb_t	*cbp = arg;
303*0Sstevel@tonic-gate 	char	*phys_path = di_devfs_path(node);
304*0Sstevel@tonic-gate 
305*0Sstevel@tonic-gate 	if (strcmp(cbp->cb_path, phys_path) == 0) {
306*0Sstevel@tonic-gate 		cbp->cb_node = node;
307*0Sstevel@tonic-gate 		ret = DI_WALK_TERMINATE;
308*0Sstevel@tonic-gate 	}
309*0Sstevel@tonic-gate 	di_devfs_path_free(phys_path);
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate 	return (ret);
312*0Sstevel@tonic-gate }
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate /*
315*0Sstevel@tonic-gate  * Map a device path to its matching di_node_t.
316*0Sstevel@tonic-gate  */
317*0Sstevel@tonic-gate static di_node_t
path2node(char * path)318*0Sstevel@tonic-gate path2node(char *path)
319*0Sstevel@tonic-gate {
320*0Sstevel@tonic-gate 	cb_t	cb;
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 	cb.cb_path = path;
323*0Sstevel@tonic-gate 	cb.cb_node = DI_NODE_NIL;
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 	(void) di_walk_node(root_node, DI_WALK_CLDFIRST, &cb, p2n_cb);
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate 	return (cb.cb_node);
328*0Sstevel@tonic-gate }
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate /*
331*0Sstevel@tonic-gate  * Check whether node corresponds to a network device.
332*0Sstevel@tonic-gate  */
333*0Sstevel@tonic-gate static boolean_t
is_network_device(di_node_t node)334*0Sstevel@tonic-gate is_network_device(di_node_t node)
335*0Sstevel@tonic-gate {
336*0Sstevel@tonic-gate 	char		*type;
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 	return (di_prom_prop_lookup_strings(phdl, node,
339*0Sstevel@tonic-gate 	    "device_type", &type) > 0 && strcmp(type, "network") == 0);
340*0Sstevel@tonic-gate }
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate /*
343*0Sstevel@tonic-gate  * Initialise bootmisc with the rootfs-type.
344*0Sstevel@tonic-gate  */
345*0Sstevel@tonic-gate static boolean_t
rootfs_type_init(void)346*0Sstevel@tonic-gate rootfs_type_init(void)
347*0Sstevel@tonic-gate {
348*0Sstevel@tonic-gate 	static struct statvfs	vfs;
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate 	if (statvfs("/", &vfs) >= 0) {
351*0Sstevel@tonic-gate 		if (strncmp(vfs.f_basetype, "nfs", sizeof ("nfs") - 1) == 0) {
352*0Sstevel@tonic-gate 			vfs.f_basetype[sizeof ("nfs") - 1] = '\0';
353*0Sstevel@tonic-gate 		}
354*0Sstevel@tonic-gate 		rootfs_type = vfs.f_basetype;
355*0Sstevel@tonic-gate 	}
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate 	return (rootfs_type != NULL && bi_put_bootmisc(BI_ROOTFS_TYPE,
358*0Sstevel@tonic-gate 	    rootfs_type, strlen(rootfs_type) + 1));
359*0Sstevel@tonic-gate }
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate /*
362*0Sstevel@tonic-gate  * Initialise bootmisc with the interface-name of the primary network device,
363*0Sstevel@tonic-gate  * and the net-config-strategy employed in configuring that device.
364*0Sstevel@tonic-gate  */
365*0Sstevel@tonic-gate static boolean_t
netif_init(char * ifn,char * ncs)366*0Sstevel@tonic-gate netif_init(char *ifn, char *ncs)
367*0Sstevel@tonic-gate {
368*0Sstevel@tonic-gate 	return (bi_put_bootmisc(BI_INTERFACE_NAME, ifn, strlen(ifn) + 1) &&
369*0Sstevel@tonic-gate 	    bi_put_bootmisc(BI_NET_CONFIG_STRATEGY, ncs, strlen(ncs) + 1));
370*0Sstevel@tonic-gate }
371*0Sstevel@tonic-gate 
372*0Sstevel@tonic-gate /*
373*0Sstevel@tonic-gate  * Determine whether the interface was configured manually.
374*0Sstevel@tonic-gate  */
375*0Sstevel@tonic-gate static boolean_t
manual_if_init(void)376*0Sstevel@tonic-gate manual_if_init(void)
377*0Sstevel@tonic-gate {
378*0Sstevel@tonic-gate 	boolean_t	ret = B_FALSE;
379*0Sstevel@tonic-gate 	char		*ncs;
380*0Sstevel@tonic-gate 	char		*devpath;
381*0Sstevel@tonic-gate 	di_node_t	node;
382*0Sstevel@tonic-gate 	int		instance;
383*0Sstevel@tonic-gate 	char		*drvname;
384*0Sstevel@tonic-gate 	char		ifname[IFNAMSIZ + 1];
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 	/*
387*0Sstevel@tonic-gate 	 * If net-config-strategy isn't "manual", don't go any further.
388*0Sstevel@tonic-gate 	 */
389*0Sstevel@tonic-gate 	if ((ncs = get_prop("chosen", BI_NET_CONFIG_STRATEGY, NULL)) == NULL ||
390*0Sstevel@tonic-gate 	    strcmp(ncs, "manual") != 0) {
391*0Sstevel@tonic-gate 		return (B_FALSE);
392*0Sstevel@tonic-gate 	}
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 	/*
395*0Sstevel@tonic-gate 	 * First check the 'bootpath' property of /chosen to see whether
396*0Sstevel@tonic-gate 	 * it specifies the path of a network device; if so, use this.
397*0Sstevel@tonic-gate 	 */
398*0Sstevel@tonic-gate 	if ((devpath = get_bootpath()) == NULL ||
399*0Sstevel@tonic-gate 	    (node = path2node(devpath)) == DI_NODE_NIL ||
400*0Sstevel@tonic-gate 	    !is_network_device(node)) {
401*0Sstevel@tonic-gate 		/*
402*0Sstevel@tonic-gate 		 * Must have been booted from CD-ROM or disk; attempt to
403*0Sstevel@tonic-gate 		 * use the path defined by the 'net' property of /aliases.
404*0Sstevel@tonic-gate 		 */
405*0Sstevel@tonic-gate 		free(devpath);
406*0Sstevel@tonic-gate 		if ((devpath = get_netalias()) == NULL ||
407*0Sstevel@tonic-gate 		    (node = path2node(devpath)) == DI_NODE_NIL ||
408*0Sstevel@tonic-gate 		    !is_network_device(node)) {
409*0Sstevel@tonic-gate 			goto cleanup;
410*0Sstevel@tonic-gate 		}
411*0Sstevel@tonic-gate 	}
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate 	/*
414*0Sstevel@tonic-gate 	 * Get the driver name and instance number of this node.
415*0Sstevel@tonic-gate 	 * We may have to load the driver.
416*0Sstevel@tonic-gate 	 */
417*0Sstevel@tonic-gate 	if ((drvname = di_driver_name(node)) == NULL) {
418*0Sstevel@tonic-gate 		goto cleanup;
419*0Sstevel@tonic-gate 	}
420*0Sstevel@tonic-gate 	if ((instance = di_instance(node)) == -1) {
421*0Sstevel@tonic-gate 		di_node_t	tmp;
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate 		/*
424*0Sstevel@tonic-gate 		 * Attempt to load the driver, create a new snapshot of the
425*0Sstevel@tonic-gate 		 * (possibly changed) device tree and re-compute our node.
426*0Sstevel@tonic-gate 		 */
427*0Sstevel@tonic-gate 		if ((tmp = di_init_driver(drvname, 0)) != DI_NODE_NIL) {
428*0Sstevel@tonic-gate 			di_fini(tmp);
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate 			if (!snapshot_devtree() ||
431*0Sstevel@tonic-gate 			    (node = path2node(devpath)) == DI_NODE_NIL) {
432*0Sstevel@tonic-gate 				goto cleanup;
433*0Sstevel@tonic-gate 			}
434*0Sstevel@tonic-gate 		}
435*0Sstevel@tonic-gate 		instance = di_instance(node);
436*0Sstevel@tonic-gate 	}
437*0Sstevel@tonic-gate 
438*0Sstevel@tonic-gate 	/*
439*0Sstevel@tonic-gate 	 * Construct the interface name.
440*0Sstevel@tonic-gate 	 */
441*0Sstevel@tonic-gate 	if (instance == -1) {
442*0Sstevel@tonic-gate 		(void) snprintf(ifname, sizeof (ifname),
443*0Sstevel@tonic-gate 		    "%s", di_driver_name(node));
444*0Sstevel@tonic-gate 	} else {
445*0Sstevel@tonic-gate 		(void) snprintf(ifname, sizeof (ifname),
446*0Sstevel@tonic-gate 		    "%s%d", di_driver_name(node), instance);
447*0Sstevel@tonic-gate 	}
448*0Sstevel@tonic-gate 
449*0Sstevel@tonic-gate 	ret = netif_init(ifname, "manual");
450*0Sstevel@tonic-gate cleanup:
451*0Sstevel@tonic-gate 	free(devpath);
452*0Sstevel@tonic-gate 	return (ret);
453*0Sstevel@tonic-gate }
454*0Sstevel@tonic-gate 
455*0Sstevel@tonic-gate /*
456*0Sstevel@tonic-gate  * Determine whether the interface was configured via DHCP.
457*0Sstevel@tonic-gate  */
458*0Sstevel@tonic-gate static boolean_t
dhcp_if_init(void)459*0Sstevel@tonic-gate dhcp_if_init(void)
460*0Sstevel@tonic-gate {
461*0Sstevel@tonic-gate 	return (strlen(dhcp_ifn) != 0 && netif_init(dhcp_ifn, "dhcp"));
462*0Sstevel@tonic-gate }
463*0Sstevel@tonic-gate 
464*0Sstevel@tonic-gate static boolean_t
bootmisc_init(void)465*0Sstevel@tonic-gate bootmisc_init(void)
466*0Sstevel@tonic-gate {
467*0Sstevel@tonic-gate 	return (rootfs_type_init() &&
468*0Sstevel@tonic-gate 	    (manual_if_init() || dhcp_if_init()));
469*0Sstevel@tonic-gate }
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 
472*0Sstevel@tonic-gate /*
473*0Sstevel@tonic-gate  * Functions dealing with bootinfo initialization/cleanup.
474*0Sstevel@tonic-gate  */
475*0Sstevel@tonic-gate boolean_t
bi_init_bootinfo(void)476*0Sstevel@tonic-gate bi_init_bootinfo(void)
477*0Sstevel@tonic-gate {
478*0Sstevel@tonic-gate 	if (snapshot_devtree() && dhcp_info_init() && bootmisc_init()) {
479*0Sstevel@tonic-gate 		return (B_TRUE);
480*0Sstevel@tonic-gate 	}
481*0Sstevel@tonic-gate 	bi_end_bootinfo();
482*0Sstevel@tonic-gate 	return (B_FALSE);
483*0Sstevel@tonic-gate }
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate void
bi_end_bootinfo(void)486*0Sstevel@tonic-gate bi_end_bootinfo(void)
487*0Sstevel@tonic-gate {
488*0Sstevel@tonic-gate 	destroy_snapshot();
489*0Sstevel@tonic-gate 	dhcp_info_end();
490*0Sstevel@tonic-gate }
491*0Sstevel@tonic-gate 
492*0Sstevel@tonic-gate /*
493*0Sstevel@tonic-gate  * Function dealing with /chosen data.
494*0Sstevel@tonic-gate  */
495*0Sstevel@tonic-gate boolean_t
bi_get_chosen_prop(const char * name,void * valbuf,size_t * vallenp)496*0Sstevel@tonic-gate bi_get_chosen_prop(const char *name, void *valbuf, size_t *vallenp)
497*0Sstevel@tonic-gate {
498*0Sstevel@tonic-gate 	char		*val;
499*0Sstevel@tonic-gate 	size_t		buflen = *vallenp;
500*0Sstevel@tonic-gate 
501*0Sstevel@tonic-gate 	if ((val = get_prop("chosen", name, vallenp)) == NULL) {
502*0Sstevel@tonic-gate 		return (B_FALSE);
503*0Sstevel@tonic-gate 	}
504*0Sstevel@tonic-gate 	if (*vallenp <= buflen) {
505*0Sstevel@tonic-gate 		(void) memcpy(valbuf, val, *vallenp);
506*0Sstevel@tonic-gate 	}
507*0Sstevel@tonic-gate 
508*0Sstevel@tonic-gate 	return (B_TRUE);
509*0Sstevel@tonic-gate }
510*0Sstevel@tonic-gate 
511*0Sstevel@tonic-gate /*
512*0Sstevel@tonic-gate  * Function dealing with DHCP data.
513*0Sstevel@tonic-gate  */
514*0Sstevel@tonic-gate boolean_t
bi_get_dhcp_info(uchar_t optcat,uint16_t optcode,uint16_t optsize,void * valbuf,size_t * vallenp)515*0Sstevel@tonic-gate bi_get_dhcp_info(uchar_t optcat, uint16_t optcode, uint16_t optsize,
516*0Sstevel@tonic-gate     void *valbuf, size_t *vallenp)
517*0Sstevel@tonic-gate {
518*0Sstevel@tonic-gate 	return (dhcp_getinfo_pl(dhcp_pl,
519*0Sstevel@tonic-gate 	    optcat, optcode, optsize, valbuf, vallenp));
520*0Sstevel@tonic-gate }
521