16
16
#include <uapi/linux/fou.h>
17
17
#include <uapi/linux/genetlink.h>
18
18
19
- static DEFINE_SPINLOCK (fou_lock );
20
- static LIST_HEAD (fou_list );
21
-
22
19
struct fou {
23
20
struct socket * sock ;
24
21
u8 protocol ;
25
22
u8 flags ;
26
- u16 port ;
23
+ __be16 port ;
24
+ u16 type ;
27
25
struct udp_offload udp_offloads ;
28
26
struct list_head list ;
29
27
};
@@ -37,6 +35,13 @@ struct fou_cfg {
37
35
struct udp_port_cfg udp_config ;
38
36
};
39
37
38
+ static unsigned int fou_net_id ;
39
+
40
+ struct fou_net {
41
+ struct list_head fou_list ;
42
+ struct mutex fou_lock ;
43
+ };
44
+
40
45
static inline struct fou * fou_from_sock (struct sock * sk )
41
46
{
42
47
return sk -> sk_user_data ;
@@ -387,20 +392,21 @@ static int gue_gro_complete(struct sk_buff *skb, int nhoff,
387
392
return err ;
388
393
}
389
394
390
- static int fou_add_to_port_list (struct fou * fou )
395
+ static int fou_add_to_port_list (struct net * net , struct fou * fou )
391
396
{
397
+ struct fou_net * fn = net_generic (net , fou_net_id );
392
398
struct fou * fout ;
393
399
394
- spin_lock ( & fou_lock );
395
- list_for_each_entry (fout , & fou_list , list ) {
400
+ mutex_lock ( & fn -> fou_lock );
401
+ list_for_each_entry (fout , & fn -> fou_list , list ) {
396
402
if (fou -> port == fout -> port ) {
397
- spin_unlock ( & fou_lock );
403
+ mutex_unlock ( & fn -> fou_lock );
398
404
return - EALREADY ;
399
405
}
400
406
}
401
407
402
- list_add (& fou -> list , & fou_list );
403
- spin_unlock ( & fou_lock );
408
+ list_add (& fou -> list , & fn -> fou_list );
409
+ mutex_unlock ( & fn -> fou_lock );
404
410
405
411
return 0 ;
406
412
}
@@ -410,14 +416,10 @@ static void fou_release(struct fou *fou)
410
416
struct socket * sock = fou -> sock ;
411
417
struct sock * sk = sock -> sk ;
412
418
413
- udp_del_offload ( & fou -> udp_offloads );
414
-
419
+ if ( sk -> sk_family == AF_INET )
420
+ udp_del_offload ( & fou -> udp_offloads );
415
421
list_del (& fou -> list );
416
-
417
- /* Remove hooks into tunnel socket */
418
- sk -> sk_user_data = NULL ;
419
-
420
- sock_release (sock );
422
+ udp_tunnel_sock_release (sock );
421
423
422
424
kfree (fou );
423
425
}
@@ -447,10 +449,10 @@ static int gue_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg)
447
449
static int fou_create (struct net * net , struct fou_cfg * cfg ,
448
450
struct socket * * sockp )
449
451
{
450
- struct fou * fou = NULL ;
451
- int err ;
452
452
struct socket * sock = NULL ;
453
+ struct fou * fou = NULL ;
453
454
struct sock * sk ;
455
+ int err ;
454
456
455
457
/* Open UDP socket */
456
458
err = udp_sock_create (net , & cfg -> udp_config , & sock );
@@ -486,6 +488,8 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
486
488
goto error ;
487
489
}
488
490
491
+ fou -> type = cfg -> type ;
492
+
489
493
udp_sk (sk )-> encap_type = 1 ;
490
494
udp_encap_enable ();
491
495
@@ -502,7 +506,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
502
506
goto error ;
503
507
}
504
508
505
- err = fou_add_to_port_list (fou );
509
+ err = fou_add_to_port_list (net , fou );
506
510
if (err )
507
511
goto error ;
508
512
@@ -514,27 +518,27 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
514
518
error :
515
519
kfree (fou );
516
520
if (sock )
517
- sock_release (sock );
521
+ udp_tunnel_sock_release (sock );
518
522
519
523
return err ;
520
524
}
521
525
522
526
static int fou_destroy (struct net * net , struct fou_cfg * cfg )
523
527
{
524
- struct fou * fou ;
525
- u16 port = cfg -> udp_config .local_udp_port ;
528
+ struct fou_net * fn = net_generic ( net , fou_net_id ) ;
529
+ __be16 port = cfg -> udp_config .local_udp_port ;
526
530
int err = - EINVAL ;
531
+ struct fou * fou ;
527
532
528
- spin_lock ( & fou_lock );
529
- list_for_each_entry (fou , & fou_list , list ) {
533
+ mutex_lock ( & fn -> fou_lock );
534
+ list_for_each_entry (fou , & fn -> fou_list , list ) {
530
535
if (fou -> port == port ) {
531
- udp_del_offload (& fou -> udp_offloads );
532
536
fou_release (fou );
533
537
err = 0 ;
534
538
break ;
535
539
}
536
540
}
537
- spin_unlock ( & fou_lock );
541
+ mutex_unlock ( & fn -> fou_lock );
538
542
539
543
return err ;
540
544
}
@@ -573,7 +577,7 @@ static int parse_nl_config(struct genl_info *info,
573
577
}
574
578
575
579
if (info -> attrs [FOU_ATTR_PORT ]) {
576
- u16 port = nla_get_u16 (info -> attrs [FOU_ATTR_PORT ]);
580
+ __be16 port = nla_get_be16 (info -> attrs [FOU_ATTR_PORT ]);
577
581
578
582
cfg -> udp_config .local_udp_port = port ;
579
583
}
@@ -592,23 +596,128 @@ static int parse_nl_config(struct genl_info *info,
592
596
593
597
static int fou_nl_cmd_add_port (struct sk_buff * skb , struct genl_info * info )
594
598
{
599
+ struct net * net = genl_info_net (info );
595
600
struct fou_cfg cfg ;
596
601
int err ;
597
602
598
603
err = parse_nl_config (info , & cfg );
599
604
if (err )
600
605
return err ;
601
606
602
- return fou_create (& init_net , & cfg , NULL );
607
+ return fou_create (net , & cfg , NULL );
603
608
}
604
609
605
610
static int fou_nl_cmd_rm_port (struct sk_buff * skb , struct genl_info * info )
606
611
{
612
+ struct net * net = genl_info_net (info );
613
+ struct fou_cfg cfg ;
614
+ int err ;
615
+
616
+ err = parse_nl_config (info , & cfg );
617
+ if (err )
618
+ return err ;
619
+
620
+ return fou_destroy (net , & cfg );
621
+ }
622
+
623
+ static int fou_fill_info (struct fou * fou , struct sk_buff * msg )
624
+ {
625
+ if (nla_put_u8 (msg , FOU_ATTR_AF , fou -> sock -> sk -> sk_family ) ||
626
+ nla_put_be16 (msg , FOU_ATTR_PORT , fou -> port ) ||
627
+ nla_put_u8 (msg , FOU_ATTR_IPPROTO , fou -> protocol ) ||
628
+ nla_put_u8 (msg , FOU_ATTR_TYPE , fou -> type ))
629
+ return -1 ;
630
+
631
+ if (fou -> flags & FOU_F_REMCSUM_NOPARTIAL )
632
+ if (nla_put_flag (msg , FOU_ATTR_REMCSUM_NOPARTIAL ))
633
+ return -1 ;
634
+ return 0 ;
635
+ }
636
+
637
+ static int fou_dump_info (struct fou * fou , u32 portid , u32 seq ,
638
+ u32 flags , struct sk_buff * skb , u8 cmd )
639
+ {
640
+ void * hdr ;
641
+
642
+ hdr = genlmsg_put (skb , portid , seq , & fou_nl_family , flags , cmd );
643
+ if (!hdr )
644
+ return - ENOMEM ;
645
+
646
+ if (fou_fill_info (fou , skb ) < 0 )
647
+ goto nla_put_failure ;
648
+
649
+ genlmsg_end (skb , hdr );
650
+ return 0 ;
651
+
652
+ nla_put_failure :
653
+ genlmsg_cancel (skb , hdr );
654
+ return - EMSGSIZE ;
655
+ }
656
+
657
+ static int fou_nl_cmd_get_port (struct sk_buff * skb , struct genl_info * info )
658
+ {
659
+ struct net * net = genl_info_net (info );
660
+ struct fou_net * fn = net_generic (net , fou_net_id );
661
+ struct sk_buff * msg ;
607
662
struct fou_cfg cfg ;
663
+ struct fou * fout ;
664
+ __be16 port ;
665
+ int ret ;
666
+
667
+ ret = parse_nl_config (info , & cfg );
668
+ if (ret )
669
+ return ret ;
670
+ port = cfg .udp_config .local_udp_port ;
671
+ if (port == 0 )
672
+ return - EINVAL ;
673
+
674
+ msg = nlmsg_new (NLMSG_DEFAULT_SIZE , GFP_KERNEL );
675
+ if (!msg )
676
+ return - ENOMEM ;
677
+
678
+ ret = - ESRCH ;
679
+ mutex_lock (& fn -> fou_lock );
680
+ list_for_each_entry (fout , & fn -> fou_list , list ) {
681
+ if (port == fout -> port ) {
682
+ ret = fou_dump_info (fout , info -> snd_portid ,
683
+ info -> snd_seq , 0 , msg ,
684
+ info -> genlhdr -> cmd );
685
+ break ;
686
+ }
687
+ }
688
+ mutex_unlock (& fn -> fou_lock );
689
+ if (ret < 0 )
690
+ goto out_free ;
608
691
609
- parse_nl_config ( info , & cfg );
692
+ return genlmsg_reply ( msg , info );
610
693
611
- return fou_destroy (& init_net , & cfg );
694
+ out_free :
695
+ nlmsg_free (msg );
696
+ return ret ;
697
+ }
698
+
699
+ static int fou_nl_dump (struct sk_buff * skb , struct netlink_callback * cb )
700
+ {
701
+ struct net * net = sock_net (skb -> sk );
702
+ struct fou_net * fn = net_generic (net , fou_net_id );
703
+ struct fou * fout ;
704
+ int idx = 0 , ret ;
705
+
706
+ mutex_lock (& fn -> fou_lock );
707
+ list_for_each_entry (fout , & fn -> fou_list , list ) {
708
+ if (idx ++ < cb -> args [0 ])
709
+ continue ;
710
+ ret = fou_dump_info (fout , NETLINK_CB (cb -> skb ).portid ,
711
+ cb -> nlh -> nlmsg_seq , NLM_F_MULTI ,
712
+ skb , FOU_CMD_GET );
713
+ if (ret )
714
+ goto done ;
715
+ }
716
+ mutex_unlock (& fn -> fou_lock );
717
+
718
+ done :
719
+ cb -> args [0 ] = idx ;
720
+ return skb -> len ;
612
721
}
613
722
614
723
static const struct genl_ops fou_nl_ops [] = {
@@ -624,6 +733,12 @@ static const struct genl_ops fou_nl_ops[] = {
624
733
.policy = fou_nl_policy ,
625
734
.flags = GENL_ADMIN_PERM ,
626
735
},
736
+ {
737
+ .cmd = FOU_CMD_GET ,
738
+ .doit = fou_nl_cmd_get_port ,
739
+ .dumpit = fou_nl_dump ,
740
+ .policy = fou_nl_policy ,
741
+ },
627
742
};
628
743
629
744
size_t fou_encap_hlen (struct ip_tunnel_encap * e )
@@ -820,38 +935,63 @@ static void ip_tunnel_encap_del_fou_ops(void)
820
935
821
936
#endif
822
937
938
+ static __net_init int fou_init_net (struct net * net )
939
+ {
940
+ struct fou_net * fn = net_generic (net , fou_net_id );
941
+
942
+ INIT_LIST_HEAD (& fn -> fou_list );
943
+ mutex_init (& fn -> fou_lock );
944
+ return 0 ;
945
+ }
946
+
947
+ static __net_exit void fou_exit_net (struct net * net )
948
+ {
949
+ struct fou_net * fn = net_generic (net , fou_net_id );
950
+ struct fou * fou , * next ;
951
+
952
+ /* Close all the FOU sockets */
953
+ mutex_lock (& fn -> fou_lock );
954
+ list_for_each_entry_safe (fou , next , & fn -> fou_list , list )
955
+ fou_release (fou );
956
+ mutex_unlock (& fn -> fou_lock );
957
+ }
958
+
959
+ static struct pernet_operations fou_net_ops = {
960
+ .init = fou_init_net ,
961
+ .exit = fou_exit_net ,
962
+ .id = & fou_net_id ,
963
+ .size = sizeof (struct fou_net ),
964
+ };
965
+
823
966
static int __init fou_init (void )
824
967
{
825
968
int ret ;
826
969
970
+ ret = register_pernet_device (& fou_net_ops );
971
+ if (ret )
972
+ goto exit ;
973
+
827
974
ret = genl_register_family_with_ops (& fou_nl_family ,
828
975
fou_nl_ops );
829
-
830
976
if (ret < 0 )
831
- goto exit ;
977
+ goto unregister ;
832
978
833
979
ret = ip_tunnel_encap_add_fou_ops ();
834
- if (ret < 0 )
835
- genl_unregister_family ( & fou_nl_family ) ;
980
+ if (ret == 0 )
981
+ return 0 ;
836
982
983
+ genl_unregister_family (& fou_nl_family );
984
+ unregister :
985
+ unregister_pernet_device (& fou_net_ops );
837
986
exit :
838
987
return ret ;
839
988
}
840
989
841
990
static void __exit fou_fini (void )
842
991
{
843
- struct fou * fou , * next ;
844
-
845
992
ip_tunnel_encap_del_fou_ops ();
846
-
847
993
genl_unregister_family (& fou_nl_family );
848
-
849
- /* Close all the FOU sockets */
850
-
851
- spin_lock (& fou_lock );
852
- list_for_each_entry_safe (fou , next , & fou_list , list )
853
- fou_release (fou );
854
- spin_unlock (& fou_lock );
994
+ unregister_pernet_device (& fou_net_ops );
855
995
}
856
996
857
997
module_init (fou_init );
0 commit comments