aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tunnel6.c
diff options
context:
space:
mode:
authorKazunori MIYAZAWA <miyazawa@linux-ipv6.org>2007-02-13 15:55:55 -0500
committerDavid S. Miller <davem@davemloft.net>2007-02-13 15:55:55 -0500
commit73d605d1abbd70ef67b7660cf2ff177259960756 (patch)
tree3b183bc597044785eef7cc8efefb41fbac097bf5 /net/ipv6/tunnel6.c
parentc73cb5a2d607b5b95a06a54d8291ddb659b348b6 (diff)
[IPSEC]: changing API of xfrm6_tunnel_register
This patch changes xfrm6_tunnel register and deregister interface to prepare for solving the conflict of device tunnels with inter address family IPsec tunnel. There is no device which conflicts with IPv4 over IPv6 IPsec tunnel. Signed-off-by: Kazunori MIYAZAWA <miyazawa@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/tunnel6.c')
-rw-r--r--net/ipv6/tunnel6.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index 918d07dd1219..23e2809878ae 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -30,9 +30,10 @@
30#include <net/xfrm.h> 30#include <net/xfrm.h>
31 31
32static struct xfrm6_tunnel *tunnel6_handlers; 32static struct xfrm6_tunnel *tunnel6_handlers;
33static struct xfrm6_tunnel *tunnel46_handlers;
33static DEFINE_MUTEX(tunnel6_mutex); 34static DEFINE_MUTEX(tunnel6_mutex);
34 35
35int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) 36int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family)
36{ 37{
37 struct xfrm6_tunnel **pprev; 38 struct xfrm6_tunnel **pprev;
38 int ret = -EEXIST; 39 int ret = -EEXIST;
@@ -40,7 +41,8 @@ int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
40 41
41 mutex_lock(&tunnel6_mutex); 42 mutex_lock(&tunnel6_mutex);
42 43
43 for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) { 44 for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
45 *pprev; pprev = &(*pprev)->next) {
44 if ((*pprev)->priority > priority) 46 if ((*pprev)->priority > priority)
45 break; 47 break;
46 if ((*pprev)->priority == priority) 48 if ((*pprev)->priority == priority)
@@ -60,14 +62,15 @@ err:
60 62
61EXPORT_SYMBOL(xfrm6_tunnel_register); 63EXPORT_SYMBOL(xfrm6_tunnel_register);
62 64
63int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) 65int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family)
64{ 66{
65 struct xfrm6_tunnel **pprev; 67 struct xfrm6_tunnel **pprev;
66 int ret = -ENOENT; 68 int ret = -ENOENT;
67 69
68 mutex_lock(&tunnel6_mutex); 70 mutex_lock(&tunnel6_mutex);
69 71
70 for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) { 72 for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
73 *pprev; pprev = &(*pprev)->next) {
71 if (*pprev == handler) { 74 if (*pprev == handler) {
72 *pprev = handler->next; 75 *pprev = handler->next;
73 ret = 0; 76 ret = 0;
@@ -103,6 +106,25 @@ drop:
103 return 0; 106 return 0;
104} 107}
105 108
109static int tunnel46_rcv(struct sk_buff **pskb)
110{
111 struct sk_buff *skb = *pskb;
112 struct xfrm6_tunnel *handler;
113
114 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
115 goto drop;
116
117 for (handler = tunnel46_handlers; handler; handler = handler->next)
118 if (!handler->handler(skb))
119 return 0;
120
121 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
122
123drop:
124 kfree_skb(skb);
125 return 0;
126}
127
106static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 128static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
107 int type, int code, int offset, __be32 info) 129 int type, int code, int offset, __be32 info)
108{ 130{
@@ -119,17 +141,30 @@ static struct inet6_protocol tunnel6_protocol = {
119 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 141 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
120}; 142};
121 143
144static struct inet6_protocol tunnel46_protocol = {
145 .handler = tunnel46_rcv,
146 .err_handler = tunnel6_err,
147 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
148};
149
122static int __init tunnel6_init(void) 150static int __init tunnel6_init(void)
123{ 151{
124 if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) { 152 if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) {
125 printk(KERN_ERR "tunnel6 init(): can't add protocol\n"); 153 printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
126 return -EAGAIN; 154 return -EAGAIN;
127 } 155 }
156 if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) {
157 printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
158 inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6);
159 return -EAGAIN;
160 }
128 return 0; 161 return 0;
129} 162}
130 163
131static void __exit tunnel6_fini(void) 164static void __exit tunnel6_fini(void)
132{ 165{
166 if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP))
167 printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
133 if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6)) 168 if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
134 printk(KERN_ERR "tunnel6 close: can't remove protocol\n"); 169 printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
135} 170}