netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-15 14:13         ` Patrick McHardy
@ 2008-01-16 18:02           ` Jan Engelhardt
  2008-01-17 13:52             ` Pablo Neira Ayuso
  0 siblings, 1 reply; 17+ messages in thread
From: Jan Engelhardt @ 2008-01-16 18:02 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Netfilter Developer Mailing List


On Jan 15 2008 15:13, Patrick McHardy wrote:
> Jan Engelhardt wrote:
>> On Jan 15 2008 07:48, Patrick McHardy wrote:
>> > This reminded me - while we're introducing new revisions, there
>> > are two things that have always been missing from xt_conntrack
>> > and I know of multiple patches adding this. One is port matching
>> > for both directions, the other is matching on the direction
>> > itself. Would you be interested in adding this? Otherwise I'm
>> > going to take care of it myself.
>> >
>> 
>> I will take care of that, yes.
>
> Thanks.
>

This patch also removes the ugly #include <linux/in.h>, which is already
found in netfilter.h (which is a better place).

===
commit 17934f6d825d2a6785cd8d7811997a8620cfd528
Author: Jan Engelhardt <jengelh@computergmbh.de>
Date:   Wed Jan 16 18:58:49 2008 +0100

    [NETFILTER]: xt_conntrack: add port and direction matching
    
    Extend the xt_conntrack match revision 1 by port matching (all four
    {orig,repl}{src,dst}) and by packet direction matching.
    
    Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>

diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h
index d2492a3..9e35ccd 100644
--- a/include/linux/netfilter/xt_conntrack.h
+++ b/include/linux/netfilter/xt_conntrack.h
@@ -6,9 +6,6 @@
 #define _XT_CONNTRACK_H
 
 #include <linux/netfilter/nf_conntrack_tuple_common.h>
-#ifdef __KERNEL__
-#	include <linux/in.h>
-#endif
 
 #define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
 #define XT_CONNTRACK_STATE_INVALID (1 << 0)
@@ -18,14 +15,21 @@
 #define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
 
 /* flags, invflags: */
-#define XT_CONNTRACK_STATE	0x01
-#define XT_CONNTRACK_PROTO	0x02
-#define XT_CONNTRACK_ORIGSRC	0x04
-#define XT_CONNTRACK_ORIGDST	0x08
-#define XT_CONNTRACK_REPLSRC	0x10
-#define XT_CONNTRACK_REPLDST	0x20
-#define XT_CONNTRACK_STATUS	0x40
-#define XT_CONNTRACK_EXPIRES	0x80
+enum {
+	XT_CONNTRACK_STATE        = 1 << 0,
+	XT_CONNTRACK_PROTO        = 1 << 1,
+	XT_CONNTRACK_ORIGSRC      = 1 << 2,
+	XT_CONNTRACK_ORIGDST      = 1 << 3,
+	XT_CONNTRACK_REPLSRC      = 1 << 4,
+	XT_CONNTRACK_REPLDST      = 1 << 5,
+	XT_CONNTRACK_STATUS       = 1 << 6,
+	XT_CONNTRACK_EXPIRES      = 1 << 7,
+	XT_CONNTRACK_ORIGSRC_PORT = 1 << 8,
+	XT_CONNTRACK_ORIGDST_PORT = 1 << 9,
+	XT_CONNTRACK_REPLSRC_PORT = 1 << 10,
+	XT_CONNTRACK_REPLDST_PORT = 1 << 11,
+	XT_CONNTRACK_DIRECTION    = 1 << 12,
+};
 
 /* This is exposed to userspace, so remains frozen in time. */
 struct ip_conntrack_old_tuple
@@ -70,8 +74,10 @@ struct xt_conntrack_mtinfo1 {
 	union nf_inet_addr repldst_addr, repldst_mask;
 	u_int32_t expires_min, expires_max;
 	u_int16_t l4proto;
+	u_int16_t origsrc_port, origdst_port;
+	u_int16_t replsrc_port, repldst_port;
+	u_int16_t match_flags, invert_flags;
 	u_int8_t state_mask, status_mask;
-	u_int8_t match_flags, invert_flags;
 };
 
 #endif /*_XT_CONNTRACK_H*/
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index e92190e..851cba6 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -166,6 +166,67 @@ conntrack_mt_repldst(const struct nf_conn *ct,
 	       &info->repldst_addr, &info->repldst_mask, family);
 }
 
+static inline bool
+ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
+                    const struct nf_conn *ct)
+{
+	const struct nf_conntrack_tuple *tuple;
+
+	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+	if (info->match_flags & XT_CONNTRACK_PROTO)
+		if ((tuple->dst.protonum == info->l4proto) ^
+		    !(info->invert_flags & XT_CONNTRACK_PROTO))
+			return false;
+
+	switch (tuple->dst.protonum) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_SCTP:
+		/*
+		 * shortcut by using .u.all rather than
+		 * .u.tcp.port + .u.udp.port!
+		 */
+		if ((info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) &&
+		    (tuple->src.u.all != info->origsrc_port) ^
+		    !(info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT))
+			return false;
+		if ((info->match_flags & XT_CONNTRACK_ORIGDST_PORT) &&
+		    (tuple->dst.u.all != info->origdst_port) ^
+		    !(info->invert_flags & XT_CONNTRACK_ORIGDST_PORT))
+			return false;
+		break;
+	default:
+		if ((info->match_flags ^ info->invert_flags) &
+		    (XT_CONNTRACK_ORIGSRC_PORT | XT_CONNTRACK_ORIGDST_PORT))
+			return false;
+		break;
+	}
+
+	tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+	switch (tuple->dst.protonum) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_SCTP:
+		/* shortcut by using ->src.all */
+		if ((info->match_flags & XT_CONNTRACK_REPLSRC_PORT) &&
+		    (tuple->src.u.all != info->replsrc_port) ^
+		    !(info->invert_flags & XT_CONNTRACK_REPLSRC_PORT))
+			return false;
+		if ((info->match_flags & XT_CONNTRACK_REPLDST_PORT) &&
+		    (tuple->dst.u.all != info->repldst_port) ^
+		    !(info->invert_flags & XT_CONNTRACK_REPLDST_PORT))
+			return false;
+		break;
+	default:
+		if ((info->match_flags ^ info->invert_flags) &
+		    (XT_CONNTRACK_REPLSRC_PORT | XT_CONNTRACK_REPLDST_PORT))
+			return false;
+		break;
+	}
+
+	return true;
+}
+
 static bool
 conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
              const struct net_device *out, const struct xt_match *match,
@@ -200,10 +261,11 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
 
 	if (ct == NULL)
 		return info->match_flags & XT_CONNTRACK_STATE;
-
-	if ((info->match_flags & XT_CONNTRACK_PROTO) &&
-	    ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
-	    info->l4proto) ^ !(info->invert_flags & XT_CONNTRACK_PROTO)))
+	if (!ct_proto_port_check(info, ct))
+		return false;
+	if ((info->match_flags & XT_CONNTRACK_DIRECTION) &&
+	    (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) ^
+	    !!(info->invert_flags & XT_CONNTRACK_DIRECTION))
 		return false;
 
 	if (info->match_flags & XT_CONNTRACK_ORIGSRC)

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-16 18:02           ` [NETFILTER]: xt_conntrack: add port and direction matching Jan Engelhardt
@ 2008-01-17 13:52             ` Pablo Neira Ayuso
  2008-01-17 15:00               ` Jan Engelhardt
  0 siblings, 1 reply; 17+ messages in thread
