示例#1
0
/*
 * 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);
}
示例#2
0
/*
 * 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);
}
示例#4
0
/*
 * 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);
}
示例#5
0
/*
 * 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);
}
示例#6
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);
}
示例#7
0
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;
}