diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-09-20 14:50:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-09-20 14:50:00 -0400 |
commit | d24f22f3df9ac3f3af95e850df0b576d41bd3cfe (patch) | |
tree | db5cf4d94fa9b56fafa677dda417fc1f9a919cc7 /net | |
parent | 46151ae81758f05086e17fd4e4da129afe100f93 (diff) |
ip6_tunnel: add optional fwmark inherit
Add IP6_TNL_F_USE_ORIG_FWMARK to ip6_tunnel, so that ip6_tnl_xmit2()
makes a route lookup taking into account skb->fwmark and doesnt cache
lookup result.
This permits more flexibility in policies and firewall setups.
To setup such a tunnel, "fwmark inherit" option should be added to "ip
-f inet6 tunnel" command.
Reported-by: Anders Franzen <Anders.Franzen@ericsson.com>
CC: Hans Schillström <hans.schillstrom@ericsson.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 694d70a8a0ee..bdc15c9003d7 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -889,7 +889,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
889 | struct net_device_stats *stats = &t->dev->stats; | 889 | struct net_device_stats *stats = &t->dev->stats; |
890 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 890 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
891 | struct ipv6_tel_txoption opt; | 891 | struct ipv6_tel_txoption opt; |
892 | struct dst_entry *dst, *ndst = NULL; | 892 | struct dst_entry *dst = NULL, *ndst = NULL; |
893 | struct net_device *tdev; | 893 | struct net_device *tdev; |
894 | int mtu; | 894 | int mtu; |
895 | unsigned int max_headroom = sizeof(struct ipv6hdr); | 895 | unsigned int max_headroom = sizeof(struct ipv6hdr); |
@@ -897,7 +897,8 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
897 | int err = -1; | 897 | int err = -1; |
898 | int pkt_len; | 898 | int pkt_len; |
899 | 899 | ||
900 | dst = ip6_tnl_dst_check(t); | 900 | if (!fl6->flowi6_mark) |
901 | dst = ip6_tnl_dst_check(t); | ||
901 | if (!dst) { | 902 | if (!dst) { |
902 | ndst = ip6_route_output(net, NULL, fl6); | 903 | ndst = ip6_route_output(net, NULL, fl6); |
903 | 904 | ||
@@ -955,8 +956,12 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
955 | skb = new_skb; | 956 | skb = new_skb; |
956 | } | 957 | } |
957 | skb_dst_drop(skb); | 958 | skb_dst_drop(skb); |
958 | skb_dst_set_noref(skb, dst); | 959 | if (fl6->flowi6_mark) { |
959 | 960 | skb_dst_set(skb, dst); | |
961 | ndst = NULL; | ||
962 | } else { | ||
963 | skb_dst_set_noref(skb, dst); | ||
964 | } | ||
960 | skb->transport_header = skb->network_header; | 965 | skb->transport_header = skb->network_header; |
961 | 966 | ||
962 | proto = fl6->flowi6_proto; | 967 | proto = fl6->flowi6_proto; |
@@ -1021,9 +1026,11 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1021 | 1026 | ||
1022 | dsfield = ipv4_get_dsfield(iph); | 1027 | dsfield = ipv4_get_dsfield(iph); |
1023 | 1028 | ||
1024 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) | 1029 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) |
1025 | fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) | 1030 | fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) |
1026 | & IPV6_TCLASS_MASK; | 1031 | & IPV6_TCLASS_MASK; |
1032 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) | ||
1033 | fl6.flowi6_mark = skb->mark; | ||
1027 | 1034 | ||
1028 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); | 1035 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); |
1029 | if (err != 0) { | 1036 | if (err != 0) { |
@@ -1070,10 +1077,12 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1070 | fl6.flowi6_proto = IPPROTO_IPV6; | 1077 | fl6.flowi6_proto = IPPROTO_IPV6; |
1071 | 1078 | ||
1072 | dsfield = ipv6_get_dsfield(ipv6h); | 1079 | dsfield = ipv6_get_dsfield(ipv6h); |
1073 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) | 1080 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) |
1074 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); | 1081 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); |
1075 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) | 1082 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) |
1076 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); | 1083 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); |
1084 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) | ||
1085 | fl6.flowi6_mark = skb->mark; | ||
1077 | 1086 | ||
1078 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); | 1087 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); |
1079 | if (err != 0) { | 1088 | if (err != 0) { |