aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>2006-11-30 00:43:28 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:23:42 -0400
commit502b093569e48db264831be7966e1c447de2f52f (patch)
tree7b9bc3f76ce37d6f907cfe8fa18317ad11e6eb1c
parent3144581cb0b4b1ef897470195128cc1c8dc037b6 (diff)
[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>
-rw-r--r--net/ipv6/ip6_tunnel.c37
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
386static int 386static int
387ip6_tnl_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 387ip6_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
673static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, 676static 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
723static int ip4ip6_rcv(struct sk_buff *skb) 732static 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
728static int ip6ip6_rcv(struct sk_buff *skb) 738static 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
733struct ipv6_tel_txoption { 744struct 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
1324ip6_tnl_dev_init_gen(struct net_device *dev) 1339ip6_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;