summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/xtables.h.in6
-rw-r--r--xtoptions.c55
2 files changed, 59 insertions, 2 deletions
diff --git a/include/xtables.h.in b/include/xtables.h.in
index dc074bc0..3e596e0c 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -48,11 +48,13 @@ struct in_addr;
/**
* %XTTYPE_NONE: option takes no argument
* %XTTYPE_UINT*: standard integer
+ * %XTTYPE_UINT*RC: colon-separated range of standard integers
*/
enum xt_option_type {
XTTYPE_NONE,
XTTYPE_UINT8,
XTTYPE_UINT32,
+ XTTYPE_UINT32RC,
};
/**
@@ -96,6 +98,7 @@ struct xt_option_entry {
* @data: per-extension data block
* @xflags: options of the extension that have been used
* @invert: whether option was used with !
+ * @nvals: number of results in uXX_multi
* @val: parsed result
*/
struct xt_option_call {
@@ -104,9 +107,10 @@ struct xt_option_call {
void *data;
unsigned int xflags;
bool invert;
+ uint8_t nvals;
union {
uint8_t u8;
- uint32_t u32;
+ uint32_t u32, u32_range[2];
} val;
};
diff --git a/xtoptions.c b/xtoptions.c
index 693c06d6..03c629e0 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -113,14 +113,66 @@ static void xtopt_parse_int(struct xt_option_call *cb)
}
}
+/**
+ * Multiple integer parse routine.
+ *
+ * This function is capable of parsing any number of fields. Only the first
+ * two values from the string will be put into @cb however (and as such,
+ * @cb->val.uXX_range is just that large) to cater for the few extensions that
+ * do not have a range[2] field, but {min, max}, and which cannot use
+ * XTOPT_POINTER.
+ */
+static void xtopt_parse_mint(struct xt_option_call *cb)
+{
+ const struct xt_option_entry *entry = cb->entry;
+ const char *arg = cb->arg;
+ uint32_t *put = XTOPT_MKPTR(cb);
+ unsigned int maxiter, value;
+ char *end = "";
+ char sep = ':';
+
+ maxiter = entry->size / sizeof(uint32_t);
+ if (maxiter == 0)
+ maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */
+ if (entry->size % sizeof(uint32_t) != 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) {
+ 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);
+ ++cb->nvals;
+ if (cb->nvals < ARRAY_SIZE(cb->val.u32_range))
+ cb->val.u32_range[cb->nvals] = value;
+ if (entry->flags & XTOPT_PUT)
+ *put++ = value;
+ if (*end == '\0')
+ break;
+ }
+}
+
static void (*const xtopt_subparse[])(struct xt_option_call *) = {
[XTTYPE_UINT8] = xtopt_parse_int,
[XTTYPE_UINT32] = xtopt_parse_int,
+ [XTTYPE_UINT32RC] = xtopt_parse_mint,
};
static const size_t xtopt_psize[] = {
[XTTYPE_UINT8] = sizeof(uint8_t),
[XTTYPE_UINT32] = sizeof(uint32_t),
+ [XTTYPE_UINT32RC] = sizeof(uint32_t[2]),
};
/**
@@ -180,7 +232,8 @@ void xtables_option_metavalidate(const char *name,
"%s: entry type of option \"--%s\" cannot be "
"combined with XTOPT_PUT\n",
name, entry->name);
- if (xtopt_psize[entry->type] != entry->size)
+ if (xtopt_psize[entry->type] != -1 &&
+ xtopt_psize[entry->type] != entry->size)
xt_params->exit_err(OTHER_PROBLEM,
"%s: option \"--%s\" points to a memory block "
"of wrong size (expected %zu, got %zu)\n",