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