diff options
Diffstat (limited to 'drivers/net/ovpn/socket.c')
-rw-r--r-- | drivers/net/ovpn/socket.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/net/ovpn/socket.c b/drivers/net/ovpn/socket.c index beec7aee35e1..f1fd98d52845 100644 --- a/drivers/net/ovpn/socket.c +++ b/drivers/net/ovpn/socket.c @@ -23,8 +23,10 @@ static void ovpn_socket_release_kref(struct kref *kref) struct ovpn_socket *sock = container_of(kref, struct ovpn_socket, refcount); - if (sock->sock->sk->sk_protocol == IPPROTO_UDP) + if (sock->sock->sk->sk_protocol == IPPROTO_UDP) { ovpn_udp_socket_detach(sock); + netdev_put(sock->ovpn->dev, &sock->dev_tracker); + } kfree_rcu(sock, rcu); } @@ -179,7 +181,6 @@ struct ovpn_socket *ovpn_socket_new(struct socket *sock, struct ovpn_peer *peer) goto sock_release; } - ovpn_sock->ovpn = peer->ovpn; ovpn_sock->sock = sock; kref_init(&ovpn_sock->refcount); @@ -190,6 +191,15 @@ struct ovpn_socket *ovpn_socket_new(struct socket *sock, struct ovpn_peer *peer) goto sock_release; } + if (sock->sk->sk_protocol == IPPROTO_UDP) { + /* in UDP we only link the ovpn instance since the socket is + * shared among multiple peers + */ + ovpn_sock->ovpn = peer->ovpn; + netdev_hold(peer->ovpn->dev, &ovpn_sock->dev_tracker, + GFP_KERNEL); + } + rcu_assign_sk_user_data(sock->sk, ovpn_sock); sock_release: release_sock(sock->sk); |