]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
libxt_TOS: use guided option parser
authorJan Engelhardt <jengelh@medozas.de>
Thu, 28 Apr 2011 23:25:14 +0000 (01:25 +0200)
committerJan Engelhardt <jengelh@medozas.de>
Sun, 1 May 2011 11:47:34 +0000 (13:47 +0200)
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
extensions/libxt_TOS.c
include/xtables.h.in
xtoptions.c

index 58ff2fc76e8571b9b0568811f683404e100f31f9..cef587650278e70aea7ab629190c9718e982a0b6 100644 (file)
@@ -2,7 +2,7 @@
  * Shared library add-on to iptables to add TOS target support
  *
  * Copyright © CC Computer Consultants GmbH, 2007
- * Contact: Jan Engelhardt <jengelh@computergmbh.de>
+ * Contact: Jan Engelhardt <jengelh@medozas.de>
  */
 #include <getopt.h>
 #include <stdbool.h>
@@ -20,20 +20,33 @@ struct ipt_tos_target_info {
 };
 
 enum {
-       FLAG_TOS = 1 << 0,
+       O_SET_TOS = 0,
+       O_AND_TOS,
+       O_OR_TOS,
+       O_XOR_TOS,
+       F_SET_TOS = 1 << O_SET_TOS,
+       F_AND_TOS = 1 << O_AND_TOS,
+       F_OR_TOS  = 1 << O_OR_TOS,
+       F_XOR_TOS = 1 << O_XOR_TOS,
+       F_ANY     = F_SET_TOS | F_AND_TOS | F_OR_TOS | F_XOR_TOS,
 };
 
-static const struct option tos_tg_opts_v0[] = {
-       {.name = "set-tos", .has_arg = true, .val = '='},
-       XT_GETOPT_TABLEEND,
+static const struct xt_option_entry tos_tg_opts_v0[] = {
+       {.name = "set-tos", .id = O_SET_TOS, .type = XTTYPE_TOSMASK,
+        .excl = F_ANY, .max = 0xFF},
+       XTOPT_TABLEEND,
 };
 
-static const struct option tos_tg_opts[] = {
-       {.name = "set-tos", .has_arg = true, .val = '='},
-       {.name = "and-tos", .has_arg = true, .val = '&'},
-       {.name = "or-tos",  .has_arg = true, .val = '|'},
-       {.name = "xor-tos", .has_arg = true, .val = '^'},
-       XT_GETOPT_TABLEEND,
+static const struct xt_option_entry tos_tg_opts[] = {
+       {.name = "set-tos", .id = O_SET_TOS, .type = XTTYPE_TOSMASK,
+        .excl = F_ANY, .max = 0x3F},
+       {.name = "and-tos", .id = O_AND_TOS, .type = XTTYPE_UINT8,
+        .excl = F_ANY},
+       {.name = "or-tos", .id = O_OR_TOS, .type = XTTYPE_UINT8,
+        .excl = F_ANY},
+       {.name = "xor-tos", .id = O_XOR_TOS, .type = XTTYPE_UINT8,
+        .excl = F_ANY},
+       XTOPT_TABLEEND,
 };
 
 static void tos_tg_help_v0(void)
@@ -78,84 +91,48 @@ XTABLES_VERSION);
 );
 }
 
-static int tos_tg_parse_v0(int c, char **argv, int invert, unsigned int *flags,
-                           const void *entry, struct xt_entry_target **target)
+static void tos_tg_parse_v0(struct xt_option_call *cb)
 {
-       struct ipt_tos_target_info *info = (void *)(*target)->data;
-       struct tos_value_mask tvm;
-
-       switch (c) {
-       case '=':
-               xtables_param_act(XTF_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS);
-               xtables_param_act(XTF_NO_INVERT, "TOS", "--set-tos", invert);
-               if (!tos_parse_symbolic(optarg, &tvm, 0xFF))
-                       xtables_param_act(XTF_BAD_VALUE, "TOS", "--set-tos", optarg);
-               if (tvm.mask != 0xFF)
-                       xtables_error(PARAMETER_PROBLEM, "tos match: Your kernel "
-                                  "is too old to support anything besides "
-                                  "/0xFF as a mask.");
-               info->tos = tvm.value;
-               *flags |= FLAG_TOS;
-               return true;
-       }
-
-       return false;
+       struct ipt_tos_target_info *info = cb->data;
+
+       xtables_option_parse(cb);
+       if (cb->val.tos_mask != 0xFF)
+               xtables_error(PARAMETER_PROBLEM, "tos match: Your kernel "
+                          "is too old to support anything besides "
+                          "/0xFF as a mask.");
+       info->tos = cb->val.tos_value;
 }
 
