..by moving type-based actions into their own function. Signed-off-by: Jan Engelhardt <jengelh@xxxxxxxxxx> --- xtoptions.c | 148 +++++++++++++++++++++++++++++++++++++--------------------- 1 files changed, 94 insertions(+), 54 deletions(-) diff --git a/xtoptions.c b/xtoptions.c index 1fc90ee..30d70b0 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. @@ -98,6 +123,9 @@ xtables_options_xfrm(struct option *orig_opts, struct option *oldopts, return merge; } +/** + * Give the upper limit for a certain type. + */ static uintmax_t xtopt_max_by_type(enum xt_option_type type) { switch (type) { @@ -119,6 +147,26 @@ static uintmax_t xtopt_max_by_type(enum xt_option_type type) } /** + * 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) @@ -181,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 @@ -193,20 +283,14 @@ 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); + size_t esize = xtopt_esize_by_type(entry->type); uintmax_t lmax = xtopt_max_by_type(entry->type); - char *put = XTOPT_MKPTR(cb); + 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) */ @@ -230,28 +314,9 @@ static void xtopt_parse_mint(struct xt_option_call *cb) "%s: Argument to \"--%s\" has unexpected " "characters near \"%s\".\n", cb->ext_name, entry->name, end); - 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; - } + 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; } @@ -726,31 +791,6 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [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_PORTRC] = 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. -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html