diff options
author | Pravin B Shelar <pshelar@nicira.com> | 2013-04-25 07:08:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-29 13:54:36 -0400 |
commit | 5f5624cf156283687e11ea329c7a0523c677ea0e (patch) | |
tree | b9a95bfab72e5fd1ec3964f338770bdb1da55861 /net/ipv6/ip6_icmp.c | |
parent | a4c4009f4f54dabaaea1bb2b2c3c8930e93cd409 (diff) |
ipv6: Kill ipv6 dependency of icmpv6_send().
Following patch adds icmp-registration module for ipv6. It allows
ipv6 protocol to register icmp_sender which is used for sending
ipv6 icmp msgs. This extra layer allows us to kill ipv6 dependency
for sending icmp packets.
This patch also fixes ip_tunnel compilation problem when ip_tunnel
is statically compiled in kernel but ipv6 is module
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ip6_icmp.c')
-rw-r--r-- | net/ipv6/ip6_icmp.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/net/ipv6/ip6_icmp.c b/net/ipv6/ip6_icmp.c new file mode 100644 index 000000000000..4578e23834f7 --- /dev/null +++ b/net/ipv6/ip6_icmp.c | |||
@@ -0,0 +1,47 @@ | |||
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) ? | ||
16 | 0 : -EBUSY; | ||
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; | ||
42 | send(skb, type, code, info); | ||
43 | out: | ||
44 | rcu_read_unlock(); | ||
45 | } | ||
46 | EXPORT_SYMBOL(icmpv6_send); | ||
47 | #endif | ||