Ejemplo n.º 1
0
/*
 * Get bridge parameters using either sysfs or old
 * ioctl.
 */
static int br_get_bridge_info(const char *bridge, struct bridge_info *info)
{
#ifdef HAVE_LIBSYSFS
	struct sysfs_class_device *dev;
	char path[SYSFS_PATH_MAX];

	if (!br_class_net)
		goto fallback;

	dev = sysfs_get_class_device(br_class_net, bridge);
	if (!dev) {
		dprintf("get_class_device '%s' failed\n", bridge);
		goto fallback;
	}

	snprintf(path, SYSFS_PATH_MAX, "%s/bridge", dev->path);
	if (sysfs_path_is_dir(path)) {
		dprintf("path '%s' is not a directory\n", path);
		sysfs_close_class_device(dev);
		goto fallback;
	}

	memset(info, 0, sizeof(*info));
	fetch_id(dev, BRIDGEATTR("root_id"), &info->designated_root);
	fetch_id(dev, BRIDGEATTR("bridge_id"), &info->bridge_id);
	info->root_path_cost = fetch_int(dev, BRIDGEATTR("root_path_cost"));
	fetch_tv(dev, BRIDGEATTR("max_age"), &info->max_age);
	fetch_tv(dev, BRIDGEATTR("hello_time"), &info->hello_time);
	fetch_tv(dev, BRIDGEATTR("forward_delay"), &info->forward_delay);
	fetch_tv(dev, BRIDGEATTR("max_age"), &info->bridge_max_age);
	fetch_tv(dev, BRIDGEATTR("hello_time"), &info->bridge_hello_time);
	fetch_tv(dev, BRIDGEATTR("forward_delay"), &info->bridge_forward_delay);
	fetch_tv(dev, BRIDGEATTR("ageing_time"), &info->ageing_time);
	fetch_tv(dev, BRIDGEATTR("hello_timer"), &info->hello_timer_value);
	fetch_tv(dev, BRIDGEATTR("tcn_timer"), &info->tcn_timer_value);
	fetch_tv(dev, BRIDGEATTR("topology_change_timer"),
		 &info->topology_change_timer_value);;
	fetch_tv(dev, BRIDGEATTR("gc_timer"), &info->gc_timer_value);

	info->root_port = fetch_int(dev, BRIDGEATTR("root_port"));
	info->stp_enabled = fetch_int(dev, BRIDGEATTR("stp_state"));
	info->topology_change = fetch_int(dev, BRIDGEATTR("topology_change"));
	info->topology_change_detected = fetch_int(dev,
						   BRIDGEATTR
						   ("topology_change_detected"));
	sysfs_close_class_device(dev);

	return 0;

fallback:
#endif
	return old_get_bridge_info(bridge, info);
}
Ejemplo n.º 2
0
/**
 * sysfs_open_class_device_path: Opens and populates class device
 * @path: path to class device.
 * returns struct sysfs_class_device with success and NULL with error.
 */
struct sysfs_class_device *sysfs_open_class_device_path(const char *path)
{
    struct sysfs_class_device *cdev;
    char temp_path[SYSFS_PATH_MAX];

    if (!path) {
        errno = EINVAL;
        return NULL;
    }

    /*
     * Post linux-2.6.14 driver model supports nested classes with
     * links to the nested hierarchy at /sys/class/xxx/. Check for
     * a link to the actual class device if a directory isn't found
     */
    if (sysfs_path_is_dir(path)) {
        dprintf("%s: Directory not found, checking for a link\n", path);
        if (!sysfs_path_is_link(path)) {
            if (sysfs_get_link(path, temp_path, SYSFS_PATH_MAX)) {
                dprintf("Error retrieving link at %s\n", path);
                return NULL;
            }
        } else {
            dprintf("%s is not a valid class device path\n", path);
            return NULL;
        }
    } else
        safestrcpy(temp_path, path);

    cdev = alloc_class_device();
    if (!cdev) {
        dprintf("calloc failed\n");
        return NULL;
    }
    if (sysfs_get_name_from_path(temp_path, cdev->name, SYSFS_NAME_LEN)) {
        errno = EINVAL;
        dprintf("Error getting class device name\n");
        sysfs_close_class_device(cdev);
        return NULL;
    }

    safestrcpy(cdev->path, temp_path);
    if (sysfs_remove_trailing_slash(cdev->path)) {
        dprintf("Invalid path to class device %s\n", cdev->path);
        sysfs_close_class_device(cdev);
        return NULL;
    }
    set_classdev_classname(cdev);

    return cdev;
}
Ejemplo n.º 3
0
static int br_set(const char *bridge, const char *name, unsigned long value, unsigned long oldcode)
{
	int ret = -1;

#ifdef HAVE_LIBSYSFS
	struct sysfs_class_device *dev;

	dev = sysfs_get_class_device(br_class_net, bridge);
	if (dev) {
		struct sysfs_attribute *attr;
		char buf[32];
		char path[SYSFS_PATH_MAX];

		snprintf(buf, sizeof(buf), "%ld\n", value);
		snprintf(path, SYSFS_PATH_MAX, "%s/bridge/%s", dev->path, name);

		attr = sysfs_open_attribute(path);
		if (attr) {
			ret = sysfs_write_attribute(attr, buf, strlen(buf));
			sysfs_close_attribute(attr);
		}
		sysfs_close_class_device(dev);
	} else
#endif
	{
		struct ifreq ifr;
		unsigned long args[4] = { oldcode, value, 0, 0 };

		strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
		ifr.ifr_data = (char *)&args;
		ret = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);
	}

	return ret < 0 ? errno : 0;
}
Ejemplo n.º 4
0
/**
 * sysfs_close_class_device: closes a single class device.
 * @dev: class device to close.
 */
void sysfs_close_class_device(struct sysfs_class_device *dev)
{
    if (dev) {
        if (dev->parent)
            sysfs_close_class_device(dev->parent);
        if (dev->sysdevice)
            sysfs_close_device(dev->sysdevice);
        if (dev->attrlist)
            dlist_destroy(dev->attrlist);
        free(dev);
    }
}
Ejemplo n.º 5
0
static void sysfs_close_cls_dev(void *dev)
{
    sysfs_close_class_device((struct sysfs_class_device *)dev);
}