* RE: [NEW TARGET] target for modifying conntrack timeout value
@ 2004-12-13 21:10 Richard
2004-12-13 21:14 ` Pablo Neira
2004-12-15 0:25 ` Pablo Neira
0 siblings, 2 replies; 16+ messages in thread
From: Richard @ 2004-12-13 21:10 UTC (permalink / raw)
To: 'Pablo Neira'; +Cc: netfilter-devel
> -----Original Message-----
> From: Richard [mailto:richard@o-matrix.org]
> Sent: Wednesday, December 08, 2004 3:48 PM
> To: 'Pablo Neira'
> Cc: 'netfilter-devel@lists.netfilter.org'
> Subject: RE: [NEW TARGET] target for modifying conntrack timeout value
>
> > + ct->timeout.expires = new_expires;
> > ^^^
> >
> > Hm I thought that I told you to use ip_ct_refresh... you should. Your
> > target will look smarter and you can forget about proper locking...
> > which is now completely broken...
>
> Hi Pablo,
>
> Thanks for the comments. I made the modification and attached the latest
> copy. Now it uses ip_ct_refresh. The target first reads the existing
> expire value, then modify it. If there is something in between, the expire
> value might get changed. Even worse, the conntrack state might change.
> That's why I locked it first, then read and write, finally unlock. If it
> is broken, there is no difference anyway...
>
Just wonder if there is any update on this please...
Thanks,
Richard
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [NEW TARGET] target for modifying conntrack timeout value 2004-12-13 21:10 [NEW TARGET] target for modifying conntrack timeout value Richard @ 2004-12-13 21:14 ` Pablo Neira 2004-12-15 0:25 ` Pablo Neira 1 sibling, 0 replies; 16+ messages in thread From: Pablo Neira @ 2004-12-13 21:14 UTC (permalink / raw) To: Richard; +Cc: Netfilter Development Mailinglist Richard wrote: > > >>-----Original Message----- >>From: Richard [mailto:richard@o-matrix.org] >>Sent: Wednesday, December 08, 2004 3:48 PM >>To: 'Pablo Neira' >>Cc: 'netfilter-devel@lists.netfilter.org' >>Subject: RE: [NEW TARGET] target for modifying conntrack timeout value >> >> >> >>>+ ct->timeout.expires = new_expires; >>> ^^^ >>> >>>Hm I thought that I told you to use ip_ct_refresh... you should. Your >>>target will look smarter and you can forget about proper locking... >>>which is now completely broken... >>> >>> >>Hi Pablo, >> >>Thanks for the comments. I made the modification and attached the latest >>copy. Now it uses ip_ct_refresh. The target first reads the existing >>expire value, then modify it. If there is something in between, the expire >>value might get changed. Even worse, the conntrack state might change. >>That's why I locked it first, then read and write, finally unlock. If it >>is broken, there is no difference anyway... >> >> >> > >Just wonder if there is any update on this please... > > sorry, I'm busy as hell right now. But I'll go through it as soon as I find some spare time. Reviewing your target is still in my todo list. Please, be patient. -- Pablo ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [NEW TARGET] target for modifying conntrack timeout value 2004-12-13 21:10 [NEW TARGET] target for modifying conntrack timeout value Richard 2004-12-13 21:14 ` Pablo Neira @ 2004-12-15 0:25 ` Pablo Neira 2004-12-15 1:16 ` Richard 1 sibling, 1 reply; 16+ messages in thread From: Pablo Neira @ 2004-12-15 0:25 UTC (permalink / raw) To: Richard; +Cc: Netfilter Development Mailinglist Richard wrote: > > >>-----Original Message----- >>From: Richard [mailto:richard@o-matrix.org] >>Sent: Wednesday, December 08, 2004 3:48 PM >>To: 'Pablo Neira' >>Cc: 'netfilter-devel@lists.netfilter.org' >>Subject: RE: [NEW TARGET] target for modifying conntrack timeout value >> >> >> >>>+ ct->timeout.expires = new_expires; >>> ^^^ >>> >>>Hm I thought that I told you to use ip_ct_refresh... you should. Your >>>target will look smarter and you can forget about proper locking... >>>which is now completely broken... >>> >>> >>Hi Pablo, >> >>Thanks for the comments. I made the modification and attached the latest >>copy. Now it uses ip_ct_refresh. The target first reads the existing >>expire value, then modify it. If there is something in between, the expire >>value might get changed. Even worse, the conntrack state might change. >>That's why I locked it first, then read and write, finally unlock. If it >>is broken, there is no difference anyway... >> >> >> > >Just wonder if there is any update on this please... > > Some comments: a) I think that you should implement this thing as a match instead of a target. Have a look at ipt_limit. It isn't actually matching anything but, for example, you could use it together with nat targets. A match gives you more flexibility. b) About source code: + if (!is_confirmed(ct)) { ^^^ remove this `if' condition. ip_ct_refresh worries about about this for you and makes the thing more simple. c) In checkentry: + if (info->mode > IPT_CTEXPIRE_MAXMODE) { + printk(KERN_WARNING "CTEXPIRE: invalid or unknown Mode %u\n", + info->mode); + return 0; + } + [...] + + if (info->expires * HZ < info->expires) { + /* if user specified value is too big, *HZ can overflow the counter + */ + printk(KERN_WARNING "CTEXPIRE: expire value too big, will overflow counter: %ld\n", info->expires); + return 0; + } You should do those checkings in user space. Those error must be handle in iptables, not in kernel. A minor aesthetic comment, a line must fit 80 columns, split longer lines in two. -- Pablo ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [NEW TARGET] target for modifying conntrack timeout value 2004-12-15 0:25 ` Pablo Neira @ 2004-12-15 1:16 ` Richard 2004-12-15 19:38 ` Pablo Neira 0 siblings, 1 reply; 16+ messages in thread From: Richard @ 2004-12-15 1:16 UTC (permalink / raw) To: 'Pablo Neira'; +Cc: 'Netfilter Development Mailinglist' > Some comments: > > a) I think that you should implement this thing as a match instead of a > target. Have a look at ipt_limit. It isn't actually matching anything > but, for example, you could use it together with nat targets. A match > gives you more flexibility. Not sure that I follow you. This target changes the conntrack expire timer. For example, the default timeout for udp stream is 180 seconds. If I want to make it 3600 for sip (udp 5060) traffic, I would do, iptables -t mangle -A INPUT -p UDP --dport 5060 -j CTEXPIRE --ctexpire-set 3600 iptables -t mangle -A OUTPUT -p UDP --sport 5060 -j CTEXPIRE --ctexpire-set 3600 > b) About source code: > > + if (!is_confirmed(ct)) { > ^^^ > remove this `if' condition. ip_ct_refresh worries about about this for > you and makes the thing more simple. In order to increase or decrease the expire value, we need to get the current expire value. If it is !is_confirmed, the ct->timeout value is the real expire value. Otherwise, it is jiffies + expire value. Is there a function to get this value without checking is_confirmed? > c) In checkentry: > > + if (info->mode > IPT_CTEXPIRE_MAXMODE) { > + printk(KERN_WARNING "CTEXPIRE: invalid or unknown Mode > %u\n", > + info->mode); > + return 0; > + } > + [...] > + > + if (info->expires * HZ < info->expires) { > + /* if user specified value is too big, *HZ can overflow > the counter > + */ > + printk(KERN_WARNING "CTEXPIRE: expire value too big, > will overflow counter: %ld\n", info->expires); > + return 0; > + } > > You should do those checkings in user space. Those error must be handle > in iptables, not in kernel. It is already done in user space. It is probably redundant doing the same thing here. I will drop it. > A minor aesthetic comment, a line must fit 80 columns, split longer > lines in two. It will be changed. Thanks for your comments. Looking forward to your next email. Richard ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [NEW TARGET] target for modifying conntrack timeout value 2004-12-15 1:16 ` Richard @ 2004-12-15 19:38 ` Pablo Neira 2004-12-17 18:10 ` Richard 0 siblings, 1 reply; 16+ messages in thread From: Pablo Neira @ 2004-12-15 19:38 UTC (permalink / raw) To: Richard; +Cc: 'Netfilter Development Mailinglist' Richard wrote: >>Some comments: >> >>a) I think that you should implement this thing as a match instead of a >>target. Have a look at ipt_limit. It isn't actually matching anything >>but, for example, you could use it together with nat targets. A match >>gives you more flexibility. >> >> >Not sure that I follow you. This target changes the conntrack expire timer. >For example, the default timeout for udp stream is 180 seconds. If I want to >make it 3600 for sip (udp 5060) traffic, I would do, >iptables -t mangle -A INPUT -p UDP --dport 5060 -j CTEXPIRE --ctexpire-set >3600 >iptables -t mangle -A OUTPUT -p UDP --sport 5060 -j CTEXPIRE --ctexpire-set >3600 > > An example of what I mean: iptables -A OUTPUT -m ctexpire --ctexpire-set 3600 -j ACCEPT BTW, why can you only use this target in mangle? I think that it's safe using it elsewhere, except by the `raw' table where you can not. >>b) About source code: >> >>+ if (!is_confirmed(ct)) { >> ^^^ >>remove this `if' condition. ip_ct_refresh worries about about this for >>you and makes the thing more simple. >> >> >In order to increase or decrease the expire value, we need to get the >current expire value. If it is !is_confirmed, the ct->timeout value is the >real expire value. Otherwise, it is jiffies + expire value. Is there a >function to get this value without checking is_confirmed? > > you are right, you need that for increments and decrements, forget this comment. >>c) In checkentry: >> >>+ if (info->mode > IPT_CTEXPIRE_MAXMODE) { >>+ printk(KERN_WARNING "CTEXPIRE: invalid or unknown Mode >>%u\n", >>+ info->mode); >>+ return 0; >>+ } >>+ [...] >>+ >>+ if (info->expires * HZ < info->expires) { >>+ /* if user specified value is too big, *HZ can overflow >>the counter >>+ */ >>+ printk(KERN_WARNING "CTEXPIRE: expire value too big, >>will overflow counter: %ld\n", info->expires); >>+ return 0; >>+ } >> >>You should do those checkings in user space. Those error must be handle >>in iptables, not in kernel. >> >> >It is already done in user space. It is probably redundant doing the same >thing here. I will drop it. > > yes, it's redudant. Please, drop that. -- Pablo ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [NEW TARGET] target for modifying conntrack timeout value 2004-12-15 19:38 ` Pablo Neira @ 2004-12-17 18:10 ` Richard 2005-01-02 0:22 ` Pablo Neira 0 siblings, 1 reply; 16+ messages in thread From: Richard @ 2004-12-17 18:10 UTC (permalink / raw) To: 'Pablo Neira'; +Cc: 'Netfilter Development Mailinglist' [-- Attachment #1: Type: text/plain, Size: 371 bytes --] > >>You should do those checkings in user space. Those error must be handle > >>in iptables, not in kernel. > >> > >> > >It is already done in user space. It is probably redundant doing the same > >thing here. I will drop it. > > > > > > yes, it's redudant. Please, drop that. > I drop it and also implemented other suggestions. Here is the latest. Thanks, Richard [-- Attachment #2: CTEXPIRE.diff --] [-- Type: application/octet-stream, Size: 13213 bytes --] Index: linux/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h =================================================================== --- linux/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h (revision 0) +++ linux/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h (revision 0) @@ -0,0 +1,19 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_CTEXPIRE_info { + u_int8_t mode; + unsigned long expires; +}; +#endif Index: linux/net/ipv4/netfilter/Makefile.ladd =================================================================== --- linux/net/ipv4/netfilter/Makefile.ladd (revision 0) +++ linux/net/ipv4/netfilter/Makefile.ladd (revision 0) @@ -0,0 +1,2 @@ +obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o +obj-$(CONFIG_IP_NF_TARGET_CTEXPIRE) += ipt_CTEXPIRE.o Index: linux/net/ipv4/netfilter/ipt_CTEXPIRE.c =================================================================== --- linux/net/ipv4/netfilter/ipt_CTEXPIRE.c (revision 0) +++ linux/net/ipv4/netfilter/ipt_CTEXPIRE.c (revision 0) @@ -0,0 +1,133 @@ +/* CTEXPIRE modification target for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * Version: 1.0 + * + * This software is distributed under the terms of GNU GPL + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/checksum.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ipt_CTEXPIRE.h> +#include <linux/netfilter_ipv4/ip_conntrack.h> + +MODULE_AUTHOR("Richard Zheng <richard@o-matrix.org>"); +MODULE_DESCRIPTION("IP tables CTEXPIRE modification module"); +MODULE_LICENSE("GPL"); + +#undef EXTRADEBUG + +static unsigned int +ipt_ctexpire_target(struct sk_buff **pskb, + unsigned int hooknum, + const struct net_device *in, + const struct net_device *out, + const void *targinfo, + void *userinfo) + +{ + const struct ipt_CTEXPIRE_info *info = targinfo; + unsigned long new_expires; + + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); + + if (ct == NULL) { + return IPT_CONTINUE; + } + + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); + + new_expires = info->expires*HZ; + +#ifdef EXTRADEBUG + printk(KERN_WARNING "CTEXPIRE: fired = %s, mode %d, value %ld\n", + !is_confirmed(ct) ? "no" : "yes", info->mode, info->expires); + unsigned long enter = ct->timeout.expires; +#endif + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + break; + case IPT_CTEXPIRE_INC: + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) { + /* TODO should we check if counter overflow? + * other kernel function didn't check this + */ + new_expires += ct->timeout.expires; + } else { + new_expires += ct->timeout.expires - jiffies; + } + break; + case IPT_CTEXPIRE_DEC: + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) { + new_expires = + (ct->timeout.expires <= new_expires) ? + 0 : (ct->timeout.expires - new_expires); + } else { + new_expires = + (ct->timeout.expires - jiffies <= new_expires) ? + 0 : (ct->timeout.expires - jiffies - new_expires); + } + break; + default: + break; + } + + + ip_ct_refresh(ct, new_expires); + +#ifdef EXTRADEBUG + printk(KERN_WARNING + "CTEXPIRE: enter = %ld/%ld, exit = %ld/%ld, diff = %ld\n", + enter, enter-jiffies, ct->timeout.expires, + ct->timeout.expires-jiffies, ct->timeout.expires - enter); +#endif + + return IPT_CONTINUE; +} + +static int ipt_ctexpire_checkentry(const char *tablename, + const struct ipt_entry *e, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + struct ipt_CTEXPIRE_info *info = targinfo; + + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_CTEXPIRE_info))) { + printk(KERN_WARNING "CTEXPIRE: targinfosize %u != %Zu\n", + targinfosize, + IPT_ALIGN(sizeof(struct ipt_CTEXPIRE_info))); + return 0; + } + + return 1; +} + +static struct ipt_target ipt_CTEXPIRE = { + .name = "CTEXPIRE", + .target = &ipt_ctexpire_target, + .checkentry = &ipt_ctexpire_checkentry, + .me = THIS_MODULE +}; + +static int __init init(void) +{ + return ipt_register_target(&ipt_CTEXPIRE); +} + +static void __exit fini(void) +{ + ipt_unregister_target(&ipt_CTEXPIRE); +} + +module_init(init); +module_exit(fini); + Index: linux/net/ipv4/netfilter/Config.in.ladd =================================================================== --- linux/net/ipv4/netfilter/Config.in.ladd (revision 0) +++ linux/net/ipv4/netfilter/Config.in.ladd (revision 0) @@ -0,0 +1,2 @@ + dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES + dep_tristate ' CTEXPIRE target support' CONFIG_IP_NF_TARGET_CTEXPIRE $CONFIG_IP_NF_IPTABLES Index: linux/Documentation/Configure.help.ladd =================================================================== --- linux/Documentation/Configure.help.ladd (revision 0) +++ linux/Documentation/Configure.help.ladd (revision 0) @@ -0,0 +1,9 @@ +CONFIG_IP_NF_TARGET_LOG +CTEXPIRE target support +CONFIG_IP_NF_TARGET_CTEXPIRE + This option adds a `CTEXPIRE' target, which enables the user to set + the conntrack expire value or increment / decrement it by a given + amount (in seconds). + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. Index: iptables/extensions/libipt_CTEXPIRE.man =================================================================== --- iptables/extensions/libipt_CTEXPIRE.man (revision 0) +++ iptables/extensions/libipt_CTEXPIRE.man (revision 0) @@ -0,0 +1,12 @@ +This is used to modify the conntrack expire field. The conntrack expire field determines +how much time left (in seconds) for the conntrack. The conntrack will be deleted or changed +to a new state when the expire field reachs 0. +.TP +.BI "--ctexpire-set " "value" +Set the conntrack expire value to `value' (in seconds). +.TP +.BI "--ctexpire-dec " "value" +Decrement the conntrack expire value `value' (in seconds), i.e. make it live shorter. +.TP +.BI "--ctexpire-inc " "value" +Increment the conntrack expire value `value' (in seconds), i.e. make it live longer. Index: iptables/extensions/libipt_CTEXPIRE.c =================================================================== --- iptables/extensions/libipt_CTEXPIRE.c (revision 0) +++ iptables/extensions/libipt_CTEXPIRE.c (revision 0) @@ -0,0 +1,196 @@ +/* Shared library add-on to iptables for the CTEXPIRE target + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * $Id: libipt_CTEXPIRE.c,v 1.0 2004/12/01 16:08:16 richard Exp $ + * + * This program is distributed under the terms of GNU GPL + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <iptables.h> +#include <sys/param.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ipt_CTEXPIRE.h> + +#define IPT_CTEXPIRE_USED 1 + +static void init(struct ipt_entry_target *t, unsigned int *nfcache) +{ +} + +static void help(void) +{ + printf( +"CTEXPIRE target v%s options\n" +" --ctexpire-set value Set conntrack expire to <value>\n" +" --ctexpire-dec value Decrement conntrack expire by <value>\n" +" --ctexpire-inc value Increment conntrack expire by <value>\n" +, IPTABLES_VERSION); +} + +static int parse(int c, char **argv, int invert, unsigned int *flags, + const struct ipt_entry *entry, + struct ipt_entry_target **target) +{ + struct ipt_CTEXPIRE_info *info = (struct ipt_CTEXPIRE_info *) (*target)->data; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long value, HZ_value; +#else + unsigned long value, HZ_value; +#endif + + if (*flags & IPT_CTEXPIRE_USED) { + exit_error(PARAMETER_PROBLEM, + "Can't specify conntrack expire option twice"); + } + + if (!optarg) + exit_error(PARAMETER_PROBLEM, + "CTEXPIRE: You must specify a value"); + + if (check_inverse(optarg, &invert, NULL, 0)) + exit_error(PARAMETER_PROBLEM, + "CTEXPIRE: unexpected `!'"); + +#ifdef KERNEL_64_USERSPACE_32 + if (string_to_number_ll(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, + "expire value invalid: `%s'\n", optarg); +#else + if (string_to_number_l(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, + "expire value invalid: `%s'\n", optarg); +#endif + + HZ_value = value*HZ; + + if (HZ_value < value) { + /* if user specified value is too big, + * *HZ can overflow the counter + */ + exit_error(PARAMETER_PROBLEM, + "expire value too big, will overflow counter: `%s'\n", optarg); + } + + + switch (c) { + + case '1': + info->mode = IPT_CTEXPIRE_SET; + break; + + case '2': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "CTEXPIRE: decreasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_DEC; + break; + + case '3': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "CTEXPIRE: increasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_INC; + break; + + default: + return 0; + + } + + info->expires = value; + *flags |= IPT_CTEXPIRE_USED; + + return 1; +} + +static void final_check(unsigned int flags) +{ + if (!(flags & IPT_CTEXPIRE_USED)) + exit_error(PARAMETER_PROBLEM, + "CTEXPIRE: You must specify an action"); +} + +static void save(const struct ipt_ip *ip, + const struct ipt_entry_target *target) +{ + const struct ipt_CTEXPIRE_info *info = + (struct ipt_CTEXPIRE_info *) target->data; + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("--ctexpire-set "); + break; + case IPT_CTEXPIRE_DEC: + printf("--ctexpire-dec "); + break; + + case IPT_CTEXPIRE_INC: + printf("--ctexpire-inc "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static void print(const struct ipt_ip *ip, + const struct ipt_entry_target *target, int numeric) +{ + const struct ipt_CTEXPIRE_info *info = + (struct ipt_CTEXPIRE_info *) target->data; + + printf("CTEXPIRE "); + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("set to "); + break; + case IPT_CTEXPIRE_DEC: + printf("decrement by "); + break; + case IPT_CTEXPIRE_INC: + printf("increment by "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static struct option opts[] = { + { "ctexpire-set", 1, 0, '1' }, + { "ctexpire-dec", 1, 0, '2' }, + { "ctexpire-inc", 1, 0, '3' }, + { 0 } +}; + +static +struct iptables_target CTEXPIRE = { NULL, + "CTEXPIRE", + IPTABLES_VERSION, + IPT_ALIGN(sizeof(struct ipt_CTEXPIRE_info)), + IPT_ALIGN(sizeof(struct ipt_CTEXPIRE_info)), + &help, + &init, + &parse, + &final_check, + &print, + &save, + opts +}; + +void _init(void) +{ + register_target(&CTEXPIRE); +} Index: iptables/extensions/.CTEXPIRE-test =================================================================== --- iptables/extensions/.CTEXPIRE-test (revision 0) +++ iptables/extensions/.CTEXPIRE-test (revision 0) @@ -0,0 +1,2 @@ +#! /bin/sh +[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_CTEXPIRE.c ] && echo CTEXPIRE Property changes on: iptables/extensions/.CTEXPIRE-test ___________________________________________________________________ Name: svn:executable + * Index: iptables/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h =================================================================== --- iptables/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h (revision 0) +++ iptables/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h (revision 0) @@ -0,0 +1,24 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_CTEXPIRE_info { + u_int8_t mode; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long expires; +#else + unsigned long expires; +#endif + +}; +#endif Index: help =================================================================== --- help (revision 0) +++ help (revision 0) @@ -0,0 +1,3 @@ +This adds an iptables CTEXPIRE manipulation target, which enables the user +to set the expire value of a conntrack or to increment / decrement it by a +given value. Index: info =================================================================== --- info (revision 0) +++ info (revision 0) @@ -0,0 +1,3 @@ +Author: Richard Zheng <richard@o-matrix.org> +Status: Expirement +Repository: extra ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [NEW TARGET] target for modifying conntrack timeout value 2004-12-17 18:10 ` Richard @ 2005-01-02 0:22 ` Pablo Neira 2005-01-02 9:11 ` Richard 0 siblings, 1 reply; 16+ messages in thread From: Pablo Neira @ 2005-01-02 0:22 UTC (permalink / raw) To: Richard; +Cc: 'Netfilter Development Mailinglist' [-- Attachment #1: Type: text/plain, Size: 495 bytes --] Hi Richard, Richard wrote: >I drop it and also implemented other suggestions. Here is the latest. > > I've converted your target to a match because that way we can use ctexpire together with NAT actions in the same rule. This was inspired by reading ipt_limit. I've done some minor cleanups and a checking to make sure that this match is never used in the raw table. Would like to send to the list a version for patch-o-matic-ng? Then we could push it to the SVN repository. -- Pablo [-- Attachment #2: ctexpire-kernel.patch --] [-- Type: text/x-patch, Size: 4078 bytes --] --- /dev/null 2004-09-23 01:18:13.000000000 +0200 +++ net/ipv4/netfilter/ipt_ctexpire.c 2005-01-02 01:15:04.000000000 +0100 @@ -0,0 +1,132 @@ +/* ctexpire modification match for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * 020105 -- converted to match. Pablo Neira Ayuso <pablo@eurodev.net> + * + * Version: 1.1 + * + * This software is distributed under the terms of GNU GPL version 2 + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/checksum.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ipt_ctexpire.h> +#include <linux/netfilter_ipv4/ip_conntrack.h> + +MODULE_AUTHOR("Richard Zheng <richard@o-matrix.org>"); +MODULE_DESCRIPTION("IP tables ctexpire modification module"); +MODULE_LICENSE("GPL"); + +static int +ipt_ctexpire_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + int *hotdrop) +{ + const struct ipt_ctexpire_info *info = matchinfo; + unsigned long new_expires = 0UL; + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct = ip_conntrack_get(skb, &ctinfo); + + if (ct == NULL) + return 0; + + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); + + new_expires = info->expires*HZ; + +#ifdef EXTRADEBUG + DEBUGP(KERN_WARNING "ctexpire: fired = %s, mode %d, value %ld\n", + !is_confirmed(ct) ? "no" : "yes", info->mode, info->expires); + unsigned long enter = ct->timeout.expires; +#endif + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + break; + case IPT_CTEXPIRE_INC: + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) + /* TODO should we check if counter overflow? + * other kernel function didn't check this */ + new_expires += ct->timeout.expires; + else + new_expires += ct->timeout.expires - jiffies; + break; + case IPT_CTEXPIRE_DEC: + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) { + new_expires = (ct->timeout.expires <= new_expires) ? + 0 : (ct->timeout.expires - new_expires); + } else { + new_expires = + (ct->timeout.expires - jiffies <= new_expires) ? + 0 : (ct->timeout.expires - jiffies - new_expires); + } + break; + default: + /* Shouldn't happen */ + break; + } + + + ip_ct_refresh_acct(ct, 0, NULL, new_expires); + +#ifdef EXTRADEBUG + printk(KERN_WARNING + "ctexpire: enter = %ld/%ld, exit = %ld/%ld, diff = %ld\n", + enter, enter-jiffies, ct->timeout.expires, + ct->timeout.expires-jiffies, ct->timeout.expires - enter); +#endif + + return 0; +} + +static int +ipt_ctexpire_checkentry(const char *tablename, + const struct ipt_ip *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ctexpire_info))) { + printk(KERN_WARNING "ctexpire: targinfosize %u != %Zu\n", + matchsize, + IPT_ALIGN(sizeof(struct ipt_ctexpire_info))); + return 0; + } + + if (strcmp(tablename, "raw") == 0) { + printk(KERN_WARNING "ctexpire can't be used in the raw' table"); + return 0; + } + + return 1; +} + +static struct ipt_match ipt_ctexpire = { + .name = "ctexpire", + .match = ipt_ctexpire_match, + .checkentry = ipt_ctexpire_checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ipt_register_match(&ipt_ctexpire); +} + +static void __exit fini(void) +{ + ipt_unregister_match(&ipt_ctexpire); +} + +module_init(init); +module_exit(fini); + --- /dev/null 2004-09-23 01:18:13.000000000 +0200 +++ include/linux/netfilter_ipv4/ipt_ctexpire.h 2005-01-02 00:18:18.000000000 +0100 @@ -0,0 +1,19 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_ctexpire_info { + u_int8_t mode; + unsigned long expires; +}; +#endif [-- Attachment #3: ctexpire-iptables.patch --] [-- Type: text/x-patch, Size: 5545 bytes --] Index: include/linux/netfilter_ipv4/ipt_ctexpire.h =================================================================== --- include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) +++ include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) @@ -0,0 +1,23 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_ctexpire_info { + u_int8_t mode; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long expires; +#else + unsigned long expires; +#endif +}; +#endif Index: extensions/libipt_ctexpire.c =================================================================== --- extensions/libipt_ctexpire.c (revision 0) +++ extensions/libipt_ctexpire.c (revision 0) @@ -0,0 +1,199 @@ +/* Shared library add-on to iptables for the ctexpire match + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * $Id: libipt_ctexpire.c,v 1.0 2004/12/01 16:08:16 richard Exp $ + * + * 020105 Converted to match -- Pablo Neira Ayuso <pablo@eurodev.net> + * + * This program is distributed under the terms of GNU GPL version 2 + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <iptables.h> +#include <sys/param.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include "../include/linux/netfilter_ipv4/ipt_ctexpire.h" + +#define IPT_CTEXPIRE_USED 1 + +static void init(struct ipt_entry_match *t, unsigned int *nfcache) +{ +} + +static void help(void) +{ + printf( +"ctexpire match v%s options\n" +" --ctexpire-set value Set conntrack expire to <value>\n" +" --ctexpire-dec value Decrement conntrack expire by <value>\n" +" --ctexpire-inc value Increment conntrack expire by <value>\n" +, IPTABLES_VERSION); +} + +static int +parse(int c, char **argv, int invert, unsigned int *flags, + const struct ipt_entry *entry, + unsigned int *nfcache, + struct ipt_entry_match **match) +{ + struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) (*match)->data; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long value, HZ_value; +#else + unsigned long value, HZ_value; +#endif + + if (*flags & IPT_CTEXPIRE_USED) { + exit_error(PARAMETER_PROBLEM, + "Can't specify conntrack expire option twice"); + } + + if (!optarg) + exit_error(PARAMETER_PROBLEM, + "ctexpire: You must specify a value"); + + if (check_inverse(optarg, &invert, NULL, 0)) + exit_error(PARAMETER_PROBLEM, + "ctexpire: unexpected `!'"); + +#ifdef KERNEL_64_USERSPACE_32 + if (string_to_number_ll(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, + "expire value invalid: `%s'\n", optarg); +#else + if (string_to_number_l(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, + "expire value invalid: `%s'\n", optarg); +#endif + + HZ_value = value*HZ; + + if (HZ_value < value) { + /* if user specified value is too big, + * *HZ can overflow the counter + */ + exit_error(PARAMETER_PROBLEM, + "expire value too big, will overflow counter: `%s'\n", optarg); + } + + switch (c) { + case '1': + info->mode = IPT_CTEXPIRE_SET; + break; + + case '2': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "ctexpire: decreasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_DEC; + break; + + case '3': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "ctexpire: increasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_INC; + break; + + default: + return 0; + + } + + info->expires = value; + *flags |= IPT_CTEXPIRE_USED; + + return 1; +} + +static void final_check(unsigned int flags) +{ + if (!(flags & IPT_CTEXPIRE_USED)) + exit_error(PARAMETER_PROBLEM, + "ctexpire: You must specify an action"); +} + +static void save(const struct ipt_ip *ip, + const struct ipt_entry_match *match) +{ + const struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) match->data; + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("--ctexpire-set "); + break; + case IPT_CTEXPIRE_DEC: + printf("--ctexpire-dec "); + break; + + case IPT_CTEXPIRE_INC: + printf("--ctexpire-inc "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static void print(const struct ipt_ip *ip, + const struct ipt_entry_match *match, int numeric) +{ + const struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) match->data; + + printf("ctexpire "); + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("set to "); + break; + case IPT_CTEXPIRE_DEC: + printf("decrement by "); + break; + case IPT_CTEXPIRE_INC: + printf("increment by "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static struct option opts[] = { + { "ctexpire-set", 1, 0, '1' }, + { "ctexpire-dec", 1, 0, '2' }, + { "ctexpire-inc", 1, 0, '3' }, + { 0 } +}; + +static +struct iptables_match ipt_ctexpire = { + .name = "ctexpire", + .version = IPTABLES_VERSION, + .size = IPT_ALIGN(sizeof(struct ipt_ctexpire_info)), + .userspacesize = IPT_ALIGN(sizeof(struct ipt_ctexpire_info)), + .help = help, + .init = init, + .parse = parse, + .final_check = final_check, + .print = print, + .save = save, + .extra_opts = opts +}; + +void _init(void) +{ + register_match(&ipt_ctexpire); +} ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [NEW TARGET] target for modifying conntrack timeout value 2005-01-02 0:22 ` Pablo Neira @ 2005-01-02 9:11 ` Richard 2005-01-02 13:15 ` Pablo Neira 0 siblings, 1 reply; 16+ messages in thread From: Richard @ 2005-01-02 9:11 UTC (permalink / raw) To: 'Pablo Neira'; +Cc: 'Netfilter Development Mailinglist' [-- Attachment #1: Type: text/plain, Size: 740 bytes --] > > I've converted your target to a match because that way we can use > ctexpire together with NAT actions in the same rule. This was inspired > by reading ipt_limit. I've done some minor cleanups and a checking to > make sure that this match is never used in the raw table. > > Would like to send to the list a version for patch-o-matic-ng? Then we > could push it to the SVN repository. > Hi Pablo, Thanks for the change and cleanups. Here is the version for pom. The only change I made is +#if 0 + ip_ct_refresh_acct(ct, 0, NULL, new_expires); +#endif + ip_ct_refresh(ct, new_expires); This is because I got unresolved symbol ip_ct_refresh_acct when loading the kernel module. I am using kernel version 2.4.25. Regards, Richard [-- Attachment #2: ctexpire.patch --] [-- Type: application/octet-stream, Size: 14144 bytes --] Index: ctexpire/linux/include/linux/netfilter_ipv4/ipt_ctexpire.h =================================================================== --- ctexpire/linux/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) +++ ctexpire/linux/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) @@ -0,0 +1,19 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_ctexpire_info { + u_int8_t mode; + unsigned long expires; +}; +#endif Index: ctexpire/linux/net/ipv4/netfilter/Makefile.ladd =================================================================== --- ctexpire/linux/net/ipv4/netfilter/Makefile.ladd (revision 0) +++ ctexpire/linux/net/ipv4/netfilter/Makefile.ladd (revision 0) @@ -0,0 +1,3 @@ +obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o +obj-$(CONFIG_IP_NF_MATCH_CTEXPIRE) += ipt_ctexpire.o + Index: ctexpire/linux/net/ipv4/netfilter/ipt_ctexpire.c =================================================================== --- ctexpire/linux/net/ipv4/netfilter/ipt_ctexpire.c (revision 0) +++ ctexpire/linux/net/ipv4/netfilter/ipt_ctexpire.c (revision 0) @@ -0,0 +1,134 @@ +/* ctexpire modification match for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * 020105 -- converted to match. Pablo Neira Ayuso <pablo@eurodev.net> + * + * Version: 1.1 + * + * This software is distributed under the terms of GNU GPL version 2 + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/checksum.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ipt_ctexpire.h> +#include <linux/netfilter_ipv4/ip_conntrack.h> + +MODULE_AUTHOR("Richard Zheng <richard@o-matrix.org>"); +MODULE_DESCRIPTION("IP tables ctexpire modification module"); +MODULE_LICENSE("GPL"); + +static int +ipt_ctexpire_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + int *hotdrop) +{ + const struct ipt_ctexpire_info *info = matchinfo; + unsigned long new_expires = 0UL; + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct = ip_conntrack_get(skb, &ctinfo); + + if (ct == NULL) + return 0; + + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); + + new_expires = info->expires*HZ; + +#ifdef EXTRADEBUG + DEBUGP(KERN_WARNING "ctexpire: fired = %s, mode %d, value %ld\n", + !is_confirmed(ct) ? "no" : "yes", info->mode, info->expires); + unsigned long enter = ct->timeout.expires; +#endif + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + break; + case IPT_CTEXPIRE_INC: + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) + /* TODO should we check if counter overflow? + * other kernel function didn't check this */ + new_expires += ct->timeout.expires; + else + new_expires += ct->timeout.expires - jiffies; + break; + case IPT_CTEXPIRE_DEC: + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) { + new_expires = (ct->timeout.expires <= new_expires) ? + 0 : (ct->timeout.expires - new_expires); + } else { + new_expires = + (ct->timeout.expires - jiffies <= new_expires) ? + 0 : (ct->timeout.expires - jiffies - new_expires); + } + break; + default: + /* Shouldn't happen */ + break; + } + +#if 0 + ip_ct_refresh_acct(ct, 0, NULL, new_expires); +#endif + ip_ct_refresh(ct, new_expires); + +#ifdef EXTRADEBUG + printk(KERN_WARNING + "ctexpire: enter = %ld/%ld, exit = %ld/%ld, diff = %ld\n", + enter, enter-jiffies, ct->timeout.expires, + ct->timeout.expires-jiffies, ct->timeout.expires - enter); +#endif + + return 0; +} + +static int +ipt_ctexpire_checkentry(const char *tablename, + const struct ipt_ip *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ctexpire_info))) { + printk(KERN_WARNING "ctexpire: targinfosize %u != %Zu\n", + matchsize, + IPT_ALIGN(sizeof(struct ipt_ctexpire_info))); + return 0; + } + + if (strcmp(tablename, "raw") == 0) { + printk(KERN_WARNING "ctexpire can't be used in the raw' table"); + return 0; + } + + return 1; +} + +static struct ipt_match ipt_ctexpire = { + .name = "ctexpire", + .match = ipt_ctexpire_match, + .checkentry = ipt_ctexpire_checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ipt_register_match(&ipt_ctexpire); +} + +static void __exit fini(void) +{ + ipt_unregister_match(&ipt_ctexpire); +} + +module_init(init); +module_exit(fini); + Index: ctexpire/linux/net/ipv4/netfilter/Config.in.ladd =================================================================== --- ctexpire/linux/net/ipv4/netfilter/Config.in.ladd (revision 0) +++ ctexpire/linux/net/ipv4/netfilter/Config.in.ladd (revision 0) @@ -0,0 +1,2 @@ + dep_tristate ' Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES + dep_tristate ' ctexpire match support' CONFIG_IP_NF_MATCH_CTEXPIRE $CONFIG_IP_NF_IPTABLES Index: ctexpire/linux/Documentation/Configure.help.ladd =================================================================== --- ctexpire/linux/Documentation/Configure.help.ladd (revision 0) +++ ctexpire/linux/Documentation/Configure.help.ladd (revision 0) @@ -0,0 +1,8 @@ +CONFIG_IP_NF_MATCH_STATE +ctexpire match support +CONFIG_IP_NF_MATCH_CTEXPIRE + This match allows you to set the conntrack expire value or + increment / decrement it by a given amount (in seconds). + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. Index: ctexpire/iptables/extensions/libipt_ctexpire.man =================================================================== --- ctexpire/iptables/extensions/libipt_ctexpire.man (revision 0) +++ ctexpire/iptables/extensions/libipt_ctexpire.man (revision 0) @@ -0,0 +1,12 @@ +This is used to modify the conntrack expire field. The conntrack expire field determines +how much time left (in seconds) for the conntrack. The conntrack will be deleted or changed +to a new state when the expire field reachs 0. +.TP +.BI "--ctexpire-set " "value" +Set the conntrack expire value to `value' (in seconds). +.TP +.BI "--ctexpire-dec " "value" +Decrement the conntrack expire value `value' (in seconds), i.e. make it live shorter. +.TP +.BI "--ctexpire-inc " "value" +Increment the conntrack expire value `value' (in seconds), i.e. make it live longer. Index: ctexpire/iptables/extensions/libipt_ctexpire.c =================================================================== --- ctexpire/iptables/extensions/libipt_ctexpire.c (revision 0) +++ ctexpire/iptables/extensions/libipt_ctexpire.c (revision 0) @@ -0,0 +1,199 @@ +/* Shared library add-on to iptables for the ctexpire match + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * $Id: libipt_ctexpire.c,v 1.0 2004/12/01 16:08:16 richard Exp $ + * + * 020105 Converted to match -- Pablo Neira Ayuso <pablo@eurodev.net> + * + * This program is distributed under the terms of GNU GPL version 2 + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <iptables.h> +#include <sys/param.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include "../include/linux/netfilter_ipv4/ipt_ctexpire.h" + +#define IPT_CTEXPIRE_USED 1 + +static void init(struct ipt_entry_match *t, unsigned int *nfcache) +{ +} + +static void help(void) +{ + printf( +"ctexpire match v%s options\n" +" --ctexpire-set value Set conntrack expire to <value>\n" +" --ctexpire-dec value Decrement conntrack expire by <value>\n" +" --ctexpire-inc value Increment conntrack expire by <value>\n" +, IPTABLES_VERSION); +} + +static int +parse(int c, char **argv, int invert, unsigned int *flags, + const struct ipt_entry *entry, + unsigned int *nfcache, + struct ipt_entry_match **match) +{ + struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) (*match)->data; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long value, HZ_value; +#else + unsigned long value, HZ_value; +#endif + + if (*flags & IPT_CTEXPIRE_USED) { + exit_error(PARAMETER_PROBLEM, + "Can't specify conntrack expire option twice"); + } + + if (!optarg) + exit_error(PARAMETER_PROBLEM, + "ctexpire: You must specify a value"); + + if (check_inverse(optarg, &invert, NULL, 0)) + exit_error(PARAMETER_PROBLEM, + "ctexpire: unexpected `!'"); + +#ifdef KERNEL_64_USERSPACE_32 + if (string_to_number_ll(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, + "expire value invalid: `%s'\n", optarg); +#else + if (string_to_number_l(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, + "expire value invalid: `%s'\n", optarg); +#endif + + HZ_value = value*HZ; + + if (HZ_value < value) { + /* if user specified value is too big, + * *HZ can overflow the counter + */ + exit_error(PARAMETER_PROBLEM, + "expire value too big, will overflow counter: `%s'\n", optarg); + } + + switch (c) { + case '1': + info->mode = IPT_CTEXPIRE_SET; + break; + + case '2': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "ctexpire: decreasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_DEC; + break; + + case '3': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "ctexpire: increasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_INC; + break; + + default: + return 0; + + } + + info->expires = value; + *flags |= IPT_CTEXPIRE_USED; + + return 1; +} + +static void final_check(unsigned int flags) +{ + if (!(flags & IPT_CTEXPIRE_USED)) + exit_error(PARAMETER_PROBLEM, + "ctexpire: You must specify an action"); +} + +static void save(const struct ipt_ip *ip, + const struct ipt_entry_match *match) +{ + const struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) match->data; + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("--ctexpire-set "); + break; + case IPT_CTEXPIRE_DEC: + printf("--ctexpire-dec "); + break; + + case IPT_CTEXPIRE_INC: + printf("--ctexpire-inc "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static void print(const struct ipt_ip *ip, + const struct ipt_entry_match *match, int numeric) +{ + const struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) match->data; + + printf("ctexpire "); + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("set to "); + break; + case IPT_CTEXPIRE_DEC: + printf("decrement by "); + break; + case IPT_CTEXPIRE_INC: + printf("increment by "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static struct option opts[] = { + { "ctexpire-set", 1, 0, '1' }, + { "ctexpire-dec", 1, 0, '2' }, + { "ctexpire-inc", 1, 0, '3' }, + { 0 } +}; + +static +struct iptables_match ipt_ctexpire = { + .name = "ctexpire", + .version = IPTABLES_VERSION, + .size = IPT_ALIGN(sizeof(struct ipt_ctexpire_info)), + .userspacesize = IPT_ALIGN(sizeof(struct ipt_ctexpire_info)), + .help = help, + .init = init, + .parse = parse, + .final_check = final_check, + .print = print, + .save = save, + .extra_opts = opts +}; + +void _init(void) +{ + register_match(&ipt_ctexpire); +} Index: ctexpire/iptables/extensions/.CTEXPIRE-test =================================================================== --- ctexpire/iptables/extensions/.CTEXPIRE-test (revision 0) +++ ctexpire/iptables/extensions/.CTEXPIRE-test (revision 0) @@ -0,0 +1,2 @@ +#! /bin/sh +[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_CTEXPIRE.c ] && echo CTEXPIRE Property changes on: ctexpire/iptables/extensions/.CTEXPIRE-test ___________________________________________________________________ Name: svn:executable + * Index: ctexpire/iptables/include/linux/netfilter_ipv4/ipt_ctexpire.h =================================================================== --- ctexpire/iptables/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) +++ ctexpire/iptables/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) @@ -0,0 +1,23 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_ctexpire_info { + u_int8_t mode; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long expires; +#else + unsigned long expires; +#endif +}; +#endif Index: ctexpire/help =================================================================== --- ctexpire/help (revision 0) +++ ctexpire/help (revision 0) @@ -0,0 +1,9 @@ +This adds an iptables ctexpire mtach, which enables the user +to set the expire value of a conntrack or to increment / decrement it by a +given value. + +Examples: + +# allow sip (udp 5060) streams to have 3600 second timeout +iptables -p udp -m udp --dport 5060 -m ctexpire --ctexpire-set 3600 -j ACCEPT +iptables -p udp -m udp --sport 5060 -m ctexpire --ctexpire-set 3600 -j ACCEPT Index: ctexpire/info =================================================================== --- ctexpire/info (revision 0) +++ ctexpire/info (revision 0) @@ -0,0 +1,3 @@ +Author: Richard Zheng <richard@o-matrix.org> +Status: Experiment +Repository: extra ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [NEW TARGET] target for modifying conntrack timeout value 2005-01-02 9:11 ` Richard @ 2005-01-02 13:15 ` Pablo Neira 2005-01-02 19:12 ` Richard 0 siblings, 1 reply; 16+ messages in thread From: Pablo Neira @ 2005-01-02 13:15 UTC (permalink / raw) To: Richard; +Cc: 'Netfilter Development Mailinglist' Richard wrote: >The only change I made is > >+#if 0 >+ ip_ct_refresh_acct(ct, 0, NULL, new_expires); >+#endif >+ ip_ct_refresh(ct, new_expires); > >This is because I got unresolved symbol ip_ct_refresh_acct when loading the >kernel module. I am using kernel version 2.4.25. > > I forgot to tell you, ip_ct_refresh was renamed to ip_ct_refresh_acct in 2.6.9. Ick, the API is kinda broken now :(. Since I work with lastest 2.6 bk snapshot, I needed to use the new name. I think that it would be nice if you add a comment in that section of code to explain why you did that? -- Pablo ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [NEW TARGET] target for modifying conntrack timeout value 2005-01-02 13:15 ` Pablo Neira @ 2005-01-02 19:12 ` Richard 2005-01-02 19:35 ` Tom Marshall 0 siblings, 1 reply; 16+ messages in thread From: Richard @ 2005-01-02 19:12 UTC (permalink / raw) To: 'Pablo Neira'; +Cc: 'Netfilter Development Mailinglist' [-- Attachment #1: Type: text/plain, Size: 1194 bytes --] > -----Original Message----- > From: Pablo Neira [mailto:pablo@eurodev.net] > Sent: Sunday, January 02, 2005 3:15 AM > To: Richard > Cc: 'Netfilter Development Mailinglist' > Subject: Re: [NEW TARGET] target for modifying conntrack timeout value > > Richard wrote: > > >The only change I made is > > > >+#if 0 > >+ ip_ct_refresh_acct(ct, 0, NULL, new_expires); > >+#endif > >+ ip_ct_refresh(ct, new_expires); > > > >This is because I got unresolved symbol ip_ct_refresh_acct when loading > the > >kernel module. I am using kernel version 2.4.25. > > > > > I forgot to tell you, ip_ct_refresh was renamed to ip_ct_refresh_acct > in 2.6.9. Ick, the API is kinda broken now :(. Since I work with lastest > 2.6 bk snapshot, I needed to use the new name. I think that it would be > nice if you add a comment in that section of code to explain why you did > that? > ok, I changed the code to this, + /* To refresh the expire timer value of a conntrack, + * linux 2.6.9 kernel starts using ip_ct_refresh_acct(), + * while older ones use ip_ct_refresh() + */ +#ifdef ip_ct_refresh_acct + ip_ct_refresh_acct(ct, 0, NULL, new_expires); +#else + ip_ct_refresh(ct, new_expires); +#endif Richard [-- Attachment #2: ctexpire.patch --] [-- Type: application/octet-stream, Size: 14338 bytes --] Index: ctexpire/linux/include/linux/netfilter_ipv4/ipt_ctexpire.h =================================================================== --- ctexpire/linux/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) +++ ctexpire/linux/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) @@ -0,0 +1,19 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_ctexpire_info { + u_int8_t mode; + unsigned long expires; +}; +#endif Index: ctexpire/linux/net/ipv4/netfilter/Makefile.ladd =================================================================== --- ctexpire/linux/net/ipv4/netfilter/Makefile.ladd (revision 0) +++ ctexpire/linux/net/ipv4/netfilter/Makefile.ladd (revision 0) @@ -0,0 +1,3 @@ +obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o +obj-$(CONFIG_IP_NF_MATCH_CTEXPIRE) += ipt_ctexpire.o + Index: ctexpire/linux/net/ipv4/netfilter/ipt_ctexpire.c =================================================================== --- ctexpire/linux/net/ipv4/netfilter/ipt_ctexpire.c (revision 0) +++ ctexpire/linux/net/ipv4/netfilter/ipt_ctexpire.c (revision 0) @@ -0,0 +1,139 @@ +/* ctexpire modification match for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * 020105 -- converted to match. Pablo Neira Ayuso <pablo@eurodev.net> + * + * Version: 1.1 + * + * This software is distributed under the terms of GNU GPL version 2 + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/checksum.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ipt_ctexpire.h> +#include <linux/netfilter_ipv4/ip_conntrack.h> + +MODULE_AUTHOR("Richard Zheng <richard@o-matrix.org>"); +MODULE_DESCRIPTION("IP tables ctexpire modification module"); +MODULE_LICENSE("GPL"); + +static int +ipt_ctexpire_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + int *hotdrop) +{ + const struct ipt_ctexpire_info *info = matchinfo; + unsigned long new_expires = 0UL; + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct = ip_conntrack_get(skb, &ctinfo); + + if (ct == NULL) + return 0; + + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); + + new_expires = info->expires*HZ; + +#ifdef EXTRADEBUG + DEBUGP(KERN_WARNING "ctexpire: fired = %s, mode %d, value %ld\n", + !is_confirmed(ct) ? "no" : "yes", info->mode, info->expires); + unsigned long enter = ct->timeout.expires; +#endif + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + break; + case IPT_CTEXPIRE_INC: + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) + /* TODO should we check if counter overflow? + * other kernel function didn't check this */ + new_expires += ct->timeout.expires; + else + new_expires += ct->timeout.expires - jiffies; + break; + case IPT_CTEXPIRE_DEC: + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) { + new_expires = (ct->timeout.expires <= new_expires) ? + 0 : (ct->timeout.expires - new_expires); + } else { + new_expires = + (ct->timeout.expires - jiffies <= new_expires) ? + 0 : (ct->timeout.expires - jiffies - new_expires); + } + break; + default: + /* Shouldn't happen */ + break; + } + + /* To refresh the expire timer value of a conntrack, + * linux 2.6.9 kernel starts using ip_ct_refresh_acct(), + * while older ones use ip_ct_refresh() + */ +#ifdef ip_ct_refresh_acct + ip_ct_refresh_acct(ct, 0, NULL, new_expires); +#else + ip_ct_refresh(ct, new_expires); +#endif + +#ifdef EXTRADEBUG + printk(KERN_WARNING + "ctexpire: enter = %ld/%ld, exit = %ld/%ld, diff = %ld\n", + enter, enter-jiffies, ct->timeout.expires, + ct->timeout.expires-jiffies, ct->timeout.expires - enter); +#endif + + return 0; +} + +static int +ipt_ctexpire_checkentry(const char *tablename, + const struct ipt_ip *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ctexpire_info))) { + printk(KERN_WARNING "ctexpire: targinfosize %u != %Zu\n", + matchsize, + IPT_ALIGN(sizeof(struct ipt_ctexpire_info))); + return 0; + } + + if (strcmp(tablename, "raw") == 0) { + printk(KERN_WARNING "ctexpire can't be used in the raw' table"); + return 0; + } + + return 1; +} + +static struct ipt_match ipt_ctexpire = { + .name = "ctexpire", + .match = ipt_ctexpire_match, + .checkentry = ipt_ctexpire_checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ipt_register_match(&ipt_ctexpire); +} + +static void __exit fini(void) +{ + ipt_unregister_match(&ipt_ctexpire); +} + +module_init(init); +module_exit(fini); + Index: ctexpire/linux/net/ipv4/netfilter/Config.in.ladd =================================================================== --- ctexpire/linux/net/ipv4/netfilter/Config.in.ladd (revision 0) +++ ctexpire/linux/net/ipv4/netfilter/Config.in.ladd (revision 0) @@ -0,0 +1,2 @@ + dep_tristate ' Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES + dep_tristate ' ctexpire match support' CONFIG_IP_NF_MATCH_CTEXPIRE $CONFIG_IP_NF_IPTABLES Index: ctexpire/linux/Documentation/Configure.help.ladd =================================================================== --- ctexpire/linux/Documentation/Configure.help.ladd (revision 0) +++ ctexpire/linux/Documentation/Configure.help.ladd (revision 0) @@ -0,0 +1,8 @@ +CONFIG_IP_NF_MATCH_STATE +ctexpire match support +CONFIG_IP_NF_MATCH_CTEXPIRE + This match allows you to set the conntrack expire value or + increment / decrement it by a given amount (in seconds). + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. Index: ctexpire/iptables/extensions/libipt_ctexpire.man =================================================================== --- ctexpire/iptables/extensions/libipt_ctexpire.man (revision 0) +++ ctexpire/iptables/extensions/libipt_ctexpire.man (revision 0) @@ -0,0 +1,12 @@ +This is used to modify the conntrack expire field. The conntrack expire field determines +how much time left (in seconds) for the conntrack. The conntrack will be deleted or changed +to a new state when the expire field reachs 0. +.TP +.BI "--ctexpire-set " "value" +Set the conntrack expire value to `value' (in seconds). +.TP +.BI "--ctexpire-dec " "value" +Decrement the conntrack expire value `value' (in seconds), i.e. make it live shorter. +.TP +.BI "--ctexpire-inc " "value" +Increment the conntrack expire value `value' (in seconds), i.e. make it live longer. Index: ctexpire/iptables/extensions/libipt_ctexpire.c =================================================================== --- ctexpire/iptables/extensions/libipt_ctexpire.c (revision 0) +++ ctexpire/iptables/extensions/libipt_ctexpire.c (revision 0) @@ -0,0 +1,199 @@ +/* Shared library add-on to iptables for the ctexpire match + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * $Id: libipt_ctexpire.c,v 1.0 2004/12/01 16:08:16 richard Exp $ + * + * 020105 Converted to match -- Pablo Neira Ayuso <pablo@eurodev.net> + * + * This program is distributed under the terms of GNU GPL version 2 + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <iptables.h> +#include <sys/param.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include "../include/linux/netfilter_ipv4/ipt_ctexpire.h" + +#define IPT_CTEXPIRE_USED 1 + +static void init(struct ipt_entry_match *t, unsigned int *nfcache) +{ +} + +static void help(void) +{ + printf( +"ctexpire match v%s options\n" +" --ctexpire-set value Set conntrack expire to <value>\n" +" --ctexpire-dec value Decrement conntrack expire by <value>\n" +" --ctexpire-inc value Increment conntrack expire by <value>\n" +, IPTABLES_VERSION); +} + +static int +parse(int c, char **argv, int invert, unsigned int *flags, + const struct ipt_entry *entry, + unsigned int *nfcache, + struct ipt_entry_match **match) +{ + struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) (*match)->data; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long value, HZ_value; +#else + unsigned long value, HZ_value; +#endif + + if (*flags & IPT_CTEXPIRE_USED) { + exit_error(PARAMETER_PROBLEM, + "Can't specify conntrack expire option twice"); + } + + if (!optarg) + exit_error(PARAMETER_PROBLEM, + "ctexpire: You must specify a value"); + + if (check_inverse(optarg, &invert, NULL, 0)) + exit_error(PARAMETER_PROBLEM, + "ctexpire: unexpected `!'"); + +#ifdef KERNEL_64_USERSPACE_32 + if (string_to_number_ll(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, + "expire value invalid: `%s'\n", optarg); +#else + if (string_to_number_l(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, + "expire value invalid: `%s'\n", optarg); +#endif + + HZ_value = value*HZ; + + if (HZ_value < value) { + /* if user specified value is too big, + * *HZ can overflow the counter + */ + exit_error(PARAMETER_PROBLEM, + "expire value too big, will overflow counter: `%s'\n", optarg); + } + + switch (c) { + case '1': + info->mode = IPT_CTEXPIRE_SET; + break; + + case '2': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "ctexpire: decreasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_DEC; + break; + + case '3': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "ctexpire: increasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_INC; + break; + + default: + return 0; + + } + + info->expires = value; + *flags |= IPT_CTEXPIRE_USED; + + return 1; +} + +static void final_check(unsigned int flags) +{ + if (!(flags & IPT_CTEXPIRE_USED)) + exit_error(PARAMETER_PROBLEM, + "ctexpire: You must specify an action"); +} + +static void save(const struct ipt_ip *ip, + const struct ipt_entry_match *match) +{ + const struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) match->data; + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("--ctexpire-set "); + break; + case IPT_CTEXPIRE_DEC: + printf("--ctexpire-dec "); + break; + + case IPT_CTEXPIRE_INC: + printf("--ctexpire-inc "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static void print(const struct ipt_ip *ip, + const struct ipt_entry_match *match, int numeric) +{ + const struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) match->data; + + printf("ctexpire "); + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("set to "); + break; + case IPT_CTEXPIRE_DEC: + printf("decrement by "); + break; + case IPT_CTEXPIRE_INC: + printf("increment by "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static struct option opts[] = { + { "ctexpire-set", 1, 0, '1' }, + { "ctexpire-dec", 1, 0, '2' }, + { "ctexpire-inc", 1, 0, '3' }, + { 0 } +}; + +static +struct iptables_match ipt_ctexpire = { + .name = "ctexpire", + .version = IPTABLES_VERSION, + .size = IPT_ALIGN(sizeof(struct ipt_ctexpire_info)), + .userspacesize = IPT_ALIGN(sizeof(struct ipt_ctexpire_info)), + .help = help, + .init = init, + .parse = parse, + .final_check = final_check, + .print = print, + .save = save, + .extra_opts = opts +}; + +void _init(void) +{ + register_match(&ipt_ctexpire); +} Index: ctexpire/iptables/extensions/.CTEXPIRE-test =================================================================== --- ctexpire/iptables/extensions/.CTEXPIRE-test (revision 0) +++ ctexpire/iptables/extensions/.CTEXPIRE-test (revision 0) @@ -0,0 +1,2 @@ +#! /bin/sh +[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_CTEXPIRE.c ] && echo CTEXPIRE Property changes on: ctexpire/iptables/extensions/.CTEXPIRE-test ___________________________________________________________________ Name: svn:executable + * Index: ctexpire/iptables/include/linux/netfilter_ipv4/ipt_ctexpire.h =================================================================== --- ctexpire/iptables/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) +++ ctexpire/iptables/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) @@ -0,0 +1,23 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_ctexpire_info { + u_int8_t mode; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long expires; +#else + unsigned long expires; +#endif +}; +#endif Index: ctexpire/help =================================================================== --- ctexpire/help (revision 0) +++ ctexpire/help (revision 0) @@ -0,0 +1,9 @@ +This adds an iptables ctexpire mtach, which enables the user +to set the expire value of a conntrack or to increment / decrement it by a +given value. + +Examples: + +# allow sip (udp 5060) streams to have 3600 second timeout +iptables -p udp -m udp --dport 5060 -m ctexpire --ctexpire-set 3600 -j ACCEPT +iptables -p udp -m udp --sport 5060 -m ctexpire --ctexpire-set 3600 -j ACCEPT Index: ctexpire/info =================================================================== --- ctexpire/info (revision 0) +++ ctexpire/info (revision 0) @@ -0,0 +1,3 @@ +Author: Richard Zheng <richard@o-matrix.org> +Status: Experiment +Repository: extra ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [NEW TARGET] target for modifying conntrack timeout value 2005-01-02 19:12 ` Richard @ 2005-01-02 19:35 ` Tom Marshall 2005-01-02 19:42 ` Richard 2005-01-02 22:24 ` Richard 0 siblings, 2 replies; 16+ messages in thread From: Tom Marshall @ 2005-01-02 19:35 UTC (permalink / raw) To: Richard; +Cc: 'Netfilter Development Mailinglist', 'Pablo Neira' [-- Attachment #1: Type: text/plain, Size: 1043 bytes --] > > I forgot to tell you, ip_ct_refresh was renamed to ip_ct_refresh_acct > > in 2.6.9. Ick, the API is kinda broken now :(. Since I work with lastest > > 2.6 bk snapshot, I needed to use the new name. I think that it would be > > nice if you add a comment in that section of code to explain why you did > > that? > > > ok, I changed the code to this, > + /* To refresh the expire timer value of a conntrack, > + * linux 2.6.9 kernel starts using ip_ct_refresh_acct(), > + * while older ones use ip_ct_refresh() > + */ > +#ifdef ip_ct_refresh_acct > + ip_ct_refresh_acct(ct, 0, NULL, new_expires); > +#else > + ip_ct_refresh(ct, new_expires); > +#endif Did you actually verify this works? I don't see ip_ct_refresh_acct defined as a macro, only a forward decl. Forward decls don't count because ifdef operates on the preprocessor level. You'll need another way to test (netfilter version, kernel version, etc.) -- Old timer, n.: One who remembers when charity was a virtue and not an organization. [-- Attachment #2: Type: application/pgp-signature, Size: 240 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [NEW TARGET] target for modifying conntrack timeout value 2005-01-02 19:35 ` Tom Marshall @ 2005-01-02 19:42 ` Richard 2005-01-02 22:24 ` Richard 1 sibling, 0 replies; 16+ messages in thread From: Richard @ 2005-01-02 19:42 UTC (permalink / raw) To: 'Tom Marshall' Cc: 'Netfilter Development Mailinglist', 'Pablo Neira' > > > > > ok, I changed the code to this, > > + /* To refresh the expire timer value of a conntrack, > > + * linux 2.6.9 kernel starts using ip_ct_refresh_acct(), > > + * while older ones use ip_ct_refresh() > > + */ > > +#ifdef ip_ct_refresh_acct > > + ip_ct_refresh_acct(ct, 0, NULL, new_expires); > > +#else > > + ip_ct_refresh(ct, new_expires); > > +#endif > > Did you actually verify this works? > > I don't see ip_ct_refresh_acct defined as a macro, only a forward decl. > Forward decls don't count because ifdef operates on the preprocessor level. > You'll need another way to test (netfilter version, kernel version, etc.) > I tried the following and it worked on 2.4.25, so I assume that the above code works. And both versions compile without a problem. #ifdef ip_ct_refresh ip_ct_refresh(ct, new_expires); #else ip_ct_refresh_acct(ct, 0, NULL, new_expires); #endif Richard ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [NEW TARGET] target for modifying conntrack timeout value 2005-01-02 19:35 ` Tom Marshall 2005-01-02 19:42 ` Richard @ 2005-01-02 22:24 ` Richard 1 sibling, 0 replies; 16+ messages in thread From: Richard @ 2005-01-02 22:24 UTC (permalink / raw) To: 'Tom Marshall' Cc: 'Netfilter Development Mailinglist', 'Pablo Neira' [-- Attachment #1: Type: text/plain, Size: 496 bytes --] > Did you actually verify this works? > > I don't see ip_ct_refresh_acct defined as a macro, only a forward decl. > Forward decls don't count because ifdef operates on the preprocessor level. > You'll need another way to test (netfilter version, kernel version, etc.) Hi Tom, Here is a new method verifying the kernel version. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) + ip_ct_refresh(ct, new_expires); +#else + ip_ct_refresh_acct(ct, 0, NULL, new_expires); +#endif Thanks! Richard [-- Attachment #2: ctexpire.patch --] [-- Type: application/octet-stream, Size: 14082 bytes --] Index: linux/include/linux/netfilter_ipv4/ipt_ctexpire.h =================================================================== --- linux/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) +++ linux/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) @@ -0,0 +1,19 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_ctexpire_info { + u_int8_t mode; + unsigned long expires; +}; +#endif Index: linux/net/ipv4/netfilter/Makefile.ladd =================================================================== --- linux/net/ipv4/netfilter/Makefile.ladd (revision 0) +++ linux/net/ipv4/netfilter/Makefile.ladd (revision 0) @@ -0,0 +1,3 @@ +obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o +obj-$(CONFIG_IP_NF_MATCH_CTEXPIRE) += ipt_ctexpire.o + Index: linux/net/ipv4/netfilter/ipt_ctexpire.c =================================================================== --- linux/net/ipv4/netfilter/ipt_ctexpire.c (revision 0) +++ linux/net/ipv4/netfilter/ipt_ctexpire.c (revision 0) @@ -0,0 +1,140 @@ +/* ctexpire modification match for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * 020105 -- converted to match. Pablo Neira Ayuso <pablo@eurodev.net> + * + * Version: 1.1 + * + * This software is distributed under the terms of GNU GPL version 2 + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/checksum.h> +#include <linux/version.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ipt_ctexpire.h> +#include <linux/netfilter_ipv4/ip_conntrack.h> + +MODULE_AUTHOR("Richard Zheng <richard@o-matrix.org>"); +MODULE_DESCRIPTION("IP tables ctexpire modification module"); +MODULE_LICENSE("GPL"); + +static int +ipt_ctexpire_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + int *hotdrop) +{ + const struct ipt_ctexpire_info *info = matchinfo; + unsigned long new_expires = 0UL; + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct = ip_conntrack_get(skb, &ctinfo); + + if (ct == NULL) + return 0; + + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); + + new_expires = info->expires*HZ; + +#ifdef EXTRADEBUG + DEBUGP(KERN_WARNING "ctexpire: fired = %s, mode %d, value %ld\n", + !is_confirmed(ct) ? "no" : "yes", info->mode, info->expires); + unsigned long enter = ct->timeout.expires; +#endif + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + break; + case IPT_CTEXPIRE_INC: + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) + /* TODO should we check if counter overflow? + * other kernel function didn't check this */ + new_expires += ct->timeout.expires; + else + new_expires += ct->timeout.expires - jiffies; + break; + case IPT_CTEXPIRE_DEC: + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) { + new_expires = (ct->timeout.expires <= new_expires) ? + 0 : (ct->timeout.expires - new_expires); + } else { + new_expires = + (ct->timeout.expires - jiffies <= new_expires) ? + 0 : (ct->timeout.expires - jiffies - new_expires); + } + break; + default: + /* Shouldn't happen */ + break; + } + + /* To refresh the expire timer value of a conntrack, + * linux 2.6.9 kernel starts using ip_ct_refresh_acct(), + * while older ones use ip_ct_refresh() + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) + ip_ct_refresh(ct, new_expires); +#else + ip_ct_refresh_acct(ct, 0, NULL, new_expires); +#endif + +#ifdef EXTRADEBUG + printk(KERN_WARNING + "ctexpire: enter = %ld/%ld, exit = %ld/%ld, diff = %ld\n", + enter, enter-jiffies, ct->timeout.expires, + ct->timeout.expires-jiffies, ct->timeout.expires - enter); +#endif + + return 0; +} + +static int +ipt_ctexpire_checkentry(const char *tablename, + const struct ipt_ip *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ctexpire_info))) { + printk(KERN_WARNING "ctexpire: targinfosize %u != %Zu\n", + matchsize, + IPT_ALIGN(sizeof(struct ipt_ctexpire_info))); + return 0; + } + + if (strcmp(tablename, "raw") == 0) { + printk(KERN_WARNING "ctexpire can't be used in the raw' table"); + return 0; + } + + return 1; +} + +static struct ipt_match ipt_ctexpire = { + .name = "ctexpire", + .match = ipt_ctexpire_match, + .checkentry = ipt_ctexpire_checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ipt_register_match(&ipt_ctexpire); +} + +static void __exit fini(void) +{ + ipt_unregister_match(&ipt_ctexpire); +} + +module_init(init); +module_exit(fini); + Index: linux/net/ipv4/netfilter/Config.in.ladd =================================================================== --- linux/net/ipv4/netfilter/Config.in.ladd (revision 0) +++ linux/net/ipv4/netfilter/Config.in.ladd (revision 0) @@ -0,0 +1,2 @@ + dep_tristate ' Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES + dep_tristate ' ctexpire match support' CONFIG_IP_NF_MATCH_CTEXPIRE $CONFIG_IP_NF_IPTABLES Index: linux/Documentation/Configure.help.ladd =================================================================== --- linux/Documentation/Configure.help.ladd (revision 0) +++ linux/Documentation/Configure.help.ladd (revision 0) @@ -0,0 +1,8 @@ +CONFIG_IP_NF_MATCH_STATE +ctexpire match support +CONFIG_IP_NF_MATCH_CTEXPIRE + This match allows you to set the conntrack expire value or + increment / decrement it by a given amount (in seconds). + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. Index: iptables/extensions/libipt_ctexpire.man =================================================================== --- iptables/extensions/libipt_ctexpire.man (revision 0) +++ iptables/extensions/libipt_ctexpire.man (revision 0) @@ -0,0 +1,12 @@ +This is used to modify the conntrack expire field. The conntrack expire field determines +how much time left (in seconds) for the conntrack. The conntrack will be deleted or changed +to a new state when the expire field reachs 0. +.TP +.BI "--ctexpire-set " "value" +Set the conntrack expire value to `value' (in seconds). +.TP +.BI "--ctexpire-dec " "value" +Decrement the conntrack expire value `value' (in seconds), i.e. make it live shorter. +.TP +.BI "--ctexpire-inc " "value" +Increment the conntrack expire value `value' (in seconds), i.e. make it live longer. Index: iptables/extensions/libipt_ctexpire.c =================================================================== --- iptables/extensions/libipt_ctexpire.c (revision 0) +++ iptables/extensions/libipt_ctexpire.c (revision 0) @@ -0,0 +1,199 @@ +/* Shared library add-on to iptables for the ctexpire match + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * $Id: libipt_ctexpire.c,v 1.0 2004/12/01 16:08:16 richard Exp $ + * + * 020105 Converted to match -- Pablo Neira Ayuso <pablo@eurodev.net> + * + * This program is distributed under the terms of GNU GPL version 2 + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <iptables.h> +#include <sys/param.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include "../include/linux/netfilter_ipv4/ipt_ctexpire.h" + +#define IPT_CTEXPIRE_USED 1 + +static void init(struct ipt_entry_match *t, unsigned int *nfcache) +{ +} + +static void help(void) +{ + printf( +"ctexpire match v%s options\n" +" --ctexpire-set value Set conntrack expire to <value>\n" +" --ctexpire-dec value Decrement conntrack expire by <value>\n" +" --ctexpire-inc value Increment conntrack expire by <value>\n" +, IPTABLES_VERSION); +} + +static int +parse(int c, char **argv, int invert, unsigned int *flags, + const struct ipt_entry *entry, + unsigned int *nfcache, + struct ipt_entry_match **match) +{ + struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) (*match)->data; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long value, HZ_value; +#else + unsigned long value, HZ_value; +#endif + + if (*flags & IPT_CTEXPIRE_USED) { + exit_error(PARAMETER_PROBLEM, + "Can't specify conntrack expire option twice"); + } + + if (!optarg) + exit_error(PARAMETER_PROBLEM, + "ctexpire: You must specify a value"); + + if (check_inverse(optarg, &invert, NULL, 0)) + exit_error(PARAMETER_PROBLEM, + "ctexpire: unexpected `!'"); + +#ifdef KERNEL_64_USERSPACE_32 + if (string_to_number_ll(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, + "expire value invalid: `%s'\n", optarg); +#else + if (string_to_number_l(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, + "expire value invalid: `%s'\n", optarg); +#endif + + HZ_value = value*HZ; + + if (HZ_value < value) { + /* if user specified value is too big, + * *HZ can overflow the counter + */ + exit_error(PARAMETER_PROBLEM, + "expire value too big, will overflow counter: `%s'\n", optarg); + } + + switch (c) { + case '1': + info->mode = IPT_CTEXPIRE_SET; + break; + + case '2': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "ctexpire: decreasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_DEC; + break; + + case '3': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "ctexpire: increasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_INC; + break; + + default: + return 0; + + } + + info->expires = value; + *flags |= IPT_CTEXPIRE_USED; + + return 1; +} + +static void final_check(unsigned int flags) +{ + if (!(flags & IPT_CTEXPIRE_USED)) + exit_error(PARAMETER_PROBLEM, + "ctexpire: You must specify an action"); +} + +static void save(const struct ipt_ip *ip, + const struct ipt_entry_match *match) +{ + const struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) match->data; + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("--ctexpire-set "); + break; + case IPT_CTEXPIRE_DEC: + printf("--ctexpire-dec "); + break; + + case IPT_CTEXPIRE_INC: + printf("--ctexpire-inc "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static void print(const struct ipt_ip *ip, + const struct ipt_entry_match *match, int numeric) +{ + const struct ipt_ctexpire_info *info = + (struct ipt_ctexpire_info *) match->data; + + printf("ctexpire "); + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("set to "); + break; + case IPT_CTEXPIRE_DEC: + printf("decrement by "); + break; + case IPT_CTEXPIRE_INC: + printf("increment by "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static struct option opts[] = { + { "ctexpire-set", 1, 0, '1' }, + { "ctexpire-dec", 1, 0, '2' }, + { "ctexpire-inc", 1, 0, '3' }, + { 0 } +}; + +static +struct iptables_match ipt_ctexpire = { + .name = "ctexpire", + .version = IPTABLES_VERSION, + .size = IPT_ALIGN(sizeof(struct ipt_ctexpire_info)), + .userspacesize = IPT_ALIGN(sizeof(struct ipt_ctexpire_info)), + .help = help, + .init = init, + .parse = parse, + .final_check = final_check, + .print = print, + .save = save, + .extra_opts = opts +}; + +void _init(void) +{ + register_match(&ipt_ctexpire); +} Index: iptables/extensions/.CTEXPIRE-test =================================================================== --- iptables/extensions/.CTEXPIRE-test (revision 0) +++ iptables/extensions/.CTEXPIRE-test (revision 0) @@ -0,0 +1,2 @@ +#! /bin/sh +[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_CTEXPIRE.c ] && echo CTEXPIRE Property changes on: iptables/extensions/.CTEXPIRE-test ___________________________________________________________________ Name: svn:executable + * Index: iptables/include/linux/netfilter_ipv4/ipt_ctexpire.h =================================================================== --- iptables/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) +++ iptables/include/linux/netfilter_ipv4/ipt_ctexpire.h (revision 0) @@ -0,0 +1,23 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_ctexpire_info { + u_int8_t mode; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long expires; +#else + unsigned long expires; +#endif +}; +#endif Index: help =================================================================== --- help (revision 0) +++ help (revision 0) @@ -0,0 +1,9 @@ +This adds an iptables ctexpire mtach, which enables the user +to set the expire value of a conntrack or to increment / decrement it by a +given value. + +Examples: + +# allow sip (udp 5060) streams to have 3600 second timeout +iptables -p udp -m udp --dport 5060 -m ctexpire --ctexpire-set 3600 -j ACCEPT +iptables -p udp -m udp --sport 5060 -m ctexpire --ctexpire-set 3600 -j ACCEPT Index: info =================================================================== --- info (revision 0) +++ info (revision 0) @@ -0,0 +1,3 @@ +Author: Richard Zheng <richard@o-matrix.org> +Status: Experiment +Repository: extra ^ permalink raw reply [flat|nested] 16+ messages in thread
* [NEW TARGET] target for modifying conntrack timeout value @ 2004-12-08 19:47 Richard 2004-12-08 20:09 ` Pablo Neira 0 siblings, 1 reply; 16+ messages in thread From: Richard @ 2004-12-08 19:47 UTC (permalink / raw) To: netfilter-devel [-- Attachment #1: Type: text/plain, Size: 170 bytes --] Hi, I sent this out a few days ago and got no reply. Thought that I should put a more obvious subject. I wonder if someone can include this into svn. Regards, Richard [-- Attachment #2: CTEXPIRE.diff.gz --] [-- Type: application/x-gzip, Size: 3458 bytes --] [-- Attachment #3: CTEXPIRE.tar.gz --] [-- Type: application/x-gzip, Size: 3890 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [NEW TARGET] target for modifying conntrack timeout value 2004-12-08 19:47 Richard @ 2004-12-08 20:09 ` Pablo Neira 2004-12-09 1:47 ` Richard 0 siblings, 1 reply; 16+ messages in thread From: Pablo Neira @ 2004-12-08 20:09 UTC (permalink / raw) To: Richard; +Cc: netfilter-devel Richard wrote: >I sent this out a few days ago and got no reply. Thought that I should put a >more obvious subject. > yes, now it's that obvious :) > I wonder if someone can include this into svn. > > OK, please next time post the patch clear text instead of a gzip, it's easier to review. In the meantime this is pushed to the SVN, we have to fix some problems. I just had a look at ipt_CTEXPIRE.c. Some comments: Index: CTEXPIRE/linux/net/ipv4/netfilter/ipt_CTEXPIRE.c =================================================================== --- CTEXPIRE/linux/net/ipv4/netfilter/ipt_CTEXPIRE.c (revision 0) +++ CTEXPIRE/linux/net/ipv4/netfilter/ipt_CTEXPIRE.c (revision 0) @@ -0,0 +1,176 @@ +/* CTEXPIRE modification target for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * Version: 1.0 + * + * This software is distributed under the terms of GNU GPL + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/checksum.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ipt_CTEXPIRE.h> +#include <linux/netfilter_ipv4/ip_conntrack.h> + +MODULE_AUTHOR("Richard Zheng <richard@o-matrix.org>"); +MODULE_DESCRIPTION("IP tables CTEXPIRE modification module"); +MODULE_LICENSE("GPL"); + +#undef DEBUG + +DECLARE_RWLOCK(ip_conntrack_lock); ^^^ ouch, you can't do that. +static unsigned int +ipt_ctexpire_target(struct sk_buff **pskb, + unsigned int hooknum, + const struct net_device *in, + const struct net_device *out, + const void *targinfo, + void *userinfo) + +{ + const struct ipt_CTEXPIRE_info *info = targinfo; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long new_expires; +#else + unsigned long new_expires; +#endif ^^^^^ that ifdef just makes sense in user space, remove it and leave it as "long". + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); + + + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); check if ct == NULL. In that case return 0. Invalid packets don't have a conntrack associated. + new_expires = info->expires*HZ; + + if (new_expires < info->expires) { + /* if user specified value is too big, *HZ can overflow the counter + * since it is big enough, just use the new value without *HZ + */ + new_expires = info->expires; ^^^ check this in user space + } + + WRITE_LOCK(&ip_conntrack_lock); + +#ifdef DEBUG + printk(KERN_WARNING "CTEXPIRE: fired = %s, mode %d, value %ld\n", + !is_confirmed(ct) ? "no" : "yes", info->mode, info->expires); + unsigned long enter = ct->timeout.expires; +#endif + + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) { + switch (info->mode) { + case IPT_CTEXPIRE_SET: + ct->timeout.expires = new_expires; ^^^ Hm I thought that I told you to use ip_ct_refresh... you should. Your target will look smarter and you can forget about proper locking... which is now completely broken... See your next email. -- Pablo ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [NEW TARGET] target for modifying conntrack timeout value 2004-12-08 20:09 ` Pablo Neira @ 2004-12-09 1:47 ` Richard 0 siblings, 0 replies; 16+ messages in thread From: Richard @ 2004-12-09 1:47 UTC (permalink / raw) To: 'Pablo Neira'; +Cc: netfilter-devel [-- Attachment #1: Type: text/plain, Size: 695 bytes --] > + ct->timeout.expires = new_expires; > ^^^ > > Hm I thought that I told you to use ip_ct_refresh... you should. Your > target will look smarter and you can forget about proper locking... > which is now completely broken... Hi Pablo, Thanks for the comments. I made the modification and attached the latest copy. Now it uses ip_ct_refresh. The target first reads the existing expire value, then modify it. If there is something in between, the expire value might get changed. Even worse, the conntrack state might change. That's why I locked it first, then read and write, finally unlock. If it is broken, there is no difference anyway... Regards, Richard [-- Attachment #2: CTEXPIRE.diff --] [-- Type: application/octet-stream, Size: 14468 bytes --] Index: CTEXPIRE/linux/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h =================================================================== --- CTEXPIRE/linux/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h (revision 0) +++ CTEXPIRE/linux/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h (revision 0) @@ -0,0 +1,19 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_CTEXPIRE_info { + u_int8_t mode; + unsigned long expires; +}; +#endif Index: CTEXPIRE/linux/net/ipv4/netfilter/Makefile.ladd =================================================================== --- CTEXPIRE/linux/net/ipv4/netfilter/Makefile.ladd (revision 0) +++ CTEXPIRE/linux/net/ipv4/netfilter/Makefile.ladd (revision 0) @@ -0,0 +1,2 @@ +obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o +obj-$(CONFIG_IP_NF_TARGET_CTEXPIRE) += ipt_CTEXPIRE.o Index: CTEXPIRE/linux/net/ipv4/netfilter/ipt_CTEXPIRE.c =================================================================== --- CTEXPIRE/linux/net/ipv4/netfilter/ipt_CTEXPIRE.c (revision 0) +++ CTEXPIRE/linux/net/ipv4/netfilter/ipt_CTEXPIRE.c (revision 0) @@ -0,0 +1,164 @@ +/* CTEXPIRE modification target for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * Version: 1.0 + * + * This software is distributed under the terms of GNU GPL + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/checksum.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ipt_CTEXPIRE.h> +#include <linux/netfilter_ipv4/ip_conntrack.h> + +MODULE_AUTHOR("Richard Zheng <richard@o-matrix.org>"); +MODULE_DESCRIPTION("IP tables CTEXPIRE modification module"); +MODULE_LICENSE("GPL"); + +#undef EXTRADEBUG + +static unsigned int +ipt_ctexpire_target(struct sk_buff **pskb, + unsigned int hooknum, + const struct net_device *in, + const struct net_device *out, + const void *targinfo, + void *userinfo) + +{ + const struct ipt_CTEXPIRE_info *info = targinfo; + unsigned long new_expires; + + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); + + if (ct == NULL) { + return IPT_CONTINUE; + } + + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); + + new_expires = info->expires*HZ; + +#ifdef EXTRADEBUG + printk(KERN_WARNING "CTEXPIRE: fired = %s, mode %d, value %ld\n", + !is_confirmed(ct) ? "no" : "yes", info->mode, info->expires); + unsigned long enter = ct->timeout.expires; +#endif + + /* If not in hash table, timer will not be active yet */ + if (!is_confirmed(ct)) { + switch (info->mode) { + case IPT_CTEXPIRE_SET: + break; + case IPT_CTEXPIRE_INC: + /* TODO should we check if counter overflow? + * other kernel function didn't check this + */ + new_expires += ct->timeout.expires; + break; + case IPT_CTEXPIRE_DEC: + new_expires = (ct->timeout.expires <= new_expires) ? + 0 : (ct->timeout.expires - new_expires); + break; + default: + break; + } + + } else { + /* Need del_timer for race avoidance (may already be dying). */ + switch (info->mode) { + case IPT_CTEXPIRE_SET: + break; + case IPT_CTEXPIRE_INC: + /* TODO should we check if counter overflow? + * other kernel function didn't check this + */ + new_expires += ct->timeout.expires - jiffies; + break; + case IPT_CTEXPIRE_DEC: + new_expires = + (ct->timeout.expires - jiffies <= new_expires) ? + 0 : (ct->timeout.expires - jiffies - new_expires); + break; + default: + break; + } + } + + + ip_ct_refresh(ct, new_expires); + +#ifdef EXTRADEBUG + printk(KERN_WARNING "CTEXPIRE: enter = %ld/%ld, exit = %ld/%ld, diff = %ld\n", + enter, enter-jiffies, ct->timeout.expires, + ct->timeout.expires-jiffies, ct->timeout.expires - enter); +#endif + + return IPT_CONTINUE; +} + +static int ipt_ctexpire_checkentry(const char *tablename, + const struct ipt_entry *e, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + struct ipt_CTEXPIRE_info *info = targinfo; + + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_CTEXPIRE_info))) { + printk(KERN_WARNING "CTEXPIRE: targinfosize %u != %Zu\n", + targinfosize, + IPT_ALIGN(sizeof(struct ipt_CTEXPIRE_info))); + return 0; + } + + if (strcmp(tablename, "mangle") && strcmp(tablename, "filter")) { + printk(KERN_WARNING "CTEXPIRE: can only be called from \"mangle\" or \"filter\" table, not \"%s\"\n", tablename); + return 0; + } + + if (info->mode > IPT_CTEXPIRE_MAXMODE) { + printk(KERN_WARNING "CTEXPIRE: invalid or unknown Mode %u\n", + info->mode); + return 0; + } + + if ((info->mode != IPT_CTEXPIRE_SET) && (info->expires == 0)) { + printk(KERN_WARNING "CTEXPIRE: increment/decrement doesn't make sense with value 0\n"); + return 0; + } + + if (info->expires * HZ < info->expires) { + /* if user specified value is too big, *HZ can overflow the counter + */ + printk(KERN_WARNING "CTEXPIRE: expire value too big, will overflow counter: %ld\n", info->expires); + return 0; + } + + return 1; +} + +static struct ipt_target ipt_CTEXPIRE = { + .name = "CTEXPIRE", + .target = &ipt_ctexpire_target, + .checkentry = &ipt_ctexpire_checkentry, + .me = THIS_MODULE +}; + +static int __init init(void) +{ + return ipt_register_target(&ipt_CTEXPIRE); +} + +static void __exit fini(void) +{ + ipt_unregister_target(&ipt_CTEXPIRE); +} + +module_init(init); +module_exit(fini); Index: CTEXPIRE/linux/net/ipv4/netfilter/Config.in.ladd =================================================================== --- CTEXPIRE/linux/net/ipv4/netfilter/Config.in.ladd (revision 0) +++ CTEXPIRE/linux/net/ipv4/netfilter/Config.in.ladd (revision 0) @@ -0,0 +1,2 @@ + dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES + dep_tristate ' CTEXPIRE target support' CONFIG_IP_NF_TARGET_CTEXPIRE $CONFIG_IP_NF_IPTABLES Index: CTEXPIRE/linux/Documentation/Configure.help.ladd =================================================================== --- CTEXPIRE/linux/Documentation/Configure.help.ladd (revision 0) +++ CTEXPIRE/linux/Documentation/Configure.help.ladd (revision 0) @@ -0,0 +1,9 @@ +CONFIG_IP_NF_TARGET_LOG +CTEXPIRE target support +CONFIG_IP_NF_TARGET_CTEXPIRE + This option adds a `CTEXPIRE' target, which enables the user to set + the conntrack expire value or increment / decrement it by a given + amount (in seconds). + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. Index: CTEXPIRE/iptables/extensions/libipt_CTEXPIRE.man =================================================================== --- CTEXPIRE/iptables/extensions/libipt_CTEXPIRE.man (revision 0) +++ CTEXPIRE/iptables/extensions/libipt_CTEXPIRE.man (revision 0) @@ -0,0 +1,12 @@ +This is used to modify the conntrack expire field. The conntrack expire field determines +how much time left (in seconds) for the conntrack. The conntrack will be deleted or changed +to a new state when the expire field reachs 0. +.TP +.BI "--ctexpire-set " "value" +Set the conntrack expire value to `value' (in seconds). +.TP +.BI "--ctexpire-dec " "value" +Decrement the conntrack expire value `value' (in seconds), i.e. make it live shorter. +.TP +.BI "--ctexpire-inc " "value" +Increment the conntrack expire value `value' (in seconds), i.e. make it live longer. Index: CTEXPIRE/iptables/extensions/libipt_CTEXPIRE.c =================================================================== --- CTEXPIRE/iptables/extensions/libipt_CTEXPIRE.c (revision 0) +++ CTEXPIRE/iptables/extensions/libipt_CTEXPIRE.c (revision 0) @@ -0,0 +1,192 @@ +/* Shared library add-on to iptables for the CTEXPIRE target + * (C) 2004 by Richard Zheng <richard@o-matrix.org> + * + * $Id: libipt_CTEXPIRE.c,v 1.0 2004/12/01 16:08:16 richard Exp $ + * + * This program is distributed under the terms of GNU GPL + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <iptables.h> +#include <sys/param.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ipt_CTEXPIRE.h> + +#define IPT_CTEXPIRE_USED 1 + +static void init(struct ipt_entry_target *t, unsigned int *nfcache) +{ +} + +static void help(void) +{ + printf( +"CTEXPIRE target v%s options\n" +" --ctexpire-set value Set conntrack expire to <value>\n" +" --ctexpire-dec value Decrement conntrack expire by <value>\n" +" --ctexpire-inc value Increment conntrack expire by <value>\n" +, IPTABLES_VERSION); +} + +static int parse(int c, char **argv, int invert, unsigned int *flags, + const struct ipt_entry *entry, + struct ipt_entry_target **target) +{ + struct ipt_CTEXPIRE_info *info = (struct ipt_CTEXPIRE_info *) (*target)->data; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long value, HZ_value; +#else + unsigned long value, HZ_value; +#endif + + if (*flags & IPT_CTEXPIRE_USED) { + exit_error(PARAMETER_PROBLEM, + "Can't specify conntrack expire option twice"); + } + + if (!optarg) + exit_error(PARAMETER_PROBLEM, + "CTEXPIRE: You must specify a value"); + + if (check_inverse(optarg, &invert, NULL, 0)) + exit_error(PARAMETER_PROBLEM, + "CTEXPIRE: unexpected `!'"); + +#ifdef KERNEL_64_USERSPACE_32 + if (string_to_number_ll(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, "expire value invalid: `%s'\n", optarg); +#else + if (string_to_number_l(optarg, 0, 0, &value) == -1) + exit_error(PARAMETER_PROBLEM, "expire value invalid: `%s'\n", optarg); +#endif + + HZ_value = value*HZ; + + if (HZ_value < value) { + /* if user specified value is too big, *HZ can overflow the counter + */ + exit_error(PARAMETER_PROBLEM, "expire value too big, will overflow counter: `%s'\n", optarg); + } + + + switch (c) { + + case '1': + info->mode = IPT_CTEXPIRE_SET; + break; + + case '2': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "CTEXPIRE: decreasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_DEC; + break; + + case '3': + if (value == 0) { + exit_error(PARAMETER_PROBLEM, + "CTEXPIRE: increasing by 0?"); + } + + info->mode = IPT_CTEXPIRE_INC; + break; + + default: + return 0; + + } + + info->expires = value; + *flags |= IPT_CTEXPIRE_USED; + + return 1; +} + +static void final_check(unsigned int flags) +{ + if (!(flags & IPT_CTEXPIRE_USED)) + exit_error(PARAMETER_PROBLEM, + "CTEXPIRE: You must specify an action"); +} + +static void save(const struct ipt_ip *ip, + const struct ipt_entry_target *target) +{ + const struct ipt_CTEXPIRE_info *info = + (struct ipt_CTEXPIRE_info *) target->data; + + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("--ctexpire-set "); + break; + case IPT_CTEXPIRE_DEC: + printf("--ctexpire-dec "); + break; + + case IPT_CTEXPIRE_INC: + printf("--ctexpire-inc "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static void print(const struct ipt_ip *ip, + const struct ipt_entry_target *target, int numeric) +{ + const struct ipt_CTEXPIRE_info *info = + (struct ipt_CTEXPIRE_info *) target->data; + + printf("CTEXPIRE "); + switch (info->mode) { + case IPT_CTEXPIRE_SET: + printf("set to "); + break; + case IPT_CTEXPIRE_DEC: + printf("decrement by "); + break; + case IPT_CTEXPIRE_INC: + printf("increment by "); + break; + } +#ifdef KERNEL_64_USERSPACE_32 + printf("%llu ", info->expires); +#else + printf("%lu ", info->expires); +#endif +} + +static struct option opts[] = { + { "ctexpire-set", 1, 0, '1' }, + { "ctexpire-dec", 1, 0, '2' }, + { "ctexpire-inc", 1, 0, '3' }, + { 0 } +}; + +static +struct iptables_target CTEXPIRE = { NULL, + "CTEXPIRE", + IPTABLES_VERSION, + IPT_ALIGN(sizeof(struct ipt_CTEXPIRE_info)), + IPT_ALIGN(sizeof(struct ipt_CTEXPIRE_info)), + &help, + &init, + &parse, + &final_check, + &print, + &save, + opts +}; + +void _init(void) +{ + register_target(&CTEXPIRE); +} Index: CTEXPIRE/iptables/extensions/.CTEXPIRE-test =================================================================== --- CTEXPIRE/iptables/extensions/.CTEXPIRE-test (revision 0) +++ CTEXPIRE/iptables/extensions/.CTEXPIRE-test (revision 0) @@ -0,0 +1,2 @@ +#! /bin/sh +[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_CTEXPIRE.c ] && echo CTEXPIRE Property changes on: CTEXPIRE/iptables/extensions/.CTEXPIRE-test ___________________________________________________________________ Name: svn:executable + * Index: CTEXPIRE/iptables/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h =================================================================== --- CTEXPIRE/iptables/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h (revision 0) +++ CTEXPIRE/iptables/include/linux/netfilter_ipv4/ipt_CTEXPIRE.h (revision 0) @@ -0,0 +1,24 @@ +/* CTEXPIRE modification module for IP tables + * (C) 2004 by Richard Zheng <richard@o-matrix.org> */ + +#ifndef _IPT_CTEXPIRE_H +#define _IPT_CTEXPIRE_H + +enum { + IPT_CTEXPIRE_SET = 0, + IPT_CTEXPIRE_INC, + IPT_CTEXPIRE_DEC +}; + +#define IPT_CTEXPIRE_MAXMODE IPT_CTEXPIRE_DEC + +struct ipt_CTEXPIRE_info { + u_int8_t mode; +#ifdef KERNEL_64_USERSPACE_32 + unsigned long long expires; +#else + unsigned long expires; +#endif + +}; +#endif Index: CTEXPIRE/help =================================================================== --- CTEXPIRE/help (revision 0) +++ CTEXPIRE/help (revision 0) @@ -0,0 +1,3 @@ +This adds an iptables CTEXPIRE manipulation target, which enables the user +to set the expire value of a conntrack or to increment / decrement it by a +given value. Index: CTEXPIRE/info =================================================================== --- CTEXPIRE/info (revision 0) +++ CTEXPIRE/info (revision 0) @@ -0,0 +1,3 @@ +Author: Richard Zheng <richard@o-matrix.org> +Status: Expirement +Repository: extra ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2005-01-02 22:24 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2004-12-13 21:10 [NEW TARGET] target for modifying conntrack timeout value Richard 2004-12-13 21:14 ` Pablo Neira 2004-12-15 0:25 ` Pablo Neira 2004-12-15 1:16 ` Richard 2004-12-15 19:38 ` Pablo Neira 2004-12-17 18:10 ` Richard 2005-01-02 0:22 ` Pablo Neira 2005-01-02 9:11 ` Richard 2005-01-02 13:15 ` Pablo Neira 2005-01-02 19:12 ` Richard 2005-01-02 19:35 ` Tom Marshall 2005-01-02 19:42 ` Richard 2005-01-02 22:24 ` Richard -- strict thread matches above, loose matches on Subject: below -- 2004-12-08 19:47 Richard 2004-12-08 20:09 ` Pablo Neira 2004-12-09 1:47 ` Richard
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.