1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2c0243892SIdo Schimmel #include <linux/rtnetlink.h> 3c0243892SIdo Schimmel #include <linux/notifier.h> 404b1d4e5SIdo Schimmel #include <linux/socket.h> 5c0243892SIdo Schimmel #include <linux/kernel.h> 6864150dfSIdo Schimmel #include <linux/export.h> 7c0243892SIdo Schimmel #include <net/net_namespace.h> 804b1d4e5SIdo Schimmel #include <net/fib_notifier.h> 9c0243892SIdo Schimmel #include <net/netns/ipv4.h> 10c0243892SIdo Schimmel #include <net/ip_fib.h> 11c0243892SIdo Schimmel 12*7c550dafSJiri Pirko int call_fib4_notifier(struct notifier_block *nb, 13c0243892SIdo Schimmel enum fib_event_type event_type, 14c0243892SIdo Schimmel struct fib_notifier_info *info) 15c0243892SIdo Schimmel { 1604b1d4e5SIdo Schimmel info->family = AF_INET; 17*7c550dafSJiri Pirko return call_fib_notifier(nb, event_type, info); 18c0243892SIdo Schimmel } 19c0243892SIdo Schimmel 2004b1d4e5SIdo Schimmel int call_fib4_notifiers(struct net *net, enum fib_event_type event_type, 21c0243892SIdo Schimmel struct fib_notifier_info *info) 22c0243892SIdo Schimmel { 2304b1d4e5SIdo Schimmel ASSERT_RTNL(); 2404b1d4e5SIdo Schimmel 2504b1d4e5SIdo Schimmel info->family = AF_INET; 26c0243892SIdo Schimmel net->ipv4.fib_seq++; 2704b1d4e5SIdo Schimmel return call_fib_notifiers(net, event_type, info); 28c0243892SIdo Schimmel } 29c0243892SIdo Schimmel 3004b1d4e5SIdo Schimmel static unsigned int fib4_seq_read(struct net *net) 31c0243892SIdo Schimmel { 3204b1d4e5SIdo Schimmel ASSERT_RTNL(); 33c0243892SIdo Schimmel 341b2a4440SIdo Schimmel return net->ipv4.fib_seq + fib4_rules_seq_read(net); 35c0243892SIdo Schimmel } 36c0243892SIdo Schimmel 3704b1d4e5SIdo Schimmel static int fib4_dump(struct net *net, struct notifier_block *nb) 38c0243892SIdo Schimmel { 391b2a4440SIdo Schimmel int err; 401b2a4440SIdo Schimmel 411b2a4440SIdo Schimmel err = fib4_rules_dump(net, nb); 421b2a4440SIdo Schimmel if (err) 431b2a4440SIdo Schimmel return err; 441b2a4440SIdo Schimmel 45d05f7a7dSIdo Schimmel fib_notify(net, nb); 46c0243892SIdo Schimmel 47c0243892SIdo Schimmel return 0; 48c0243892SIdo Schimmel } 49c0243892SIdo Schimmel 5004b1d4e5SIdo Schimmel static const struct fib_notifier_ops fib4_notifier_ops_template = { 5104b1d4e5SIdo Schimmel .family = AF_INET, 5204b1d4e5SIdo Schimmel .fib_seq_read = fib4_seq_read, 5304b1d4e5SIdo Schimmel .fib_dump = fib4_dump, 54864150dfSIdo Schimmel .owner = THIS_MODULE, 5504b1d4e5SIdo Schimmel }; 5604b1d4e5SIdo Schimmel 5704b1d4e5SIdo Schimmel int __net_init fib4_notifier_init(struct net *net) 58c0243892SIdo Schimmel { 5904b1d4e5SIdo Schimmel struct fib_notifier_ops *ops; 6004b1d4e5SIdo Schimmel 6104b1d4e5SIdo Schimmel net->ipv4.fib_seq = 0; 6204b1d4e5SIdo Schimmel 6304b1d4e5SIdo Schimmel ops = fib_notifier_ops_register(&fib4_notifier_ops_template, net); 6404b1d4e5SIdo Schimmel if (IS_ERR(ops)) 6504b1d4e5SIdo Schimmel return PTR_ERR(ops); 6604b1d4e5SIdo Schimmel net->ipv4.notifier_ops = ops; 6704b1d4e5SIdo Schimmel 6804b1d4e5SIdo Schimmel return 0; 69c0243892SIdo Schimmel } 7004b1d4e5SIdo Schimmel 7104b1d4e5SIdo Schimmel void __net_exit fib4_notifier_exit(struct net *net) 7204b1d4e5SIdo Schimmel { 7304b1d4e5SIdo Schimmel fib_notifier_ops_unregister(net->ipv4.notifier_ops); 7404b1d4e5SIdo Schimmel } 75