190792Sgshapiro// SPDX-License-Identifier: GPL-2.0
2132943Sgshapiro#include <linux/rtnetlink.h>
390792Sgshapiro#include <linux/notifier.h>
490792Sgshapiro#include <linux/socket.h>
590792Sgshapiro#include <linux/kernel.h>
690792Sgshapiro#include <linux/export.h>
790792Sgshapiro#include <net/net_namespace.h>
890792Sgshapiro#include <net/fib_notifier.h>
990792Sgshapiro#include <net/ip_fib.h>
1090792Sgshapiro
1190792Sgshapiroint call_fib4_notifier(struct notifier_block *nb,
1290792Sgshapiro		       enum fib_event_type event_type,
1390792Sgshapiro		       struct fib_notifier_info *info)
1490792Sgshapiro{
15157001Sgshapiro	info->family = AF_INET;
1690792Sgshapiro	return call_fib_notifier(nb, event_type, info);
1790792Sgshapiro}
1890792Sgshapiro
1990792Sgshapiroint call_fib4_notifiers(struct net *net, enum fib_event_type event_type,
20157001Sgshapiro			struct fib_notifier_info *info)
2190792Sgshapiro{
2290792Sgshapiro	ASSERT_RTNL();
2390792Sgshapiro
2490792Sgshapiro	info->family = AF_INET;
2590792Sgshapiro	net->ipv4.fib_seq++;
2690792Sgshapiro	return call_fib_notifiers(net, event_type, info);
27120256Sgshapiro}
28120256Sgshapiro
29120256Sgshapirostatic unsigned int fib4_seq_read(struct net *net)
30120256Sgshapiro{
31120256Sgshapiro	ASSERT_RTNL();
32120256Sgshapiro
3390792Sgshapiro	return net->ipv4.fib_seq + fib4_rules_seq_read(net);
3490792Sgshapiro}
3590792Sgshapiro
3690792Sgshapirostatic int fib4_dump(struct net *net, struct notifier_block *nb,
3790792Sgshapiro		     struct netlink_ext_ack *extack)
3890792Sgshapiro{
3990792Sgshapiro	int err;
4090792Sgshapiro
4190792Sgshapiro	err = fib4_rules_dump(net, nb, extack);
4290792Sgshapiro	if (err)
4390792Sgshapiro		return err;
4490792Sgshapiro
4590792Sgshapiro	return fib_notify(net, nb, extack);
4690792Sgshapiro}
4790792Sgshapiro
4890792Sgshapirostatic const struct fib_notifier_ops fib4_notifier_ops_template = {
4990792Sgshapiro	.family		= AF_INET,
5090792Sgshapiro	.fib_seq_read	= fib4_seq_read,
5190792Sgshapiro	.fib_dump	= fib4_dump,
5290792Sgshapiro	.owner		= THIS_MODULE,
5390792Sgshapiro};
5490792Sgshapiro
5590792Sgshapiroint __net_init fib4_notifier_init(struct net *net)
5690792Sgshapiro{
5790792Sgshapiro	struct fib_notifier_ops *ops;
5890792Sgshapiro
5990792Sgshapiro	net->ipv4.fib_seq = 0;
6090792Sgshapiro
6190792Sgshapiro	ops = fib_notifier_ops_register(&fib4_notifier_ops_template, net);
6290792Sgshapiro	if (IS_ERR(ops))
6390792Sgshapiro		return PTR_ERR(ops);
6490792Sgshapiro	net->ipv4.notifier_ops = ops;
6590792Sgshapiro
66141858Sgshapiro	return 0;
6790792Sgshapiro}
6890792Sgshapiro
6990792Sgshapirovoid __net_exit fib4_notifier_exit(struct net *net)
7090792Sgshapiro{
7190792Sgshapiro	fib_notifier_ops_unregister(net->ipv4.notifier_ops);
7290792Sgshapiro}
7390792Sgshapiro