All of lore.kernel.org
 help / color / mirror / Atom feed
* Follow packets in rules
@ 2007-06-12 18:08 Fabrice Rafart
  2007-06-12 21:41 ` Simon
                   ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Fabrice Rafart @ 2007-06-12 18:08 UTC (permalink / raw)
  To: netfilter-devel

Hello,

I look for a tool to follow a packets into rules of netfilter.

For example :

# iptables-test -s 192.168.1.1 -d 192.168.2.1 -p tcp --dport 25
--> FORWARD line 1  : -p tcp --dport 25 -j SMTP
--> SMTP line 3     : -s 192.168.1.0/24 -j DROP

This show me which rules matches the packet until the end.

Does this exist ?

Thank and sorry for my poor english.

Cordialement,
-- 
Fabrice Rafart
Administrateur systèmes et réseaux
Etablissement français du sang, Ile de France.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-12 18:08 Follow packets in rules Fabrice Rafart
@ 2007-06-12 21:41 ` Simon
  2007-06-13  7:31   ` Fabrice Rafart
  2007-06-13  8:57 ` Pablo Neira Ayuso
  2007-07-03 15:07 ` Fabrice Rafart
  2 siblings, 1 reply; 28+ messages in thread
From: Simon @ 2007-06-12 21:41 UTC (permalink / raw)
  To: Fabrice Rafart; +Cc: netfilter-devel

On 6/12/07, Fabrice Rafart <fabrice.rafart@efs.sante.fr> wrote:
> Hello,

Salut Fabrice!

> I look for a tool to follow a packets into rules of netfilter.
[...]
> This show me which rules matches the packet until the end.

I'm not sure if such a tool exists, but there is a way to follow the
packets very well.
Using the LOG target, you can log packets as they match certain rules
and you can put a message to be put in the log to identify that line.

After, you just have to grep the logfile for patterns matching the ip
address and you should see the history of each packets that came in.

You could make your own target queues like LOGDROP or LOGACCEPT and
have a log rule followed by the drop/accept rule.

Note that logging things this way takes a lot of disk space and should
only be used in a lan for experimentation.

Good luck,
  Simon

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: Follow packets in rules
  2007-06-12 21:41 ` Simon
@ 2007-06-13  7:31   ` Fabrice Rafart
  2007-06-18 16:12     ` Simon
  0 siblings, 1 reply; 28+ messages in thread
From: Fabrice Rafart @ 2007-06-13  7:31 UTC (permalink / raw)
  To: 'Simon'; +Cc: netfilter-devel

> -----Message d'origine-----
> De : netfilter-devel-bounces@lists.netfilter.org 
> [mailto:netfilter-devel-bounces@lists.netfilter.org] De la 
> part de Simon
> Envoyé : mardi 12 juin 2007 23:41
> À : Fabrice Rafart
> Cc : netfilter-devel@lists.netfilter.org
> Objet : Re: Follow packets in rules
> 
> On 6/12/07, Fabrice Rafart <fabrice.rafart@efs.sante.fr> wrote:
> > Hello,
> 
> Salut Fabrice!
> 
> > I look for a tool to follow a packets into rules of netfilter.
> [...]
> > This show me which rules matches the packet until the end.
> 
> I'm not sure if such a tool exists, but there is a way to follow the
> packets very well.
> Using the LOG target, you can log packets as they match certain rules
> and you can put a message to be put in the log to identify that line.
> 
> After, you just have to grep the logfile for patterns matching the ip
> address and you should see the history of each packets that came in.
> 
> You could make your own target queues like LOGDROP or LOGACCEPT and
> have a log rule followed by the drop/accept rule.

Thanks for your answer.

I know this possibility and I use it for log some packets but I can't double
all my rules (almost 200) by a log rule.

Cordialement,
-- 
Fabrice Rafart
Administrateur systèmes et réseaux
Etablissement français du sang, Ile de France. 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-12 18:08 Follow packets in rules Fabrice Rafart
  2007-06-12 21:41 ` Simon
@ 2007-06-13  8:57 ` Pablo Neira Ayuso
  2007-06-13 15:43   ` Juan León
  2007-07-03 15:07 ` Fabrice Rafart
  2 siblings, 1 reply; 28+ messages in thread
From: Pablo Neira Ayuso @ 2007-06-13  8:57 UTC (permalink / raw)
  To: Fabrice Rafart; +Cc: netfilter-devel

Fabrice Rafart wrote:
> I look for a tool to follow a packets into rules of netfilter.
> 
> For example :
> 
> # iptables-test -s 192.168.1.1 -d 192.168.2.1 -p tcp --dport 25
> --> FORWARD line 1  : -p tcp --dport 25 -j SMTP
> --> SMTP line 3     : -s 192.168.1.0/24 -j DROP
> 
> This show me which rules matches the packet until the end.
> 
> Does this exist ?

check nfsim: http://ozlabs.org/~jk/projects/nfsim/

AFAIK, it's not actively maintained so probably you'll have to hack on 
it a bit.

-- 
The dawn of the fourth age of Linux firewalling is coming; a time of 
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-13  8:57 ` Pablo Neira Ayuso
@ 2007-06-13 15:43   ` Juan León
  2007-06-13 16:28     ` Samuel Jean
  0 siblings, 1 reply; 28+ messages in thread
From: Juan León @ 2007-06-13 15:43 UTC (permalink / raw)
  To: Fabrice Rafart, netfilter-devel, pablo

Hi Fabrice,


2007/6/13, Pablo Neira Ayuso <pablo@netfilter.org>:
> Fabrice Rafart wrote:
> > I look for a tool to follow a packets into rules of netfilter.
> >
> > For example :
> >
> > # iptables-test -s 192.168.1.1 -d 192.168.2.1 -p tcp --dport 25
> > --> FORWARD line 1  : -p tcp --dport 25 -j SMTP
> > --> SMTP line 3     : -s 192.168.1.0/24 -j DROP
> >
> > This show me which rules matches the packet until the end.
> >
> > Does this exist ?

  You can try using iptables command line to know if the package
matchs with your rules.

In the example bellow you'll see something familiar.

 debian:~# iptables -nvL FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
 125     25  ACCEPT     0    --  *      *       192.168.132.25
192.126.132.56


Let's take a close look at this part.
 pkts bytes
  125     25


 Every time your rule matchs, you'll see the packages changes.

Use the line bellow to check it.

debian:~# watch -n 1 'iptables -nvL FORWARD'


> check nfsim: http://ozlabs.org/~jk/projects/nfsim/
>
> AFAIK, it's not actively maintained so probably you'll have to hack on
> it a bit.

As far as read, it's not longer maintained.


I hope this help.

Best Regards.

> --
> The dawn of the fourth age of Linux firewalling is coming; a time of
> great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
>
>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-13 15:43   ` Juan León
@ 2007-06-13 16:28     ` Samuel Jean
  2007-06-13 16:53       ` Patrick McHardy
  0 siblings, 1 reply; 28+ messages in thread
From: Samuel Jean @ 2007-06-13 16:28 UTC (permalink / raw)
  To: Juan León, Fabrice Rafart, netfilter-devel, pablo, kaber,
	nicboul

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 894 bytes --]

On Wed, Jun 13, 2007, Juan León <debjuanca@gmail.com> said:

> Hi Fabrice,
> 
> 
> 2007/6/13, Pablo Neira Ayuso <pablo@netfilter.org>:
>> Fabrice Rafart wrote:
>> > I look for a tool to follow a packets into rules of netfilter.
>> >
>> > For example :
>> >
>> > # iptables-test -s 192.168.1.1 -d 192.168.2.1 -p tcp --dport 25
>> > --> FORWARD line 1  : -p tcp --dport 25 -j SMTP
>> > --> SMTP line 3     : -s 192.168.1.0/24 -j DROP
>> >
>> > This show me which rules matches the packet until the end.
>> >
>> > Does this exist ?

There was the TRACE target born for this purpose a couple years ago.

http://svn.netfilter.org/cgi-bin/viewcvs.cgi/branches/patch-o-matic-ng/linux-2.6.11/TRACE/?rev=3680

It sure will require a bit of hacking for recent kernels.

Pablo, Patrick --

Is this an interesting feature that worths merging in mainline, or
patch-o-matic at least ?

Best regards,
Samuel 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-13 16:28     ` Samuel Jean
@ 2007-06-13 16:53       ` Patrick McHardy
  2007-06-13 19:43         ` Jozsef Kadlecsik
  0 siblings, 1 reply; 28+ messages in thread
From: Patrick McHardy @ 2007-06-13 16:53 UTC (permalink / raw)
  To: jix; +Cc: Fabrice Rafart, netfilter-devel, nicboul, pablo, Juan León

Samuel Jean wrote:
> There was the TRACE target born for this purpose a couple years ago.
> 
> http://svn.netfilter.org/cgi-bin/viewcvs.cgi/branches/patch-o-matic-ng/linux-2.6.11/TRACE/?rev=3680
> 
> It sure will require a bit of hacking for recent kernels.
> 
> Pablo, Patrick --
> 
> Is this an interesting feature that worths merging in mainline, or
> patch-o-matic at least ?


It would be interesting for the kernel if it can be done in a
non-intrusive way. I can't remember what the old patches exactly
did, but I believe it was kind of a hack.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-13 16:53       ` Patrick McHardy
@ 2007-06-13 19:43         ` Jozsef Kadlecsik
  2007-06-14  7:55           ` Fabrice Rafart
  2007-06-14 13:13           ` Patrick McHardy
  0 siblings, 2 replies; 28+ messages in thread
From: Jozsef Kadlecsik @ 2007-06-13 19:43 UTC (permalink / raw)
  To: netfilter-devel

On Wed, 13 Jun 2007, Patrick McHardy wrote:

> Samuel Jean wrote:
>> There was the TRACE target born for this purpose a couple years ago.
>>
>> http://svn.netfilter.org/cgi-bin/viewcvs.cgi/branches/patch-o-matic-ng/linux-2.6.11/TRACE/?rev=3680
>>
>> It sure will require a bit of hacking for recent kernels.
>>
>> Pablo, Patrick --
>>
>> Is this an interesting feature that worths merging in mainline, or
>> patch-o-matic at least ?
>
> It would be interesting for the kernel if it can be done in a
> non-intrusive way. I can't remember what the old patches exactly
> did, but I believe it was kind of a hack.

It was just a little bit of hack ;-). I could not find the patch lying 
around here, fortunately there is an old copy from the patch-o-matic era
in svn:

http://svn.netfilter.org/cgi-bin/viewcvs.cgi/old_stuff/netfilter/trunk/patch-o-matic/extra/TRACE.patch?rev=3069

Best regards,
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlec@sunserv.kfki.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
           H-1525 Budapest 114, POB. 49, Hungary

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: Follow packets in rules
  2007-06-13 19:43         ` Jozsef Kadlecsik