From: Pablo Neira Ayuso @ 2008-01-17 13:52 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Patrick McHardy, Netfilter Developer Mailing List

Jan Engelhardt wrote:
> +	switch (tuple->dst.protonum) {
> +	case IPPROTO_TCP:
> +	case IPPROTO_UDP:
> +	case IPPROTO_SCTP:

Minor nitpick. Add IPPROTO_UDPLITE.

-- 
"Los honestos son inadaptados sociales" -- Les Luthiers

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-17 13:52             ` Pablo Neira Ayuso
@ 2008-01-17 15:00               ` Jan Engelhardt
  2008-01-20 13:00                 ` Patrick McHardy
  0 siblings, 1 reply; 17+ messages in thread
From: Jan Engelhardt @ 2008-01-17 15:00 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Patrick McHardy, Netfilter Developer Mailing List


On Jan 17 2008 14:52, Pablo Neira Ayuso wrote:
> Jan Engelhardt wrote:
>> +	switch (tuple->dst.protonum) {
>> +	case IPPROTO_TCP:
>> +	case IPPROTO_UDP:
>> +	case IPPROTO_SCTP:
>
> Minor nitpick. Add IPPROTO_UDPLITE.

Yeah that can be easily added. I wonder why Netfilter does not support
DCCP conntracking? (At least there is no dccp field in struct nf_conn
and the tuple things.)

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-17 15:00               ` Jan Engelhardt
@ 2008-01-20 13:00                 ` Patrick McHardy
  2008-01-20 13:12                   ` Jan Engelhardt
  2008-01-21  1:14                   ` Pablo Neira Ayuso
  0 siblings, 2 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-20 13:00 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Pablo Neira Ayuso, Netfilter Developer Mailing List

Jan Engelhardt wrote:
> On Jan 17 2008 14:52, Pablo Neira Ayuso wrote:
>> Jan Engelhardt wrote:
>>> +	switch (tuple->dst.protonum) {
>>> +	case IPPROTO_TCP:
>>> +	case IPPROTO_UDP:
>>> +	case IPPROTO_SCTP:
>> Minor nitpick. Add IPPROTO_UDPLITE.
> 
> Yeah that can be easily added.

Another nitpick: we support masks for the addresses, ranges of ports
would be nice to have here as well. I also don't think the protocol
check is very useful in this case since all conntrack entries contain
port numbers or something similar.

> I wonder why Netfilter does not support
> DCCP conntracking? (At least there is no dccp field in struct nf_conn
> and the tuple things.)

I have an old patch for this, but it was missing proper protocol state
tracking. Perhaps I should merge it without it for now since thats
still better than no support at all.

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-20 13:00                 ` Patrick McHardy
@ 2008-01-20 13:12                   ` Jan Engelhardt
  2008-01-20 13:15                     ` Patrick McHardy
  2008-01-21  1:14                   ` Pablo Neira Ayuso
  1 sibling, 1 reply; 17+ messages in thread
From: Jan Engelhardt @ 2008-01-20 13:12 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Pablo Neira Ayuso, Netfilter Developer Mailing List


On Jan 20 2008 14:00, Patrick McHardy wrote:
>
> Another nitpick: we support masks for the addresses, ranges of ports
> would be nice to have here as well.

Well well why don't we just add address ranges too then :p
Do we need it so badly?

> I also don't think the protocol
> check is very useful in this case since all conntrack entries contain
> port numbers or something similar.

Is IPv4-in-IPv4 or IPv6-in-IPv4 conntracked like UDP is?

The protocol check is important though, because IPPROTO_GRE is
_not_ included, since, it's not something that has a port.

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-20 13:12                   ` Jan Engelhardt
@ 2008-01-20 13:15                     ` Patrick McHardy
  2008-01-20 16:48                       ` Jan Engelhardt
  0 siblings, 1 reply; 17+ messages in thread
From: Patrick McHardy @ 2008-01-20 13:15 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Pablo Neira Ayuso, Netfilter Developer Mailing List

Jan Engelhardt wrote:
> On Jan 20 2008 14:00, Patrick McHardy wrote:
>> Another nitpick: we support masks for the addresses, ranges of ports
>> would be nice to have here as well.
> 
> Well well why don't we just add address ranges too then :p
> Do we need it so badly?

We already have masks, which is probably good enough.

> 
>> I also don't think the protocol
>> check is very useful in this case since all conntrack entries contain
>> port numbers or something similar.
> 
> Is IPv4-in-IPv4 or IPv6-in-IPv4 conntracked like UDP is?

Sure, by proto_generic, which uses 0 for the port numbers.

> The protocol check is important though, because IPPROTO_GRE is
> _not_ included, since, it's not something that has a port.

It has the keys, which are also just a numerical value. Don't
think of it as ports but as "layer 4 protocol keys".

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-20 13:15                     ` Patrick McHardy
@ 2008-01-20 16:48                       ` Jan Engelhardt
  2008-01-20 16:55                         ` Patrick McHardy
  0 siblings, 1 reply; 17+ messages in thread
From: Jan Engelhardt @ 2008-01-20 16:48 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Pablo Neira Ayuso, Netfilter Developer Mailing List


On Jan 20 2008 14:15, Patrick McHardy wrote:
>> 
>> > I also don't think the protocol
>> > check is very useful in this case since all conntrack entries contain
>> > port numbers or something similar.
>> 
>> Is IPv4-in-IPv4 or IPv6-in-IPv4 conntracked like UDP is?
>
> Sure, by proto_generic, which uses 0 for the port numbers.

See, that's another case why we have to explicitly list the protocols.
Just consider a stupid invocation of iptables:

	-m conntrack --ctorigport 0

I'd rather not let that match IPv4-in-IPv4 or so.

>> The protocol check is important though, because IPPROTO_GRE is
>> _not_ included, since, it's not something that has a port.
>
> It has the keys, which are also just a numerical value. Don't
> think of it as ports but as "layer 4 protocol keys".
>
But do these keys actually get modified in NAT?

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-20 16:48                       ` Jan Engelhardt
@ 2008-01-20 16:55                         ` Patrick McHardy
  0 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-20 16:55 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Pablo Neira Ayuso, Netfilter Developer Mailing List

Jan Engelhardt wrote:
> On Jan 20 2008 14:15, Patrick McHardy wrote:
>>>> I also don't think the protocol
>>>> check is very useful in this case since all conntrack entries contain
>>>> port numbers or something similar.
>>> Is IPv4-in-IPv4 or IPv6-in-IPv4 conntracked like UDP is?
>> Sure, by proto_generic, which uses 0 for the port numbers.
> 
> See, that's another case why we have to explicitly list the protocols.
> Just consider a stupid invocation of iptables:
> 
> 	-m conntrack --ctorigport 0
> 
> I'd rather not let that match IPv4-in-IPv4 or so.

I prefer that to listing all the protocols explicitly. I guess
you would not object if it was named "--ctorigprotokey", but 
--ctorigport is clearer for most protocols.

>>> The protocol check is important though, because IPPROTO_GRE is
>>> _not_ included, since, it's not something that has a port.
>> It has the keys, which are also just a numerical value. Don't
>> think of it as ports but as "layer 4 protocol keys".
>>
> But do these keys actually get modified in NAT?

If the protocol is known to NAT and it clashes then yes.


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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-20 13:00                 ` Patrick McHardy
  2008-01-20 13:12                   ` Jan Engelhardt
@ 2008-01-21  1:14                   ` Pablo Neira Ayuso
  2008-01-21  1:15                     ` Jan Engelhardt
  2008-01-21  1:19                     ` Patrick McHardy
  1 sibling, 2 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2008-01-21  1:14 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Patrick McHardy, Netfilter Developer Mailing List

Patrick McHardy wrote:
> Jan Engelhardt wrote:
>> On Jan 17 2008 14:52, Pablo Neira Ayuso wrote:
>>> Jan Engelhardt wrote:
>>>> +    switch (tuple->dst.protonum) {
>>>> +    case IPPROTO_TCP:
>>>> +    case IPPROTO_UDP:
>>>> +    case IPPROTO_SCTP:
>>> Minor nitpick. Add IPPROTO_UDPLITE.
>>
>> Yeah that can be easily added.

BTW, it would be great if we add support for layer 4 protocol state
matching, e.g. match TCP established. We can use this together with the
target that would mark certain events as volatile, e.g.

iptables -A 192.168.0.0/24 -m conntrack ! --tcp-state ESTABLISHED -j
VOLATILE

The idea behind this it that ctnetlink would ignore certain events,
thus, reducing CPU load.

-- 
"Los honestos son inadaptados sociales" -- Les Luthiers

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-21  1:14                   ` Pablo Neira Ayuso
@ 2008-01-21  1:15                     ` Jan Engelhardt
  2008-01-21  1:18                       ` Pablo Neira Ayuso
  2008-01-21  1:19                     ` Patrick McHardy
  1 sibling, 1 reply; 17+ messages in thread
From: Jan Engelhardt @ 2008-01-21  1:15 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Patrick McHardy, Netfilter Developer Mailing List


On Jan 21 2008 02:14, Pablo Neira Ayuso wrote:
>
>BTW, it would be great if we add support for layer 4 protocol state
>matching, e.g. match TCP established. We can use this together with the
>target that would mark certain events as volatile, e.g.
>
>iptables -A 192.168.0.0/24 -m conntrack ! --tcp-state ESTABLISHED -j
>VOLATILE

And what's xt_VOLATILE do? (Was it hidden in your recent
xt_CONNTRACK submission?)

>The idea behind this it that ctnetlink would ignore certain events,
>thus, reducing CPU load.

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-21  1:15                     ` Jan Engelhardt
@ 2008-01-21  1:18                       ` Pablo Neira Ayuso
  2008-01-21  1:31                         ` Jan Engelhardt
  0 siblings, 1 reply; 17+ messages in thread
From: Pablo Neira Ayuso @ 2008-01-21  1:18 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Patrick McHardy, Netfilter Developer Mailing List

Jan Engelhardt wrote:
> On Jan 21 2008 02:14, Pablo Neira Ayuso wrote:
>> BTW, it would be great if we add support for layer 4 protocol state
>> matching, e.g. match TCP established. We can use this together with the
>> target that would mark certain events as volatile, e.g.
>>
>> iptables -A 192.168.0.0/24 -m conntrack ! --tcp-state ESTABLISHED -j
>> VOLATILE
> 
> And what's xt_VOLATILE do? (Was it hidden in your recent
> xt_CONNTRACK submission?)

Indeed. Just set the IPCT_VOLATILE flag to tell ctnetlink to skip that
event. It would be a very simple target. I don't know if VOLATILE would
be a nice name, perhaps CTNETLINK.

-- 
"Los honestos son inadaptados sociales" -- Les Luthiers

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-21  1:14                   ` Pablo Neira Ayuso
  2008-01-21  1:15                     ` Jan Engelhardt
@ 2008-01-21  1:19                     ` Patrick McHardy
  1 sibling, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-21  1:19 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Jan Engelhardt, Netfilter Developer Mailing List

Pablo Neira Ayuso wrote:
> Patrick McHardy wrote:
>> Jan Engelhardt wrote:
>>> On Jan 17 2008 14:52, Pablo Neira Ayuso wrote:
>>>> Jan Engelhardt wrote:
>>>>> +    switch (tuple->dst.protonum) {
>>>>> +    case IPPROTO_TCP:
>>>>> +    case IPPROTO_UDP:
>>>>> +    case IPPROTO_SCTP:
>>>> Minor nitpick. Add IPPROTO_UDPLITE.
>>> Yeah that can be easily added.
> 
> BTW, it would be great if we add support for layer 4 protocol state
> matching, e.g. match TCP established. We can use this together with the
> target that would mark certain events as volatile, e.g.
> 
> iptables -A 192.168.0.0/24 -m conntrack ! --tcp-state ESTABLISHED -j
> VOLATILE
> 
> The idea behind this it that ctnetlink would ignore certain events,
> thus, reducing CPU load.


I guess the main question is how to do this properly without running
into compatiblity problems at the next opportunity with our crappy
userspace interface. Can we trust that a u8 is enough for all relevant
states for the forseeable future? For the purpose of avoiding
uninteresting state messages it seems like good enough ...


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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-21  1:18                       ` Pablo Neira Ayuso
@ 2008-01-21  1:31                         ` Jan Engelhardt
  0 siblings, 0 replies; 17+ messages in thread
From: Jan Engelhardt @ 2008-01-21  1:31 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Patrick McHardy, Netfilter Developer Mailing List


On Jan 21 2008 02:18, Pablo Neira Ayuso wrote:
>> 
>> And what's xt_VOLATILE do? (Was it hidden in your recent
>> xt_CONNTRACK submission?)
>
>Indeed. Just set the IPCT_VOLATILE flag to tell ctnetlink to skip that
>event. It would be a very simple target. I don't know if VOLATILE would
>be a nice name, perhaps CTNETLINK.

Oh I would not mind names all that much.
At the basic level, there is ACCEPT DROP and REJECT.
Then, in the depths of POM-nation there is TARPIT and TEE, (I'm missing COFFEE).
Elsewhere, I wrote CHAOS and DELUDE.
Most recently, I sampled up STEAL.
You see, VOLATILE is not so off after all. :-)

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

* [NETFILTER]: xt_conntrack: add port and direction matching
@ 2008-01-24 22:38 Jan Engelhardt
  2008-01-24 22:38 ` [IPTABLES]: libxt_conntrack revision 1 Jan Engelhardt
  2008-01-29 13:08 ` [NETFILTER]: xt_conntrack: add port and direction matching Patrick McHardy
  0 siblings, 2 replies; 17+ messages in thread
From: Jan Engelhardt @ 2008-01-24 22:38 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List

commit 7f1764fa749032eb8566226bbd1c5a58a8a5efc6
Author: Jan Engelhardt <jengelh@computergmbh.de>
Date:   Wed Jan 16 18:58:49 2008 +0100

    [NETFILTER]: xt_conntrack: add port and direction matching
    
    Extend the xt_conntrack match revision 1 by port matching (all four
    {orig,repl}{src,dst}) and by packet direction matching.
    
    Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>

diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h
index d2492a3..f3fd83e 100644
--- a/include/linux/netfilter/xt_conntrack.h
+++ b/include/linux/netfilter/xt_conntrack.h
@@ -6,9 +6,6 @@
 #define _XT_CONNTRACK_H
 
 #include <linux/netfilter/nf_conntrack_tuple_common.h>
-#ifdef __KERNEL__
-#	include <linux/in.h>
-#endif
 
 #define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
 #define XT_CONNTRACK_STATE_INVALID (1 << 0)
@@ -18,14 +15,21 @@
 #define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
 
 /* flags, invflags: */
-#define XT_CONNTRACK_STATE	0x01
-#define XT_CONNTRACK_PROTO	0x02
-#define XT_CONNTRACK_ORIGSRC	0x04
-#define XT_CONNTRACK_ORIGDST	0x08
-#define XT_CONNTRACK_REPLSRC	0x10
-#define XT_CONNTRACK_REPLDST	0x20
-#define XT_CONNTRACK_STATUS	0x40
-#define XT_CONNTRACK_EXPIRES	0x80
+enum {
+	XT_CONNTRACK_STATE        = 1 << 0,
+	XT_CONNTRACK_PROTO        = 1 << 1,
+	XT_CONNTRACK_ORIGSRC      = 1 << 2,
+	XT_CONNTRACK_ORIGDST      = 1 << 3,
+	XT_CONNTRACK_REPLSRC      = 1 << 4,
+	XT_CONNTRACK_REPLDST      = 1 << 5,
+	XT_CONNTRACK_STATUS       = 1 << 6,
+	XT_CONNTRACK_EXPIRES      = 1 << 7,
+	XT_CONNTRACK_ORIGSRC_PORT = 1 << 8,
+	XT_CONNTRACK_ORIGDST_PORT = 1 << 9,
+	XT_CONNTRACK_REPLSRC_PORT = 1 << 10,
+	XT_CONNTRACK_REPLDST_PORT = 1 << 11,
+	XT_CONNTRACK_DIRECTION    = 1 << 12,
+};
 
 /* This is exposed to userspace, so remains frozen in time. */
 struct ip_conntrack_old_tuple
@@ -70,8 +74,10 @@ struct xt_conntrack_mtinfo1 {
 	union nf_inet_addr repldst_addr, repldst_mask;
 	u_int32_t expires_min, expires_max;
 	u_int16_t l4proto;
+	__be16 origsrc_port, origdst_port;
+	__be16 replsrc_port, repldst_port;
+	u_int16_t match_flags, invert_flags;
 	u_int8_t state_mask, status_mask;
-	u_int8_t match_flags, invert_flags;
 };
 
 #endif /*_XT_CONNTRACK_H*/
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index e92190e..8533085 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -4,7 +4,6 @@
  *
  *	(C) 2001  Marc Boucher (marc@mbsi.ca).
  *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
- *	Jan Engelhardt <jengelh@computergmbh.de>
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License version 2 as
@@ -20,6 +19,7 @@
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
+MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
 MODULE_DESCRIPTION("Xtables: connection tracking state match");
 MODULE_ALIAS("ipt_conntrack");
 MODULE_ALIAS("ip6t_conntrack");
@@ -166,6 +166,44 @@ conntrack_mt_repldst(const struct nf_conn *ct,
 	       &info->repldst_addr, &info->repldst_mask, family);
 }
 
