summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2011-05-25 05:34:04 +0200
committerPatrick McHardy <kaber@trash.net>2011-05-25 05:34:04 +0200
commit790845385fb84ce8e79a96e91fc6c4f7df60713d (patch)
tree3a0269859e66b8703af172f8e0debe846db124a6 /extensions
parent17f7937f79af4d260c60cb800e56fc0df0a48b37 (diff)
parentdb50b83bc3cd634beb71f38978ad7d035c88ff11 (diff)
Merge branch 'master' of git://dev.medozas.de/iptables
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libip6t_ah.c10
-rw-r--r--extensions/libip6t_frag.c12
-rw-r--r--extensions/libip6t_rt.c14
-rw-r--r--extensions/libipt_REDIRECT.c3
-rw-r--r--extensions/libipt_ah.c10
-rw-r--r--extensions/libxt_NFQUEUE.c12
-rw-r--r--extensions/libxt_TCPMSS.man14
-rw-r--r--extensions/libxt_TPROXY.c8
-rw-r--r--extensions/libxt_conntrack.c73
-rw-r--r--extensions/libxt_esp.c10
-rw-r--r--extensions/libxt_hashlimit.man26
-rw-r--r--extensions/libxt_ipvs.c6
-rw-r--r--extensions/libxt_length.c4
-rw-r--r--extensions/libxt_quota.c3
-rw-r--r--extensions/libxt_rateest.c6
-rw-r--r--extensions/libxt_rateest.man71
-rw-r--r--extensions/libxt_time.c38
-rw-r--r--extensions/libxt_time.man45
-rw-r--r--extensions/libxt_u32.c3
19 files changed, 180 insertions, 188 deletions
diff --git a/extensions/libip6t_ah.c b/extensions/libip6t_ah.c
index d30ddfa4..26f81408 100644
--- a/extensions/libip6t_ah.c
+++ b/extensions/libip6t_ah.c
@@ -28,13 +28,6 @@ static const struct xt_option_entry ah_opts[] = {
};
#undef s
-static void ah_init(struct xt_entry_match *m)
-{
- struct ip6t_ah *ahinfo = (struct ip6t_ah *)m->data;
-
- ahinfo->spis[1] = 0xFFFFFFFF;
-}
-
static void ah_parse(struct xt_option_call *cb)
{
struct ip6t_ah *ahinfo = cb->data;
@@ -42,6 +35,8 @@ static void ah_parse(struct xt_option_call *cb)
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_AHSPI:
+ if (cb->nvals == 1)
+ ahinfo->spis[1] = ahinfo->spis[0];
if (cb->invert)
ahinfo->invflags |= IP6T_AH_INV_SPI;
break;
@@ -132,7 +127,6 @@ static struct xtables_match ah_mt6_reg = {
.size = XT_ALIGN(sizeof(struct ip6t_ah)),
.userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)),
.help = ah_help,
- .init = ah_init,
.print = ah_print,
.save = ah_save,
.x6_parse = ah_parse,
diff --git a/extensions/libip6t_frag.c b/extensions/libip6t_frag.c
index 12794e42..47793860 100644
--- a/extensions/libip6t_frag.c
+++ b/extensions/libip6t_frag.c
@@ -41,19 +41,16 @@ static const struct xt_option_entry frag_opts[] = {
};
#undef s
-static void frag_init(struct xt_entry_match *m)
-{
- struct ip6t_frag *fraginfo = (struct ip6t_frag *)m->data;
-
- fraginfo->ids[1] = 0xFFFFFFFF;
-}
-
static void frag_parse(struct xt_option_call *cb)
{
struct ip6t_frag *fraginfo = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
+ case O_FRAGID:
+ if (cb->nvals == 1)
+ fraginfo->ids[1] = fraginfo->ids[0];
+ break;
case O_FRAGRES:
fraginfo->flags |= IP6T_FRAG_RES;
break;
@@ -160,7 +157,6 @@ static struct xtables_match frag_mt6_reg = {
.size = XT_ALIGN(sizeof(struct ip6t_frag)),
.userspacesize = XT_ALIGN(sizeof(struct ip6t_frag)),
.help = frag_help,
- .init = frag_init,
.print = frag_print,
.save = frag_save,
.x6_parse = frag_parse,
diff --git a/extensions/libip6t_rt.c b/extensions/libip6t_rt.c
index eb308204..d470488d 100644
--- a/extensions/libip6t_rt.c
+++ b/extensions/libip6t_rt.c
@@ -31,8 +31,8 @@ IP6T_RT_HOPS);
#define s struct ip6t_rt
static const struct xt_option_entry rt_opts[] = {
- {.name = "rt-type", .id = O_RT_TYPE, .type = XTTYPE_UINT32RC,
- .flags = XTOPT_INVERT},
+ {.name = "rt-type", .id = O_RT_TYPE, .type = XTTYPE_UINT32,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, rt_type)},
{.name = "rt-segsleft", .id = O_RT_SEGSLEFT, .type = XTTYPE_UINT32RC,
.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segsleft)},
{.name = "rt-len", .id = O_RT_LEN, .type = XTTYPE_UINT32,
@@ -99,13 +99,6 @@ parse_addresses(const char *addrstr, struct in6_addr *addrp)
return i;
}
-static void rt_init(struct xt_entry_match *m)
-{
- struct ip6t_rt *rtinfo = (struct ip6t_rt *)m->data;
-
- rtinfo->segsleft[1] = 0xFFFFFFFF;
-}
-
static void rt_parse(struct xt_option_call *cb)
{
struct ip6t_rt *rtinfo = cb->data;
@@ -118,6 +111,8 @@ static void rt_parse(struct xt_option_call *cb)
rtinfo->flags |= IP6T_RT_TYP;
break;
case O_RT_SEGSLEFT:
+ if (cb->nvals == 1)
+ rtinfo->segsleft[1] = rtinfo->segsleft[0];
if (cb->invert)
rtinfo->invflags |= IP6T_RT_INV_SGS;
rtinfo->flags |= IP6T_RT_SGS;
@@ -250,7 +245,6 @@ static struct xtables_match rt_mt6_reg = {
.size = XT_ALIGN(sizeof(struct ip6t_rt)),
.userspacesize = XT_ALIGN(sizeof(struct ip6t_rt)),
.help = rt_help,
- .init = rt_init,
.x6_parse = rt_parse,
.print = rt_print,
.save = rt_save,
diff --git a/extensions/libipt_REDIRECT.c b/extensions/libipt_REDIRECT.c
index 426a7463..e67360a0 100644
--- a/extensions/libipt_REDIRECT.c
+++ b/extensions/libipt_REDIRECT.c
@@ -23,8 +23,7 @@ static void REDIRECT_help(void)
}
static const struct xt_option_entry REDIRECT_opts[] = {
- {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING,
- .flags = XTOPT_MAND},
+ {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
XTOPT_TABLEEND,
};
diff --git a/extensions/libipt_ah.c b/extensions/libipt_ah.c
index 53adfd87..8cf167c4 100644
--- a/extensions/libipt_ah.c
+++ b/extensions/libipt_ah.c
@@ -21,18 +21,13 @@ static const struct xt_option_entry ah_opts[] = {
XTOPT_TABLEEND,
};
-static void ah_init(struct xt_entry_match *m)
-{
- struct ipt_ah *ahinfo = (struct ipt_ah *)m->data;
-
- ahinfo->spis[1] = 0xFFFFFFFF;
-}
-
static void ah_parse(struct xt_option_call *cb)
{
struct ipt_ah *ahinfo = cb->data;
xtables_option_parse(cb);
+ if (cb->nvals == 1)
+ ahinfo->spis[1] = ahinfo->spis[0];
if (cb->invert)
ahinfo->invflags |= IPT_AH_INV_SPI;
}
@@ -97,7 +92,6 @@ static struct xtables_match ah_mt_reg = {
.size = XT_ALIGN(sizeof(struct ipt_ah)),
.userspacesize = XT_ALIGN(sizeof(struct ipt_ah)),
.help = ah_help,
- .init = ah_init,
.print = ah_print,
.save = ah_save,
.x6_parse = ah_parse,
diff --git a/extensions/libxt_NFQUEUE.c b/extensions/libxt_NFQUEUE.c
index a86c88a3..e47b586c 100644
--- a/extensions/libxt_NFQUEUE.c
+++ b/extensions/libxt_NFQUEUE.c
@@ -13,6 +13,8 @@ enum {
O_QUEUE_NUM = 0,
O_QUEUE_BALANCE,
O_QUEUE_BYPASS,
+ F_QUEUE_NUM = 1 << O_QUEUE_NUM,
+ F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE,
};
static void NFQUEUE_help(void)
@@ -41,9 +43,10 @@ static void NFQUEUE_help_v2(void)
#define s struct xt_NFQ_info
static const struct xt_option_entry NFQUEUE_opts[] = {
{.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16,
- .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum)},
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum),
+ .excl = F_QUEUE_BALANCE},
{.name = "queue-balance", .id = O_QUEUE_BALANCE,
- .type = XTTYPE_UINT16RC},
+ .type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM},
{.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE},
XTOPT_TABLEEND,
};
@@ -81,14 +84,11 @@ static void NFQUEUE_parse_v2(struct xt_option_call *cb)
{
struct xt_NFQ_info_v2 *info = cb->data;
- xtables_option_parse(cb);
+ NFQUEUE_parse_v1(cb);
switch (cb->entry->id) {
case O_QUEUE_BYPASS:
info->bypass = 1;
break;
- default:
- NFQUEUE_parse_v1(cb);
- break;
}
}
diff --git a/extensions/libxt_TCPMSS.man b/extensions/libxt_TCPMSS.man
index ac8fb4e8..8da8e761 100644
--- a/extensions/libxt_TCPMSS.man
+++ b/extensions/libxt_TCPMSS.man
@@ -11,19 +11,13 @@ packets. The symptoms of this
problem are that everything works fine from your Linux
firewall/router, but machines behind it can never exchange large
packets:
-.PD 0
-.RS 0.1i
-.TP 0.3i
-1)
+.IP 1. 4
Web browsers connect, then hang with no data received.
-.TP
-2)
+.IP 2. 4
Small mail works fine, but large emails hang.
-.TP
-3)
+.IP 3. 4
ssh works fine, but scp hangs after initial handshaking.
-.RE
-.PD
+.PP
Workaround: activate this option and add a rule to your firewall
configuration like:
.IP
diff --git a/extensions/libxt_TPROXY.c b/extensions/libxt_TPROXY.c
index 61646c93..d13ec85f 100644
--- a/extensions/libxt_TPROXY.c
+++ b/extensions/libxt_TPROXY.c
@@ -20,8 +20,8 @@ enum {
#define s struct xt_tproxy_target_info
static const struct xt_option_entry tproxy_tg0_opts[] = {
- {.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT_NE,
- .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, lport)},
+ {.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT,
+ .flags = XTOPT_MAND | XTOPT_NBO | XTOPT_PUT, XTOPT_POINTER(s, lport)},
{.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST},
{.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
XTOPT_TABLEEND,
@@ -29,8 +29,8 @@ static const struct xt_option_entry tproxy_tg0_opts[] = {
#undef s
#define s struct xt_tproxy_target_info_v1
static const struct xt_option_entry tproxy_tg1_opts[] = {
- {.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT_NE,
- .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, lport)},
+ {.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT,
+ .flags = XTOPT_MAND | XTOPT_NBO | XTOPT_PUT, XTOPT_POINTER(s, lport)},
{.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST,
.flags = XTOPT_PUT, XTOPT_POINTER(s, laddr)},
{.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c
index ed0bd939..e1d85755 100644
--- a/extensions/libxt_conntrack.c
+++ b/extensions/libxt_conntrack.c
@@ -291,69 +291,6 @@ conntrack_ps_statuses(struct xt_conntrack_mtinfo3 *info, const char *arg)
xtables_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
}
-static unsigned long
-parse_expire(const char *s)
-{
- unsigned int len;
-
- if (!xtables_strtoui(s, NULL, &len, 0, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM, "expire value invalid: \"%s\"\n", s);
- else
- return len;
-}
-
-/* If a single value is provided, min and max are both set to the value */
-static void
-parse_expires(const char *s, struct xt_conntrack_info *sinfo)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(s);
- if ((cp = strchr(buffer, ':')) == NULL)
- sinfo->expires_min = sinfo->expires_max =
- parse_expire(buffer);
- else {
- *cp = '\0';
- cp++;
-
- sinfo->expires_min = buffer[0] ? parse_expire(buffer) : 0;
- sinfo->expires_max = cp[0]
- ? parse_expire(cp)
- : (unsigned long)-1;
- }
- free(buffer);
-
- if (sinfo->expires_min > sinfo->expires_max)
- xtables_error(PARAMETER_PROBLEM,
- "expire min. range value `%lu' greater than max. "
- "range value `%lu'", sinfo->expires_min, sinfo->expires_max);
-}
-
-static void
-conntrack_ps_expires(struct xt_conntrack_mtinfo3 *info, const char *s)
-{
- unsigned int min, max;
- char *end;
-
- if (!xtables_strtoui(s, &end, &min, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
- max = min;
- if (*end == ':')
- if (!xtables_strtoui(end + 1, &end, &max, 0, UINT32_MAX))
- xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
- if (*end != '\0')
- xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
-
- if (min > max)
- xtables_error(PARAMETER_PROBLEM,
- "expire min. range value \"%u\" greater than max. "
- "range value \"%u\"", min, max);
-
- info->expires_min = min;
- info->expires_max = max;
-}
-
static void conntrack_parse(struct xt_option_call *cb)
{
struct xt_conntrack_info *sinfo = cb->data;
@@ -408,7 +345,10 @@ static void conntrack_parse(struct xt_option_call *cb)
sinfo->flags |= XT_CONNTRACK_STATUS;
break;
case O_CTEXPIRE:
- parse_expires(cb->arg, sinfo);
+ sinfo->expires_min = cb->val.u32_range[0];
+ sinfo->expires_max = cb->val.u32_range[0];
+ if (cb->nvals >= 2)
+ sinfo->expires_max = cb->val.u32_range[1];
if (cb->invert)
sinfo->invflags |= XT_CONNTRACK_EXPIRES;
sinfo->flags |= XT_CONNTRACK_EXPIRES;
@@ -473,7 +413,10 @@ static void conntrack_mt_parse(struct xt_option_call *cb, uint8_t rev)
info->invert_flags |= XT_CONNTRACK_STATUS;
break;
case O_CTEXPIRE:
- conntrack_ps_expires(info, cb->arg);
+ info->expires_min = cb->val.u32_range[0];
+ info->expires_max = cb->val.u32_range[0];
+ if (cb->nvals >= 2)
+ info->expires_max = cb->val.u32_range[1];
info->match_flags |= XT_CONNTRACK_EXPIRES;
if (cb->invert)
info->invert_flags |= XT_CONNTRACK_EXPIRES;
diff --git a/extensions/libxt_esp.c b/extensions/libxt_esp.c
index e9d7990e..294338b4 100644
--- a/extensions/libxt_esp.c
+++ b/extensions/libxt_esp.c
@@ -21,18 +21,13 @@ static const struct xt_option_entry esp_opts[] = {
XTOPT_TABLEEND,
};
-static void esp_init(struct xt_entry_match *m)
-{
- struct xt_esp *espinfo = (struct xt_esp *)m->data;
-
- espinfo->spis[1] = 0xFFFFFFFF;
-}
-
static void esp_parse(struct xt_option_call *cb)
{
struct xt_esp *espinfo = cb->data;
xtables_option_parse(cb);
+ if (cb->nvals == 1)
+ espinfo->spis[1] = espinfo->spis[0];
if (cb->invert)
espinfo->invflags |= XT_ESP_INV_SPI;
}
@@ -91,7 +86,6 @@ static struct xtables_match esp_match = {
.size = XT_ALIGN(sizeof(struct xt_esp)),
.userspacesize = XT_ALIGN(sizeof(struct xt_esp)),
.help = esp_help,
- .init = esp_init,
.print = esp_print,
.save = esp_save,
.x6_parse = esp_parse,
diff --git a/extensions/libxt_hashlimit.man b/extensions/libxt_hashlimit.man
index e91d0c63..f90577e7 100644
--- a/extensions/libxt_hashlimit.man
+++ b/extensions/libxt_hashlimit.man
@@ -2,16 +2,7 @@
\fBlimit\fP match) for a group of connections using a \fBsingle\fP 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\fP 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 port
-"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"
+quantum per group" (see below for some examples).
.PP
A hash limit option (\fB\-\-hashlimit\-upto\fP, \fB\-\-hashlimit\-above\fP) and
\fB\-\-hashlimit\-name\fP are required.
@@ -57,3 +48,18 @@ After how many milliseconds do hash entries expire.
.TP
\fB\-\-hashlimit\-htable\-gcinterval\fP \fImsec\fP
How many milliseconds between garbage collection intervals.
+.PP
+Examples:
+.TP
+matching on source host
+"1000 packets per second for every host in 192.168.0.0/16" =>
+\-s 192.168.0.0/16 \-\-hashlimit\-mode srcip \-\-hashlimit\-upto 1000/sec
+.TP
+matching on source port
+"100 packets per second for every service of 192.168.1.1" =>
+\-s 192.168.1.1 \-\-hashlimit\-mode srcport \-\-hashlimit\-upto 100/sec
+.TP
+matching on subnet
+"10000 packets per minute for every /28 subnet (groups of 8 addresses)
+in 10.0.0.0/8" =>
+\-s 10.0.0.8 \-\-hashlimit\-mask 28 \-\-hashlimit\-upto 10000/min
diff --git a/extensions/libxt_ipvs.c b/extensions/libxt_ipvs.c
index 88d235f6..46727660 100644
--- a/extensions/libxt_ipvs.c
+++ b/extensions/libxt_ipvs.c
@@ -32,12 +32,14 @@ static const struct xt_option_entry ipvs_mt_opts[] = {
{.name = "vaddr", .id = O_VADDR, .type = XTTYPE_HOSTMASK,
.flags = XTOPT_INVERT},
{.name = "vport", .id = O_VPORT, .type = XTTYPE_PORT,
- .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, vport)},
+ .flags = XTOPT_NBO | XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(s, vport)},
{.name = "vdir", .id = O_VDIR, .type = XTTYPE_STRING},
{.name = "vmethod", .id = O_VMETHOD, .type = XTTYPE_STRING,
.flags = XTOPT_INVERT},
{.name = "vportctl", .id = O_VPORTCTL, .type = XTTYPE_PORT,
- .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, vportctl)},
+ .flags = XTOPT_NBO | XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(s, vportctl)},
XTOPT_TABLEEND,
};
#undef s
diff --git a/extensions/libxt_length.c b/extensions/libxt_length.c
index 4f3a3318..6ea76465 100644
--- a/extensions/libxt_length.c
+++ b/extensions/libxt_length.c
@@ -26,7 +26,9 @@ static void length_parse(struct xt_option_call *cb)
xtables_option_parse(cb);
info->min = cb->val.u16_range[0];
- info->max = (cb->nvals == 2) ? cb->val.u16_range[1] : UINT16_MAX;
+ info->max = cb->val.u16_range[0];
+ if (cb->nvals >= 2)
+ info->max = cb->val.u16_range[1];
if (cb->invert)
info->invert = 1;
}
diff --git a/extensions/libxt_quota.c b/extensions/libxt_quota.c
index 988f404f..ff498da7 100644
--- a/extensions/libxt_quota.c
+++ b/extensions/libxt_quota.c
@@ -13,7 +13,8 @@ enum {
static const struct xt_option_entry quota_opts[] = {
{.name = "quota", .id = O_QUOTA, .type = XTTYPE_UINT64,
- .flags = XTOPT_MAND | XTOPT_INVERT},
+ .flags = XTOPT_MAND | XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct xt_quota_info, quota)},
XTOPT_TABLEEND,
};
diff --git a/extensions/libxt_rateest.c b/extensions/libxt_rateest.c
index e70edc67..509b3e31 100644
--- a/extensions/libxt_rateest.c
+++ b/extensions/libxt_rateest.c
@@ -65,11 +65,11 @@ static const struct rate_suffix {
{ "bit", 1. },
{ "Kibit", 1024. },
{ "kbit", 1000. },
- { "mibit", 1024.*1024. },
+ { "Mibit", 1024.*1024. },
{ "mbit", 1000000. },
- { "gibit", 1024.*1024.*1024. },
+ { "Gibit", 1024.*1024.*1024. },
{ "gbit", 1000000000. },
- { "tibit", 1024.*1024.*1024.*1024. },
+ { "Tibit", 1024.*1024.*1024.*1024. },
{ "tbit", 1000000000000. },
{ "Bps", 8. },
{ "KiBps", 8.*1024. },
diff --git a/extensions/libxt_rateest.man b/extensions/libxt_rateest.man
index 75303c50..42a82f32 100644
--- a/extensions/libxt_rateest.man
+++ b/extensions/libxt_rateest.man
@@ -1,34 +1,75 @@
The rate estimator can match on estimated rates as collected by the RATEEST
target. It supports matching on absolute bps/pps values, comparing two rate
estimators and matching on the difference between two rate estimators.
+.PP
+For a better understanding of the available options, these are all possible
+combinations:
+.\" * Absolute:
+.IP \(bu 4
+\fBrateest\fP \fIoperator\fP \fBrateest-bps\fP
+.IP \(bu 4
+\fBrateest\fP \fIoperator\fP \fBrateest-pps\fP
+.\" * Absolute + Delta:
+.IP \(bu 4
+(\fBrateest\fP minus \fBrateest-bps1\fP) \fIoperator\fP \fBrateest-bps2\fP
+.IP \(bu 4
+(\fBrateest\fP minus \fBrateest-pps1\fP) \fIoperator\fP \fBrateest-pps2\fP
+.\" * Relative:
+.IP \(bu 4
+\fBrateest1\fP \fIoperator\fP \fBrateest2\fP \fBrateest-bps\fP(without rate!)
+.IP \(bu 4
+\fBrateest1\fP \fIoperator\fP \fBrateest2\fP \fBrateest-pps\fP(without rate!)
+.\" * Relative + Delta:
+.IP \(bu 4
+(\fBrateest1\fP minus \fBrateest-bps1\fP) \fIoperator\fP
+(\fBrateest2\fP minus \fBrateest-bps2\fP)
+.IP \(bu 4
+(\fBrateest1\fP minus \fBrateest-pps1\fP) \fIoperator\fP
+(\fBrateest2\fP minus \fBrateest-pps2\fP)
+.TP
+\fB\-\-rateest\-delta\fP
+For each estimator (either absolute or relative mode), calculate the difference
+between the estimator-determined flow rate and the static value chosen with the
+BPS/PPS options. If the flow rate is higher than the specified BPS/PPS, 0 will
+be used instead of a negative value. In other words, "max(0, rateest#_rate -
+rateest#_bps)" is used.
+.TP
+[\fB!\fP] \fB\-\-rateest\-lt\fP
+Match if rate is less than given rate/estimator.
+.TP
+[\fB!\fP] \fB\-\-rateest\-gt\fP
+Match if rate is greater than given rate/estimator.
+.TP
+[\fB!\fP] \fB\-\-rateest\-eq\fP
+Match if rate is equal to given rate/estimator.
+.PP
+In the so-called "absolute mode", only one rate estimator is used and compared
+against a static value, while in "relative mode", two rate estimators are
+compared against another.
+.TP
+\fB\-\-rateest\fP \fIname\fP
+Name of the one rate estimator for absolute mode.
.TP
\fB\-\-rateest1\fP \fIname\fP
-Name of the first rate estimator.
.TP
\fB\-\-rateest2\fP \fIname\fP
-Name of the second rate estimator (if difference is to be calculated).
+The names of the two rate estimators for relative mode.
.TP
-\fB\-\-rateest\-delta\fP
-Compare difference(s) to given rate(s)
+\fB\-\-rateest\-bps\fP [\fIvalue\fP]
+.TP
+\fB\-\-rateest\-pps\fP [\fIvalue\fP]
.TP
\fB\-\-rateest\-bps1\fP [\fIvalue\fP]
.TP
\fB\-\-rateest\-bps2\fP [\fIvalue\fP]
-Compare bytes per second.
.TP
\fB\-\-rateest\-pps1\fP [\fIvalue\fP]
.TP
\fB\-\-rateest\-pps2\fP [\fIvalue\fP]
-Compare packets per second.
-.TP
-[\fB!\fP] \fB\-\-rateest\-lt\fP
-Match if rate is less than given rate/estimator.
-.TP
-[\fB!\fP] \fB\-\-rateest\-gt\fP
-Match if rate is greater than given rate/estimator.
-.TP
-[\fB!\fP] \fB\-\-rateest\-eq\fP
-Match if rate is equal to given rate/estimator.
+Compare the estimator(s) by bytes or packets per second, and compare against
+the chosen value. See the above bullet list for which option is to be used in
+which case. A unit suffix may be used - available ones are: bit, [kmgt]bit,
+[KMGT]ibit, Bps, [KMGT]Bps, [KMGT]iBps.
.PP
Example: This is what can be used to route outgoing data connections from an
FTP server over two lines based on the available bandwidth at the time the data
diff --git a/extensions/libxt_time.c b/extensions/libxt_time.c
index b538476c..44c05b8f 100644
--- a/extensions/libxt_time.c
+++ b/extensions/libxt_time.c
@@ -26,6 +26,10 @@ enum {
O_WEEKDAYS,
O_LOCAL_TZ,
O_UTC,
+ O_KERNEL_TZ,
+ F_LOCAL_TZ = 1 << O_LOCAL_TZ,
+ F_UTC = 1 << O_UTC,
+ F_KERNEL_TZ = 1 << O_KERNEL_TZ,
};
static const char *const week_days[] = {
@@ -41,8 +45,12 @@ static const struct xt_option_entry time_opts[] = {
.flags = XTOPT_INVERT},
{.name = "monthdays", .id = O_MONTHDAYS, .type = XTTYPE_STRING,
.flags = XTOPT_INVERT},
- {.name = "localtz", .id = O_LOCAL_TZ, .type = XTTYPE_NONE},
- {.name = "utc", .id = O_UTC, .type = XTTYPE_NONE},
+ {.name = "localtz", .id = O_LOCAL_TZ, .type = XTTYPE_NONE,
+ .excl = F_UTC},
+ {.name = "utc", .id = O_UTC, .type = XTTYPE_NONE,
+ .excl = F_LOCAL_TZ | F_KERNEL_TZ},
+ {.name = "kerneltz", .id = O_KERNEL_TZ, .type = XTTYPE_NONE,
+ .excl = F_UTC},
XTOPT_TABLEEND,
};
@@ -59,7 +67,7 @@ static void time_help(void)
"[!] --weekdays value List of weekdays on which to match, sep. by comma\n"
" (Possible days: Mon,Tue,Wed,Thu,Fri,Sat,Sun or 1 to 7\n"
" Defaults to all weekdays.)\n"
-" --localtz/--utc Time is interpreted as UTC/local time\n");
+" --kerneltz Work with the kernel timezone instead of UTC\n");
}
static void time_init(struct xt_entry_match *m)
@@ -75,9 +83,6 @@ static void time_init(struct xt_entry_match *m)
/* ...and have no date-begin or date-end boundary */
info->date_start = 0;
info->date_stop = INT_MAX;
-
- /* local time is default */
- info->flags |= XT_TIME_LOCAL_TZ;
}
static time_t time_parse_date(const char *s, bool end)
@@ -136,6 +141,12 @@ static time_t time_parse_date(const char *s, bool end)
tm.tm_min = minute;
tm.tm_sec = second;
tm.tm_isdst = 0;
+ /*
+ * Offsetting, if any, is done by xt_time.ko,
+ * so we have to disable it here in userspace.
+ */
+ setenv("TZ", "UTC", true);
+ tzset();
ret = mktime(&tm);
if (ret >= 0)
return ret;
@@ -263,6 +274,12 @@ static void time_parse(struct xt_option_call *cb)
info->daytime_stop = time_parse_minutes(cb->arg);
break;
case O_LOCAL_TZ:
+ fprintf(stderr, "WARNING: --localtz is being replaced by "
+ "--kerneltz, since \"local\" is ambiguous. Note the "
+ "kernel timezone has caveats - "
+ "see manpage for details.\n");
+ /* fallthrough */
+ case O_KERNEL_TZ:
info->flags |= XT_TIME_LOCAL_TZ;
break;
case O_MONTHDAYS:
@@ -275,9 +292,6 @@ static void time_parse(struct xt_option_call *cb)
if (cb->invert)
info->weekdays_match ^= XT_TIME_ALL_WEEKDAYS;
break;
- case O_UTC:
- info->flags &= ~XT_TIME_LOCAL_TZ;
- break;
}
}
@@ -289,7 +303,7 @@ static void time_print_date(time_t date, const char *command)
if (date == 0 || date == LONG_MAX)
return;
- t = localtime(&date);
+ t = gmtime(&date);
if (command != NULL)
/*
* Need a contiguous string (no whitespaces), hence using
@@ -413,8 +427,8 @@ static void time_save(const void *ip, const struct xt_entry_match *match)
}
time_print_date(info->date_start, "--datestart");
time_print_date(info->date_stop, "--datestop");
- if (!(info->flags & XT_TIME_LOCAL_TZ))
- printf(" --utc");
+ if (info->flags & XT_TIME_LOCAL_TZ)
+ printf(" --kerneltz");
}
static struct xtables_match time_match = {
diff --git a/extensions/libxt_time.man b/extensions/libxt_time.man
index 2bceaf66..1d677b94 100644
--- a/extensions/libxt_time.man
+++ b/extensions/libxt_time.man
@@ -1,10 +1,10 @@
This matches if the packet arrival time/date is within a given range. All
-options are optional, but are ANDed when specified.
+options are optional, but are ANDed when specified. All times are interpreted
+as UTC by default.
.TP
\fB\-\-datestart\fP \fIYYYY\fP[\fB\-\fP\fIMM\fP[\fB\-\fP\fIDD\fP[\fBT\fP\fIhh\fP[\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]]]]]
.TP
\fB\-\-datestop\fP \fIYYYY\fP[\fB\-\fP\fIMM\fP[\fB\-\fP\fIDD\fP[\fBT\fP\fIhh\fP[\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]]]]]
-.IP
Only match during the given time, which must be in ISO 8601 "T" notation.
The possible time range is 1970-01-01T00:00:00 to 2038-01-19T04:17:07.
.IP
@@ -14,34 +14,51 @@ and 2038-01-19, respectively.
\fB\-\-timestart\fP \fIhh\fP\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]
.TP
\fB\-\-timestop\fP \fIhh\fP\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]
-.IP
Only match during the given daytime. The possible time range is 00:00:00 to
23:59:59. Leading zeroes are allowed (e.g. "06:03") and correctly interpreted
as base-10.
.TP
[\fB!\fP] \fB\-\-monthdays\fP \fIday\fP[\fB,\fP\fIday\fP...]
-.IP
Only match on the given days of the month. Possible values are \fB1\fP
to \fB31\fP. Note that specifying \fB31\fP will of course not match
on months which do not have a 31st day; the same goes for 28- or 29-day
February.
.TP
[\fB!\fP] \fB\-\-weekdays\fP \fIday\fP[\fB,\fP\fIday\fP...]
-.IP
Only match on the given weekdays. Possible values are \fBMon\fP, \fBTue\fP,
\fBWed\fP, \fBThu\fP, \fBFri\fP, \fBSat\fP, \fBSun\fP, or values from \fB1\fP
to \fB7\fP, respectively. You may also use two-character variants (\fBMo\fP,
\fBTu\fP, etc.).
.TP
-\fB\-\-utc\fP
-.IP
-Interpret the times given for \fB\-\-datestart\fP, \fB\-\-datestop\fP,
-\fB\-\-timestart\fP and \fB\-\-timestop\fP to be UTC.
-.TP
-\fB\-\-localtz\fP
-.IP
-Interpret the times given for \fB\-\-datestart\fP, \fB\-\-datestop\fP,
-\fB\-\-timestart\fP and \fB\-\-timestop\fP to be local kernel time. (Default)
+\fB\-\-kerneltz\fP
+Use the kernel timezone instead of UTC to determine whether a packet meets the
+time regulations.
+.PP
+About kernel timezones: Linux keeps the system time in UTC, and always does so.
+On boot, system time is initialized from a referential time source. Where this
+time source has no timezone information, such as the x86 CMOS RTC, UTC will be
+assumed. If the time source is however not in UTC, userspace should provide the
+correct system time and timezone to the kernel once it has the information.
+.PP
+Local time is a feature on top of the (timezone independent) system time. Each
+process has its own idea of local time, specified via the TZ environment
+variable. The kernel also has its own timezone offset variable. The TZ
+userspace environment variable specifies how the UTC-based system time is
+displayed, e.g. when you run date(1), or what you see on your desktop clock.
+The TZ string may resolve to different offsets at different dates, which is
+what enables the automatic time-jumping in userspace. when DST changes. The
+kernel's timezone offset variable is used when it has to convert between
+non-UTC sources, such as FAT filesystems, to UTC (since the latter is what the
+rest of the system uses).
+.PP
+The caveat with the kernel timezone is that Linux distributions may ignore to
+set the kernel timezone, and instead only set the system time. Even if a
+particular distribution does set the timezone at boot, it is usually does not
+keep the kernel timezone offset - which is what changes on DST - up to date.
+ntpd will not touch the kernel timezone, so running it will not resolve the
+issue. As such, one may encounter a timezone that is always +0000, or one that
+is wrong half of the time of the year. As such, \fBusing \-\-kerneltz is highly
+discouraged.\fP
.PP
EXAMPLES. To match on weekends, use:
.IP
diff --git a/extensions/libxt_u32.c b/extensions/libxt_u32.c
index 9198edca..774d5eac 100644
--- a/extensions/libxt_u32.c
+++ b/extensions/libxt_u32.c
@@ -23,7 +23,8 @@ enum {
};
static const struct xt_option_entry u32_opts[] = {
- {.name = "u32", .id = O_U32, .type = XTTYPE_STRING},
+ {.name = "u32", .id = O_U32, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND},
XTOPT_TABLEEND,
};