1c0243892SIdo Schimmel #include <linux/rtnetlink.h> 2c0243892SIdo Schimmel #include <linux/notifier.h> 304b1d4e5SIdo Schimmel #include <linux/socket.h> 4c0243892SIdo Schimmel #include <linux/kernel.h> 5c0243892SIdo Schimmel #include <net/net_namespace.h> 604b1d4e5SIdo Schimmel #include <net/fib_notifier.h> 7c0243892SIdo Schimmel #include <net/netns/ipv4.h> 8c0243892SIdo Schimmel #include <net/ip_fib.h> 9c0243892SIdo Schimmel 1004b1d4e5SIdo Schimmel int call_fib4_notifier(struct notifier_block *nb, struct net *net, 11c0243892SIdo Schimmel enum fib_event_type event_type, 12c0243892SIdo Schimmel struct fib_notifier_info *info) 13c0243892SIdo Schimmel { 1404b1d4e5SIdo Schimmel info->family = AF_INET; 1504b1d4e5SIdo Schimmel return call_fib_notifier(nb, net, event_type, info); 16c0243892SIdo Schimmel } 17c0243892SIdo Schimmel 1804b1d4e5SIdo Schimmel int call_fib4_notifiers(struct net *net, enum fib_event_type event_type, 19c0243892SIdo Schimmel struct fib_notifier_info *info) 20c0243892SIdo Schimmel { 2104b1d4e5SIdo Schimmel ASSERT_RTNL(); 2204b1d4e5SIdo Schimmel 2304b1d4e5SIdo Schimmel info->family = AF_INET; 24c0243892SIdo Schimmel net->ipv4.fib_seq++; 2504b1d4e5SIdo Schimmel return call_fib_notifiers(net, event_type, info); 26c0243892SIdo Schimmel } 27c0243892SIdo Schimmel 2804b1d4e5SIdo Schimmel static unsigned int fib4_seq_read(struct net *net) 29c0243892SIdo Schimmel { 3004b1d4e5SIdo Schimmel ASSERT_RTNL(); 31c0243892SIdo Schimmel 3204b1d4e5SIdo Schimmel return net->ipv4.fib_seq; 33c0243892SIdo Schimmel } 34c0243892SIdo Schimmel 3504b1d4e5SIdo Schimmel static int fib4_dump(struct net *net, struct notifier_block *nb) 36c0243892SIdo Schimmel { 37d05f7a7dSIdo Schimmel fib_rules_notify(net, nb); 38d05f7a7dSIdo Schimmel fib_notify(net, nb); 39c0243892SIdo Schimmel 40c0243892SIdo Schimmel return 0; 41c0243892SIdo Schimmel } 42c0243892SIdo Schimmel 4304b1d4e5SIdo Schimmel static const struct fib_notifier_ops fib4_notifier_ops_template = { 4404b1d4e5SIdo Schimmel .family = AF_INET, 4504b1d4e5SIdo Schimmel .fib_seq_read = fib4_seq_read, 4604b1d4e5SIdo Schimmel .fib_dump = fib4_dump, 4704b1d4e5SIdo Schimmel }; 4804b1d4e5SIdo Schimmel 4904b1d4e5SIdo Schimmel int __net_init fib4_notifier_init(struct net *net) 50c0243892SIdo Schimmel { 5104b1d4e5SIdo Schimmel struct fib_notifier_ops *ops; 5204b1d4e5SIdo Schimmel 5304b1d4e5SIdo Schimmel net->ipv4.fib_seq = 0; 5404b1d4e5SIdo Schimmel 5504b1d4e5SIdo Schimmel ops = fib_notifier_ops_register(&fib4_notifier_ops_template, net); 5604b1d4e5SIdo Schimmel if (IS_ERR(ops)) 5704b1d4e5SIdo Schimmel return PTR_ERR(ops); 5804b1d4e5SIdo Schimmel net->ipv4.notifier_ops = ops; 5904b1d4e5SIdo Schimmel 6004b1d4e5SIdo Schimmel return 0; 61c0243892SIdo Schimmel } 6204b1d4e5SIdo Schimmel 6304b1d4e5SIdo Schimmel void __net_exit fib4_notifier_exit(struct net *net) 6404b1d4e5SIdo Schimmel { 6504b1d4e5SIdo Schimmel fib_notifier_ops_unregister(net->ipv4.notifier_ops); 6604b1d4e5SIdo Schimmel } 67