@ 2007-06-14  7:55           ` Fabrice Rafart
  2007-06-14 13:13           ` Patrick McHardy
  1 sibling, 0 replies; 28+ messages in thread
From: Fabrice Rafart @ 2007-06-14  7:55 UTC (permalink / raw)
  To: netfilter-devel

Hello,

Thanks for all your answers.

I can't use LOG destination or the packet/byes count :
  - LOG : I must double all my rules by a LOG rules : heavy and too verbose.
  - counter : My fw is in use, so I can't make difference between real
packet and the test one.

Netfilter had all the code to parse his rules, I think about a little hack
to give some parameter on a command line and print the matches on stdin.
But, there is a but ! I'm not a programmer.

Cordialement,
-- 
Fabrice Rafart
Administrateur systèmes et réseaux
Etablissement français du sang, Ile de France.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-13 19:43         ` Jozsef Kadlecsik
  2007-06-14  7:55           ` Fabrice Rafart
@ 2007-06-14 13:13           ` Patrick McHardy
  2007-06-14 14:18             ` Jozsef Kadlecsik
  1 sibling, 1 reply; 28+ messages in thread
From: Patrick McHardy @ 2007-06-14 13:13 UTC (permalink / raw)
  To: Jozsef Kadlecsik; +Cc: netfilter-devel

Jozsef Kadlecsik wrote:
> On Wed, 13 Jun 2007, Patrick McHardy wrote:
> 
>> It would be interesting for the kernel if it can be done in a
>> non-intrusive way. I can't remember what the old patches exactly
>> did, but I believe it was kind of a hack.
> 
> 
> It was just a little bit of hack ;-). I could not find the patch lying
> around here, fortunately there is an old copy from the patch-o-matic era
> in svn:
> 
> http://svn.netfilter.org/cgi-bin/viewcvs.cgi/old_stuff/netfilter/trunk/patch-o-matic/extra/TRACE.patch?rev=3069


Yeah, it doesn't look too bad. Unfortunately it breaks userspace
compatibility. How about just adding a new match that prints
a user-supplied string for specially marked packets?

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-14 13:13           ` Patrick McHardy
@ 2007-06-14 14:18             ` Jozsef Kadlecsik
  2007-06-14 14:23               ` Patrick McHardy
  0 siblings, 1 reply; 28+ messages in thread
From: Jozsef Kadlecsik @ 2007-06-14 14:18 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel

Hi Patrick,

On Thu, 14 Jun 2007, Patrick McHardy wrote:

>> http://svn.netfilter.org/cgi-bin/viewcvs.cgi/old_stuff/netfilter/trunk/patch-o-matic/extra/TRACE.patch?rev=3069
>
> Yeah, it doesn't look too bad. Unfortunately it breaks userspace
> compatibility.

Sigh.

> How about just adding a new match that prints a user-supplied string for 
> specially marked packets?

That'd be hard to use in practice: imagine, you have hundred of rules in 
multiple, multilevel chains. You should have to modify all your rules and 
add meaningful, different log strings to every one of them if you'd need 
to check how given packets traverse the rules.

Also, it'd be about the same as writing a log match. But in longer term 
we'd better support multiple targets instead of a log match.

The "beauty" of the TRACE target is that there is no need to tweak the 
rules: just "mark" the packets (we don't use the standard mark, so we 
cannot clash with any rule) you are interested in to check how they 
traverse the rulesets and that's all. Simple and clean.

An earlier version of the patch did not suffer from backward 
incompatibility: when we hit a marked packet and a matched rule, it 
searched the chain name and computed the rule number internally. But it 
can slow down packet processing if there are many matching rules and large 
number of rules in the chains so I introduced stored rulenumbers. What 
about going back to that approach? Tracing packets should not be 
considered as normal (and thus performance efficient) mode.

Best regards,
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlec@sunserv.kfki.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
           H-1525 Budapest 114, POB. 49, Hungary

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-14 14:18             ` Jozsef Kadlecsik
@ 2007-06-14 14:23               ` Patrick McHardy
  2007-06-18 10:16                 ` Jozsef Kadlecsik
  0 siblings, 1 reply; 28+ messages in thread
From: Patrick McHardy @ 2007-06-14 14:23 UTC (permalink / raw)
  To: Jozsef Kadlecsik; +Cc: netfilter-devel

Jozsef Kadlecsik wrote:
> Hi Patrick,
> 
> On Thu, 14 Jun 2007, Patrick McHardy wrote:
> 
>>> http://svn.netfilter.org/cgi-bin/viewcvs.cgi/old_stuff/netfilter/trunk/patch-o-matic/extra/TRACE.patch?rev=3069
>>>
>>
>>
>> Yeah, it doesn't look too bad. Unfortunately it breaks userspace
>> compatibility.
> 
> 
> Sigh.
> 
>> How about just adding a new match that prints a user-supplied string
>> for specially marked packets?
> 
> 
> That'd be hard to use in practice: imagine, you have hundred of rules in
> multiple, multilevel chains. You should have to modify all your rules
> and add meaningful, different log strings to every one of them if you'd
> need to check how given packets traverse the rules.
> 
> Also, it'd be about the same as writing a log match. But in longer term
> we'd better support multiple targets instead of a log match.


Indeed. I was thinking that iptables could automatically insert the
match into rules, so you wouldn't have to modify your ruleset.
But that could also be done with multiple targets.

> The "beauty" of the TRACE target is that there is no need to tweak the
> rules: just "mark" the packets (we don't use the standard mark, so we
> cannot clash with any rule) you are interested in to check how they
> traverse the rulesets and that's all. Simple and clean.
> 
> An earlier version of the patch did not suffer from backward
> incompatibility: when we hit a marked packet and a matched rule, it
> searched the chain name and computed the rule number internally. But it
> can slow down packet processing if there are many matching rules and
> large number of rules in the chains so I introduced stored rulenumbers.
> What about going back to that approach? Tracing packets should not be
> considered as normal (and thus performance efficient) mode.