+static inline bool
+ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
+                    const struct nf_conn *ct)
+{
+	const struct nf_conntrack_tuple *tuple;
+
+	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+	if ((info->match_flags & XT_CONNTRACK_PROTO) &&
+	    (tuple->dst.protonum == info->l4proto) ^
+	    !(info->invert_flags & XT_CONNTRACK_PROTO))
+		return false;
+
+	/* Shortcut to match all recognized protocols by using ->src.all. */
+	if ((info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) &&
+	    (tuple->src.u.all == info->origsrc_port) ^
+	    !(info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT))
+		return false;
+
+	if ((info->match_flags & XT_CONNTRACK_ORIGDST_PORT) &&
+	    (tuple->dst.u.all == info->origdst_port) ^
+	    !(info->invert_flags & XT_CONNTRACK_ORIGDST_PORT))
+		return false;
+
+	tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+
+	if ((info->match_flags & XT_CONNTRACK_REPLSRC_PORT) &&
+	    (tuple->src.u.all == info->replsrc_port) ^
+	    !(info->invert_flags & XT_CONNTRACK_REPLSRC_PORT))
+		return false;
+
+	if ((info->match_flags & XT_CONNTRACK_REPLDST_PORT) &&
+	    (tuple->dst.u.all == info->repldst_port) ^
+	    !(info->invert_flags & XT_CONNTRACK_REPLDST_PORT))
+		return false;
+
+	return true;
+}
+
 static bool
 conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
              const struct net_device *out, const struct xt_match *match,
