xref: /linux/net/ipv4/fib_notifier.c (revision 7c550daffe22a97282effa75fe7c1f6b83563ecb)
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