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 | |
parent | 17f7937f79af4d260c60cb800e56fc0df0a48b37 (diff) | |
parent | db50b83bc3cd634beb71f38978ad7d035c88ff11 (diff) | |
download | platform_external_iptables-790845385fb84ce8e79a96e91fc6c4f7df60713d.tar.gz platform_external_iptables-790845385fb84ce8e79a96e91fc6c4f7df60713d.tar.bz2 platform_external_iptables-790845385fb84ce8e79a96e91fc6c4f7df60713d.zip |
Merge branch 'master' of git://dev.medozas.de/iptables
-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 | ||||
-rw-r--r-- | include/xtables.h.in | 16 | ||||
-rw-r--r-- | ip6tables.8.in | 5 | ||||
-rw-r--r-- | iptables.8.in | 5 | ||||
-rw-r--r-- | xtables.c | 20 | ||||
-rw-r--r-- | xtoptions.c | 226 |
24 files changed, 348 insertions, 292 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, }; diff --git a/include/xtables.h.in b/include/xtables.h.in index 38c0e5ee..2565dd23 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -64,10 +64,9 @@ struct in_addr; * %XTTYPE_HOSTMASK: one host or address, with an optional prefix length * (ptr: union nf_inet_addr; only host portion is stored) * %XTTYPE_PROTOCOL: protocol number/name from /etc/protocols (ptr: uint8_t) - * %XTTYPE_PORT: 16-bit port name or number - * %XTTYPE_PORT_NE: 16-bit port name or number, stored as network-endian - * %XTTYPE_PORTRC: colon-separated port range (names acceptable) - * %XTTYPE_PORTRC_NE: same as %XTTYPE_PORTRC, stored in network-endian + * %XTTYPE_PORT: 16-bit port name or number (supports %XTOPT_NBO) + * %XTTYPE_PORTRC: colon-separated port range (names acceptable), + * (supports %XTOPT_NBO) * %XTTYPE_PLEN: prefix length * %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr) * %XTTYPE_ETHERMAC: Ethernet MAC address in hex form @@ -91,9 +90,7 @@ enum xt_option_type { XTTYPE_HOSTMASK, XTTYPE_PROTOCOL, XTTYPE_PORT, - XTTYPE_PORT_NE, XTTYPE_PORTRC, - XTTYPE_PORTRC_NE, XTTYPE_PLEN, XTTYPE_PLENMASK, XTTYPE_ETHERMAC, @@ -104,12 +101,15 @@ enum xt_option_type { * %XTOPT_MAND: option is mandatory * %XTOPT_MULTI: option may be specified multiple times * %XTOPT_PUT: store value into memory at @ptroff + * %XTOPT_NBO: store value in network-byte order + * (only certain XTTYPEs recognize this) */ enum xt_option_flags { XTOPT_INVERT = 1 << 0, XTOPT_MAND = 1 << 1, XTOPT_MULTI = 1 << 2, XTOPT_PUT = 1 << 3, + XTOPT_NBO = 1 << 4, }; /** @@ -408,8 +408,8 @@ extern void xtables_register_matches(struct xtables_match *, unsigned int); extern void xtables_register_target(struct xtables_target *me); extern void xtables_register_targets(struct xtables_target *, unsigned int); -extern bool xtables_strtoul(const char *, char **, unsigned long *, - unsigned long, unsigned long); +extern bool xtables_strtoul(const char *, char **, uintmax_t *, + uintmax_t, uintmax_t); extern bool xtables_strtoui(const char *, char **, unsigned int *, unsigned int, unsigned int); extern int xtables_service_to_port(const char *name, const char *proto); diff --git a/ip6tables.8.in b/ip6tables.8.in index 61d6667e..48ba18e1 100644 --- a/ip6tables.8.in +++ b/ip6tables.8.in @@ -243,15 +243,14 @@ add, delete, insert, replace and append commands). [\fB!\fP] \fB\-p\fP, \fB\-\-protocol\fP \fIprotocol\fP The protocol of the rule or of the packet to check. The specified protocol can be one of \fBtcp\fP, \fBudp\fP, \fBudplite\fP, -\fBicmpv6\fP, \fBesp\fP, \fBmh\fP or \fBall\fP, +\fBicmpv6\fP, \fBesp\fP, \fBmh\fP or the special keyword "\fBall\fP", or it can be a numeric value, representing one of these protocols or a different one. A protocol name from /etc/protocols is also allowed. But IPv6 extension headers except \fBesp\fP are not allowed. \fBesp\fP and \fBipv6\-nonext\fP can be used with Kernel version 2.6.11 or later. A "!" argument before the protocol inverts the -test. The number zero is equivalent to \fBall\fP. -Protocol \fBall\fP +test. The number zero is equivalent to \fBall\fP. "\fBall\fP" will match with all protocols and is taken as default when this option is omitted. .TP diff --git a/iptables.8.in b/iptables.8.in index 110c5994..d09bf7aa 100644 --- a/iptables.8.in +++ b/iptables.8.in @@ -246,12 +246,11 @@ add, delete, insert, replace and append commands). [\fB!\fP] \fB\-p\fP, \fB\-\-protocol\fP \fIprotocol\fP The protocol of the rule or of the packet to check. The specified protocol can be one of \fBtcp\fP, \fBudp\fP, \fBudplite\fP, -\fBicmp\fP, \fBesp\fP, \fBah\fP, \fBsctp\fP or \fBall\fP, +\fBicmp\fP, \fBesp\fP, \fBah\fP, \fBsctp\fP or the special keyword "\fBall\fP", or it can be a numeric value, representing one of these protocols or a different one. A protocol name from /etc/protocols is also allowed. A "!" argument before the protocol inverts the -test. The number zero is equivalent to \fBall\fP. -Protocol \fBall\fP +test. The number zero is equivalent to \fBall\fP. "\fBall\fP" will match with all protocols and is taken as default when this option is omitted. .TP @@ -15,9 +15,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#include <ctype.h> #include <errno.h> #include <fcntl.h> +#include <inttypes.h> #include <netdb.h> #include <stdarg.h> #include <stdbool.h> @@ -426,15 +427,20 @@ int xtables_load_ko(const char *modprobe, bool quiet) * Returns true/false whether number was accepted. On failure, *value has * undefined contents. */ -bool xtables_strtoul(const char *s, char **end, unsigned long *value, - unsigned long min, unsigned long max) +bool xtables_strtoul(const char *s, char **end, uintmax_t *value, + uintmax_t min, uintmax_t max) { - unsigned long v; + uintmax_t v; + const char *p; char *my_end; errno = 0; - v = strtoul(s, &my_end, 0); - + /* Since strtoul allows leading minus, we have to check for ourself. */ + for (p = s; isspace(*p); ++p) + ; + if (*p == '-') + return false; + v = strtoumax(s, &my_end, 0); if (my_end == s) return false; if (end != NULL) @@ -454,7 +460,7 @@ bool xtables_strtoul(const char *s, char **end, unsigned long *value, bool xtables_strtoui(const char *s, char **end, unsigned int *value, unsigned int min, unsigned int max) { - unsigned long v; + uintmax_t v; bool ret; ret = xtables_strtoul(s, end, &v, min, max); diff --git a/xtoptions.c b/xtoptions.c index eb9e4e6b..ac0601f2 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -41,6 +41,31 @@ struct tos_value_mask { uint8_t value, mask; }; +static const size_t xtopt_psize[] = { + /* + * All types not listed here, and thus essentially being initialized to + * zero have zero on purpose. + */ + [XTTYPE_UINT8] = sizeof(uint8_t), + [XTTYPE_UINT16] = sizeof(uint16_t), + [XTTYPE_UINT32] = sizeof(uint32_t), + [XTTYPE_UINT64] = sizeof(uint64_t), + [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), + [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), + [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), + [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), + [XTTYPE_DOUBLE] = sizeof(double), + [XTTYPE_STRING] = -1, + [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), + [XTTYPE_HOST] = sizeof(union nf_inet_addr), + [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr), + [XTTYPE_PROTOCOL] = sizeof(uint8_t), + [XTTYPE_PORT] = sizeof(uint16_t), + [XTTYPE_PORTRC] = sizeof(uint16_t[2]), + [XTTYPE_PLENMASK] = sizeof(union nf_inet_addr), + [XTTYPE_ETHERMAC] = sizeof(uint8_t[6]), +}; + /** * Creates getopt options from the x6-style option map, and assigns each a * getopt id. @@ -99,29 +124,66 @@ xtables_options_xfrm(struct option *orig_opts, struct option *oldopts, } /** + * Give the upper limit for a certain type. + */ +static uintmax_t xtopt_max_by_type(enum xt_option_type type) +{ + switch (type) { + case XTTYPE_UINT8: + case XTTYPE_UINT8RC: + return UINT8_MAX; + case XTTYPE_UINT16: + case XTTYPE_UINT16RC: + return UINT16_MAX; + case XTTYPE_UINT32: + case XTTYPE_UINT32RC: + return UINT32_MAX; + case XTTYPE_UINT64: + case XTTYPE_UINT64RC: + return UINT64_MAX; + default: + return 0; + } +} + +/** + * Return the size of a single entity based upon a type - predominantly an + * XTTYPE_UINT*RC type. + */ +static size_t xtopt_esize_by_type(enum xt_option_type type) +{ + switch (type) { + case XTTYPE_UINT8RC: + return xtopt_psize[XTTYPE_UINT8]; + case XTTYPE_UINT16RC: + return xtopt_psize[XTTYPE_UINT16]; + case XTTYPE_UINT32RC: + return xtopt_psize[XTTYPE_UINT32]; + case XTTYPE_UINT64RC: + return xtopt_psize[XTTYPE_UINT64]; + default: + return xtopt_psize[type]; + } +} + +/** * Require a simple integer. */ static void xtopt_parse_int(struct xt_option_call *cb) { const struct xt_option_entry *entry = cb->entry; - unsigned long long lmin = 0, lmax = UINT32_MAX; - unsigned int value; + uintmax_t lmin = 0, lmax = xtopt_max_by_type(entry->type); + uintmax_t value; - if (entry->type == XTTYPE_UINT8) - lmax = UINT8_MAX; - else if (entry->type == XTTYPE_UINT16) - lmax = UINT16_MAX; - else if (entry->type == XTTYPE_UINT64) - lmax = UINT64_MAX; if (cb->entry->min != 0) lmin = cb->entry->min; if (cb->entry->max != 0) lmax = cb->entry->max; - if (!xtables_strtoui(cb->arg, NULL, &value, lmin, lmax)) + if (!xtables_strtoul(cb->arg, NULL, &value, lmin, lmax)) xt_params->exit_err(PARAMETER_PROBLEM, "%s: bad value for option \"--%s\", " - "or out of range (%llu-%llu).\n", + "or out of range (%ju-%ju).\n", cb->ext_name, entry->name, lmin, lmax); if (entry->type == XTTYPE_UINT8) { @@ -167,6 +229,48 @@ static void xtopt_parse_float(struct xt_option_call *cb) } /** + * Copy the parsed value to the appropriate entry in cb->val. + */ +static void xtopt_mint_value_to_cb(struct xt_option_call *cb, uintmax_t value) +{ + const struct xt_option_entry *entry = cb->entry; + + if (cb->nvals >= ARRAY_SIZE(cb->val.u32_range)) + return; + if (entry->type == XTTYPE_UINT8RC) + cb->val.u8_range[cb->nvals] = value; + else if (entry->type == XTTYPE_UINT16RC) + cb->val.u16_range[cb->nvals] = value; + else if (entry->type == XTTYPE_UINT32RC) + cb->val.u32_range[cb->nvals] = value; + else if (entry->type == XTTYPE_UINT64RC) + cb->val.u64_range[cb->nvals] = value; +} + +/** + * Copy the parsed value to the data area, using appropriate type access. + */ +static void xtopt_mint_value_to_ptr(struct xt_option_call *cb, void **datap, + uintmax_t value) +{ + const struct xt_option_entry *entry = cb->entry; + void *data = *datap; + + if (!(entry->flags & XTOPT_PUT)) + return; + if (entry->type == XTTYPE_UINT8RC) + *(uint8_t *)data = value; + else if (entry->type == XTTYPE_UINT16RC) + *(uint16_t *)data = value; + else if (entry->type == XTTYPE_UINT32RC) + *(uint32_t *)data = value; + else if (entry->type == XTTYPE_UINT64RC) + *(uint64_t *)data = value; + data += xtopt_esize_by_type(entry->type); + *datap = data; +} + +/** * Multiple integer parse routine. * * This function is capable of parsing any number of fields. Only the first @@ -179,62 +283,46 @@ static void xtopt_parse_mint(struct xt_option_call *cb) { const struct xt_option_entry *entry = cb->entry; const char *arg = cb->arg; - size_t esize = sizeof(uint32_t); - char *put = XTOPT_MKPTR(cb); - unsigned int maxiter, value; + size_t esize = xtopt_esize_by_type(entry->type); + const uintmax_t lmax = xtopt_max_by_type(entry->type); + void *put = XTOPT_MKPTR(cb); + unsigned int maxiter; + uintmax_t value; char *end = ""; char sep = ':'; - if (entry->type == XTTYPE_UINT8RC) - esize = sizeof(uint8_t); - else if (entry->type == XTTYPE_UINT16RC) - esize = sizeof(uint16_t); - else if (entry->type == XTTYPE_UINT64RC) - esize = sizeof(uint64_t); maxiter = entry->size / esize; if (maxiter == 0) - maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */ + maxiter = ARRAY_SIZE(cb->val.u32_range); if (entry->size % esize != 0) xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " "not have proper size\n", __func__); cb->nvals = 0; - for (arg = cb->arg; ; arg = end + 1) { + for (arg = cb->arg, end = (char *)arg; ; arg = end + 1) { if (cb->nvals == maxiter) xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " "components for option \"--%s\" (max: %u)\n", cb->ext_name, entry->name, maxiter); - if (!xtables_strtoui(arg, &end, &value, 0, UINT32_MAX)) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: bad value for option \"--%s\", " - "or out of range (0-%u).\n", - cb->ext_name, entry->name, UINT32_MAX); - if (*end != '\0' && *end != sep) - xt_params->exit_err(PARAMETER_PROBLEM, - "%s: Argument to \"--%s\" has unexpected " - "characters.\n", cb->ext_name, entry->name); - if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) { - if (entry->type == XTTYPE_UINT8RC) - cb->val.u8_range[cb->nvals] = value; - else if (entry->type == XTTYPE_UINT16RC) - cb->val.u16_range[cb->nvals] = value; - else if (entry->type == XTTYPE_UINT32RC) - cb->val.u32_range[cb->nvals] = value; - else if (entry->type == XTTYPE_UINT64RC) - cb->val.u64_range[cb->nvals] = value; + if (*arg == '\0' || *arg == sep) { + /* Default range components when field not spec'd. */ + end = (char *)arg; + value = (cb->nvals == 1) ? lmax : 0; + } else { + if (!xtables_strtoul(arg, &end, &value, 0, lmax)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad value for option \"--%s\" near " + "\"%s\", or out of range (0-%ju).\n", + cb->ext_name, entry->name, arg, lmax); + if (*end != '\0' && *end != sep) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: Argument to \"--%s\" has " + "unexpected characters near \"%s\".\n", + cb->ext_name, entry->name, end); } + xtopt_mint_value_to_cb(cb, value); ++cb->nvals; - if (entry->flags & XTOPT_PUT) { - if (entry->type == XTTYPE_UINT8RC) - *(uint8_t *)put = value; - else if (entry->type == XTTYPE_UINT16RC) - *(uint16_t *)put = value; - else if (entry->type == XTTYPE_UINT32RC) - *(uint32_t *)put = value; - else if (entry->type == XTTYPE_UINT64RC) - *(uint64_t *)put = value; - put += esize; - } + xtopt_mint_value_to_ptr(cb, &put, value); if (*end == '\0') break; } @@ -509,6 +597,7 @@ static void xtopt_parse_protocol(struct xt_option_call *cb) */ static void xtopt_parse_port(struct xt_option_call *cb) { + const struct xt_option_entry *entry = cb->entry; int ret; ret = xtables_getportbyname(cb->arg); @@ -516,10 +605,10 @@ static void xtopt_parse_port(struct xt_option_call *cb) xt_params->exit_err(PARAMETER_PROBLEM, "Port \"%s\" does not resolve to anything.\n", cb->arg); + if (entry->flags & XTOPT_NBO) + ret = htons(ret); cb->val.port = ret; - if (cb->entry->type == XTTYPE_PORT_NE) - cb->val.port = htons(cb->val.port); - if (cb->entry->flags & XTOPT_PUT) + if (entry->flags & XTOPT_PUT) *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port; } @@ -561,7 +650,7 @@ static void xtopt_parse_mport(struct xt_option_call *cb) xt_params->exit_err(PARAMETER_PROBLEM, "Port \"%s\" does not resolve to " "anything.\n", arg); - if (entry->type == XTTYPE_PORTRC_NE) + if (entry->flags & XTOPT_NBO) value = htons(value); if (cb->nvals < ARRAY_SIZE(cb->val.port_range)) cb->val.port_range[cb->nvals] = value; @@ -702,41 +791,12 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_HOSTMASK] = xtopt_parse_hostmask, [XTTYPE_PROTOCOL] = xtopt_parse_protocol, [XTTYPE_PORT] = xtopt_parse_port, - [XTTYPE_PORT_NE] = xtopt_parse_port, [XTTYPE_PORTRC] = xtopt_parse_mport, - [XTTYPE_PORTRC_NE] = xtopt_parse_mport, [XTTYPE_PLEN] = xtopt_parse_plen, [XTTYPE_PLENMASK] = xtopt_parse_plenmask, [XTTYPE_ETHERMAC] = xtopt_parse_ethermac, }; -static const size_t xtopt_psize[] = { - /* - * All types not listed here, and thus essentially being initialized to - * zero have zero on purpose. - */ - [XTTYPE_UINT8] = sizeof(uint8_t), - [XTTYPE_UINT16] = sizeof(uint16_t), - [XTTYPE_UINT32] = sizeof(uint32_t), - [XTTYPE_UINT64] = sizeof(uint64_t), - [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), - [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), - [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), - [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), - [XTTYPE_DOUBLE] = sizeof(double), - [XTTYPE_STRING] = -1, - [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), - [XTTYPE_HOST] = sizeof(union nf_inet_addr), - [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr), - [XTTYPE_PROTOCOL] = sizeof(uint8_t), - [XTTYPE_PORT] = sizeof(uint16_t), - [XTTYPE_PORT_NE] = sizeof(uint16_t), - [XTTYPE_PORTRC] = sizeof(uint16_t[2]), - [XTTYPE_PORTRC_NE] = sizeof(uint16_t[2]), - [XTTYPE_PLENMASK] = sizeof(union nf_inet_addr), - [XTTYPE_ETHERMAC] = sizeof(uint8_t[6]), -}; - /** * The master option parsing routine. May be used for the ".x6_parse" * function pointer in extensions if fully automatic parsing is desired. |