genetlink: make netns aware
authorJohannes Berg <johannes@sipsolutions.net>
Fri, 10 Jul 2009 09:51:34 +0000 (09:51 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 12 Jul 2009 21:03:27 +0000 (14:03 -0700)
This makes generic netlink network namespace aware. No
generic netlink families except for the controller family
are made namespace aware, they need to be checked one by
one and then set the family->netnsok member to true.

A new function genlmsg_multicast_netns() is introduced to
allow sending a multicast message in a given namespace,
for example when it applies to an object that lives in
that namespace, a new function genlmsg_multicast_allns()
to send a message to all network namespaces (for objects
that do not have an associated netns).

The function genlmsg_multicast() is changed to multicast
the message in just init_net, which is currently correct
for all generic netlink families since they only work in
init_net right now. Some will later want to work in all
net namespaces because they do not care about the netns
at all -- those will have to be converted to use one of
the new functions genlmsg_multicast_allns() or
genlmsg_multicast_netns() whenever they are made netns
aware in some way.

After this patch families can easily decide whether or
not they should be available in all net namespaces. Many
genl families us it for objects not related to networking
and should therefore be available in all namespaces, but
that will have to be done on a per family basis.

Note that this doesn't touch on the checkpoint/restart
problem where network namespaces could be used, genl
families and multicast groups are numbered globally and
I see no easy way of changing that, especially since it
must be possible to multicast to all network namespaces
for those families that do not care about netns.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
fs/dlm/netlink.c
include/net/genetlink.h
include/net/net_namespace.h
kernel/taskstats.c
net/irda/irnetlink.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netlink/genetlink.c
net/tipc/netlink.c
net/wireless/nl80211.c

index ccc9d62c462d940c156c42c6c99518261edb4603..55ea369f43a9f0d153ca769074b89e71d52082cf 100644 (file)
@@ -63,7 +63,7 @@ static int send_data(struct sk_buff *skb)
                return rv;
        }
 
-       return genlmsg_unicast(skb, listener_nlpid);
+       return genlmsg_unicast(&init_net, skb, listener_nlpid);
 }
 
 static int user_cmd(struct sk_buff *skb, struct genl_info *info)
index 1b0e3ee4ddd84dbe31250710395c17c34a9ebc8c..2a1c06874c42f212970513f585d248c148b58281 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/genetlink.h>
 #include <net/netlink.h>
+#include <net/net_namespace.h>
 
 /**
  * struct genl_multicast_group - generic netlink multicast group
@@ -27,6 +28,8 @@ struct genl_multicast_group
  * @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
@@ -39,6 +42,7 @@ struct genl_family
        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 */
@@ -62,8 +66,32 @@ struct genl_info
        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