@@ -200,10 +238,9 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
 
 	if (ct == NULL)
 		return info->match_flags & XT_CONNTRACK_STATE;
-
-	if ((info->match_flags & XT_CONNTRACK_PROTO) &&
-	    ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
-	    info->l4proto) ^ !(info->invert_flags & XT_CONNTRACK_PROTO)))
+	if ((info->match_flags & XT_CONNTRACK_DIRECTION) &&
+	    (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) ^
+	    !!(info->invert_flags & XT_CONNTRACK_DIRECTION))
 		return false;
 
 	if (info->match_flags & XT_CONNTRACK_ORIGSRC)
@@ -226,6 +263,9 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
 		    !(info->invert_flags & XT_CONNTRACK_REPLDST))
 			return false;
 
+	if (!ct_proto_port_check(info, ct))
+		return false;
+
 	if ((info->match_flags & XT_CONNTRACK_STATUS) &&
 	    (!!(info->status_mask & ct->status) ^
 	    !(info->invert_flags & XT_CONNTRACK_STATUS)))

-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [IPTABLES]: libxt_conntrack revision 1
  2008-01-24 22:38 [NETFILTER]: xt_conntrack: add port and direction matching Jan Engelhardt
@ 2008-01-24 22:38 ` Jan Engelhardt
  2008-01-29 13:20   ` Patrick McHardy
  2008-01-29 13:08 ` [NETFILTER]: xt_conntrack: add port and direction matching Patrick McHardy
  1 sibling, 1 reply; 17+ messages in thread
From: Jan Engelhardt @ 2008-01-24 22:38 UTC (permalink / raw)
  To: kaber; +Cc: Netfilter Developer Mailing List

Add support for xt_conntrack match revision 1.

Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>

---
 extensions/libxt_conntrack.c   |  575 ++++++++++++++++++++++++++++++++++++++++-
 extensions/libxt_conntrack.man |   18 -
 2 files changed, 576 insertions(+), 17 deletions(-)

Index: iptables/extensions/libxt_conntrack.c
===================================================================
--- iptables.orig/extensions/libxt_conntrack.c
+++ iptables/extensions/libxt_conntrack.c
@@ -1,10 +1,17 @@
-/* Shared library add-on to iptables for conntrack matching support.
- * GPL (C) 2001  Marc Boucher (marc@mbsi.ca).
+/*
+ *	libxt_conntrack
+ *	Shared library add-on to iptables for conntrack matching support.
+ *
+ *	GPL (C) 2001  Marc Boucher (marc@mbsi.ca).
+ *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
+ *	Jan Engelhardt <jengelh@computergmbh.de>
  */
-
+#include <sys/socket.h>
+#include <sys/types.h>
 #include <ctype.h>
 #include <getopt.h>
 #include <netdb.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -13,6 +20,7 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter/xt_conntrack.h>
 #include <linux/netfilter/nf_conntrack_common.h>
+#include <arpa/inet.h>
 
 /* Function which prints out usage message. */
 static void conntrack_mt_help(void)
@@ -27,14 +35,20 @@ static void conntrack_mt_help(void)
 "[!] --ctreplsrc address[/mask]\n"
 "[!] --ctrepldst address[/mask]\n"
 "                               Original/Reply source/destination address\n"
+"[!] --ctorigsrcport port\n"
+"[!] --ctorigdstport port\n"
+"[!] --ctreplsrcport port\n"
+"[!] --ctrepldstport port\n"
+"                               TCP/UDP/SCTP orig./reply source/destination port\n"
 "[!] --ctstatus {NONE|EXPECTED|SEEN_REPLY|ASSURED|CONFIRMED}[,...]\n"
 "                               Status(es) to match\n"
 "[!] --ctexpire time[:time]     Match remaining lifetime in seconds against\n"
 "                               value or range of values (inclusive)\n"
+"    --ctdir {ORIGINAL|REPLY}   Flow direction of packet\n"
 "\n");
 }
 
-static const struct option conntrack_mt_opts[] = {
+static const struct option conntrack_mt_opts_v0[] = {
 	{.name = "ctstate",   .has_arg = true, .val = '1'},
 	{.name = "ctproto",   .has_arg = true, .val = '2'},
 	{.name = "ctorigsrc", .has_arg = true, .val = '3'},
@@ -46,6 +60,23 @@ static const struct option conntrack_mt_
 	{},
 };
 
+static const struct option conntrack_mt_opts[] = {
+	{.name = "ctstate",       .has_arg = true, .val = '1'},
+	{.name = "ctproto",       .has_arg = true, .val = '2'},
+	{.name = "ctorigsrc",     .has_arg = true, .val = '3'},
+	{.name = "ctorigdst",     .has_arg = true, .val = '4'},
+	{.name = "ctreplsrc",     .has_arg = true, .val = '5'},
+	{.name = "ctrepldst",     .has_arg = true, .val = '6'},
+	{.name = "ctstatus",      .has_arg = true, .val = '7'},
+	{.name = "ctexpire",      .has_arg = true, .val = '8'},
+	{.name = "ctorigsrcport", .has_arg = true, .val = 'a'},
+	{.name = "ctorigdstport", .has_arg = true, .val = 'b'},
+	{.name = "ctreplsrcport", .has_arg = true, .val = 'c'},
+	{.name = "ctrepldstport", .has_arg = true, .val = 'd'},
+	{.name = "ctdir",         .has_arg = true, .val = 'e'},
+	{},
+};
+
 static int
 parse_state(const char *state, size_t strlen, struct xt_conntrack_info *sinfo)
 {
@@ -83,6 +114,45 @@ parse_states(const char *arg, struct xt_
 		exit_error(PARAMETER_PROBLEM, "Bad ctstate `%s'", arg);
 }
 
