* Re: [PATCH 2/2] extensions: add HMARK target
@ 2012-07-12 7:34 Hans Schillstrom
2012-07-12 15:29 ` Pablo Neira Ayuso
0 siblings, 1 reply; 5+ messages in thread
From: Hans Schillstrom @ 2012-07-12 7:34 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Hi Pablo
[snip]
+static void HMARK_check(struct xt_fcheck_call *cb)
>+{
>+ if (!(cb->xflags & (1 << O_HMARK_MODULUS)))
>+ xtables_error(PARAMETER_PROBLEM, "--hmark-mod is mandatory");
>+ if (!(cb->xflags & (1 << O_HMARK_RND)))
>+ xtables_error(PARAMETER_PROBLEM, "--hmark-rnd is mandatory");
I don't think rnd should be mandatory, a default value is enough.
offset however should be mandatory.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] extensions: add HMARK target
2012-07-12 7:34 [PATCH 2/2] extensions: add HMARK target Hans Schillstrom
@ 2012-07-12 15:29 ` Pablo Neira Ayuso
0 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2012-07-12 15:29 UTC (permalink / raw)
To: Hans Schillstrom; +Cc: netfilter-devel
On Thu, Jul 12, 2012 at 09:34:45AM +0200, Hans Schillstrom wrote:
> Hi Pablo
> [snip]
> +static void HMARK_check(struct xt_fcheck_call *cb)
> >+{
> >+ if (!(cb->xflags & (1 << O_HMARK_MODULUS)))
> >+ xtables_error(PARAMETER_PROBLEM, "--hmark-mod is mandatory");
> >+ if (!(cb->xflags & (1 << O_HMARK_RND)))
> >+ xtables_error(PARAMETER_PROBLEM, "--hmark-rnd is mandatory");
>
> I don't think rnd should be mandatory, a default value is enough.
> offset however should be mandatory.
As I said, parameters that are not set will likely not be set by
users. If default value for random, the easier it will be for an
attacker to direct all flows to the same target.
I'll be OK to make --hmark-offset mandatory, BTW.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re[2]: [PATCH 2/2] extensions: add HMARK target
@ 2012-07-14 22:53 Hans Schillstrom
2012-07-16 12:22 ` Pablo Neira Ayuso
0 siblings, 1 reply; 5+ messages in thread
From: Hans Schillstrom @ 2012-07-14 22:53 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
>
>On Thu, Jul 12, 2012 at 09:34:45AM +0200, Hans Schillstrom wrote:
>> Hi Pablo
>> [snip]
>> +static void HMARK_check(struct xt_fcheck_call *cb)
>> >+{
>> >+ if (!(cb->xflags & (1 << O_HMARK_MODULUS)))
>> >+ xtables_error(PARAMETER_PROBLEM, "--hmark-mod is mandatory");
>> >+ if (!(cb->xflags & (1 << O_HMARK_RND)))
>> >+ xtables_error(PARAMETER_PROBLEM, "--hmark-rnd is mandatory");
>>
>> I don't think rnd should be mandatory, a default value is enough.
>> offset however should be mandatory.
>
>As I said, parameters that are not set will likely not be set by
>users. If default value for random, the easier it will be for an
>attacker to direct all flows to the same target.
If he knows the modulo, and assume that default rand.value is used....
I still don't think rnd should be mandatory, but I can live with it.
>
>I'll be OK to make --hmark-offset mandatory, BTW.
Well, if people use it to other things than PBR it will be bad to have it mandatory
so I think we leave it as it is.
I don't like is that MODE_L3 is gone
L3 can be substituted by using --hamrk-tuple src, dst. so that might be OK
but there is no flag set. (causing a lot of extra cpu cycles)
All masks have gone from set to zero, (due to hmark-tuple ?)
If it's more clear or not , I don't know but the man page needs to be updated
--hmark-tuple ct alone doesn't do much.
iptables \-t mangle \-A PREROUTING \-m state \-\-state NEW
- \-j HMARK \-\-hmark-tuple ct \-\-hmark-offset 10000 \-\-hmark\-mod 10
change to
+ \-j HMARK \-\-hmark-tuple ct,src,dst \-\-hmark-offset 10000 \-\-hmark\-mod 10
\-\-hmark\-rnd 0xfeedcafe
Some faults found during my first sanity check.
(I have not run any real tests so far, just some manual command tests
Due to the new behaviour and syntax the test suite needs some update)
diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c
index ee2629d..053bc10 100644
--- a/extensions/libxt_HMARK.c
+++ b/extensions/libxt_HMARK.c
@@ -280,15 +280,15 @@ static void HMARK_check(struct xt_fcheck_call *cb)
static void HMARK_print(const struct xt_hmark_info *info)
{
- if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
printf("sport-mask 0x%x ", htons(info->port_mask.p16.src));
- if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
printf("dport-mask 0x%x ", htons(info->port_mask.p16.dst));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
printf("spi-mask 0x%x ", htonl(info->port_mask.v32));
- if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
printf("sport-set 0x%x ", htons(info->port_set.p16.src));
- if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
printf("dport-set 0x%x ", htons(info->port_set.p16.dst));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
printf("spi-set 0x%x ", htonl(info->port_set.v32));
@@ -333,11 +333,11 @@ static void HMARK_ip4_print(const void *ip,
if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
printf("ct, ");
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
- printf("src-prefix %s ",
- xtables_ipmask_to_numeric(&info->src_mask.in) + 1);
+ printf("src-prefix %d ",
+ xtables_ipmask_to_cidr(&info->src_mask.in));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
- printf("dst-prefix %s ",
- xtables_ipmask_to_numeric(&info->dst_mask.in) + 1);
+ printf("dst-prefix %d ",
+ xtables_ipmask_to_cidr(&info->dst_mask.in));
HMARK_print(info);
}
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] extensions: add HMARK target
2012-07-14 22:53 Re[2]: " Hans Schillstrom
@ 2012-07-16 12:22 ` Pablo Neira Ayuso
0 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2012-07-16 12:22 UTC (permalink / raw)
To: Hans Schillstrom; +Cc: netfilter-devel
On Sun, Jul 15, 2012 at 12:53:46AM +0200, Hans Schillstrom wrote:
[...]
> >I'll be OK to make --hmark-offset mandatory, BTW.
>
> Well, if people use it to other things than PBR it will be bad to have it mandatory
> so I think we leave it as it is.
Sorry, I missed this mail and pushed this into master. Already made it
mandatory. Send me a patch if you want to relax this. I'll apply it.
> I don't like is that MODE_L3 is gone
> L3 can be substituted by using --hamrk-tuple src, dst. so that might be OK
> but there is no flag set. (causing a lot of extra cpu cycles)
This saves cycles for some specific case, but at the cost of adding
some branch misprediction in other case (ie. more cycles in other
cases). If we aim to genericity, we have to remove it.
BTW, I'd like to see some follow-up patch to support ICMP. We can just
generate the hash mark it using the src,dst,proto parts. That should
be easy.
> All masks have gone from set to zero, (due to hmark-tuple ?)
> If it's more clear or not , I don't know but the man page needs to be updated
> --hmark-tuple ct alone doesn't do much.
You're right, I fixed this in a follow-up patch now in master.
> iptables \-t mangle \-A PREROUTING \-m state \-\-state NEW
> - \-j HMARK \-\-hmark-tuple ct \-\-hmark-offset 10000 \-\-hmark\-mod 10
> change to
> + \-j HMARK \-\-hmark-tuple ct,src,dst \-\-hmark-offset 10000 \-\-hmark\-mod 10
> \-\-hmark\-rnd 0xfeedcafe
>
> Some faults found during my first sanity check.
> (I have not run any real tests so far, just some manual command tests
> Due to the new behaviour and syntax the test suite needs some update)
I've applied this patch below. Please, add description next time.
> diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c
> index ee2629d..053bc10 100644
> --- a/extensions/libxt_HMARK.c
> +++ b/extensions/libxt_HMARK.c
> @@ -280,15 +280,15 @@ static void HMARK_check(struct xt_fcheck_call *cb)
>
> static void HMARK_print(const struct xt_hmark_info *info)
> {
> - if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
> + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
> printf("sport-mask 0x%x ", htons(info->port_mask.p16.src));
> - if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
> + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
> printf("dport-mask 0x%x ", htons(info->port_mask.p16.dst));
> if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
> printf("spi-mask 0x%x ", htonl(info->port_mask.v32));
> - if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
> + if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
> printf("sport-set 0x%x ", htons(info->port_set.p16.src));
> - if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
> + if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
> printf("dport-set 0x%x ", htons(info->port_set.p16.dst));
> if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
> printf("spi-set 0x%x ", htonl(info->port_set.v32));
> @@ -333,11 +333,11 @@ static void HMARK_ip4_print(const void *ip,
> if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
> printf("ct, ");
> if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
> - printf("src-prefix %s ",
> - xtables_ipmask_to_numeric(&info->src_mask.in) + 1);
> + printf("src-prefix %d ",
> + xtables_ipmask_to_cidr(&info->src_mask.in));
> if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
> - printf("dst-prefix %s ",
> - xtables_ipmask_to_numeric(&info->dst_mask.in) + 1);
> + printf("dst-prefix %d ",
> + xtables_ipmask_to_cidr(&info->dst_mask.in));
> HMARK_print(info);
> }
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] extensions: add HMARK target
@ 2012-07-12 7:29 Hans Schillstrom
0 siblings, 0 replies; 5+ messages in thread
From: Hans Schillstrom @ 2012-07-12 7:29 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Hi Pablo
Some minor typos,
>
>The target allows you to set mark packets based Jenkins' hash calculation:
>
>h(t, rnd) = x
>
>mark = (x % mod) + offset
>
>where:
>
>* t is a tuple that is used for the hashing:
>
> t = [ src, dst, proto, sport, dport ]
>
>Note that you can customize the tuple, thus, removing some component
>that you don't want to use for the calculation. You can also use spi
>instead of sport and dport, btw.
>
>* rnd is the random seed that is explicitly passed via --hmark-mod
Typo , --hmark-rnd is better
>* mod is the modulus, to determine the range of possible marks
>* offset determines where the mark starts from
>
>This target only works for the "raw" and "mangle" tables.
>
>This can be used to distribute flows between a cluster of
>systems and uplinks.
>
>Initially based on work from Hans Schillingstrom. Pablo took it
>over and introduced several improvements.
>
>Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
>Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
>---
> extensions/libxt_HMARK.c | 441 ++++++++++++++++++++++++++++++++++++
> extensions/libxt_HMARK.man | 60 +++++
> include/linux/netfilter/xt_HMARK.h | 50 ++++
> 3 files changed, 551 insertions(+)
> create mode 100644 extensions/libxt_HMARK.c
> create mode 100644 extensions/libxt_HMARK.man
> create mode 100644 include/linux/netfilter/xt_HMARK.h
>
>diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c
>new file mode 100644
>index 0000000..ee2629d
>--- /dev/null
>+++ b/extensions/libxt_HMARK.c
>@@ -0,0 +1,441 @@
>+/*
>+ * (C) 2012 by Hans Schillstrom <hans.schillstrom@ericsson.com>
>+ * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
>+ *
>+ * This program is free software; you can redistribute it and/or modify
>+ * it under the terms of the GNU General Public License version 2 as
>+ * published by the Free Software Foundation.
>+ *
>+ * Description: shared library add-on to iptables to add HMARK target support
>+ *
>+ * Initial development by Hans Schillstrom. Pablo's improvements to this piece
>+ * of software has been sponsored by Sophos Astaro <http://www.sophos.com>.
>+ */
>+
>+#include <stdbool.h>
>+#include <stdio.h>
>+#include <string.h>
>+
>+#include "xtables.h"
>+#include <linux/netfilter/xt_HMARK.h>
>+
>+static void HMARK_help(void)
>+{
>+ printf(
>+"HMARK target options, i.e. modify hash calculation by:\n"
>+" --hmark-tuple [src|dst|sport|dport|spi|proto|ct][,...]\n"
>+" --hmark-mod value nfmark modulus value\n"
>+" --hmark-offset value Last action add value to nfmark\n\n"
>+" --hmark-rnd Random see for hashing\n"
Random seed...
>+" Alternatively, fine tuning of what will be included in hash calculation\n"
>+" --hmark-src-prefix length Source address mask CIDR prefix\n"
>+" --hmark-dst-prefix length Dest address mask CIDR prefix\n"
>+" --hmark-sport-mask value Mask src port with value\n"
>+" --hmark-dport-mask value Mask dst port with value\n"
>+" --hmark-spi-mask value For esp and ah AND spi with value\n"
>+" --hmark-sport-set value OR src port with value\n"
>+" --hmark-dport-set value OR dst port with value\n"
>+" --hmark-spi-set value For esp and ah OR spi with value\n"
>+" --hmark-proto-mask value Mask Protocol with value\n");
>+}
>+
>+#define hi struct xt_hmark_info
>+
>+enum {
>+ O_HMARK_SADDR_MASK,
>+ O_HMARK_DADDR_MASK,
>+ O_HMARK_SPI,
>+ O_HMARK_SPI_MASK,
>+ O_HMARK_SPORT,
>+ O_HMARK_DPORT,
>+ O_HMARK_SPORT_MASK,
>+ O_HMARK_DPORT_MASK,
>+ O_HMARK_PROTO_MASK,
>+ O_HMARK_RND,
>+ O_HMARK_MODULUS,
>+ O_HMARK_OFFSET,
>+ O_HMARK_CT,
>+ O_HMARK_TYPE,
>+};
>+
>+#define HMARK_OPT_PKT_MASK \
>+ ((1 << O_HMARK_SADDR_MASK) | \
>+ (1 << O_HMARK_DADDR_MASK) | \
>+ (1 << O_HMARK_SPI_MASK) | \
>+ (1 << O_HMARK_SPORT_MASK) | \
>+ (1 << O_HMARK_DPORT_MASK) | \
>+ (1 << O_HMARK_PROTO_MASK) | \
>+ (1 << O_HMARK_SPI_MASK) | \
>+ (1 << O_HMARK_SPORT) | \
>+ (1 << O_HMARK_DPORT) | \
>+ (1 << O_HMARK_SPI))
>+
>+static const struct xt_option_entry HMARK_opts[] = {
>+ { .name = "hmark-tuple",
>+ .type = XTTYPE_STRING,
>+ .id = O_HMARK_TYPE,
>+ },
>+ { .name = "hmark-src-prefix",
>+ .type = XTTYPE_PLENMASK,
>+ .id = O_HMARK_SADDR_MASK,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, src_mask)
>+ },
>+ { .name = "hmark-dst-prefix",
>+ .type = XTTYPE_PLENMASK,
>+ .id = O_HMARK_DADDR_MASK,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, dst_mask)
>+ },
>+ { .name = "hmark-sport-mask",
>+ .type = XTTYPE_UINT16,
>+ .id = O_HMARK_SPORT_MASK,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.src)
>+ },
>+ { .name = "hmark-dport-mask",
>+ .type = XTTYPE_UINT16,
>+ .id = O_HMARK_DPORT_MASK,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.dst)
>+ },
>+ { .name = "hmark-spi-mask",
>+ .type = XTTYPE_UINT32,
>+ .id = O_HMARK_SPI_MASK,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.v32)
>+ },
>+ { .name = "hmark-sport",
>+ .type = XTTYPE_UINT16,
>+ .id = O_HMARK_SPORT,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.src)
>+ },
>+ { .name = "hmark-dport",
>+ .type = XTTYPE_UINT16,
>+ .id = O_HMARK_DPORT,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.dst)
>+ },
>+ { .name = "hmark-spi",
>+ .type = XTTYPE_UINT32,
>+ .id = O_HMARK_SPI,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.v32)
>+ },
>+ { .name = "hmark-proto-mask",
>+ .type = XTTYPE_UINT16,
>+ .id = O_HMARK_PROTO_MASK,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, proto_mask)
>+ },
>+ { .name = "hmark-rnd",
>+ .type = XTTYPE_UINT32,
>+ .id = O_HMARK_RND,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, hashrnd)
>+ },
>+ { .name = "hmark-mod",
>+ .type = XTTYPE_UINT32,
>+ .id = O_HMARK_MODULUS,
>+ .min = 1,
>+ .flags = XTOPT_PUT | XTOPT_MAND, XTOPT_POINTER(hi, hmodulus)
>+ },
>+ { .name = "hmark-offset",
>+ .type = XTTYPE_UINT32,
>+ .id = O_HMARK_OFFSET,
>+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, hoffset)
>+ },
>+ XTOPT_TABLEEND,
>+};
>+
>+static int
>+hmark_parse(const char *type, size_t len, struct xt_hmark_info *info,
>+ unsigned int *xflags)
>+{
>+ if (strncasecmp(type, "ct", len) == 0) {
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
>+ *xflags |= (1 << O_HMARK_CT);
>+ } else if (strncasecmp(type, "src", len) == 0) {
>+ memset(&info->src_mask, 0xff, sizeof(info->src_mask));
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
>+ *xflags |= (1 << O_HMARK_SADDR_MASK);
>+ } else if (strncasecmp(type, "dst", len) == 0) {
>+ memset(&info->dst_mask, 0xff, sizeof(info->dst_mask));
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
>+ *xflags |= (1 << O_HMARK_DADDR_MASK);
>+ } else if (strncasecmp(type, "sport", len) == 0) {
>+ memset(&info->port_mask.p16.src, 0xff,
>+ sizeof(info->port_mask.p16.src));
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
>+ *xflags |= (1 << O_HMARK_SPORT_MASK);
>+ } else if (strncasecmp(type, "dport", len) == 0) {
>+ memset(&info->port_mask.p16.dst, 0xff,
>+ sizeof(info->port_mask.p16.dst));
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
>+ *xflags |= (1 << O_HMARK_DPORT_MASK);
>+ } else if (strncasecmp(type, "proto", len) == 0) {
>+ memset(&info->proto_mask, 0xff, sizeof(info->proto_mask));
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
>+ *xflags |= (1 << O_HMARK_PROTO_MASK);
>+ } else if (strncasecmp(type, "spi", len) == 0) {
>+ memset(&info->port_mask.v32, 0xff, sizeof(info->port_mask.v32));
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
>+ *xflags |= (1 << O_HMARK_SPI_MASK);
>+ } else
>+ return 0;
>+
>+ return 1;
>+}
>+
>+static void
>+hmark_parse_type(struct xt_option_call *cb)
>+{
>+ const char *arg = cb->arg;
>+ struct xt_hmark_info *info = cb->data;
>+ const char *comma;
>+
>+ while ((comma = strchr(arg, ',')) != NULL) {
>+ if (comma == arg ||
>+ !hmark_parse(arg, comma-arg, info, &cb->xflags))
>+ xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg);
>+ arg = comma+1;
>+ }
>+ if (!*arg)
>+ xtables_error(PARAMETER_PROBLEM, "\"--hmark-tuple\" requires "
>+ "a list of types with no "
>+ "spaces, e.g. "
>+ "src,dst,sport,dport,proto");
>+ if (strlen(arg) == 0 ||
>+ !hmark_parse(arg, strlen(arg), info, &cb->xflags))
>+ xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg);
>+}
>+
>+static void HMARK_parse(struct xt_option_call *cb, int plen)
>+{
>+ struct xt_hmark_info *info = cb->data;
>+
>+ xtables_option_parse(cb);
>+
>+ switch (cb->entry->id) {
>+ case O_HMARK_TYPE:
>+ hmark_parse_type(cb);
>+ break;
>+ case O_HMARK_SADDR_MASK:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
>+ break;
>+ case O_HMARK_DADDR_MASK:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
>+ break;
>+ case O_HMARK_SPI:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
>+ break;
>+ case O_HMARK_SPORT:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT);
>+ break;
>+ case O_HMARK_DPORT:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT);
>+ break;
>+ case O_HMARK_SPORT_MASK:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
>+ break;
>+ case O_HMARK_DPORT_MASK:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
>+ break;
>+ case O_HMARK_PROTO_MASK:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
>+ break;
>+ case O_HMARK_RND:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_RND);
>+ break;
>+ case O_HMARK_MODULUS:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_MODULUS);
>+ break;
>+ case O_HMARK_OFFSET:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_OFFSET);
>+ break;
>+ case O_HMARK_CT:
>+ info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
>+ break;
>+ }
>+ cb->xflags |= (1 << cb->entry->id);
>+}
>+
>+static void HMARK_ip4_parse(struct xt_option_call *cb)
>+{
>+ HMARK_parse(cb, 32);
>+}
>+static void HMARK_ip6_parse(struct xt_option_call *cb)
>+{
>+ HMARK_parse(cb, 128);
>+}
>+
>+static void HMARK_check(struct xt_fcheck_call *cb)
>+{
>+ if (!(cb->xflags & (1 << O_HMARK_MODULUS)))
>+ xtables_error(PARAMETER_PROBLEM, "--hmark-mod is mandatory");
>+ if (!(cb->xflags & (1 << O_HMARK_RND)))
>+ xtables_error(PARAMETER_PROBLEM, "--hmark-rnd is mandatory");
>+ if (cb->xflags & (1 << O_HMARK_SPI_MASK) &&
>+ (cb->xflags & (1 << O_HMARK_SPORT_MASK ||
>+ cb->xflags & (1 << O_HMARK_DPORT_MASK))))
>+ xtables_error(PARAMETER_PROBLEM, "you cannot use "
>+ "--hmark-spi-mask and --hmark-?port-mask,"
>+ "at the same time");
>+ if (!((cb->xflags & HMARK_OPT_PKT_MASK) ||
>+ cb->xflags & (1 << O_HMARK_CT)))
>+ xtables_error(PARAMETER_PROBLEM, "you have to specify "
>+ "--hmark-tuple at least");
>+}
>+
>+static void HMARK_print(const struct xt_hmark_info *info)
>+{
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
>+ printf("sport-mask 0x%x ", htons(info->port_mask.p16.src));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
>+ printf("dport-mask 0x%x ", htons(info->port_mask.p16.dst));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
>+ printf("spi-mask 0x%x ", htonl(info->port_mask.v32));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
>+ printf("sport-set 0x%x ", htons(info->port_set.p16.src));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
>+ printf("dport-set 0x%x ", htons(info->port_set.p16.dst));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
>+ printf("spi-set 0x%x ", htonl(info->port_set.v32));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK))
>+ printf("proto-mask 0x%x ", info->proto_mask);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND))
>+ printf("rnd 0x%x ", info->hashrnd);
>+}
>+
>+static void HMARK_ip6_print(const void *ip,
>+ const struct xt_entry_target *target, int numeric)
>+{
>+ const struct xt_hmark_info *info =
>+ (const struct xt_hmark_info *)target->data;
>+
>+ printf(" HMARK ");
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
>+ printf("mod %u ", info->hmodulus);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
>+ printf("+ 0x%x ", info->hoffset);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
>+ printf("ct, ");
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
>+ printf("src-prefix %s ",
>+ xtables_ip6mask_to_numeric(&info->src_mask.in6) + 1);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
>+ printf("dst-prefix %s ",
>+ xtables_ip6mask_to_numeric(&info->dst_mask.in6) + 1);
>+ HMARK_print(info);
>+}
>+static void HMARK_ip4_print(const void *ip,
>+ const struct xt_entry_target *target, int numeric)
>+{
>+ const struct xt_hmark_info *info =
>+ (const struct xt_hmark_info *)target->data;
>+
>+ printf(" HMARK ");
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
>+ printf("mod %u ", info->hmodulus);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
>+ printf("+ 0x%x ", info->hoffset);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
>+ printf("ct, ");
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
>+ printf("src-prefix %s ",
>+ xtables_ipmask_to_numeric(&info->src_mask.in) + 1);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
>+ printf("dst-prefix %s ",
>+ xtables_ipmask_to_numeric(&info->dst_mask.in) + 1);
>+ HMARK_print(info);
>+}
>+
>+static void HMARK_save(const struct xt_hmark_info *info)
>+{
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
>+ printf(" --hmark-sport-mask 0x%04x",
>+ htons(info->port_mask.p16.src));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
>+ printf(" --hmark-dport-mask 0x%04x",
>+ htons(info->port_mask.p16.dst));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
>+ printf(" --hmark-spi-mask 0x%08x",
>+ htonl(info->port_mask.v32));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
>+ printf(" --hmark-sport-set 0x%04x",
>+ htons(info->port_set.p16.src));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
>+ printf(" --hmark-dport-set 0x%04x",
>+ htons(info->port_set.p16.dst));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
>+ printf(" --hmark-spi-set 0x%08x", htonl(info->port_set.v32));
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK))
>+ printf(" --hmark-proto-mask 0x%02x", info->proto_mask);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND))
>+ printf(" --hmark-rnd 0x%08x", info->hashrnd);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
>+ printf(" --hmark-mod %u", info->hmodulus);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
>+ printf(" --hmark-offset %u", info->hoffset);
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
>+ printf(" --hmark-tuple ct");
>+}
>+
>+static void HMARK_ip6_save(const void *ip, const struct xt_entry_target *target)
>+{
>+ const struct xt_hmark_info *info =
>+ (const struct xt_hmark_info *)target->data;
>+ int ret;
>+
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) {
>+ ret = xtables_ip6mask_to_cidr(&info->src_mask.in6);
>+ printf(" --hmark-src-prefix %d", ret);
>+ }
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) {
>+ ret = xtables_ip6mask_to_cidr(&info->dst_mask.in6);
>+ printf(" --hmark-dst-prefix %d", ret);
>+ }
>+ HMARK_save(info);
>+}
>+
>+static void HMARK_ip4_save(const void *ip, const struct xt_entry_target *target)
>+{
>+ const struct xt_hmark_info *info =
>+ (const struct xt_hmark_info *)target->data;
>+ int ret;
>+
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) {
>+ ret = xtables_ipmask_to_cidr(&info->src_mask.in);
>+ printf(" --hmark-src-prefix %d", ret);
>+ }
>+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) {
>+ ret = xtables_ipmask_to_cidr(&info->dst_mask.in);
>+ printf(" --hmark-dst-prefix %d", ret);
>+ }
>+ HMARK_save(info);
>+}
>+
>+static struct xtables_target mark_tg_reg[] = {
>+ {
>+ .family = NFPROTO_IPV4,
>+ .name = "HMARK",
>+ .version = XTABLES_VERSION,
>+ .size = XT_ALIGN(sizeof(struct xt_hmark_info)),
>+ .userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
>+ .help = HMARK_help,
>+ .print = HMARK_ip4_print,
>+ .save = HMARK_ip4_save,
>+ .x6_parse = HMARK_ip4_parse,
>+ .x6_fcheck = HMARK_check,
>+ .x6_options = HMARK_opts,
>+ },
>+ {
>+ .family = NFPROTO_IPV6,
>+ .name = "HMARK",
>+ .version = XTABLES_VERSION,
>+ .size = XT_ALIGN(sizeof(struct xt_hmark_info)),
>+ .userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
>+ .help = HMARK_help,
>+ .print = HMARK_ip6_print,
>+ .save = HMARK_ip6_save,
>+ .x6_parse = HMARK_ip6_parse,
>+ .x6_fcheck = HMARK_check,
>+ .x6_options = HMARK_opts,
>+ },
>+};
>+
>+void _init(void)
>+{
>+ xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
>+}
>diff --git a/extensions/libxt_HMARK.man b/extensions/libxt_HMARK.man
>new file mode 100644
>index 0000000..6b36b58
>--- /dev/null
>+++ b/extensions/libxt_HMARK.man
>@@ -0,0 +1,60 @@
>+Like MARK, i.e. set the fwmark, but the mark is calculated from hashing
>+packet selector at choice. You have also to specify the mark range and,
>+optionally, the offset to start from. ICMP error messages are inspected
>+and used to calculate the hashing.
>+.PP
>+Existing options are:
>+.TP
>+\fB\-\-hmark\-tuple\fP tuple\fI\fP
>+Possible tuple members are:
>+.B src
>+meaning source address (IPv4, IPv6 address),
>+.B dst
>+meaning destination address (IPv4, IPv6 address),
>+.B sport
>+meaning source port (TCP, UDP, UDPlite, SCTP, DCCP),
>+.B dport
>+meaning destination port (TCP, UDP, UDPlite, SCTP, DCCP),
>+.B spi
>+meaning Security Parameter Index (AH, ESP), and
>+.B ct
>+meaning the usage of the conntrack tuple instead of the packet selectors.
>+.TP
>+\fB\-\-hmark\-mod\fP \fIvalue (must be > 0)\fP
>+Modulus for hash calculation (to limit the range of possible marks)
>+.TP
>+\fB\-\-hmark\-offset\fP \fIvalue\fP
>+Offset to start marks from.
>+.TP
>+For advanced usage, instead of using \-\-hmark\-tuple, you can specify custom
>+prefixes and masks:
>+.TP
>+\fB\-\-hmark\-src\-prefix\fP \fIcidr\fP
>+The source address mask in CIDR notation.
>+.TP
>+\fB\-\-hmark\-dst\-prefix\fP \fIcidr\fP
>+The destination address mask in CIDR notation.
>+.TP
>+\fB\-\-hmark\-sport\-mask\fP \fIvalue\fP
>+A 16 bit source port mask in hexadecimal.
>+.TP
>+\fB\-\-hmark\-dport\-mask\fP \fIvalue\fP
>+A 16 bit destination port mask in hexadecimal.
>+.TP
>+\fB\-\-hmark\-spi\-mask\fP \fIvalue\fP
>+A 32 bit field with spi mask.
>+.TP
>+\fB\-\-hmark\-proto\-mask\fP \fIvalue\fP
>+An 8 bit field with layer 4 protocol number.
>+.TP
>+\fB\-\-hmark\-rnd\fP \fIvalue\fP
>+A 32 bit random custom value to feed hash calculation.
>+.PP
>+\fIExamples:\fP
>+.PP
>+iptables \-t mangle \-A PREROUTING \-m state \-\-state NEW
>+ \-j HMARK \-\-hmark-tuple ct \-\-hmark-offset 10000 \-\-hmark\-mod 10
>+\-\-hmark\-rnd 0xfeedcafe
>+.PP
>+iptables \-t mangle \-A PREROUTING -j HMARK \-\-hmark-tuple src,dst,proto
>+\-\-hmark-mod 10 \-\-hmark\-rand 0xdeafbeef
>diff --git a/include/linux/netfilter/xt_HMARK.h b/include/linux/netfilter/xt_HMARK.h
>new file mode 100644
>index 0000000..826fc58
>--- /dev/null
>+++ b/include/linux/netfilter/xt_HMARK.h
>@@ -0,0 +1,50 @@
>+#ifndef XT_HMARK_H_
>+#define XT_HMARK_H_
>+
>+#include <linux/types.h>
>+
>+enum {
>+ XT_HMARK_SADDR_MASK,
>+ XT_HMARK_DADDR_MASK,
>+ XT_HMARK_SPI,
>+ XT_HMARK_SPI_MASK,
>+ XT_HMARK_SPORT,
>+ XT_HMARK_DPORT,
>+ XT_HMARK_SPORT_MASK,
>+ XT_HMARK_DPORT_MASK,
>+ XT_HMARK_PROTO_MASK,
>+ XT_HMARK_RND,
>+ XT_HMARK_MODULUS,
>+ XT_HMARK_OFFSET,
>+ XT_HMARK_CT,
>+ XT_HMARK_METHOD_L3,
>+ XT_HMARK_METHOD_L3_4,
>+};
>+#define XT_HMARK_FLAG(flag) (1 << flag)
>+
>+union hmark_ports {
>+ struct {
>+ __u16 src;
>+ __u16 dst;
>+ } p16;
>+ struct {
>+ __be16 src;
>+ __be16 dst;
>+ } b16;
>+ __u32 v32;
>+ __be32 b32;
>+};
>+
>+struct xt_hmark_info {
>+ union nf_inet_addr src_mask;
>+ union nf_inet_addr dst_mask;
>+ union hmark_ports port_mask;
>+ union hmark_ports port_set;
>+ __u32 flags;
>+ __u16 proto_mask;
>+ __u32 hashrnd;
>+ __u32 hmodulus;
>+ __u32 hoffset; /* Mark offset to start from */
>+};
>+
>+#endif /* XT_HMARK_H_ */
>--
>1.7.10
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 0/2] revamped HMARK extension
@ 2012-07-10 23:17 pablo
2012-07-10 23:17 ` [PATCH 2/2] extensions: add HMARK target pablo
0 siblings, 1 reply; 5+ messages in thread
From: pablo @ 2012-07-10 23:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Hans Schillstrom
From: Pablo Neira Ayuso <pablo@netfilter.org>
Hi Hans,
I'm taking over your initial HMARK extension for iptables and took the freedom
to revamp it.
It now provides a shortcut for easy configuration:
iptables -I PREROUTING -t mangle -j HMARK \
--hmark-tuple src,dst,proto \
--hmark-mod 2 \
--hmark-rnd 0xfeedcafe
Where --hmark-tuple can be src,dst,proto,sport,dport,spi,ct
Of course, you cannot set spi and sport/dport at the same time and ct must be
used all alone.
You can still use the advanced options for fine tweaking --hmark-*-prefix
and --hmark-*-mask.
I also needed to add some new functions to libxtables to obtain the network
prefix a.k.a CIDR notation. Also reworked xtables_ip[6]mask_to_numeric.
Frankly, I think they now look better from the string handling perspective.
Note that the --hmark-rnd and --hmark-mod are mandatory. Specifically, I don't
want any assumption on --hmark-rnd, users are lazy, they don't set what is not
mandatory (and I believe this parameter is important).
Please, test and report any issue with this asap. I'd like to integrate this
into iptables' master branch by when 3.5 is out so people upgrading to that
kernel can enjoy it.
I'm respecting your authorship in the HMARK extension, as you started this
code.
You can also find these two patches in the hmark branch of the iptables git tree.
Hans Schillstrom (1):
extensions: add HMARK target
Pablo Neira Ayuso (1):
libxtables: add xtables_ip[6]mask_to_cidr
extensions/libxt_HMARK.c | 441 ++++++++++++++++++++++++++++++++++++
extensions/libxt_HMARK.man | 60 +++++
include/linux/netfilter/xt_HMARK.h | 50 ++++
include/xtables.h.in | 2 +
libxtables/xtables.c | 33 ++-
5 files changed, 577 insertions(+), 9 deletions(-)
create mode 100644 extensions/libxt_HMARK.c
create mode 100644 extensions/libxt_HMARK.man
create mode 100644 include/linux/netfilter/xt_HMARK.h
--
1.7.10
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] extensions: add HMARK target
2012-07-10 23:17 [PATCH 0/2] revamped HMARK extension pablo
@ 2012-07-10 23:17 ` pablo
0 siblings, 0 replies; 5+ messages in thread
From: pablo @ 2012-07-10 23:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Hans Schillstrom
From: Hans Schillstrom <hans.schillstrom@ericsson.com>
The target allows you to set mark packets based Jenkins' hash calculation:
h(t, rnd) = x
mark = (x % mod) + offset
where:
* t is a tuple that is used for the hashing:
t = [ src, dst, proto, sport, dport ]
Note that you can customize the tuple, thus, removing some component
that you don't want to use for the calculation. You can also use spi
instead of sport and dport, btw.
* rnd is the random seed that is explicitly passed via --hmark-mod
* mod is the modulus, to determine the range of possible marks
* offset determines where the mark starts from
This target only works for the "raw" and "mangle" tables.
This can be used to distribute flows between a cluster of
systems and uplinks.
Initially based on work from Hans Schillingstrom. Pablo took it
over and introduced several improvements.
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
extensions/libxt_HMARK.c | 441 ++++++++++++++++++++++++++++++++++++
extensions/libxt_HMARK.man | 60 +++++
include/linux/netfilter/xt_HMARK.h | 50 ++++
3 files changed, 551 insertions(+)
create mode 100644 extensions/libxt_HMARK.c
create mode 100644 extensions/libxt_HMARK.man
create mode 100644 include/linux/netfilter/xt_HMARK.h
diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c
new file mode 100644
index 0000000..ee2629d
--- /dev/null
+++ b/extensions/libxt_HMARK.c
@@ -0,0 +1,441 @@
+/*
+ * (C) 2012 by Hans Schillstrom <hans.schillstrom@ericsson.com>
+ * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Description: shared library add-on to iptables to add HMARK target support
+ *
+ * Initial development by Hans Schillstrom. Pablo's improvements to this piece
+ * of software has been sponsored by Sophos Astaro <http://www.sophos.com>.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "xtables.h"
+#include <linux/netfilter/xt_HMARK.h>
+
+static void HMARK_help(void)
+{
+ printf(
+"HMARK target options, i.e. modify hash calculation by:\n"
+" --hmark-tuple [src|dst|sport|dport|spi|proto|ct][,...]\n"
+" --hmark-mod value nfmark modulus value\n"
+" --hmark-offset value Last action add value to nfmark\n\n"
+" --hmark-rnd Random see for hashing\n"
+" Alternatively, fine tuning of what will be included in hash calculation\n"
+" --hmark-src-prefix length Source address mask CIDR prefix\n"
+" --hmark-dst-prefix length Dest address mask CIDR prefix\n"
+" --hmark-sport-mask value Mask src port with value\n"
+" --hmark-dport-mask value Mask dst port with value\n"
+" --hmark-spi-mask value For esp and ah AND spi with value\n"
+" --hmark-sport-set value OR src port with value\n"
+" --hmark-dport-set value OR dst port with value\n"
+" --hmark-spi-set value For esp and ah OR spi with value\n"
+" --hmark-proto-mask value Mask Protocol with value\n");
+}
+
+#define hi struct xt_hmark_info
+
+enum {
+ O_HMARK_SADDR_MASK,
+ O_HMARK_DADDR_MASK,
+ O_HMARK_SPI,
+ O_HMARK_SPI_MASK,
+ O_HMARK_SPORT,
+ O_HMARK_DPORT,
+ O_HMARK_SPORT_MASK,
+ O_HMARK_DPORT_MASK,
+ O_HMARK_PROTO_MASK,
+ O_HMARK_RND,
+ O_HMARK_MODULUS,
+ O_HMARK_OFFSET,
+ O_HMARK_CT,
+ O_HMARK_TYPE,
+};
+
+#define HMARK_OPT_PKT_MASK \
+ ((1 << O_HMARK_SADDR_MASK) | \
+ (1 << O_HMARK_DADDR_MASK) | \
+ (1 << O_HMARK_SPI_MASK) | \
+ (1 << O_HMARK_SPORT_MASK) | \
+ (1 << O_HMARK_DPORT_MASK) | \
+ (1 << O_HMARK_PROTO_MASK) | \
+ (1 << O_HMARK_SPI_MASK) | \
+ (1 << O_HMARK_SPORT) | \
+ (1 << O_HMARK_DPORT) | \
+ (1 << O_HMARK_SPI))
+
+static const struct xt_option_entry HMARK_opts[] = {
+ { .name = "hmark-tuple",
+ .type = XTTYPE_STRING,
+ .id = O_HMARK_TYPE,
+ },
+ { .name = "hmark-src-prefix",
+ .type = XTTYPE_PLENMASK,
+ .id = O_HMARK_SADDR_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, src_mask)
+ },
+ { .name = "hmark-dst-prefix",
+ .type = XTTYPE_PLENMASK,
+ .id = O_HMARK_DADDR_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, dst_mask)
+ },
+ { .name = "hmark-sport-mask",
+ .type = XTTYPE_UINT16,
+ .id = O_HMARK_SPORT_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.src)
+ },
+ { .name = "hmark-dport-mask",
+ .type = XTTYPE_UINT16,
+ .id = O_HMARK_DPORT_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.dst)
+ },
+ { .name = "hmark-spi-mask",
+ .type = XTTYPE_UINT32,
+ .id = O_HMARK_SPI_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.v32)
+ },
+ { .name = "hmark-sport",
+ .type = XTTYPE_UINT16,
+ .id = O_HMARK_SPORT,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.src)
+ },
+ { .name = "hmark-dport",
+ .type = XTTYPE_UINT16,
+ .id = O_HMARK_DPORT,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.dst)
+ },
+ { .name = "hmark-spi",
+ .type = XTTYPE_UINT32,
+ .id = O_HMARK_SPI,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.v32)
+ },
+ { .name = "hmark-proto-mask",
+ .type = XTTYPE_UINT16,
+ .id = O_HMARK_PROTO_MASK,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, proto_mask)
+ },
+ { .name = "hmark-rnd",
+ .type = XTTYPE_UINT32,
+ .id = O_HMARK_RND,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, hashrnd)
+ },
+ { .name = "hmark-mod",
+ .type = XTTYPE_UINT32,
+ .id = O_HMARK_MODULUS,
+ .min = 1,
+ .flags = XTOPT_PUT | XTOPT_MAND, XTOPT_POINTER(hi, hmodulus)
+ },
+ { .name = "hmark-offset",
+ .type = XTTYPE_UINT32,
+ .id = O_HMARK_OFFSET,
+ .flags = XTOPT_PUT, XTOPT_POINTER(hi, hoffset)
+ },
+ XTOPT_TABLEEND,
+};
+
+static int
+hmark_parse(const char *type, size_t len, struct xt_hmark_info *info,
+ unsigned int *xflags)
+{
+ if (strncasecmp(type, "ct", len) == 0) {
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
+ *xflags |= (1 << O_HMARK_CT);
+ } else if (strncasecmp(type, "src", len) == 0) {
+ memset(&info->src_mask, 0xff, sizeof(info->src_mask));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
+ *xflags |= (1 << O_HMARK_SADDR_MASK);
+ } else if (strncasecmp(type, "dst", len) == 0) {
+ memset(&info->dst_mask, 0xff, sizeof(info->dst_mask));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
+ *xflags |= (1 << O_HMARK_DADDR_MASK);
+ } else if (strncasecmp(type, "sport", len) == 0) {
+ memset(&info->port_mask.p16.src, 0xff,
+ sizeof(info->port_mask.p16.src));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
+ *xflags |= (1 << O_HMARK_SPORT_MASK);
+ } else if (strncasecmp(type, "dport", len) == 0) {
+ memset(&info->port_mask.p16.dst, 0xff,
+ sizeof(info->port_mask.p16.dst));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
+ *xflags |= (1 << O_HMARK_DPORT_MASK);
+ } else if (strncasecmp(type, "proto", len) == 0) {
+ memset(&info->proto_mask, 0xff, sizeof(info->proto_mask));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
+ *xflags |= (1 << O_HMARK_PROTO_MASK);
+ } else if (strncasecmp(type, "spi", len) == 0) {
+ memset(&info->port_mask.v32, 0xff, sizeof(info->port_mask.v32));
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
+ *xflags |= (1 << O_HMARK_SPI_MASK);
+ } else
+ return 0;
+
+ return 1;
+}
+
+static void
+hmark_parse_type(struct xt_option_call *cb)
+{
+ const char *arg = cb->arg;
+ struct xt_hmark_info *info = cb->data;
+ const char *comma;
+
+ while ((comma = strchr(arg, ',')) != NULL) {
+ if (comma == arg ||
+ !hmark_parse(arg, comma-arg, info, &cb->xflags))
+ xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg);
+ arg = comma+1;
+ }
+ if (!*arg)
+ xtables_error(PARAMETER_PROBLEM, "\"--hmark-tuple\" requires "
+ "a list of types with no "
+ "spaces, e.g. "
+ "src,dst,sport,dport,proto");
+ if (strlen(arg) == 0 ||
+ !hmark_parse(arg, strlen(arg), info, &cb->xflags))
+ xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg);
+}
+
+static void HMARK_parse(struct xt_option_call *cb, int plen)
+{
+ struct xt_hmark_info *info = cb->data;
+
+ xtables_option_parse(cb);
+
+ switch (cb->entry->id) {
+ case O_HMARK_TYPE:
+ hmark_parse_type(cb);
+ break;
+ case O_HMARK_SADDR_MASK:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
+ break;
+ case O_HMARK_DADDR_MASK:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
+ break;
+ case O_HMARK_SPI:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
+ break;
+ case O_HMARK_SPORT:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT);
+ break;
+ case O_HMARK_DPORT:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT);
+ break;
+ case O_HMARK_SPORT_MASK:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
+ break;
+ case O_HMARK_DPORT_MASK:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
+ break;
+ case O_HMARK_PROTO_MASK:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
+ break;
+ case O_HMARK_RND:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_RND);
+ break;
+ case O_HMARK_MODULUS:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_MODULUS);
+ break;
+ case O_HMARK_OFFSET:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_OFFSET);
+ break;
+ case O_HMARK_CT:
+ info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
+ break;
+ }
+ cb->xflags |= (1 << cb->entry->id);
+}
+
+static void HMARK_ip4_parse(struct xt_option_call *cb)
+{
+ HMARK_parse(cb, 32);
+}
+static void HMARK_ip6_parse(struct xt_option_call *cb)
+{
+ HMARK_parse(cb, 128);
+}
+
+static void HMARK_check(struct xt_fcheck_call *cb)
+{
+ if (!(cb->xflags & (1 << O_HMARK_MODULUS)))
+ xtables_error(PARAMETER_PROBLEM, "--hmark-mod is mandatory");
+ if (!(cb->xflags & (1 << O_HMARK_RND)))
+ xtables_error(PARAMETER_PROBLEM, "--hmark-rnd is mandatory");
+ if (cb->xflags & (1 << O_HMARK_SPI_MASK) &&
+ (cb->xflags & (1 << O_HMARK_SPORT_MASK ||
+ cb->xflags & (1 << O_HMARK_DPORT_MASK))))
+ xtables_error(PARAMETER_PROBLEM, "you cannot use "
+ "--hmark-spi-mask and --hmark-?port-mask,"
+ "at the same time");
+ if (!((cb->xflags & HMARK_OPT_PKT_MASK) ||
+ cb->xflags & (1 << O_HMARK_CT)))
+ xtables_error(PARAMETER_PROBLEM, "you have to specify "
+ "--hmark-tuple at least");
+}
+
+static void HMARK_print(const struct xt_hmark_info *info)
+{
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
+ printf("sport-mask 0x%x ", htons(info->port_mask.p16.src));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
+ printf("dport-mask 0x%x ", htons(info->port_mask.p16.dst));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
+ printf("spi-mask 0x%x ", htonl(info->port_mask.v32));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
+ printf("sport-set 0x%x ", htons(info->port_set.p16.src));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
+ printf("dport-set 0x%x ", htons(info->port_set.p16.dst));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
+ printf("spi-set 0x%x ", htonl(info->port_set.v32));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK))
+ printf("proto-mask 0x%x ", info->proto_mask);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND))
+ printf("rnd 0x%x ", info->hashrnd);
+}
+
+static void HMARK_ip6_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_hmark_info *info =
+ (const struct xt_hmark_info *)target->data;
+
+ printf(" HMARK ");
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
+ printf("mod %u ", info->hmodulus);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
+ printf("+ 0x%x ", info->hoffset);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
+ printf("ct, ");
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
+ printf("src-prefix %s ",
+ xtables_ip6mask_to_numeric(&info->src_mask.in6) + 1);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
+ printf("dst-prefix %s ",
+ xtables_ip6mask_to_numeric(&info->dst_mask.in6) + 1);
+ HMARK_print(info);
+}
+static void HMARK_ip4_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_hmark_info *info =
+ (const struct xt_hmark_info *)target->data;
+
+ printf(" HMARK ");
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
+ printf("mod %u ", info->hmodulus);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
+ printf("+ 0x%x ", info->hoffset);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
+ printf("ct, ");
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
+ printf("src-prefix %s ",
+ xtables_ipmask_to_numeric(&info->src_mask.in) + 1);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
+ printf("dst-prefix %s ",
+ xtables_ipmask_to_numeric(&info->dst_mask.in) + 1);
+ HMARK_print(info);
+}
+
+static void HMARK_save(const struct xt_hmark_info *info)
+{
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
+ printf(" --hmark-sport-mask 0x%04x",
+ htons(info->port_mask.p16.src));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
+ printf(" --hmark-dport-mask 0x%04x",
+ htons(info->port_mask.p16.dst));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
+ printf(" --hmark-spi-mask 0x%08x",
+ htonl(info->port_mask.v32));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
+ printf(" --hmark-sport-set 0x%04x",
+ htons(info->port_set.p16.src));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
+ printf(" --hmark-dport-set 0x%04x",
+ htons(info->port_set.p16.dst));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
+ printf(" --hmark-spi-set 0x%08x", htonl(info->port_set.v32));
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK))
+ printf(" --hmark-proto-mask 0x%02x", info->proto_mask);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND))
+ printf(" --hmark-rnd 0x%08x", info->hashrnd);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
+ printf(" --hmark-mod %u", info->hmodulus);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
+ printf(" --hmark-offset %u", info->hoffset);
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
+ printf(" --hmark-tuple ct");
+}
+
+static void HMARK_ip6_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_hmark_info *info =
+ (const struct xt_hmark_info *)target->data;
+ int ret;
+
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) {
+ ret = xtables_ip6mask_to_cidr(&info->src_mask.in6);
+ printf(" --hmark-src-prefix %d", ret);
+ }
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) {
+ ret = xtables_ip6mask_to_cidr(&info->dst_mask.in6);
+ printf(" --hmark-dst-prefix %d", ret);
+ }
+ HMARK_save(info);
+}
+
+static void HMARK_ip4_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_hmark_info *info =
+ (const struct xt_hmark_info *)target->data;
+ int ret;
+
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) {
+ ret = xtables_ipmask_to_cidr(&info->src_mask.in);
+ printf(" --hmark-src-prefix %d", ret);
+ }
+ if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) {
+ ret = xtables_ipmask_to_cidr(&info->dst_mask.in);
+ printf(" --hmark-dst-prefix %d", ret);
+ }
+ HMARK_save(info);
+}
+
+static struct xtables_target mark_tg_reg[] = {
+ {
+ .family = NFPROTO_IPV4,
+ .name = "HMARK",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_hmark_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
+ .help = HMARK_help,
+ .print = HMARK_ip4_print,
+ .save = HMARK_ip4_save,
+ .x6_parse = HMARK_ip4_parse,
+ .x6_fcheck = HMARK_check,
+ .x6_options = HMARK_opts,
+ },
+ {
+ .family = NFPROTO_IPV6,
+ .name = "HMARK",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_hmark_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
+ .help = HMARK_help,
+ .print = HMARK_ip6_print,
+ .save = HMARK_ip6_save,
+ .x6_parse = HMARK_ip6_parse,
+ .x6_fcheck = HMARK_check,
+ .x6_options = HMARK_opts,
+ },
+};
+
+void _init(void)
+{
+ xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
+}
diff --git a/extensions/libxt_HMARK.man b/extensions/libxt_HMARK.man
new file mode 100644
index 0000000..6b36b58
--- /dev/null
+++ b/extensions/libxt_HMARK.man
@@ -0,0 +1,60 @@
+Like MARK, i.e. set the fwmark, but the mark is calculated from hashing
+packet selector at choice. You have also to specify the mark range and,
+optionally, the offset to start from. ICMP error messages are inspected
+and used to calculate the hashing.
+.PP
+Existing options are:
+.TP
+\fB\-\-hmark\-tuple\fP tuple\fI\fP
+Possible tuple members are:
+.B src
+meaning source address (IPv4, IPv6 address),
+.B dst
+meaning destination address (IPv4, IPv6 address),
+.B sport
+meaning source port (TCP, UDP, UDPlite, SCTP, DCCP),
+.B dport
+meaning destination port (TCP, UDP, UDPlite, SCTP, DCCP),
+.B spi
+meaning Security Parameter Index (AH, ESP), and
+.B ct
+meaning the usage of the conntrack tuple instead of the packet selectors.
+.TP
+\fB\-\-hmark\-mod\fP \fIvalue (must be > 0)\fP
+Modulus for hash calculation (to limit the range of possible marks)
+.TP
+\fB\-\-hmark\-offset\fP \fIvalue\fP
+Offset to start marks from.
+.TP
+For advanced usage, instead of using \-\-hmark\-tuple, you can specify custom
+prefixes and masks:
+.TP
+\fB\-\-hmark\-src\-prefix\fP \fIcidr\fP
+The source address mask in CIDR notation.
+.TP
+\fB\-\-hmark\-dst\-prefix\fP \fIcidr\fP
+The destination address mask in CIDR notation.
+.TP
+\fB\-\-hmark\-sport\-mask\fP \fIvalue\fP
+A 16 bit source port mask in hexadecimal.
+.TP
+\fB\-\-hmark\-dport\-mask\fP \fIvalue\fP
+A 16 bit destination port mask in hexadecimal.
+.TP
+\fB\-\-hmark\-spi\-mask\fP \fIvalue\fP
+A 32 bit field with spi mask.
+.TP
+\fB\-\-hmark\-proto\-mask\fP \fIvalue\fP
+An 8 bit field with layer 4 protocol number.
+.TP
+\fB\-\-hmark\-rnd\fP \fIvalue\fP
+A 32 bit random custom value to feed hash calculation.
+.PP
+\fIExamples:\fP
+.PP
+iptables \-t mangle \-A PREROUTING \-m state \-\-state NEW
+ \-j HMARK \-\-hmark-tuple ct \-\-hmark-offset 10000 \-\-hmark\-mod 10
+\-\-hmark\-rnd 0xfeedcafe
+.PP
+iptables \-t mangle \-A PREROUTING -j HMARK \-\-hmark-tuple src,dst,proto
+\-\-hmark-mod 10 \-\-hmark\-rand 0xdeafbeef
diff --git a/include/linux/netfilter/xt_HMARK.h b/include/linux/netfilter/xt_HMARK.h
new file mode 100644
index 0000000..826fc58
--- /dev/null
+++ b/include/linux/netfilter/xt_HMARK.h
@@ -0,0 +1,50 @@
+#ifndef XT_HMARK_H_
+#define XT_HMARK_H_
+
+#include <linux/types.h>
+
+enum {
+ XT_HMARK_SADDR_MASK,
+ XT_HMARK_DADDR_MASK,
+ XT_HMARK_SPI,
+ XT_HMARK_SPI_MASK,
+ XT_HMARK_SPORT,
+ XT_HMARK_DPORT,
+ XT_HMARK_SPORT_MASK,
+ XT_HMARK_DPORT_MASK,
+ XT_HMARK_PROTO_MASK,
+ XT_HMARK_RND,
+ XT_HMARK_MODULUS,
+ XT_HMARK_OFFSET,
+ XT_HMARK_CT,
+ XT_HMARK_METHOD_L3,
+ XT_HMARK_METHOD_L3_4,
+};
+#define XT_HMARK_FLAG(flag) (1 << flag)
+
+union hmark_ports {
+ struct {
+ __u16 src;
+ __u16 dst;
+ } p16;
+ struct {
+ __be16 src;
+ __be16 dst;
+ } b16;
+ __u32 v32;
+ __be32 b32;
+};
+
+struct xt_hmark_info {
+ union nf_inet_addr src_mask;
+ union nf_inet_addr dst_mask;
+ union hmark_ports port_mask;
+ union hmark_ports port_set;
+ __u32 flags;
+ __u16 proto_mask;
+ __u32 hashrnd;
+ __u32 hmodulus;
+ __u32 hoffset; /* Mark offset to start from */
+};
+
+#endif /* XT_HMARK_H_ */
--
1.7.10
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-07-16 12:22 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-12 7:34 [PATCH 2/2] extensions: add HMARK target Hans Schillstrom
2012-07-12 15:29 ` Pablo Neira Ayuso
-- strict thread matches above, loose matches on Subject: below --
2012-07-14 22:53 Re[2]: " Hans Schillstrom
2012-07-16 12:22 ` Pablo Neira Ayuso
2012-07-12 7:29 Hans Schillstrom
2012-07-10 23:17 [PATCH 0/2] revamped HMARK extension pablo
2012-07-10 23:17 ` [PATCH 2/2] extensions: add HMARK target pablo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).