All of lore.kernel.org
 help / color / mirror / Atom feed
From: Felix Fietkau <nbd@openwrt.org>
To: "Luis R. Rodriguez" <lrodriguez@atheros.com>
Cc: linux-wireless <linux-wireless@vger.kernel.org>
Subject: [PATCH v3] compat: backport netlink changes used in the nl80211 cleanup
Date: Thu, 07 Oct 2010 14:55:29 +0200	[thread overview]
Message-ID: <4CADC341.40305@openwrt.org> (raw)
In-Reply-To: <4CADC142.7010709@openwrt.org>

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
v2:
- fix genl_unregister_family wrapper (removes the family from the internal list)
- fix error handling in doit ops
v3:
- fix a theoretical race in family unregister

--- a/include/linux/compat-2.6.37.h
+++ b/include/linux/compat-2.6.37.h
@@ -45,6 +45,68 @@ static inline void skb_checksum_none_ass
 
 #define pcmcia_enable_device(link)	pcmcia_request_configuration(link, &link->conf)
 
+#include <net/genetlink.h>
+
+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);
+
+#define genl_info_net(_info) genl_info_net((_info)->info)
+#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 */
--- 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) */

  reply	other threads:[~2010-10-07 12:55 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-07 11:59 [PATCH] compat: backport netlink changes used in the nl80211 cleanup Felix Fietkau
2010-10-07 12:46 ` [PATCH v2] " Felix Fietkau
2010-10-07 12:55   ` Felix Fietkau [this message]
2010-10-07 18:39     ` [PATCH v3] " Johannes Berg
2010-10-07 19:56     ` [PATCH v4] " Felix Fietkau
2010-10-07 21:48       ` Luis R. Rodriguez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4CADC341.40305@openwrt.org \
    --to=nbd@openwrt.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=lrodriguez@atheros.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.