Yes, that sounds reasonable. Performance doesn't matter much for this.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-14 14:23               ` Patrick McHardy
@ 2007-06-18 10:16                 ` Jozsef Kadlecsik
  2007-06-18 12:49                   ` Patrick McHardy
  2007-06-22 14:20                   ` Patrick McHardy
  0 siblings, 2 replies; 28+ messages in thread
From: Jozsef Kadlecsik @ 2007-06-18 10:16 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1220 bytes --]

Hi Patrick,

On Thu, 14 Jun 2007, Patrick McHardy wrote:

>> An earlier version of the patch did not suffer from backward
>> incompatibility: when we hit a marked packet and a matched rule, it
>> searched the chain name and computed the rule number internally. But it
>> can slow down packet processing if there are many matching rules and
>> large number of rules in the chains so I introduced stored rulenumbers.
>> What about going back to that approach? Tracing packets should not be
>> considered as normal (and thus performance efficient) mode.
>
> Yes, that sounds reasonable. Performance doesn't matter much for this.

Attached you can find the reworked TRACE target, which does not suffer 
from backward incompatibility. Unfortunately I had to steal one unused bit 
from skbuff to be able to mark the packets so that it surely does not 
clash with any rules using the standard "MARK" target. Logging level, 
flags and type are hardcoded. What do you think?

Best regards,
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlec@sunserv.kfki.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
           H-1525 Budapest 114, POB. 49, Hungary

[-- Attachment #2: TRACE.patch --]
[-- Type: TEXT/PLAIN, Size: 12456 bytes --]

diff -urN --exclude-from=/usr/src/diff.exclude linux-2.6.21-orig/include/linux/skbuff.h linux-2.6.21-TRACE/include/linux/skbuff.h
--- linux-2.6.21-orig/include/linux/skbuff.h	2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21-TRACE/include/linux/skbuff.h	2007-06-14 16:35:25.000000000 +0200
@@ -217,6 +217,7 @@
  *	@mark: Generic packet mark
  *	@nfct: Associated connection, if any
  *	@ipvs_property: skbuff is owned by ipvs
+ *	@nf_trace: netfilter packet trace flag
  *	@nfctinfo: Relationship of this skb to the connection
  *	@nfct_reasm: netfilter conntrack re-assembly pointer
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
@@ -285,7 +286,8 @@
 				nfctinfo:3;
 	__u8			pkt_type:3,
 				fclone:2,
-				ipvs_property:1;
+				ipvs_property:1,
+				nf_trace:1;
 	__be16			protocol;
 
 	void			(*destructor)(struct sk_buff *skb);
diff -urN --exclude-from=/usr/src/diff.exclude linux-2.6.21-orig/net/ipv4/netfilter/ip_tables.c linux-2.6.21-TRACE/net/ipv4/netfilter/ip_tables.c
--- linux-2.6.21-orig/net/ipv4/netfilter/ip_tables.c	2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21-TRACE/net/ipv4/netfilter/ip_tables.c	2007-06-18 11:20:10.000000000 +0200
@@ -210,6 +210,110 @@
 	return (struct ipt_entry *)(base + offset);
 }
 
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ipt_ip *ip)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
+		if (((__u32 *)ip)[i])
+			return 0;
+
+	return 1;
+}
+
+static const char *hooknames[] = {
+	[NF_IP_PRE_ROUTING] = "PREROUTING",
+	[NF_IP_LOCAL_IN] = "INPUT",
+	[NF_IP_FORWARD] = "FORWARD",
+	[NF_IP_LOCAL_OUT] = "OUTPUT",
+	[NF_IP_POST_ROUTING] = "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+	NF_IP_TRACE_COMMENT_RULE,
+	NF_IP_TRACE_COMMENT_RETURN,
+	NF_IP_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+	[NF_IP_TRACE_COMMENT_RULE] = "rule",
+	[NF_IP_TRACE_COMMENT_RETURN] = "return",
+	[NF_IP_TRACE_COMMENT_POLICY] = "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+	.type = NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level = 4,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static inline int
+get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
+		      char *hookname, char **chainname,
+		      char **comment, unsigned int *rulenum)
+{
+	struct ipt_standard_target *t = (void *)ipt_get_target(s);
+	
+	if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
+		/* Head of user chain: ERROR target with chainname */
+		*chainname = t->target.data;
+		(*rulenum) = 0;
+	} else if (s == e) {
+		(*rulenum)++;
+
+		if (s->target_offset == sizeof(struct ipt_entry)
+		   && strcmp(t->target.u.kernel.target->name, 
+		   	     IPT_STANDARD_TARGET) == 0
+		   && t->verdict < 0
+	           && unconditional(&s->ip)) {
+	           	/* Tail of chains: STANDARD target (return/policy) */
+	           	*comment = *chainname == hookname 
+	           		? (char *)comments[NF_IP_TRACE_COMMENT_POLICY]
+	           		: (char *)comments[NF_IP_TRACE_COMMENT_RETURN];
+		}
+		return 1;
+	} else
+		(*rulenum)++;
+
+	return 0;
+}
+
+
+static inline void trace_packet(struct sk_buff *skb,
+				unsigned int hook,
+				const struct net_device *in,
+				const struct net_device *out,
+				char *tablename,
+				struct xt_table_info *private,
+				struct ipt_entry *e)
+{
+	void *table_base;
+	struct ipt_entry *root;
+	char *hookname, *chainname, *comment;
+	unsigned int rulenum = 0;
+
+	table_base = (void *)private->entries[smp_processor_id()];
+	root = get_entry(table_base, private->hook_entry[hook]);
+
+	hookname = chainname = (char *)hooknames[hook];
+	comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE];
+
+	IPT_ENTRY_ITERATE(root,
+			  private->size - private->hook_entry[hook],
+			  get_chainname_rulenum,
+			  e, hookname, &chainname, &comment, &rulenum);
+
+	nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
+		      "TRACE: %s:%s:%s:%u ",
+		      tablename, chainname, comment, rulenum);
+}
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ipt_do_table(struct sk_buff **pskb,
@@ -267,6 +371,12 @@
 
 			t = ipt_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
+			
+			/* The packet is traced: log it */
+			if ((*pskb)->nf_trace)
+				trace_packet(*pskb, hook, in, out,
+					     table->name, private, e);
+
 			/* Standard target? */
 			if (!t->u.kernel.target->target) {
 				int v;
@@ -347,19 +457,6 @@
 #endif
 }
 
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ipt_ip *ip)
-{
-	unsigned int i;
-
-	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
-		if (((__u32 *)ip)[i])
-			return 0;
-
-	return 1;
-}
-
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
diff -urN --exclude-from=/usr/src/diff.exclude linux-2.6.21-orig/net/ipv6/netfilter/ip6_tables.c linux-2.6.21-TRACE/net/ipv6/netfilter/ip6_tables.c
--- linux-2.6.21-orig/net/ipv6/netfilter/ip6_tables.c	2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21-TRACE/net/ipv6/netfilter/ip6_tables.c	2007-06-18 11:22:17.000000000 +0200
@@ -250,6 +250,111 @@
 	return (struct ip6t_entry *)(base + offset);
 }
 
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ip6t_ip6 *ipv6)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ipv6); i++)
+		if (((char *)ipv6)[i])
+			break;
+
+	return (i == sizeof(*ipv6));
+}
+
+/* This cries for unification! */
+static const char *hooknames[] = {
+	[NF_IP6_PRE_ROUTING] = "PREROUTING",
+	[NF_IP6_LOCAL_IN] = "INPUT",
+	[NF_IP6_FORWARD] = "FORWARD",
+	[NF_IP6_LOCAL_OUT] = "OUTPUT",
+	[NF_IP6_POST_ROUTING] = "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+	NF_IP6_TRACE_COMMENT_RULE,
+	NF_IP6_TRACE_COMMENT_RETURN,
+	NF_IP6_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+	[NF_IP6_TRACE_COMMENT_RULE] = "rule",
+	[NF_IP6_TRACE_COMMENT_RETURN] = "return",
+	[NF_IP6_TRACE_COMMENT_POLICY] = "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+	.type = NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level = 4,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static inline int
+get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
+		      char *hookname, char **chainname,
+		      char **comment, unsigned int *rulenum)
+{
+	struct ip6t_standard_target *t = (void *)ip6t_get_target(s);
+	
+	if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
+		/* Head of user chain: ERROR target with chainname */
+		*chainname = t->target.data;
+		(*rulenum) = 0;
+	} else if (s == e) {
+		(*rulenum)++;
+
+		if (s->target_offset == sizeof(struct ip6t_entry)
+		   && strcmp(t->target.u.kernel.target->name, 
+		   	     IP6T_STANDARD_TARGET) == 0
+		   && t->verdict < 0
+	           && unconditional(&s->ipv6)) {
+	           	/* Tail of chains: STANDARD target (return/policy) */
+	           	*comment = *chainname == hookname 
+	           		? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY]
+	           		: (char *)comments[NF_IP6_TRACE_COMMENT_RETURN];
+		}
+		return 1;
+	} else
+		(*rulenum)++;
+
+	return 0;
+}
+
+
+static inline void trace_packet(struct sk_buff *skb,
+				unsigned int hook,
+				const struct net_device *in,
+				const struct net_device *out,
+				char *tablename,
+				struct xt_table_info *private,
+				struct ip6t_entry *e)
+{
+	void *table_base;
+	struct ip6t_entry *root;
+	char *hookname, *chainname, *comment;
+	unsigned int rulenum = 0;
+
+	table_base = (void *)private->entries[smp_processor_id()];
+	root = get_entry(table_base, private->hook_entry[hook]);
+
+	hookname = chainname = (char *)hooknames[hook];
+	comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE];
+
+	IP6T_ENTRY_ITERATE(root,
+			   private->size - private->hook_entry[hook],
+			   get_chainname_rulenum,
+			   e, hookname, &chainname, &comment, &rulenum);
+
+	nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
+		      "TRACE: %s:%s:%s:%u ",
+		      tablename, chainname, comment, rulenum);
+}
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ip6t_do_table(struct sk_buff **pskb,
@@ -307,6 +412,12 @@
 
 			t = ip6t_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
+
+			/* The packet is traced: log it */
+			if ((*pskb)->nf_trace)
+				trace_packet(*pskb, hook, in, out,
+					     table->name, private, e);
+
 			/* Standard target? */
 			if (!t->u.kernel.target->target) {
 				int v;
@@ -386,19 +497,6 @@
 #endif
 }
 
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ip6t_ip6 *ipv6)
-{
-	unsigned int i;
-
-	for (i = 0; i < sizeof(*ipv6); i++)
-		if (((char *)ipv6)[i])
-			break;
-
-	return (i == sizeof(*ipv6));
-}
-
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
diff -urN --exclude-from=/usr/src/diff.exclude linux-2.6.21-orig/net/netfilter/Kconfig linux-2.6.21-TRACE/net/netfilter/Kconfig
--- linux-2.6.21-orig/net/netfilter/Kconfig	2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21-TRACE/net/netfilter/Kconfig	2007-06-14 22:06:57.000000000 +0200
@@ -376,6 +376,18 @@
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_TARGET_TRACE
+	tristate  '"TRACE" target support'
+	depends on NETFILTER_XTABLES
+	depends on IP_NF_RAW || IP6_NF_RAW
+	help
+	  The TRACE target allows you to mark packets so that the kernel
+	  will log every rule which match the packets as those traverse
+	  the tables, chains, rules.
+	
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.
+
 config NETFILTER_XT_TARGET_SECMARK
 	tristate '"SECMARK" target support'
 	depends on NETFILTER_XTABLES && NETWORK_SECMARK
diff -urN --exclude-from=/usr/src/diff.exclude linux-2.6.21-orig/net/netfilter/Makefile linux-2.6.21-TRACE/net/netfilter/Makefile
--- linux-2.6.21-orig/net/netfilter/Makefile	2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21-TRACE/net/netfilter/Makefile	2007-06-14 22:04:39.000000000 +0200
@@ -44,6 +44,7 @@
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
diff -urN --exclude-from=/usr/src/diff.exclude linux-2.6.21-orig/net/netfilter/xt_TRACE.c linux-2.6.21-TRACE/net/netfilter/xt_TRACE.c
--- linux-2.6.21-orig/net/netfilter/xt_TRACE.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21-TRACE/net/netfilter/xt_TRACE.c	2007-06-14 22:04:12.000000000 +0200
@@ -0,0 +1,52 @@
+/* This is a module which is used to mark packets for tracing.
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TRACE");
+
+static unsigned int
+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)
+{
+	(*pskb)->nf_trace = 1;
+	return XT_CONTINUE;
+}
+
+static struct xt_target xt_trace_target[] = {
+	{
+		.name		= "TRACE",
+		.family		= AF_INET,
+		.target		= target,
+		.table		= "raw",
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "TRACE",
+		.family		= AF_INET6,
+		.target		= target,
+		.table		= "raw",
+		.me		= THIS_MODULE,
+	},
+};
+
+static int __init xt_trace_init(void)
+{
+	return xt_register_targets(xt_trace_target,
+				   ARRAY_SIZE(xt_trace_target));
+}
+
+static void __exit xt_trace_fini(void)
+{
+	xt_unregister_targets(xt_trace_target, ARRAY_SIZE(xt_trace_target));
+}
+
+module_init(xt_trace_init);
+module_exit(xt_trace_fini);

[-- Attachment #3: iptables-trace.patch --]
[-- Type: TEXT/PLAIN, Size: 5397 bytes --]

diff -urN --exclude=.svn iptables/extensions/.TRACE-test iptables-trace/extensions/.TRACE-test
--- iptables/extensions/.TRACE-test	1970-01-01 01:00:00.000000000 +0100
+++ iptables-trace/extensions/.TRACE-test	2007-06-14 22:30:03.000000000 +0200
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/net/netfilter/xt_TRACE.c ] && echo TRACE
diff -urN --exclude=.svn iptables/extensions/.TRACE-test6 iptables-trace/extensions/.TRACE-test6
--- iptables/extensions/.TRACE-test6	1970-01-01 01:00:00.000000000 +0100
+++ iptables-trace/extensions/.TRACE-test6	2007-06-18 11:40:26.000000000 +0200
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/net/netfilter/xt_TRACE.c ] && echo TRACE
diff -urN --exclude=.svn iptables/extensions/libip6t_TRACE.c iptables-trace/extensions/libip6t_TRACE.c
--- iptables/extensions/libip6t_TRACE.c	1970-01-01 01:00:00.000000000 +0100
+++ iptables-trace/extensions/libip6t_TRACE.c	2007-06-18 11:41:40.000000000 +0200
@@ -0,0 +1,63 @@
+/* Shared library add-on to ip6tables to add TRACE target support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+	printf(
+"TRACE target v%s takes no options\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+	{ 0 }
+};
+
+/* Initialize the target. */
+static void
+init(struct ip6t_entry_target *t, unsigned int *nfcache)
+{
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      struct ip6t_entry_target **target)
+{
+	return 0;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+static
+struct ip6tables_target trace 
+= {	.next = NULL,
+	.name = "TRACE",
+	.version = IPTABLES_VERSION,
+	.size = IP6T_ALIGN(0),
+	.userspacesize = IP6T_ALIGN(0),
+	.help = &help,
+	.init = &init,
+	.parse = &parse,
+	.final_check = &final_check,
+	.print = NULL, /* print */
+	.save = NULL, /* save */
+	.extra_opts = opts
+};
+
+void _init(void)
+{
+	register_target6(&trace);
+}
diff -urN --exclude=.svn iptables/extensions/libip6t_TRACE.man iptables-trace/extensions/libip6t_TRACE.man
--- iptables/extensions/libip6t_TRACE.man	1970-01-01 01:00:00.000000000 +0100
+++ iptables-trace/extensions/libip6t_TRACE.man	2007-06-18 11:51:13.000000000 +0200
@@ -0,0 +1,10 @@
+This target marks packes so that the kernel will log every rule which match 
+the packets as those traverse the tables, chains, rules. (The ip6t_LOG module 
+is required for the logging.) The packets are logged with the string prefix: 
+"TRACE: tablename:chainname:type:rulenum " where type can be "rule" for 
+plain rule, "return" for implicit rule at the end of a user defined chain 
+and "policy" for the policy of the built in chains. 
+.br
+It can only be used in the
+.BR raw
+table.
diff -urN --exclude=.svn iptables/extensions/libipt_TRACE.c iptables-trace/extensions/libipt_TRACE.c
--- iptables/extensions/libipt_TRACE.c	1970-01-01 01:00:00.000000000 +0100
+++ iptables-trace/extensions/libipt_TRACE.c	2007-06-14 22:20:12.000000000 +0200
@@ -0,0 +1,63 @@
+/* Shared library add-on to iptables to add TRACE target support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <iptables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+	printf(
+"TRACE target v%s takes no options\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+	{ 0 }
+};
+
+/* Initialize the target. */
+static void
+init(struct ipt_entry_target *t, unsigned int *nfcache)
+{
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ipt_entry *entry,
+      struct ipt_entry_target **target)
+{
+	return 0;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+static
+struct iptables_target trace 
+= {	.next = NULL,
+	.name = "TRACE",
+	.version = IPTABLES_VERSION,
+	.size = IPT_ALIGN(0),
+	.userspacesize = IPT_ALIGN(0),
+	.help = &help,
+	.init = &init,
+	.parse = &parse,
+	.final_check = &final_check,
+	.print = NULL, /* print */
+	.save = NULL, /* save */
+	.extra_opts = opts
+};
+
+void _init(void)
+{
+	register_target(&trace);
+}
diff -urN --exclude=.svn iptables/extensions/libipt_TRACE.man iptables-trace/extensions/libipt_TRACE.man
--- iptables/extensions/libipt_TRACE.man	1970-01-01 01:00:00.000000000 +0100
+++ iptables-trace/extensions/libipt_TRACE.man	2007-06-18 11:50:49.000000000 +0200
@@ -0,0 +1,10 @@
+This target marks packes so that the kernel will log every rule which match 
+the packets as those traverse the tables, chains, rules. (The ipt_LOG module 
+is required for the logging.) The packets are logged with the string prefix: 
+"TRACE: tablename:chainname:type:rulenum " where type can be "rule" for 
+plain rule, "return" for implicit rule at the end of a user defined chain 
+and "policy" for the policy of the built in chains. 
+.br
+It can only be used in the
+.BR raw
+table.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-18 10:16                 ` Jozsef Kadlecsik
@ 2007-06-18 12:49                   ` Patrick McHardy
  2007-06-18 13:05                     ` Jozsef Kadlecsik
  2007-06-22 14:20                   ` Patrick McHardy
  1 sibling, 1 reply; 28+ messages in thread
From: Patrick McHardy @ 2007-06-18 12:49 UTC (permalink / raw)
  To: Jozsef Kadlecsik; +Cc: netfilter-devel

Jozsef Kadlecsik wrote:
> Attached you can find the reworked TRACE target, which does not suffer
> from backward incompatibility. Unfortunately I had to steal one unused
> bit from skbuff to be able to mark the packets so that it surely does
> not clash with any rules using the standard "MARK" target. Logging
> level, flags and type are hardcoded. What do you think?


Looks pretty good. Maybe we can avoid using the skb bit though, what
do you think about letting the user set a special "trace-mark" value
through /proc and using that? Not sure if thats better or worse :)

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-18 12:49                   ` Patrick McHardy
@ 2007-06-18 13:05                     ` Jozsef Kadlecsik
  2007-06-18 13:08                       ` Patrick McHardy
  0 siblings, 1 reply; 28+ messages in thread
