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