ip6_icmp.c 974 B

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