From: Jozsef Kadlecsik @ 2007-06-18 13:05 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel

On Mon, 18 Jun 2007, Patrick McHardy wrote:

> Jozsef Kadlecsik wrote:
>> Attached you can find the reworked TRACE target, which does not suffer
>> from backward incompatibility. Unfortunately I had to steal one unused
>> bit from skbuff to be able to mark the packets so that it surely does
>> not clash with any rules using the standard "MARK" target. Logging
>> level, flags and type are hardcoded. What do you think?
>
> Looks pretty good. Maybe we can avoid using the skb bit though, what
> do you think about letting the user set a special "trace-mark" value
> through /proc and using that? Not sure if thats better or worse :)

If one uses 'MARK --set-mark' and would want to trace a living ruleset, 
he'd be forced to change the ruleset in order to be able to use tracing. 
And that's a full can of worms...

Hey, we returned the all 32 bit of nfcache! This is just one bit getting 
back ;-)

Best regards,
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlec@sunserv.kfki.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
           H-1525 Budapest 114, POB. 49, Hungary

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-18 13:05                     ` Jozsef Kadlecsik
@ 2007-06-18 13:08                       ` Patrick McHardy
  0 siblings, 0 replies; 28+ messages in thread
From: Patrick McHardy @ 2007-06-18 13:08 UTC (permalink / raw)
  To: Jozsef Kadlecsik; +Cc: netfilter-devel

Jozsef Kadlecsik wrote:
> On Mon, 18 Jun 2007, Patrick McHardy wrote:
> 
>> Jozsef Kadlecsik wrote:
>>
>>> Attached you can find the reworked TRACE target, which does not suffer
>>> from backward incompatibility. Unfortunately I had to steal one unused
>>> bit from skbuff to be able to mark the packets so that it surely does
>>> not clash with any rules using the standard "MARK" target. Logging
>>> level, flags and type are hardcoded. What do you think?
>>
>>
>> Looks pretty good. Maybe we can avoid using the skb bit though, what
>> do you think about letting the user set a special "trace-mark" value
>> through /proc and using that? Not sure if thats better or worse :)
> 
> 
> If one uses 'MARK --set-mark' and would want to trace a living ruleset,
> he'd be forced to change the ruleset in order to be able to use tracing.
> And that's a full can of worms...


Good point.

> Hey, we returned the all 32 bit of nfcache! This is just one bit getting
> back ;-)


