aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/sit.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/sit.c')
-rw-r--r--net/ipv6/sit.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 4d3cf301e1fc..862ed7c52c38 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -216,7 +216,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
216} 216}
217 217
218 218
219static void ipip6_err(struct sk_buff *skb, u32 info) 219static int ipip6_err(struct sk_buff *skb, u32 info)
220{ 220{
221#ifndef I_WISH_WORLD_WERE_PERFECT 221#ifndef I_WISH_WORLD_WERE_PERFECT
222 222
@@ -228,21 +228,22 @@ static void ipip6_err(struct sk_buff *skb, u32 info)
228 int type = skb->h.icmph->type; 228 int type = skb->h.icmph->type;
229 int code = skb->h.icmph->code; 229 int code = skb->h.icmph->code;
230 struct ip_tunnel *t; 230 struct ip_tunnel *t;
231 int err;
231 232
232 switch (type) { 233 switch (type) {
233 default: 234 default:
234 case ICMP_PARAMETERPROB: 235 case ICMP_PARAMETERPROB:
235 return; 236 return 0;
236 237
237 case ICMP_DEST_UNREACH: 238 case ICMP_DEST_UNREACH:
238 switch (code) { 239 switch (code) {
239 case ICMP_SR_FAILED: 240 case ICMP_SR_FAILED:
240 case ICMP_PORT_UNREACH: 241 case ICMP_PORT_UNREACH:
241 /* Impossible event. */ 242 /* Impossible event. */
242 return; 243 return 0;
243 case ICMP_FRAG_NEEDED: 244 case ICMP_FRAG_NEEDED:
244 /* Soft state for pmtu is maintained by IP core. */ 245 /* Soft state for pmtu is maintained by IP core. */
245 return; 246 return 0;
246 default: 247 default:
247 /* All others are translated to HOST_UNREACH. 248 /* All others are translated to HOST_UNREACH.
248 rfc2003 contains "deep thoughts" about NET_UNREACH, 249 rfc2003 contains "deep thoughts" about NET_UNREACH,
@@ -253,14 +254,18 @@ static void ipip6_err(struct sk_buff *skb, u32 info)
253 break; 254 break;
254 case ICMP_TIME_EXCEEDED: 255 case ICMP_TIME_EXCEEDED:
255 if (code != ICMP_EXC_TTL) 256 if (code != ICMP_EXC_TTL)
256 return; 257 return 0;
257 break; 258 break;
258 } 259 }
259 260
261 err = -ENOENT;
262
260 read_lock(&ipip6_lock); 263 read_lock(&ipip6_lock);
261 t = ipip6_tunnel_lookup(iph->daddr, iph->saddr); 264 t = ipip6_tunnel_lookup(iph->daddr, iph->saddr);
262 if (t == NULL || t->parms.iph.daddr == 0) 265 if (t == NULL || t->parms.iph.daddr == 0)
263 goto out; 266 goto out;
267
268 err = 0;
264 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 269 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
265 goto out; 270 goto out;
266 271
@@ -271,7 +276,7 @@ static void ipip6_err(struct sk_buff *skb, u32 info)
271 t->err_time = jiffies; 276 t->err_time = jiffies;
272out: 277out:
273 read_unlock(&ipip6_lock); 278 read_unlock(&ipip6_lock);
274 return; 279 return err;
275#else 280#else
276 struct iphdr *iph = (struct iphdr*)dp; 281 struct iphdr *iph = (struct iphdr*)dp;
277 int hlen = iph->ihl<<2; 282 int hlen = iph->ihl<<2;
@@ -332,7 +337,7 @@ out:
332 /* Prepare fake skb to feed it to icmpv6_send */ 337 /* Prepare fake skb to feed it to icmpv6_send */
333 skb2 = skb_clone(skb, GFP_ATOMIC); 338 skb2 = skb_clone(skb, GFP_ATOMIC);
334 if (skb2 == NULL) 339 if (skb2 == NULL)
335 return; 340 return 0;
336 dst_release(skb2->dst); 341 dst_release(skb2->dst);
337 skb2->dst = NULL; 342 skb2->dst = NULL;
338 skb_pull(skb2, skb->data - (u8*)iph6); 343 skb_pull(skb2, skb->data - (u8*)iph6);
@@ -355,7 +360,7 @@ out:
355 } 360 }
356 } 361 }
357 kfree_skb(skb2); 362 kfree_skb(skb2);
358 return; 363 return 0;
359#endif 364#endif
360} 365}
361 366
@@ -791,9 +796,10 @@ static int __init ipip6_fb_tunnel_init(struct net_device *dev)
791 return 0; 796 return 0;
792} 797}
793 798
794static struct net_protocol sit_protocol = { 799static struct xfrm_tunnel sit_handler = {
795 .handler = ipip6_rcv, 800 .handler = ipip6_rcv,
796 .err_handler = ipip6_err, 801 .err_handler = ipip6_err,
802 .priority = 1,
797}; 803};
798 804
799static void __exit sit_destroy_tunnels(void) 805static void __exit sit_destroy_tunnels(void)
@@ -812,7 +818,7 @@ static void __exit sit_destroy_tunnels(void)
812 818
813static void __exit sit_cleanup(void) 819static void __exit sit_cleanup(void)
814{ 820{
815 inet_del_protocol(&sit_protocol, IPPROTO_IPV6); 821 xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
816 822
817 rtnl_lock(); 823 rtnl_lock();
818 sit_destroy_tunnels(); 824 sit_destroy_tunnels();
@@ -826,7 +832,7 @@ static int __init sit_init(void)
826 832
827 printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n"); 833 printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n");
828 834
829 if (inet_add_protocol(&sit_protocol, IPPROTO_IPV6) < 0) { 835 if (xfrm4_tunnel_register(&sit_handler, AF_INET6) < 0) {
830 printk(KERN_INFO "sit init: Can't add protocol\n"); 836 printk(KERN_INFO "sit init: Can't add protocol\n");
831 return -EAGAIN; 837 return -EAGAIN;
832 } 838 }
@@ -848,7 +854,7 @@ static int __init sit_init(void)
848 err2: 854 err2:
849 free_netdev(ipip6_fb_tunnel_dev); 855 free_netdev(ipip6_fb_tunnel_dev);
850 err1: 856 err1:
851 inet_del_protocol(&sit_protocol, IPPROTO_IPV6); 857 xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
852 goto out; 858 goto out;
853} 859}
854 860