Blame view
net/ipv6/tunnel6.c
4.65 KB
d2acc3479 [INET]: Introduce... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* * Copyright (C)2003,2004 USAGI/WIDE Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors Mitsuru KANDA <mk@linux-ipv6.org> * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> */ |
50fba2aa7 [INET]: Move no-t... |
21 |
#include <linux/icmpv6.h> |
d2acc3479 [INET]: Introduce... |
22 23 24 25 26 |
#include <linux/init.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/netdevice.h> #include <linux/skbuff.h> |
5a0e3ad6a include cleanup: ... |
27 |
#include <linux/slab.h> |
50fba2aa7 [INET]: Move no-t... |
28 |
#include <net/ipv6.h> |
d2acc3479 [INET]: Introduce... |
29 30 |
#include <net/protocol.h> #include <net/xfrm.h> |
6f0bcf152 tunnels: add _rcu... |
31 32 |
static struct xfrm6_tunnel __rcu *tunnel6_handlers __read_mostly; static struct xfrm6_tunnel __rcu *tunnel46_handlers __read_mostly; |
d2acc3479 [INET]: Introduce... |
33 |
static DEFINE_MUTEX(tunnel6_mutex); |
73d605d1a [IPSEC]: changing... |
34 |
int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family) |
d2acc3479 [INET]: Introduce... |
35 |
{ |
6f0bcf152 tunnels: add _rcu... |
36 37 |
struct xfrm6_tunnel __rcu **pprev; struct xfrm6_tunnel *t; |
d2acc3479 [INET]: Introduce... |
38 39 40 41 |
int ret = -EEXIST; int priority = handler->priority; mutex_lock(&tunnel6_mutex); |
73d605d1a [IPSEC]: changing... |
42 |
for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; |
6f0bcf152 tunnels: add _rcu... |
43 44 45 46 |
(t = rcu_dereference_protected(*pprev, lockdep_is_held(&tunnel6_mutex))) != NULL; pprev = &t->next) { if (t->priority > priority) |
d2acc3479 [INET]: Introduce... |
47 |
break; |
6f0bcf152 tunnels: add _rcu... |
48 |
if (t->priority == priority) |
d2acc3479 [INET]: Introduce... |
49 50 51 52 |
goto err; } handler->next = *pprev; |
49d61e239 tunnels: missing ... |
53 |
rcu_assign_pointer(*pprev, handler); |
d2acc3479 [INET]: Introduce... |
54 55 56 57 58 59 60 61 62 63 |
ret = 0; err: mutex_unlock(&tunnel6_mutex); return ret; } EXPORT_SYMBOL(xfrm6_tunnel_register); |
73d605d1a [IPSEC]: changing... |
64 |
int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family) |
d2acc3479 [INET]: Introduce... |
65 |
{ |
6f0bcf152 tunnels: add _rcu... |
66 67 |
struct xfrm6_tunnel __rcu **pprev; struct xfrm6_tunnel *t; |
d2acc3479 [INET]: Introduce... |
68 69 70 |
int ret = -ENOENT; mutex_lock(&tunnel6_mutex); |
73d605d1a [IPSEC]: changing... |
71 |
for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; |
6f0bcf152 tunnels: add _rcu... |
72 73 74 75 |
(t = rcu_dereference_protected(*pprev, lockdep_is_held(&tunnel6_mutex))) != NULL; pprev = &t->next) { if (t == handler) { |
d2acc3479 [INET]: Introduce... |
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
*pprev = handler->next; ret = 0; break; } } mutex_unlock(&tunnel6_mutex); synchronize_net(); return ret; } EXPORT_SYMBOL(xfrm6_tunnel_deregister); |
875168a93 net: tunnels shou... |
90 91 92 93 |
#define for_each_tunnel_rcu(head, handler) \ for (handler = rcu_dereference(head); \ handler != NULL; \ handler = rcu_dereference(handler->next)) \ |
e5bbef20e [IPV6]: Replace s... |
94 |
static int tunnel6_rcv(struct sk_buff *skb) |
d2acc3479 [INET]: Introduce... |
95 |
{ |
d2acc3479 [INET]: Introduce... |
96 |
struct xfrm6_tunnel *handler; |
50fba2aa7 [INET]: Move no-t... |
97 98 |
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto drop; |
875168a93 net: tunnels shou... |
99 |
for_each_tunnel_rcu(tunnel6_handlers, handler) |
d2acc3479 [INET]: Introduce... |
100 101 |
if (!handler->handler(skb)) return 0; |
3ffe533c8 ipv6: drop unused... |
102 |
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); |
50fba2aa7 [INET]: Move no-t... |
103 104 |
drop: |
d2acc3479 [INET]: Introduce... |
105 106 107 |
kfree_skb(skb); return 0; } |
e5bbef20e [IPV6]: Replace s... |
108 |
static int tunnel46_rcv(struct sk_buff *skb) |
73d605d1a [IPSEC]: changing... |
109 |
{ |
73d605d1a [IPSEC]: changing... |
110 |
struct xfrm6_tunnel *handler; |
828363723 [IPV6] TUNNEL6: F... |
111 |
if (!pskb_may_pull(skb, sizeof(struct iphdr))) |
73d605d1a [IPSEC]: changing... |
112 |
goto drop; |
875168a93 net: tunnels shou... |
113 |
for_each_tunnel_rcu(tunnel46_handlers, handler) |
73d605d1a [IPSEC]: changing... |
114 115 |
if (!handler->handler(skb)) return 0; |
3ffe533c8 ipv6: drop unused... |
116 |
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); |
73d605d1a [IPSEC]: changing... |
117 118 119 120 121 |
drop: kfree_skb(skb); return 0; } |
d2acc3479 [INET]: Introduce... |
122 |
static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
d5fdd6bab ipv6: Use correct... |
123 |
u8 type, u8 code, int offset, __be32 info) |
d2acc3479 [INET]: Introduce... |
124 125 |
{ struct xfrm6_tunnel *handler; |
875168a93 net: tunnels shou... |
126 |
for_each_tunnel_rcu(tunnel6_handlers, handler) |
d2acc3479 [INET]: Introduce... |
127 128 129 |
if (!handler->err_handler(skb, opt, type, code, offset, info)) break; } |
41135cc83 net: constify str... |
130 |
static const struct inet6_protocol tunnel6_protocol = { |
d2acc3479 [INET]: Introduce... |
131 132 133 134 |
.handler = tunnel6_rcv, .err_handler = tunnel6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; |
41135cc83 net: constify str... |
135 |
static const struct inet6_protocol tunnel46_protocol = { |
73d605d1a [IPSEC]: changing... |
136 137 138 139 |
.handler = tunnel46_rcv, .err_handler = tunnel6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; |
d2acc3479 [INET]: Introduce... |
140 141 142 143 144 145 146 |
static int __init tunnel6_init(void) { if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) { printk(KERN_ERR "tunnel6 init(): can't add protocol "); return -EAGAIN; } |
73d605d1a [IPSEC]: changing... |
147 148 149 150 151 152 |
if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) { printk(KERN_ERR "tunnel6 init(): can't add protocol "); inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6); return -EAGAIN; } |
d2acc3479 [INET]: Introduce... |
153 154 155 156 157 |
return 0; } static void __exit tunnel6_fini(void) { |
73d605d1a [IPSEC]: changing... |
158 159 160 |
if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP)) printk(KERN_ERR "tunnel6 close: can't remove protocol "); |
d2acc3479 [INET]: Introduce... |
161 162 163 164 165 166 167 168 |
if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6)) printk(KERN_ERR "tunnel6 close: can't remove protocol "); } module_init(tunnel6_init); module_exit(tunnel6_fini); MODULE_LICENSE("GPL"); |