On Monday 25 February 2002 09:51, Harald Welte wrote: > Well, as you know, it is now resolved - the mangle5hooks patch has > made it into 2.4.18-preX and is definitely working since > 2.4.18-rc1.
I am not referring to what hooks mangle shold hook into, but it's priorities. When I last proposed this patch your were thinking of moving mangle infront of conntrack, to be able to exclude packets from conntrack I think. Moving mangle infront of conntrack breaks parts of this patch as the most common use of this patch is to mark packets on their conntrack entry for use in routing. > > I would certainly not mind having it in patch-o-matic/extra if > > possible. > > sure. Please send me a patch to put it cleanly in patch-o-matic. > Thanks. Attached. The .??*-test and libipt_* files goes into extensions (4 in total, one match and one target), the CONNMARK.* files into patch-o-matic (8 in total). Regards Henrik
.connmark-test
Description: extensions/.connmark-test condition on when to build the connmark userspace match module
/* Shared library add-on to iptables to add CONNMARK matching support. */ #include <stdio.h> #include <netdb.h> #include <string.h> #include <stdlib.h> #include <getopt.h> #include <iptables.h> #include <linux/netfilter_ipv4/ipt_connmark.h> /* Function which prints out usage message. */ static void help(void) { printf( "CONNMARK match v%s options:\n" "[!] --mark value[/mask] Match nfmark value with optional mask\n" "\n", NETFILTER_VERSION); } static struct option opts[] = { { "mark", 1, 0, '1' }, {0} }; /* Initialize the match. */ static void init(struct ipt_entry_match *m, unsigned int *nfcache) { /* Can't cache this. */ *nfcache |= NFC_UNKNOWN; } /* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, unsigned int *nfcache, struct ipt_entry_match **match) { struct ipt_connmark_info *markinfo = (struct ipt_connmark_info *)(*match)->data; switch (c) { char *end; case '1': if (check_inverse(optarg, &invert)) optind++; markinfo->mark = strtoul(optarg, &end, 0); if (*end == '/') { markinfo->mask = strtoul(end+1, &end, 0); } else markinfo->mask = 0xffffffff; if (*end != '\0' || end == optarg) exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg); if (invert) markinfo->invert = 1; *flags = 1; break; default: return 0; } return 1; } static void print_mark(unsigned long mark, unsigned long mask, int invert, int numeric) { if (invert) fputc('!', stdout); if(mask != 0xffffffff) printf("0x%lx/0x%lx ", mark, mask); else printf("0x%lx ", mark); } /* Final check; must have specified --mark. */ static void final_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, "MARK match: You must specify `--mark'"); } /* Prints out the matchinfo. */ static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric) { printf("CONNMARK match "); print_mark(((struct ipt_connmark_info *)match->data)->mark, ((struct ipt_connmark_info *)match->data)->mask, ((struct ipt_connmark_info *)match->data)->invert, numeric); } /* Saves the union ipt_matchinfo in parsable form to stdout. */ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) { printf("--mark "); print_mark(((struct ipt_connmark_info *)match->data)->mark, ((struct ipt_connmark_info *)match->data)->mask, ((struct ipt_connmark_info *)match->data)->invert, 0); } struct iptables_match mark = { NULL, "connmark", NETFILTER_VERSION, IPT_ALIGN(sizeof(struct ipt_connmark_info)), IPT_ALIGN(sizeof(struct ipt_connmark_info)), &help, &init, &parse, &final_check, &print, &save, opts }; void _init(void) { register_match(&mark); }
.CONNMARK-test
Description: extensions/.CONNMARK-test userspace test on when to build the userspace CONNMARK target module
/* Shared library add-on to iptables to add CONNMARK target support. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <getopt.h> #include <iptables.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_CONNMARK.h> #if 0 struct markinfo { struct ipt_entry_target t; struct ipt_connmark_target_info mark; }; #endif /* Function which prints out usage message. */ static void help(void) { printf( "CONNMARK target v%s options:\n" " --set-mark value Set conntrack mark value\n" " --save-mark Save the packet nfmark on the connection\n" " --restore-mark Restore saved nfmark value\n" "\n", NETFILTER_VERSION); } static struct option opts[] = { { "set-mark", 1, 0, '1' }, { "save-mark", 0, 0, '2' }, { "restore-mark", 0, 0, '3' }, { 0 } }; /* Initialize the target. */ static void init(struct ipt_entry_target *t, unsigned int *nfcache) { } /* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct ipt_entry_target **target) { struct ipt_connmark_target_info *markinfo = (struct ipt_connmark_target_info *)(*target)->data; switch (c) { char *end; case '1': markinfo->mode = IPT_CONNMARK_SET; markinfo->mark = strtoul(optarg, &end, 0); if (*end != '\0' || end == optarg) exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg); if (*flags) exit_error(PARAMETER_PROBLEM, "CONNMARK target: Can't specify --set-mark twice"); *flags = 1; break; case '2': markinfo->mode = IPT_CONNMARK_SAVE; if (*flags) exit_error(PARAMETER_PROBLEM, "CONNMARK target: Can't specify --save-mark twice"); *flags = 1; break; case '3': markinfo->mode = IPT_CONNMARK_RESTORE; if (*flags) exit_error(PARAMETER_PROBLEM, "CONNMARK target: Can't specify --restore-mark twice"); *flags = 1; break; default: return 0; } return 1; } static void final_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, "CONNMARK target: Parameter --set-mark is required"); } static void print_mark(unsigned long mark, int numeric) { printf("0x%lx ", mark); } /* Prints out the targinfo. */ static void print(const struct ipt_ip *ip, const struct ipt_entry_target *target, int numeric) { const struct ipt_connmark_target_info *markinfo = (const struct ipt_connmark_target_info *)target->data; switch (markinfo->mode) { case IPT_CONNMARK_SET: printf("CONNMARK set "); print_mark(markinfo->mark, numeric); break; case IPT_CONNMARK_SAVE: printf("CONNMARK save "); break; case IPT_CONNMARK_RESTORE: printf("CONNMARK restore "); break; default: printf("ERROR: UNKNOWN CONNMARK MODE "); break; } } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target) { const struct ipt_connmark_target_info *markinfo = (const struct ipt_connmark_target_info *)target->data; switch (markinfo->mode) { case IPT_CONNMARK_SET: printf("--set-mark 0x%lx ", markinfo->mark); break; case IPT_CONNMARK_SAVE: printf("--save-mark "); break; case IPT_CONNMARK_RESTORE: printf("--restore-mark "); break; default: printf("ERROR: UNKNOWN CONNMARK MODE "); break; } } struct iptables_target mark = { NULL, "CONNMARK", NETFILTER_VERSION, IPT_ALIGN(sizeof(struct ipt_connmark_target_info)), IPT_ALIGN(sizeof(struct ipt_connmark_target_info)), &help, &init, &parse, &final_check, &print, &save, opts }; void _init(void) { register_target(&mark); }
diff -uN linux-2.4.3-pre3/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.3-pre3-uml/include/linux/netfilter_ipv4/ip_conntrack.h --- linux-2.4.3-pre3/include/linux/netfilter_ipv4/ip_conntrack.h Fri Mar 9 21:43:28 2001 +++ linux-2.4.3-pre3-uml/include/linux/netfilter_ipv4/ip_conntrack.h Wed Mar 21 13:20:37 2001 @@ -147,6 +147,9 @@ } nat; #endif /* CONFIG_IP_NF_NAT_NEEDED */ +#if defined(CONFIG_IP_NF_CONNTRACK_MARK) + unsigned long mark; +#endif }; /* Alter reply tuple (maybe alter helper). If it's already taken, diff -uN --exclude .* --exclude *.o linux-2.4.3-pre3/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.3-pre3-uml/net/ipv4/netfilter/ip_conntrack_standalone.c --- linux-2.4.3-pre3/net/ipv4/netfilter/ip_conntrack_standalone.c Thu Aug 10 21:35:15 2000 +++ linux-2.4.3-pre3-uml/net/ipv4/netfilter/ip_conntrack_standalone.c Wed Mar 21 13:04:19 2001 @@ -92,6 +92,9 @@ len += sprintf(buffer + len, "[UNCONFIRMED] "); len += sprintf(buffer + len, "use=%u ", atomic_read(&conntrack->ct_general.use)); +#if defined(CONFIG_IP_NF_CONNTRACK_MARK) + len += sprintf(buffer + len, "mark=%d ", conntrack->mark); +#endif len += sprintf(buffer + len, "\n"); return len; --- linux-2.4.4-pre1-hno/net/ipv4/netfilter/ip_conntrack_core.c Tue Apr 10 22:33:21 2001 +++ linux-2.4.4-pre1-uml/net/ipv4/netfilter/ip_conntrack_core.c Mon Apr 16 00:23:00 2001 @@ -523,6 +523,9 @@ conntrack->status = IPS_EXPECTED; conntrack->master.master = &expected->expectant->ct_general; IP_NF_ASSERT(conntrack->master.master); +#if CONFIG_IP_NF_CONNTRACK_MARK + conntrack->mark = expected->expectant->mark; +#endif LIST_DELETE(&expect_list, expected); expected->expectant = NULL; nf_conntrack_get(&conntrack->master); diff -uN linux-2.4.3-pre3/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.4.3-pre3-uml/include/linux/netfilter_ipv4/ipt_connmark.h --- linux-2.4.3-pre3/include/linux/netfilter_ipv4/ipt_connmark.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.3-pre3-uml/include/linux/netfilter_ipv4/ipt_connmark.h Wed Mar 21 11:38:46 2001 @@ -0,0 +1,9 @@ +#ifndef _IPT_CONNMARK_H +#define _IPT_CONNMARK_H + +struct ipt_connmark_info { + unsigned long mark, mask; + u_int8_t invert; +}; + +#endif /*_IPT_CONNMARK_H*/ diff -uN --exclude .* --exclude *.o linux-2.4.3-pre3/net/ipv4/netfilter/ipt_connmark.c linux-2.4.3-pre3-uml/net/ipv4/netfilter/ipt_connmark.c --- linux-2.4.3-pre3/net/ipv4/netfilter/ipt_connmark.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.3-pre3-uml/net/ipv4/netfilter/ipt_connmark.c Wed Mar 21 13:23:33 2001 @@ -0,0 +1,55 @@ +/* Kernel module to match connection mark values. */ +#include <linux/module.h> +#include <linux/skbuff.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ipt_connmark.h> +#include <linux/netfilter_ipv4/ip_conntrack.h> + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + const void *hdr, + u_int16_t datalen, + int *hotdrop) +{ + const struct ipt_connmark_info *info = matchinfo; + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); + if (!ct) + return 0; + + return ((ct->mark & info->mask) == info->mark) ^ info->invert; +} + +static int +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_connmark_info))) + return 0; + + return 1; +} + +static struct ipt_match connmark_match += { { NULL, NULL }, "connmark", &match, &checkentry, NULL, THIS_MODULE }; + +static int __init init(void) +{ + return ipt_register_match(&connmark_match); +} + +static void __exit fini(void) +{ + ipt_unregister_match(&connmark_match); +} + +module_init(init); +module_exit(fini); diff -uN linux-2.4.3-pre3/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.4.3-pre3-uml/include/linux/netfilter_ipv4/ipt_CONNMARK.h --- linux-2.4.3-pre3/include/linux/netfilter_ipv4/ipt_CONNMARK.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.3-pre3-uml/include/linux/netfilter_ipv4/ipt_CONNMARK.h Wed Mar 21 12:25:20 2001 @@ -0,0 +1,15 @@ +#ifndef _IPT_CONNMARK_H_target +#define _IPT_CONNMARK_H_target + +enum { + IPT_CONNMARK_SET = 0, + IPT_CONNMARK_SAVE, + IPT_CONNMARK_RESTORE +}; + +struct ipt_connmark_target_info { + unsigned long mark; + u_int8_t mode; +}; + +#endif /*_IPT_CONNMARK_H_target*/ diff -uN --exclude .* --exclude *.o linux-2.4.3-pre3/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.4.3-pre3-uml/net/ipv4/netfilter/ipt_CONNMARK.c --- linux-2.4.3-pre3/net/ipv4/netfilter/ipt_CONNMARK.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.3-pre3-uml/net/ipv4/netfilter/ipt_CONNMARK.c Wed May 20 17:49:10 2001 @@ -0,0 +1,87 @@ +/* This is a module which is used for setting/remembering the mark field of + * an connection, or optionally restore it to the skb + */ +#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_CONNMARK.h> +#include <linux/netfilter_ipv4/ip_conntrack.h> + +static unsigned int +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_connmark_target_info *markinfo = targinfo; + + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); + if (ct) { + switch(markinfo->mode) { + case IPT_CONNMARK_SET: + ct->mark = markinfo->mark; + break; + case IPT_CONNMARK_SAVE: + ct->mark = (*pskb)->nfmark; + break; + case IPT_CONNMARK_RESTORE: + if (ct->mark != (*pskb)->nfmark) { + (*pskb)->nfmark = ct->mark; + (*pskb)->nfcache |= NFC_ALTERED; + } + break; + } + } + + return IPT_CONTINUE; +} + +static int +checkentry(const char *tablename, + const struct ipt_entry *e, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + struct ipt_connmark_target_info *matchinfo = targinfo; + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) { + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n", + targinfosize, + IPT_ALIGN(sizeof(struct ipt_connmark_target_info))); + return 0; + } + + if (matchinfo->mode == IPT_CONNMARK_RESTORE) { + if (strcmp(tablename, "mangle") != 0) { + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); + return 0; + } + } + + return 1; +} + +static struct ipt_target ipt_connmark_reg += { { NULL, NULL }, "CONNMARK", target, checkentry, NULL, THIS_MODULE }; + +static int __init init(void) +{ + if (ipt_register_target(&ipt_connmark_reg)) + return -EINVAL; + + return 0; +} + +static void __exit fini(void) +{ + ipt_unregister_target(&ipt_connmark_reg); +} + +module_init(init); +module_exit(fini);
dep_tristate ' Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then dep_tristate ' Connection mark match support' CONFIG_IP_NF_MATCH_CONNMARK $CONFIG_IP_NF_IPTABLES fi
obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
Author: Henrik Nordstrom <[EMAIL PROTECTED]> Status: working This patch adds per connection marks, and a target (CONNMARK) respective a match (connmark) for using these. Usage: connmark This module matches the netfilter mark field associated with a connection (which can be set using the CONNMARK target below). --mark value[/mask] Matches packets in connections with the given unsigned mark value (if a mask is specified, this is logically ANDed with the mark before the compar ison). CONNMARK This is used to set the netfilter mark value associated with the connection --set-mark mark Set connection mark --save-mark Set connection mark to the same as the one on the packet --restore-mark Set the netfilter packet mark value to the one associated with the connection. This is only valid in the mangle table.
dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then dep_tristate ' CONNMARK target support' CONFIG_IP_NF_TARGET_CONNMARK $CONFIG_IP_NF_IPTABLES fi
dep_tristate ' FTP protocol support' CONFIG_IP_NF_FTP $CONFIG_IP_NF_CONNTRACK bool ' Connection mark tracking support' CONFIG_IP_NF_CONNTRACK_MARK
CONFIG_IP_NF_FTP Per connection mark support CONFIG_IP_NF_CONNTRACK_MARK This option enables support for connection marks, used by the `CONNMARK' target and `connmark' match. Similar to the mark value of packets, but this mark value is kept in the conntrack session instead of the individual packets. CONNMARK target support CONFIG_IP_NF_TARGET_CONNMARK 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 Documentation/modules.txt. The module will be called ipt_CONNMARK.o. If unsure, say `N'. connmark match support CONFIP_IP_NF_MATCH_CONNMARK This option adds a `connmark' match, which allows you to match the connection mark value previously set for the session by `CONNMARK'.