@@ -98,8 +126,6 @@ extern int genl_register_mc_group(struct genl_family *family,
 extern void genl_unregister_mc_group(struct genl_family *family,
                                     struct genl_multicast_group *grp);
 
-extern struct sock *genl_sock;
-
 /**
  * genlmsg_put - Add generic netlink header to netlink message
  * @skb: socket buffer holding the message
@@ -170,7 +196,21 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
 }
 
 /**
- * genlmsg_multicast - multicast a netlink message
+ * 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_multicast(net->genl_sock, skb, pid, group, flags);
+}
+
+/**
+ * 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
@@ -179,17 +219,29 @@ static inline void 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);
 }
 
 /**
@@ -199,7 +251,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);
 }
 
 /**
index b34a6ee73754c857fac757d0fd65aefa4675b699..3173d12d946b2323b0c577e9db4df32f4b4cca9d 100644 (file)
@@ -26,6 +26,7 @@ struct net_device;
 struct sock;
 struct ctl_table_header;
 struct net_generic;
+struct sock;
 
 struct net {
        atomic_t                count;          /* To decided when the network
@@ -57,6 +58,7 @@ struct net {
        spinlock_t              rules_mod_lock;
 
        struct sock             *rtnl;                  /* rtnetlink socket */
+       struct sock             *genl_sock;
 
        struct netns_core       core;
        struct netns_mib        mib;
index 888adbcca30c17c2db3922351a9ef8c9939a2d64..ea8384d3caa7a0fc4f58a70f66faf4d2000c6c6d 100644 (file)
@@ -108,7 +108,7 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
 /*
  * Send taskstats data in @skb to listener with nl_pid @pid
  */
-static int send_reply(struct sk_buff *skb, pid_t pid)
+static int send_reply(struct sk_buff *skb, struct genl_info *info)
 {
        struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
        void *reply = genlmsg_data(genlhdr);
@@ -120,7 +120,7 @@ static int send_reply(struct sk_buff *skb, pid_t pid)
                return rc;
        }
 
-       return genlmsg_unicast(skb, pid);
+       return genlmsg_reply(skb, info);
 }
 
 /*
@@ -150,7 +150,7 @@ static void send_cpu_listeners(struct sk_buff *skb,
                        if (!skb_next)
                                break;
                }
-               rc = genlmsg_unicast(skb_cur, s->pid);
+               rc = genlmsg_unicast(&init_net, skb_cur, s->pid);
                if (rc == -ECONNREFUSED) {
                        s->valid = 0;
                        delcount++;
@@ -418,7 +418,7 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
                goto err;
        }
 
-       rc = send_reply(rep_skb, info->snd_pid);
+       rc = send_reply(rep_skb, info);
 
 err:
        fput_light(file, fput_needed);
@@ -487,7 +487,7 @@ free_return_rc:
        } else
                goto err;
 
-       return send_reply(rep_skb, info->snd_pid);
+       return send_reply(rep_skb, info);
 err:
        nlmsg_free(rep_skb);
        return rc;
index 8dd7ed7e7c1fa184d18a2eb711194e90a7495f76..476b307bd801e7cf281c9a255dd13036dd36fb7c 100644 (file)
@@ -115,7 +115,7 @@ static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info)
 
        genlmsg_end(msg, hdr);
 
-       return genlmsg_unicast(msg, info->snd_pid);
+       return genlmsg_reply(msg, info);
 
  err_out:
        nlmsg_free(msg);
index 7c1333c67ff3d5f810540eea5f774fc6582030dd..2d24d81474ce04826b680a49ca53696680499be4 100644 (file)
@@ -3231,7 +3231,7 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info)
        }
 
        genlmsg_end(msg, reply);
-       ret = genlmsg_unicast(msg, info->snd_pid);
+       ret = genlmsg_reply(msg, info);
        goto out;
 
 nla_put_failure:
index eed4c6a8afc0256fb6c3e1e267da6ca21233e823..575c64341508eb12119eb120349de4704525648a 100644 (file)
@@ -18,8 +18,6 @@
 #include <net/sock.h>
 #include <net/genetlink.h>
 
-struct sock *genl_sock = NULL;
-
 static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */
 
 static inline void genl_lock(void)
@@ -175,10 +173,31 @@ int genl_register_mc_group(struct genl_family *family,
                mc_groups_longs++;
        }
 
-       err = netlink_change_ngroups(genl_sock,
-                                    mc_groups_longs * BITS_PER_LONG);
-       if (err)
-               goto out;
+       if (family->netnsok) {
+               struct net *net;
+
+               rcu_read_lock();
+               for_each_net_rcu(net) {
+                       err = netlink_change_ngroups(net->genl_sock,
+                                       mc_groups_longs * BITS_PER_LONG);
+                       if (err) {
+                               /*
+                                * No need to roll back, can only fail if
+                                * memory allocation fails and then the
+                                * number of _possible_ groups has been
+                                * increased on some sockets which is ok.
+                                */
+                               rcu_read_unlock();
+                               goto out;
+                       }
+               }
+               rcu_read_unlock();
+       } else {
+               err = netlink_change_ngroups(init_net.genl_sock,
+                                            mc_groups_longs * BITS_PER_LONG);
+               if (err)
+                       goto out;
+       }
 
        grp->id = id;
        set_bit(id, mc_groups);
