Blame view
net/ipv4/tunnel4.c
4.12 KB
d2acc3479 [INET]: Introduce... |
1 2 3 4 5 6 7 8 9 10 |
/* tunnel4.c: Generic IP tunnel transformer. * * Copyright (C) 2003 David S. Miller (davem@redhat.com) */ #include <linux/init.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/netdevice.h> #include <linux/skbuff.h> |
5a0e3ad6a include cleanup: ... |
11 |
#include <linux/slab.h> |
50fba2aa7 [INET]: Move no-t... |
12 13 |
#include <net/icmp.h> #include <net/ip.h> |
d2acc3479 [INET]: Introduce... |
14 15 |
#include <net/protocol.h> #include <net/xfrm.h> |
b33eab084 tunnels: add __rc... |
16 17 |
static struct xfrm_tunnel __rcu *tunnel4_handlers __read_mostly; static struct xfrm_tunnel __rcu *tunnel64_handlers __read_mostly; |
d2acc3479 [INET]: Introduce... |
18 |
static DEFINE_MUTEX(tunnel4_mutex); |
b33eab084 tunnels: add __rc... |
19 |
static inline struct xfrm_tunnel __rcu **fam_handlers(unsigned short family) |
358352b8b [INET]: Cleanup t... |
20 21 22 |
{ return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; } |
c0d56408e [IPSEC]: Changing... |
23 |
int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family) |
d2acc3479 [INET]: Introduce... |
24 |
{ |
b33eab084 tunnels: add __rc... |
25 26 |
struct xfrm_tunnel __rcu **pprev; struct xfrm_tunnel *t; |
d2acc3479 [INET]: Introduce... |
27 28 29 30 |
int ret = -EEXIST; int priority = handler->priority; mutex_lock(&tunnel4_mutex); |
b33eab084 tunnels: add __rc... |
31 32 33 34 35 |
for (pprev = fam_handlers(family); (t = rcu_dereference_protected(*pprev, lockdep_is_held(&tunnel4_mutex))) != NULL; pprev = &t->next) { if (t->priority > priority) |
d2acc3479 [INET]: Introduce... |
36 |
break; |
b33eab084 tunnels: add __rc... |
37 |
if (t->priority == priority) |
d2acc3479 [INET]: Introduce... |
38 39 40 41 |
goto err; } handler->next = *pprev; |
49d61e239 tunnels: missing ... |
42 |
rcu_assign_pointer(*pprev, handler); |
d2acc3479 [INET]: Introduce... |
43 44 45 46 47 48 49 50 |
ret = 0; err: mutex_unlock(&tunnel4_mutex); return ret; } |
d2acc3479 [INET]: Introduce... |
51 |
EXPORT_SYMBOL(xfrm4_tunnel_register); |
c0d56408e [IPSEC]: Changing... |
52 |
int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family) |
d2acc3479 [INET]: Introduce... |
53 |
{ |
b33eab084 tunnels: add __rc... |
54 55 |
struct xfrm_tunnel __rcu **pprev; struct xfrm_tunnel *t; |
d2acc3479 [INET]: Introduce... |
56 57 58 |
int ret = -ENOENT; mutex_lock(&tunnel4_mutex); |
b33eab084 tunnels: add __rc... |
59 60 61 62 63 |
for (pprev = fam_handlers(family); (t = rcu_dereference_protected(*pprev, lockdep_is_held(&tunnel4_mutex))) != NULL; pprev = &t->next) { if (t == handler) { |
d2acc3479 [INET]: Introduce... |
64 65 66 67 68 69 70 71 72 73 74 75 |
*pprev = handler->next; ret = 0; break; } } mutex_unlock(&tunnel4_mutex); synchronize_net(); return ret; } |
d2acc3479 [INET]: Introduce... |
76 |
EXPORT_SYMBOL(xfrm4_tunnel_deregister); |
875168a93 net: tunnels shou... |
77 78 79 80 81 |
#define for_each_tunnel_rcu(head, handler) \ for (handler = rcu_dereference(head); \ handler != NULL; \ handler = rcu_dereference(handler->next)) \ |
d2acc3479 [INET]: Introduce... |
82 83 84 |
static int tunnel4_rcv(struct sk_buff *skb) { struct xfrm_tunnel *handler; |
50fba2aa7 [INET]: Move no-t... |
85 86 |
if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto drop; |
875168a93 net: tunnels shou... |
87 |
for_each_tunnel_rcu(tunnel4_handlers, handler) |
d2acc3479 [INET]: Introduce... |
88 89 |
if (!handler->handler(skb)) return 0; |
50fba2aa7 [INET]: Move no-t... |
90 91 92 |
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); drop: |
d2acc3479 [INET]: Introduce... |
93 94 95 |
kfree_skb(skb); return 0; } |
dfd56b8b3 net: use IS_ENABL... |
96 |
#if IS_ENABLED(CONFIG_IPV6) |
c0d56408e [IPSEC]: Changing... |
97 98 99 |
static int tunnel64_rcv(struct sk_buff *skb) { struct xfrm_tunnel *handler; |
baa2bfb8a [IPV4] TUNNEL4: F... |
100 |
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
c0d56408e [IPSEC]: Changing... |
101 |
goto drop; |
875168a93 net: tunnels shou... |
102 |
for_each_tunnel_rcu(tunnel64_handlers, handler) |
c0d56408e [IPSEC]: Changing... |
103 104 105 106 107 108 109 110 111 112 |
if (!handler->handler(skb)) return 0; icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); drop: kfree_skb(skb); return 0; } #endif |
d2acc3479 [INET]: Introduce... |
113 114 115 |
static void tunnel4_err(struct sk_buff *skb, u32 info) { struct xfrm_tunnel *handler; |
875168a93 net: tunnels shou... |
116 |
for_each_tunnel_rcu(tunnel4_handlers, handler) |
d2acc3479 [INET]: Introduce... |
117 118 119 |
if (!handler->err_handler(skb, info)) break; } |
dfd56b8b3 net: use IS_ENABL... |
120 |
#if IS_ENABLED(CONFIG_IPV6) |
99f933263 [INET]: Add misse... |
121 122 123 |
static void tunnel64_err(struct sk_buff *skb, u32 info) { struct xfrm_tunnel *handler; |
875168a93 net: tunnels shou... |
124 |
for_each_tunnel_rcu(tunnel64_handlers, handler) |
99f933263 [INET]: Add misse... |
125 126 127 128 |
if (!handler->err_handler(skb, info)) break; } #endif |
32613090a net: constify str... |
129 |
static const struct net_protocol tunnel4_protocol = { |
d2acc3479 [INET]: Introduce... |
130 131 132 |
.handler = tunnel4_rcv, .err_handler = tunnel4_err, .no_policy = 1, |
4597a0ce0 [IPIP]: Allow for... |
133 |
.netns_ok = 1, |
d2acc3479 [INET]: Introduce... |
134 |
}; |
dfd56b8b3 net: use IS_ENABL... |
135 |
#if IS_ENABLED(CONFIG_IPV6) |
32613090a net: constify str... |
136 |
static const struct net_protocol tunnel64_protocol = { |
c0d56408e [IPSEC]: Changing... |
137 |
.handler = tunnel64_rcv, |
99f933263 [INET]: Add misse... |
138 |
.err_handler = tunnel64_err, |
c0d56408e [IPSEC]: Changing... |
139 |
.no_policy = 1, |
b0970c428 [SIT]: Allow for ... |
140 |
.netns_ok = 1, |
c0d56408e [IPSEC]: Changing... |
141 142 |
}; #endif |
d2acc3479 [INET]: Introduce... |
143 144 145 |
static int __init tunnel4_init(void) { if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { |
058bd4d2a net: Convert prin... |
146 147 |
pr_err("%s: can't add protocol ", __func__); |
d2acc3479 [INET]: Introduce... |
148 149 |
return -EAGAIN; } |
dfd56b8b3 net: use IS_ENABL... |
150 |
#if IS_ENABLED(CONFIG_IPV6) |
c0d56408e [IPSEC]: Changing... |
151 |
if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) { |
058bd4d2a net: Convert prin... |
152 153 |
pr_err("tunnel64 init: can't add protocol "); |
c0d56408e [IPSEC]: Changing... |
154 155 156 157 |
inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP); return -EAGAIN; } #endif |
d2acc3479 [INET]: Introduce... |
158 159 160 161 162 |
return 0; } static void __exit tunnel4_fini(void) { |
dfd56b8b3 net: use IS_ENABL... |
163 |
#if IS_ENABLED(CONFIG_IPV6) |
c0d56408e [IPSEC]: Changing... |
164 |
if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6)) |
058bd4d2a net: Convert prin... |
165 166 |
pr_err("tunnel64 close: can't remove protocol "); |
c0d56408e [IPSEC]: Changing... |
167 |
#endif |
d2acc3479 [INET]: Introduce... |
168 |
if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) |
058bd4d2a net: Convert prin... |
169 170 |
pr_err("tunnel4 close: can't remove protocol "); |
d2acc3479 [INET]: Introduce... |
171 172 173 174 175 |
} module_init(tunnel4_init); module_exit(tunnel4_fini); MODULE_LICENSE("GPL"); |