diff options
Diffstat (limited to 'net/ipv6/ip6_tunnel.c')
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 70684e0d31f1..d8c84d8d7cf8 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -384,7 +384,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) | |||
384 | **/ | 384 | **/ |
385 | 385 | ||
386 | static int | 386 | static int |
387 | ip6_tnl_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 387 | ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, |
388 | int *type, int *code, int *msg, __be32 *info, int offset) | 388 | int *type, int *code, int *msg, __be32 *info, int offset) |
389 | { | 389 | { |
390 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; | 390 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; |
@@ -404,6 +404,9 @@ ip6_tnl_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
404 | if ((t = ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL) | 404 | if ((t = ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL) |
405 | goto out; | 405 | goto out; |
406 | 406 | ||
407 | if (t->parms.proto != ipproto && t->parms.proto != 0) | ||
408 | goto out; | ||
409 | |||
407 | err = 0; | 410 | err = 0; |
408 | 411 | ||
409 | switch (*type) { | 412 | switch (*type) { |
@@ -487,8 +490,8 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
487 | struct flowi fl; | 490 | struct flowi fl; |
488 | struct rtable *rt; | 491 | struct rtable *rt; |
489 | 492 | ||
490 | err = ip6_tnl_err(skb, opt, &rel_type, &rel_code, &rel_msg, &rel_info, | 493 | err = ip6_tnl_err(skb, IPPROTO_IPIP, opt, &rel_type, &rel_code, |
491 | offset); | 494 | &rel_msg, &rel_info, offset); |
492 | if (err < 0) | 495 | if (err < 0) |
493 | return err; | 496 | return err; |
494 | 497 | ||
@@ -581,8 +584,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
581 | __u32 rel_info = info; | 584 | __u32 rel_info = info; |
582 | int err; | 585 | int err; |
583 | 586 | ||
584 | err = ip6_tnl_err(skb, opt, &rel_type, &rel_code, &rel_msg, &rel_info, | 587 | err = ip6_tnl_err(skb, IPPROTO_IPV6, opt, &rel_type, &rel_code, |
585 | offset); | 588 | &rel_msg, &rel_info, offset); |
586 | if (err < 0) | 589 | if (err < 0) |
587 | return err; | 590 | return err; |
588 | 591 | ||
@@ -671,6 +674,7 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) | |||
671 | **/ | 674 | **/ |
672 | 675 | ||
673 | static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | 676 | static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, |
677 | __u8 ipproto, | ||
674 | void (*dscp_ecn_decapsulate)(struct ip6_tnl *t, | 678 | void (*dscp_ecn_decapsulate)(struct ip6_tnl *t, |
675 | struct ipv6hdr *ipv6h, | 679 | struct ipv6hdr *ipv6h, |
676 | struct sk_buff *skb)) | 680 | struct sk_buff *skb)) |
@@ -683,6 +687,11 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
683 | read_lock(&ip6_tnl_lock); | 687 | read_lock(&ip6_tnl_lock); |
684 | 688 | ||
685 | if ((t = ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { | 689 | if ((t = ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { |
690 | if (t->parms.proto != ipproto && t->parms.proto != 0) { | ||
691 | read_unlock(&ip6_tnl_lock); | ||
692 | goto discard; | ||
693 | } | ||
694 | |||
686 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 695 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
687 | read_unlock(&ip6_tnl_lock); | 696 | read_unlock(&ip6_tnl_lock); |
688 | goto discard; | 697 | goto discard; |
@@ -722,12 +731,14 @@ discard: | |||
722 | 731 | ||
723 | static int ip4ip6_rcv(struct sk_buff *skb) | 732 | static int ip4ip6_rcv(struct sk_buff *skb) |
724 | { | 733 | { |
725 | return ip6_tnl_rcv(skb, ETH_P_IP, ip4ip6_dscp_ecn_decapsulate); | 734 | return ip6_tnl_rcv(skb, ETH_P_IP, IPPROTO_IPIP, |
735 | ip4ip6_dscp_ecn_decapsulate); | ||
726 | } | 736 | } |
727 | 737 | ||
728 | static int ip6ip6_rcv(struct sk_buff *skb) | 738 | static int ip6ip6_rcv(struct sk_buff *skb) |
729 | { | 739 | { |
730 | return ip6_tnl_rcv(skb, ETH_P_IPV6, ip6ip6_dscp_ecn_decapsulate); | 740 | return ip6_tnl_rcv(skb, ETH_P_IPV6, IPPROTO_IPV6, |
741 | ip6ip6_dscp_ecn_decapsulate); | ||
731 | } | 742 | } |
732 | 743 | ||
733 | struct ipv6_tel_txoption { | 744 | struct ipv6_tel_txoption { |
@@ -939,7 +950,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
939 | __u32 mtu; | 950 | __u32 mtu; |
940 | int err; | 951 | int err; |
941 | 952 | ||
942 | if (!ip6_tnl_xmit_ctl(t)) | 953 | if ((t->parms.proto != IPPROTO_IPIP && t->parms.proto != 0) || |
954 | !ip6_tnl_xmit_ctl(t)) | ||
943 | return -1; | 955 | return -1; |
944 | 956 | ||
945 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | 957 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) |
@@ -978,7 +990,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
978 | __u32 mtu; | 990 | __u32 mtu; |
979 | int err; | 991 | int err; |
980 | 992 | ||
981 | if (!ip6_tnl_xmit_ctl(t) || ip6_tnl_addr_conflict(t, ipv6h)) | 993 | if ((t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) || |
994 | !ip6_tnl_xmit_ctl(t) || ip6_tnl_addr_conflict(t, ipv6h)) | ||
982 | return -1; | 995 | return -1; |
983 | 996 | ||
984 | if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) { | 997 | if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) { |
@@ -1140,6 +1153,7 @@ ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) | |||
1140 | t->parms.encap_limit = p->encap_limit; | 1153 | t->parms.encap_limit = p->encap_limit; |
1141 | t->parms.flowinfo = p->flowinfo; | 1154 | t->parms.flowinfo = p->flowinfo; |
1142 | t->parms.link = p->link; | 1155 | t->parms.link = p->link; |
1156 | t->parms.proto = p->proto; | ||
1143 | ip6_tnl_dst_reset(t); | 1157 | ip6_tnl_dst_reset(t); |
1144 | ip6_tnl_link_config(t); | 1158 | ip6_tnl_link_config(t); |
1145 | return 0; | 1159 | return 0; |
@@ -1205,7 +1219,8 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1205 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) | 1219 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) |
1206 | break; | 1220 | break; |
1207 | err = -EINVAL; | 1221 | err = -EINVAL; |
1208 | if (p.proto != IPPROTO_IPV6) | 1222 | if (p.proto != IPPROTO_IPV6 && p.proto != IPPROTO_IPIP && |
1223 | p.proto != 0) | ||
1209 | break; | 1224 | break; |
1210 | t = ip6_tnl_locate(&p, cmd == SIOCADDTUNNEL); | 1225 | t = ip6_tnl_locate(&p, cmd == SIOCADDTUNNEL); |
1211 | if (dev != ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) { | 1226 | if (dev != ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) { |
@@ -1324,7 +1339,6 @@ static inline void | |||
1324 | ip6_tnl_dev_init_gen(struct net_device *dev) | 1339 | ip6_tnl_dev_init_gen(struct net_device *dev) |
1325 | { | 1340 | { |
1326 | struct ip6_tnl *t = netdev_priv(dev); | 1341 | struct ip6_tnl *t = netdev_priv(dev); |
1327 | t->fl.proto = IPPROTO_IPV6; | ||
1328 | t->dev = dev; | 1342 | t->dev = dev; |
1329 | strcpy(t->parms.name, dev->name); | 1343 | strcpy(t->parms.name, dev->name); |
1330 | } | 1344 | } |
@@ -1355,6 +1369,7 @@ ip6_fb_tnl_dev_init(struct net_device *dev) | |||
1355 | { | 1369 | { |
1356 | struct ip6_tnl *t = netdev_priv(dev); | 1370 | struct ip6_tnl *t = netdev_priv(dev); |
1357 | ip6_tnl_dev_init_gen(dev); | 1371 | ip6_tnl_dev_init_gen(dev); |
1372 | t->parms.proto = IPPROTO_IPV6; | ||
1358 | dev_hold(dev); | 1373 | dev_hold(dev); |
1359 | tnls_wc[0] = t; | 1374 | tnls_wc[0] = t; |
1360 | return 0; | 1375 | return 0; |