@@ -195,8 +214,14 @@ EXPORT_SYMBOL(genl_register_mc_group);
 static void __genl_unregister_mc_group(struct genl_family *family,
                                       struct genl_multicast_group *grp)
 {
+       struct net *net;
        BUG_ON(grp->family != family);
-       netlink_clear_multicast_users(genl_sock, grp->id);
+
+       rcu_read_lock();
+       for_each_net_rcu(net)
+               netlink_clear_multicast_users(net->genl_sock, grp->id);
+       rcu_read_unlock();
+
        clear_bit(grp->id, mc_groups);
        list_del(&grp->list);
        genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp);
@@ -467,6 +492,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
        struct genl_ops *ops;
        struct genl_family *family;
+       struct net *net = sock_net(skb->sk);
        struct genl_info info;
        struct genlmsghdr *hdr = nlmsg_data(nlh);
        int hdrlen, err;
@@ -475,6 +501,10 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        if (family == NULL)
                return -ENOENT;
 
+       /* this family doesn't exist in this netns */
+       if (!family->netnsok && !net_eq(net, &init_net))
+               return -ENOENT;
+
        hdrlen = GENL_HDRLEN + family->hdrsize;
        if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
                return -EINVAL;
@@ -492,7 +522,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        return -EOPNOTSUPP;
 
                genl_unlock();
-               err = netlink_dump_start(genl_sock, skb, nlh,
+               err = netlink_dump_start(net->genl_sock, skb, nlh,
                                         ops->dumpit, ops->done);
                genl_lock();
                return err;
@@ -514,6 +544,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        info.genlhdr = nlmsg_data(nlh);
        info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
        info.attrs = family->attrbuf;
+       genl_info_net_set(&info, net);
 
        return ops->doit(skb, &info);
 }
@@ -534,6 +565,7 @@ static struct genl_family genl_ctrl = {
        .name = "nlctrl",
        .version = 0x2,
        .maxattr = CTRL_ATTR_MAX,
+       .netnsok = true,
 };
 
 static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
@@ -650,6 +682,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
 
        int i, n = 0;
        struct genl_family *rt;
+       struct net *net = sock_net(skb->sk);
        int chains_to_skip = cb->args[0];
        int fams_to_skip = cb->args[1];
 
@@ -658,6 +691,8 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
                        continue;
                n = 0;
                list_for_each_entry(rt, genl_family_chain(i), family_list) {
+                       if (!rt->netnsok && !net_eq(net, &init_net))
+                               continue;
                        if (++n < fams_to_skip)
                                continue;
                        if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).pid,
@@ -729,6 +764,7 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[CTRL_ATTR_FAMILY_ID]) {
                u16 id = nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]);
                res = genl_family_find_byid(id);
+               err = -ENOENT;
        }
 
        if (info->attrs[CTRL_ATTR_FAMILY_NAME]) {
@@ -736,49 +772,61 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
 
                name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]);
                res = genl_family_find_byname(name);
+               err = -ENOENT;
        }
 
