On Sunday 2008-10-05 16:33, Jan Engelhardt wrote: >On Sunday 2008-10-05 16:28, David Miller wrote: >>> On Sun, 5 Oct 2008, Jan Engelhardt wrote: >>> >>> > I'd like to go for $(always lowercase extension name)_{mt,tg}.c if >>> > noone objects. >>> > Or, when obvious extensions get combined maybe (like xt_mark and xt_MARK), >>> > just mark.c and the issue is all gone. >>> >>> I think match/target combined in one file is the best way to go. As they >>> cover the same realm (match some quantity of something and change it), >>> they do fit together. >> >>This also makes sense to me. > >Before I start moving code, would we may want to combine more modules >into one file at this point besides xt_FOO and xt_foo only? (Probably not.) Funny thing is, only when you try you see more problems a-coming. Like, Kconfig option names. Keep/Lose NETFILTER_XT_{MATCH,TARGET}_CONNMARK, and query users for a new one? Dunno. Sample patch below. As for memory saving, the combined module weighs in at 4928 bytes, whereas previously it took 5632 (2496+3136). Solid win of 12.50000%! commit 1143a39a1f76331bf47bee6b63fded9fb5227e4b parent 13992bcb338f0044010a1809f24d2198b5bd91c8 parenturl git://dev.medozas.de/linux master Author: Jan Engelhardt <jengelh@xxxxxxxxxx> Date: Sun Oct 5 16:46:52 2008 -0400 netfilter: xtables: combine xt_connmark target and match Signed-off-by: Jan Engelhardt <jengelh@xxxxxxxxxx> --- net/netfilter/Kconfig | 40 ++----- net/netfilter/Makefile | 3 +- net/netfilter/xt_CONNMARK.c | 225 ----------------------------------- net/netfilter/xt_connmark.c | 206 +++++++++++++++++++++++++++++++- 4 files changed, 212 insertions(+), 262 deletions(-) delete mode 100644 net/netfilter/xt_CONNMARK.c diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 899e780..bc65b31 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -302,6 +302,18 @@ config NETFILTER_XTABLES if NETFILTER_XTABLES +# alphabetically ordered list of match/target combos + +config NETFILTER_XT_CONNMARK + tristate '"CONNMARK" extensions' + depends on NF_CONNTRACK + depends on NETFILTER_ADVANCED + select NF_CONNTRACK_MARK + ---help--- + This option adds support for manipulating and matching the + connection mark value. It is similar to the packet mark, but + is per-connection. + # alphabetically ordered list of targets config NETFILTER_XT_TARGET_CLASSIFY @@ -316,21 +328,6 @@ config NETFILTER_XT_TARGET_CLASSIFY To compile it as a module, choose M here. If unsure, say N. -config NETFILTER_XT_TARGET_CONNMARK - tristate '"CONNMARK" target support' - depends on IP_NF_MANGLE || IP6_NF_MANGLE - depends on NF_CONNTRACK - depends on NETFILTER_ADVANCED - select NF_CONNTRACK_MARK - help - This option adds a `CONNMARK' target, which allows one to manipulate - the connection mark value. Similar to the MARK target, but - affects the connection mark value rather than the packet mark value. - - If you want to compile it as a module, say M here and read - <file:Documentation/kbuild/modules.txt>. The module will be called - ipt_CONNMARK.ko. If unsure, say `N'. - config NETFILTER_XT_TARGET_CONNSECMARK tristate '"CONNSECMARK" target support' depends on NF_CONNTRACK && NF_CONNTRACK_SECMARK @@ -521,19 +518,6 @@ config NETFILTER_XT_MATCH_CONNLIMIT This match allows you to match against the number of parallel connections to a server per client IP address (or address block). -config NETFILTER_XT_MATCH_CONNMARK - tristate '"connmark" connection mark match support' - depends on NF_CONNTRACK - depends on NETFILTER_ADVANCED - select NF_CONNTRACK_MARK - help - This option adds a `connmark' match, which allows you to match the - connection mark value previously set for the session by `CONNMARK'. - - If you want to compile it as a module, say M here and read - <file:Documentation/kbuild/modules.txt>. The module will be called - ipt_connmark.ko. If unsure, say `N'. - config NETFILTER_XT_MATCH_CONNTRACK tristate '"conntrack" connection tracking match support' depends on NF_CONNTRACK diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 8ce6766..62f48df 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -39,10 +39,10 @@ obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o # generic X tables obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o +obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o # targets obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o -obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o @@ -60,7 +60,6 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o -obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c deleted file mode 100644 index d6e5ab4..0000000 --- a/net/netfilter/xt_CONNMARK.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * xt_CONNMARK - Netfilter module to modify the connection mark values - * - * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> - * by Henrik Nordstrom <hno@xxxxxxxxxxxxxxx> - * Copyright © CC Computer Consultants GmbH, 2007 - 2008 - * Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/module.h> -#include <linux/skbuff.h> -#include <linux/ip.h> -#include <net/checksum.h> - -MODULE_AUTHOR("Henrik Nordstrom <hno@xxxxxxxxxxxxxxx>"); -MODULE_DESCRIPTION("Xtables: connection mark modification"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_CONNMARK"); -MODULE_ALIAS("ip6t_CONNMARK"); - -#include <linux/netfilter/x_tables.h> -#include <linux/netfilter/xt_CONNMARK.h> -#include <net/netfilter/nf_conntrack_ecache.h> - -static unsigned int -connmark_tg_v0(struct sk_buff *skb, const struct xt_target_param *par) -{ - const struct xt_connmark_target_info *markinfo = par->targinfo; - struct nf_conn *ct; - enum ip_conntrack_info ctinfo; - u_int32_t diff; - u_int32_t mark; - u_int32_t newmark; - - ct = nf_ct_get(skb, &ctinfo); - if (ct) { - switch(markinfo->mode) { - case XT_CONNMARK_SET: - newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; - if (newmark != ct->mark) { - ct->mark = newmark; - nf_conntrack_event_cache(IPCT_MARK, ct); - } - break; - case XT_CONNMARK_SAVE: - newmark = (ct->mark & ~markinfo->mask) | - (skb->mark & markinfo->mask); - if (ct->mark != newmark) { - ct->mark = newmark; - nf_conntrack_event_cache(IPCT_MARK, ct); - } - break; - case XT_CONNMARK_RESTORE: - mark = skb->mark; - diff = (ct->mark ^ mark) & markinfo->mask; - skb->mark = mark ^ diff; - break; - } - } - - return XT_CONTINUE; -} - -static unsigned int -connmark_tg(struct sk_buff *skb, const struct xt_target_param *par) -{ - const struct xt_connmark_tginfo1 *info = par->targinfo; - enum ip_conntrack_info ctinfo; - struct nf_conn *ct; - u_int32_t newmark; - - ct = nf_ct_get(skb, &ctinfo); - if (ct == NULL) - return XT_CONTINUE; - - switch (info->mode) { - case XT_CONNMARK_SET: - newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; - if (ct->mark != newmark) { - ct->mark = newmark; - nf_conntrack_event_cache(IPCT_MARK, ct); - } - break; - case XT_CONNMARK_SAVE: - newmark = (ct->mark & ~info->ctmask) ^ - (skb->mark & info->nfmask); - if (ct->mark != newmark) { - ct->mark = newmark; - nf_conntrack_event_cache(IPCT_MARK, ct); - } - break; - case XT_CONNMARK_RESTORE: - newmark = (skb->mark & ~info->nfmask) ^ - (ct->mark & info->ctmask); - skb->mark = newmark; - break; - } - - return XT_CONTINUE; -} - -static bool connmark_tg_check_v0(const struct xt_tgchk_param *par) -{ - const struct xt_connmark_target_info *matchinfo = par->targinfo; - - if (matchinfo->mode == XT_CONNMARK_RESTORE) { - if (strcmp(par->table, "mangle") != 0) { - printk(KERN_WARNING "CONNMARK: restore can only be " - "called from \"mangle\" table, not \"%s\"\n", - par->table); - return false; - } - } - if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) { - printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n"); - return false; - } - if (nf_ct_l3proto_try_module_get(par->family) < 0) { - printk(KERN_WARNING "can't load conntrack support for " - "proto=%u\n", par->family); - return false; - } - return true; -} - -static bool connmark_tg_check(const struct xt_tgchk_param *par) -{ - if (nf_ct_l3proto_try_module_get(par->family) < 0) { - printk(KERN_WARNING "cannot load conntrack support for " - "proto=%u\n", par->family); - return false; - } - return true; -} - -static void connmark_tg_destroy(const struct xt_tgdtor_param *par) -{ - nf_ct_l3proto_module_put(par->family); -} - -#ifdef CONFIG_COMPAT -struct compat_xt_connmark_target_info { - compat_ulong_t mark, mask; - u_int8_t mode; - u_int8_t __pad1; - u_int16_t __pad2; -}; - -static void connmark_tg_compat_from_user_v0(void *dst, void *src) -{ - const struct compat_xt_connmark_target_info *cm = src; - struct xt_connmark_target_info m = { - .mark = cm->mark, - .mask = cm->mask, - .mode = cm->mode, - }; - memcpy(dst, &m, sizeof(m)); -} - -static int connmark_tg_compat_to_user_v0(void __user *dst, void *src) -{ - const struct xt_connmark_target_info *m = src; - struct compat_xt_connmark_target_info cm = { - .mark = m->mark, - .mask = m->mask, - .mode = m->mode, - }; - return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; -} -#endif /* CONFIG_COMPAT */ - -static struct xt_target connmark_tg_reg[] __read_mostly = { - { - .name = "CONNMARK", - .revision = 0, - .family = NFPROTO_UNSPEC, - .checkentry = connmark_tg_check_v0, - .destroy = connmark_tg_destroy, - .target = connmark_tg_v0, - .targetsize = sizeof(struct xt_connmark_target_info), -#ifdef CONFIG_COMPAT - .compatsize = sizeof(struct compat_xt_connmark_target_info), - .compat_from_user = connmark_tg_compat_from_user_v0, - .compat_to_user = connmark_tg_compat_to_user_v0, -#endif - .me = THIS_MODULE - }, - { - .name = "CONNMARK", - .revision = 1, - .family = NFPROTO_UNSPEC, - .checkentry = connmark_tg_check, - .target = connmark_tg, - .targetsize = sizeof(struct xt_connmark_tginfo1), - .destroy = connmark_tg_destroy, - .me = THIS_MODULE, - }, -}; - -static int __init connmark_tg_init(void) -{ - return xt_register_targets(connmark_tg_reg, - ARRAY_SIZE(connmark_tg_reg)); -} - -static void __exit connmark_tg_exit(void) -{ - xt_unregister_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg)); -} - -module_init(connmark_tg_init); -module_exit(connmark_tg_exit); diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c index 86cacab..bcfad86 100644 --- a/net/netfilter/xt_connmark.c +++ b/net/netfilter/xt_connmark.c @@ -26,12 +26,16 @@ #include <net/netfilter/nf_conntrack.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter/xt_connmark.h> +#include <linux/netfilter/xt_CONNMARK.h> +#include <net/netfilter/nf_conntrack_ecache.h> MODULE_AUTHOR("Henrik Nordstrom <hno@xxxxxxxxxxxxxxx>"); -MODULE_DESCRIPTION("Xtables: connection mark match"); +MODULE_DESCRIPTION("Xtables: connection mark match and modification"); MODULE_LICENSE("GPL"); MODULE_ALIAS("ipt_connmark"); MODULE_ALIAS("ip6t_connmark"); +MODULE_ALIAS("ipt_CONNMARK"); +MODULE_ALIAS("ip6t_CONNMARK"); static bool connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par) @@ -92,6 +96,122 @@ static void connmark_mt_destroy(const struct xt_mtdtor_param *par) nf_ct_l3proto_module_put(par->family); } +static unsigned int +connmark_tg_v0(struct sk_buff *skb, const struct xt_target_param *par) +{ + const struct xt_connmark_target_info *markinfo = par->targinfo; + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + u_int32_t diff; + u_int32_t mark; + u_int32_t newmark; + + ct = nf_ct_get(skb, &ctinfo); + if (ct) { + switch(markinfo->mode) { + case XT_CONNMARK_SET: + newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; + if (newmark != ct->mark) { + ct->mark = newmark; + nf_conntrack_event_cache(IPCT_MARK, ct); + } + break; + case XT_CONNMARK_SAVE: + newmark = (ct->mark & ~markinfo->mask) | + (skb->mark & markinfo->mask); + if (ct->mark != newmark) { + ct->mark = newmark; + nf_conntrack_event_cache(IPCT_MARK, ct); + } + break; + case XT_CONNMARK_RESTORE: + mark = skb->mark; + diff = (ct->mark ^ mark) & markinfo->mask; + skb->mark = mark ^ diff; + break; + } + } + + return XT_CONTINUE; +} + +static unsigned int +connmark_tg(struct sk_buff *skb, const struct xt_target_param *par) +{ + const struct xt_connmark_tginfo1 *info = par->targinfo; + enum ip_conntrack_info ctinfo; + struct nf_conn *ct; + u_int32_t newmark; + + ct = nf_ct_get(skb, &ctinfo); + if (ct == NULL) + return XT_CONTINUE; + + switch (info->mode) { + case XT_CONNMARK_SET: + newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; + if (ct->mark != newmark) { + ct->mark = newmark; + nf_conntrack_event_cache(IPCT_MARK, ct); + } + break; + case XT_CONNMARK_SAVE: + newmark = (ct->mark & ~info->ctmask) ^ + (skb->mark & info->nfmask); + if (ct->mark != newmark) { + ct->mark = newmark; + nf_conntrack_event_cache(IPCT_MARK, ct); + } + break; + case XT_CONNMARK_RESTORE: + newmark = (skb->mark & ~info->nfmask) ^ + (ct->mark & info->ctmask); + skb->mark = newmark; + break; + } + + return XT_CONTINUE; +} + +static bool connmark_tg_check_v0(const struct xt_tgchk_param *par) +{ + const struct xt_connmark_target_info *matchinfo = par->targinfo; + + if (matchinfo->mode == XT_CONNMARK_RESTORE) { + if (strcmp(par->table, "mangle") != 0) { + printk(KERN_WARNING "CONNMARK: restore can only be " + "called from \"mangle\" table, not \"%s\"\n", + par->table); + return false; + } + } + if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) { + printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n"); + return false; + } + if (nf_ct_l3proto_try_module_get(par->family) < 0) { + printk(KERN_WARNING "can't load conntrack support for " + "proto=%u\n", par->family); + return false; + } + return true; +} + +static bool connmark_tg_check(const struct xt_tgchk_param *par) +{ + if (nf_ct_l3proto_try_module_get(par->family) < 0) { + printk(KERN_WARNING "cannot load conntrack support for " + "proto=%u\n", par->family); + return false; + } + return true; +} + +static void connmark_tg_destroy(const struct xt_tgdtor_param *par) +{ + nf_ct_l3proto_module_put(par->family); +} + #ifdef CONFIG_COMPAT struct compat_xt_connmark_info { compat_ulong_t mark, mask; @@ -100,6 +220,13 @@ struct compat_xt_connmark_info { u_int16_t __pad2; }; +struct compat_xt_connmark_target_info { + compat_ulong_t mark, mask; + u_int8_t mode; + u_int8_t __pad1; + u_int16_t __pad2; +}; + static void connmark_mt_compat_from_user_v0(void *dst, void *src) { const struct compat_xt_connmark_info *cm = src; @@ -121,6 +248,28 @@ static int connmark_mt_compat_to_user_v0(void __user *dst, void *src) }; return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; } + +static void connmark_tg_compat_from_user_v0(void *dst, void *src) +{ + const struct compat_xt_connmark_target_info *cm = src; + struct xt_connmark_target_info m = { + .mark = cm->mark, + .mask = cm->mask, + .mode = cm->mode, + }; + memcpy(dst, &m, sizeof(m)); +} + +static int connmark_tg_compat_to_user_v0(void __user *dst, void *src) +{ + const struct xt_connmark_target_info *m = src; + struct compat_xt_connmark_target_info cm = { + .mark = m->mark, + .mask = m->mask, + .mode = m->mode, + }; + return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; +} #endif /* CONFIG_COMPAT */ static struct xt_match connmark_mt_reg[] __read_mostly = { @@ -151,16 +300,59 @@ static struct xt_match connmark_mt_reg[] __read_mostly = { }, }; -static int __init connmark_mt_init(void) +static struct xt_target connmark_tg_reg[] __read_mostly = { + { + .name = "CONNMARK", + .revision = 0, + .family = NFPROTO_UNSPEC, + .checkentry = connmark_tg_check_v0, + .destroy = connmark_tg_destroy, + .target = connmark_tg_v0, + .targetsize = sizeof(struct xt_connmark_target_info), +#ifdef CONFIG_COMPAT + .compatsize = sizeof(struct compat_xt_connmark_target_info), + .compat_from_user = connmark_tg_compat_from_user_v0, + .compat_to_user = connmark_tg_compat_to_user_v0, +#endif + .me = THIS_MODULE + }, + { + .name = "CONNMARK", + .revision = 1, + .family = NFPROTO_UNSPEC, + .checkentry = connmark_tg_check, + .target = connmark_tg, + .targetsize = sizeof(struct xt_connmark_tginfo1), + .destroy = connmark_tg_destroy, + .me = THIS_MODULE, + }, +}; + +static int __init xt_connmark_init(void) { - return xt_register_matches(connmark_mt_reg, - ARRAY_SIZE(connmark_mt_reg)); + int ret; + + ret = xt_register_matches(connmark_mt_reg, + ARRAY_SIZE(connmark_mt_reg)); + if (ret < 0) + return ret; + + ret = xt_register_targets(connmark_tg_reg, + ARRAY_SIZE(connmark_tg_reg)); + if (ret < 0) { + xt_unregister_matches(connmark_mt_reg, + ARRAY_SIZE(connmark_mt_reg)); + return ret; + } + + return 0; } -static void __exit connmark_mt_exit(void) +static void __exit xt_connmark_exit(void) { xt_unregister_matches(connmark_mt_reg, ARRAY_SIZE(connmark_mt_reg)); + xt_unregister_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg)); } -module_init(connmark_mt_init); -module_exit(connmark_mt_exit); +module_init(xt_connmark_init); +module_exit(xt_connmark_exit); -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html