diff options
-rw-r--r-- | include/net/ip6_tunnel.h | 3 | ||||
-rw-r--r-- | net/ipv6/ip6_gre.c | 2 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 23 | ||||
-rw-r--r-- | net/ipv6/ip6_vti.c | 10 |
4 files changed, 26 insertions, 12 deletions
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h index a5593dab6af7..9326c41c2d7f 100644 --- a/include/net/ip6_tunnel.h +++ b/include/net/ip6_tunnel.h | |||
@@ -65,7 +65,8 @@ void ip6_tnl_dst_reset(struct ip6_tnl *t); | |||
65 | void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst); | 65 | void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst); |
66 | int ip6_tnl_rcv_ctl(struct ip6_tnl *t, const struct in6_addr *laddr, | 66 | int ip6_tnl_rcv_ctl(struct ip6_tnl *t, const struct in6_addr *laddr, |
67 | const struct in6_addr *raddr); | 67 | const struct in6_addr *raddr); |
68 | int ip6_tnl_xmit_ctl(struct ip6_tnl *t); | 68 | int ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr, |
69 | const struct in6_addr *raddr); | ||
69 | __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw); | 70 | __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw); |
70 | __u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr, | 71 | __u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr, |
71 | const struct in6_addr *raddr); | 72 | const struct in6_addr *raddr); |
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 | ||
912 | int ip6_tnl_xmit_ctl(struct ip6_tnl *t) | 912 | int 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); |