-       if (res == NULL) {
-               err = -ENOENT;
-               goto errout;
+       if (res == NULL)
+               return err;
+
+       if (!res->netnsok && !net_eq(genl_info_net(info), &init_net)) {
+               /* family doesn't exist here */
+               return -ENOENT;
        }
 
        msg = ctrl_build_family_msg(res, info->snd_pid, info->snd_seq,
                                    CTRL_CMD_NEWFAMILY);
-       if (IS_ERR(msg)) {
-               err = PTR_ERR(msg);
-               goto errout;
-       }
+       if (IS_ERR(msg))
+               return PTR_ERR(msg);
 
-       err = genlmsg_reply(msg, info);
-errout:
-       return err;
+       return genlmsg_reply(msg, info);
 }
 
 static int genl_ctrl_event(int event, void *data)
 {
        struct sk_buff *msg;
+       struct genl_family *family;
+       struct genl_multicast_group *grp;
 
-       if (genl_sock == NULL)
+       /* genl is still initialising */
+       if (!init_net.genl_sock)
                return 0;
 
        switch (event) {
        case CTRL_CMD_NEWFAMILY:
        case CTRL_CMD_DELFAMILY:
-               msg = ctrl_build_family_msg(data, 0, 0, event);
-               if (IS_ERR(msg))
-                       return PTR_ERR(msg);
-
-               genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);
+               family = data;
+               msg = ctrl_build_family_msg(family, 0, 0, event);
                break;
        case CTRL_CMD_NEWMCAST_GRP:
        case CTRL_CMD_DELMCAST_GRP:
+               grp = data;
+               family = grp->family;
                msg = ctrl_build_mcgrp_msg(data, 0, 0, event);
-               if (IS_ERR(msg))
-                       return PTR_ERR(msg);
-
-               genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);
                break;
+       default:
+               return -EINVAL;
+       }
+
+       if (IS_ERR(msg))
+               return PTR_ERR(msg);
+
+       if (!family->netnsok) {
+               genlmsg_multicast_netns(&init_net, msg, 0,
+                                       GENL_ID_CTRL, GFP_KERNEL);
+       } else {
+               rcu_read_lock();
+               genlmsg_multicast_allns(msg, 0, GENL_ID_CTRL, GFP_ATOMIC);
+               rcu_read_unlock();
        }
 
        return 0;
@@ -795,6 +843,33 @@ static struct genl_multicast_group notify_grp = {
        .name           = "notify",
 };
 
+static int __net_init genl_pernet_init(struct net *net)
+{
+       /* we'll bump the group number right afterwards */
+       net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, 0,
+                                              genl_rcv, &genl_mutex,
+                                              THIS_MODULE);
+
+       if (!net->genl_sock && net_eq(net, &init_net))
+               panic("GENL: Cannot initialize generic netlink\n");
+
+       if (!net->genl_sock)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void __net_exit genl_pernet_exit(struct net *net)
+{
+       netlink_kernel_release(net->genl_sock);
+       net->genl_sock = NULL;
+}
+
+static struct pernet_operations genl_pernet_ops = {
+       .init = genl_pernet_init,
+       .exit = genl_pernet_exit,
+};
+
 static int __init genl_init(void)
 {
        int i, err;
@@ -804,36 +879,67 @@ static int __init genl_init(void)
 
        err = genl_register_family(&genl_ctrl);
        if (err < 0)
-               goto errout;
+               goto problem;
 
        err = genl_register_ops(&genl_ctrl, &genl_ctrl_ops);
        if (err < 0)
-               goto errout_register;
+               goto problem;
 
        netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);
 
-       /* we'll bump the group number right afterwards */
-       genl_sock = netlink_kernel_create(&init_net, NETLINK_GENERIC, 0,
-                                         genl_rcv, &genl_mutex, THIS_MODULE);
-       if (genl_sock == NULL)
-               panic("GENL: Cannot initialize generic netlink\n");
+       err = register_pernet_subsys(&genl_pernet_ops);
+       if (err)
+               goto problem;
 
        err = genl_register_mc_group(&genl_ctrl, &notify_grp);
        if (err < 0)
-               goto errout_register;
+               goto problem;
 
        return 0;
 
-errout_register:
-       genl_unregister_family(&genl_ctrl);
-errout:
+problem:
        panic("GENL: Cannot register controller: %d\n", err);
 }
 
 subsys_initcall(genl_init);
 
-EXPORT_SYMBOL(genl_sock);
 EXPORT_SYMBOL(genl_register_ops);
 EXPORT_SYMBOL(genl_unregister_ops);
 EXPORT_SYMBOL(genl_register_family);
 EXPORT_SYMBOL(genl_unregister_family);
