diff options
author | Patrick McHardy <kaber@trash.net> | 2011-05-25 05:34:04 +0200 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-05-25 05:34:04 +0200 |
commit | 790845385fb84ce8e79a96e91fc6c4f7df60713d (patch) | |
tree | 3a0269859e66b8703af172f8e0debe846db124a6 /extensions | |
parent | 17f7937f79af4d260c60cb800e56fc0df0a48b37 (diff) | |
parent | db50b83bc3cd634beb71f38978ad7d035c88ff11 (diff) |
Merge branch 'master' of git://dev.medozas.de/iptables
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/libip6t_ah.c | 10 | ||||
-rw-r--r-- | extensions/libip6t_frag.c | 12 | ||||
-rw-r--r-- | extensions/libip6t_rt.c | 14 | ||||
-rw-r--r-- | extensions/libipt_REDIRECT.c | 3 | ||||
-rw-r--r-- | extensions/libipt_ah.c | 10 | ||||
-rw-r--r-- | extensions/libxt_NFQUEUE.c | 12 | ||||
-rw-r--r-- | extensions/libxt_TCPMSS.man | 14 | ||||
-rw-r--r-- | extensions/libxt_TPROXY.c | 8 | ||||
-rw-r--r-- | extensions/libxt_conntrack.c | 73 | ||||
-rw-r--r-- | extensions/libxt_esp.c | 10 | ||||
-rw-r--r-- | extensions/libxt_hashlimit.man | 26 | ||||
-rw-r--r-- | extensions/libxt_ipvs.c | 6 | ||||
-rw-r--r-- | extensions/libxt_length.c | 4 | ||||
-rw-r--r-- | extensions/libxt_quota.c | 3 | ||||
-rw-r--r-- | extensions/libxt_rateest.c | 6 | ||||
-rw-r--r-- | extensions/libxt_rateest.man | 71 | ||||
-rw-r--r-- | extensions/libxt_time.c | 38 | ||||
-rw-r--r-- | extensions/libxt_time.man | 45 | ||||
-rw-r--r-- | extensions/libxt_u32.c | 3 |
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, }; |