netlink: Add new netlink_release function
authorAnjali Kulkarni <anjali.k.kulkarni@oracle.com>
Wed, 19 Jul 2023 20:18:17 +0000 (13:18 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 23 Jul 2023 10:34:22 +0000 (11:34 +0100)
A new function netlink_release is added in netlink_sock to store the
protocol's release function. This is called when the socket is deleted.
This can be supplied by the protocol via the release function in
netlink_kernel_cfg. This is being added for the NETLINK_CONNECTOR
protocol, so it can free it's data when socket is deleted.

Signed-off-by: Anjali Kulkarni <anjali.k.kulkarni@oracle.com>
Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netlink.h
net/netlink/af_netlink.c
net/netlink/af_netlink.h

index 3a6563681b50072baefcc35f4a20b8b3bb40e500..75d7de34c90874cea69471f93a47df669b0e30f0 100644 (file)
@@ -50,6 +50,7 @@ struct netlink_kernel_cfg {
        struct mutex    *cb_mutex;
        int             (*bind)(struct net *net, int group);
        void            (*unbind)(struct net *net, int group);
+       void            (*release) (struct sock *sk, unsigned long *groups);
 };
 
 struct sock *__netlink_kernel_create(struct net *net, int unit,
index 6c0bcde620e84d0a032667650520d1789600e14d..96c605e45235815a273784302d45fa7ff88e6d62 100644 (file)
@@ -677,6 +677,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
        struct netlink_sock *nlk;
        int (*bind)(struct net *net, int group);
        void (*unbind)(struct net *net, int group);
+       void (*release)(struct sock *sock, unsigned long *groups);
        int err = 0;
 
        sock->state = SS_UNCONNECTED;
@@ -704,6 +705,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
        cb_mutex = nl_table[protocol].cb_mutex;
        bind = nl_table[protocol].bind;
        unbind = nl_table[protocol].unbind;
+       release = nl_table[protocol].release;
        netlink_unlock_table();
 
        if (err < 0)
@@ -719,6 +721,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
        nlk->module = module;
        nlk->netlink_bind = bind;
        nlk->netlink_unbind = unbind;
+       nlk->netlink_release = release;
 out:
        return err;
 
@@ -763,6 +766,8 @@ static int netlink_release(struct socket *sock)
         * OK. Socket is unlinked, any packets that arrive now
         * will be purged.
         */
+       if (nlk->netlink_release)
+               nlk->netlink_release(sk, nlk->groups);
 
        /* must not acquire netlink_table_lock in any way again before unbind
         * and notifying genetlink is done as otherwise it might deadlock
@@ -2089,6 +2094,7 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module,
                if (cfg) {
                        nl_table[unit].bind = cfg->bind;
                        nl_table[unit].unbind = cfg->unbind;
+                       nl_table[unit].release = cfg->release;
                        nl_table[unit].flags = cfg->flags;
                }
                nl_table[unit].registered = 1;
index 90a3198a9b7f792ffc30e5255a9774d5bbf65df4..fd424cd63f31cf09b00398a1ca92c0e0600ac7bb 100644 (file)
@@ -42,6 +42,8 @@ struct netlink_sock {
        void                    (*netlink_rcv)(struct sk_buff *skb);
        int                     (*netlink_bind)(struct net *net, int group);
        void                    (*netlink_unbind)(struct net *net, int group);
+       void                    (*netlink_release)(struct sock *sk,
+                                                  unsigned long *groups);
        struct module           *module;
 
        struct rhash_head       node;
@@ -64,6 +66,8 @@ struct netlink_table {
        struct module           *module;
        int                     (*bind)(struct net *net, int group);
        void                    (*unbind)(struct net *net, int group);
+       void                    (*release)(struct sock *sk,
+                                          unsigned long *groups);
        int                     registered;
 };