From: Felix Fietkau Date: Thu, 7 Oct 2010 21:47:53 +0000 (-0700) Subject: compat: backport netlink changes used in the nl80211 cleanup X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=49a1b74cb1df6682d1dff0cd0f18aad3c558ac17;p=openwrt%2Fstaging%2Fblogic.git compat: backport netlink changes used in the nl80211 cleanup Signed-off-by: Felix Fietkau --- diff --git a/compat/Makefile b/compat/Makefile index 1f053f2cb42c..c15a8f350539 100644 --- a/compat/Makefile +++ b/compat/Makefile @@ -23,7 +23,6 @@ compat-$(CONFIG_COMPAT_KERNEL_27) += compat-2.6.27.o compat-$(CONFIG_COMPAT_KERNEL_28) += compat-2.6.28.o compat-$(CONFIG_COMPAT_KERNEL_29) += compat-2.6.29.o compat-$(CONFIG_COMPAT_KERNEL_30) += compat-2.6.30.o -compat-$(CONFIG_COMPAT_KERNEL_31) += compat-2.6.31.o compat-$(CONFIG_COMPAT_KERNEL_32) += compat-2.6.32.o compat-$(CONFIG_COMPAT_KERNEL_33) += compat-2.6.33.o compat-$(CONFIG_COMPAT_KERNEL_35) += compat-2.6.35.o diff --git a/compat/compat-2.6.31.c b/compat/compat-2.6.31.c deleted file mode 100644 index dc8588fef27d..000000000000 --- a/compat/compat-2.6.31.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2007 Luis R. Rodriguez - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Compatibility file for Linux wireless for kernels 2.6.31. - */ - -#include - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) - -#include - -/** - * genl_register_family_with_ops - register a generic netlink family - * @family: generic netlink family - * @ops: operations to be registered - * @n_ops: number of elements to register - * - * Registers the specified family and operations from the specified table. - * Only one family may be registered with the same family name or identifier. - * - * The family id may equal GENL_ID_GENERATE causing an unique id to - * be automatically generated and assigned. - * - * Either a doit or dumpit callback must be specified for every registered - * operation or the function will fail. Only one operation structure per - * command identifier may be registered. - * - * See include/net/genetlink.h for more documenation on the operations - * structure. - * - * This is equivalent to calling genl_register_family() followed by - * genl_register_ops() for every operation entry in the table taking - * care to unregister the family on error path. - * - * Return 0 on success or a negative error code. - */ -int genl_register_family_with_ops(struct genl_family *family, - struct genl_ops *ops, size_t n_ops) -{ - int err, i; - - err = genl_register_family(family); - if (err) - return err; - - for (i = 0; i < n_ops; ++i, ++ops) { - err = genl_register_ops(family, ops); - if (err) - goto err_out; - } - return 0; -err_out: - genl_unregister_family(family); - return err; -} -EXPORT_SYMBOL(genl_register_family_with_ops); - -#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) */ - diff --git a/compat/compat-2.6.37.c b/compat/compat-2.6.37.c index 655b92fc2be2..52c5a32478e8 100644 --- a/compat/compat-2.6.37.c +++ b/compat/compat-2.6.37.c @@ -42,4 +42,116 @@ EXPORT_SYMBOL_GPL(net_ns_type_operations); #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)*/ +#undef genl_info +#undef genl_unregister_family + +static LIST_HEAD(compat_nl_fam); + +static struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family) +{ + struct genl_ops *ops; + + list_for_each_entry(ops, &family->family.ops_list, ops.ops_list) + if (ops->cmd == cmd) + return ops; + + return NULL; +} + + +static int nl_doit_wrapper(struct sk_buff *skb, struct genl_info *info) +{ + struct compat_genl_info compat_info; + struct genl_family *family; + struct genl_ops *ops; + int err; + + list_for_each_entry(family, &compat_nl_fam, list) { + if (family->id == info->nlhdr->nlmsg_type) + goto found; + } + return -ENOENT; + +found: + ops = genl_get_cmd(info->genlhdr->cmd, family); + if (!ops) + return -ENOENT; + + memset(&compat_info.user_ptr, 0, sizeof(compat_info.user_ptr)); + compat_info.info = info; +#define __copy(_field) compat_info._field = info->_field + __copy(snd_seq); + __copy(snd_pid); + __copy(genlhdr); + __copy(attrs); +#undef __copy + if (family->pre_doit) { + err = family->pre_doit(ops, skb, &compat_info); + if (err) + return err; + } + + err = ops->doit(skb, &compat_info); + + if (family->post_doit) + family->post_doit(ops, skb, &compat_info); + + return err; +} + +int compat_genl_register_family_with_ops(struct genl_family *family, + struct genl_ops *ops, size_t n_ops) +{ + int i, ret; + +#define __copy(_field) family->family._field = family->_field + __copy(id); + __copy(hdrsize); + __copy(version); + __copy(maxattr); + strncpy(family->family.name, family->name, sizeof(family->family.name)); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) + __copy(netnsok); +#endif +#undef __copy + + ret = genl_register_family(&family->family); + if (ret < 0) + return ret; + + family->attrbuf = family->family.attrbuf; + family->id = family->family.id; + + for (i = 0; i < n_ops; i++) { +#define __copy(_field) ops[i].ops._field = ops[i]._field + __copy(cmd); + __copy(flags); + __copy(policy); + __copy(dumpit); + __copy(done); +#undef __copy + ops[i].ops.doit = nl_doit_wrapper; + ret = genl_register_ops(&family->family, &ops[i].ops); + if (ret < 0) + goto error_ops; + } + list_add(&family->list, &compat_nl_fam); + + return ret; + +error_ops: + compat_genl_unregister_family(family); + return ret; +} +EXPORT_SYMBOL(compat_genl_register_family_with_ops); + +int compat_genl_unregister_family(struct genl_family *family) +{ + int err; + err = genl_unregister_family(&family->family); + list_del(&family->list); + return err; +} +EXPORT_SYMBOL(compat_genl_unregister_family); + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) */ diff --git a/include/linux/compat-2.6.31.h b/include/linux/compat-2.6.31.h index 6c454cb20689..d2e0f01bb910 100644 --- a/include/linux/compat-2.6.31.h +++ b/include/linux/compat-2.6.31.h @@ -114,10 +114,6 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb) return (struct rtable *)skb_dst(skb); } -extern int genl_register_family_with_ops(struct genl_family *family, - struct genl_ops *ops, size_t n_ops); - - /* Backport threaded IRQ support */ static inline diff --git a/include/linux/compat-2.6.37.h b/include/linux/compat-2.6.37.h index 7fce42aa32c6..3bb922857772 100644 --- a/include/linux/compat-2.6.37.h +++ b/include/linux/compat-2.6.37.h @@ -45,6 +45,71 @@ static inline void skb_checksum_none_assert(struct sk_buff *skb) #define pcmcia_enable_device(link) pcmcia_request_configuration(link, &link->conf) +#include + +struct compat_genl_info { + struct genl_info *info; + + u32 snd_seq; + u32 snd_pid; + struct genlmsghdr *genlhdr; + struct nlattr **attrs; + void *user_ptr[2]; +}; +#define genl_info compat_genl_info + +struct compat_genl_ops { + struct genl_ops ops; + + u8 cmd; + u8 internal_flags; + unsigned int flags; + const struct nla_policy *policy; + + int (*doit)(struct sk_buff *skb, struct genl_info *info); + int (*dumpit)(struct sk_buff *skb, struct netlink_callback *cb); + int (*done)(struct netlink_callback *cb); +}; +#define genl_ops compat_genl_ops + +struct compat_genl_family { + struct genl_family family; + + struct list_head list; + + unsigned int id, hdrsize, version, maxattr; + const char *name; + bool netnsok; + + struct nlattr **attrbuf; + + int (*pre_doit)(struct genl_ops *ops, struct sk_buff *skb, + struct genl_info *info); + + void (*post_doit)(struct genl_ops *ops, struct sk_buff *skb, + struct genl_info *info); +}; + +#define genl_family compat_genl_family + +#define genl_register_family_with_ops compat_genl_register_family_with_ops + +int genl_register_family_with_ops(struct genl_family *family, + struct genl_ops *ops, size_t n_ops); + +#define genl_unregister_family compat_genl_unregister_family + +int genl_unregister_family(struct genl_family *family); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) +#define genl_info_net(_info) genl_info_net((_info)->info) +#endif + +#define genlmsg_reply(_msg, _info) genlmsg_reply(_msg, (_info)->info) +#define genlmsg_put(_skb, _pid, _seq, _fam, _flags, _cmd) genlmsg_put(_skb, _pid, _seq, &(_fam)->family, _flags, _cmd) +#define genl_register_mc_group(_fam, _grp) genl_register_mc_group(&(_fam)->family, _grp) +#define genl_unregister_mc_group(_fam, _grp) genl_unregister_mc_group(&(_fam)->family, _grp) + #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) */ #endif /* LINUX_26_37_COMPAT_H */