-static int tos_tg_parse(int c, char **argv, int invert, unsigned int *flags,
-                         const void *entry, struct xt_entry_target **target)
+static void tos_tg_parse(struct xt_option_call *cb)
 {
-       struct xt_tos_target_info *info = (void *)(*target)->data;
-       struct tos_value_mask tvm;
-       unsigned int bits;
-
-       switch (c) {
-       case '=': /* --set-tos */
-               xtables_param_act(XTF_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS);
-               xtables_param_act(XTF_NO_INVERT, "TOS", "--set-tos", invert);
-               if (!tos_parse_symbolic(optarg, &tvm, 0x3F))
-                       xtables_param_act(XTF_BAD_VALUE, "TOS", "--set-tos", optarg);
-               info->tos_value = tvm.value;
-               info->tos_mask  = tvm.mask;
-               break;
+       struct xt_tos_target_info *info = cb->data;
 
-       case '&': /* --and-tos */
-               xtables_param_act(XTF_ONLY_ONCE, "TOS", "--and-tos", *flags & FLAG_TOS);
-               xtables_param_act(XTF_NO_INVERT, "TOS", "--and-tos", invert);
-               if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX))
-                       xtables_param_act(XTF_BAD_VALUE, "TOS", "--and-tos", optarg);
+       xtables_option_parse(cb);
+       switch (cb->entry->id) {
+       case O_SET_TOS:
+               info->tos_value = cb->val.tos_value;
+               info->tos_mask  = cb->val.tos_mask;
+               break;
+       case O_AND_TOS:
                info->tos_value = 0;
-               info->tos_mask  = ~bits;
+               info->tos_mask  = ~cb->val.u8;
                break;
-
-       case '|': /* --or-tos */
-               xtables_param_act(XTF_ONLY_ONCE, "TOS", "--or-tos", *flags & FLAG_TOS);
-               xtables_param_act(XTF_NO_INVERT, "TOS", "--or-tos", invert);
-               if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX))
-                       xtables_param_act(XTF_BAD_VALUE, "TOS", "--or-tos", optarg);
-               info->tos_value = bits;
-               info->tos_mask  = bits;
+       case O_OR_TOS:
+               info->tos_value = cb->val.u8;
+               info->tos_mask  = cb->val.u8;
                break;
-
-       case '^': /* --xor-tos */
-               xtables_param_act(XTF_ONLY_ONCE, "TOS", "--xor-tos", *flags & FLAG_TOS);
-               xtables_param_act(XTF_NO_INVERT, "TOS", "--xor-tos", invert);
-               if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX))
-                       xtables_param_act(XTF_BAD_VALUE, "TOS", "--xor-tos", optarg);
-               info->tos_value = bits;
+       case O_XOR_TOS:
+               info->tos_value = cb->val.u8;
                info->tos_mask  = 0;
                break;
        }
-
-       *flags |= FLAG_TOS;
-       return true;
 }
 
