V4L/DVB: saa7134: add code to allow changing IR protocol
[safe/jmp/linux-2.6] / include / net / genetlink.h
index b6eaca1..eb551ba 100644 (file)
@@ -3,6 +3,22 @@
 
 #include <linux/genetlink.h>
 #include <net/netlink.h>
+#include <net/net_namespace.h>
+
+/**
+ * struct genl_multicast_group - generic netlink multicast group
+ * @name: name of the multicast group, names are per-family
+ * @id: multicast group ID, assigned by the core, to use with
+ *      genlmsg_multicast().
+ * @list: list entry for linking
+ * @family: pointer to family, need not be set before registering
+ */
+struct genl_multicast_group {
+       struct genl_family      *family;        /* private */
+       struct list_head        list;           /* private */
+       char                    name[GENL_NAMSIZ];
+       u32                     id;
+};
 
 /**
  * struct genl_family - generic netlink family
  * @name: name of family
  * @version: protocol version
  * @maxattr: maximum number of attributes supported
+ * @netnsok: set to true if the family can handle network
+ *     namespaces and should be presented in all of them
  * @attrbuf: buffer to store parsed attributes
  * @ops_list: list of all assigned operations
  * @family_list: family list
+ * @mcast_groups: multicast groups list
  */
-struct genl_family
-{
+struct genl_family {
        unsigned int            id;
        unsigned int            hdrsize;
        char                    name[GENL_NAMSIZ];
        unsigned int            version;
        unsigned int            maxattr;
+       bool                    netnsok;
        struct nlattr **        attrbuf;        /* private */
        struct list_head        ops_list;       /* private */
        struct list_head        family_list;    /* private */
+       struct list_head        mcast_groups;   /* private */
 };
 
 /**
@@ -36,16 +56,39 @@ struct genl_family
  * @userhdr: user specific header
  * @attrs: netlink attributes
  */
-struct genl_info
-{
+struct genl_info {
        u32                     snd_seq;
        u32                     snd_pid;
        struct nlmsghdr *       nlhdr;
        struct genlmsghdr *     genlhdr;
        void *                  userhdr;
        struct nlattr **        attrs;
+#ifdef CONFIG_NET_NS
+       struct net *            _net;
+#endif
 };
 
+#ifdef CONFIG_NET_NS
+static inline struct net *genl_info_net(struct genl_info *info)
+{
+       return info->_net;
+}
+
+static inline void genl_info_net_set(struct genl_info *info, struct net *net)
+{
+       info->_net = net;
+}
+#else
+static inline struct net *genl_info_net(struct genl_info *info)
+{
+       return &init_net;
+}
+
+static inline void genl_info_net_set(struct genl_info *info, struct net *net)
+{
+}
+#endif
+
 /**
  * struct genl_ops - generic netlink operations
  * @cmd: command identifier
@@ -56,8 +99,7 @@ struct genl_info
  * @done: completion callback for dumps
  * @ops_list: operations list
  */
-struct genl_ops
-{
+struct genl_ops {
        u8                      cmd;
        unsigned int            flags;
        const struct nla_policy *policy;
@@ -70,11 +112,15 @@ struct genl_ops
 };
 
 extern int genl_register_family(struct genl_family *family);
+extern int genl_register_family_with_ops(struct genl_family *family,
+       struct genl_ops *ops, size_t n_ops);
 extern int genl_unregister_family(struct genl_family *family);
 extern int genl_register_ops(struct genl_family *, struct genl_ops *ops);
 extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops);
-
-extern struct sock *genl_sock;
+extern int genl_register_mc_group(struct genl_family *family,
+                                 struct genl_multicast_group *grp);
+extern void genl_unregister_mc_group(struct genl_family *family,
+                                    struct genl_multicast_group *grp);
 
 /**
  * genlmsg_put - Add generic netlink header to netlink message
@@ -140,13 +186,27 @@ static inline int genlmsg_end(struct sk_buff *skb, void *hdr)
  * @skb: socket buffer the message is stored in
  * @hdr: generic netlink message header
  */
-static inline int genlmsg_cancel(struct sk_buff *skb, void *hdr)
+static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
+{
+       nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
+}
+
+/**
+ * genlmsg_multicast_netns - multicast a netlink message to a specific netns
+ * @net: the net namespace
+ * @skb: netlink message as socket buffer
+ * @pid: own netlink pid to avoid sending to yourself
+ * @group: multicast group id
+ * @flags: allocation flags
+ */
+static inline int genlmsg_multicast_netns(struct net *net, struct sk_buff *skb,
+                                         u32 pid, unsigned int group, gfp_t flags)
 {
-       return nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
+       return nlmsg_multicast(net->genl_sock, skb, pid, group, flags);
 }
 
 /**
- * genlmsg_multicast - multicast a netlink message
+ * genlmsg_multicast - multicast a netlink message to the default netns
  * @skb: netlink message as socket buffer
  * @pid: own netlink pid to avoid sending to yourself
  * @group: multicast group id
@@ -155,17 +215,29 @@ static inline int genlmsg_cancel(struct sk_buff *skb, void *hdr)
 static inline int genlmsg_multicast(struct sk_buff *skb, u32 pid,
                                    unsigned int group, gfp_t flags)
 {
-       return nlmsg_multicast(genl_sock, skb, pid, group, flags);
+       return genlmsg_multicast_netns(&init_net, skb, pid, group, flags);
 }
 
 /**
+ * genlmsg_multicast_allns - multicast a netlink message to all net namespaces
+ * @skb: netlink message as socket buffer
+ * @pid: own netlink pid to avoid sending to yourself
+ * @group: multicast group id
+ * @flags: allocation flags
+ *
+ * This function must hold the RTNL or rcu_read_lock().
+ */
+int genlmsg_multicast_allns(struct sk_buff *skb, u32 pid,
+                           unsigned int group, gfp_t flags);
+
+/**
  * genlmsg_unicast - unicast a netlink message
  * @skb: netlink message as socket buffer
  * @pid: netlink pid of the destination socket
  */
-static inline int genlmsg_unicast(struct sk_buff *skb, u32 pid)
+static inline int genlmsg_unicast(struct net *net, struct sk_buff *skb, u32 pid)
 {
-       return nlmsg_unicast(genl_sock, skb, pid);
+       return nlmsg_unicast(net->genl_sock, skb, pid);
 }
 
 /**
@@ -175,7 +247,7 @@ static inline int genlmsg_unicast(struct sk_buff *skb, u32 pid)
  */
 static inline int genlmsg_reply(struct sk_buff *skb, struct genl_info *info)
 {
-       return genlmsg_unicast(skb, info->snd_pid);
+       return genlmsg_unicast(genl_info_net(info), skb, info->snd_pid);
 }
 
 /**