diff options
-rw-r--r-- | include/net/xfrm.h | 4 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 6 | ||||
-rw-r--r-- | net/ipv6/tunnel6.c | 43 | ||||
-rw-r--r-- | net/ipv6/xfrm6_input.c | 3 | ||||
-rw-r--r-- | net/ipv6/xfrm6_tunnel.c | 19 |
5 files changed, 62 insertions, 13 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 20be8beb9a11..92a1fc46ea59 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -952,8 +952,8 @@ extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi); | |||
952 | extern int xfrm6_rcv(struct sk_buff **pskb); | 952 | extern int xfrm6_rcv(struct sk_buff **pskb); |
953 | extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | 953 | extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, |
954 | xfrm_address_t *saddr, u8 proto); | 954 | xfrm_address_t *saddr, u8 proto); |
955 | extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler); | 955 | extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family); |
956 | extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler); | 956 | extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family); |
957 | extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); | 957 | extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); |
958 | extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); | 958 | extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); |
959 | extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); | 959 | extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 367b74832986..662edb826899 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -1128,7 +1128,7 @@ static int __init ip6_tunnel_init(void) | |||
1128 | { | 1128 | { |
1129 | int err; | 1129 | int err; |
1130 | 1130 | ||
1131 | if (xfrm6_tunnel_register(&ip6ip6_handler)) { | 1131 | if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) { |
1132 | printk(KERN_ERR "ip6ip6 init: can't register tunnel\n"); | 1132 | printk(KERN_ERR "ip6ip6 init: can't register tunnel\n"); |
1133 | return -EAGAIN; | 1133 | return -EAGAIN; |
1134 | } | 1134 | } |
@@ -1147,7 +1147,7 @@ static int __init ip6_tunnel_init(void) | |||
1147 | } | 1147 | } |
1148 | return 0; | 1148 | return 0; |
1149 | fail: | 1149 | fail: |
1150 | xfrm6_tunnel_deregister(&ip6ip6_handler); | 1150 | xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); |
1151 | return err; | 1151 | return err; |
1152 | } | 1152 | } |
1153 | 1153 | ||
@@ -1171,7 +1171,7 @@ static void __exit ip6ip6_destroy_tunnels(void) | |||
1171 | 1171 | ||
1172 | static void __exit ip6_tunnel_cleanup(void) | 1172 | static void __exit ip6_tunnel_cleanup(void) |
1173 | { | 1173 | { |
1174 | if (xfrm6_tunnel_deregister(&ip6ip6_handler)) | 1174 | if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6)) |
1175 | printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); | 1175 | printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); |
1176 | 1176 | ||
1177 | rtnl_lock(); | 1177 | rtnl_lock(); |
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 | ||
32 | static struct xfrm6_tunnel *tunnel6_handlers; | 32 | static struct xfrm6_tunnel *tunnel6_handlers; |
33 | static struct xfrm6_tunnel *tunnel46_handlers; | ||
33 | static DEFINE_MUTEX(tunnel6_mutex); | 34 | static DEFINE_MUTEX(tunnel6_mutex); |
34 | 35 | ||
35 | int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) | 36 | int 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 | ||
61 | EXPORT_SYMBOL(xfrm6_tunnel_register); | 63 | EXPORT_SYMBOL(xfrm6_tunnel_register); |
62 | 64 | ||
63 | int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) | 65 | int 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 | ||
109 | static 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 | |||
123 | drop: | ||
124 | kfree_skb(skb); | ||
125 | return 0; | ||
126 | } | ||
127 | |||
106 | static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 128 | static 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 | ||
144 | static struct inet6_protocol tunnel46_protocol = { | ||
145 | .handler = tunnel46_rcv, | ||
146 | .err_handler = tunnel6_err, | ||
147 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | ||
148 | }; | ||
149 | |||
122 | static int __init tunnel6_init(void) | 150 | static 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 | ||
131 | static void __exit tunnel6_fini(void) | 164 | static 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 | } |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 25250147bdc3..31f651f95096 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -40,7 +40,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi) | |||
40 | if (xfrm_nr == XFRM_MAX_DEPTH) | 40 | if (xfrm_nr == XFRM_MAX_DEPTH) |
41 | goto drop; | 41 | goto drop; |
42 | 42 | ||
43 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, nexthdr, AF_INET6); | 43 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, |
44 | nexthdr != IPPROTO_IPIP ? nexthdr : IPPROTO_IPV6, AF_INET6); | ||
44 | if (x == NULL) | 45 | if (x == NULL) |
45 | goto drop; | 46 | goto drop; |
46 | spin_lock(&x->lock); | 47 | spin_lock(&x->lock); |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index fb0228772f01..ee4b84a33ff4 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -339,17 +339,29 @@ static struct xfrm6_tunnel xfrm6_tunnel_handler = { | |||
339 | .priority = 2, | 339 | .priority = 2, |
340 | }; | 340 | }; |
341 | 341 | ||
342 | static struct xfrm6_tunnel xfrm46_tunnel_handler = { | ||
343 | .handler = xfrm6_tunnel_rcv, | ||
344 | .err_handler = xfrm6_tunnel_err, | ||
345 | .priority = 2, | ||
346 | }; | ||
347 | |||
342 | static int __init xfrm6_tunnel_init(void) | 348 | static int __init xfrm6_tunnel_init(void) |
343 | { | 349 | { |
344 | if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) | 350 | if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) |
345 | return -EAGAIN; | 351 | return -EAGAIN; |
346 | 352 | ||
347 | if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) { | 353 | if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) { |
354 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); | ||
355 | return -EAGAIN; | ||
356 | } | ||
357 | if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) { | ||
358 | xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); | ||
348 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); | 359 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); |
349 | return -EAGAIN; | 360 | return -EAGAIN; |
350 | } | 361 | } |
351 | if (xfrm6_tunnel_spi_init() < 0) { | 362 | if (xfrm6_tunnel_spi_init() < 0) { |
352 | xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); | 363 | xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); |
364 | xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); | ||
353 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); | 365 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); |
354 | return -EAGAIN; | 366 | return -EAGAIN; |
355 | } | 367 | } |
@@ -359,7 +371,8 @@ static int __init xfrm6_tunnel_init(void) | |||
359 | static void __exit xfrm6_tunnel_fini(void) | 371 | static void __exit xfrm6_tunnel_fini(void) |
360 | { | 372 | { |
361 | xfrm6_tunnel_spi_fini(); | 373 | xfrm6_tunnel_spi_fini(); |
362 | xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); | 374 | xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); |
375 | xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); | ||
363 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); | 376 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); |
364 | } | 377 | } |
365 | 378 | ||