aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2014-11-05 02:02:48 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-06 14:19:19 -0500
commitd50051407f136028108cfda068d55ef053a54fe1 (patch)
tree012d164d745342f453d5fed4619884839f51fbc0 /net/ipv6
parente1b2cb655060e081e73b384b1fc8b2e978f73467 (diff)
ipv6: Allow sending packets through tunnels with wildcard endpoints
Currently we need the IP6_TNL_F_CAP_XMIT capabiltiy to transmit packets through an ipv6 tunnel. This capability is set when the tunnel gets configured, based on the tunnel endpoint addresses. On tunnels with wildcard tunnel endpoints, we need to do the capabiltiy checking on a per packet basis like it is done in the receive path. This patch extends ip6_tnl_xmit_ctl() to take local and remote addresses as parameters to allow for per packet capabiltiy checking. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6_gre.c2
-rw-r--r--net/ipv6/ip6_tunnel.c23
-rw-r--r--net/ipv6/ip6_vti.c10
3 files changed, 24 insertions, 11 deletions
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 12c3c8ef3849..1fcf62ea5eb4 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -902,7 +902,7 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
902 struct net_device_stats *stats = &t->dev->stats; 902 struct net_device_stats *stats = &t->dev->stats;
903 int ret; 903 int ret;
904 904
905 if (!ip6_tnl_xmit_ctl(t)) 905 if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr))
906 goto tx_err; 906 goto tx_err;
907 907
908 switch (skb->protocol) { 908 switch (skb->protocol) {
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 8c97cd1048c2..a8f94ff9c606 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -909,24 +909,28 @@ ip6_tnl_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr)
909 return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); 909 return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr);
910} 910}
911 911
912int ip6_tnl_xmit_ctl(struct ip6_tnl *t) 912int ip6_tnl_xmit_ctl(struct ip6_tnl *t,
913 const struct in6_addr *laddr,
914 const struct in6_addr *raddr)
913{ 915{
914 struct __ip6_tnl_parm *p = &t->parms; 916 struct __ip6_tnl_parm *p = &t->parms;
915 int ret = 0; 917 int ret = 0;
916 struct net *net = t->net; 918 struct net *net = t->net;
917 919
918 if (p->flags & IP6_TNL_F_CAP_XMIT) { 920 if ((p->flags & IP6_TNL_F_CAP_XMIT) ||
921 ((p->flags & IP6_TNL_F_CAP_PER_PACKET) &&
922 (ip6_tnl_get_cap(t, laddr, raddr) & IP6_TNL_F_CAP_XMIT))) {
919 struct net_device *ldev = NULL; 923 struct net_device *ldev = NULL;
920 924
921 rcu_read_lock(); 925 rcu_read_lock();
922 if (p->link) 926 if (p->link)
923 ldev = dev_get_by_index_rcu(net, p->link); 927 ldev = dev_get_by_index_rcu(net, p->link);
924 928
925 if (unlikely(!ipv6_chk_addr(net, &p->laddr, ldev, 0))) 929 if (unlikely(!ipv6_chk_addr(net, laddr, ldev, 0)))
926 pr_warn("%s xmit: Local address not yet configured!\n", 930 pr_warn("%s xmit: Local address not yet configured!\n",
927 p->name); 931 p->name);
928 else if (!ipv6_addr_is_multicast(&p->raddr) && 932 else if (!ipv6_addr_is_multicast(raddr) &&
929 unlikely(ipv6_chk_addr(net, &p->raddr, NULL, 0))) 933 unlikely(ipv6_chk_addr(net, raddr, NULL, 0)))
930 pr_warn("%s xmit: Routing loop! Remote address found on this node!\n", 934 pr_warn("%s xmit: Routing loop! Remote address found on this node!\n",
931 p->name); 935 p->name);
932 else 936 else
@@ -977,6 +981,10 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
977 981
978 if (!fl6->flowi6_mark) 982 if (!fl6->flowi6_mark)
979 dst = ip6_tnl_dst_check(t); 983 dst = ip6_tnl_dst_check(t);
984
985 if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr))
986 goto tx_err_link_failure;
987
980 if (!dst) { 988 if (!dst) {
981 ndst = ip6_route_output(net, NULL, fl6); 989 ndst = ip6_route_output(net, NULL, fl6);
982 990
@@ -1086,8 +1094,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1086 int err; 1094 int err;
1087 1095
1088 tproto = ACCESS_ONCE(t->parms.proto); 1096 tproto = ACCESS_ONCE(t->parms.proto);
1089 if ((tproto != IPPROTO_IPIP && tproto != 0) || 1097 if (tproto != IPPROTO_IPIP && tproto != 0)
1090 !ip6_tnl_xmit_ctl(t))
1091 return -1; 1098 return -1;
1092 1099
1093 if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) 1100 if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
@@ -1131,7 +1138,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1131 1138
1132 tproto = ACCESS_ONCE(t->parms.proto); 1139 tproto = ACCESS_ONCE(t->parms.proto);
1133 if ((tproto != IPPROTO_IPV6 && tproto != 0) || 1140 if ((tproto != IPPROTO_IPV6 && tproto != 0) ||
1134 !ip6_tnl_xmit_ctl(t) || ip6_tnl_addr_conflict(t, ipv6h)) 1141 ip6_tnl_addr_conflict(t, ipv6h))
1135 return -1; 1142 return -1;
1136 1143
1137 offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb)); 1144 offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index d440bb585524..0e8e97e0d38b 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -416,6 +416,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
416 struct net_device_stats *stats = &t->dev->stats; 416 struct net_device_stats *stats = &t->dev->stats;
417 struct dst_entry *dst = skb_dst(skb); 417 struct dst_entry *dst = skb_dst(skb);
418 struct net_device *tdev; 418 struct net_device *tdev;
419 struct xfrm_state *x;
419 int err = -1; 420 int err = -1;
420 421
421 if (!dst) 422 if (!dst)
@@ -429,7 +430,12 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
429 goto tx_err_link_failure; 430 goto tx_err_link_failure;
430 } 431 }
431 432
432 if (!vti6_state_check(dst->xfrm, &t->parms.raddr, &t->parms.laddr)) 433 x = dst->xfrm;
434 if (!vti6_state_check(x, &t->parms.raddr, &t->parms.laddr))
435 goto tx_err_link_failure;
436
437 if (!ip6_tnl_xmit_ctl(t, (const struct in6_addr *)&x->props.saddr,
438 (const struct in6_addr *)&x->id.daddr))
433 goto tx_err_link_failure; 439 goto tx_err_link_failure;
434 440
435 tdev = dst->dev; 441 tdev = dst->dev;
@@ -484,7 +490,7 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
484 ipv6h = ipv6_hdr(skb); 490 ipv6h = ipv6_hdr(skb);
485 491
486 if ((t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) || 492 if ((t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) ||
487 !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h)) 493 vti6_addr_conflict(t, ipv6h))
488 goto tx_err; 494 goto tx_err;
489 495
490 xfrm_decode_session(skb, &fl, AF_INET6); 496 xfrm_decode_session(skb, &fl, AF_INET6);