@@ -259,30 +259,30 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
259259 return iptunnel_pull_header (skb , hdrlen , skb -> protocol , xnet );
260260}
261261
262- static void gtp_encap_disable (struct gtp_dev * gtp )
262+ static void gtp_encap_destroy (struct sock * sk )
263263{
264- if (gtp -> sk0 ) {
265- udp_sk (gtp -> sk0 )-> encap_type = 0 ;
266- rcu_assign_sk_user_data (gtp -> sk0 , NULL );
267- sock_put (gtp -> sk0 );
268- }
269- if (gtp -> sk1u ) {
270- udp_sk (gtp -> sk1u )-> encap_type = 0 ;
271- rcu_assign_sk_user_data (gtp -> sk1u , NULL );
272- sock_put (gtp -> sk1u );
273- }
264+ struct gtp_dev * gtp ;
274265
275- gtp -> sk0 = NULL ;
276- gtp -> sk1u = NULL ;
266+ gtp = rcu_dereference_sk_user_data (sk );
267+ if (gtp ) {
268+ udp_sk (sk )-> encap_type = 0 ;
269+ rcu_assign_sk_user_data (sk , NULL );
270+ sock_put (sk );
271+ }
277272}
278273
279- static void gtp_encap_destroy (struct sock * sk )
274+ static void gtp_encap_disable_sock (struct sock * sk )
280275{
281- struct gtp_dev * gtp ;
276+ if (!sk )
277+ return ;
282278
283- gtp = rcu_dereference_sk_user_data (sk );
284- if (gtp )
285- gtp_encap_disable (gtp );
279+ gtp_encap_destroy (sk );
280+ }
281+
282+ static void gtp_encap_disable (struct gtp_dev * gtp )
283+ {
284+ gtp_encap_disable_sock (gtp -> sk0 );
285+ gtp_encap_disable_sock (gtp -> sk1u );
286286}
287287
288288/* UDP encapsulation receive handler. See net/ipv4/udp.c.
@@ -642,27 +642,23 @@ static void gtp_link_setup(struct net_device *dev)
642642
643643static int gtp_hashtable_new (struct gtp_dev * gtp , int hsize );
644644static void gtp_hashtable_free (struct gtp_dev * gtp );
645- static int gtp_encap_enable (struct net_device * dev , struct gtp_dev * gtp ,
646- int fd_gtp0 , int fd_gtp1 );
645+ static int gtp_encap_enable (struct gtp_dev * gtp , struct nlattr * data []);
647646
648647static int gtp_newlink (struct net * src_net , struct net_device * dev ,
649648 struct nlattr * tb [], struct nlattr * data [])
650649{
651- int hashsize , err , fd0 , fd1 ;
652650 struct gtp_dev * gtp ;
653651 struct gtp_net * gn ;
652+ int hashsize , err ;
654653
655- if (!data [IFLA_GTP_FD0 ] || !data [IFLA_GTP_FD1 ])
654+ if (!data [IFLA_GTP_FD0 ] && !data [IFLA_GTP_FD1 ])
656655 return - EINVAL ;
657656
658657 gtp = netdev_priv (dev );
659658
660- fd0 = nla_get_u32 (data [IFLA_GTP_FD0 ]);
661- fd1 = nla_get_u32 (data [IFLA_GTP_FD1 ]);
662-
663- err = gtp_encap_enable (dev , gtp , fd0 , fd1 );
659+ err = gtp_encap_enable (gtp , data );
664660 if (err < 0 )
665- goto out_err ;
661+ return err ;
666662
667663 if (!data [IFLA_GTP_PDP_HASHSIZE ])
668664 hashsize = 1024 ;
@@ -690,7 +686,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
690686 gtp_hashtable_free (gtp );
691687out_encap :
692688 gtp_encap_disable (gtp );
693- out_err :
694689 return err ;
695690}
696691
@@ -805,63 +800,76 @@ static void gtp_hashtable_free(struct gtp_dev *gtp)
805800 kfree (gtp -> tid_hash );
806801}
807802
808- static int gtp_encap_enable ( struct net_device * dev , struct gtp_dev * gtp ,
809- int fd_gtp0 , int fd_gtp1 )
803+ static struct sock * gtp_encap_enable_socket ( int fd , int type ,
804+ struct gtp_dev * gtp )
810805{
811806 struct udp_tunnel_sock_cfg tuncfg = {NULL };
812- struct socket * sock0 , * sock1u ;
807+ struct socket * sock ;
808+ struct sock * sk ;
813809 int err ;
814810
815- netdev_dbg ( dev , "enable gtp on %d, %d\n" , fd_gtp0 , fd_gtp1 );
811+ pr_debug ( "enable gtp on %d, %d\n" , fd , type );
816812
817- sock0 = sockfd_lookup (fd_gtp0 , & err );
818- if (sock0 == NULL ) {
819- netdev_dbg ( dev , " socket fd=%d not found (gtp0) \n" , fd_gtp0 );
820- return - ENOENT ;
813+ sock = sockfd_lookup (fd , & err );
814+ if (! sock ) {
815+ pr_debug ( "gtp socket fd=%d not found\n" , fd );
816+ return NULL ;
821817 }
822818
823- if (sock0 -> sk -> sk_protocol != IPPROTO_UDP ) {
824- netdev_dbg ( dev , "socket fd=%d not UDP\n" , fd_gtp0 );
825- err = - EINVAL ;
826- goto err1 ;
819+ if (sock -> sk -> sk_protocol != IPPROTO_UDP ) {
820+ pr_debug ( "socket fd=%d not UDP\n" , fd );
821+ sk = ERR_PTR ( - EINVAL ) ;
822+ goto out_sock ;
827823 }
828824
829- sock1u = sockfd_lookup (fd_gtp1 , & err );
830- if (sock1u == NULL ) {
831- netdev_dbg (dev , "socket fd=%d not found (gtp1u)\n" , fd_gtp1 );
832- err = - ENOENT ;
833- goto err1 ;
834- }
835-
836- if (sock1u -> sk -> sk_protocol != IPPROTO_UDP ) {
837- netdev_dbg (dev , "socket fd=%d not UDP\n" , fd_gtp1 );
838- err = - EINVAL ;
839- goto err2 ;
825+ if (rcu_dereference_sk_user_data (sock -> sk )) {
826+ sk = ERR_PTR (- EBUSY );
827+ goto out_sock ;
840828 }
841829
842- netdev_dbg (dev , "enable gtp on %p, %p\n" , sock0 , sock1u );
843-
844- sock_hold (sock0 -> sk );
845- gtp -> sk0 = sock0 -> sk ;
846- sock_hold (sock1u -> sk );
847- gtp -> sk1u = sock1u -> sk ;
830+ sk = sock -> sk ;
831+ sock_hold (sk );
848832
849833 tuncfg .sk_user_data = gtp ;
834+ tuncfg .encap_type = type ;
850835 tuncfg .encap_rcv = gtp_encap_recv ;
851836 tuncfg .encap_destroy = gtp_encap_destroy ;
852837
853- tuncfg .encap_type = UDP_ENCAP_GTP0 ;
854- setup_udp_tunnel_sock (sock_net (gtp -> sk0 ), sock0 , & tuncfg );
838+ setup_udp_tunnel_sock (sock_net (sock -> sk ), sock , & tuncfg );
855839
856- tuncfg .encap_type = UDP_ENCAP_GTP1U ;
857- setup_udp_tunnel_sock (sock_net (gtp -> sk1u ), sock1u , & tuncfg );
840+ out_sock :
841+ sockfd_put (sock );
842+ return sk ;
843+ }
858844
859- err = 0 ;
860- err2 :
861- sockfd_put (sock1u );
862- err1 :
863- sockfd_put (sock0 );
864- return err ;
845+ static int gtp_encap_enable (struct gtp_dev * gtp , struct nlattr * data [])
846+ {
847+ struct sock * sk1u = NULL ;
848+ struct sock * sk0 = NULL ;
849+
850+ if (data [IFLA_GTP_FD0 ]) {
851+ u32 fd0 = nla_get_u32 (data [IFLA_GTP_FD0 ]);
852+
853+ sk0 = gtp_encap_enable_socket (fd0 , UDP_ENCAP_GTP0 , gtp );
854+ if (IS_ERR (sk0 ))
855+ return PTR_ERR (sk0 );
856+ }
857+
858+ if (data [IFLA_GTP_FD1 ]) {
859+ u32 fd1 = nla_get_u32 (data [IFLA_GTP_FD1 ]);
860+
861+ sk1u = gtp_encap_enable_socket (fd1 , UDP_ENCAP_GTP1U , gtp );
862+ if (IS_ERR (sk1u )) {
863+ if (sk0 )
864+ gtp_encap_disable_sock (sk0 );
865+ return PTR_ERR (sk1u );
866+ }
867+ }
868+
869+ gtp -> sk0 = sk0 ;
870+ gtp -> sk1u = sk1u ;
871+
872+ return 0 ;
865873}
866874
867875static struct net_device * gtp_find_dev (struct net * net , int ifindex )
0 commit comments