/* * The functions in this file do a dev tree walk to build up a model of the * disks, controllers and paths on the system. This model is returned in the * args->disk_listp and args->controller_listp members of the args param. * There is no global data for this file so it is thread safe. It is up to * the caller to merge the resulting model with any existing model that is * cached. The caller must also free the memory for this model when it is * no longer needed. */ void findevs(struct search_args *args) { di_node_t di_root; args->bus_listp = NULL; args->controller_listp = NULL; args->disk_listp = NULL; args->dev_walk_status = 0; args->handle = di_devlink_init(NULL, 0); /* * Have to make several passes at this with the new devfs caching. * First, we find non-mpxio devices. Then we find mpxio/multipath * devices. */ di_root = di_init("/", DINFOCACHE); args->ph = di_prom_init(); (void) di_walk_minor(di_root, NULL, 0, args, add_devs); di_fini(di_root); di_root = di_init("/", DINFOCPYALL|DINFOPATH); (void) di_walk_minor(di_root, NULL, 0, args, add_devs); di_fini(di_root); (void) di_devlink_fini(&(args->handle)); clean_paths(args); }
/* * The rule for scsi disks uses this to determine if the /devices * entry corresponds to a cdrom drive. Use libdevinfo to walk * the device tree: * calling find_cd_nodes() for each minor node of type DDI_NT_CD. * calling find_sd_nodes() for each minor node of type DDI_NT_BLOCK_CHAN. */ static void find_cdsd(void) { di_node_t root_node; root_node = di_init("/", DINFOSUBTREE|DINFOMINOR); if (root_node == DI_NODE_NIL) { return; } di_walk_minor(root_node, DDI_NT_CD, 0, NULL, find_cd_nodes); di_walk_minor(root_node, DDI_NT_BLOCK_CHAN, 0, NULL, find_sd_nodes); di_fini(root_node); }
/* * Attempt to access PCI subsystem using Solaris's devfs interface. * Solaris version */ _pci_hidden int pci_system_solx_devfs_create( void ) { int err = 0; di_node_t di_node; probe_info_t pinfo; struct pci_device_private *devices; if (nexus_list != NULL) { return 0; } if ((di_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { err = errno; (void) fprintf(stderr, "di_init() failed: %s\n", strerror(errno)); return (err); } if ((devices = calloc(INITIAL_NUM_DEVICES, sizeof (struct pci_device_private))) == NULL) { err = errno; di_fini(di_node); return (err); } #ifdef __sparc if ((di_phdl = di_prom_init()) == DI_PROM_HANDLE_NIL) (void) fprintf(stderr, "di_prom_init failed: %s\n", strerror(errno)); #endif pinfo.num_allocated_elems = INITIAL_NUM_DEVICES; pinfo.num_devices = 0; pinfo.devices = devices; (void) di_walk_minor(di_node, DDI_NT_REGACC, 0, &pinfo, probe_nexus_node); di_fini(di_node); if ((pci_sys = calloc(1, sizeof (struct pci_system))) == NULL) { err = errno; free(devices); return (err); } pci_sys->methods = &solx_devfs_methods; pci_sys->devices = pinfo.devices; pci_sys->num_devices = pinfo.num_devices; return (err); }
/* * Drives the walk of the network minor device nodes to * build the niclist. * * Returns: ICFG_SUCCESS or ICFG_FAILURE. In the case of * ICFG_FAILURE, syserr will contain the errno. */ static int nic_build_list(niclist_t **niclist, int *numif, int *syserr) { wlkreq_t request; di_node_t root_node; int err = ICFG_SUCCESS; int ret; root_node = di_init(NIC_DEVTREE_ROOT, DINFOSUBTREE | DINFOMINOR); if (root_node == DI_NODE_NIL) { *syserr = errno; return (ICFG_FAILURE); } /* * di_walk_minor() only allows one arg to be passed to walker. */ request.wr_niclist = niclist; request.wr_numif = numif; request.wr_syserr = syserr; request.wr_err = &err; ret = di_walk_minor(root_node, DDI_NT_NET, DI_CHECK_ALIAS, &request, nic_process_minor_nodes); if (ret != 0) { *syserr = errno; di_fini(root_node); return (ICFG_FAILURE); } /* * On error, free the partially formed list. */ if (err != ICFG_SUCCESS) { nic_free_list(*niclist); *numif = 0; } di_fini(root_node); return (err); }
/* * Don't use devfs if stat() in /devices fails. Use libdevinfo instead. * Retired devices don't show up in devfs. * * Returns: * 1 - minor exists and is of type BLK * 0 - minor does not exist or is not of type BLK. */ static int is_devinfo_blk(char *minor_path) { char *minor_portion; struct chk_dev chk_dev; di_node_t node; int rv; /* * prune minor path for di_init() - no /devices prefix and no minor name */ if (strncmp(minor_path, "/devices/", strlen("/devices/")) != 0) return (0); minor_portion = strrchr(minor_path, *MINOR_SEP); if (minor_portion == NULL) return (0); *minor_portion = 0; node = di_init(minor_path + strlen("/devices"), DINFOMINOR); *minor_portion = *MINOR_SEP; if (node == DI_NODE_NIL) return (0); chk_dev.c_isblk = 0; chk_dev.c_minor = minor_portion + 1; rv = di_walk_minor(node, NULL, 0, &chk_dev, chk_dev_fcn); di_fini(node); if (rv == 0 && chk_dev.c_isblk) return (1); else return (0); }
/* * update_cache() * * The devinfo tree walking code is lifted from ifconfig.c. */ static void update_cache(rcm_handle_t *hd) { net_cache_t *probe; di_node_t root; int rv; (void) mutex_lock(&cache_lock); /* first we walk the entire cache, marking each entry stale */ probe = cache_head.next; while (probe != &cache_tail) { probe->flags |= CACHE_STALE; probe = probe->next; } root = di_init("/", DINFOSUBTREE | DINFOMINOR); if (root == DI_NODE_NIL) { goto done; } (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, NULL, devfs_entry); di_fini(root); probe = cache_head.next; while (probe != &cache_tail) { net_cache_t *freeit; if (probe->flags & CACHE_STALE) { (void) rcm_unregister_interest(hd, probe->resource, 0); rcm_log_message(RCM_DEBUG, _("NET: unregistered %s\n"), probe->resource); freeit = probe; probe = probe->next; cache_remove(freeit); free_node(freeit); continue; } if (!(probe->flags & CACHE_NEW)) { probe = probe->next; continue; } rcm_log_message(RCM_DEBUG, _("NET: registering %s\n"), probe->resource); rv = rcm_register_interest(hd, probe->resource, 0, NULL); if (rv != RCM_SUCCESS) { rcm_log_message(RCM_ERROR, _("NET: failed to register %s\n"), probe->resource); } else { rcm_log_message(RCM_DEBUG, _("NET: registered %s as SUNW_datalink/%u\n"), probe->resource, probe->linkid); probe->flags &= ~(CACHE_NEW); } probe = probe->next; } done: (void) mutex_unlock(&cache_lock); }
int NetIfList(std::list <ComObjPtr<HostNetworkInterface> > &list) { /* * Use libdevinfo for determining all physical interfaces. */ di_node_t Root; Root = di_init("/", DINFOCACHE); if (Root != DI_NODE_NIL) { di_walk_minor(Root, DDI_NT_NET, 0, &list, vboxSolarisAddPhysHostIface); di_fini(Root); } /* * Use libdlpi for determining all DLPI interfaces. */ if (VBoxSolarisLibDlpiFound()) g_pfnLibDlpiWalk(vboxSolarisAddLinkHostIface, &list, 0); /* * This gets only the list of all plumbed logical interfaces. * This is needed for zones which cannot access the device tree * and in this case we just let them use the list of plumbed interfaces * on the zone. */ int Sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (Sock > 0) { struct lifnum IfNum; memset(&IfNum, 0, sizeof(IfNum)); IfNum.lifn_family = AF_INET; int rc = ioctl(Sock, SIOCGLIFNUM, &IfNum); if (!rc) { struct lifreq Ifaces[24]; struct lifconf IfConfig; memset(&IfConfig, 0, sizeof(IfConfig)); IfConfig.lifc_family = AF_INET; IfConfig.lifc_len = sizeof(Ifaces); IfConfig.lifc_buf = (caddr_t)&(Ifaces[0]); rc = ioctl(Sock, SIOCGLIFCONF, &IfConfig); if (!rc) { for (int i = 0; i < IfNum.lifn_count; i++) { /* * Skip loopback interfaces. */ if (!strncmp(Ifaces[i].lifr_name, "lo", 2)) continue; #if 0 rc = ioctl(Sock, SIOCGLIFADDR, &(Ifaces[i])); if (rc >= 0) { memcpy(Info.IPAddress.au8, ((struct sockaddr *)&Ifaces[i].lifr_addr)->sa_data, sizeof(Info.IPAddress.au8)); // SIOCGLIFNETMASK struct arpreq ArpReq; memcpy(&ArpReq.arp_pa, &Ifaces[i].lifr_addr, sizeof(struct sockaddr_in)); /* * We might fail if the interface has not been assigned an IP address. * That doesn't matter; as long as it's plumbed we can pick it up. * But, if it has not acquired an IP address we cannot obtain it's MAC * address this way, so we just use all zeros there. */ rc = ioctl(Sock, SIOCGARP, &ArpReq); if (rc >= 0) memcpy(&Info.MACAddress, ArpReq.arp_ha.sa_data, sizeof(Info.MACAddress)); char szNICDesc[LIFNAMSIZ + 256]; char *pszIface = Ifaces[i].lifr_name; strcpy(szNICDesc, pszIface); vboxSolarisAddLinkHostIface(pszIface, &list); } #endif char *pszIface = Ifaces[i].lifr_name; vboxSolarisAddLinkHostIface(pszIface, &list); } } } close(Sock); } /* * Weed out duplicates caused by dlpi_walk inconsistencies across Nevadas. */ list.sort(vboxSolarisSortNICList); list.unique(vboxSolarisSameNIC); return VINF_SUCCESS; }