+
+static int genlmsg_mcast(struct sk_buff *skb, u32 pid, unsigned long group,
+                        gfp_t flags)
+{
+       struct sk_buff *tmp;
+       struct net *net, *prev = NULL;
+       int err;
+
+       for_each_net_rcu(net) {
+               if (prev) {
+                       tmp = skb_clone(skb, flags);
+                       if (!tmp) {
+                               err = -ENOMEM;
+                               goto error;
+                       }
+                       err = nlmsg_multicast(prev->genl_sock, tmp,
+                                             pid, group, flags);
+                       if (err)
+                               goto error;
+               }
+
+               prev = net;
+       }
+
+       return nlmsg_multicast(prev->genl_sock, skb, pid, group, flags);
+ error:
+       kfree_skb(skb);
+       return err;
+}
+
+int genlmsg_multicast_allns(struct sk_buff *skb, u32 pid, unsigned int group,
+                           gfp_t flags)
+{
+       return genlmsg_mcast(skb, pid, group, flags);
+}
+EXPORT_SYMBOL(genlmsg_multicast_allns);
index 3c57005e44d1cd060e17d8e13ae93a1d75b65315..7bda8e3d1398937d83cf7a92e5477030826ed554 100644 (file)
@@ -62,7 +62,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
                rep_nlh = nlmsg_hdr(rep_buf);
                memcpy(rep_nlh, req_nlh, hdr_space);
                rep_nlh->nlmsg_len = rep_buf->len;
-               genlmsg_unicast(rep_buf, NETLINK_CB(skb).pid);
+               genlmsg_unicast(&init_net, rep_buf, NETLINK_CB(skb).pid);
        }
 
        return 0;
index 9deb12f73c448f6e1f914ac299e04aa3a93494df..2a04beba436933c4a3a81552ccbc52bb0528b9ee 100644 (file)
@@ -413,7 +413,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
 
        cfg80211_unlock_rdev(dev);
 
-       return genlmsg_unicast(msg, info->snd_pid);
+       return genlmsg_reply(msg, info);
 
  out_free:
        nlmsg_free(msg);
@@ -739,7 +739,7 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
        dev_put(netdev);
        cfg80211_unlock_rdev(dev);
 
-       return genlmsg_unicast(msg, info->snd_pid);
+       return genlmsg_reply(msg, info);
 
  out_free:
        nlmsg_free(msg);
@@ -1030,7 +1030,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
                goto nla_put_failure;
 
        genlmsg_end(msg, hdr);
-       err = genlmsg_unicast(msg, info->snd_pid);
+       err = genlmsg_reply(msg, info);
        goto out;
 
  nla_put_failure:
@@ -1618,7 +1618,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
                                 dev, mac_addr, &sinfo) < 0)
                goto out_free;
 
-       err = genlmsg_unicast(msg, info->snd_pid);
+       err = genlmsg_reply(msg, info);
        goto out;
 
  out_free:
@@ -2087,7 +2087,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
                                 dev, dst, next_hop, &pinfo) < 0)
                goto out_free;
 
-       err = genlmsg_unicast(msg, info->snd_pid);
+       err = genlmsg_reply(msg, info);
        goto out;
 
  out_free:
@@ -2436,7 +2436,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
                        cur_params.dot11MeshHWMPnetDiameterTraversalTime);
        nla_nest_end(msg, pinfoattr);
        genlmsg_end(msg, hdr);
-       err = genlmsg_unicast(msg, info->snd_pid);
+       err = genlmsg_reply(msg, info);
        goto out;
 
  nla_put_failure:
@@ -2624,7 +2624,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
        nla_nest_end(msg, nl_reg_rules);
 
        genlmsg_end(msg, hdr);
-       err = genlmsg_unicast(msg, info->snd_pid);
+       err = genlmsg_reply(msg, info);
        goto out;
 
 nla_put_failure: