X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Fbrcompat.c;h=f9d008399cd19434cc0cd22754e858afe09cbda7;hb=8b28d8649d96325f99cbc73fae8215face4a0ce4;hp=92fcecc216719dce8eb274b96ffb5210c95491ae;hpb=c170afc1dbdcf2e5adb1a0d2da6635bd81b7126f;p=sliver-openvswitch.git diff --git a/datapath/brcompat.c b/datapath/brcompat.c index 92fcecc21..f9d008399 100644 --- a/datapath/brcompat.c +++ b/datapath/brcompat.c @@ -1,11 +1,13 @@ /* - * Copyright (c) 2009 Nicira Networks. + * Copyright (c) 2009, 2011 Nicira Networks. * Distributed under the terms of the GNU GPL version 2. * * Significant portions of this file may be copied from parts of the Linux * kernel, by Linus Torvalds and others. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -15,9 +17,7 @@ #include #include -#include "compat.h" #include "openvswitch/brcompat-netlink.h" -#include "brc_procfs.h" #include "datapath.h" static struct genl_family brc_genl_family; @@ -42,8 +42,8 @@ static u32 brc_seq; /* Sequence number for current op. */ static struct sk_buff *brc_send_command(struct sk_buff *, struct nlattr **attrs); static int brc_send_simple_command(struct sk_buff *); -static struct sk_buff * -brc_make_request(int op, const char *bridge, const char *port) +static struct sk_buff *brc_make_request(int op, const char *bridge, + const char *port) { struct sk_buff *skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) @@ -82,6 +82,9 @@ static int brc_add_del_bridge(char __user *uname, int add) struct sk_buff *request; char name[IFNAMSIZ]; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(name, uname, IFNAMSIZ)) return -EFAULT; @@ -146,8 +149,7 @@ static int brc_get_bridges(int __user *uindices, int n) } /* Legacy deviceless bridge ioctl's. Called with br_ioctl_mutex. */ -static int -old_deviceless(void __user *uarg) +static int old_deviceless(void __user *uarg) { unsigned long args[3]; @@ -189,13 +191,15 @@ brc_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg) return -EOPNOTSUPP; } -static int -brc_add_del_port(struct net_device *dev, int port_ifindex, int add) +static int brc_add_del_port(struct net_device *dev, int port_ifindex, int add) { struct sk_buff *request; struct net_device *port; int err; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + port = __dev_get_by_index(&init_net, port_ifindex); if (!port) return -EINVAL; @@ -214,18 +218,17 @@ brc_add_del_port(struct net_device *dev, int port_ifindex, int add) return err; } -static int -brc_get_bridge_info(struct net_device *dev, struct __bridge_info __user *ub) +static int brc_get_bridge_info(struct net_device *dev, + struct __bridge_info __user *ub) { struct __bridge_info b; - u64 id = 0; - int i; memset(&b, 0, sizeof(struct __bridge_info)); - for (i=0; idev_addr[i] << (8*(ETH_ALEN-1 - i)); - b.bridge_id = cpu_to_be64(id); + /* First two bytes are the priority, which we should skip. This comes + * from struct bridge_id in br_private.h, which is unavailable to us. + */ + memcpy((u8 *)&b.bridge_id + 2, dev->dev_addr, ETH_ALEN); b.stp_enabled = 0; if (copy_to_user(ub, &b, sizeof(struct __bridge_info))) @@ -234,8 +237,8 @@ brc_get_bridge_info(struct net_device *dev, struct __bridge_info __user *ub) return 0; } -static int -brc_get_port_list(struct net_device *dev, int __user *uindices, int num) +static int brc_get_port_list(struct net_device *dev, int __user *uindices, + int num) { int retval; @@ -254,7 +257,7 @@ brc_get_port_list(struct net_device *dev, int __user *uindices, int num) * (limited to a page for sanity) * offset -- number of records to skip */ -static int brc_get_fdb_entries(struct net_device *dev, void __user *userbuf, +static int brc_get_fdb_entries(struct net_device *dev, void __user *userbuf, unsigned long maxnum, unsigned long offset) { struct nlattr *attrs[BRC_GENL_A_MAX + 1]; @@ -306,8 +309,7 @@ nla_put_failure: } /* Legacy ioctl's through SIOCDEVPRIVATE. Called with rtnl_lock. */ -static int -old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { unsigned long args[4]; @@ -335,8 +337,7 @@ old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } /* Called with the rtnl_lock. */ -static int -brc_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int brc_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { int err; @@ -374,7 +375,7 @@ static int brc_genl_query(struct sk_buff *skb, struct genl_info *info) void *data; ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!ans_skb) + if (!ans_skb) return -ENOMEM; data = genlmsg_put_reply(ans_skb, info, &brc_genl_family, @@ -394,27 +395,13 @@ nla_put_failure: return err; } -static struct genl_ops brc_genl_ops_query_dp = { - .cmd = BRC_GENL_C_QUERY_MC, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ - .policy = NULL, - .doit = brc_genl_query, - .dumpit = NULL -}; - /* Attribute policy: what each attribute may contain. */ static struct nla_policy brc_genl_policy[BRC_GENL_A_MAX + 1] = { [BRC_GENL_A_ERR_CODE] = { .type = NLA_U32 }, - - [BRC_GENL_A_PROC_DIR] = { .type = NLA_NUL_STRING }, - [BRC_GENL_A_PROC_NAME] = { .type = NLA_NUL_STRING }, - [BRC_GENL_A_PROC_DATA] = { .type = NLA_NUL_STRING }, - [BRC_GENL_A_FDB_DATA] = { .type = NLA_UNSPEC }, }; -static int -brc_genl_dp_result(struct sk_buff *skb, struct genl_info *info) +static int brc_genl_dp_result(struct sk_buff *skb, struct genl_info *info) { unsigned long int flags; int err; @@ -430,8 +417,7 @@ brc_genl_dp_result(struct sk_buff *skb, struct genl_info *info) if (brc_seq == info->snd_seq) { brc_seq++; - if (brc_reply) - kfree_skb(brc_reply); + kfree_skb(brc_reply); brc_reply = skb; complete(&brc_done); @@ -445,23 +431,21 @@ brc_genl_dp_result(struct sk_buff *skb, struct genl_info *info) return err; } -static struct genl_ops brc_genl_ops_dp_result = { - .cmd = BRC_GENL_C_DP_RESULT, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ - .policy = brc_genl_policy, - .doit = brc_genl_dp_result, - .dumpit = NULL +static struct genl_ops brc_genl_ops[] = { + { .cmd = BRC_GENL_C_QUERY_MC, + .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ + .policy = NULL, + .doit = brc_genl_query, + }, + { .cmd = BRC_GENL_C_DP_RESULT, + .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ + .policy = brc_genl_policy, + .doit = brc_genl_dp_result, + }, }; -static struct genl_ops brc_genl_ops_set_proc = { - .cmd = BRC_GENL_C_SET_PROC, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */ - .policy = brc_genl_policy, - .doit = brc_genl_set_proc, - .dumpit = NULL -}; - -static struct sk_buff *brc_send_command(struct sk_buff *request, struct nlattr **attrs) +static struct sk_buff *brc_send_command(struct sk_buff *request, + struct nlattr **attrs) { unsigned long int flags; struct sk_buff *reply; @@ -485,8 +469,10 @@ static struct sk_buff *brc_send_command(struct sk_buff *request, struct nlattr * /* Wait for reply. */ error = -ETIMEDOUT; - if (!wait_for_completion_timeout(&brc_done, BRC_TIMEOUT)) + if (!wait_for_completion_timeout(&brc_done, BRC_TIMEOUT)) { + pr_warn("timed out waiting for userspace\n"); goto error; + } /* Grab reply. */ spin_lock_irqsave(&brc_lock, flags); @@ -509,8 +495,7 @@ error: return ERR_PTR(error); } -static int -__init brc_init(void) +static int __init brc_init(void) { int err; @@ -529,22 +514,11 @@ __init brc_init(void) /* Register generic netlink family to communicate changes to * userspace. */ - err = genl_register_family(&brc_genl_family); + err = genl_register_family_with_ops(&brc_genl_family, + brc_genl_ops, ARRAY_SIZE(brc_genl_ops)); if (err) goto error; - err = genl_register_ops(&brc_genl_family, &brc_genl_ops_query_dp); - if (err != 0) - goto err_unregister; - - err = genl_register_ops(&brc_genl_family, &brc_genl_ops_dp_result); - if (err != 0) - goto err_unregister; - - err = genl_register_ops(&brc_genl_family, &brc_genl_ops_set_proc); - if (err != 0) - goto err_unregister; - strcpy(brc_mc_group.name, "brcompat"); err = genl_register_mc_group(&brc_genl_family, &brc_mc_group); if (err < 0) @@ -555,19 +529,17 @@ __init brc_init(void) err_unregister: genl_unregister_family(&brc_genl_family); error: - printk(KERN_EMERG "brcompat: failed to install!"); + pr_emerg("failed to install!\n"); return err; } -static void -brc_cleanup(void) +static void brc_cleanup(void) { /* Unregister ioctl hooks */ dp_ioctl_hook = NULL; brioctl_set(NULL); genl_unregister_family(&brc_genl_family); - brc_procfs_exit(); } module_init(brc_init);