This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
Andreas Schultz aschultz at tpip.netAdd a socket destroy handler and use it to detach and release all resources from an UDP socket. Do not longer pin the socket with a reference. This together with the release handler allows user space to close the socket from underneath us. The destroy handler will handle the rest. Signed-off-by: Andreas Schultz <aschultz at tpip.net> --- gtp.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/gtp.c b/gtp.c index 61add82..40a5d1c 100644 --- a/gtp.c +++ b/gtp.c @@ -80,6 +80,8 @@ struct gtp_net { struct list_head gtp_instance_list; }; +static void gtp_encap_disable(struct gtp_instance *gti); + static inline u32 gtp0_hashfn(u64 tid) { u32 *tid32 = (u32 *) &tid; @@ -317,6 +319,16 @@ out_rcu: return ret; } +static void gtp_udp_encap_destroy(struct sock *sk) +{ + struct gtp_instance *gti = sk_to_gti(sk); + + if (gti) { + gtp_encap_disable(gti); + sock_put(sk); + } +} + /* UDP encapsulation receive handler. See net/ipv4/udp.c. * Return codes: 0: success, <0: error, >0: passed up to userspace UDP. */ @@ -401,8 +413,6 @@ static int gtp_dev_init(struct net_device *dev) return 0; } -static void gtp_encap_disable(struct gtp_instance *gti); - static void gtp_dev_uninit(struct net_device *dev) { struct gtp_instance *gti = netdev_priv(dev); @@ -958,15 +968,18 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_instance *gti, sk = gti->sock0->sk; udp_sk(sk)->encap_type = UDP_ENCAP_GTP0; udp_sk(sk)->encap_rcv = gtp_udp_encap_recv; + udp_sk(sk)->encap_destroy = gtp_udp_encap_destroy; sk->sk_user_data = gti; udp_encap_enable(); sk = gti->sock1u->sk; udp_sk(sk)->encap_type = UDP_ENCAP_GTP1U; udp_sk(sk)->encap_rcv = gtp_udp_encap_recv; + udp_sk(sk)->encap_destroy = gtp_udp_encap_destroy; sk->sk_user_data = gti; - return 0; + err = 0; + err2: sockfd_put(sock1u); err1: @@ -976,10 +989,17 @@ err1: static void gtp_encap_disable(struct gtp_instance *gti) { - if (gti->sock1u) - sockfd_put(gti->sock1u); - if (gti->sock0) - sockfd_put(gti->sock0); + if (gti->sock0 && gti->sock0->sk) { + udp_sk(gti->sock0->sk)->encap_type = 0; + rcu_assign_sk_user_data(gti->sock0->sk, NULL); + } + if (gti->sock1u && gti->sock1u->sk) { + udp_sk(gti->sock1u->sk)->encap_type = 0; + rcu_assign_sk_user_data(gti->sock1u->sk, NULL); + } + + gti->sock0 = NULL; + gti->sock1u = NULL; } static struct net_device *gtp_find_dev(struct net *net, int ifindex) -- 2.5.0