linux/net/ipv6/ip6_icmp.c
<<
>>
Prefs
   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
   7#include <net/ipv6.h>
   8
   9#if IS_ENABLED(CONFIG_IPV6)
  10
  11static ip6_icmp_send_t __rcu *ip6_icmp_send;
  12
  13int inet6_register_icmp_sender(ip6_icmp_send_t *fn)
  14{
  15        return (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, NULL, fn) == NULL) ?
  16                0 : -EBUSY;
  17}
  18EXPORT_SYMBOL(inet6_register_icmp_sender);
  19
  20int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn)
  21{
  22        int ret;
  23
  24        ret = (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, fn, NULL) == fn) ?
  25              0 : -EINVAL;
  26
  27        synchronize_net();
  28
  29        return ret;
  30}
  31EXPORT_SYMBOL(inet6_unregister_icmp_sender);
  32
  33void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
  34{
  35        ip6_icmp_send_t *send;
  36
  37        rcu_read_lock();
  38        send = rcu_dereference(ip6_icmp_send);
  39
  40        if (!send)
  41                goto out;
  42        send(skb, type, code, info);
  43out:
  44        rcu_read_unlock();
  45}
  46EXPORT_SYMBOL(icmpv6_send);
  47#endif
  48