diff options
Diffstat (limited to 'net/ipv4/fib_frontend.c')
-rw-r--r-- | net/ipv4/fib_frontend.c | 88 |
1 files changed, 80 insertions, 8 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 1bb956b3be28..0484cae02736 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -59,7 +59,7 @@ struct fib_table *ip_fib_main_table; | |||
59 | #define FIB_TABLE_HASHSZ 1 | 59 | #define FIB_TABLE_HASHSZ 1 |
60 | static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; | 60 | static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; |
61 | 61 | ||
62 | static int __init fib4_rules_init(void) | 62 | static int __net_init fib4_rules_init(struct net *net) |
63 | { | 63 | { |
64 | ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL); | 64 | ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL); |
65 | if (ip_fib_local_table == NULL) | 65 | if (ip_fib_local_table == NULL) |
@@ -863,10 +863,18 @@ static void nl_fib_input(struct sk_buff *skb) | |||
863 | netlink_unicast(fibnl, skb, pid, MSG_DONTWAIT); | 863 | netlink_unicast(fibnl, skb, pid, MSG_DONTWAIT); |
864 | } | 864 | } |
865 | 865 | ||
866 | static void nl_fib_lookup_init(void) | 866 | static int nl_fib_lookup_init(struct net *net) |
867 | { | 867 | { |
868 | fibnl = netlink_kernel_create(&init_net, NETLINK_FIB_LOOKUP, 0, | 868 | fibnl = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0, |
869 | nl_fib_input, NULL, THIS_MODULE); | 869 | nl_fib_input, NULL, THIS_MODULE); |
870 | if (fibnl == NULL) | ||
871 | return -EAFNOSUPPORT; | ||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | static void nl_fib_lookup_exit(struct net *net) | ||
876 | { | ||
877 | sock_put(fibnl); | ||
870 | } | 878 | } |
871 | 879 | ||
872 | static void fib_disable_ip(struct net_device *dev, int force) | 880 | static void fib_disable_ip(struct net_device *dev, int force) |
@@ -949,22 +957,86 @@ static struct notifier_block fib_netdev_notifier = { | |||
949 | .notifier_call =fib_netdev_event, | 957 | .notifier_call =fib_netdev_event, |
950 | }; | 958 | }; |
951 | 959 | ||
952 | void __init ip_fib_init(void) | 960 | static int __net_init ip_fib_net_init(struct net *net) |
953 | { | 961 | { |
954 | unsigned int i; | 962 | unsigned int i; |
955 | 963 | ||
956 | for (i = 0; i < FIB_TABLE_HASHSZ; i++) | 964 | for (i = 0; i < FIB_TABLE_HASHSZ; i++) |
957 | INIT_HLIST_HEAD(&fib_table_hash[i]); | 965 | INIT_HLIST_HEAD(&fib_table_hash[i]); |
958 | 966 | ||
959 | BUG_ON(fib4_rules_init()); | 967 | return fib4_rules_init(net); |
968 | } | ||
960 | 969 | ||
961 | register_netdevice_notifier(&fib_netdev_notifier); | 970 | static void __net_exit ip_fib_net_exit(struct net *net) |
962 | register_inetaddr_notifier(&fib_inetaddr_notifier); | 971 | { |
963 | nl_fib_lookup_init(); | 972 | unsigned int i; |
973 | |||
974 | #ifdef CONFIG_IP_MULTIPLE_TABLES | ||
975 | fib4_rules_exit(net); | ||
976 | #endif | ||
977 | |||
978 | for (i = 0; i < FIB_TABLE_HASHSZ; i++) { | ||
979 | struct fib_table *tb; | ||
980 | struct hlist_head *head; | ||
981 | struct hlist_node *node, *tmp; | ||
964 | 982 | ||
983 | head = &fib_table_hash[i]; | ||
984 | hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) { | ||
985 | hlist_del(node); | ||
986 | tb->tb_flush(tb); | ||
987 | kfree(tb); | ||
988 | } | ||
989 | } | ||
990 | } | ||
991 | |||
992 | static int __net_init fib_net_init(struct net *net) | ||
993 | { | ||
994 | int error; | ||
995 | |||
996 | error = 0; | ||
997 | if (net != &init_net) | ||
998 | goto out; | ||
999 | |||
1000 | error = ip_fib_net_init(net); | ||
1001 | if (error < 0) | ||
1002 | goto out; | ||
1003 | error = nl_fib_lookup_init(net); | ||
1004 | if (error < 0) | ||
1005 | goto out_nlfl; | ||
1006 | error = fib_proc_init(net); | ||
1007 | if (error < 0) | ||
1008 | goto out_proc; | ||
1009 | out: | ||
1010 | return error; | ||
1011 | |||
1012 | out_proc: | ||
1013 | nl_fib_lookup_exit(net); | ||
1014 | out_nlfl: | ||
1015 | ip_fib_net_exit(net); | ||
1016 | goto out; | ||
1017 | } | ||
1018 | |||
1019 | static void __net_exit fib_net_exit(struct net *net) | ||
1020 | { | ||
1021 | fib_proc_exit(net); | ||
1022 | nl_fib_lookup_exit(net); | ||
1023 | ip_fib_net_exit(net); | ||
1024 | } | ||
1025 | |||
1026 | static struct pernet_operations fib_net_ops = { | ||
1027 | .init = fib_net_init, | ||
1028 | .exit = fib_net_exit, | ||
1029 | }; | ||
1030 | |||
1031 | void __init ip_fib_init(void) | ||
1032 | { | ||
965 | rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL); | 1033 | rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL); |
966 | rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL); | 1034 | rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL); |
967 | rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib); | 1035 | rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib); |
1036 | |||
1037 | register_pernet_subsys(&fib_net_ops); | ||
1038 | register_netdevice_notifier(&fib_netdev_notifier); | ||
1039 | register_inetaddr_notifier(&fib_inetaddr_notifier); | ||
968 | } | 1040 | } |
969 | 1041 | ||
970 | EXPORT_SYMBOL(inet_addr_type); | 1042 | EXPORT_SYMBOL(inet_addr_type); |