11/*
22 * gw.c - CAN frame Gateway/Router/Bridge with netlink interface
33 *
4- * Copyright (c) 2011 Volkswagen Group Electronic Research
4+ * Copyright (c) 2017 Volkswagen Group Electronic Research
55 * All rights reserved.
66 *
77 * Redistribution and use in source and binary forms, with or without
5959#include <net/net_namespace.h>
6060#include <net/sock.h>
6161
62- #define CAN_GW_VERSION "20130117 "
62+ #define CAN_GW_VERSION "20170425 "
6363#define CAN_GW_NAME "can-gw"
6464
6565MODULE_DESCRIPTION ("PF_CAN netlink gateway" );
@@ -79,9 +79,7 @@ MODULE_PARM_DESC(max_hops,
7979 __stringify (CGW_MAX_HOPS ) " hops, "
8080 "default: " __stringify (CGW_DEFAULT_HOPS ) ")" );
8181
82- static HLIST_HEAD (cgw_list );
8382static struct notifier_block notifier ;
84-
8583static struct kmem_cache * cgw_cache __read_mostly ;
8684
8785/* structure that contains the (on-the-fly) CAN frame modifications */
@@ -438,26 +436,25 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
438436 gwj -> handled_frames ++ ;
439437}
440438
441- static inline int cgw_register_filter (struct cgw_job * gwj )
439+ static inline int cgw_register_filter (struct net * net , struct cgw_job * gwj )
442440{
443- return can_rx_register (& init_net , gwj -> src .dev , gwj -> ccgw .filter .can_id ,
441+ return can_rx_register (net , gwj -> src .dev , gwj -> ccgw .filter .can_id ,
444442 gwj -> ccgw .filter .can_mask , can_can_gw_rcv ,
445443 gwj , "gw" , NULL );
446444}
447445
448- static inline void cgw_unregister_filter (struct cgw_job * gwj )
446+ static inline void cgw_unregister_filter (struct net * net , struct cgw_job * gwj )
449447{
450- can_rx_unregister (& init_net , gwj -> src .dev , gwj -> ccgw .filter .can_id ,
448+ can_rx_unregister (net , gwj -> src .dev , gwj -> ccgw .filter .can_id ,
451449 gwj -> ccgw .filter .can_mask , can_can_gw_rcv , gwj );
452450}
453451
454452static int cgw_notifier (struct notifier_block * nb ,
455453 unsigned long msg , void * ptr )
456454{
457455 struct net_device * dev = netdev_notifier_info_to_dev (ptr );
456+ struct net * net = dev_net (dev );
458457
459- if (!net_eq (dev_net (dev ), & init_net ))
460- return NOTIFY_DONE ;
461458 if (dev -> type != ARPHRD_CAN )
462459 return NOTIFY_DONE ;
463460
@@ -468,11 +465,11 @@ static int cgw_notifier(struct notifier_block *nb,
468465
469466 ASSERT_RTNL ();
470467
471- hlist_for_each_entry_safe (gwj , nx , & cgw_list , list ) {
468+ hlist_for_each_entry_safe (gwj , nx , & net -> can . cgw_list , list ) {
472469
473470 if (gwj -> src .dev == dev || gwj -> dst .dev == dev ) {
474471 hlist_del (& gwj -> list );
475- cgw_unregister_filter (gwj );
472+ cgw_unregister_filter (net , gwj );
476473 kmem_cache_free (cgw_cache , gwj );
477474 }
478475 }
@@ -592,12 +589,13 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type,
592589/* Dump information about all CAN gateway jobs, in response to RTM_GETROUTE */
593590static int cgw_dump_jobs (struct sk_buff * skb , struct netlink_callback * cb )
594591{
592+ struct net * net = sock_net (skb -> sk );
595593 struct cgw_job * gwj = NULL ;
596594 int idx = 0 ;
597595 int s_idx = cb -> args [0 ];
598596
599597 rcu_read_lock ();
600- hlist_for_each_entry_rcu (gwj , & cgw_list , list ) {
598+ hlist_for_each_entry_rcu (gwj , & net -> can . cgw_list , list ) {
601599 if (idx < s_idx )
602600 goto cont ;
603601
@@ -812,6 +810,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
812810static int cgw_create_job (struct sk_buff * skb , struct nlmsghdr * nlh ,
813811 struct netlink_ext_ack * extack )
814812{
813+ struct net * net = sock_net (skb -> sk );
815814 struct rtcanmsg * r ;
816815 struct cgw_job * gwj ;
817816 struct cf_mod mod ;
@@ -842,7 +841,7 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
842841 ASSERT_RTNL ();
843842
844843 /* check for updating an existing job with identical uid */
845- hlist_for_each_entry (gwj , & cgw_list , list ) {
844+ hlist_for_each_entry (gwj , & net -> can . cgw_list , list ) {
846845
847846 if (gwj -> mod .uid != mod .uid )
848847 continue ;
@@ -880,15 +879,15 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
880879
881880 err = - ENODEV ;
882881
883- gwj -> src .dev = __dev_get_by_index (& init_net , gwj -> ccgw .src_idx );
882+ gwj -> src .dev = __dev_get_by_index (net , gwj -> ccgw .src_idx );
884883
885884 if (!gwj -> src .dev )
886885 goto out ;
887886
888887 if (gwj -> src .dev -> type != ARPHRD_CAN )
889888 goto out ;
890889
891- gwj -> dst .dev = __dev_get_by_index (& init_net , gwj -> ccgw .dst_idx );
890+ gwj -> dst .dev = __dev_get_by_index (net , gwj -> ccgw .dst_idx );
892891
893892 if (!gwj -> dst .dev )
894893 goto out ;
@@ -898,33 +897,34 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
898897
899898 ASSERT_RTNL ();
900899
901- err = cgw_register_filter (gwj );
900+ err = cgw_register_filter (net , gwj );
902901 if (!err )
903- hlist_add_head_rcu (& gwj -> list , & cgw_list );
902+ hlist_add_head_rcu (& gwj -> list , & net -> can . cgw_list );
904903out :
905904 if (err )
906905 kmem_cache_free (cgw_cache , gwj );
907906
908907 return err ;
909908}
910909
911- static void cgw_remove_all_jobs (void )
910+ static void cgw_remove_all_jobs (struct net * net )
912911{
913912 struct cgw_job * gwj = NULL ;
914913 struct hlist_node * nx ;
915914
916915 ASSERT_RTNL ();
917916
918- hlist_for_each_entry_safe (gwj , nx , & cgw_list , list ) {
917+ hlist_for_each_entry_safe (gwj , nx , & net -> can . cgw_list , list ) {
919918 hlist_del (& gwj -> list );
920- cgw_unregister_filter (gwj );
919+ cgw_unregister_filter (net , gwj );
921920 kmem_cache_free (cgw_cache , gwj );
922921 }
923922}
924923
925924static int cgw_remove_job (struct sk_buff * skb , struct nlmsghdr * nlh ,
926925 struct netlink_ext_ack * extack )
927926{
927+ struct net * net = sock_net (skb -> sk );
928928 struct cgw_job * gwj = NULL ;
929929 struct hlist_node * nx ;
930930 struct rtcanmsg * r ;
@@ -953,7 +953,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh,
953953
954954 /* two interface indices both set to 0 => remove all entries */
955955 if (!ccgw .src_idx && !ccgw .dst_idx ) {
956- cgw_remove_all_jobs ();
956+ cgw_remove_all_jobs (net );
957957 return 0 ;
958958 }
959959
@@ -962,7 +962,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh,
962962 ASSERT_RTNL ();
963963
964964 /* remove only the first matching entry */
965- hlist_for_each_entry_safe (gwj , nx , & cgw_list , list ) {
965+ hlist_for_each_entry_safe (gwj , nx , & net -> can . cgw_list , list ) {
966966
967967 if (gwj -> flags != r -> flags )
968968 continue ;
@@ -985,7 +985,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh,
985985 continue ;
986986
987987 hlist_del (& gwj -> list );
988- cgw_unregister_filter (gwj );
988+ cgw_unregister_filter (net , gwj );
989989 kmem_cache_free (cgw_cache , gwj );
990990 err = 0 ;
991991 break ;
@@ -994,6 +994,24 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh,
994994 return err ;
995995}
996996
997+ static int __net_init cangw_pernet_init (struct net * net )
998+ {
999+ INIT_HLIST_HEAD (& net -> can .cgw_list );
1000+ return 0 ;
1001+ }
1002+
1003+ static void __net_exit cangw_pernet_exit (struct net * net )
1004+ {
1005+ rtnl_lock ();
1006+ cgw_remove_all_jobs (net );
1007+ rtnl_unlock ();
1008+ }
1009+
1010+ static struct pernet_operations cangw_pernet_ops = {
1011+ .init = cangw_pernet_init ,
1012+ .exit = cangw_pernet_exit ,
1013+ };
1014+
9971015static __init int cgw_module_init (void )
9981016{
9991017 /* sanitize given module parameter */
@@ -1002,6 +1020,7 @@ static __init int cgw_module_init(void)
10021020 pr_info ("can: netlink gateway (rev " CAN_GW_VERSION ") max_hops=%d\n" ,
10031021 max_hops );
10041022
1023+ register_pernet_subsys (& cangw_pernet_ops );
10051024 cgw_cache = kmem_cache_create ("can_gw" , sizeof (struct cgw_job ),
10061025 0 , 0 , NULL );
10071026
@@ -1031,10 +1050,7 @@ static __exit void cgw_module_exit(void)
10311050
10321051 unregister_netdevice_notifier (& notifier );
10331052
1034- rtnl_lock ();
1035- cgw_remove_all_jobs ();
1036- rtnl_unlock ();
1037-
1053+ unregister_pernet_subsys (& cangw_pernet_ops );
10381054 rcu_barrier (); /* Wait for completion of call_rcu()'s */
10391055
10401056 kmem_cache_destroy (cgw_cache );
0 commit comments