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