-static void tos_tg_check(unsigned int flags)
+static void tos_tg_check(struct xt_fcheck_call *cb)
 {
-       if (flags == 0)
+       if (!(cb->xflags & F_ANY))
                xtables_error(PARAMETER_PROBLEM,
-                          "TOS: The --set-tos parameter is required");
+                          "TOS: An action is required");
 }
 
 static void tos_tg_print_v0(const void *ip,
@@ -215,11 +192,11 @@ static struct xtables_target tos_tg_reg[] = {
                .size          = XT_ALIGN(sizeof(struct xt_tos_target_info)),
                .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
                .help          = tos_tg_help_v0,
-               .parse         = tos_tg_parse_v0,
-               .final_check   = tos_tg_check,
                .print         = tos_tg_print_v0,
                .save          = tos_tg_save_v0,
-               .extra_opts    = tos_tg_opts_v0,
+               .x6_parse      = tos_tg_parse_v0,
+               .x6_fcheck     = tos_tg_check,
+               .x6_options    = tos_tg_opts_v0,
        },
        {
                .version       = XTABLES_VERSION,
@@ -229,11 +206,11 @@ static struct xtables_target tos_tg_reg[] = {
                .size          = XT_ALIGN(sizeof(struct xt_tos_target_info)),
                .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
                .help          = tos_tg_help,
-               .parse         = tos_tg_parse,
-               .final_check   = tos_tg_check,
                .print         = tos_tg_print,
                .save          = tos_tg_save,
-               .extra_opts    = tos_tg_opts,
+               .x6_parse      = tos_tg_parse,
+               .x6_fcheck     = tos_tg_check,
+               .x6_options    = tos_tg_opts,
        },
 };
 
index a9a9ffadf134a44dc947170f53bc5d20431e341d..b06ab613e13c73d8c7fc3fd8192166e186848571 100644 (file)
@@ -50,6 +50,7 @@ struct in_addr;
  * %XTTYPE_UINT*:      standard integer
  * %XTTYPE_UINT*RC:    colon-separated range of standard integers
  * %XTTYPE_STRING:     arbitrary string
+ * %XTTYPE_TOSMASK:    8-bit TOS value with optional mask
  * %XTTYPE_MARKMASK32: 32-bit mark with optional mask
  * %XTTYPE_SYSLOGLEVEL:        syslog level by name or number
  * %XTTYPE_ONEHOST:    one host or address (union nf_inet_addr)
@@ -67,6 +68,7 @@ enum xt_option_type {
        XTTYPE_UINT32RC,
        XTTYPE_UINT64RC,
        XTTYPE_STRING,
+       XTTYPE_TOSMASK,
        XTTYPE_MARKMASK32,
        XTTYPE_SYSLOGLEVEL,
        XTTYPE_ONEHOST,
@@ -131,6 +133,9 @@ struct xt_option_call {
                uint32_t u32, u32_range[2];
                uint64_t u64, u64_range[2];
                union nf_inet_addr inetaddr;
+               struct {
+                       uint8_t tos_value, tos_mask;
+               };
                struct {
                        uint32_t mark, mask;
                };
index 8478d26de4e66e66f3178fbc3a282928d62a1b1e..69e43e957186a57f352e2a6ca1577efd9de92bc3 100644 (file)
 #include <string.h>
 #include <syslog.h>
 #include <arpa/inet.h>
+#include <netinet/ip.h>
 #include "xtables.h"
 #include "xshared.h"
+#ifndef IPTOS_NORMALSVC
+#      define IPTOS_NORMALSVC 0
+#endif
 
 #define XTOPT_MKPTR(cb) \
        ((void *)((char *)(cb)->data + (cb)->entry->ptroff))
@@ -33,6 +37,10 @@ struct syslog_level {
        uint8_t level;
 };
 
+struct tos_value_mask {
+       uint8_t value, mask;
+};
+
 /**
  * Creates getopt options from the x6-style option map, and assigns each a
  * getopt id.
@@ -232,6 +240,78 @@ static void xtopt_parse_string(struct xt_option_call *cb)
        p[z] = '\0';
 }
 
+static const struct tos_symbol_info {
+       unsigned char value;
+       const char *name;
+} tos_symbol_names[] = {
+       {IPTOS_LOWDELAY,    "Minimize-Delay"},
+       {IPTOS_THROUGHPUT,  "Maximize-Throughput"},
+       {IPTOS_RELIABILITY, "Maximize-Reliability"},
+       {IPTOS_MINCOST,     "Minimize-Cost"},
+       {IPTOS_NORMALSVC,   "Normal-Service"},
+       {},
+};
+
+/*
+ * tos_parse_numeric - parse a string like "15/255"
+ *
+ * @str:       input string
+ * @tvm:       (value/mask) tuple
+ * @max:       maximum allowed value (must be pow(2,some_int)-1)
+ */
+static bool tos_parse_numeric(const char *str, struct xt_option_call *cb,
+                              unsigned int max)
+{
+       unsigned int value;
+       char *end;
+
+       xtables_strtoui(str, &end, &value, 0, max);
+       cb->val.tos_value = value;
+       cb->val.tos_mask  = max;
+
+       if (*end == '/') {
+               const char *p = end + 1;
+
+               if (!xtables_strtoui(p, &end, &value, 0, max))
+                       xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"",
+                                  str);
+               cb->val.tos_mask = value;
+       }
+
+       if (*end != '\0')
+               xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str);
+       return true;
+}
+
+/**
+ * @str:       input string
+ * @tvm:       (value/mask) tuple
+ * @def_mask:  mask to force when a symbolic name is used
+ */
+static void xtopt_parse_tosmask(struct xt_option_call *cb)
+{
+       const struct tos_symbol_info *symbol;
+       char *tmp;
+
+       if (xtables_strtoui(cb->arg, &tmp, NULL, 0, UINT8_MAX)) {
+               tos_parse_numeric(cb->arg, cb, UINT8_MAX);
+               return;
+       }
+       /*
+        * This is our way we deal with different defaults
+        * for different revisions.
+        */
+       cb->val.tos_mask = cb->entry->max;
+       for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+               if (strcasecmp(cb->arg, symbol->name) == 0) {
+                       cb->val.tos_value = symbol->value;
+                       return;
+               }
+
+       xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown",
+                     cb->arg);
+}
+
 /**
  * Validate the input for being conformant to "mark[/mask]".
  */
@@ -413,6 +493,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
        [XTTYPE_UINT32RC]    = xtopt_parse_mint,
        [XTTYPE_UINT64RC]    = xtopt_parse_mint,
        [XTTYPE_STRING]      = xtopt_parse_string,
+       [XTTYPE_TOSMASK]     = xtopt_parse_tosmask,
        [XTTYPE_MARKMASK32]  = xtopt_parse_markmask,
        [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel,
        [XTTYPE_ONEHOST]     = xtopt_parse_onehost,