ip6_icmp.c 938 B

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. #include <linux/export.h>
  2. #include <linux/icmpv6.h>
  3. #include <linux/mutex.h>
  4. #include <linux/netdevice.h>
  5. #include <linux/spinlock.h>
  6. #include <net/ipv6.h>
  7. #if IS_ENABLED(CONFIG_IPV6)
  8. static ip6_icmp_send_t __rcu *ip6_icmp_send;
  9. int inet6_register_icmp_sender(ip6_icmp_send_t *fn)
  10. {
  11. return (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, NULL, fn) == NULL) ?
  12. 0 : -EBUSY;
  13. }
  14. EXPORT_SYMBOL(inet6_register_icmp_sender);
  15. int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn)
  16. {
  17. int ret;
  18. ret = (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, fn, NULL) == fn) ?
  19. 0 : -EINVAL;
  20. synchronize_net();
  21. return ret;
  22. }
  23. EXPORT_SYMBOL(inet6_unregister_icmp_sender);
  24. void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
  25. {
  26. ip6_icmp_send_t *send;
  27. rcu_read_lock();
  28. send = rcu_dereference(ip6_icmp_send);
  29. if (!send)
  30. goto out;
  31. send(skb, type, code, info, NULL);
  32. out:
  33. rcu_read_unlock();
  34. }
  35. EXPORT_SYMBOL(icmpv6_send);
  36. #endif