diff options
| -rw-r--r-- | net/ipv4/ip_output.c | 1 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 1 | ||||
| -rw-r--r-- | net/netfilter/xt_TEE.c | 40 |
3 files changed, 18 insertions, 24 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 0abfddec1e26..f09135e1e14f 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -309,7 +309,6 @@ int ip_output(struct sk_buff *skb) | |||
| 309 | ip_finish_output, | 309 | ip_finish_output, |
| 310 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 310 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
| 311 | } | 311 | } |
| 312 | EXPORT_SYMBOL_GPL(ip_output); | ||
| 313 | 312 | ||
| 314 | int ip_queue_xmit(struct sk_buff *skb, int ipfragok) | 313 | int ip_queue_xmit(struct sk_buff *skb, int ipfragok) |
| 315 | { | 314 | { |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d09be7ff8735..c10a38a71a5e 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -176,7 +176,6 @@ int ip6_output(struct sk_buff *skb) | |||
| 176 | ip6_finish_output, | 176 | ip6_finish_output, |
| 177 | !(IP6CB(skb)->flags & IP6SKB_REROUTED)); | 177 | !(IP6CB(skb)->flags & IP6SKB_REROUTED)); |
| 178 | } | 178 | } |
| 179 | EXPORT_SYMBOL_GPL(ip6_output); | ||
| 180 | 179 | ||
| 181 | /* | 180 | /* |
| 182 | * xmit an sk_buff (used by TCP) | 181 | * xmit an sk_buff (used by TCP) |
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index b3d730163f12..842e7012eca7 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | */ | 12 | */ |
| 13 | #include <linux/ip.h> | 13 | #include <linux/ip.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/percpu.h> | ||
| 15 | #include <linux/route.h> | 16 | #include <linux/route.h> |
| 16 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
| 17 | #include <net/checksum.h> | 18 | #include <net/checksum.h> |
| @@ -32,6 +33,7 @@ | |||
| 32 | #endif | 33 | #endif |
| 33 | 34 | ||
| 34 | static const union nf_inet_addr tee_zero_address; | 35 | static const union nf_inet_addr tee_zero_address; |
| 36 | static DEFINE_PER_CPU(bool, tee_active); | ||
| 35 | 37 | ||
| 36 | static struct net *pick_net(struct sk_buff *skb) | 38 | static struct net *pick_net(struct sk_buff *skb) |
| 37 | { | 39 | { |
| @@ -91,6 +93,8 @@ tee_tg4(struct sk_buff *skb, const struct xt_target_param *par) | |||
| 91 | const struct xt_tee_tginfo *info = par->targinfo; | 93 | const struct xt_tee_tginfo *info = par->targinfo; |
| 92 | struct iphdr *iph; | 94 | struct iphdr *iph; |
| 93 | 95 | ||
| 96 | if (percpu_read(tee_active)) | ||
| 97 | return XT_CONTINUE; | ||
| 94 | /* | 98 | /* |
| 95 | * Copy the skb, and route the copy. Will later return %XT_CONTINUE for | 99 | * Copy the skb, and route the copy. Will later return %XT_CONTINUE for |
| 96 | * the original skb, which should continue on its way as if nothing has | 100 | * the original skb, which should continue on its way as if nothing has |
| @@ -125,24 +129,13 @@ tee_tg4(struct sk_buff *skb, const struct xt_target_param *par) | |||
| 125 | --iph->ttl; | 129 | --iph->ttl; |
| 126 | ip_send_check(iph); | 130 | ip_send_check(iph); |
| 127 | 131 | ||
| 128 | /* | 132 | if (tee_tg_route4(skb, info)) { |
| 129 | * Xtables is not reentrant currently, so a choice has to be made: | 133 | percpu_write(tee_active, true); |
| 130 | * 1. return absolute verdict for the original and let the cloned | 134 | ip_local_out(skb); |
| 131 | * packet travel through the chains | 135 | percpu_write(tee_active, false); |
| 132 | * 2. let the original continue travelling and not pass the clone | 136 | } else { |
| 133 | * to Xtables. | ||
| 134 | * #2 is chosen. Normally, we would use ip_local_out for the clone. | ||
| 135 | * Because iph->check is already correct and we don't pass it to | ||
| 136 | * Xtables anyway, a shortcut to dst_output [forwards to ip_output] can | ||
| 137 | * be taken. %IPSKB_REROUTED needs to be set so that ip_output does not | ||
| 138 | * invoke POSTROUTING on the cloned packet. | ||
| 139 | */ | ||
| 140 | IPCB(skb)->flags |= IPSKB_REROUTED; | ||
| 141 | if (tee_tg_route4(skb, info)) | ||
| 142 | ip_output(skb); | ||
| 143 | else | ||
| 144 | kfree_skb(skb); | 137 | kfree_skb(skb); |
| 145 | 138 | } | |
| 146 | return XT_CONTINUE; | 139 | return XT_CONTINUE; |
| 147 | } | 140 | } |
| 148 | 141 | ||
| @@ -177,6 +170,8 @@ tee_tg6(struct sk_buff *skb, const struct xt_target_param *par) | |||
| 177 | { | 170 | { |
| 178 | const struct xt_tee_tginfo *info = par->targinfo; | 171 | const struct xt_tee_tginfo *info = par->targinfo; |
| 179 | 172 | ||
| 173 | if (percpu_read(tee_active)) | ||
| 174 | return XT_CONTINUE; | ||
| 180 | skb = pskb_copy(skb, GFP_ATOMIC); | 175 | skb = pskb_copy(skb, GFP_ATOMIC); |
| 181 | if (skb == NULL) | 176 | if (skb == NULL) |
| 182 | return XT_CONTINUE; | 177 | return XT_CONTINUE; |
| @@ -192,12 +187,13 @@ tee_tg6(struct sk_buff *skb, const struct xt_target_param *par) | |||
| 192 | struct ipv6hdr *iph = ipv6_hdr(skb); | 187 | struct ipv6hdr *iph = ipv6_hdr(skb); |
| 193 | --iph->hop_limit; | 188 | --iph->hop_limit; |
| 194 | } | 189 | } |
| 195 | IP6CB(skb)->flags |= IP6SKB_REROUTED; | 190 | if (tee_tg_route6(skb, info)) { |
| 196 | if (tee_tg_route6(skb, info)) | 191 | percpu_write(tee_active, true); |
| 197 | ip6_output(skb); | 192 | ip6_local_out(skb); |
| 198 | else | 193 | percpu_write(tee_active, false); |
| 194 | } else { | ||
| 199 | kfree_skb(skb); | 195 | kfree_skb(skb); |
| 200 | 196 | } | |
| 201 | return XT_CONTINUE; | 197 | return XT_CONTINUE; |
| 202 | } | 198 | } |
| 203 | #endif /* WITH_IPV6 */ | 199 | #endif /* WITH_IPV6 */ |
