Blame view

net/ipv6/tunnel6.c 4.65 KB
d2acc3479   Herbert Xu   [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   Herbert Xu   [INET]: Move no-t...
21
  #include <linux/icmpv6.h>
d2acc3479   Herbert Xu   [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   Tejun Heo   include cleanup: ...
27
  #include <linux/slab.h>
50fba2aa7   Herbert Xu   [INET]: Move no-t...
28
  #include <net/ipv6.h>
d2acc3479   Herbert Xu   [INET]: Introduce...
29
30
  #include <net/protocol.h>
  #include <net/xfrm.h>
6f0bcf152   Eric Dumazet   tunnels: add _rcu...
31
32
  static struct xfrm6_tunnel __rcu *tunnel6_handlers __read_mostly;
  static struct xfrm6_tunnel __rcu *tunnel46_handlers __read_mostly;
d2acc3479   Herbert Xu   [INET]: Introduce...
33
  static DEFINE_MUTEX(tunnel6_mutex);
73d605d1a   Kazunori MIYAZAWA   [IPSEC]: changing...
34
  int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family)
d2acc3479   Herbert Xu   [INET]: Introduce...
35
  {
6f0bcf152   Eric Dumazet   tunnels: add _rcu...
36
37
  	struct xfrm6_tunnel __rcu **pprev;
  	struct xfrm6_tunnel *t;
d2acc3479   Herbert Xu   [INET]: Introduce...
38
39
40
41
  	int ret = -EEXIST;
  	int priority = handler->priority;
  
  	mutex_lock(&tunnel6_mutex);
73d605d1a   Kazunori MIYAZAWA   [IPSEC]: changing...
42
  	for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
6f0bcf152   Eric Dumazet   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   Herbert Xu   [INET]: Introduce...
47
  			break;
6f0bcf152   Eric Dumazet   tunnels: add _rcu...
48
  		if (t->priority == priority)
d2acc3479   Herbert Xu   [INET]: Introduce...
49
50
51
52
  			goto err;
  	}
  
  	handler->next = *pprev;
49d61e239   Eric Dumazet   tunnels: missing ...
53
  	rcu_assign_pointer(*pprev, handler);
d2acc3479   Herbert Xu   [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   Kazunori MIYAZAWA   [IPSEC]: changing...
64
  int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family)
d2acc3479   Herbert Xu   [INET]: Introduce...
65
  {
6f0bcf152   Eric Dumazet   tunnels: add _rcu...
66
67
  	struct xfrm6_tunnel __rcu **pprev;
  	struct xfrm6_tunnel *t;
d2acc3479   Herbert Xu   [INET]: Introduce...
68
69
70
  	int ret = -ENOENT;
  
  	mutex_lock(&tunnel6_mutex);
73d605d1a   Kazunori MIYAZAWA   [IPSEC]: changing...
71
  	for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
6f0bcf152   Eric Dumazet   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   Herbert Xu   [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   Eric Dumazet   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   Herbert Xu   [IPV6]: Replace s...
94
  static int tunnel6_rcv(struct sk_buff *skb)
d2acc3479   Herbert Xu   [INET]: Introduce...
95
  {
d2acc3479   Herbert Xu   [INET]: Introduce...
96
  	struct xfrm6_tunnel *handler;
50fba2aa7   Herbert Xu   [INET]: Move no-t...
97
98
  	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
  		goto drop;
875168a93   Eric Dumazet   net: tunnels shou...
99
  	for_each_tunnel_rcu(tunnel6_handlers, handler)
d2acc3479   Herbert Xu   [INET]: Introduce...
100
101
  		if (!handler->handler(skb))
  			return 0;
3ffe533c8   Alexey Dobriyan   ipv6: drop unused...
102
  	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
50fba2aa7   Herbert Xu   [INET]: Move no-t...
103
104
  
  drop:
d2acc3479   Herbert Xu   [INET]: Introduce...
105
106
107
  	kfree_skb(skb);
  	return 0;
  }
e5bbef20e   Herbert Xu   [IPV6]: Replace s...
108
  static int tunnel46_rcv(struct sk_buff *skb)
73d605d1a   Kazunori MIYAZAWA   [IPSEC]: changing...
109
  {
73d605d1a   Kazunori MIYAZAWA   [IPSEC]: changing...
110
  	struct xfrm6_tunnel *handler;
828363723   Colin   [IPV6] TUNNEL6: F...
111
  	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
73d605d1a   Kazunori MIYAZAWA   [IPSEC]: changing...
112
  		goto drop;
875168a93   Eric Dumazet   net: tunnels shou...
113
  	for_each_tunnel_rcu(tunnel46_handlers, handler)
73d605d1a   Kazunori MIYAZAWA   [IPSEC]: changing...
114
115
  		if (!handler->handler(skb))
  			return 0;
3ffe533c8   Alexey Dobriyan   ipv6: drop unused...
116
  	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
73d605d1a   Kazunori MIYAZAWA   [IPSEC]: changing...
117
118
119
120
121
  
  drop:
  	kfree_skb(skb);
  	return 0;
  }
d2acc3479   Herbert Xu   [INET]: Introduce...
122
  static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
d5fdd6bab   Brian Haley   ipv6: Use correct...
123
  			u8 type, u8 code, int offset, __be32 info)
d2acc3479   Herbert Xu   [INET]: Introduce...
124
125
  {
  	struct xfrm6_tunnel *handler;
875168a93   Eric Dumazet   net: tunnels shou...
126
  	for_each_tunnel_rcu(tunnel6_handlers, handler)
d2acc3479   Herbert Xu   [INET]: Introduce...
127
128
129
  		if (!handler->err_handler(skb, opt, type, code, offset, info))
  			break;
  }
41135cc83   Alexey Dobriyan   net: constify str...
130
  static const struct inet6_protocol tunnel6_protocol = {
d2acc3479   Herbert Xu   [INET]: Introduce...
131
132
133
134
  	.handler	= tunnel6_rcv,
  	.err_handler	= tunnel6_err,
  	.flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
  };
41135cc83   Alexey Dobriyan   net: constify str...
135
  static const struct inet6_protocol tunnel46_protocol = {
73d605d1a   Kazunori MIYAZAWA   [IPSEC]: changing...
136
137
138
139
  	.handler	= tunnel46_rcv,
  	.err_handler	= tunnel6_err,
  	.flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
  };
d2acc3479   Herbert Xu   [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   Kazunori MIYAZAWA   [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   Herbert Xu   [INET]: Introduce...
153
154
155
156
157
  	return 0;
  }
  
  static void __exit tunnel6_fini(void)
  {
73d605d1a   Kazunori MIYAZAWA   [IPSEC]: changing...
158
159
160
  	if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP))
  		printk(KERN_ERR "tunnel6 close: can't remove protocol
  ");
d2acc3479   Herbert Xu   [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");