summaryrefslogtreecommitdiff
path: root/drivers/vlan_mon/vlan_mon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vlan_mon/vlan_mon.c')
-rw-r--r--drivers/vlan_mon/vlan_mon.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/vlan_mon/vlan_mon.c b/drivers/vlan_mon/vlan_mon.c
index 16bb11e..9a2d211 100644
--- a/drivers/vlan_mon/vlan_mon.c
+++ b/drivers/vlan_mon/vlan_mon.c
@@ -490,6 +490,36 @@ static int vlan_mon_nl_cmd_del_vlan_mon(struct sk_buff *skb, struct genl_info *i
return 0;
}
+static int vlan_mon_nl_cmd_check_busy(struct sk_buff *skb, struct genl_info *info)
+{
+ int ifindex, vid;
+ struct net_device *dev;
+ int ret = 0;
+
+ if (!info->attrs[VLAN_MON_ATTR_IFINDEX] || !info->attrs[VLAN_MON_ATTR_VID])
+ return -EINVAL;
+
+ ifindex = nla_get_u32(info->attrs[VLAN_MON_ATTR_IFINDEX]);
+ vid = nla_get_u16(info->attrs[VLAN_MON_ATTR_VID]);
+
+ down(&vlan_mon_lock);
+
+ rtnl_lock();
+ dev = __dev_get_by_index(&init_net, ifindex);
+ if (dev) {
+ struct vlan_dev *d = dev->ml_priv;
+ if (d) {
+ if (d->busy[vid / (8*sizeof(long))] & (1lu << (vid % (8*sizeof(long)))))
+ ret = -EBUSY;
+ }
+ }
+ rtnl_unlock();
+
+ up(&vlan_mon_lock);
+
+ return ret;
+}
+
static struct nla_policy vlan_mon_nl_policy[VLAN_MON_ATTR_MAX + 1] = {
[VLAN_MON_ATTR_NONE] = { .type = NLA_UNSPEC, },
[VLAN_MON_ATTR_VLAN_MASK] = { .type = NLA_BINARY, .len = 4096/8 },
@@ -523,6 +553,12 @@ static struct genl_ops vlan_mon_nl_ops[] = {
.policy = vlan_mon_nl_policy,
.flags = GENL_ADMIN_PERM,
},
+ {
+ .cmd = VLAN_MON_CMD_CHECK_BUSY,
+ .doit = vlan_mon_nl_cmd_check_busy,
+ .policy = vlan_mon_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
};
static struct genl_family vlan_mon_nl_family = {