* [PATCH 4/5][IPTABLES]: libxt_CONNMARK revision 1
2008-01-24 19:01 [PATCH 1/5][IPTABLES]: Import netfilter.h Jan Engelhardt
2008-01-24 19:01 ` [PATCH 2/5][IPTABLES]: Give preference to iptables header files Jan Engelhardt
2008-01-24 19:02 ` [PATCH 3/5][IPTABLES]: Build adjustments Jan Engelhardt
@ 2008-01-24 19:02 ` Jan Engelhardt
2008-01-29 13:19 ` Patrick McHardy
2008-01-24 19:02 ` [PATCH 5/5][IPTABLES]: libxt_hashlimit " Jan Engelhardt
2008-01-29 13:10 ` [PATCH 1/5][IPTABLES]: Import netfilter.h Patrick McHardy
4 siblings, 1 reply; 11+ messages in thread
From: Jan Engelhardt @ 2008-01-24 19:02 UTC (permalink / raw)
To: kaber; +Cc: Netfilter Developer Mailing List
Add support for xt_CONNMARK target revision 1.
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
---
extensions/libxt_CONNMARK.c | 267 ++++++++++++++++++++++++++++++++--
extensions/libxt_CONNMARK.man | 65 ++++++--
include/linux/netfilter/xt_CONNMARK.h | 5
3 files changed, 315 insertions(+), 22 deletions(-)
Index: iptables/extensions/libxt_CONNMARK.c
===================================================================
--- iptables.orig/extensions/libxt_CONNMARK.c
+++ iptables/extensions/libxt_CONNMARK.c
@@ -28,12 +28,10 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_CONNMARK.h>
-#if 0
-struct markinfo {
- struct xt_entry_target t;
- struct ipt_connmark_target_info mark;
+enum {
+ F_MARK = 1 << 0,
+ F_SR_MARK = 1 << 1,
};
-#endif
/* Function which prints out usage message. */
static void CONNMARK_help(void)
@@ -55,6 +53,53 @@ static const struct option CONNMARK_opts
{ }
};
+static const struct option connmark_tg_opts[] = {
+ {.name = "set-xmark", .has_arg = true, .val = '='},
+ {.name = "set-mark", .has_arg = true, .val = '-'},
+ {.name = "and-mark", .has_arg = true, .val = '&'},
+ {.name = "or-mark", .has_arg = true, .val = '|'},
+ {.name = "xor-mark", .has_arg = true, .val = '^'},
+ {.name = "save-mark", .has_arg = false, .val = 'S'},
+ {.name = "restore-mark", .has_arg = false, .val = 'R'},
+ {.name = "ctmask", .has_arg = true, .val = 'c'},
+ {.name = "nfmask", .has_arg = true, .val = 'n'},
+ {.name = "mask", .has_arg = true, .val = 'm'},
+ {},
+};
+
+static void connmark_tg_help(void)
+{
+ printf(
+"CONNMARK target options:\n"
+" XOR-based operations:\n"
+" --set-xmark value[/ctmask] Zero mask bits and XOR ctmark with value\n"
+" --save-mark [--ctmask mask] [--nfmask mask]\n"
+" Copy ctmark to nfmark using masks\n"
+" --restore-mark [--ctmask mask] [--nfmask mask]\n"
+" Copy nfmark to ctmark using masks\n"
+" OR-based operations:\n"
+" --set-mark value[/mask] Set conntrack mark value\n"
+" --save-mark [--mask mask] Save the packet nfmark in the connection\n"
+" --restore-mark [--mask mask] Restore saved nfmark value\n"
+" Other operations:\n"
+" --and-mark value Binary AND the ctmark with bits\n"
+" --or-mark value Binary OR the ctmark with bits\n"
+" --xor-mark value Binary XOR the ctmark with bits\n"
+);
+}
+
+static void connmark_tg_init(struct xt_entry_target *target)
+{
+ struct xt_connmark_tginfo1 *info = (void *)target->data;
+
+ /*
+ * Need these defaults for --save-mark/--restore-mark if no
+ * --ctmark or --nfmask is given.
+ */
+ info->ctmask = ~0U;
+ info->nfmask = ~0U;
+}
+
/* Function which parses command options; returns true if it
ate an option */
static int
@@ -110,7 +155,110 @@ CONNMARK_parse(int c, char **argv, int i
return 1;
}
-static void CONNMARK_check(unsigned int flags)
+static int connmark_tg_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ struct xt_connmark_tginfo1 *info = (void *)(*target)->data;
+ unsigned int value, mask = ~0U;
+ char *end;
+
+ switch (c) {
+ case '=': /* --set-xmark */
+ case '-': /* --set-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!strtonum(optarg, &end, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+ if (*end == '/')
+ if (!strtonum(end + 1, &end, &mask, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+ if (*end != '\0')
+ param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = value;
+ info->ctmask = mask;
+ if (c == '-')
+ info->ctmask |= value;
+ *flags |= F_MARK;
+ return true;
+
+ case '&': /* --and-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!strtonum(optarg, NULL, &mask, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--and-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = 0;
+ info->ctmask = ~mask;
+ *flags |= F_MARK;
+ return true;
+
+ case '|': /* --or-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!strtonum(optarg, NULL, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--or-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = value;
+ info->ctmask = value;
+ *flags |= F_MARK;
+ return true;
+
+ case '^': /* --xor-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!strtonum(optarg, NULL, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--xor-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = value;
+ info->ctmask = 0;
+ *flags |= F_MARK;
+ return true;
+
+ case 'S': /* --save-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ info->mode = XT_CONNMARK_SAVE;
+ *flags |= F_MARK | F_SR_MARK;
+ return true;
+
+ case 'R': /* --restore-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ info->mode = XT_CONNMARK_RESTORE;
+ *flags |= F_MARK | F_SR_MARK;
+ return true;
+
+ case 'n': /* --nfmask */
+ if (!(*flags & F_SR_MARK))
+ exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+ "or --restore-mark is required for "
+ "--nfmask");
+ if (!strtonum(optarg, NULL, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--nfmask", optarg);
+ info->nfmask = value;
+ return true;
+
+ case 'c': /* --ctmask */
+ if (!(*flags & F_SR_MARK))
+ exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+ "or --restore-mark is required for "
+ "--ctmask");
+ if (!strtonum(optarg, NULL, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--ctmask", optarg);
+ info->ctmask = value;
+ return true;
+
+ case 'm': /* --mask */
+ if (!(*flags & F_SR_MARK))
+ exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+ "or --restore-mark is required for "
+ "--mask");
+ if (!strtonum(optarg, NULL, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--mask", optarg);
+ info->nfmask = info->ctmask = value;
+ return true;
+ }
+
+ return false;
+}
+
+static void connmark_tg_check(unsigned int flags)
{
if (!flags)
exit_error(PARAMETER_PROBLEM,
@@ -159,6 +307,50 @@ static void CONNMARK_print(const void *i
}
}
+static void
+connmark_tg_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_connmark_tginfo1 *info = (const void *)target->data;
+
+ switch (info->mode) {
+ case XT_CONNMARK_SET:
+ if (info->ctmark == 0)
+ printf("CONNMARK and 0x%x ",
+ (unsigned int)(u_int32_t)~info->ctmask);
+ else if (info->ctmark == info->ctmask)
+ printf("CONNMARK or 0x%x ", info->ctmark);
+ else if (info->ctmask == 0)
+ printf("CONNMARK xor 0x%x ", info->ctmark);
+ else
+ printf("CONNMARK xset 0x%x/0x%x ",
+ info->ctmark, info->ctmask);
+ break;
+ case XT_CONNMARK_SAVE:
+ if (info->nfmask == ~0U && info->ctmask == ~0U)
+ printf("CONNMARK save ");
+ else if (info->nfmask == info->ctmask)
+ printf("CONNMARK save mask 0x%x ", info->nfmask);
+ else
+ printf("CONNMARK save nfmask 0x%x ctmask ~0x%x ",
+ info->nfmask, info->ctmask);
+ break;
+ case XT_CONNMARK_RESTORE:
+ if (info->ctmask == ~0U && info->nfmask == ~0U)
+ printf("CONNMARK restore ");
+ else if (info->ctmask == info->nfmask)
+ printf("CONNMARK restore mask 0x%x ", info->ctmask);
+ else
+ printf("CONNMARK restore ctmask 0x%x nfmask ~0x%x ",
+ info->ctmask, info->nfmask);
+ break;
+
+ default:
+ printf("ERROR: UNKNOWN CONNMARK MODE");
+ break;
+ }
+}
+
/* Saves the target into in parsable form to stdout. */
static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
{
@@ -194,16 +386,40 @@ static void CONNMARK_init(struct xt_entr
markinfo->mask = 0xffffffffUL;
}
+static void
+connmark_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_connmark_tginfo1 *info = (const void *)target->data;
+
+ switch (info->mode) {
+ case XT_CONNMARK_SET:
+ printf("--set-xmark 0x%x/0x%x ", info->ctmark, info->ctmask);
+ break;
+ case XT_CONNMARK_SAVE:
+ printf("--save-mark --nfmask 0x%x --ctmask 0x%x ",
+ info->nfmask, info->ctmask);
+ break;
+ case XT_CONNMARK_RESTORE:
+ printf("--restore-mark --nfmask 0x%x --ctmask 0x%x ",
+ info->nfmask, info->ctmask);
+ break;
+ default:
+ printf("ERROR: UNKNOWN CONNMARK MODE");
+ break;
+ }
+}
+
static struct xtables_target connmark_target = {
.family = AF_INET,
.name = "CONNMARK",
+ .revision = 0,
.version = IPTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
.help = CONNMARK_help,
.init = CONNMARK_init,
.parse = CONNMARK_parse,
- .final_check = CONNMARK_check,
+ .final_check = connmark_tg_check,
.print = CONNMARK_print,
.save = CONNMARK_save,
.extra_opts = CONNMARK_opts,
@@ -212,20 +428,55 @@ static struct xtables_target connmark_ta
static struct xtables_target connmark_target6 = {
.family = AF_INET6,
.name = "CONNMARK",
+ .revision = 0,
.version = IPTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
.help = CONNMARK_help,
.init = CONNMARK_init,
.parse = CONNMARK_parse,
- .final_check = CONNMARK_check,
+ .final_check = connmark_tg_check,
.print = CONNMARK_print,
.save = CONNMARK_save,
.extra_opts = CONNMARK_opts,
};
+static struct xtables_target connmark_tg_reg = {
+ .version = IPTABLES_VERSION,
+ .name = "CONNMARK",
+ .revision = 1,
+ .family = AF_INET,
+ .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
+ .help = connmark_tg_help,
+ .init = connmark_tg_init,
+ .parse = connmark_tg_parse,
+ .final_check = connmark_tg_check,
+ .print = connmark_tg_print,
+ .save = connmark_tg_save,
+ .extra_opts = connmark_tg_opts,
+};
+
+static struct xtables_target connmark_tg6_reg = {
+ .version = IPTABLES_VERSION,
+ .name = "CONNMARK",
+ .revision = 1,
+ .family = AF_INET6,
+ .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
+ .help = connmark_tg_help,
+ .init = connmark_tg_init,
+ .parse = connmark_tg_parse,
+ .final_check = connmark_tg_check,
+ .print = connmark_tg_print,
+ .save = connmark_tg_save,
+ .extra_opts = connmark_tg_opts,
+};
+
void _init(void)
{
xtables_register_target(&connmark_target);
xtables_register_target(&connmark_target6);
+ xtables_register_target(&connmark_tg_reg);
+ xtables_register_target(&connmark_tg6_reg);
}
Index: iptables/extensions/libxt_CONNMARK.man
===================================================================
--- iptables.orig/extensions/libxt_CONNMARK.man
+++ iptables/extensions/libxt_CONNMARK.man
@@ -1,15 +1,52 @@
-This module sets the netfilter mark value associated with a connection
+This module sets the netfilter mark value associated with a connection.
.TP
-.B --set-mark mark[/mask]
-Set connection mark. If a mask is specified then only those bits set in the
-mask is modified.
-.TP
-.B --save-mark [--mask mask]
-Copy the netfilter packet mark value to the connection mark. If a mask
-is specified then only those bits are copied.
-.TP
-.B --restore-mark [--mask mask]
-Copy the connection mark value to the packet. If a mask is specified
-then only those bits are copied. This is only valid in the
-.B mangle
-table.
+\fB--set-xmark\fR \fIvalue\fR[\fB/\fR\fImask\fR]
+Zero out the bits given by \fImask\fR and XOR \fIvalue\fR into the ctmark.
+.TP
+\fB--save-mark\fR [\fB--nfmask\fR \fInfmask\fR] [\fB--ctmask\fR \fIctmask\fR]
+Copy the packet mark (nfmark) to the connection mark (ctmark) using the given
+masks. The new nfmark value is determined as follows:
+.IP
+ctmark = (ctmark & ~ctmask) ^ (nfmark & nfmask)
+.IP
+i.e. \fIctmask\fR defines what bits to clear and \fInfmask\fR what bits of the
+nfmark to XOR into the ctmark. \fIctmask\fR and \fInfmask\fR default to
+0xFFFFFFFF.
+.TP
+\fB--restore-mark\fR [\fB--nfmask\fR \fInfmask\fR] [\fB--ctmask\fR \fIctmask\fR]
+Copy the connection mark (ctmark) to the packet mark (nfmark) using the given
+masks. The new ctmark value is determined as follows:
+.IP
+nfmark = (nfmark & ~\fInfmask\fR) ^ (ctmark & \fIctmask\fR);
+.IP
+i.e. \fInfmask\fR defines what bits to clear and \fIctmask\fR what bits of the
+ctmark to XOR into the nfmark. \fIctmask\fR and \fInfmask\fR default to
+0xFFFFFFFF.
+.IP
+\fB--restore-mark\fR is only valid in the \fBmangle\fR table.
+.PP
+The following mnemonics are available for \fB--set-xmark\fR:
+.TP
+\fB--and-mark\fR \fIbits\fR
+Binary AND the ctmark with \fIbits\fR. (Mnemonic for \fB--set-xmark
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB--or-mark\fR \fIbits\fR
+Binary OR the ctmark with \fIbits\fR. (Mnemonic for \fB--set-xmark\fR
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB--xor-mark\fR \fIbits\fR
+Binary XOR the ctmark with \fIbits\fR. (Mnemonic for \fB--set-xmark\fR
+\fIbits\fR\fB/0\fR.)
+.TP
+\fB--set-mark\fR \fIvalue\fR[\fB/\fR\fImask\fR]
+Set the connection mark. If a mask is specified then only those bits set in the
+mask are modified.
+.TP
+\fB--save-mark\fR [\fB--mask\fR \fImask\fR]
+Copy the nfmark to the ctmark. If a mask is specified, only those bits are
+copied.
+.TP
+\fB--restore-mark\fR [\fB--mask\fR \fImask\fR]
+Copy the ctmark to the nfmark. If a mask is specified, only those bits are
+copied. This is only valid in the \fBmangle\fR table.
Index: iptables/include/linux/netfilter/xt_CONNMARK.h
===================================================================
--- iptables.orig/include/linux/netfilter/xt_CONNMARK.h
+++ iptables/include/linux/netfilter/xt_CONNMARK.h
@@ -22,4 +22,9 @@ struct xt_connmark_target_info {
u_int8_t mode;
};
+struct xt_connmark_tginfo1 {
+ u_int32_t ctmark, ctmask, nfmask;
+ u_int8_t mode;
+};
+
#endif /*_XT_CONNMARK_H_target*/
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 5/5][IPTABLES]: libxt_hashlimit revision 1
2008-01-24 19:01 [PATCH 1/5][IPTABLES]: Import netfilter.h Jan Engelhardt
` (2 preceding siblings ...)
2008-01-24 19:02 ` [PATCH 4/5][IPTABLES]: libxt_CONNMARK revision 1 Jan Engelhardt
@ 2008-01-24 19:02 ` Jan Engelhardt
2008-01-29 13:10 ` [PATCH 1/5][IPTABLES]: Import netfilter.h Patrick McHardy
4 siblings, 0 replies; 11+ messages in thread
From: Jan Engelhardt @ 2008-01-24 19:02 UTC (permalink / raw)
To: kaber; +Cc: Netfilter Developer Mailing List
Add support for xt_hashlimit match revision 1.
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
---
extensions/libxt_hashlimit.c | 398 ++++++++++++++++++++++++++++++---
extensions/libxt_hashlimit.man | 80 ++++--
include/linux/netfilter/xt_hashlimit.h | 39 ++-
3 files changed, 456 insertions(+), 61 deletions(-)
Index: iptables/extensions/libxt_hashlimit.c
===================================================================
--- iptables.orig/extensions/libxt_hashlimit.c
+++ iptables/extensions/libxt_hashlimit.c
@@ -10,7 +10,7 @@
*
* Error corections by nmalykh@bilim.com (22.01.2005)
*/
-
+#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -45,6 +45,27 @@ static void hashlimit_help(void)
"\n", IPTABLES_VERSION, XT_HASHLIMIT_BURST);
}
+static void hashlimit_mt_help(void)
+{
+ printf(
+"hashlimit match options:\n"
+" --hashlimit-upto <avg> max average match rate\n"
+" [Packets per second unless followed by \n"
+" /sec /minute /hour /day postfixes]\n"
+" --hashlimit-above <avg> min average match rate\n"
+" --hashlimit-mode <mode> mode is a comma-separated list of\n"
+" dstip,srcip,dstport,srcport (or none)\n"
+" --hashlimit-srcmask <length> source address grouping prefix length\n"
+" --hashlimit-dstmask <length> destination address grouping prefix length\n"
+" --hashlimit-name <name> name for /proc/net/ipt_hashlimit\n"
+" --hashlimit-burst <num> number to match in a burst, default %u\n"
+" --hashlimit-htable-size <num> number of hashtable buckets\n"
+" --hashlimit-htable-max <num> number of hashtable entries\n"
+" --hashlimit-htable-gcinterval interval between garbage collection runs\n"
+" --hashlimit-htable-expire after which time are idle entries expired?\n"
+"\n", XT_HASHLIMIT_BURST);
+}
+
static const struct option hashlimit_opts[] = {
{ "hashlimit", 1, NULL, '%' },
{ "hashlimit-burst", 1, NULL, '$' },
@@ -57,6 +78,22 @@ static const struct option hashlimit_opt
{ }
};
+static const struct option hashlimit_mt_opts[] = {
+ {.name = "hashlimit-upto", .has_arg = true, .val = '%'},
+ {.name = "hashlimit-above", .has_arg = true, .val = '^'},
+ {.name = "hashlimit", .has_arg = true, .val = '%'},
+ {.name = "hashlimit-srcmask", .has_arg = true, .val = '<'},
+ {.name = "hashlimit-dstmask", .has_arg = true, .val = '>'},
+ {.name = "hashlimit-burst", .has_arg = true, .val = '$'},
+ {.name = "hashlimit-htable-size", .has_arg = true, .val = '&'},
+ {.name = "hashlimit-htable-max", .has_arg = true, .val = '*'},
+ {.name = "hashlimit-htable-gcinterval", .has_arg = true, .val = '('},
+ {.name = "hashlimit-htable-expire", .has_arg = true, .val = ')'},
+ {.name = "hashlimit-mode", .has_arg = true, .val = '_'},
+ {.name = "hashlimit-name", .has_arg = true, .val = '"'},
+ {},
+};
+
static
int parse_rate(const char *rate, u_int32_t *val)
{
@@ -98,15 +135,39 @@ static void hashlimit_init(struct xt_ent
{
struct xt_hashlimit_info *r = (struct xt_hashlimit_info *)m->data;
+ r->cfg.mode = 0;
r->cfg.burst = XT_HASHLIMIT_BURST;
r->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
r->cfg.expire = XT_HASHLIMIT_EXPIRE;
}
+static void hashlimit_mt4_init(struct xt_entry_match *match)
+{
+ struct xt_hashlimit_mtinfo1 *info = (void *)match->data;
+
+ info->cfg.mode = 0;
+ info->cfg.burst = XT_HASHLIMIT_BURST;
+ info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
+ info->cfg.expire = XT_HASHLIMIT_EXPIRE;
+ info->cfg.srcmask = 32;
+ info->cfg.dstmask = 32;
+}
+
+static void hashlimit_mt6_init(struct xt_entry_match *match)
+{
+ struct xt_hashlimit_mtinfo1 *info = (void *)match->data;
+
+ info->cfg.mode = 0;
+ info->cfg.burst = XT_HASHLIMIT_BURST;
+ info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
+ info->cfg.expire = XT_HASHLIMIT_EXPIRE;
+ info->cfg.srcmask = 128;
+ info->cfg.dstmask = 128;
+}
/* Parse a 'mode' parameter into the required bitmask */
-static int parse_mode(struct xt_hashlimit_info *r, char *optarg)
+static int parse_mode(uint32_t *mode, const char *optarg)
{
char *tok;
char *arg = strdup(optarg);
@@ -114,19 +175,17 @@ static int parse_mode(struct xt_hashlimi
if (!arg)
return -1;
- r->cfg.mode = 0;
-
for (tok = strtok(arg, ",|");
tok;
tok = strtok(NULL, ",|")) {
if (!strcmp(tok, "dstip"))
- r->cfg.mode |= XT_HASHLIMIT_HASH_DIP;
+ *mode |= XT_HASHLIMIT_HASH_DIP;
else if (!strcmp(tok, "srcip"))
- r->cfg.mode |= XT_HASHLIMIT_HASH_SIP;
+ *mode |= XT_HASHLIMIT_HASH_SIP;
else if (!strcmp(tok, "srcport"))
- r->cfg.mode |= XT_HASHLIMIT_HASH_SPT;
+ *mode |= XT_HASHLIMIT_HASH_SPT;
else if (!strcmp(tok, "dstport"))
- r->cfg.mode |= XT_HASHLIMIT_HASH_DPT;
+ *mode |= XT_HASHLIMIT_HASH_DPT;
else {
free(arg);
return -1;
@@ -136,14 +195,18 @@ static int parse_mode(struct xt_hashlimi
return 0;
}
-#define PARAM_LIMIT 0x00000001
-#define PARAM_BURST 0x00000002
-#define PARAM_MODE 0x00000004
-#define PARAM_NAME 0x00000008
-#define PARAM_SIZE 0x00000010
-#define PARAM_MAX 0x00000020
-#define PARAM_GCINTERVAL 0x00000040
-#define PARAM_EXPIRE 0x00000080
+enum {
+ PARAM_LIMIT = 1 << 0,
+ PARAM_BURST = 1 << 1,
+ PARAM_MODE = 1 << 2,
+ PARAM_NAME = 1 << 3,
+ PARAM_SIZE = 1 << 4,
+ PARAM_MAX = 1 << 5,
+ PARAM_GCINTERVAL = 1 << 6,
+ PARAM_EXPIRE = 1 << 7,
+ PARAM_SRCMASK = 1 << 8,
+ PARAM_DSTMASK = 1 << 9,
+};
/* Function which parses command options; returns true if it
ate an option */
@@ -224,7 +287,7 @@ hashlimit_parse(int c, char **argv, int
param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-mode",
*flags & PARAM_MODE);
if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (parse_mode(r, optarg) < 0)
+ if (parse_mode(&r->cfg.mode, optarg) < 0)
exit_error(PARAMETER_PROBLEM,
"bad --hashlimit-mode: `%s'\n", optarg);
*flags |= PARAM_MODE;
@@ -249,6 +312,146 @@ hashlimit_parse(int c, char **argv, int
return 1;
}
+static int
+hashlimit_mt_parse(struct xt_hashlimit_mtinfo1 *info, unsigned int *flags,
+ int c, int invert, unsigned int maxmask)
+{
+ unsigned int num;
+
+ switch(c) {
+ case '%': /* --hashlimit / --hashlimit-below */
+ param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-upto",
+ *flags & PARAM_LIMIT);
+ if (invert)
+ info->cfg.mode |= XT_HASHLIMIT_INVERT;
+ if (!parse_rate(optarg, &info->cfg.avg))
+ param_act(P_BAD_VALUE, "hashlimit",
+ "--hashlimit-upto", optarg);
+ *flags |= PARAM_LIMIT;
+ return true;
+
+ case '^': /* --hashlimit-above == !--hashlimit-below */
+ param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-above",
+ *flags & PARAM_LIMIT);
+ if (!invert)
+ info->cfg.mode |= XT_HASHLIMIT_INVERT;
+ if (!parse_rate(optarg, &info->cfg.avg))
+ param_act(P_BAD_VALUE, "hashlimit",
+ "--hashlimit-above", optarg);
+ *flags |= PARAM_LIMIT;
+ return true;
+
+ case '$': /* --hashlimit-burst */
+ param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-burst",
+ *flags & PARAM_BURST);
+ if (!strtonum(optarg, NULL, &num, 0, 10000))
+ param_act(P_BAD_VALUE, "hashlimit",
+ "--hashlimit-burst", optarg);
+ info->cfg.burst = num;
+ *flags |= PARAM_BURST;
+ return true;
+
+ case '&': /* --hashlimit-htable-size */
+ param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size",
+ *flags & PARAM_SIZE);
+ if (!strtonum(optarg, NULL, &num, 0, 0xffffffff))
+ param_act(P_BAD_VALUE, "hashlimit",
+ "--hashlimit-htable-size", optarg);
+ info->cfg.size = num;
+ *flags |= PARAM_SIZE;
+ return true;
+
+ case '*': /* --hashlimit-htable-max */
+ param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max",
+ *flags & PARAM_MAX);
+ if (!strtonum(optarg, NULL, &num, 0, 0xffffffff))
+ param_act(P_BAD_VALUE, "hashlimit",
+ "--hashlimit-htable-max", optarg);
+ info->cfg.max = num;
+ *flags |= PARAM_MAX;
+ return true;
+
+ case '(': /* --hashlimit-htable-gcinterval */
+ param_act(P_ONLY_ONCE, "hashlimit",
+ "--hashlimit-htable-gcinterval",
+ *flags & PARAM_GCINTERVAL);
+ if (!strtonum(optarg, NULL, &num, 0, 0xffffffff))
+ param_act(P_BAD_VALUE, "hashlimit",
+ "--hashlimit-htable-gcinterval", optarg);
+ /* FIXME: not HZ dependent!! */
+ info->cfg.gc_interval = num;
+ *flags |= PARAM_GCINTERVAL;
+ return true;
+
+ case ')': /* --hashlimit-htable-expire */
+ param_act(P_ONLY_ONCE, "hashlimit",
+ "--hashlimit-htable-expire", *flags & PARAM_EXPIRE);
+ if (!strtonum(optarg, NULL, &num, 0, 0xffffffff))
+ param_act(P_BAD_VALUE, "hashlimit",
+ "--hashlimit-htable-expire", optarg);
+ /* FIXME: not HZ dependent */
+ info->cfg.expire = num;
+ *flags |= PARAM_EXPIRE;
+ return true;
+
+ case '_':
+ param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-mode",
+ *flags & PARAM_MODE);
+ if (parse_mode(&info->cfg.mode, optarg) < 0)
+ param_act(P_BAD_VALUE, "hashlimit",
+ "--hashlimit-mode", optarg);
+ *flags |= PARAM_MODE;
+ return true;
+
+ case '"': /* --hashlimit-name */
+ param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-name",
+ *flags & PARAM_NAME);
+ if (strlen(optarg) == 0)
+ exit_error(PARAMETER_PROBLEM, "Zero-length name?");
+ strncpy(info->name, optarg, sizeof(info->name));
+ info->name[sizeof(info->name)-1] = '\0';
+ *flags |= PARAM_NAME;
+ return true;
+
+ case '<': /* --hashlimit-srcmask */
+ param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-srcmask",
+ *flags & PARAM_SRCMASK);
+ if (!strtonum(optarg, NULL, &num, 0, maxmask))
+ param_act(P_BAD_VALUE, "hashlimit",
+ "--hashlimit-srcmask", optarg);
+ info->cfg.srcmask = num;
+ *flags |= PARAM_SRCMASK;
+ return true;
+
+ case '>': /* --hashlimit-dstmask */
+ param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-dstmask",
+ *flags & PARAM_DSTMASK);
+ if (!strtonum(optarg, NULL, &num, 0, maxmask))
+ param_act(P_BAD_VALUE, "hashlimit",
+ "--hashlimit-dstmask", optarg);
+ info->cfg.dstmask = num;
+ *flags |= PARAM_DSTMASK;
+ return true;
+ }
+ return false;
+}
+
+static int
+hashlimit_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ return hashlimit_mt_parse((void *)(*match)->data,
+ flags, c, invert, 32);
+}
+
+static int
+hashlimit_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ return hashlimit_mt_parse((void *)(*match)->data,
+ flags, c, invert, 128);
+}
+
/* Final check; nothing. */
static void hashlimit_check(unsigned int flags)
{
@@ -263,6 +466,16 @@ static void hashlimit_check(unsigned int
"You have to specify --hashlimit-name");
}
+static void hashlimit_mt_check(unsigned int flags)
+{
+ if (!(flags & PARAM_LIMIT))
+ exit_error(PARAMETER_PROBLEM, "You have to specify "
+ "--hashlimit-upto or --hashlimit-above");
+ if (!(flags & PARAM_NAME))
+ exit_error(PARAMETER_PROBLEM,
+ "You have to specify --hashlimit-name");
+}
+
static const struct rates
{
const char *name;
@@ -285,29 +498,27 @@ static void print_rate(u_int32_t period)
printf("%u/%s ", rates[i-1].mult / period, rates[i-1].name);
}
-static void print_mode(const struct xt_hashlimit_info *r, char separator)
+static void print_mode(unsigned int mode, char separator)
{
- int prevmode = 0;
+ bool prevmode = false;
- if (r->cfg.mode & XT_HASHLIMIT_HASH_SIP) {
- if (prevmode)
- putchar(separator);
+ if (mode & XT_HASHLIMIT_HASH_SIP) {
fputs("srcip", stdout);
prevmode = 1;
}
- if (r->cfg.mode & XT_HASHLIMIT_HASH_SPT) {
+ if (mode & XT_HASHLIMIT_HASH_SPT) {
if (prevmode)
putchar(separator);
fputs("srcport", stdout);
prevmode = 1;
}
- if (r->cfg.mode & XT_HASHLIMIT_HASH_DIP) {
+ if (mode & XT_HASHLIMIT_HASH_DIP) {
if (prevmode)
putchar(separator);
fputs("dstip", stdout);
prevmode = 1;
}
- if (r->cfg.mode & XT_HASHLIMIT_HASH_DPT) {
+ if (mode & XT_HASHLIMIT_HASH_DPT) {
if (prevmode)
putchar(separator);
fputs("dstport", stdout);
@@ -324,7 +535,7 @@ static void hashlimit_print(const void *
fputs("limit: avg ", stdout); print_rate(r->cfg.avg);
printf("burst %u ", r->cfg.burst);
fputs("mode ", stdout);
- print_mode(r, '-');
+ print_mode(r->cfg.mode, '-');
if (r->cfg.size)
printf("htable-size %u ", r->cfg.size);
if (r->cfg.max)
@@ -335,6 +546,53 @@ static void hashlimit_print(const void *
printf("htable-expire %u ", r->cfg.expire);
}
+static void
+hashlimit_mt_print(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask)
+{
+ if (info->cfg.mode & XT_HASHLIMIT_INVERT)
+ fputs("limit: above ", stdout);
+ else
+ fputs("limit: up to ", stdout);
+ print_rate(info->cfg.avg);
+ printf("burst %u ", info->cfg.burst);
+ if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
+ XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
+ fputs("mode ", stdout);
+ print_mode(info->cfg.mode, '-');
+ }
+ if (info->cfg.size != 0)
+ printf("htable-size %u ", info->cfg.size);
+ if (info->cfg.max != 0)
+ printf("htable-max %u ", info->cfg.max);
+ if (info->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
+ printf("htable-gcinterval %u ", info->cfg.gc_interval);
+ if (info->cfg.expire != XT_HASHLIMIT_EXPIRE)
+ printf("htable-expire %u ", info->cfg.expire);
+
+ if (info->cfg.srcmask != dmask)
+ printf("srcmask %u ", info->cfg.srcmask);
+ if (info->cfg.dstmask != dmask)
+ printf("dstmask %u ", info->cfg.dstmask);
+}
+
+static void
+hashlimit_mt4_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
+
+ hashlimit_mt_print(info, 32);
+}
+
+static void
+hashlimit_mt6_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
+
+ hashlimit_mt_print(info, 128);
+}
+
/* FIXME: Make minimalist: only print rate if not default --RR */
static void hashlimit_save(const void *ip, const struct xt_entry_match *match)
{
@@ -346,7 +604,7 @@ static void hashlimit_save(const void *i
printf("--hashlimit-burst %u ", r->cfg.burst);
fputs("--hashlimit-mode ", stdout);
- print_mode(r, ',');
+ print_mode(r->cfg.mode, ',');
printf("--hashlimit-name %s ", r->name);
@@ -360,10 +618,61 @@ static void hashlimit_save(const void *i
printf("--hashlimit-htable-expire %u ", r->cfg.expire);
}
+static void
+hashlimit_mt_save(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask)
+{
+ if (info->cfg.mode & XT_HASHLIMIT_INVERT)
+ fputs("--hashlimit-above ", stdout);
+ else
+ fputs("--hashlimit-upto ", stdout);
+ print_rate(info->cfg.avg);
+ if (info->cfg.burst != XT_HASHLIMIT_BURST)
+ printf("--hashlimit-burst %u ", info->cfg.burst);
+
+ if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
+ XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
+ fputs("--hashlimit-mode ", stdout);
+ print_mode(info->cfg.mode, ',');
+ }
+
+ printf("--hashlimit-name %s ", info->name);
+
+ if (info->cfg.size != 0)
+ printf("--hashlimit-htable-size %u ", info->cfg.size);
+ if (info->cfg.max != 0)
+ printf("--hashlimit-htable-max %u ", info->cfg.max);
+ if (info->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
+ printf("--hashlimit-htable-gcinterval %u", info->cfg.gc_interval);
+ if (info->cfg.expire != XT_HASHLIMIT_EXPIRE)
+ printf("--hashlimit-htable-expire %u ", info->cfg.expire);
+
+ if (info->cfg.srcmask != dmask)
+ printf("--hashlimit-srcmask %u ", info->cfg.srcmask);
+ if (info->cfg.dstmask != dmask)
+ printf("--hashlimit-dstmask %u ", info->cfg.dstmask);
+}
+
+static void
+hashlimit_mt4_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
+
+ hashlimit_mt_save(info, 32);
+}
+
+static void
+hashlimit_mt6_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
+
+ hashlimit_mt_save(info, 128);
+}
+
static struct xtables_match hashlimit_match = {
.family = AF_INET,
.name = "hashlimit",
.version = IPTABLES_VERSION,
+ .revision = 0,
.size = XT_ALIGN(sizeof(struct xt_hashlimit_info)),
.userspacesize = offsetof(struct xt_hashlimit_info, hinfo),
.help = hashlimit_help,
@@ -379,6 +688,7 @@ static struct xtables_match hashlimit_ma
.family = AF_INET6,
.name = "hashlimit",
.version = IPTABLES_VERSION,
+ .revision = 0,
.size = XT_ALIGN(sizeof(struct xt_hashlimit_info)),
.userspacesize = offsetof(struct xt_hashlimit_info, hinfo),
.help = hashlimit_help,
@@ -390,8 +700,42 @@ static struct xtables_match hashlimit_ma
.extra_opts = hashlimit_opts,
};
+static struct xtables_match hashlimit_mt_reg = {
+ .version = IPTABLES_VERSION,
+ .name = "hashlimit",
+ .revision = 1,
+ .family = AF_INET,
+ .size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
+ .userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
+ .help = hashlimit_mt_help,
+ .init = hashlimit_mt4_init,
+ .parse = hashlimit_mt4_parse,
+ .final_check = hashlimit_mt_check,
+ .print = hashlimit_mt4_print,
+ .save = hashlimit_mt4_save,
+ .extra_opts = hashlimit_mt_opts,
+};
+
+static struct xtables_match hashlimit_mt6_reg = {
+ .version = IPTABLES_VERSION,
+ .name = "hashlimit",
+ .revision = 1,
+ .family = AF_INET6,
+ .size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
+ .userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
+ .help = hashlimit_mt_help,
+ .init = hashlimit_mt6_init,
+ .parse = hashlimit_mt6_parse,
+ .final_check = hashlimit_mt_check,
+ .print = hashlimit_mt6_print,
+ .save = hashlimit_mt6_save,
+ .extra_opts = hashlimit_mt_opts,
+};
+
void _init(void)
{
xtables_register_match(&hashlimit_match);
xtables_register_match(&hashlimit_match6);
+ xtables_register_match(&hashlimit_mt_reg);
+ xtables_register_match(&hashlimit_mt6_reg);
}
Index: iptables/extensions/libxt_hashlimit.man
===================================================================
--- iptables.orig/extensions/libxt_hashlimit.man
+++ iptables/extensions/libxt_hashlimit.man
@@ -1,35 +1,59 @@
-This patch adds a new match called 'hashlimit'.
-The idea is to have something like 'limit', but either per
-destination-ip or per (destip,destport) tuple.
-
-It gives you the ability to express
-.IP
- '1000 packets per second for every host in 192.168.0.0/16'
-.IP
- '100 packets per second for every service of 192.168.1.1'
-.P
-with a single iptables rule.
-.TP
-.BI "--hashlimit " "rate"
-A rate just like the limit match
-.TP
-.BI "--hashlimit-burst " "num"
-Burst value, just like limit match
+\fBhashlimit\fR uses hash buckets to express a rate limiting match (like the
+\fBlimit\fR match) for a group of connections using a \fBsingle\fR iptables
+rule. Grouping can be done per-hostgroup (source and/or destination address)
+and/or per-port. It gives you the ability to express "\fIN\fR packets per time
+quantum per group":
+.TP
+matching on source host
+"1000 packets per second for every host in 192.168.0.0/16"
+.TP
+matching on source prot
+"100 packets per second for every service of 192.168.1.1"
+.TP
+matching on subnet
+"10000 packets per minute for every /28 subnet in 10.0.0.0/8"
+.PP
+A hash limit option (\fB--hashlimit-upto\fR, \fB--hashlimit-above\fR) and
+\fB--hashlimit-name\fR are required.
+.TP
+\fB--hashlimit-upto\fR \fIamount\fR[\fB/second\fR|\fB/minute\fR|\fB/hour\fR|\fB/day\fR]
+Match if the rate is below or equal to \fIamount\fR/quantum. It is specified as
+a number, with an optional time quantum suffix; the default is 3/hour.
+.TP
+\fB--hashlimit-above\fR \fIamount\fR[\fB/second\fR|\fB/minute\fR|\fB/hour\fR|\fB/day\fR]
+Match if the rate is above \fIamount\fR/quantum.
+.TP
+\fB--hashlimit-burst\fR \fIamount\fR
+Maximum initial number of packets to match: this number gets recharged by one
+every time the limit specified above is not reached, up to this number; the
+default is 5.
+.TP
+\fB--hashlimit-mode\fR [\fBsrcip\fR|\fBsrcport\fR|\fBdstip\fR|\fBdstport\fR[\fB,\fR...]]
+A comma-separated list of objects to take into consideration. If no
+--hashlimit-mode option is given, hashlimit acts like limit, but at the
+expensive of doing the hash housekeeping.
+.TP
+\fB--hashlimit-srcmask\fR \fIprefix\fR
+When --hashlimit-mode srcip is used, all source addresses encountered will be
+grouped according to the given prefix length and the so-created subnet will be
+subject to hashlimit. \fIprefix\fR must be between (inclusive) 0 and 32. Note
+that --hashlimit-srcmask 0 is basically doing the same thing as not specifying
+srcip for --hashlimit-mode, but is technically more expensive.
.TP
-.BI "--hashlimit-mode " "dstip,srcip,dstport,srcport"
-A comma-separated list of objects to take into consideration
+\fB--hashlimit-dstmask\fR \fIprefix\fR
+Like --hashlimit-srcmask, but for destination addresses.
.TP
-.BI "--hashlimit-name " "foo"
-The name for the /proc/net/ipt_hashlimit/foo entry
+\fB--hashlimit-name\fR \fIfoo\fR
+The name for the /proc/net/ipt_hashlimit/foo entry.
.TP
-.BI "--hashlimit-htable-size " "num"
+\fB--hashlimit-htable-size\fR \fIbuckets\fR
The number of buckets of the hash table
.TP
-.BI "--hashlimit-htable-max " "num"
-Maximum entries in the hash
+\fB--hashlimit-htable-max\fR \fIentries\fR
+Maximum entries in the hash.
.TP
-.BI "--hashlimit-htable-expire " "num"
-After how many miliseconds do hash entries expire
+\fB--hashlimit-htable-expire\fR \fImsec\fR
+After how many miliseconds do hash entries expire.
.TP
-.BI "--hashlimit-htable-gcinterval " "num"
-How many miliseconds between garbage collection intervals
+\fB--hashlimit-htable-gcinterval\fR \fImsec\fR
+How many miliseconds between garbage collection intervals.
Index: iptables/include/linux/netfilter/xt_hashlimit.h
===================================================================
--- iptables.orig/include/linux/netfilter/xt_hashlimit.h
+++ iptables/include/linux/netfilter/xt_hashlimit.h
@@ -9,13 +9,16 @@
/* details of this structure hidden by the implementation */
struct xt_hashlimit_htable;
-#define XT_HASHLIMIT_HASH_DIP 0x0001
-#define XT_HASHLIMIT_HASH_DPT 0x0002
-#define XT_HASHLIMIT_HASH_SIP 0x0004
-#define XT_HASHLIMIT_HASH_SPT 0x0008
+enum {
+ XT_HASHLIMIT_HASH_DIP = 1 << 0,
+ XT_HASHLIMIT_HASH_DPT = 1 << 1,
+ XT_HASHLIMIT_HASH_SIP = 1 << 2,
+ XT_HASHLIMIT_HASH_SPT = 1 << 3,
+ XT_HASHLIMIT_INVERT = 1 << 4,
+};
struct hashlimit_cfg {
- u_int32_t mode; /* bitmask of IPT_HASHLIMIT_HASH_* */
+ u_int32_t mode; /* bitmask of XT_HASHLIMIT_HASH_* */
u_int32_t avg; /* Average secs between packets * scale */
u_int32_t burst; /* Period multiplier for upper limit. */
@@ -29,12 +32,36 @@ struct hashlimit_cfg {
struct xt_hashlimit_info {
char name [IFNAMSIZ]; /* name */
struct hashlimit_cfg cfg;
- struct xt_hashlimit_htable *hinfo;
/* Used internally by the kernel */
+ struct xt_hashlimit_htable *hinfo;
union {
void *ptr;
struct xt_hashlimit_info *master;
} u;
};
+
+struct hashlimit_cfg1 {
+ u_int32_t mode; /* bitmask of XT_HASHLIMIT_HASH_* */
+ u_int32_t avg; /* Average secs between packets * scale */
+ u_int32_t burst; /* Period multiplier for upper limit. */
+
+ /* user specified */
+ u_int32_t size; /* how many buckets */
+ u_int32_t max; /* max number of entries */
+ u_int32_t gc_interval; /* gc interval */
+ u_int32_t expire; /* when do entries expire? */
+
+ u_int8_t srcmask, dstmask;
+};
+
+struct xt_hashlimit_mtinfo1 {
+ char name[IFNAMSIZ];
+ struct hashlimit_cfg1 cfg;
+
+ /* Used internally by the kernel */
+ struct xt_hashlimit_htable *hinfo __attribute__((aligned(8)));
+ struct xt_hashlimit_mtinfo1 *master __attribute__((aligned(8)));
+};
+
#endif /*_XT_HASHLIMIT_H*/
^ permalink raw reply [flat|nested] 11+ messages in thread