Fair enough I guess :) The bit is unused anyway, so at least for now it
won't do any harm. I'll do some more thoroughly review in the next days
and queue it for 2.6.23 if no other issues come up.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-13  7:31   ` Fabrice Rafart
@ 2007-06-18 16:12     ` Simon
  2007-06-18 16:14       ` Patrick McHardy
  0 siblings, 1 reply; 28+ messages in thread
From: Simon @ 2007-06-18 16:12 UTC (permalink / raw)
  To: Fabrice Rafart; +Cc: netfilter-devel

> I know this possibility and I use it for log some packets but I can't double
> all my rules (almost 200) by a log rule.

Hi Fabrice,
  I don't log everything too.  I usually choose some types of
information to log, and some IP's to log from.  For example, a friend
connected to my pc and logged in to a secure website, at that moment,
i stop logging this guy, the website logs in its own way.  Somebody
that is still trying stuff and has not yet connected for X minutes
will then get flagged as a suspect and different logging takes place
(to avoid DoS, and others).

  One last detail, is if your rules are done well, you don't need to
log much.  Logging more would be for "debuging" or "development" in my
opinion.  So when I was suggesting to have a log identify each rules
passed by each packets it wasn't for a production environment.  But
then again, if you asked this kind of question, i hope it wasn't for a
prod system!

  As for testing the rules, I think the best way is to craft packets
and send them to the interface.  There are some hacking tools that
permit to make raw ethernet frames and provide "easy" way of modifying
packets at the ip or tcp level and they work like scripts that you
execute.

Good luck!
  Simon

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-18 16:12     ` Simon
@ 2007-06-18 16:14       ` Patrick McHardy
  0 siblings, 0 replies; 28+ messages in thread
From: Patrick McHardy @ 2007-06-18 16:14 UTC (permalink / raw)
  To: Simon; +Cc: Fabrice Rafart, netfilter-devel

Simon wrote:
>> I know this possibility and I use it for log some packets but I can't
>> double
>> all my rules (almost 200) by a log rule.
> 
> 
> Hi Fabrice,
>  I don't log everything too.  I usually choose some types of
> information to log, and some IP's to log from.  For example, a friend
> connected to my pc and logged in to a secure website, at that moment,
> i stop logging this guy, the website logs in its own way.  Somebody
> that is still trying stuff and has not yet connected for X minutes
> will then get flagged as a suspect and different logging takes place
> (to avoid DoS, and others).
> 
>  One last detail, is if your rules are done well, you don't need to
> log much.  Logging more would be for "debuging" or "development" in my
> opinion.  So when I was suggesting to have a log identify each rules
> passed by each packets it wasn't for a production environment.  But
> then again, if you asked this kind of question, i hope it wasn't for a
> prod system!
> 
>  As for testing the rules, I think the best way is to craft packets
> and send them to the interface.  There are some hacking tools that
> permit to make raw ethernet frames and provide "easy" way of modifying
> packets at the ip or tcp level and they work like scripts that you
> execute.


Just FYI, Jozsef sent a patch to merge TRACE into mainline today, I'll
most likely send it upstream for 2.6.23.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-18 10:16                 ` Jozsef Kadlecsik
  2007-06-18 12:49                   ` Patrick McHardy
@ 2007-06-22 14:20                   ` Patrick McHardy
  2007-06-23 16:45                     ` Jozsef Kadlecsik
  1 sibling, 1 reply; 28+ messages in thread
From: Patrick McHardy @ 2007-06-22 14:20 UTC (permalink / raw)
  To: Jozsef Kadlecsik; +Cc: netfilter-devel

Jozsef Kadlecsik wrote:
> Attached you can find the reworked TRACE target, which does not suffer
> from backward incompatibility. Unfortunately I had to steal one unused
> bit from skbuff to be able to mark the packets so that it surely does
> not clash with any rules using the standard "MARK" target. Logging
> level, flags and type are hardcoded. What do you think?

Could you send me a Signed-off-by: line so I can queue this for 2.6.23?

> +static inline void trace_packet(struct sk_buff *skb,
> +				unsigned int hook,
> +				const struct net_device *in,
> +				const struct net_device *out,
> +				char *tablename,
> +				struct xt_table_info *private,
> +				struct ipt_entry *e)


I'm going to remove the inline here ..

>  /* Returns one of the generic firewall policies, like NF_ACCEPT. */
>  unsigned int
>  ipt_do_table(struct sk_buff **pskb,
> @@ -267,6 +371,12 @@
>  
>  			t = ipt_get_target(e);
>  			IP_NF_ASSERT(t->u.kernel.target);
> +			
> +			/* The packet is traced: log it */
> +			if ((*pskb)->nf_trace)
> +				trace_packet(*pskb, hook, in, out,
> +					     table->name, private, e);
> +

and mark this unlikely so we don't bloat the main loop of ipt_do_table.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-22 14:20                   ` Patrick McHardy
@ 2007-06-23 16:45                     ` Jozsef Kadlecsik
  2007-06-24 14:48                       ` Patrick McHardy
  0 siblings, 1 reply; 28+ messages in thread
From: Jozsef Kadlecsik @ 2007-06-23 16:45 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel

On Fri, 22 Jun 2007, Patrick McHardy wrote:

> Jozsef Kadlecsik wrote:
>> Attached you can find the reworked TRACE target, which does not suffer
>> from backward incompatibility. Unfortunately I had to steal one unused
>> bit from skbuff to be able to mark the packets so that it surely does
>> not clash with any rules using the standard "MARK" target. Logging
>> level, flags and type are hardcoded. What do you think?
>
> Could you send me a Signed-off-by: line so I can queue this for 2.6.23?

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>

>> +static inline void trace_packet(struct sk_buff *skb,
>> +				unsigned int hook,
>> +				const struct net_device *in,
>> +				const struct net_device *out,
>> +				char *tablename,
>> +				struct xt_table_info *private,
>> +				struct ipt_entry *e)
>
>
> I'm going to remove the inline here ..

Yes, that's better.

