Esempio n. 1
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;
}
Esempio n. 2
0
static struct sysfs_directory *bridge_sysfs_directory(const char *devname,
						      const char *subname)
{
	struct sysfs_directory *sdir;
	struct sysfs_class_device *dev;
	char path[SYSFS_PATH_MAX];

	if (!devname)
		return NULL;

	if (!br_class_net) {
		dprintf("can't find class_net\n");
		return NULL;
	}

	dev = sysfs_get_class_device(br_class_net, (char *) devname);
	if (!dev) {
		dprintf("can't find device %s in %s\n", devname, br_class_net->path);
		return NULL;
	}

	snprintf(path, SYSFS_PATH_MAX, "%s/%s", dev->path, subname);
	sdir = sysfs_open_directory(path);
	if (!sdir)
		dprintf("can't open directory: %s\n", path);
	return sdir;
}
Esempio n. 3
0
int br_read_fdb(const char *bridge, struct fdb_entry *fdbs, 
		unsigned long offset, int num)
{
	int i, fd = -1, n;
	struct __fdb_entry fe[num];
#ifdef HAVE_LIBSYSFS
	struct sysfs_class_device *dev;
	
	/* open /sys/class/net/brXXX/brforward */
	if (br_class_net &&
	    (dev = sysfs_get_class_device(br_class_net, (char *) bridge))) {
		char path[SYSFS_PATH_MAX];

		snprintf(path, SYSFS_PATH_MAX, "%s/%s", dev->path, 
			 SYSFS_BRIDGE_FDB);
		fd = open(path, O_RDONLY, 0);
	}

	if (fd != -1) {
		/* read records from file */
		lseek(fd, offset*sizeof(struct __fdb_entry), SEEK_SET);
		n = read(fd, fe, num*sizeof(struct __fdb_entry));
		if (n > 0)
			n /= sizeof(struct __fdb_entry);
	} else
#endif
	{
		/* old kernel, use ioctl */
		unsigned long args[4] = { BRCTL_GET_FDB_ENTRIES,
					  (unsigned long) fe,
					  num, offset };
		struct ifreq ifr;
		int retries = 0;

		strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
		ifr.ifr_data = (char *) args;

	retry:
		n = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);

		/* table can change during ioctl processing */
		if (n < 0 && errno == EAGAIN && ++retries < 10) {
			sleep(0);
			goto retry;
		}
	}

	for (i = 0; i < n; i++) 
		__copy_fdb(fdbs+i, fe+i);

	if (fd > 0)
		close(fd);
	
	return n;
}
Esempio n. 4
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);
}
Esempio n. 5
0
/*
 * Iterate over all ports in bridge (using sysfs).
 */
int br_foreach_port(const char *brname,
                    int (*iterator)(const char *br, const char *port, void *arg),
                    void *arg)
{
#ifdef HAVE_LIBSYSFS
    struct sysfs_class_device *dev;
    DIR *dir;
    struct dirent *dirent;
    int err = 0;
    char path[SYSFS_PATH_MAX];

    if (!br_class_net ||
            !(dev = sysfs_get_class_device(br_class_net, (char *) brname)))
        goto old;

    snprintf(path, sizeof(path), "%s/%s",
             dev->path, SYSFS_BRIDGE_PORT_SUBDIR);


    dir = opendir(path);
    if (!dir) {
        /* no /sys/class/net/ethX/brif subdirectory
         * either: old kernel, or not really a bridge
         */
        goto old;
    }

    err = 0;
    while ((dirent = readdir(dir)) != NULL) {
        if (0 == strcmp(dirent->d_name, "."))
            continue;
        if (0 == strcmp(dirent->d_name, ".."))
            continue;
        ++err;
        if (iterator(brname, dirent->d_name, arg))
            break;
    }
    closedir(dir);

    return err;

old:
#endif
    return old_foreach_port(brname, iterator, arg);

}
Esempio n. 6
0
/*
 * Iterate over all ports in bridge (using sysfs).
 */
int br_foreach_port(const char *brname,
		    int (*iterator)(const char *br, const char *port, void *arg),
		    void *arg)
{
#ifdef HAVE_LIBSYSFS
	struct sysfs_class_device *dev;
	struct sysfs_directory *dir;
	struct sysfs_link *plink;
	struct dlist *links;
	int err = 0;
	char path[SYSFS_PATH_MAX];

	if (!br_class_net ||
	    !(dev = sysfs_get_class_device(br_class_net, (char *) brname)))
		goto old;

	snprintf(path, sizeof(path), "%s/%s", 
		 dev->path, SYSFS_BRIDGE_PORT_SUBDIR);

	dprintf("path=%s\n", path);
	dir = sysfs_open_directory(path);
	if (!dir) {
		/* no /sys/class/net/ethX/brif subdirectory
		 * either: old kernel, or not really a bridge
		 */
		goto old;
	}

	links = sysfs_get_dir_links(dir);
	if (!links) {
		err = -ENOSYS;
		goto out;
	}

	err = 0;
	dlist_for_each_data(links, plink, struct sysfs_link) {
		++err;
		if (iterator(brname, plink->name, arg))
			break;
	}