Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[IPV6] IP6TUNNEL: Enable to control the handled inner protocol.

ip6_tunnel before supporting IPv4/IPv6 tunnel allows only IPPROTO_IPV6
in configurations from userland. This allows userland to set IPPROTO_IPIP
and 0(wildcard). ip6_tunnel only handles allowed inner protocols.

Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yasuyuki Kozakai and committed by
David S. Miller
502b0935 3144581c

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