X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Fip6_tunnel.c;h=48597538db3f05c57de09834de9d715cbd36444e;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=a995796b5a577fb7b0f4a947d54a85897143a1ab;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index a995796b5..48597538d 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -390,7 +391,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) * to the specifications in RFC 2473. **/ -static int +static void ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, int type, int code, int offset, __u32 info) { @@ -401,7 +402,6 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, int rel_code = ICMPV6_ADDR_UNREACH; __u32 rel_info = 0; __u16 len; - int err = -ENOENT; /* If the packet doesn't contain the original IPv6 header we are in trouble since we might need the source address for further @@ -411,8 +411,6 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if ((t = ip6ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL) goto out; - err = 0; - switch (type) { __u32 teli; struct ipv6_tlv_tnl_enc_lim *tel; @@ -494,7 +492,6 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, } out: read_unlock(&ip6ip6_lock); - return err; } static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph, @@ -514,11 +511,15 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph, **/ static int -ip6ip6_rcv(struct sk_buff *skb) +ip6ip6_rcv(struct sk_buff **pskb) { + struct sk_buff *skb = *pskb; struct ipv6hdr *ipv6h; struct ip6_tnl *t; + if (!pskb_may_pull(skb, sizeof (*ipv6h))) + goto discard; + ipv6h = skb->nh.ipv6h; read_lock(&ip6ip6_lock); @@ -526,7 +527,8 @@ ip6ip6_rcv(struct sk_buff *skb) if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { read_unlock(&ip6ip6_lock); - goto discard; + kfree_skb(skb); + return 0; } if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) { @@ -553,11 +555,9 @@ ip6ip6_rcv(struct sk_buff *skb) return 0; } read_unlock(&ip6ip6_lock); - return 1; - + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev); discard: - kfree_skb(skb); - return 0; + return 1; } static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) @@ -1112,12 +1112,39 @@ ip6ip6_fb_tnl_dev_init(struct net_device *dev) return 0; } +#ifdef CONFIG_INET6_TUNNEL static struct xfrm6_tunnel ip6ip6_handler = { .handler = ip6ip6_rcv, .err_handler = ip6ip6_err, - .priority = 1, }; +static inline int ip6ip6_register(void) +{ + return xfrm6_tunnel_register(&ip6ip6_handler); +} + +static inline int ip6ip6_unregister(void) +{ + return xfrm6_tunnel_deregister(&ip6ip6_handler); +} +#else +static struct inet6_protocol xfrm6_tunnel_protocol = { + .handler = ip6ip6_rcv, + .err_handler = ip6ip6_err, + .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, +}; + +static inline int ip6ip6_register(void) +{ + return inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6); +} + +static inline int ip6ip6_unregister(void) +{ + return inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6); +} +#endif + /** * ip6_tunnel_init - register protocol and reserve needed resources * @@ -1128,7 +1155,7 @@ static int __init ip6_tunnel_init(void) { int err; - if (xfrm6_tunnel_register(&ip6ip6_handler)) { + if (ip6ip6_register() < 0) { printk(KERN_ERR "ip6ip6 init: can't register tunnel\n"); return -EAGAIN; } @@ -1147,7 +1174,7 @@ static int __init ip6_tunnel_init(void) } return 0; fail: - xfrm6_tunnel_deregister(&ip6ip6_handler); + ip6ip6_unregister(); return err; } @@ -1157,7 +1184,7 @@ fail: static void __exit ip6_tunnel_cleanup(void) { - if (xfrm6_tunnel_deregister(&ip6ip6_handler)) + if (ip6ip6_unregister() < 0) printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); unregister_netdev(ip6ip6_fb_tnl_dev);