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/ip_fib.h>
10c0243892SIdo Schimmel
call_fib4_notifier(struct notifier_block * nb,enum fib_event_type event_type,struct fib_notifier_info * info)117c550dafSJiri Pirko int call_fib4_notifier(struct notifier_block *nb,
12c0243892SIdo Schimmel enum fib_event_type event_type,
13c0243892SIdo Schimmel struct fib_notifier_info *info)
14c0243892SIdo Schimmel {
1504b1d4e5SIdo Schimmel info->family = AF_INET;
167c550dafSJiri Pirko return call_fib_notifier(nb, event_type, info);
17c0243892SIdo Schimmel }
18c0243892SIdo Schimmel
call_fib4_notifiers(struct net * net,enum fib_event_type event_type,struct fib_notifier_info * info)1904b1d4e5SIdo Schimmel int call_fib4_notifiers(struct net *net, enum fib_event_type event_type,
20c0243892SIdo Schimmel struct fib_notifier_info *info)
21c0243892SIdo Schimmel {
2204b1d4e5SIdo Schimmel ASSERT_RTNL();
2304b1d4e5SIdo Schimmel
2404b1d4e5SIdo Schimmel info->family = AF_INET;
25c0243892SIdo Schimmel net->ipv4.fib_seq++;
2604b1d4e5SIdo Schimmel return call_fib_notifiers(net, event_type, info);
27c0243892SIdo Schimmel }
28c0243892SIdo Schimmel
fib4_seq_read(struct net * net)2904b1d4e5SIdo Schimmel static unsigned int fib4_seq_read(struct net *net)
30c0243892SIdo Schimmel {
3104b1d4e5SIdo Schimmel ASSERT_RTNL();
32c0243892SIdo Schimmel
331b2a4440SIdo Schimmel return net->ipv4.fib_seq + fib4_rules_seq_read(net);
34c0243892SIdo Schimmel }
35c0243892SIdo Schimmel
fib4_dump(struct net * net,struct notifier_block * nb,struct netlink_ext_ack * extack)36*b7a59557SJiri Pirko static int fib4_dump(struct net *net, struct notifier_block *nb,
37*b7a59557SJiri Pirko struct netlink_ext_ack *extack)
38c0243892SIdo Schimmel {
391b2a4440SIdo Schimmel int err;
401b2a4440SIdo Schimmel
41*b7a59557SJiri Pirko err = fib4_rules_dump(net, nb, extack);
421b2a4440SIdo Schimmel if (err)
431b2a4440SIdo Schimmel return err;
441b2a4440SIdo Schimmel
45*b7a59557SJiri Pirko return fib_notify(net, nb, extack);
46c0243892SIdo Schimmel }
47c0243892SIdo Schimmel
4804b1d4e5SIdo Schimmel static const struct fib_notifier_ops fib4_notifier_ops_template = {
4904b1d4e5SIdo Schimmel .family = AF_INET,
5004b1d4e5SIdo Schimmel .fib_seq_read = fib4_seq_read,
5104b1d4e5SIdo Schimmel .fib_dump = fib4_dump,
52864150dfSIdo Schimmel .owner = THIS_MODULE,
5304b1d4e5SIdo Schimmel };
5404b1d4e5SIdo Schimmel
fib4_notifier_init(struct net * net)5504b1d4e5SIdo Schimmel int __net_init fib4_notifier_init(struct net *net)
56c0243892SIdo Schimmel {
5704b1d4e5SIdo Schimmel struct fib_notifier_ops *ops;
5804b1d4e5SIdo Schimmel
5904b1d4e5SIdo Schimmel net->ipv4.fib_seq = 0;
6004b1d4e5SIdo Schimmel
6104b1d4e5SIdo Schimmel ops = fib_notifier_ops_register(&fib4_notifier_ops_template, net);
6204b1d4e5SIdo Schimmel if (IS_ERR(ops))
6304b1d4e5SIdo Schimmel return PTR_ERR(ops);
6404b1d4e5SIdo Schimmel net->ipv4.notifier_ops = ops;
6504b1d4e5SIdo Schimmel
6604b1d4e5SIdo Schimmel return 0;
67c0243892SIdo Schimmel }
6804b1d4e5SIdo Schimmel
fib4_notifier_exit(struct net * net)6904b1d4e5SIdo Schimmel void __net_exit fib4_notifier_exit(struct net *net)
7004b1d4e5SIdo Schimmel {
7104b1d4e5SIdo Schimmel fib_notifier_ops_unregister(net->ipv4.notifier_ops);
7204b1d4e5SIdo Schimmel }
73