summaryrefslogtreecommitdiff
path: root/drivers/net/ovpn/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ovpn/socket.c')
-rw-r--r--drivers/net/ovpn/socket.c14
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);