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 v4] compat: backport netlink changes used in the nl80211 cleanup
Date: Thu, 07 Oct 2010 21:56:38 +0200	[thread overview]
Message-ID: <4CAE25F6.2010707@openwrt.org> (raw)
In-Reply-To: <4CADC341.40305@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
v4:
- remove old genl_register_family_with_ops implementation
- fix genl_info_net redefinition
tested on 2.6.30

--- 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_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);
+
+#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 */
--- 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) */
--- a/compat/compat-2.6.31.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2007	Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
- *
- * 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 <linux/compat.h>
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
-
-#include <linux/netdevice.h>
-
-/**
- * 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)) */
-
--- 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(
 	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
--- a/compat/Makefile
+++ b/compat/Makefile
@@ -23,7 +23,6 @@ compat-$(CONFIG_COMPAT_KERNEL_27) += com
 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

  parent reply	other threads:[~2010-10-07 19:56 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   ` [PATCH v3] " Felix Fietkau
2010-10-07 18:39     ` Johannes Berg
2010-10-07 19:56     ` Felix Fietkau [this message]
2010-10-07 21:48       ` [PATCH v4] " 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=4CAE25F6.2010707@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.