>
>>  /* Returns one of the generic firewall policies, like NF_ACCEPT. */
>>  unsigned int
>>  ipt_do_table(struct sk_buff **pskb,
>> @@ -267,6 +371,12 @@
>>
>>  			t = ipt_get_target(e);
>>  			IP_NF_ASSERT(t->u.kernel.target);
>> +
>> +			/* The packet is traced: log it */
>> +			if ((*pskb)->nf_trace)
>> +				trace_packet(*pskb, hook, in, out,
>> +					     table->name, private, e);
>> +
>
> and mark this unlikely so we don't bloat the main loop of ipt_do_table.

OK, fine and thanks!

Best regards,
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlec@sunserv.kfki.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
           H-1525 Budapest 114, POB. 49, Hungary

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-23 16:45                     ` Jozsef Kadlecsik
@ 2007-06-24 14:48                       ` Patrick McHardy
  2007-06-25 12:19                         ` Patrick McHardy
  0 siblings, 1 reply; 28+ messages in thread
From: Patrick McHardy @ 2007-06-24 14:48 UTC (permalink / raw)
  To: Jozsef Kadlecsik; +Cc: netfilter-devel

Jozsef Kadlecsik wrote:
> On Fri, 22 Jun 2007, Patrick McHardy wrote:
> 
>> Jozsef Kadlecsik wrote:
>>
>>> Attached you can find the reworked TRACE target, which does not suffer
>>> from backward incompatibility. Unfortunately I had to steal one unused
>>> bit from skbuff to be able to mark the packets so that it surely does
>>> not clash with any rules using the standard "MARK" target. Logging
>>> level, flags and type are hardcoded. What do you think?
>>
>>
>> Could you send me a Signed-off-by: line so I can queue this for 2.6.23?
> 
> 
> Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>


Thanks Jozsef, applied. I've also added the missing ip6t_TRACE alias
to xt_TRACE.c.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-24 14:48                       ` Patrick McHardy
@ 2007-06-25 12:19                         ` Patrick McHardy
  2007-06-25 12:49                           ` Jan Engelhardt
  0 siblings, 1 reply; 28+ messages in thread
From: Patrick McHardy @ 2007-06-25 12:19 UTC (permalink / raw)
  To: Jozsef Kadlecsik; +Cc: netfilter-devel

[-- Attachment #1: Type: text/plain, Size: 1092 bytes --]

Patrick McHardy wrote:
> Thanks Jozsef, applied. I've also added the missing ip6t_TRACE alias
> to xt_TRACE.c.
>   

And missing copying of the nf_trace bit.

This is really cool:

RACE: raw:PREROUTING:policy:2 IN=eth0 OUT= 
MAC=00:15:f2:24:91:f8:00:0d:60:ca:60:12:08:00 SRC=192.168.0.102 
DST=192.168.0.100 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=47932 DF PROTO=TCP 
SPT=58555 DPT=12345 SEQ=3478324482 ACK=0 WINDOW=5840 RES=0x00 SYN URGP=0 
OPT (020405B40402080A0C78BE3E0000000001030305)
TRACE: filter:INPUT:rule:1 IN=eth0 OUT= 
MAC=00:15:f2:24:91:f8:00:0d:60:ca:60:12:08:00 SRC=192.168.0.102 
DST=192.168.0.100 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=47932 DF PROTO=TCP 
SPT=58555 DPT=12345 SEQ=3478324482 ACK=0 WINDOW=5840 RES=0x00 SYN URGP=0 
OPT (020405B40402080A0C78BE3E0000000001030305)
TRACE: filter:INPUT:rule:2 IN=eth0 OUT= 
MAC=00:15:f2:24:91:f8:00:0d:60:ca:60:12:08:00 SRC=192.168.0.102 
DST=192.168.0.100 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=47932 DF PROTO=TCP 
SPT=58555 DPT=12345 SEQ=3478324482 ACK=0 WINDOW=5840 RES=0x00 SYN URGP=0 
OPT (020405B40402080A0C78BE3E0000000001030305)

:)


[-- Attachment #2: x --]
[-- Type: text/plain, Size: 15031 bytes --]

[NETFILTER]: x_tables: add TRACE target

The TRACE target can be used to follow IP and IPv6 packets through
the ruleset.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick NcHardy <kaber@trash.net>

---
commit b8a85c673f041bd0acc1346150512eab5aa93b08
tree 62240ddb32f7a480a34b78b7e0deb09d84f88489
parent 69c897e7476fb6aa1adae6a57863e2c2eb278588
author Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> Mon, 25 Jun 2007 14:17:16 +0200
committer Patrick McHardy <kaber@trash.net> Mon, 25 Jun 2007 14:17:16 +0200

 include/linux/skbuff.h          |    4 +
 net/core/skbuff.c               |    8 ++
 net/ipv4/ip_output.c            |    4 +
 net/ipv4/netfilter/ip_tables.c  |  127 +++++++++++++++++++++++++++++++++++----
 net/ipv6/ip6_output.c           |    4 +
 net/ipv6/netfilter/ip6_tables.c |  128 +++++++++++++++++++++++++++++++++++----
 net/netfilter/Kconfig           |   12 ++++
 net/netfilter/Makefile          |    1 
 net/netfilter/xt_TRACE.c        |   53 ++++++++++++++++
 9 files changed, 314 insertions(+), 27 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6f0b2f7..52bba8c 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -227,6 +227,7 @@ typedef unsigned char *sk_buff_data_t;
  *	@mark: Generic packet mark
  *	@nfct: Associated connection, if any
  *	@ipvs_property: skbuff is owned by ipvs
+ *	@nf_trace: netfilter packet trace flag
  *	@nfctinfo: Relationship of this skb to the connection
  *	@nfct_reasm: netfilter conntrack re-assembly pointer
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
@@ -277,7 +278,8 @@ struct sk_buff {
 				nfctinfo:3;
 	__u8			pkt_type:3,
 				fclone:2,
-				ipvs_property:1;
+				ipvs_property:1,
+				nf_trace:1;
 	__be16			protocol;
 
 	void			(*destructor)(struct sk_buff *skb);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 27cfe5f..d2878a3 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -426,6 +426,10 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
 	n->destructor = NULL;
 	C(mark);
 	__nf_copy(n, skb);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	C(nf_trace);
+#endif
 #ifdef CONFIG_NET_SCHED
 	C(tc_index);
 #ifdef CONFIG_NET_CLS_ACT
@@ -482,6 +486,10 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 	new->destructor = NULL;
 	new->mark	= old->mark;
 	__nf_copy(new, old);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	new->nf_trace	= old->nf_trace;
+#endif
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	new->ipvs_property = old->ipvs_property;
 #endif
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 34ea454..7ea6144 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -399,6 +399,10 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
 	to->tc_index = from->tc_index;
 #endif
 	nf_copy(to, from);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	to->nf_trace = from->nf_trace;
+#endif
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	to->ipvs_property = from->ipvs_property;
 #endif
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 7962306..cdfdf88 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -204,6 +204,112 @@ get_entry(void *base, unsigned int offset)
 	return (struct ipt_entry *)(base + offset);
 }
 
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ipt_ip *ip)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
+		if (((__u32 *)ip)[i])
+			return 0;
+
+	return 1;
+}
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+static const char *hooknames[] = {
+	[NF_IP_PRE_ROUTING] = "PREROUTING",
+	[NF_IP_LOCAL_IN] = "INPUT",
+	[NF_IP_FORWARD] = "FORWARD",
+	[NF_IP_LOCAL_OUT] = "OUTPUT",
+	[NF_IP_POST_ROUTING] = "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+	NF_IP_TRACE_COMMENT_RULE,
+	NF_IP_TRACE_COMMENT_RETURN,
+	NF_IP_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+	[NF_IP_TRACE_COMMENT_RULE] = "rule",
+	[NF_IP_TRACE_COMMENT_RETURN] = "return",
+	[NF_IP_TRACE_COMMENT_POLICY] = "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+	.type = NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level = 4,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static inline int
+get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
+		      char *hookname, char **chainname,
+		      char **comment, unsigned int *rulenum)
+{
+	struct ipt_standard_target *t = (void *)ipt_get_target(s);
+
+	if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
+		/* Head of user chain: ERROR target with chainname */
+		*chainname = t->target.data;
+		(*rulenum) = 0;
+	} else if (s == e) {
+		(*rulenum)++;
+
+		if (s->target_offset == sizeof(struct ipt_entry)
+		   && strcmp(t->target.u.kernel.target->name,
+		   	     IPT_STANDARD_TARGET) == 0
+		   && t->verdict < 0
+	           && unconditional(&s->ip)) {
+	           	/* Tail of chains: STANDARD target (return/policy) */
+	           	*comment = *chainname == hookname
+	           		? (char *)comments[NF_IP_TRACE_COMMENT_POLICY]
+	           		: (char *)comments[NF_IP_TRACE_COMMENT_RETURN];
+		}
+		return 1;
+	} else
+		(*rulenum)++;
+
+	return 0;
+}
+
+static void trace_packet(struct sk_buff *skb,
+			 unsigned int hook,
+			 const struct net_device *in,
+			 const struct net_device *out,
+			 char *tablename,
+			 struct xt_table_info *private,
+			 struct ipt_entry *e)
+{
+	void *table_base;
+	struct ipt_entry *root;
+	char *hookname, *chainname, *comment;
+	unsigned int rulenum = 0;
+
+	table_base = (void *)private->entries[smp_processor_id()];
+	root = get_entry(table_base, private->hook_entry[hook]);
+
+	hookname = chainname = (char *)hooknames[hook];
+	comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE];
+
+	IPT_ENTRY_ITERATE(root,
+			  private->size - private->hook_entry[hook],
+			  get_chainname_rulenum,
+			  e, hookname, &chainname, &comment, &rulenum);
+
+	nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
+		      "TRACE: %s:%s:%s:%u ",
+		      tablename, chainname, comment, rulenum);
+}
+#endif
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ipt_do_table(struct sk_buff **pskb,
@@ -261,6 +367,14 @@ ipt_do_table(struct sk_buff **pskb,
 
 			t = ipt_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+			/* The packet is traced: log it */
+			if (unlikely((*pskb)->nf_trace))
+				trace_packet(*pskb, hook, in, out,
+					     table->name, private, e);
+#endif
 			/* Standard target? */
 			if (!t->u.kernel.target->target) {
 				int v;
@@ -341,19 +455,6 @@ ipt_do_table(struct sk_buff **pskb,
 #endif
 }
 
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ipt_ip *ip)
-{
-	unsigned int i;
-
-	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
-		if (((__u32 *)ip)[i])
-			return 0;
-
-	return 1;
-}
-
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 4704b5f..db47321 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -521,6 +521,10 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
 	to->tc_index = from->tc_index;
 #endif
 	nf_copy(to, from);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	to->nf_trace = from->nf_trace;
+#endif
 	skb_copy_secmark(to, from);
 }
 
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 7fe4d29..a67cec8 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -241,6 +241,113 @@ get_entry(void *base, unsigned int offset)
 	return (struct ip6t_entry *)(base + offset);
 }
 
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ip6t_ip6 *ipv6)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ipv6); i++)
+		if (((char *)ipv6)[i])
+			break;
+
+	return (i == sizeof(*ipv6));
+}
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+/* This cries for unification! */
+static const char *hooknames[] = {
+	[NF_IP6_PRE_ROUTING] = "PREROUTING",
+	[NF_IP6_LOCAL_IN] = "INPUT",
+	[NF_IP6_FORWARD] = "FORWARD",
+	[NF_IP6_LOCAL_OUT] = "OUTPUT",
+	[NF_IP6_POST_ROUTING] = "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+	NF_IP6_TRACE_COMMENT_RULE,
+	NF_IP6_TRACE_COMMENT_RETURN,
+	NF_IP6_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+	[NF_IP6_TRACE_COMMENT_RULE] = "rule",
+	[NF_IP6_TRACE_COMMENT_RETURN] = "return",
+	[NF_IP6_TRACE_COMMENT_POLICY] = "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+	.type = NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level = 4,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static inline int
+get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
+		      char *hookname, char **chainname,
+		      char **comment, unsigned int *rulenum)
+{
+	struct ip6t_standard_target *t = (void *)ip6t_get_target(s);
+
+	if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
+		/* Head of user chain: ERROR target with chainname */
+		*chainname = t->target.data;
+		(*rulenum) = 0;
+	} else if (s == e) {
+		(*rulenum)++;
+
+		if (s->target_offset == sizeof(struct ip6t_entry)
+		   && strcmp(t->target.u.kernel.target->name, 
+		   	     IP6T_STANDARD_TARGET) == 0
+		   && t->verdict < 0
+	           && unconditional(&s->ipv6)) {
+	           	/* Tail of chains: STANDARD target (return/policy) */
+	           	*comment = *chainname == hookname 
+	           		? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY]
+	           		: (char *)comments[NF_IP6_TRACE_COMMENT_RETURN];
+		}
+		return 1;
+	} else
+		(*rulenum)++;
+
+	return 0;
+}
+
+static void trace_packet(struct sk_buff *skb,
+			 unsigned int hook,
+			 const struct net_device *in,
+			 const struct net_device *out,
+			 char *tablename,
+			 struct xt_table_info *private,
+			 struct ip6t_entry *e)
+{
+	void *table_base;
+	struct ip6t_entry *root;
+	char *hookname, *chainname, *comment;
+	unsigned int rulenum = 0;
+
+	table_base = (void *)private->entries[smp_processor_id()];
+	root = get_entry(table_base, private->hook_entry[hook]);
+
+	hookname = chainname = (char *)hooknames[hook];
+	comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE];
+
+	IP6T_ENTRY_ITERATE(root,
+			   private->size - private->hook_entry[hook],
+			   get_chainname_rulenum,
+			   e, hookname, &chainname, &comment, &rulenum);
+
+	nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
+		      "TRACE: %s:%s:%s:%u ",
+		      tablename, chainname, comment, rulenum);
+}
+#endif
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ip6t_do_table(struct sk_buff **pskb,
@@ -298,6 +405,14 @@ ip6t_do_table(struct sk_buff **pskb,
 
 			t = ip6t_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+			/* The packet is traced: log it */
+			if (unlikely((*pskb)->nf_trace))
+				trace_packet(*pskb, hook, in, out,
+					     table->name, private, e);
+#endif
 			/* Standard target? */
 			if (!t->u.kernel.target->target) {
 				int v;
@@ -377,19 +492,6 @@ ip6t_do_table(struct sk_buff **pskb,
 #endif
 }
 
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ip6t_ip6 *ipv6)
-{
-	unsigned int i;
-
-	for (i = 0; i < sizeof(*ipv6); i++)
-		if (((char *)ipv6)[i])
-			break;
-
-	return (i == sizeof(*ipv6));
-}
-
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index aa567fa..df5e8da 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -343,6 +343,18 @@ config NETFILTER_XT_TARGET_NOTRACK
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_TARGET_TRACE
+	tristate  '"TRACE" target support'
+	depends on NETFILTER_XTABLES
+	depends on IP_NF_RAW || IP6_NF_RAW
+	help
+	  The TRACE target allows you to mark packets so that the kernel
+	  will log every rule which match the packets as those traverse
+	  the tables, chains, rules.
+
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.
+
 config NETFILTER_XT_TARGET_SECMARK
 	tristate '"SECMARK" target support'
 	depends on NETFILTER_XTABLES && NETWORK_SECMARK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 3cf5b9c..3b79268 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c
new file mode 100644
index 0000000..b82fc46
--- /dev/null
+++ b/net/netfilter/xt_TRACE.c
@@ -0,0 +1,53 @@
+/* This is a module which is used to mark packets for tracing.
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TRACE");
+MODULE_ALIAS("ip6t_TRACE");
+
+static unsigned int
+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)
+{
+	(*pskb)->nf_trace = 1;
+	return XT_CONTINUE;
+}
+
+static struct xt_target xt_trace_target[] = {
+	{
+		.name		= "TRACE",
+		.family		= AF_INET,
+		.target		= target,
+		.table		= "raw",
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "TRACE",
+		.family		= AF_INET6,
+		.target		= target,
+		.table		= "raw",
+		.me		= THIS_MODULE,
+	},
+};
+
+static int __init xt_trace_init(void)
+{
+	return xt_register_targets(xt_trace_target,
+				   ARRAY_SIZE(xt_trace_target));
+}
+
+static void __exit xt_trace_fini(void)
+{
+	xt_unregister_targets(xt_trace_target, ARRAY_SIZE(xt_trace_target));
+}
+
+module_init(xt_trace_init);
+module_exit(xt_trace_fini);

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-25 12:19                         ` Patrick McHardy
@ 2007-06-25 12:49                           ` Jan Engelhardt
  2007-06-25 12:52                             ` Patrick McHardy
  2007-06-25 13:00                             ` Patrick McHardy
  0 siblings, 2 replies; 28+ messages in thread
From: Jan Engelhardt @ 2007-06-25 12:49 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel, Jozsef Kadlecsik

Hi,

On Jun 25 2007 14:19, Patrick McHardy wrote:
>
>

What was that about inline patches ... take the
following with a bit of ":)"


+static const char *hooknames[] = {
+	[NF_IP_PRE_ROUTING] = "PREROUTING",
+	[NF_IP_LOCAL_IN] = "INPUT",
+	[NF_IP_FORWARD] = "FORWARD",
+	[NF_IP_LOCAL_OUT] = "OUTPUT",
+	[NF_IP_POST_ROUTING] = "POSTROUTING",
+};

Align it up.


>--- a/net/netfilter/Kconfig
>@@ -343,6 +343,18 @@ config NETFILTER_XT_TARGET_NOTRACK
>
>[...]
>
>--- a/net/netfilter/Makefile
>+++ b/net/netfilter/Makefile
>@@ -44,6 +44,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
>+obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
> obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o

I don't know about your locale, but in mine,
SECMARK < TCPMSS < TRACE holds.
(Including CONNSECMARK < SECMARK, but that seems to be another thing.)

>+MODULE_LICENSE("GPL");
>+MODULE_ALIAS("ipt_TRACE");
>+MODULE_ALIAS("ip6t_TRACE");

No MODULE_AUTHOR/MODULE_DESCRIPTION?

>+static struct xt_target xt_trace_target[] = {
>+	{
>+		.name		= "TRACE",
                        ^ spaces?
 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-25 12:49                           ` Jan Engelhardt
@ 2007-06-25 12:52                             ` Patrick McHardy
  2007-06-25 13:00                             ` Patrick McHardy
  1 sibling, 0 replies; 28+ messages in thread
From: Patrick McHardy @ 2007-06-25 12:52 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netfilter-devel, Jozsef Kadlecsik

Jan Engelhardt wrote:
>
> +static const char *hooknames[] = {
> +	[NF_IP_PRE_ROUTING] = "PREROUTING",
> +	[NF_IP_LOCAL_IN] = "INPUT",
> +	[NF_IP_FORWARD] = "FORWARD",
> +	[NF_IP_LOCAL_OUT] = "OUTPUT",
> +	[NF_IP_POST_ROUTING] = "POSTROUTING",
> +};
>
> Align it up.
>   

Yeah, I like that better as well.
>
>   
>> --- a/net/netfilter/Kconfig
>> @@ -343,6 +343,18 @@ config NETFILTER_XT_TARGET_NOTRACK
>>
>> [...]
>>
>> --- a/net/netfilter/Makefile
>> +++ b/net/netfilter/Makefile
>> @@ -44,6 +44,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
>> obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
>> obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
>> obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
>> +obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
>> obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
>> obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
>> obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
>>     
>
> I don't know about your locale, but in mine,
> SECMARK < TCPMSS < TRACE holds.
> (Including CONNSECMARK < SECMARK, but that seems to be another thing.)
>   

They're not strictly alphabetically ordered. TRACE is next to NOTRACK
because they're both raw table targets. In the TRACE case I think it
would make sense to lift that restriction though.

>   
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("ipt_TRACE");
>> +MODULE_ALIAS("ip6t_TRACE");
>>     
>
> No MODULE_AUTHOR/MODULE_DESCRIPTION?
>   

Not required. How really reads those anyway?

>   
>> +static struct xt_target xt_trace_target[] = {
>> +	{
>> +		.name		= "TRACE",
>>     
>                         ^ spaces?
>   

Thanks, will fix.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-25 12:49                           ` Jan Engelhardt
  2007-06-25 12:52                             ` Patrick McHardy
@ 2007-06-25 13:00                             ` Patrick McHardy
  2007-06-25 13:52                               ` Jan Engelhardt
  1 sibling, 1 reply; 28+ messages in thread
From: Patrick McHardy @ 2007-06-25 13:00 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netfilter-devel, Jozsef Kadlecsik

[-- Attachment #1: Type: text/plain, Size: 71 bytes --]

Jan Engelhardt wrote:
> ...

Whitespace issues fixed, texts aligned.



[-- Attachment #2: x --]
[-- Type: text/plain, Size: 14940 bytes --]

[NETFILTER]: x_tables: add TRACE target

The TRACE target can be used to follow IP and IPv6 packets through
the ruleset.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick NcHardy <kaber@trash.net>

---
commit cd9e0f04391e5fa3e0a289fcb646e2770013e3c7
tree 3628c2e1254ba709e685a71f6f81ea493a9256b5
parent 69c897e7476fb6aa1adae6a57863e2c2eb278588
author Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> Mon, 25 Jun 2007 14:59:24 +0200
committer Patrick McHardy <kaber@trash.net> Mon, 25 Jun 2007 14:59:24 +0200

 include/linux/skbuff.h          |    4 +
 net/core/skbuff.c               |    8 ++
 net/ipv4/ip_output.c            |    4 +
 net/ipv4/netfilter/ip_tables.c  |  127 +++++++++++++++++++++++++++++++++++----
 net/ipv6/ip6_output.c           |    4 +
 net/ipv6/netfilter/ip6_tables.c |  128 +++++++++++++++++++++++++++++++++++----
 net/netfilter/Kconfig           |   12 ++++
 net/netfilter/Makefile          |    1 
 net/netfilter/xt_TRACE.c        |   53 ++++++++++++++++
 9 files changed, 314 insertions(+), 27 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6f0b2f7..52bba8c 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -227,6 +227,7 @@ typedef unsigned char *sk_buff_data_t;
  *	@mark: Generic packet mark
  *	@nfct: Associated connection, if any
  *	@ipvs_property: skbuff is owned by ipvs
+ *	@nf_trace: netfilter packet trace flag
  *	@nfctinfo: Relationship of this skb to the connection
  *	@nfct_reasm: netfilter conntrack re-assembly pointer
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
@@ -277,7 +278,8 @@ struct sk_buff {
 				nfctinfo:3;
 	__u8			pkt_type:3,
 				fclone:2,
-				ipvs_property:1;
+				ipvs_property:1,
+				nf_trace:1;
 	__be16			protocol;
 
 	void			(*destructor)(struct sk_buff *skb);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 27cfe5f..d2878a3 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -426,6 +426,10 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
 	n->destructor = NULL;
 	C(mark);
 	__nf_copy(n, skb);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	C(nf_trace);
+#endif
 #ifdef CONFIG_NET_SCHED
 	C(tc_index);
 #ifdef CONFIG_NET_CLS_ACT
@@ -482,6 +486,10 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 	new->destructor = NULL;
 	new->mark	= old->mark;
 	__nf_copy(new, old);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	new->nf_trace	= old->nf_trace;
+#endif
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	new->ipvs_property = old->ipvs_property;
 #endif
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 34ea454..7ea6144 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -399,6 +399,10 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
 	to->tc_index = from->tc_index;
 #endif
 	nf_copy(to, from);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	to->nf_trace = from->nf_trace;
+#endif
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	to->ipvs_property = from->ipvs_property;
 #endif
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 7962306..650ab52 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -204,6 +204,112 @@ get_entry(void *base, unsigned int offset)
 	return (struct ipt_entry *)(base + offset);
 }
 
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ipt_ip *ip)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
+		if (((__u32 *)ip)[i])
+			return 0;
+
+	return 1;
+}
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+static const char *hooknames[] = {
+	[NF_IP_PRE_ROUTING]		= "PREROUTING",
+	[NF_IP_LOCAL_IN]		= "INPUT",
+	[NF_IP_FORWARD]			= "FORWARD",
+	[NF_IP_LOCAL_OUT]		= "OUTPUT",
+	[NF_IP_POST_ROUTING]		= "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+	NF_IP_TRACE_COMMENT_RULE,
+	NF_IP_TRACE_COMMENT_RETURN,
+	NF_IP_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+	[NF_IP_TRACE_COMMENT_RULE]	= "rule",
+	[NF_IP_TRACE_COMMENT_RETURN]	= "return",
+	[NF_IP_TRACE_COMMENT_POLICY]	= "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+	.type = NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level = 4,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static inline int
+get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
+		      char *hookname, char **chainname,
+		      char **comment, unsigned int *rulenum)
+{
+	struct ipt_standard_target *t = (void *)ipt_get_target(s);
+
+	if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
+		/* Head of user chain: ERROR target with chainname */
+		*chainname = t->target.data;
+		(*rulenum) = 0;
+	} else if (s == e) {
+		(*rulenum)++;
+
+		if (s->target_offset == sizeof(struct ipt_entry)
+		   && strcmp(t->target.u.kernel.target->name,
+			     IPT_STANDARD_TARGET) == 0
+		   && t->verdict < 0
+		   && unconditional(&s->ip)) {
+			/* Tail of chains: STANDARD target (return/policy) */
+			*comment = *chainname == hookname
+				? (char *)comments[NF_IP_TRACE_COMMENT_POLICY]
+				: (char *)comments[NF_IP_TRACE_COMMENT_RETURN];
+		}
+		return 1;
+	} else
+		(*rulenum)++;
+
+	return 0;
+}
+
+static void trace_packet(struct sk_buff *skb,
+			 unsigned int hook,
+			 const struct net_device *in,
+			 const struct net_device *out,
+			 char *tablename,
+			 struct xt_table_info *private,
+			 struct ipt_entry *e)
+{
+	void *table_base;
+	struct ipt_entry *root;
+	char *hookname, *chainname, *comment;
+	unsigned int rulenum = 0;
+
+	table_base = (void *)private->entries[smp_processor_id()];
+	root = get_entry(table_base, private->hook_entry[hook]);
+
+	hookname = chainname = (char *)hooknames[hook];
+	comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE];
+
+	IPT_ENTRY_ITERATE(root,
+			  private->size - private->hook_entry[hook],
+			  get_chainname_rulenum,
+			  e, hookname, &chainname, &comment, &rulenum);
+
+	nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
+		      "TRACE: %s:%s:%s:%u ",
+		      tablename, chainname, comment, rulenum);
+}
+#endif
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ipt_do_table(struct sk_buff **pskb,
@@ -261,6 +367,14 @@ ipt_do_table(struct sk_buff **pskb,
 
 			t = ipt_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+			/* The packet is traced: log it */
+			if (unlikely((*pskb)->nf_trace))
+				trace_packet(*pskb, hook, in, out,
+					     table->name, private, e);
+#endif
 			/* Standard target? */
 			if (!t->u.kernel.target->target) {
 				int v;
@@ -341,19 +455,6 @@ ipt_do_table(struct sk_buff **pskb,
 #endif
 }
 
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ipt_ip *ip)
-{
-	unsigned int i;
-
-	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
-		if (((__u32 *)ip)[i])
-			return 0;
-
-	return 1;
-}
-
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 4704b5f..db47321 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -521,6 +521,10 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
 	to->tc_index = from->tc_index;
 #endif
 	nf_copy(to, from);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	to->nf_trace = from->nf_trace;
+#endif
 	skb_copy_secmark(to, from);
 }
 
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 7fe4d29..4f93b79 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -241,6 +241,113 @@ get_entry(void *base, unsigned int offset)
 	return (struct ip6t_entry *)(base + offset);
 }
 
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ip6t_ip6 *ipv6)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ipv6); i++)
+		if (((char *)ipv6)[i])
+			break;
+
+	return (i == sizeof(*ipv6));
+}
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+/* This cries for unification! */
+static const char *hooknames[] = {
+	[NF_IP6_PRE_ROUTING]		= "PREROUTING",
+	[NF_IP6_LOCAL_IN]		= "INPUT",
+	[NF_IP6_FORWARD]		= "FORWARD",
+	[NF_IP6_LOCAL_OUT]		= "OUTPUT",
+	[NF_IP6_POST_ROUTING]		= "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+	NF_IP6_TRACE_COMMENT_RULE,
+	NF_IP6_TRACE_COMMENT_RETURN,
+	NF_IP6_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+	[NF_IP6_TRACE_COMMENT_RULE]	= "rule",
+	[NF_IP6_TRACE_COMMENT_RETURN]	= "return",
+	[NF_IP6_TRACE_COMMENT_POLICY]	= "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+	.type = NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level = 4,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static inline int
+get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
+		      char *hookname, char **chainname,
+		      char **comment, unsigned int *rulenum)
+{
+	struct ip6t_standard_target *t = (void *)ip6t_get_target(s);
+
+	if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
+		/* Head of user chain: ERROR target with chainname */
+		*chainname = t->target.data;
+		(*rulenum) = 0;
+	} else if (s == e) {
+		(*rulenum)++;
+
+		if (s->target_offset == sizeof(struct ip6t_entry)
+		   && strcmp(t->target.u.kernel.target->name,
+			     IP6T_STANDARD_TARGET) == 0
+		   && t->verdict < 0
+		   && unconditional(&s->ipv6)) {
+			/* Tail of chains: STANDARD target (return/policy) */
+			*comment = *chainname == hookname
+				? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY]
+				: (char *)comments[NF_IP6_TRACE_COMMENT_RETURN];
+		}
+		return 1;
+	} else
+		(*rulenum)++;
+
+	return 0;
+}
+
+static void trace_packet(struct sk_buff *skb,
+			 unsigned int hook,
+			 const struct net_device *in,
+			 const struct net_device *out,
+			 char *tablename,
+			 struct xt_table_info *private,
+			 struct ip6t_entry *e)
+{
+	void *table_base;
+	struct ip6t_entry *root;
+	char *hookname, *chainname, *comment;
+	unsigned int rulenum = 0;
+
+	table_base = (void *)private->entries[smp_processor_id()];
+	root = get_entry(table_base, private->hook_entry[hook]);
+
+	hookname = chainname = (char *)hooknames[hook];
+	comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE];
+
+	IP6T_ENTRY_ITERATE(root,
+			   private->size - private->hook_entry[hook],
+			   get_chainname_rulenum,
+			   e, hookname, &chainname, &comment, &rulenum);
+
+	nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
+		      "TRACE: %s:%s:%s:%u ",
+		      tablename, chainname, comment, rulenum);
+}
+#endif
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ip6t_do_table(struct sk_buff **pskb,
@@ -298,6 +405,14 @@ ip6t_do_table(struct sk_buff **pskb,
 
 			t = ip6t_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+			/* The packet is traced: log it */
+			if (unlikely((*pskb)->nf_trace))
+				trace_packet(*pskb, hook, in, out,
+					     table->name, private, e);
+#endif
 			/* Standard target? */
 			if (!t->u.kernel.target->target) {
 				int v;
@@ -377,19 +492,6 @@ ip6t_do_table(struct sk_buff **pskb,
 #endif
 }
 
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ip6t_ip6 *ipv6)
-{
-	unsigned int i;
-
-	for (i = 0; i < sizeof(*ipv6); i++)
-		if (((char *)ipv6)[i])
-			break;
-
-	return (i == sizeof(*ipv6));
-}
-
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index aa567fa..df5e8da 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -343,6 +343,18 @@ config NETFILTER_XT_TARGET_NOTRACK
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_TARGET_TRACE
+	tristate  '"TRACE" target support'
+	depends on NETFILTER_XTABLES
+	depends on IP_NF_RAW || IP6_NF_RAW
+	help
+	  The TRACE target allows you to mark packets so that the kernel
+	  will log every rule which match the packets as those traverse
+	  the tables, chains, rules.
+
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.
+
 config NETFILTER_XT_TARGET_SECMARK
 	tristate '"SECMARK" target support'
 	depends on NETFILTER_XTABLES && NETWORK_SECMARK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 3cf5b9c..3b79268 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c
new file mode 100644
index 0000000..b82fc46
--- /dev/null
+++ b/net/netfilter/xt_TRACE.c
@@ -0,0 +1,53 @@
+/* This is a module which is used to mark packets for tracing.
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TRACE");
+MODULE_ALIAS("ip6t_TRACE");
+
+static unsigned int
+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)
+{
+	(*pskb)->nf_trace = 1;
+	return XT_CONTINUE;
+}
+
+static struct xt_target xt_trace_target[] = {
+	{
+		.name		= "TRACE",
+		.family		= AF_INET,
+		.target		= target,
+		.table		= "raw",
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "TRACE",
+		.family		= AF_INET6,
+		.target		= target,
+		.table		= "raw",
+		.me		= THIS_MODULE,
+	},
+};
+
+static int __init xt_trace_init(void)
+{
+	return xt_register_targets(xt_trace_target,
+				   ARRAY_SIZE(xt_trace_target));
+}
+
+static void __exit xt_trace_fini(void)
+{
+	xt_unregister_targets(xt_trace_target, ARRAY_SIZE(xt_trace_target));
+}
+
+module_init(xt_trace_init);
+module_exit(xt_trace_fini);

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-25 13:00                             ` Patrick McHardy
@ 2007-06-25 13:52                               ` Jan Engelhardt
  2007-06-25 13:55                                 ` Patrick McHardy
  0 siblings, 1 reply; 28+ messages in thread
From: Jan Engelhardt @ 2007-06-25 13:52 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel, Jozsef Kadlecsik


On Jun 25 2007 15:00, Patrick McHardy wrote:
+static const char *hooknames[] = {
+	[NF_IP_PRE_ROUTING]		= "PREROUTING",
                           ^
Well I meant: Where are the spaces? Try looking at it with tab width 4
and you'll see the alignment breaks :)


	Jan
-- 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Follow packets in rules
  2007-06-25 13:52                               ` Jan Engelhardt
@ 2007-06-25 13:55                                 ` Patrick McHardy
  0 siblings, 0 replies; 28+ messages in thread
From: Patrick McHardy @ 2007-06-25 13:55 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netfilter-devel, Jozsef Kadlecsik

Jan Engelhardt wrote:
> On Jun 25 2007 15:00, Patrick McHardy wrote:
> +static const char *hooknames[] = {
> +	[NF_IP_PRE_ROUTING]		= "PREROUTING",
>                            ^
> Well I meant: Where are the spaces? Try looking at it with tab width 4
> and you'll see the alignment breaks :)


I don't really care how it looks with tab width 4.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: Follow packets in rules
  2007-06-12 18:08 Follow packets in rules Fabrice Rafart
  2007-06-12 21:41 ` Simon
  2007-06-13  8:57 ` Pablo Neira Ayuso
@ 2007-07-03 15:07 ` Fabrice Rafart
  2 siblings, 0 replies; 28+ messages in thread
From: Fabrice Rafart @ 2007-07-03 15:07 UTC (permalink / raw)
  To: netfilter-devel

Hi to all !

I see that my post is not useless ! :)

Finally, it doesn't exist a user friendly solution to my problem ... Maybe
later.

Regards to all.

Ps : I'll not keep my subscription to this list.

Cordialement,
-- 
Fabrice Rafart
Administrateur systèmes et réseaux
Etablissement français du sang, Ile de France.

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2007-07-03 15:07 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-06-12 18:08 Follow packets in rules Fabrice Rafart
2007-06-12 21:41 ` Simon
2007-06-13  7:31   ` Fabrice Rafart
2007-06-18 16:12     ` Simon
2007-06-18 16:14       ` Patrick McHardy
2007-06-13  8:57 ` Pablo Neira Ayuso
2007-06-13 15:43   ` Juan León
2007-06-13 16:28     ` Samuel Jean
2007-06-13 16:53       ` Patrick McHardy
2007-06-13 19:43         ` Jozsef Kadlecsik
2007-06-14  7:55           ` Fabrice Rafart
2007-06-14 13:13           ` Patrick McHardy
2007-06-14 14:18             ` Jozsef Kadlecsik
2007-06-14 14:23               ` Patrick McHardy
2007-06-18 10:16                 ` Jozsef Kadlecsik
2007-06-18 12:49                   ` Patrick McHardy
2007-06-18 13:05                     ` Jozsef Kadlecsik
2007-06-18 13:08                       ` Patrick McHardy
2007-06-22 14:20                   ` Patrick McHardy
2007-06-23 16:45                     ` Jozsef Kadlecsik
2007-06-24 14:48                       ` Patrick McHardy
2007-06-25 12:19                         ` Patrick McHardy
2007-06-25 12:49                           ` Jan Engelhardt
2007-06-25 12:52                             ` Patrick McHardy
2007-06-25 13:00                             ` Patrick McHardy
2007-06-25 13:52                               ` Jan Engelhardt
2007-06-25 13:55                                 ` Patrick McHardy
2007-07-03 15:07 ` Fabrice Rafart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.