From: Sebastian Classen <sebastian.classen@freenet.ag>
To: Patrick Schaaf <bof@bof.de>
Cc: Jan Engelhardt <jengelh@computergmbh.de>,
netfilter-devel@lists.netfilter.org
Subject: Re: new target: -j TEE
Date: Thu, 13 Sep 2007 09:37:07 +0200 [thread overview]
Message-ID: <1189669027.22541.6.camel@basti79.freenet-ag.de> (raw)
In-Reply-To: <20070830070004.GF8438@oknodo.bof.de>
[-- Attachment #1: Type: text/plain, Size: 3242 bytes --]
Am Donnerstag, den 30.08.2007, 09:00 +0200 schrieb Patrick Schaaf:
> > * RETURN: -1 if an error occured
> > * 1 if the packet was succesfully routed to the
> > * destination desired
> > * 0 if the kernel routing table could not route the packet
> > * according to the keys specified
> > */
> > static int route(struct sk_buff *skb,
> > const struct xt_TEE_info *info)
> ...
> > /* Trying to route the packet using the standard routing table. */
> > if ((err = ip_route_output_key(&rt, &fl)) != 0) {
> > if (net_ratelimit())
> > pr_debug(KBUILD_MODNAME
> > "could not route pkt (err: %d)", err);
> > return -1;
> > }
>
> Comment does not match behaviour. Suggest to change comment, and make
> function return 0/1 only.
OK, fixed.
> > static inline void route_gw(const struct xt_TEE_info *info, struct sk_buff *skb)
> > {
> > if (route(skb, info) != 1)
> > return;
> > ip_direct_send(skb);
> > }
>
> Too small, and only called once, to warrant being a function.
Function removed.
> > /*
> > * If we are at PREROUTING or INPUT hook,
> > * the TTL is not decreased by the IP stack
> > */
> > if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_IN) {
> ...
> > if (iph->ttl <= 1) {
> ...
>
> I believe this case (the whole synthesizing an ICMP_TIME_EXCEEDED) is not
> neccessary for TEE.
>
> The code is working on the original skb. With ROUTE, the logic was that
> the skb would be dropped soon due to exceeding TTL, and if we reroute
> and send directly now, that wouldn't happen.
>
> With TEE (as well as the previous ROUTE --tee option), the original
> packet is not rerouted, and ICMP_TIME_EXCEEDED should be generated
> for it as usual. Right?
>
> That would leave two questions:
>
> Should we skb_copy+route for the above quoted conditions, i.e. hook
> PRE_ROUTING/LOCAL_IN and skb->ttl <= 1, although the tee'd packet will
> be dropped soon?
>
> And if we decide to tee the packet regardless of the ttl condition,
> should the ttl be decremented after skb_copy on the teed packet,
> or not?
>
> My gut feeling is to remove all ttl handling, and let the next hop of
> the teed packet handle ttl as if it were the original recipient,
> instead of our tee pot.
>
I would also suggest to remove TTL handling completly and already did
so. Find the new xt_TEE.c attached.
@Jan: Could you please add the new version to your SVN repository.
Thanks.
Greets
Sebastian.
--
Mit freundlichen Grüßen / Yours sincerely
Sebastian Claßen
Postmaster
----------------------------------------------------------------------
Telefon: + 49 (0) 211 53087 522
Telefax: + 49 (0) 211 5381573
E-Mail: sebastian.classen@freenet.ag
Website: www.freenet.de; www.mobilcom.de
----------------------------------------------------------------------
freenet AG
Willstätterstr. 13
40549 Düsseldorf
----------------------------------------------------------------------
Vorsitzender des Aufsichtsrates: Prof. Dr. Helmut Thoma
Vorstand: Eckhard Spoerr (Vors.), Axel Krieger, Stephan Esch, Eric Berger
Sitz: Büdelsdorf
Amtsgericht Kiel HRB 7306 KI
[-- Attachment #2: xt_TEE.c --]
[-- Type: text/x-csrc, Size: 8031 bytes --]
/*
* This implements the TEE target.
*
* Copyright (C) 2007 Sebastian.Classen <sebastian.classen@freenet.de>
* Jan Engelhardt <jengelh@computergmbh.de>, 2007
* based on ipt_ROUTE.c from Cédric de Launois <delaunois@info.ucl.ac.be>
*
* This software is distributed under GNU GPL v2, 1991
*/
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/netfilter/x_tables.h>
#include <linux/route.h>
#include <linux/skbuff.h>
#include <net/checksum.h>
#include <net/icmp.h>
#include <net/ip.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/route.h>
#include "xt_TEE.h"
static struct nf_conn tee_track;
/*
* Try to route the packet according to the routing keys specified in
* route_info. Keys are :
* - ifindex :
* 0 if no oif preferred,
* otherwise set to the index of the desired oif
* - route_info->gw :
* 0 if no gateway specified,
* otherwise set to the next host to which the pkt must be routed
* If success, skb->dev is the output device to which the packet must
* be sent and skb->dst is not NULL
*
* RETURN: false - if an error occured
* true - if the packet was succesfully routed to the
* destination desired
*/
static bool route(struct sk_buff *skb,
const struct xt_TEE_info *info)
{
int err;
struct rtable *rt;
struct iphdr *iph = ip_hdr(skb);
struct flowi fl = {
.oif = 0,
.nl_u = {
.ip4_u = {
.daddr = iph->daddr,
.saddr = 0,
.tos = RT_TOS(iph->tos),
.scope = RT_SCOPE_UNIVERSE,
}
}
};
/* The destination address may be overloaded by the target */
if (info->gw != 0)
fl.fl4_dst = info->gw;
/* Trying to route the packet using the standard routing table. */
err = ip_route_output_key(&rt, &fl);
if (err != 0) {
if (net_ratelimit())
pr_debug(KBUILD_MODNAME
"could not route pkt (err: %d)", err);
return false;
}
/* Drop old route. */
dst_release(skb->dst);
skb->dst = NULL;
/* Success if no oif specified or if the oif correspond to the
* one desired */
/* SC: allways the case, because we have no oif. */
skb->dst = &rt->u.dst;
skb->dev = skb->dst->dev;
skb->protocol = htons(ETH_P_IP);
return true;
}
/* Stolen from ip_finish_output2
* PRE : skb->dev is set to the device we are leaving by
* skb->dst is not NULL
* POST: the packet is sent with the link layer header pushed
* the packet is destroyed
*/
static void ip_direct_send(struct sk_buff *skb)
{
const struct dst_entry *dst = skb->dst;
const struct net_device *dev = dst->dev;
unsigned int hh_len = LL_RESERVED_SPACE(dev);
/* Be paranoid, rather than too clever. */
if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header != NULL)) {
struct sk_buff *skb2;
skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
if (skb2 == NULL) {
kfree_skb(skb);
return;
}
if (skb->sk != NULL)
skb_set_owner_w(skb2, skb->sk);
kfree_skb(skb);
skb = skb2;
}
if (dst->hh != NULL) {
neigh_hh_output(dst->hh, skb);
} else if (dst->neighbour != NULL) {
dst->neighbour->output(skb);
} else {
if (net_ratelimit())
pr_debug(KBUILD_MODNAME "no hdr & no neighbour cache!\n");
kfree_skb(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
xt_TEE_target(struct sk_buff **pskb, const struct net_device *in,
const struct net_device *out, unsigned int hooknum,
const struct xt_target *target, const void *targinfo)
{
const struct xt_TEE_info *info = targinfo;
struct sk_buff *skb = *pskb;
if (skb->nfct == &tee_track.ct_general) {
/*
* 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;
}
/*
* If we are at INPUT the checksum must be recalculated since
* the length could change as the result of a defragmentation.
*/
if (hooknum == NF_IP_LOCAL_IN) {
iph->check = 0;
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
}
/*
* Copy the *pskb, and route the copy. Will later return XT_CONTINUE
* for the original skb, which should continue on its way as if nothing
* has happened. The copy should be independantly delivered to the TEE
* --gw.
*/
skb = skb_copy(*pskb, GFP_ATOMIC);
if (skb == NULL) {
if (net_ratelimit())
pr_debug(KBUILD_MODNAME "copy failed!\n");
return XT_CONTINUE;
}
/*
* Tell conntrack to forget this packet since it may get confused
* when a packet is leaving with dst address == our address.
* Good idea? Dunno. Need advice.
*
* NEW: mark the skb with our &tee_track, so we avoid looping
* on any already routed packet.
*/
nf_conntrack_put(skb->nfct);
skb->nfct = &tee_track.ct_general;
skb->nfctinfo = IP_CT_NEW;
nf_conntrack_get(skb->nfct);
if (info->gw != 0)
if (route(info, skb))
ip_direct_send(skb);
else if (net_ratelimit())
pr_debug(KBUILD_MODNAME "no parameter!\n");
return XT_CONTINUE;
}
static struct xt_target xt_TEE_reg __read_mostly = {
.name = "TEE",
.family = AF_INET,
.table = "mangle",
.hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
(1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT) |
(1 << NF_IP_POST_ROUTING),
.target = xt_TEE_target,
.targetsize = sizeof(struct xt_TEE_info),
.me = THIS_MODULE,
};
static int __init xt_TEE_init(void)
{
/*
* Set up fake conntrack (stolen from raw.patch):
* - to never be deleted, not in any hashes
*/
atomic_set(&tee_track.ct_general.use, 1);
/* - and look it like as a confirmed connection */
set_bit(IPS_CONFIRMED_BIT, &tee_track.status);
/* Initialize fake conntrack so that NAT will skip it */
tee_track.status |= IPS_NAT_DONE_MASK;
return xt_register_target(&xt_TEE_reg);
}
static void __exit xt_TEE_exit(void)
{
xt_unregister_target(&xt_TEE_reg);
/* SC: shoud not we cleanup tee_track here? */
}
module_init(xt_TEE_init);
module_exit(xt_TEE_exit);
MODULE_AUTHOR("Sebastian Classen <sebastian.classen@freenet.ag>, Jan Engelhardt <jengelh@computergmbh.de>");
MODULE_DESCRIPTION("netfilter TEE target module");
MODULE_LICENSE("GPL");
next prev parent reply other threads:[~2007-09-13 7:37 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-08-27 12:08 new target: -j TEE Sebastian Classen
2007-08-27 14:21 ` Jan Engelhardt
[not found] ` <1188237343.4548.4.camel@calypso>
2007-08-29 19:03 ` Patrick McHardy
2007-08-29 19:33 ` Jan Engelhardt
2007-08-29 19:44 ` Patrick McHardy
2007-08-30 7:00 ` Patrick Schaaf
2007-09-13 7:37 ` Sebastian Classen [this message]
2007-09-13 9:59 ` Sebastian Classen
[not found] ` <Pine.LNX.4.64.0709142354170.10168@fbirervta.pbzchgretzou.qr>
2007-10-01 12:44 ` Sebastian Classen
2007-10-01 13:01 ` Jan Engelhardt
2007-08-29 19:30 ` Jan Engelhardt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1189669027.22541.6.camel@basti79.freenet-ag.de \
--to=sebastian.classen@freenet.ag \
--cc=bof@bof.de \
--cc=jengelh@computergmbh.de \
--cc=netfilter-devel@lists.netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).