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 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 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 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 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 * 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 * 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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