+static bool
+conntrack_ps_state(struct xt_conntrack_mtinfo1 *info, const char *state,
+                   size_t z)
+{
+	if (strncasecmp(state, "INVALID", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_INVALID;
+	else if (strncasecmp(state, "NEW", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
+	else if (strncasecmp(state, "ESTABLISHED", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
+	else if (strncasecmp(state, "RELATED", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
+	else if (strncasecmp(state, "UNTRACKED", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_UNTRACKED;
+	else if (strncasecmp(state, "SNAT", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_SNAT;
+	else if (strncasecmp(state, "DNAT", z) == 0)
+		info->state_mask |= XT_CONNTRACK_STATE_DNAT;
+	else
+		return false;
+	return true;
+}
+
+static void
+conntrack_ps_states(struct xt_conntrack_mtinfo1 *info, const char *arg)
+{
+	const char *comma;
+
+	while ((comma = strchr(arg, ',')) != NULL) {
+		if (comma == arg || !conntrack_ps_state(info, arg, comma - arg))
+			exit_error(PARAMETER_PROBLEM,
+			           "Bad ctstate \"%s\"", arg);
+		arg = comma + 1;
+	}
+
+	if (strlen(arg) == 0 || !conntrack_ps_state(info, arg, strlen(arg)))
+		exit_error(PARAMETER_PROBLEM, "Bad ctstate \"%s\"", arg);
+}
+
 static int
 parse_status(const char *status, size_t strlen, struct xt_conntrack_info *sinfo)
 {
@@ -96,7 +166,7 @@ parse_status(const char *status, size_t 
 		sinfo->statusmask |= IPS_ASSURED;
 #ifdef IPS_CONFIRMED
 	else if (strncasecmp(status, "CONFIRMED", strlen) == 0)
-		sinfo->stausmask |= IPS_CONFIRMED;
+		sinfo->statusmask |= IPS_CONFIRMED;
 #endif
 	else
 		return 0;
@@ -118,6 +188,41 @@ parse_statuses(const char *arg, struct x
 		exit_error(PARAMETER_PROBLEM, "Bad ctstatus `%s'", arg);
 }
 
+static bool
+conntrack_ps_status(struct xt_conntrack_mtinfo1 *info, const char *status,
+                    size_t z)
+{
+	if (strncasecmp(status, "NONE", z) == 0)
+		info->status_mask |= 0;
+	else if (strncasecmp(status, "EXPECTED", z) == 0)
+		info->status_mask |= IPS_EXPECTED;
+	else if (strncasecmp(status, "SEEN_REPLY", z) == 0)
+		info->status_mask |= IPS_SEEN_REPLY;
+	else if (strncasecmp(status, "ASSURED", z) == 0)
+		info->status_mask |= IPS_ASSURED;
+	else if (strncasecmp(status, "CONFIRMED", z) == 0)
+		info->status_mask |= IPS_CONFIRMED;
+	else
+		return false;
+	return true;
+}
+
+static void
+conntrack_ps_statuses(struct xt_conntrack_mtinfo1 *info, const char *arg)
+{
+	const char *comma;
+
+	while ((comma = strchr(arg, ',')) != NULL) {
+		if (comma == arg || !conntrack_ps_status(info, arg, comma - arg))
+			exit_error(PARAMETER_PROBLEM,
+			           "Bad ctstatus \"%s\"", arg);
+		arg = comma + 1;
+	}
+
+	if (strlen(arg) == 0 || !conntrack_ps_status(info, arg, strlen(arg)))
+		exit_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
+}
+
 static unsigned long
 parse_expire(const char *s)
 {
@@ -138,7 +243,8 @@ parse_expires(const char *s, struct xt_c
 
 	buffer = strdup(s);
 	if ((cp = strchr(buffer, ':')) == NULL)
-		sinfo->expires_min = sinfo->expires_max = parse_expire(buffer);
+		sinfo->expires_min = sinfo->expires_max =
+			parse_expire(buffer);
 	else {
 		*cp = '\0';
 		cp++;
@@ -154,6 +260,30 @@ parse_expires(const char *s, struct xt_c
 		           "range value `%lu'", sinfo->expires_min, sinfo->expires_max);
 }
 
+static void
+conntrack_ps_expires(struct xt_conntrack_mtinfo1 *info, const char *s)
+{
+	unsigned int min, max;
+	char *end;
+
+	if (!strtonum(s, &end, &min, 0, ~0))
+		param_act(P_BAD_VALUE, "conntrack", "--expires", s);
+	max = min;
+	if (*end == ':')
+		if (!strtonum(s, &end, &max, 0, ~0U))
+			param_act(P_BAD_VALUE, "conntrack", "--expires", s);
+	if (*end != '\0')
+		param_act(P_BAD_VALUE, "conntrack", "--expires", s);
+
+	if (min > max)
+		exit_error(PARAMETER_PROBLEM,
+		           "expire min. range value \"%u\" greater than max. "
+		           "range value \"%u\"", min, max);
+
+	info->expires_min = min;
+	info->expires_max = max;
+}
+
 /* Function which parses command options; returns true if it
    ate an option */
 static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags,
@@ -305,10 +435,257 @@ static int conntrack_parse(int c, char *
 	return 1;
 }
 
+static int
+conntrack_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+                   struct xt_entry_match **match)
+{
+	struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
+	unsigned int port;
+	char *p;
+
+	switch (c) {
+	case '1': /* --ctstate */
+		conntrack_ps_states(info, optarg);
+		info->match_flags |= XT_CONNTRACK_STATE;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_STATE;
+		break;
+
+	case '2': /* --ctproto */
+		/* Canonicalize into lower case */
+		for (p = optarg; *p != '\0'; ++p)
+			*p = tolower(*p);
+		info->l4proto = parse_protocol(optarg);
+
+		if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO))
+			exit_error(PARAMETER_PROBLEM, "conntrack: rule would "
+			           "never match protocol");
+
+		info->match_flags |= XT_CONNTRACK_PROTO;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_PROTO;
+		break;
+
+	case '7': /* --ctstatus */
+		conntrack_ps_statuses(info, optarg);
+		info->match_flags |= XT_CONNTRACK_STATUS;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_STATUS;
+		break;
+
+	case '8': /* --ctexpire */
+		conntrack_ps_expires(info, optarg);
+		info->match_flags |= XT_CONNTRACK_EXPIRES;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_EXPIRES;
+		break;
+
+	case 'a': /* --ctorigsrcport */
+		if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
+			param_act(P_BAD_VALUE, "conntrack",
+			          "--ctorigsrcport", optarg);
+		info->match_flags |= XT_CONNTRACK_ORIGSRC_PORT;
+		info->origsrc_port = htons(port);
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGSRC_PORT;
+		break;
+
+	case 'b': /* --ctorigdstport */
+		if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
+			param_act(P_BAD_VALUE, "conntrack",
+			          "--ctorigdstport", optarg);
+		info->match_flags |= XT_CONNTRACK_ORIGDST_PORT;
+		info->origdst_port = htons(port);
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGDST_PORT;
+		break;
+
+	case 'c': /* --ctreplsrcport */
+		if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
+			param_act(P_BAD_VALUE, "conntrack",
+			          "--ctreplsrcport", optarg);
+		info->match_flags |= XT_CONNTRACK_REPLSRC_PORT;
+		info->replsrc_port = htons(port);
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLSRC_PORT;
+		break;
+
+	case 'd': /* --ctrepldstport */
+		if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
+			param_act(P_BAD_VALUE, "conntrack",
+			          "--ctrepldstport", optarg);
+		info->match_flags |= XT_CONNTRACK_REPLDST_PORT;
+		info->repldst_port = htons(port);
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLDST_PORT;
+		break;
+
+	case 'e': /* --ctdir */
+		param_act(P_NO_INVERT, "conntrack", "--ctdir", invert);
+		if (strcasecmp(optarg, "ORIGINAL") == 0) {
+			info->match_flags  |= XT_CONNTRACK_DIRECTION;
+			info->invert_flags &= ~XT_CONNTRACK_DIRECTION;
+		} else if (strcasecmp(optarg, "REPLY") == 0) {
+			info->match_flags  |= XT_CONNTRACK_DIRECTION;
+			info->invert_flags |= XT_CONNTRACK_DIRECTION;
+		} else {
+			param_act(P_BAD_VALUE, "conntrack", "--ctdir", optarg);
+		}
+		break;
+
+	default:
+		return false;
+	}
+
+	*flags = info->match_flags;
+	return true;
+}
+
+static int
+conntrack_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
+                    const void *entry, struct xt_entry_match **match)
+{
+	struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
+	struct in_addr *addr = NULL;
+	unsigned int naddrs = 0;
+
+	switch (c) {
+	case '3': /* --ctorigsrc */
+		ipparse_hostnetworkmask(optarg, &addr, &info->origsrc_mask.in,
+		                        &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->origsrc_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_ORIGSRC;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGSRC;
+		break;
+
+	case '4': /* --ctorigdst */
+		ipparse_hostnetworkmask(optarg, &addr, &info->origdst_mask.in,
+		                        &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_ORIGDST;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGDST;
+		break;
+
+	case '5': /* --ctreplsrc */
+		ipparse_hostnetworkmask(optarg, &addr, &info->replsrc_mask.in,
+		                        &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_REPLSRC;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLSRC;
+		break;
+
+	case '6': /* --ctrepldst */
+		ipparse_hostnetworkmask(optarg, &addr, &info->repldst_mask.in,
+		                        &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_REPLDST;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLDST;
+		break;
+
+
+	default:
+		return conntrack_mt_parse(c, argv, invert, flags, match);
+	}
+
+	*flags = info->match_flags;
+	return true;
+}
+
+static int
+conntrack_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
+                    const void *entry, struct xt_entry_match **match)
+{
+	struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
+	struct in6_addr *addr = NULL;
+	unsigned int naddrs = 0;
+
+	switch (c) {
+	case '3': /* --ctorigsrc */
+		ip6parse_hostnetworkmask(optarg, &addr,
+		                         &info->origsrc_mask.in6, &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->origsrc_addr.in6, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_ORIGSRC;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGSRC;
+		break;
+
+	case '4': /* --ctorigdst */
+		ip6parse_hostnetworkmask(optarg, &addr,
+		                         &info->origdst_mask.in6, &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_ORIGDST;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGDST;
+		break;
+
+	case '5': /* --ctreplsrc */
+		ip6parse_hostnetworkmask(optarg, &addr,
+		                         &info->replsrc_mask.in6, &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_REPLSRC;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLSRC;
+		break;
+
+	case '6': /* --ctrepldst */
+		ip6parse_hostnetworkmask(optarg, &addr,
+		                         &info->repldst_mask.in6, &naddrs);
+		if (naddrs > 1)
+			exit_error(PARAMETER_PROBLEM,
+			           "multiple IP addresses not allowed");
+		if (naddrs == 1)
+			memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
+		info->match_flags |= XT_CONNTRACK_REPLDST;
+		if (invert)
+			info->invert_flags |= XT_CONNTRACK_REPLDST;
+		break;
+
+
+	default:
+		return conntrack_mt_parse(c, argv, invert, flags, match);
+	}
+
+	*flags = info->match_flags;
+	return true;
+}
+
 static void conntrack_mt_check(unsigned int flags)
 {
 	if (flags == 0)
-		exit_error(PARAMETER_PROBLEM, "You must specify one or more options");
+		exit_error(PARAMETER_PROBLEM, "conntrack: At least one option "
+		           "is required");
 }
 
 static void
@@ -364,20 +741,37 @@ print_status(unsigned int statusmask)
 		printf("%sASSURED", sep);
 		sep = ",";
 	}
-#ifdef IPS_CONFIRMED
 	if (statusmask & IPS_CONFIRMED) {
 		printf("%sCONFIRMED", sep);
-		sep =",";
-	}
-#endif
-	if (statusmask == 0) {
-		printf("%sNONE", sep);
 		sep = ",";
 	}
+	if (statusmask == 0)
+		printf("%sNONE", sep);
 	printf(" ");
 }
 
 static void
+conntrack_dump_addr(const union nf_inet_addr *addr,
+                    const union nf_inet_addr *mask,
+                    unsigned int family, bool numeric)
+{
+	if (family == AF_INET) {
+		if (!numeric && addr->ip == 0) {
+			printf("anywhere ");
+			return;
+		}
+		printf("%s ", ipaddr_to_anyname(&addr->in));
+	} else if (family == AF_INET6) {
+		if (!numeric && addr->ip6[0] == 0 && addr->ip6[1] == 0 &&
+		    addr->ip6[2] == 0 && addr->ip6[3] == 0) {
+			printf("anywhere ");
+			return;
+		}
+		printf("%s ", ip6addr_to_anyname(&addr->in6));
+	}
+}
+
+static void
 print_addr(struct in_addr *addr, struct in_addr *mask, int inv, int numeric)
 {
 	char buf[BUFSIZ];
@@ -484,6 +878,103 @@ matchinfo_print(const void *ip, const st
 	}
 }
 
+static void
+conntrack_dump(const struct xt_conntrack_mtinfo1 *info, const char *prefix,
+               unsigned int family, bool numeric)
+{
+	if (info->match_flags & XT_CONNTRACK_STATE) {
+		if (info->invert_flags & XT_CONNTRACK_STATE)
+			printf("! ");
+		printf("%sctstate ", prefix);
+		print_state(info->state_mask);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_PROTO) {
+		if (info->invert_flags & XT_CONNTRACK_PROTO)
+			printf("! ");
+		printf("%sctproto %u ", prefix, info->l4proto);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_ORIGSRC) {
+		if (info->invert_flags & XT_CONNTRACK_PROTO)
+			printf("! ");
+		printf("%sctorigsrc ", prefix);
+		conntrack_dump_addr(&info->origsrc_addr, &info->origsrc_mask,
+		                    family, numeric);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_ORIGDST) {
+		if (info->invert_flags & XT_CONNTRACK_PROTO)
+			printf("! ");
+		printf("%sctorigdst ", prefix);
+		conntrack_dump_addr(&info->origdst_addr, &info->origdst_mask,
+		                    family, numeric);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_REPLSRC) {
+		if (info->invert_flags & XT_CONNTRACK_PROTO)
+			printf("! ");
+		printf("%sctreplsrc ", prefix);
+		conntrack_dump_addr(&info->replsrc_addr, &info->replsrc_mask,
+		                    family, numeric);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_REPLDST) {
+		if (info->invert_flags & XT_CONNTRACK_PROTO)
+			printf("! ");
+		printf("%sctrepldst ", prefix);
+		conntrack_dump_addr(&info->repldst_addr, &info->repldst_mask,
+		                    family, numeric);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) {
+		if (info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT)
+			printf("! ");
+		printf("%sctorigsrcport %u ", prefix,
+		       ntohs(info->origsrc_port));
+	}
+
+	if (info->match_flags & XT_CONNTRACK_ORIGDST_PORT) {
+		if (info->invert_flags & XT_CONNTRACK_ORIGDST_PORT)
+			printf("! ");
+		printf("%sctorigdstport %u ", prefix,
+		       ntohs(info->origdst_port));
+	}
+
+	if (info->match_flags & XT_CONNTRACK_REPLSRC_PORT) {
+		if (info->invert_flags & XT_CONNTRACK_REPLSRC_PORT)
+			printf("! ");
+		printf("%sctreplsrcport %u ", prefix,
+		       ntohs(info->replsrc_port));
+	}
+
+	if (info->match_flags & XT_CONNTRACK_REPLDST_PORT) {
+		if (info->invert_flags & XT_CONNTRACK_REPLDST_PORT)
+			printf("! ");
+		printf("%sctrepldstport %u ", prefix,
+		       ntohs(info->repldst_port));
+	}
+
+	if (info->match_flags & XT_CONNTRACK_STATUS) {
+		if (info->invert_flags & XT_CONNTRACK_STATUS)
+			printf("! ");
+		printf("%sctstatus ", prefix);
+		print_status(info->status_mask);
+	}
+
+	if (info->match_flags & XT_CONNTRACK_EXPIRES) {
+		if (info->invert_flags & XT_CONNTRACK_EXPIRES)
+			printf("! ");
+		printf("%sctexpire ", prefix);
+
+		if (info->expires_max == info->expires_min)
+			printf("%u ", (unsigned int)info->expires_min);
+		else
+			printf("%u:%u ", (unsigned int)info->expires_min,
+			       (unsigned int)info->expires_max);
+	}
+}
+
 /* Prints out the matchinfo. */
 static void conntrack_print(const void *ip, const struct xt_entry_match *match,
                             int numeric)
@@ -491,12 +982,38 @@ static void conntrack_print(const void *
 	matchinfo_print(ip, match, numeric, "");
 }
 
+static void
+conntrack_mt_print(const void *ip, const struct xt_entry_match *match,
+                   int numeric)
+{
+	conntrack_dump((const void *)match->data, "", AF_INET, numeric);
+}
+
+static void
+conntrack_mt6_print(const void *ip, const struct xt_entry_match *match,
+                    int numeric)
+{
+	conntrack_dump((const void *)match->data, "", AF_INET6, numeric);
+}
+
 /* Saves the matchinfo in parsable form to stdout. */
 static void conntrack_save(const void *ip, const struct xt_entry_match *match)
 {
 	matchinfo_print(ip, match, 1, "--");
 }
 
+static void conntrack_mt_save(const void *ip,
+                              const struct xt_entry_match *match)
+{
+	conntrack_dump((const void *)match->data, "--", AF_INET, true);
+}
+
+static void conntrack_mt6_save(const void *ip,
+                               const struct xt_entry_match *match)
+{
+	conntrack_dump((const void *)match->data, "--", AF_INET6, true);
+}
+
 static struct xtables_match conntrack_match = {
 	.version       = IPTABLES_VERSION,
 	.name          = "conntrack",
@@ -509,10 +1026,42 @@ static struct xtables_match conntrack_ma
 	.final_check   = conntrack_mt_check,
 	.print         = conntrack_print,
 	.save          = conntrack_save,
+	.extra_opts    = conntrack_mt_opts_v0,
+};
+
+static struct xtables_match conntrack_mt_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "conntrack",
+	.revision      = 1,
+	.family        = AF_INET,
+	.size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+	.help          = conntrack_mt_help,
+	.parse         = conntrack_mt4_parse,
+	.final_check   = conntrack_mt_check,
+	.print         = conntrack_mt_print,
+	.save          = conntrack_mt_save,
+	.extra_opts    = conntrack_mt_opts,
+};
+
+static struct xtables_match conntrack_mt6_reg = {
+	.version       = IPTABLES_VERSION,
+	.name          = "conntrack",
+	.revision      = 1,
+	.family        = AF_INET6,
+	.size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+	.help          = conntrack_mt_help,
+	.parse         = conntrack_mt6_parse,
+	.final_check   = conntrack_mt_check,
+	.print         = conntrack_mt6_print,
+	.save          = conntrack_mt6_save,
 	.extra_opts    = conntrack_mt_opts,
 };
 
 void _init(void)
 {
 	xtables_register_match(&conntrack_match);
+	xtables_register_match(&conntrack_mt_reg);
+	xtables_register_match(&conntrack_mt6_reg);
 }
Index: iptables/extensions/libxt_conntrack.man
===================================================================
--- iptables.orig/extensions/libxt_conntrack.man
+++ iptables/extensions/libxt_conntrack.man
@@ -9,16 +9,22 @@ Possible states are listed below.
 Layer-4 protocol to match (by number or name)
 .TP
 [\fB!\fR] \fB--ctorigsrc\fR \fIaddress\fR[\fB/\fR\fImask\fR]
-Match against original source address
 .TP
 [\fB!\fR] \fB--ctorigdst\fR \fIaddress\fR[\fB/\fR\fImask\fR]
-Match against original destination address
 .TP
 [\fB!\fR] \fB--ctreplsrc\fR \fIaddress\fR[\fB/\fR\fImask\fR]
-Match against reply source address
 .TP
 [\fB!\fR] \fB--ctrepldst\fR \fIaddress\fR[\fB/\fR\fImask\fR]
-Match against reply destination address
+Match against original/reply source/destination address
+.TP
+[\fB!\fR] \fB--ctorigsrcport\fR \fIport\fR
+.TP
+[\fB!\fR] \fB--ctorigdstport\fR \fIport\fR
+.TP
+[\fB!\fR] \fB--ctreplsrcport\fR \fIport\fR
+.TP
+[\fB!\fR] \fB--ctrepldstport\fR \fIport\fR
+Match against original/reply source/destination port (TCP/UDP/etc.) or GRE key.
 .TP
 [\fB!\fR] \fB--ctstatus\fR \fIstatelist\fR
 \fIstatuslist\fR is a comma separated list of the connection statuses to match.
@@ -27,6 +33,10 @@ Possible statuses are listed below.
 [\fB!\fR] \fB--ctexpire\fR \fItime\fR[\fB:\fR\fItime\fR]
 Match remaining lifetime in seconds against given value or range of values
 (inclusive)
+.TP
+\fB--ctdir\fR {\fBORIGINAL\fR|\fBREPLY\fR}
+Match packets that are flowing in the specified direction. If this flag is not
+specified at all, matches packets in both directions.
 .PP
 States for \fB--ctstate\fR:
 .TP
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [NETFILTER]: xt_conntrack: add port and direction matching
  2008-01-24 22:38 [NETFILTER]: xt_conntrack: add port and direction matching Jan Engelhardt
  2008-01-24 22:38 ` [IPTABLES]: libxt_conntrack revision 1 Jan Engelhardt
@ 2008-01-29 13:08 ` Patrick McHardy
  1 sibling, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-29 13:08 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List

Jan Engelhardt wrote:
> commit 7f1764fa749032eb8566226bbd1c5a58a8a5efc6
> Author: Jan Engelhardt <jengelh@computergmbh.de>
> Date:   Wed Jan 16 18:58:49 2008 +0100
> 
>     [NETFILTER]: xt_conntrack: add port and direction matching
>     
>     Extend the xt_conntrack match revision 1 by port matching (all four
>     {orig,repl}{src,dst}) and by packet direction matching.

Applied, thanks.

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

* Re: [IPTABLES]: libxt_conntrack revision 1
  2008-01-24 22:38 ` [IPTABLES]: libxt_conntrack revision 1 Jan Engelhardt
@ 2008-01-29 13:20   ` Patrick McHardy
  0 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-29 13:20 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List

Jan Engelhardt wrote:
> Add support for xt_conntrack match revision 1.
> 
> Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>


Applied, thanks.

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

end of thread, other threads:[~2008-01-29 13:36 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-24 22:38 [NETFILTER]: xt_conntrack: add port and direction matching Jan Engelhardt
2008-01-24 22:38 ` [IPTABLES]: libxt_conntrack revision 1 Jan Engelhardt
2008-01-29 13:20   ` Patrick McHardy
2008-01-29 13:08 ` [NETFILTER]: xt_conntrack: add port and direction matching Patrick McHardy
  -- strict thread matches above, loose matches on Subject: below --
2008-01-02 20:18 [PATCH 0/27] Netfilter update Jan Engelhardt
2008-01-02 20:28 ` [PATCH 10/27] xt_conntrack match, revision 1 Jan Engelhardt
2008-01-04 14:53   ` Patrick McHardy
2008-01-15  6:48     ` Patrick McHardy
2008-01-15 12:31       ` Jan Engelhardt
2008-01-15 14:13         ` Patrick McHardy
2008-01-16 18:02           ` [NETFILTER]: xt_conntrack: add port and direction matching Jan Engelhardt
2008-01-17 13:52             ` Pablo Neira Ayuso
2008-01-17 15:00               ` Jan Engelhardt
2008-01-20 13:00                 ` Patrick McHardy
2008-01-20 13:12                   ` Jan Engelhardt
2008-01-20 13:15                     ` Patrick McHardy
2008-01-20 16:48                       ` Jan Engelhardt
2008-01-20 16:55                         ` Patrick McHardy
2008-01-21  1:14                   ` Pablo Neira Ayuso
2008-01-21  1:15                     ` Jan Engelhardt
2008-01-21  1:18                       ` Pablo Neira Ayuso
2008-01-21  1:31                         ` Jan Engelhardt
2008-01-21  1:19                     ` Patrick McHardy

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).