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