* VLAN match within iptables
@ 2007-06-26 9:22 Jaime Nebrera
2007-06-26 9:34 ` Jan Engelhardt
2007-06-26 10:00 ` Pablo Neira Ayuso
0 siblings, 2 replies; 16+ messages in thread
From: Jaime Nebrera @ 2007-06-26 9:22 UTC (permalink / raw)
To: netfilter-devel, Amin Azez
Hi all,
We are seeking for a way to match rules based on VLAN Tag ID.
Searching the archives I have found this post:
http://lists.netfilter.org/pipermail/netfilter-devel/2006-August/025336.html
But the patch is missing and the answer was to use ebtables.
Of course ebtables already has this and this is kinda redundant, but
at the same time things get a bit complex when you have to worry about
so many marks due to vlan id, ips stuff etc etc
Is there any way to access the patch Amin sent to the list?
Regards
--
Jaime Nebrera - jnebrera@eneotecnologia.com
Consultor TI - ENEO Tecnologia SL
Pol. PISA - C/ Manufactura 6, P1, 3B
Mairena del Aljarafe - 41927 - Sevilla
Telf.- 955 60 11 60 / 619 04 55 18
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: VLAN match within iptables
2007-06-26 9:22 VLAN match within iptables Jaime Nebrera
@ 2007-06-26 9:34 ` Jan Engelhardt
2007-06-26 9:38 ` Patrick McHardy
2007-06-26 10:00 ` Pablo Neira Ayuso
1 sibling, 1 reply; 16+ messages in thread
From: Jan Engelhardt @ 2007-06-26 9:34 UTC (permalink / raw)
To: Jaime Nebrera; +Cc: netfilter-devel, Amin Azez
On Jun 26 2007 11:22, Jaime Nebrera wrote:
>
> Is there any way to access the patch Amin sent to the list?
You do see the "Url: " part, don't you?
Jan
--
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: VLAN match within iptables
2007-06-26 9:34 ` Jan Engelhardt
@ 2007-06-26 9:38 ` Patrick McHardy
2007-06-26 9:41 ` Jan Engelhardt
0 siblings, 1 reply; 16+ messages in thread
From: Patrick McHardy @ 2007-06-26 9:38 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel, Amin Azez, Jaime Nebrera
Jan Engelhardt wrote:
> On Jun 26 2007 11:22, Jaime Nebrera wrote:
>
>> Is there any way to access the patch Amin sent to the list?
>
>
> You do see the "Url: " part, don't you?
>
Of course this behaviour is complete crap for a developer mailinglist
archive:
A non-text attachment was scrubbed...
Name: vlan.2.6.17.patch
I'd just use a different archive until one of us gets around to
changing this (which might take a looong time since I don't
know if anyone is familiar with pipermail).
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: VLAN match within iptables
2007-06-26 9:38 ` Patrick McHardy
@ 2007-06-26 9:41 ` Jan Engelhardt
0 siblings, 0 replies; 16+ messages in thread
From: Jan Engelhardt @ 2007-06-26 9:41 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel, Amin Azez, Jaime Nebrera
On Jun 26 2007 11:38, Patrick McHardy wrote:
>Jan Engelhardt wrote:
>> On Jun 26 2007 11:22, Jaime Nebrera wrote:
>>
>>> Is there any way to access the patch Amin sent to the list?
>>
>>
>> You do see the "Url: " part, don't you?
>
>Of course this behaviour is complete crap for a developer mailinglist
>archive:
>
>A non-text attachment was scrubbed...
>Name: vlan.2.6.17.patch
>
>I'd just use a different archive until one of us gets around to
>changing this (which might take a looong time since I don't
>know if anyone is familiar with pipermail).
FWIW,
http://lists.netfilter.org/pipermail/netfilter-devel/attachments/20060818/508fa575/vlan.2.6.11-0001.bin
brings up the 2nd attachment, for example.
"All" that would be needed is to transform that url into a clickable link.
Jan
--
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: VLAN match within iptables
2007-06-26 9:22 VLAN match within iptables Jaime Nebrera
2007-06-26 9:34 ` Jan Engelhardt
@ 2007-06-26 10:00 ` Pablo Neira Ayuso
2007-06-26 10:09 ` Patrick McHardy
1 sibling, 1 reply; 16+ messages in thread
From: Pablo Neira Ayuso @ 2007-06-26 10:00 UTC (permalink / raw)
To: Jaime Nebrera; +Cc: netfilter-devel, Amin Azez
Jaime Nebrera wrote:
> We are seeking for a way to match rules based on VLAN Tag ID.
>
> Searching the archives I have found this post:
>
> http://lists.netfilter.org/pipermail/netfilter-devel/2006-August/025336.html
>
> But the patch is missing and the answer was to use ebtables.
>
> Of course ebtables already has this and this is kinda redundant, but
> at the same time things get a bit complex when you have to worry about
> so many marks due to vlan id, ips stuff etc etc
>
> Is there any way to access the patch Amin sent to the list?
Since you have to apply that patch to your kernel anyway, I suggest you
to apply the u32 patch instead (it is scheduled for 2.6.23 IIRC).
http://lists.netfilter.org/pipermail/netfilter-devel/2007-June/028189.html
http://lists.netfilter.org/pipermail/netfilter-devel/2007-June/028176.html
Of course, you'll have to define the rule to match the vlan stuff but if
later on you need to match any other minor bit, you'll already have the
way to do so.
--
"Países en desarrollo es el nombre con que los expertos designan a los
países arrollados por el desarrollo ajeno" -- Patas Arriba. La Escuela
del Mundo al Revés -- E. Galeano
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: VLAN match within iptables
2007-06-26 10:00 ` Pablo Neira Ayuso
@ 2007-06-26 10:09 ` Patrick McHardy
2007-06-26 12:38 ` Jan Engelhardt
0 siblings, 1 reply; 16+ messages in thread
From: Patrick McHardy @ 2007-06-26 10:09 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: Jan Engelhardt, netfilter-devel, Amin Azez, Jaime Nebrera
Pablo Neira Ayuso wrote:
> Since you have to apply that patch to your kernel anyway, I suggest you
> to apply the u32 patch instead (it is scheduled for 2.6.23 IIRC).
I don't think that will work, it can't be used to match on data
before skb->data since the offset can only be positive.
Jan, I just noticed the length checks are insufficient, very
large positives offsets will lead to integer overflow and
probably trigger the BUG afterwards. Another thing I missed
before is that you should never do:
BUG_ON(expression with side-effects);
since some people disable BUG_ON.
Can you send a fix for this please?
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: VLAN match within iptables
2007-06-26 10:09 ` Patrick McHardy
@ 2007-06-26 12:38 ` Jan Engelhardt
2007-06-26 12:50 ` Patrick McHardy
0 siblings, 1 reply; 16+ messages in thread
From: Jan Engelhardt @ 2007-06-26 12:38 UTC (permalink / raw)
To: Patrick McHardy
Cc: netfilter-devel, Amin Azez, Pablo Neira Ayuso, Jaime Nebrera
On Jun 26 2007 12:09, Patrick McHardy wrote:
>Pablo Neira Ayuso wrote:
>> Since you have to apply that patch to your kernel anyway, I suggest you
>> to apply the u32 patch instead (it is scheduled for 2.6.23 IIRC).
>
>I don't think that will work, it can't be used to match on data
>before skb->data since the offset can only be positive.
The VLAN ID is not in the Layer3 window. xt_u32 uses skb_copy_bits,
which seems to start at the Layer3 (IPv4/ipv6) header(why that?!).
>Jan, I just noticed the length checks are insufficient, very
>large positives offsets will lead to integer overflow and
>probably trigger the BUG afterwards.
Is this the right way to check for overflows?
if (at > skb->len || at + pos > skb->len ||
at + pos + 3 > skb->len)
return false;
Jan
--
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: VLAN match within iptables
2007-06-26 12:38 ` Jan Engelhardt
@ 2007-06-26 12:50 ` Patrick McHardy
2007-06-26 13:12 ` xt_u32 20070626 (Re: VLAN match within iptables) Jan Engelhardt
0 siblings, 1 reply; 16+ messages in thread
From: Patrick McHardy @ 2007-06-26 12:50 UTC (permalink / raw)
To: Jan Engelhardt
Cc: netfilter-devel, Amin Azez, Pablo Neira Ayuso, Jaime Nebrera
Jan Engelhardt wrote:
> On Jun 26 2007 12:09, Patrick McHardy wrote:
>
>> Pablo Neira Ayuso wrote:
>>
>>> Since you have to apply that patch to your kernel anyway, I suggest you
>>> to apply the u32 patch instead (it is scheduled for 2.6.23 IIRC).
>>>
>> I don't think that will work, it can't be used to match on data
>> before skb->data since the offset can only be positive.
>>
>
> The VLAN ID is not in the Layer3 window. xt_u32 uses skb_copy_bits,
> which seems to start at the Layer3 (IPv4/ipv6) header(why that?!).
>
It stats at skb->data, since thats the most natural way for
users. And it supports negative offsets, but you need to
make sure they're valid.
>
>> Jan, I just noticed the length checks are insufficient, very
>> large positives offsets will lead to integer overflow and
>> probably trigger the BUG afterwards.
>>
>
> Is this the right way to check for overflows?
>
> if (at > skb->len || at + pos > skb->len ||
> at + pos + 3 > skb->len)
> return false;
>
>
It depends, I'm not sure I understand the code correctly:
if (at + pos + 3 > skb->len || at + pos < 0)
return false;
BUG_ON(skb_copy_bits(skb, pos, &val, sizeof(val)) < 0);
You're only copying at pos here, so I don't get why you're
checking for at + pos. Just doing:
if (skb->len < 3 || pos > skb->len - 3)
return false;
should be fine for this case.
The second one goes:
if (at + pos + 3 > skb->len || at + pos < 0)
return false;
BUG_ON(skb_copy_bits(skb, at+pos, &val,
sizeof(val)) < 0);
So here I would do:
if (at + 3 < at || skb->len < at + 3 || pos > skb->len - at - 3)
return false;
^ permalink raw reply [flat|nested] 16+ messages in thread
* xt_u32 20070626 (Re: VLAN match within iptables)
2007-06-26 12:50 ` Patrick McHardy
@ 2007-06-26 13:12 ` Jan Engelhardt
2007-06-26 13:13 ` xt_u32 20070626 (iptables part) Jan Engelhardt
2007-06-26 13:19 ` xt_u32 20070626 (Re: VLAN match within iptables) Patrick McHardy
0 siblings, 2 replies; 16+ messages in thread
From: Jan Engelhardt @ 2007-06-26 13:12 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Netfilter Developer Mailing List
[-- Attachment #1: Type: TEXT/PLAIN, Size: 6635 bytes --]
Subject: Add the U32 match from POM-NG
xt_u32 is the successor of ipt_u32 which has been in from POM-NG.
* IPv6 support
* inversion
* lock-free, big buffer is gone
* misc fixes (overflow checks)
Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
---
include/linux/netfilter/xt_u32.h | 40 +++++++++++
net/netfilter/Kconfig | 13 +++
net/netfilter/Makefile | 1
net/netfilter/xt_u32.c | 135 +++++++++++++++++++++++++++++++++++++++
4 files changed, 189 insertions(+)
Index: linux-2.6.22/include/linux/netfilter/xt_u32.h
===================================================================
--- /dev/null
+++ linux-2.6.22/include/linux/netfilter/xt_u32.h
@@ -0,0 +1,40 @@
+#ifndef _XT_U32_H
+#define _XT_U32_H 1
+
+enum xt_u32_ops {
+ XT_U32_AND,
+ XT_U32_LEFTSH,
+ XT_U32_RIGHTSH,
+ XT_U32_AT,
+};
+
+struct xt_u32_location_element {
+ u_int32_t number;
+ u_int8_t nextop;
+};
+
+struct xt_u32_value_element {
+ u_int32_t min;
+ u_int32_t max;
+};
+
+/*
+ * Any way to allow for an arbitrary number of elements?
+ * For now, I settle with a limit of 10 each.
+ */
+#define XT_U32_MAXSIZE 10
+
+struct xt_u32_test {
+ struct xt_u32_location_element location[XT_U32_MAXSIZE+1];
+ struct xt_u32_value_element value[XT_U32_MAXSIZE+1];
+ u_int8_t nnums;
+ u_int8_t nvalues;
+};
+
+struct xt_u32 {
+ struct xt_u32_test tests[XT_U32_MAXSIZE+1];
+ u_int8_t ntests;
+ u_int8_t invert;
+};
+
+#endif /* _XT_U32_H */
Index: linux-2.6.22/net/netfilter/Kconfig
===================================================================
--- linux-2.6.22.orig/net/netfilter/Kconfig
+++ linux-2.6.22/net/netfilter/Kconfig
@@ -635,6 +635,19 @@ config NETFILTER_XT_MATCH_TCPMSS
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_U32
+ tristate '"u32" match support'
+ depends on NETFILTER_XTABLES
+ ---help---
+ u32 allows you to extract quantities of up to 4 bytes from a packet,
+ AND them with specified masks, shift them by specified amounts and
+ test whether the results are in any of a set of specified ranges.
+ The specification of what to extract is general enough to skip over
+ headers with lengths stored in the packet, as in IP or TCP header
+ lengths.
+
+ Details and examples are in the kernel module source.
+
config NETFILTER_XT_MATCH_HASHLIMIT
tristate '"hashlimit" match support'
depends on NETFILTER_XTABLES && (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
Index: linux-2.6.22/net/netfilter/Makefile
===================================================================
--- linux-2.6.22.orig/net/netfilter/Makefile
+++ linux-2.6.22/net/netfilter/Makefile
@@ -72,4 +72,5 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTI
obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
Index: linux-2.6.22/net/netfilter/xt_u32.c
===================================================================
--- /dev/null
+++ linux-2.6.22/net/netfilter/xt_u32.c
@@ -0,0 +1,135 @@
+/*
+ * xt_u32 - kernel module to match u32 packet content
+ *
+ * Original author: Don Cohen <don@isis.cs3-inc.com>
+ * © Jan Engelhardt <jengelh@gmx.de>, 2007
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_u32.h>
+
+static bool u32_match_it(const struct xt_u32 *data,
+ const struct sk_buff *skb)
+{
+ const struct xt_u32_test *ct;
+ unsigned int testind;
+ unsigned int nnums;
+ unsigned int nvals;
+ unsigned int i;
+ u_int32_t pos;
+ u_int32_t val;
+ u_int32_t at;
+ int ret;
+
+ /*
+ * Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17"
+ * (=IPv4 and (TCP or UDP)). Outer loop runs over the "&&" operands.
+ */
+ for (testind = 0; testind < data->ntests; ++testind) {
+ ct = &data->tests[testind];
+ at = 0;
+ pos = ct->location[0].number;
+
+ if (skb->len < 3 || pos > skb->len - 3);
+ return false;
+
+ ret = skb_copy_bits(skb, pos, &val, sizeof(val));
+ BUG_ON(ret < 0);
+ val = ntohl(val);
+ nnums = ct->nnums;
+
+ /* Inner loop runs over "&", "<<", ">>" and "@" operands */
+ for (i = 1; i < nnums; ++i) {
+ u_int32_t number = ct->location[i].number;
+ switch (ct->location[i].nextop) {
+ case XT_U32_AND:
+ val &= number;
+ break;
+ case XT_U32_LEFTSH:
+ val <<= number;
+ break;
+ case XT_U32_RIGHTSH:
+ val >>= number;
+ break;
+ case XT_U32_AT:
+ if (at + val < at)
+ return false;
+ at += val;
+ pos = number;
+ if (at + 3 < at || skb->len < at + 3 ||
+ pos > skb->len - at - 3)
+ return false;
+
+ ret = skb_copy_bits(skb, at + pos, &val,
+ sizeof(val));
+ BUG_ON(ret < 0);
+ val = ntohl(val);
+ break;
+ }
+ }
+
+ /* Run over the "," and ":" operands */
+ nvals = ct->nvalues;
+ for (i = 0; i < nvals; ++i)
+ if (ct->value[i].min <= val && val <= ct->value[i].max)
+ break;
+
+ if (i >= ct->nvalues)
+ return false;
+ }
+
+ return true;
+}
+
+static bool u32_match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match, const void *matchinfo,
+ int offset, unsigned int protoff, bool *hotdrop)
+{
+ const struct xt_u32 *data = matchinfo;
+ bool ret;
+
+ ret = u32_match_it(data, skb);
+ return ret ^ data->invert;
+}
+
+static struct xt_match u32_reg[] = {
+ {
+ .name = "u32",
+ .family = AF_INET,
+ .match = u32_match,
+ .matchsize = sizeof(struct xt_u32),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "u32",
+ .family = AF_INET6,
+ .match = u32_match,
+ .matchsize = sizeof(struct xt_u32),
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_u32_init(void)
+{
+ return xt_register_matches(u32_reg, ARRAY_SIZE(u32_reg));
+}
+
+static void __exit xt_u32_exit(void)
+{
+ xt_unregister_matches(u32_reg, ARRAY_SIZE(u32_reg));
+}
+
+module_init(xt_u32_init);
+module_exit(xt_u32_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_DESCRIPTION("netfilter u32 match module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_u32");
+MODULE_ALIAS("ip6t_u32");
^ permalink raw reply [flat|nested] 16+ messages in thread
* xt_u32 20070626 (iptables part)
2007-06-26 13:12 ` xt_u32 20070626 (Re: VLAN match within iptables) Jan Engelhardt
@ 2007-06-26 13:13 ` Jan Engelhardt
2007-06-26 16:49 ` Patrick McHardy
2007-06-26 13:19 ` xt_u32 20070626 (Re: VLAN match within iptables) Patrick McHardy
1 sibling, 1 reply; 16+ messages in thread
From: Jan Engelhardt @ 2007-06-26 13:13 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Netfilter Developer Mailing List
[-- Attachment #1: Type: TEXT/PLAIN, Size: 23051 bytes --]
# Small documentation update.
# ( s/skb->head/skb->data/ )
Refreshed libipt_u32 to work with xt_u32.
Introduces libip6t_u32.
Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
---
symlink extensions/.u32-test6 -> extensions/.u32-test
symlink extensions/libip6t_u32.man -> extensions/libipt_u32.man
extensions/.u32-test | 2
extensions/libip6t_u32.c | 299 ++++++++++++++++++++++++++++++++++++++++++++++
extensions/libipt_u32.c | 299 ++++++++++++++++++++++++++++++++++++++++++++++
extensions/libipt_u32.man | 129 +++++++++++++++++++
4 files changed, 729 insertions(+)
Index: iptables/extensions/.u32-test
===================================================================
--- /dev/null
+++ iptables/extensions/.u32-test
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ -f "$KERNEL_DIR/include/linux/netfilter/xt_u32.h" ] && echo u32
Index: iptables/extensions/libip6t_u32.c
===================================================================
--- /dev/null
+++ iptables/extensions/libip6t_u32.c
@@ -0,0 +1,299 @@
+/* Shared library add-on to iptables to add u32 matching,
+ * generalized matching on values found at packet offsets
+ *
+ * Detailed doc is in the kernel module source
+ * net/netfilter/xt_u32.c
+ *
+ * (C) 2002 by Don Cohen <don-netf@isis.cs3-inc.com>
+ * © Jan Engelhardt <jengelh@gmx.de>, 2007
+ * Released under the terms of GNU GPL v2
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ip6tables.h>
+#include <linux/netfilter/xt_u32.h>
+
+static const struct option u32_opts[] = {
+ {"u32", 1, NULL, '1'},
+ {NULL},
+};
+
+/* Function which prints out usage message. */
+static void u32_help(void)
+{
+ printf(
+ "u32 v%s options:\n"
+ "[!] --u32 tests\n"
+ "\t\t\t""tests := location \"=\" value | tests \"&&\" location \"=\" value\n"
+ "\t\t\t""value := range | value \",\" range\n"
+ "\t\t\t""range := number | number \":\" number\n"
+ "\t\t\t""location := number | location operator number\n"
+ "\t\t\t""operator := \"&\" | \"<<\" | \">>\" | \"@\"\n",
+ IPTABLES_VERSION);
+ return;
+}
+
+/* shared printing code */
+static void u32_dump(const struct xt_u32 *data)
+{
+ const struct xt_u32_test *ct;
+ unsigned int testind, i;
+
+ for (testind = 0; testind < data->ntests; ++testind) {
+ ct = &data->tests[testind];
+
+ if (testind > 0)
+ printf("&&");
+
+ printf("0x%x", ct->location[0].number);
+ for (i = 1; i < ct->nnums; ++i) {
+ switch (ct->location[i].nextop) {
+ case XT_U32_AND:
+ printf("&");
+ break;
+ case XT_U32_LEFTSH:
+ printf("<<");
+ break;
+ case XT_U32_RIGHTSH:
+ printf(">>");
+ break;
+ case XT_U32_AT:
+ printf("@");
+ break;
+ }
+ printf("0x%x", ct->location[i].number);
+ }
+
+ printf("=");
+ for (i = 0; i < ct->nvalues; ++i) {
+ if (i > 0)
+ printf(",");
+ if (ct->value[i].min == ct->value[i].max)
+ printf("0x%x", ct->value[i].min);
+ else
+ printf("0x%x:0x%x", ct->value[i].min,
+ ct->value[i].max);
+ }
+ }
+ printf(" ");
+}
+
+/* string_to_number is not quite what we need here ... */
+static uint32_t parse_number(char **s, int pos)
+{
+ uint32_t number;
+ char *end;
+ errno = 0;
+
+ number = strtoul(*s, &end, 0);
+ if (end == *s)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: expected number", pos);
+ if (errno)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: error reading number", pos);
+ *s = end;
+ return number;
+}
+
+/* Function which parses command options; returns true if it ate an option */
+static int u32_parse(int c, char **argv, int invert, unsigned int *flags,
+ const struct ip6t_entry *entry, unsigned int *nfcache,
+ struct ip6t_entry_match **match)
+{
+ struct xt_u32 *data = (void *)(*match)->data;
+ unsigned int testind = 0, locind = 0, valind = 0;
+ struct xt_u32_test *ct = &data->tests[testind]; /* current test */
+ char *arg = argv[optind-1]; /* the argument string */
+ char *start = arg;
+ int state = 0;
+
+ if (c != '1')
+ return 0;
+
+ data->invert = invert;
+
+ /*
+ * states:
+ * 0 = looking for numbers and operations,
+ * 1 = looking for ranges
+ */
+ while (1) {
+ /* read next operand/number or range */
+ while (isspace(*arg))
+ ++arg;
+
+ if (*arg == '\0') {
+ /* end of argument found */
+ if (state == 0)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: input ended in location spec");
+ if (valind == 0)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: test ended with no value spec");
+
+ ct->nnums = locind;
+ ct->nvalues = valind;
+ data->ntests = ++testind;
+
+ if (testind > XT_U32_MAXSIZE)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: too many \"&&\"s",
+ arg - start);
+ return 1;
+ }
+
+ if (state == 0) {
+ /*
+ * reading location: read a number if nothing read yet,
+ * otherwise either op number or = to end location spec
+ */
+ if (*arg == '=') {
+ if (locind == 0) {
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: "
+ "location spec missing",
+ arg - start);
+ } else {
+ ++arg;
+ state = 1;
+ }
+ } else {
+ if (locind != 0) {
+ /* need op before number */
+ if (*arg == '&') {
+ ct->location[locind].nextop = XT_U32_AND;
+ } else if (*arg == '<') {
+ if (*++arg != '<')
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: a second < expected", arg - start);
+ ct->location[locind].nextop = XT_U32_LEFTSH;
+ } else if (*arg == '>') {
+ if (*++arg != '>')
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: a second > expected", arg - start);
+ ct->location[locind].nextop = XT_U32_RIGHTSH;
+ } else if (*arg == '@') {
+ ct->location[locind].nextop = XT_U32_AT;
+ } else {
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: operator expected", arg - start);
+ }
+ ++arg;
+ }
+ /* now a number; string_to_number skips white space? */
+ ct->location[locind].number =
+ parse_number(&arg, arg - start);
+ if (++locind > XT_U32_MAXSIZE)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: too many operators", arg - start);
+ }
+ } else {
+ /*
+ * state 1 - reading values: read a range if nothing
+ * read yet, otherwise either ,range or && to end
+ * test spec
+ */
+ if (*arg == '&') {
+ if (*++arg != '&')
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: a second & was expected", arg - start);
+ if (valind == 0) {
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: value spec missing", arg - start);
+ } else {
+ ct->nnums = locind;
+ ct->nvalues = valind;
+ ct = &data->tests[++testind];
+ if (testind > XT_U32_MAXSIZE)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: too many \"&&\"s", arg - start);
+ ++arg;
+ state = 0;
+ locind = 0;
+ valind = 0;
+ }
+ } else { /* read value range */
+ if (valind > 0) { /* need , before number */
+ if (*arg != ',')
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: expected , or &&", arg - start);
+ ++arg;
+ }
+ ct->value[valind].min =
+ parse_number(&arg, arg - start);
+
+ while (isspace(*arg))
+ ++arg;
+
+ if (*arg == ':') {
+ ++arg;
+ ct->value[valind].max =
+ parse_number(&arg, arg-start);
+ } else {
+ ct->value[valind].max =
+ ct->value[valind].min;
+ }
+
+ if (++valind > XT_U32_MAXSIZE)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: too many \",\"s", arg - start);
+ }
+ }
+ }
+}
+
+/* Final check; must specify something. */
+static void u32_final_check(unsigned int flags)
+{
+}
+
+/* Prints out the matchinfo. */
+static void u32_print(const struct ip6t_ip6 *ip,
+ const struct ip6t_entry_match *match, int numeric)
+{
+ const struct xt_u32 *data = (const void *)match->data;
+ printf("u32 ");
+ if (data->invert)
+ printf("! ");
+ u32_dump(data);
+ return;
+}
+
+/* Saves the union ipt_matchinfo in parsable form to stdout. */
+static void u32_save(const struct ip6t_ip6 *ip,
+ const struct ip6t_entry_match *match)
+{
+ const struct xt_u32 *data = (const void *)match->data;
+ if (data->invert)
+ printf("! ");
+ printf("--u32 ");
+ u32_dump(data);
+ return;
+}
+
+static struct ip6tables_match u32_reg = {
+ .name = "u32",
+ .version = IPTABLES_VERSION,
+ .size = IP6T_ALIGN(sizeof(struct xt_u32)),
+ .userspacesize = IP6T_ALIGN(sizeof(struct xt_u32)),
+ .help = u32_help,
+ .parse = u32_parse,
+ .final_check = u32_final_check,
+ .print = u32_print,
+ .save = u32_save,
+ .extra_opts = u32_opts,
+};
+
+static __attribute__((constructor)) void libip6t_u32_init(void)
+{
+ register_match6(&u32_reg);
+ return;
+}
Index: iptables/extensions/libipt_u32.c
===================================================================
--- /dev/null
+++ iptables/extensions/libipt_u32.c
@@ -0,0 +1,299 @@
+/* Shared library add-on to iptables to add u32 matching,
+ * generalized matching on values found at packet offsets
+ *
+ * Detailed doc is in the kernel module source
+ * net/netfilter/xt_u32.c
+ *
+ * (C) 2002 by Don Cohen <don-netf@isis.cs3-inc.com>
+ * © Jan Engelhardt <jengelh@gmx.de>, 2007
+ * Released under the terms of GNU GPL v2
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <iptables.h>
+#include <linux/netfilter/xt_u32.h>
+
+static const struct option u32_opts[] = {
+ {"u32", 1, NULL, '1'},
+ {NULL},
+};
+
+/* Function which prints out usage message. */
+static void u32_help(void)
+{
+ printf(
+ "u32 v%s options:\n"
+ "[!] --u32 tests\n"
+ "\t\t\t""tests := location \"=\" value | tests \"&&\" location \"=\" value\n"
+ "\t\t\t""value := range | value \",\" range\n"
+ "\t\t\t""range := number | number \":\" number\n"
+ "\t\t\t""location := number | location operator number\n"
+ "\t\t\t""operator := \"&\" | \"<<\" | \">>\" | \"@\"\n",
+ IPTABLES_VERSION);
+ return;
+}
+
+/* shared printing code */
+static void u32_dump(const struct xt_u32 *data)
+{
+ const struct xt_u32_test *ct;
+ unsigned int testind, i;
+
+ for (testind = 0; testind < data->ntests; ++testind) {
+ ct = &data->tests[testind];
+
+ if (testind > 0)
+ printf("&&");
+
+ printf("0x%x", ct->location[0].number);
+ for (i = 1; i < ct->nnums; ++i) {
+ switch (ct->location[i].nextop) {
+ case XT_U32_AND:
+ printf("&");
+ break;
+ case XT_U32_LEFTSH:
+ printf("<<");
+ break;
+ case XT_U32_RIGHTSH:
+ printf(">>");
+ break;
+ case XT_U32_AT:
+ printf("@");
+ break;
+ }
+ printf("0x%x", ct->location[i].number);
+ }
+
+ printf("=");
+ for (i = 0; i < ct->nvalues; ++i) {
+ if (i > 0)
+ printf(",");
+ if (ct->value[i].min == ct->value[i].max)
+ printf("0x%x", ct->value[i].min);
+ else
+ printf("0x%x:0x%x", ct->value[i].min,
+ ct->value[i].max);
+ }
+ }
+ printf(" ");
+}
+
+/* string_to_number is not quite what we need here ... */
+static uint32_t parse_number(char **s, int pos)
+{
+ uint32_t number;
+ char *end;
+ errno = 0;
+
+ number = strtoul(*s, &end, 0);
+ if (end == *s)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: expected number", pos);
+ if (errno)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: error reading number", pos);
+ *s = end;
+ return number;
+}
+
+/* Function which parses command options; returns true if it ate an option */
+static int u32_parse(int c, char **argv, int invert, unsigned int *flags,
+ const struct ipt_entry *entry, unsigned int *nfcache,
+ struct ipt_entry_match **match)
+{
+ struct xt_u32 *data = (void *)(*match)->data;
+ unsigned int testind = 0, locind = 0, valind = 0;
+ struct xt_u32_test *ct = &data->tests[testind]; /* current test */
+ char *arg = argv[optind-1]; /* the argument string */
+ char *start = arg;
+ int state = 0;
+
+ if (c != '1')
+ return 0;
+
+ data->invert = invert;
+
+ /*
+ * states:
+ * 0 = looking for numbers and operations,
+ * 1 = looking for ranges
+ */
+ while (1) {
+ /* read next operand/number or range */
+ while (isspace(*arg))
+ ++arg;
+
+ if (*arg == '\0') {
+ /* end of argument found */
+ if (state == 0)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: input ended in location spec");
+ if (valind == 0)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: test ended with no value spec");
+
+ ct->nnums = locind;
+ ct->nvalues = valind;
+ data->ntests = ++testind;
+
+ if (testind > XT_U32_MAXSIZE)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: too many \"&&\"s",
+ arg - start);
+ return 1;
+ }
+
+ if (state == 0) {
+ /*
+ * reading location: read a number if nothing read yet,
+ * otherwise either op number or = to end location spec
+ */
+ if (*arg == '=') {
+ if (locind == 0) {
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: "
+ "location spec missing",
+ arg - start);
+ } else {
+ ++arg;
+ state = 1;
+ }
+ } else {
+ if (locind != 0) {
+ /* need op before number */
+ if (*arg == '&') {
+ ct->location[locind].nextop = XT_U32_AND;
+ } else if (*arg == '<') {
+ if (*++arg != '<')
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: a second < expected", arg - start);
+ ct->location[locind].nextop = XT_U32_LEFTSH;
+ } else if (*arg == '>') {
+ if (*++arg != '>')
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: a second > expected", arg - start);
+ ct->location[locind].nextop = XT_U32_RIGHTSH;
+ } else if (*arg == '@') {
+ ct->location[locind].nextop = XT_U32_AT;
+ } else {
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: operator expected", arg - start);
+ }
+ ++arg;
+ }
+ /* now a number; string_to_number skips white space? */
+ ct->location[locind].number =
+ parse_number(&arg, arg - start);
+ if (++locind > XT_U32_MAXSIZE)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: too many operators", arg - start);
+ }
+ } else {
+ /*
+ * state 1 - reading values: read a range if nothing
+ * read yet, otherwise either ,range or && to end
+ * test spec
+ */
+ if (*arg == '&') {
+ if (*++arg != '&')
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: a second & was expected", arg - start);
+ if (valind == 0) {
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: value spec missing", arg - start);
+ } else {
+ ct->nnums = locind;
+ ct->nvalues = valind;
+ ct = &data->tests[++testind];
+ if (testind > XT_U32_MAXSIZE)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: too many \"&&\"s", arg - start);
+ ++arg;
+ state = 0;
+ locind = 0;
+ valind = 0;
+ }
+ } else { /* read value range */
+ if (valind > 0) { /* need , before number */
+ if (*arg != ',')
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: expected , or &&", arg - start);
+ ++arg;
+ }
+ ct->value[valind].min =
+ parse_number(&arg, arg - start);
+
+ while (isspace(*arg))
+ ++arg;
+
+ if (*arg == ':') {
+ ++arg;
+ ct->value[valind].max =
+ parse_number(&arg, arg-start);
+ } else {
+ ct->value[valind].max =
+ ct->value[valind].min;
+ }
+
+ if (++valind > XT_U32_MAXSIZE)
+ exit_error(PARAMETER_PROBLEM,
+ "u32: at char %d: too many \",\"s", arg - start);
+ }
+ }
+ }
+}
+
+/* Final check; must specify something. */
+static void u32_final_check(unsigned int flags)
+{
+}
+
+/* Prints out the matchinfo. */
+static void u32_print(const struct ipt_ip *ip,
+ const struct ipt_entry_match *match, int numeric)
+{
+ const struct xt_u32 *data = (const void *)match->data;
+ printf("u32 ");
+ if (data->invert)
+ printf("! ");
+ u32_dump(data);
+ return;
+}
+
+/* Saves the union ipt_matchinfo in parsable form to stdout. */
+static void u32_save(const struct ipt_ip *ip,
+ const struct ipt_entry_match *match)
+{
+ const struct xt_u32 *data = (const void *)match->data;
+ if (data->invert)
+ printf("! ");
+ printf("--u32 ");
+ u32_dump(data);
+ return;
+}
+
+static struct iptables_match u32_reg = {
+ .name = "u32",
+ .version = IPTABLES_VERSION,
+ .size = IPT_ALIGN(sizeof(struct xt_u32)),
+ .userspacesize = IPT_ALIGN(sizeof(struct xt_u32)),
+ .help = u32_help,
+ .parse = u32_parse,
+ .final_check = u32_final_check,
+ .print = u32_print,
+ .save = u32_save,
+ .extra_opts = u32_opts,
+};
+
+static __attribute__((constructor)) void libipt_u32_init(void)
+{
+ register_match(&u32_reg);
+ return;
+}
Index: iptables/extensions/libipt_u32.man
===================================================================
--- /dev/null
+++ iptables/extensions/libipt_u32.man
@@ -0,0 +1,129 @@
+U32 tests whether quantities of up to 4 bytes extracted from a packet have
+specified values. The specification of what to extract is general enough to
+find data at given offsets from tcp headers or payloads.
+.TP
+[\fB!\fR]\fB --u32 \fItests\fR
+The argument amounts to a program in a small language described below.
+.IP
+tests := location "=" value | tests "&&" location "=" value
+.IP
+value := range | value "," range
+.IP
+range := number | number ":" number
+.PP
+a single number, \fIn\fR, is interpreted the same as \fIn:n\fR. \fIn:m\fR is
+interpreted as the range of numbers \fB>=n\fR and \fB<=m\fR.
+.IP "" 4
+location := number | location operator number
+.IP "" 4
+operator := "&" | "<<" | ">>" | "@"
+.PP
+The operators \fB&\fR, \fB<<\fR, \fB>>\fR and \fB&&\fR mean the same as in C.
+The \fB=\fR is really a set membership operator and the value syntax describes
+a set. The \fB@\fR operator is what allows moving to the next header and is
+described further below.
+.PP
+There are currently some artificial implementation limits on the size of the
+tests:
+.IP " *"
+no more than 10 of "\fB=\fR" (and 9 "\fB&&\fR"s) in the u32 argument
+.IP " *"
+no more than 10 ranges (and 9 commas) per value
+.IP " *"
+no more than 10 numbers (and 9 operators) per location
+.PP
+To describe the meaning of location, imagine the following machine that
+interprets it. There are three registers:
+.IP
+A is of type \fBchar *\fR, initially the address of the IP header
+.IP
+B and C are unsigned 32 bit integers, initially zero
+.PP
+The instructions are:
+.IP
+number B = number;
+.IP
+C = (*(A+B)<<24) + (*(A+B+1)<<16) + (*(A+B+2)<<8) + *(A+B+3)
+.IP
+&number C = C & number
+.IP
+<< number C = C << number
+.IP
+>> number C = C >> number
+.IP
+@number A = A + C; then do the instruction number
+.PP
+Any access of memory outside [skb->data,skb->end] causes the match to fail.
+Otherwise the result of the computation is the final value of C.
+.PP
+Whitespace is allowed but not required in the tests. However, the characters
+that do occur there are likely to require shell quoting, so it is a good idea
+to enclose the arguments in quotes.
+.PP
+Example:
+.IP
+match IP packets with total length >= 256
+.IP
+The IP header contains a total length field in bytes 2-3.
+.IP
+--u32 "\fB0 & 0xFFFF = 0x100:0xFFFF\fR"
+.IP
+read bytes 0-3
+.IP
+AND that with 0xFFFF (giving bytes 2-3), and test whether that is in the range
+[0x100:0xFFFF]
+.PP
+Example: (more realistic, hence more complicated)
+.IP
+match ICMP packets with icmp type 0
+.IP
+First test that it is an ICMP packet, true iff byte 9 (protocol) = 1
+.IP
+--u32 "\fB6 & 0xFF = 1 &&\fR ...
+.IP
+read bytes 6-9, use \fB&\fR to throw away bytes 6-8 and compare the result to
+1. Next test that it is not a fragment. (If so, it might be part of such a
+packet but we cannot always tell.) N.B.: This test is generally needed if you
+want to match anything beyond the IP header. The last 6 bits of byte 6 and all
+of byte 7 are 0 iff this is a complete packet (not a fragment). Alternatively,
+you can allow first fragments by only testing the last 5 bits of byte 6.
+.IP
+ ... \fB4 & 0x3FFF = 0 &&\fR ...
+.IP
+Last test: the first byte past the IP header (the type) is 0. This is where we
+have to use the @syntax. The length of the IP header (IHL) in 32 bit words is
+stored in the right half of byte 0 of the IP header itself.
+.IP
+ ... \fB0 >> 22 & 0x3C @ 0 >> 24 = 0\fR"
+.IP
+The first 0 means read bytes 0-3, \fB>>22\fR means shift that 22 bits to the
+right. Shifting 24 bits would give the first byte, so only 22 bits is four
+times that plus a few more bits. \fB&3C\fR then eliminates the two extra bits
+on the right and the first four bits of the first byte. For instance, if IHL=5,
+then the IP header is 20 (4 x 5) bytes long. In this case, bytes 0-1 are (in
+binary) xxxx0101 yyzzzzzz, \fB>>22\fR gives the 10 bit value xxxx0101yy and
+\fB&3C\fR gives 010100. \fB@\fR means to use this number as a new offset into
+the packet, and read four bytes starting from there. This is the first 4 bytes
+of the ICMP payload, of which byte 0 is the ICMP type. Therefore, we simply
+shift the value 24 to the right to throw out all but the first byte and compare
+the result with 0.
+.PP
+Example:
+.IP
+TCP payload bytes 8-12 is any of 1, 2, 5 or 8
+.IP
+First we test that the packet is a tcp packet (similar to ICMP).
+.IP
+--u32 "\fB6 & 0xFF = 6 &&\fR ...
+.IP
+Next, test that it is not a fragment (same as above).
+.IP
+ ... \fB0 >> 22 & 0x3C @ 12 >> 26 & 0x3C @ 8 = 1,2,5,8\fR"
+.IP
+\fB0>>22&3C\fR as above computes the number of bytes in the IP header. \fB@\fR
+makes this the new offset into the packet, which is the start of the TCP
+header. The length of the TCP header (again in 32 bit words) is the left half
+of byte 12 of the TCP header. The \fB12>>26&3C\fR computes this length in bytes
+(similar to the IP header before). "@" makes this the new offset, which is the
+start of the TCP payload. Finally, 8 reads bytes 8-12 of the payload and
+\fB=\fR checks whether the result is any of 1, 2, 5 or 8.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: xt_u32 20070626 (Re: VLAN match within iptables)
2007-06-26 13:12 ` xt_u32 20070626 (Re: VLAN match within iptables) Jan Engelhardt
2007-06-26 13:13 ` xt_u32 20070626 (iptables part) Jan Engelhardt
@ 2007-06-26 13:19 ` Patrick McHardy
2007-06-26 13:35 ` Jan Engelhardt
1 sibling, 1 reply; 16+ messages in thread
From: Patrick McHardy @ 2007-06-26 13:19 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List
Jan Engelhardt wrote:
> Subject: Add the U32 match from POM-NG
I prefer incremental patches. Your patch looks good,
I'm wondering about the constant 3 though. A int is
four bytes long.
+ if (skb->len < 3 || pos > skb->len - 3);
assume skb->len == 3, pos = 0. Its obviously incorrent.
+ if (at + 3 < at || skb->len < at + 3 ||
+ pos > skb->len - at - 3)
Same here, just assume the same as above and at == 0.
So I'm replacing all 3s by 4s.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: xt_u32 20070626 (Re: VLAN match within iptables)
2007-06-26 13:19 ` xt_u32 20070626 (Re: VLAN match within iptables) Patrick McHardy
@ 2007-06-26 13:35 ` Jan Engelhardt
2007-06-26 13:36 ` Patrick McHardy
0 siblings, 1 reply; 16+ messages in thread
From: Jan Engelhardt @ 2007-06-26 13:35 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Netfilter Developer Mailing List
[-- Attachment #1: Type: TEXT/PLAIN, Size: 2444 bytes --]
On Jun 26 2007 15:19, Patrick McHardy wrote:
> Jan Engelhardt wrote:
>> Subject: Add the U32 match from POM-NG
>
> I prefer incremental patches.
Hm, some UTF-8 got broken. Hence I attach the (incremental)
patch (also fixes 3 -> 4) with a 8 bit preserving mime type.
Inline version below for by-standers to look at :)
===
Correct overflow checks in xt_u32 and separate BUG_ON from expressions with
side-effects.
Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
---
net/netfilter/xt_u32.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
Index: linux-2.6.22/net/netfilter/xt_u32.c
===================================================================
--- linux-2.6.22.orig/net/netfilter/xt_u32.c
+++ linux-2.6.22/net/netfilter/xt_u32.c
@@ -2,7 +2,7 @@
* xt_u32 - kernel module to match u32 packet content
*
* Original author: Don Cohen <don@isis.cs3-inc.com>
- * Jan Engelhardt <jengelh@gmx.de>, 2007
+ * Copyright © Jan Engelhardt <jengelh@gmx.de>, 2007
*/
#include <linux/module.h>
@@ -13,7 +13,6 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_u32.h>
-
static bool u32_match_it(const struct xt_u32 *data,
const struct sk_buff *skb)
{
@@ -25,6 +24,7 @@ static bool u32_match_it(const struct xt
u_int32_t pos;
u_int32_t val;
u_int32_t at;
+ int ret;
/*
* Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17"
@@ -35,10 +35,11 @@ static bool u32_match_it(const struct xt
at = 0;
pos = ct->location[0].number;
- if (at + pos + 3 > skb->len || at + pos < 0)
+ if (skb->len < 4 || pos > skb->len - 4);
return false;
- BUG_ON(skb_copy_bits(skb, pos, &val, sizeof(val)) < 0);
+ ret = skb_copy_bits(skb, pos, &val, sizeof(val));
+ BUG_ON(ret < 0);
val = ntohl(val);
nnums = ct->nnums;
@@ -56,13 +57,17 @@ static bool u32_match_it(const struct xt
val >>= number;
break;
case XT_U32_AT:
+ if (at + val < at)
+ return false;
at += val;
pos = number;
- if (at + pos + 3 > skb->len || at + pos < 0)
+ if (at + 4 < at || skb->len < at + 4 ||
+ pos > skb->len - at - 4)
return false;
- BUG_ON(skb_copy_bits(skb, at+pos, &val,
- sizeof(val)) < 0);
+ ret = skb_copy_bits(skb, at + pos, &val,
+ sizeof(val));
+ BUG_ON(ret < 0);
val = ntohl(val);
break;
}
[-- Attachment #2: Type: APPLICATION/x-bzip, Size: 993 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: xt_u32 20070626 (Re: VLAN match within iptables)
2007-06-26 13:35 ` Jan Engelhardt
@ 2007-06-26 13:36 ` Patrick McHardy
2007-06-26 14:05 ` Jan Engelhardt
0 siblings, 1 reply; 16+ messages in thread
From: Patrick McHardy @ 2007-06-26 13:36 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List
Jan Engelhardt wrote:
> Hm, some UTF-8 got broken.
>
I noticed that and removed the broken part. So unless there's some
other difference (and the 3 -> 4) I'm leaving it as it is.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: xt_u32 20070626 (Re: VLAN match within iptables)
2007-06-26 13:36 ` Patrick McHardy
@ 2007-06-26 14:05 ` Jan Engelhardt
2007-06-26 14:06 ` Patrick McHardy
0 siblings, 1 reply; 16+ messages in thread
From: Jan Engelhardt @ 2007-06-26 14:05 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Netfilter Developer Mailing List
On Jun 26 2007 15:36, Patrick McHardy wrote:
> Jan Engelhardt wrote:
>> Hm, some UTF-8 got broken.
>>
>
> I noticed that and removed the broken part. So unless there's some
> other difference (and the 3 -> 4) I'm leaving it as it is.
I also did the BUG_ON(side_effect) separation in the most recent patch.
Jan
--
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: xt_u32 20070626 (Re: VLAN match within iptables)
2007-06-26 14:05 ` Jan Engelhardt
@ 2007-06-26 14:06 ` Patrick McHardy
0 siblings, 0 replies; 16+ messages in thread
From: Patrick McHardy @ 2007-06-26 14:06 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List
Jan Engelhardt wrote:
> On Jun 26 2007 15:36, Patrick McHardy wrote:
>
>> Jan Engelhardt wrote:
>>
>>> Hm, some UTF-8 got broken.
>>>
>>>
>> I noticed that and removed the broken part. So unless there's some
>> other difference (and the 3 -> 4) I'm leaving it as it is.
>>
>
> I also did the BUG_ON(side_effect) separation in the most recent patch.
>
That was already in the last one.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: xt_u32 20070626 (iptables part)
2007-06-26 13:13 ` xt_u32 20070626 (iptables part) Jan Engelhardt
@ 2007-06-26 16:49 ` Patrick McHardy
0 siblings, 0 replies; 16+ messages in thread
From: Patrick McHardy @ 2007-06-26 16:49 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List
Jan Engelhardt wrote:
> Index: iptables/extensions/.u32-test
> ===================================================================
> --- /dev/null
> +++ iptables/extensions/.u32-test
> @@ -0,0 +1,2 @@
> +#!/bin/sh
> +[ -f "$KERNEL_DIR/include/linux/netfilter/xt_u32.h" ] && echo u32
> Index: iptables/extensions/libip6t_u32.c
> ===================================================================
>
Having to build against a kernel tree sucks, please add
the header and build unconditionally.
> +/* shared printing code */
> +static void u32_dump(const struct xt_u32 *data)
> +{
> + const struct xt_u32_test *ct;
> + unsigned int testind, i;
> +
> + for (testind = 0; testind < data->ntests; ++testind) {
> + ct = &data->tests[testind];
> +
> + if (testind > 0)
> + printf("&&");
> +
> + printf("0x%x", ct->location[0].number);
> + for (i = 1; i < ct->nnums; ++i) {
> + switch (ct->location[i].nextop) {
> + case XT_U32_AND:
> + printf("&");
> + break;
> + case XT_U32_LEFTSH:
> + printf("<<");
> + break;
> + case XT_U32_RIGHTSH:
> + printf(">>");
> + break;
> + case XT_U32_AT:
> + printf("@");
> + break;
> + }
> + printf("0x%x", ct->location[i].number);
> + }
> +
> + printf("=");
> + for (i = 0; i < ct->nvalues; ++i) {
> + if (i > 0)
> + printf(",");
> + if (ct->value[i].min == ct->value[i].max)
> + printf("0x%x", ct->value[i].min);
> + else
> + printf("0x%x:0x%x", ct->value[i].min,
> + ct->value[i].max);
> + }
> + }
> + printf(" ");
> +}
> +
> +/* string_to_number is not quite what we need here ... */
> +static uint32_t parse_number(char **s, int pos)
> +{
> + uint32_t number;
> + char *end;
> + errno = 0;
> +
> + number = strtoul(*s, &end, 0);
> + if (end == *s)
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: expected number", pos);
> + if (errno)
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: error reading number", pos);
> + *s = end;
> + return number;
> +}
> +
> +/* Function which parses command options; returns true if it ate an option */
> +static int u32_parse(int c, char **argv, int invert, unsigned int *flags,
> + const struct ip6t_entry *entry, unsigned int *nfcache,
> + struct ip6t_entry_match **match)
> +{
> + struct xt_u32 *data = (void *)(*match)->data;
> + unsigned int testind = 0, locind = 0, valind = 0;
> + struct xt_u32_test *ct = &data->tests[testind]; /* current test */
> + char *arg = argv[optind-1]; /* the argument string */
> + char *start = arg;
> + int state = 0;
> +
> + if (c != '1')
> + return 0;
> +
> + data->invert = invert;
> +
> + /*
> + * states:
> + * 0 = looking for numbers and operations,
> + * 1 = looking for ranges
> + */
> + while (1) {
> + /* read next operand/number or range */
> + while (isspace(*arg))
> + ++arg;
> +
> + if (*arg == '\0') {
> + /* end of argument found */
> + if (state == 0)
> + exit_error(PARAMETER_PROBLEM,
> + "u32: input ended in location spec");
> + if (valind == 0)
> + exit_error(PARAMETER_PROBLEM,
> + "u32: test ended with no value spec");
> +
> + ct->nnums = locind;
> + ct->nvalues = valind;
> + data->ntests = ++testind;
> +
> + if (testind > XT_U32_MAXSIZE)
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: too many \"&&\"s",
> + arg - start);
> + return 1;
> + }
> +
> + if (state == 0) {
> + /*
> + * reading location: read a number if nothing read yet,
> + * otherwise either op number or = to end location spec
> + */
> + if (*arg == '=') {
> + if (locind == 0) {
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: "
> + "location spec missing",
> + arg - start);
> + } else {
> + ++arg;
> + state = 1;
> + }
> + } else {
> + if (locind != 0) {
> + /* need op before number */
> + if (*arg == '&') {
> + ct->location[locind].nextop = XT_U32_AND;
> + } else if (*arg == '<') {
> + if (*++arg != '<')
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: a second < expected", arg - start);
> + ct->location[locind].nextop = XT_U32_LEFTSH;
> + } else if (*arg == '>') {
> + if (*++arg != '>')
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: a second > expected", arg - start);
> + ct->location[locind].nextop = XT_U32_RIGHTSH;
> + } else if (*arg == '@') {
> + ct->location[locind].nextop = XT_U32_AT;
> + } else {
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: operator expected", arg - start);
> + }
> + ++arg;
> + }
> + /* now a number; string_to_number skips white space? */
> + ct->location[locind].number =
> + parse_number(&arg, arg - start);
> + if (++locind > XT_U32_MAXSIZE)
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: too many operators", arg - start);
> + }
> + } else {
> + /*
> + * state 1 - reading values: read a range if nothing
> + * read yet, otherwise either ,range or && to end
> + * test spec
> + */
> + if (*arg == '&') {
> + if (*++arg != '&')
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: a second & was expected", arg - start);
> + if (valind == 0) {
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: value spec missing", arg - start);
> + } else {
> + ct->nnums = locind;
> + ct->nvalues = valind;
> + ct = &data->tests[++testind];
> + if (testind > XT_U32_MAXSIZE)
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: too many \"&&\"s", arg - start);
> + ++arg;
> + state = 0;
> + locind = 0;
> + valind = 0;
> + }
> + } else { /* read value range */
> + if (valind > 0) { /* need , before number */
> + if (*arg != ',')
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: expected , or &&", arg - start);
> + ++arg;
> + }
> + ct->value[valind].min =
> + parse_number(&arg, arg - start);
> +
> + while (isspace(*arg))
> + ++arg;
> +
> + if (*arg == ':') {
> + ++arg;
> + ct->value[valind].max =
> + parse_number(&arg, arg-start);
> + } else {
> + ct->value[valind].max =
> + ct->value[valind].min;
> + }
> +
> + if (++valind > XT_U32_MAXSIZE)
> + exit_error(PARAMETER_PROBLEM,
> + "u32: at char %d: too many \",\"s", arg - start);
>
Thats not very understandable code. I hope I never have
to fix anything in there ..
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2007-06-26 16:49 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-06-26 9:22 VLAN match within iptables Jaime Nebrera
2007-06-26 9:34 ` Jan Engelhardt
2007-06-26 9:38 ` Patrick McHardy
2007-06-26 9:41 ` Jan Engelhardt
2007-06-26 10:00 ` Pablo Neira Ayuso
2007-06-26 10:09 ` Patrick McHardy
2007-06-26 12:38 ` Jan Engelhardt
2007-06-26 12:50 ` Patrick McHardy
2007-06-26 13:12 ` xt_u32 20070626 (Re: VLAN match within iptables) Jan Engelhardt
2007-06-26 13:13 ` xt_u32 20070626 (iptables part) Jan Engelhardt
2007-06-26 16:49 ` Patrick McHardy
2007-06-26 13:19 ` xt_u32 20070626 (Re: VLAN match within iptables) Patrick McHardy
2007-06-26 13:35 ` Jan Engelhardt
2007-06-26 13:36 ` Patrick McHardy
2007-06-26 14:05 ` Jan Engelhardt
2007-06-26 14:06 ` Patrick McHardy
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.