fib_notifier.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/rtnetlink.h>
  3. #include <linux/notifier.h>
  4. #include <linux/socket.h>
  5. #include <linux/kernel.h>
  6. #include <linux/export.h>
  7. #include <net/net_namespace.h>
  8. #include <net/fib_notifier.h>
  9. #include <net/ip_fib.h>
  10. int call_fib4_notifier(struct notifier_block *nb,
  11. enum fib_event_type event_type,
  12. struct fib_notifier_info *info)
  13. {
  14. info->family = AF_INET;
  15. return call_fib_notifier(nb, event_type, info);
  16. }
  17. int call_fib4_notifiers(struct net *net, enum fib_event_type event_type,
  18. struct fib_notifier_info *info)
  19. {
  20. ASSERT_RTNL();
  21. info->family = AF_INET;
  22. /* Paired with READ_ONCE() in fib4_seq_read() */
  23. WRITE_ONCE(net->ipv4.fib_seq, net->ipv4.fib_seq + 1);
  24. return call_fib_notifiers(net, event_type, info);
  25. }
  26. static unsigned int fib4_seq_read(const struct net *net)
  27. {
  28. /* Paired with WRITE_ONCE() in call_fib4_notifiers() */
  29. return READ_ONCE(net->ipv4.fib_seq) + fib4_rules_seq_read(net);
  30. }
  31. static int fib4_dump(struct net *net, struct notifier_block *nb,
  32. struct netlink_ext_ack *extack)
  33. {
  34. int err;
  35. err = fib4_rules_dump(net, nb, extack);
  36. if (err)
  37. return err;
  38. return fib_notify(net, nb, extack);
  39. }
  40. static const struct fib_notifier_ops fib4_notifier_ops_template = {
  41. .family = AF_INET,
  42. .fib_seq_read = fib4_seq_read,
  43. .fib_dump = fib4_dump,
  44. .owner = THIS_MODULE,
  45. };
  46. int __net_init fib4_notifier_init(struct net *net)
  47. {
  48. struct fib_notifier_ops *ops;
  49. net->ipv4.fib_seq = 0;
  50. ops = fib_notifier_ops_register(&fib4_notifier_ops_template, net);
  51. if (IS_ERR(ops))
  52. return PTR_ERR(ops);
  53. net->ipv4.notifier_ops = ops;
  54. return 0;
  55. }
  56. void __net_exit fib4_notifier_exit(struct net *net)
  57. {
  58. fib_notifier_ops_unregister(net->ipv4.notifier_ops);
  59. }