mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-06 20:55:13 +02:00
Merge branch 'tee'
This commit is contained in:
@@ -1,6 +1,13 @@
|
|||||||
|
|
||||||
HEAD
|
HEAD
|
||||||
====
|
====
|
||||||
|
- TEE: do rechecksumming in PREROUTING too
|
||||||
|
- TEE: decrease TTL on cloned packet
|
||||||
|
- TEE: set dont-fragment on cloned packets
|
||||||
|
- TEE: free skb when route lookup failed
|
||||||
|
- TEE: do not limit use to mangle table
|
||||||
|
- TEE: do not retain iif and mark on cloned packet
|
||||||
|
- TEE: new loop detection logic
|
||||||
|
|
||||||
|
|
||||||
Xtables-addons 1.24 (March 17 2010)
|
Xtables-addons 1.24 (March 17 2010)
|
||||||
|
@@ -33,6 +33,7 @@ static struct nf_conn tee_track;
|
|||||||
#include "compat_xtables.h"
|
#include "compat_xtables.h"
|
||||||
#include "xt_TEE.h"
|
#include "xt_TEE.h"
|
||||||
|
|
||||||
|
static bool tee_active[NR_CPUS];
|
||||||
static const union nf_inet_addr tee_zero_address;
|
static const union nf_inet_addr tee_zero_address;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -60,12 +61,6 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info)
|
|||||||
struct flowi fl;
|
struct flowi fl;
|
||||||
|
|
||||||
memset(&fl, 0, sizeof(fl));
|
memset(&fl, 0, sizeof(fl));
|
||||||
fl.iif = skb_ifindex(skb);
|
|
||||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
|
||||||
fl.nl_u.ip4_u.fwmark = skb_nfmark(skb);
|
|
||||||
#else
|
|
||||||
fl.mark = skb_nfmark(skb);
|
|
||||||
#endif
|
|
||||||
fl.nl_u.ip4_u.daddr = info->gw.ip;
|
fl.nl_u.ip4_u.daddr = info->gw.ip;
|
||||||
fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
|
fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
|
||||||
fl.nl_u.ip4_u.scope = RT_SCOPE_UNIVERSE;
|
fl.nl_u.ip4_u.scope = RT_SCOPE_UNIVERSE;
|
||||||
@@ -76,6 +71,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info)
|
|||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
pr_debug(KBUILD_MODNAME
|
pr_debug(KBUILD_MODNAME
|
||||||
": could not route packet (%d)", err);
|
": could not route packet (%d)", err);
|
||||||
|
kfree_skb(skb);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,44 +130,16 @@ static void tee_tg_send(struct sk_buff *skb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* To detect and deter routed packet loopback when using the --tee option, we
|
|
||||||
* take a page out of the raw.patch book: on the copied skb, we set up a fake
|
|
||||||
* ->nfct entry, pointing to the local &route_tee_track. We skip routing
|
|
||||||
* packets when we see they already have that ->nfct.
|
|
||||||
*/
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
tee_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
|
tee_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||||
{
|
{
|
||||||
const struct xt_tee_tginfo *info = par->targinfo;
|
const struct xt_tee_tginfo *info = par->targinfo;
|
||||||
struct sk_buff *skb = *pskb;
|
struct sk_buff *skb = *pskb;
|
||||||
|
struct iphdr *iph;
|
||||||
|
unsigned int cpu = smp_processor_id();
|
||||||
|
|
||||||
#ifdef WITH_CONNTRACK
|
if (tee_active[cpu])
|
||||||
if (skb->nfct == &tee_track.ct_general) {
|
return XT_CONTINUE;
|
||||||
/*
|
|
||||||
* Loopback - a packet we already routed, is to be
|
|
||||||
* routed another time. Avoid that, now.
|
|
||||||
*/
|
|
||||||
if (net_ratelimit())
|
|
||||||
pr_debug(KBUILD_MODNAME "loopback - DROP!\n");
|
|
||||||
return NF_DROP;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!skb_make_writable(pskb, sizeof(struct iphdr)))
|
|
||||||
return NF_DROP;
|
|
||||||
skb = *pskb;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we are in INPUT, the checksum must be recalculated since
|
|
||||||
* the length could have changed as a result of defragmentation.
|
|
||||||
*/
|
|
||||||
if (par->hooknum == NF_INET_LOCAL_IN) {
|
|
||||||
struct iphdr *iph = ip_hdr(skb);
|
|
||||||
iph->check = 0;
|
|
||||||
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the skb, and route the copy. Will later return %XT_CONTINUE for
|
* Copy the skb, and route the copy. Will later return %XT_CONTINUE for
|
||||||
* the original skb, which should continue on its way as if nothing has
|
* the original skb, which should continue on its way as if nothing has
|
||||||
@@ -181,15 +149,28 @@ tee_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
|
|||||||
skb = skb_copy(skb, GFP_ATOMIC);
|
skb = skb_copy(skb, GFP_ATOMIC);
|
||||||
if (skb == NULL)
|
if (skb == NULL)
|
||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
|
/*
|
||||||
|
* If we are in PREROUTING/INPUT, the checksum must be recalculated
|
||||||
|
* since the length could have changed as a result of defragmentation.
|
||||||
|
*
|
||||||
|
* We also decrease the TTL to mitigate potential TEE loops
|
||||||
|
* between two hosts.
|
||||||
|
*
|
||||||
|
* Set %IP_DF so that the original source is notified of a potentially
|
||||||
|
* decreased MTU on the clone route. IPv6 does this too.
|
||||||
|
*/
|
||||||
|
iph = ip_hdr(skb);
|
||||||
|
iph->frag_off |= htons(IP_DF);
|
||||||
|
if (par->hooknum == NF_INET_PRE_ROUTING ||
|
||||||
|
par->hooknum == NF_INET_LOCAL_IN)
|
||||||
|
--iph->ttl;
|
||||||
|
ip_send_check(iph);
|
||||||
|
|
||||||
#ifdef WITH_CONNTRACK
|
#ifdef WITH_CONNTRACK
|
||||||
/*
|
/*
|
||||||
* Tell conntrack to forget this packet since it may get confused
|
* Tell conntrack to forget this packet. It may have side effects to
|
||||||
* when a packet is leaving with dst address == our address.
|
* see the same packet twice, as for example, accounting the original
|
||||||
* Good idea? Dunno. Need advice.
|
* connection for the cloned packet.
|
||||||
*
|
|
||||||
* NEW: mark the skb with our &tee_track, so we avoid looping
|
|
||||||
* on any already routed packet.
|
|
||||||
*/
|
*/
|
||||||
nf_conntrack_put(skb->nfct);
|
nf_conntrack_put(skb->nfct);
|
||||||
skb->nfct = &tee_track.ct_general;
|
skb->nfct = &tee_track.ct_general;
|
||||||
@@ -213,9 +194,11 @@ tee_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
|
|||||||
* Also on purpose, no fragmentation is done, to preserve the
|
* Also on purpose, no fragmentation is done, to preserve the
|
||||||
* packet as best as possible.
|
* packet as best as possible.
|
||||||
*/
|
*/
|
||||||
if (tee_tg_route4(skb, info))
|
if (tee_tg_route4(skb, info)) {
|
||||||
|
tee_active[cpu] = true;
|
||||||
tee_tg_send(skb);
|
tee_tg_send(skb);
|
||||||
|
tee_active[cpu] = false;
|
||||||
|
}
|
||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,13 +211,6 @@ tee_tg_route6(struct sk_buff *skb, const struct xt_tee_tginfo *info)
|
|||||||
struct flowi fl;
|
struct flowi fl;
|
||||||
|
|
||||||
memset(&fl, 0, sizeof(fl));
|
memset(&fl, 0, sizeof(fl));
|
||||||
fl.iif = skb_ifindex(skb);
|
|
||||||
/* No mark in flowi before 2.6.19 */
|
|
||||||
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 19)
|
|
||||||
fl.nl_u.ip6_u.fwmark = skb_nfmark(skb);
|
|
||||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
|
|
||||||
fl.mark = skb_nfmark(skb);
|
|
||||||
#endif
|
|
||||||
fl.nl_u.ip6_u.daddr = info->gw.in6;
|
fl.nl_u.ip6_u.daddr = info->gw.in6;
|
||||||
fl.nl_u.ip6_u.flowlabel = ((iph->flow_lbl[0] & 0xF) << 16) |
|
fl.nl_u.ip6_u.flowlabel = ((iph->flow_lbl[0] & 0xF) << 16) |
|
||||||
(iph->flow_lbl[1] << 8) | iph->flow_lbl[2];
|
(iph->flow_lbl[1] << 8) | iph->flow_lbl[2];
|
||||||
@@ -247,6 +223,7 @@ tee_tg_route6(struct sk_buff *skb, const struct xt_tee_tginfo *info)
|
|||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
printk(KERN_ERR "ip6_route_output failed for tee\n");
|
printk(KERN_ERR "ip6_route_output failed for tee\n");
|
||||||
|
kfree_skb(skb);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,13 +239,10 @@ tee_tg6(struct sk_buff **pskb, const struct xt_target_param *par)
|
|||||||
{
|
{
|
||||||
const struct xt_tee_tginfo *info = par->targinfo;
|
const struct xt_tee_tginfo *info = par->targinfo;
|
||||||
struct sk_buff *skb = *pskb;
|
struct sk_buff *skb = *pskb;
|
||||||
|
unsigned int cpu = smp_processor_id();
|
||||||
|
|
||||||
/* Try silence. */
|
if (tee_active[cpu])
|
||||||
#ifdef WITH_CONNTRACK
|
return XT_CONTINUE;
|
||||||
if (skb->nfct == &tee_track.ct_general)
|
|
||||||
return NF_DROP;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((skb = skb_copy(skb, GFP_ATOMIC)) == NULL)
|
if ((skb = skb_copy(skb, GFP_ATOMIC)) == NULL)
|
||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
|
|
||||||
@@ -278,9 +252,16 @@ tee_tg6(struct sk_buff **pskb, const struct xt_target_param *par)
|
|||||||
skb->nfctinfo = IP_CT_NEW;
|
skb->nfctinfo = IP_CT_NEW;
|
||||||
nf_conntrack_get(skb->nfct);
|
nf_conntrack_get(skb->nfct);
|
||||||
#endif
|
#endif
|
||||||
if (tee_tg_route6(skb, info))
|
if (par->hooknum == NF_INET_PRE_ROUTING ||
|
||||||
|
par->hooknum == NF_INET_LOCAL_IN) {
|
||||||
|
struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||||
|
--iph->hop_limit;
|
||||||
|
}
|
||||||
|
if (tee_tg_route6(skb, info)) {
|
||||||
|
tee_active[cpu] = true;
|
||||||
tee_tg_send(skb);
|
tee_tg_send(skb);
|
||||||
|
tee_active[cpu] = false;
|
||||||
|
}
|
||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
}
|
}
|
||||||
#endif /* WITH_IPV6 */
|
#endif /* WITH_IPV6 */
|
||||||
@@ -299,7 +280,6 @@ static struct xt_target tee_tg_reg[] __read_mostly = {
|
|||||||
.name = "TEE",
|
.name = "TEE",
|
||||||
.revision = 0,
|
.revision = 0,
|
||||||
.family = NFPROTO_IPV4,
|
.family = NFPROTO_IPV4,
|
||||||
.table = "mangle",
|
|
||||||
.target = tee_tg4,
|
.target = tee_tg4,
|
||||||
.targetsize = sizeof(struct xt_tee_tginfo),
|
.targetsize = sizeof(struct xt_tee_tginfo),
|
||||||
.checkentry = tee_tg_check,
|
.checkentry = tee_tg_check,
|
||||||
@@ -310,7 +290,6 @@ static struct xt_target tee_tg_reg[] __read_mostly = {
|
|||||||
.name = "TEE",
|
.name = "TEE",
|
||||||
.revision = 0,
|
.revision = 0,
|
||||||
.family = NFPROTO_IPV6,
|
.family = NFPROTO_IPV6,
|
||||||
.table = "mangle",
|
|
||||||
.target = tee_tg6,
|
.target = tee_tg6,
|
||||||
.targetsize = sizeof(struct xt_tee_tginfo),
|
.targetsize = sizeof(struct xt_tee_tginfo),
|
||||||
.checkentry = tee_tg_check,
|
.checkentry = tee_tg_check,
|
||||||
@@ -323,8 +302,7 @@ static int __init tee_tg_init(void)
|
|||||||
{
|
{
|
||||||
#ifdef WITH_CONNTRACK
|
#ifdef WITH_CONNTRACK
|
||||||
/*
|
/*
|
||||||
* Set up fake conntrack (stolen from raw.patch):
|
* Set up fake conntrack - to never be deleted, not in any hashes
|
||||||
* - to never be deleted, not in any hashes
|
|
||||||
*/
|
*/
|
||||||
atomic_set(&tee_track.ct_general.use, 1);
|
atomic_set(&tee_track.ct_general.use, 1);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user