/* * Format up to a page worth of forwarding table entries * userbuf -- where to copy result * maxnum -- maximum number of entries desired * (limited to a page for sanity) * offset -- number of records to skip
*/ staticint get_fdb_entries(struct net_bridge *br, void __user *userbuf, unsignedlong maxnum, unsignedlong offset)
{ int num; void *buf;
size_t size;
/* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */ if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry))
maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);
size = maxnum * sizeof(struct __fdb_entry);
buf = kmalloc(size, GFP_USER); if (!buf) return -ENOMEM;
num = br_fdb_fillbuf(br, buf, maxnum, offset); if (num > 0) { if (copy_to_user(userbuf, buf,
array_size(num, sizeof(struct __fdb_entry))))
num = -EFAULT;
}
kfree(buf);
return num;
}
/* called with RTNL */ staticint add_del_if(struct net_bridge *br, int ifindex, int isadd)
{ struct net *net = dev_net(br->dev); struct net_device *dev; int ret;
if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) return -EPERM;
dev = __dev_get_by_index(net, ifindex); if (dev == NULL) return -EINVAL;
if (isadd)
ret = br_add_if(br, dev, NULL); else
ret = br_del_if(br, dev);
/* * Legacy ioctl's through SIOCDEVPRIVATE * This interface is deprecated because it was too difficult * to do the translation for 32/64bit ioctl compatibility.
*/ int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq, void __user *data, int cmd)
{ struct net_bridge *br = netdev_priv(dev); struct net_bridge_port *p = NULL; unsignedlong args[4]; void __user *argp; int ret;
ret = br_dev_read_uargs(args, ARRAY_SIZE(args), &argp, data); if (ret) return ret;
switch (args[0]) { case BRCTL_ADD_IF: case BRCTL_DEL_IF: return add_del_if(br, args[1], args[0] == BRCTL_ADD_IF);
case BRCTL_GET_BRIDGE_INFO:
{ struct __bridge_info b;
switch (cmd) { case SIOCGIFBR: case SIOCSIFBR:
ret = old_deviceless(net, uarg); break; case SIOCBRADDBR: case SIOCBRDELBR:
{ char buf[IFNAMSIZ];
if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) {
ret = -EPERM; break;
}
if (copy_from_user(buf, uarg, IFNAMSIZ)) {
ret = -EFAULT; break;
}
buf[IFNAMSIZ-1] = 0; if (cmd == SIOCBRADDBR)
ret = br_add_bridge(net, buf); else
ret = br_del_bridge(net, buf);
} break; case SIOCBRADDIF: case SIOCBRDELIF:
{ struct net_device *dev;
dev = __dev_get_by_name(net, ifr.ifr_name); if (!dev || !netif_device_present(dev)) {
ret = -ENODEV; break;
} if (!netif_is_bridge_master(dev)) {
ret = -EOPNOTSUPP; break;
}
ret = add_del_if(netdev_priv(dev), ifr.ifr_ifindex, cmd == SIOCBRADDIF);
} break;
}
rtnl_unlock();
return ret;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.