Commit | Line | Data |
---|---|---|
5f5624cf PS |
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 | ||
11 | static ip6_icmp_send_t __rcu *ip6_icmp_send; | |
12 | ||
13 | int inet6_register_icmp_sender(ip6_icmp_send_t *fn) | |
14 | { | |
15 | return (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, NULL, fn) == NULL) ? | |
67ba4152 | 16 | 0 : -EBUSY; |
5f5624cf PS |
17 | } |
18 | EXPORT_SYMBOL(inet6_register_icmp_sender); | |
19 | ||
20 | int 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 | } | |
31 | EXPORT_SYMBOL(inet6_unregister_icmp_sender); | |
32 | ||
33 | void 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; | |
b1cadc1a | 42 | send(skb, type, code, info, NULL); |
5f5624cf PS |
43 | out: |
44 | rcu_read_unlock(); | |
45 | } | |
46 | EXPORT_SYMBOL(icmpv6_send); | |
47 | #endif |