summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libipt_tos.c163
-rw-r--r--extensions/libipt_tos.man9
-rw-r--r--extensions/libxt_tos.c190
-rw-r--r--extensions/libxt_tos.man12
-rw-r--r--extensions/tos_values.c90
5 files changed, 292 insertions, 172 deletions
diff --git a/extensions/libipt_tos.c b/extensions/libipt_tos.c
deleted file mode 100644
index 11c304f1..00000000
--- a/extensions/libipt_tos.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/* Shared library add-on to iptables to add TOS matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_tos.h>
-
-/* TOS names and values. */
-static const
-struct TOS_value
-{
- unsigned char TOS;
- const char *name;
-} TOS_values[] = {
- { IPTOS_LOWDELAY, "Minimize-Delay" },
- { IPTOS_THROUGHPUT, "Maximize-Throughput" },
- { IPTOS_RELIABILITY, "Maximize-Reliability" },
- { IPTOS_MINCOST, "Minimize-Cost" },
- { IPTOS_NORMALSVC, "Normal-Service" },
-};
-
-/* Function which prints out usage message. */
-static void tos_help(void)
-{
- unsigned int i;
-
- printf(
-"TOS match v%s options:\n"
-"[!] --tos value Match Type of Service field from one of the\n"
-" following numeric or descriptive values:\n",
-IPTABLES_VERSION);
-
- for (i = 0; i < sizeof(TOS_values)/sizeof(struct TOS_value);i++)
- printf(" %s %u (0x%02x)\n",
- TOS_values[i].name,
- TOS_values[i].TOS,
- TOS_values[i].TOS);
- fputc('\n', stdout);
-}
-
-static const struct option tos_opts[] = {
- { "tos", 1, NULL, '1' },
- { }
-};
-
-static void
-parse_tos(const char *s, struct ipt_tos_info *info)
-{
- unsigned int i;
- unsigned int tos;
-
- if (string_to_number(s, 0, 255, &tos) != -1) {
- if (tos == IPTOS_LOWDELAY
- || tos == IPTOS_THROUGHPUT
- || tos == IPTOS_RELIABILITY
- || tos == IPTOS_MINCOST
- || tos == IPTOS_NORMALSVC) {
- info->tos = (u_int8_t )tos;
- return;
- }
- } else {
- for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
- if (strcasecmp(s,TOS_values[i].name) == 0) {
- info->tos = TOS_values[i].TOS;
- return;
- }
- }
- exit_error(PARAMETER_PROBLEM, "Bad TOS value `%s'", s);
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int tos_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- struct ipt_tos_info *tosinfo = (struct ipt_tos_info *)(*match)->data;
-
- switch (c) {
- case '1':
- /* Ensure that `--tos' haven't been used yet. */
- if (*flags == 1)
- exit_error(PARAMETER_PROBLEM,
- "tos match: only use --tos once!");
-
- check_inverse(optarg, &invert, &optind, 0);
- parse_tos(argv[optind-1], tosinfo);
- if (invert)
- tosinfo->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static void
-print_tos(u_int8_t tos, int numeric)
-{
- unsigned int i;
-
- if (!numeric) {
- for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
- if (TOS_values[i].TOS == tos) {
- printf("%s ", TOS_values[i].name);
- return;
- }
- }
- printf("0x%02x ", tos);
-}
-
-/* Final check; must have specified --tos. */
-static void tos_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "TOS match: You must specify `--tos'");
-}
-
-/* Prints out the matchinfo. */
-static void tos_print(const void *ip, const struct xt_entry_match *match,
- int numeric)
-{
- const struct ipt_tos_info *info = (const struct ipt_tos_info *)match->data;
-
- printf("TOS match ");
- if (info->invert)
- printf("!");
- print_tos(info->tos, numeric);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void tos_save(const void *ip, const struct xt_entry_match *match)
-{
- const struct ipt_tos_info *info = (const struct ipt_tos_info *)match->data;
-
- if (info->invert)
- printf("! ");
- printf("--tos ");
- print_tos(info->tos, 0);
-}
-
-static struct iptables_match tos_match = {
- .name = "tos",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_tos_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_tos_info)),
- .help = tos_help,
- .parse = tos_parse,
- .final_check = tos_check,
- .print = tos_print,
- .save = tos_save,
- .extra_opts = tos_opts,
-};
-
-void _init(void)
-{
- register_match(&tos_match);
-}
diff --git a/extensions/libipt_tos.man b/extensions/libipt_tos.man
deleted file mode 100644
index c612b299..00000000
--- a/extensions/libipt_tos.man
+++ /dev/null
@@ -1,9 +0,0 @@
-This module matches the 8 bits of Type of Service field in the IP
-header (ie. including the precedence bits).
-.TP
-.BI "--tos " "tos"
-The argument is either a standard name, (use
-.br
- iptables -m tos -h
-.br
-to see the list), or a numeric value to match.
diff --git a/extensions/libxt_tos.c b/extensions/libxt_tos.c
new file mode 100644
index 00000000..e437f470
--- /dev/null
+++ b/extensions/libxt_tos.c
@@ -0,0 +1,190 @@
+/*
+ * Shared library add-on to iptables to add tos match support
+ *
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <getopt.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_dscp.h>
+#include <linux/netfilter_ipv4/ipt_tos.h>
+#include "tos_values.c"
+
+enum {
+ FLAG_TOS = 1 << 0,
+};
+
+static const struct option tos_mt_opts[] = {
+ {.name = "tos", .has_arg = true, .val = 't'},
+ {},
+};
+
+static void tos_mt_help(void)
+{
+ const struct tos_symbol_info *symbol;
+
+ printf(
+"tos match options:\n"
+"[!] --tos value[/mask] Match Type of Service/Priority field value\n"
+"[!] --tos symbol Match TOS field (IPv4 only) by symbol\n"
+" Accepted symbolic names for value are:\n");
+
+ for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+ printf(" (0x%02x) %2u %s\n",
+ symbol->value, symbol->value, symbol->name);
+
+ printf("\n");
+}
+
+static int tos_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ipt_tos_info *info = (void *)(*match)->data;
+ struct tos_value_mask tvm;
+
+ switch (c) {
+ case 't':
+ param_act(P_ONLY_ONCE, "tos", "--tos", *flags & FLAG_TOS);
+ if (!tos_parse_symbolic(optarg, &tvm, 0xFF))
+ param_act(P_BAD_VALUE, "tos", "--tos", optarg);
+ if (tvm.mask != 0xFF)
+ exit_error(PARAMETER_PROBLEM, "tos: Your kernel is "
+ "too old to support anything besides /0xFF "
+ "as a mask.");
+ info->tos = tvm.value;
+ if (invert)
+ info->invert = true;
+ *flags |= FLAG_TOS;
+ return true;
+ }
+ return false;
+}
+
+static int tos_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_tos_match_info *info = (void *)(*match)->data;
+ struct tos_value_mask tvm = {.mask = 0xFF};
+
+ switch (c) {
+ case 't':
+ param_act(P_ONLY_ONCE, "tos", "--tos", *flags & FLAG_TOS);
+ if (!tos_parse_symbolic(optarg, &tvm, 0x3F))
+ param_act(P_BAD_VALUE, "tos", "--tos", optarg);
+ info->tos_value = tvm.value;
+ info->tos_mask = tvm.mask;
+ if (invert)
+ info->invert = true;
+ *flags |= FLAG_TOS;
+ return true;
+ }
+ return false;
+}
+
+static void tos_mt_check(unsigned int flags)
+{
+ if (flags == 0)
+ exit_error(PARAMETER_PROBLEM,
+ "tos: --tos parameter required");
+}
+
+static void tos_mt_print_v0(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ipt_tos_info *info = (const void *)match->data;
+
+ printf("tos match ");
+ if (info->invert)
+ printf("!");
+ if (numeric || !tos_try_print_symbolic("", info->tos, 0x3F))
+ printf("0x%02x ", info->tos);
+}
+
+static void tos_mt_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_tos_match_info *info = (const void *)match->data;
+
+ printf("tos match ");
+ if (info->invert)
+ printf("!");
+ if (numeric ||
+ !tos_try_print_symbolic("", info->tos_value, info->tos_mask))
+ printf("0x%02x/0x%02x ", info->tos_value, info->tos_mask);
+}
+
+static void tos_mt_save_v0(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ipt_tos_info *info = (const void *)match->data;
+
+ if (info->invert)
+ printf("! ");
+ printf("--tos 0x%02x ", info->tos);
+}
+
+static void tos_mt_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_tos_match_info *info = (const void *)match->data;
+
+ if (info->invert)
+ printf("! ");
+ printf("--tos 0x%02x/0x%02x ", info->tos_value, info->tos_mask);
+}
+
+static struct xtables_match tos_mt_reg_v0 = {
+ .version = IPTABLES_VERSION,
+ .name = "tos",
+ .family = AF_INET,
+ .revision = 0,
+ .size = XT_ALIGN(sizeof(struct ipt_tos_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_tos_info)),
+ .help = tos_mt_help,
+ .parse = tos_mt_parse_v0,
+ .final_check = tos_mt_check,
+ .print = tos_mt_print_v0,
+ .save = tos_mt_save_v0,
+ .extra_opts = tos_mt_opts,
+};
+
+static struct xtables_match tos_mt_reg = {
+ .version = IPTABLES_VERSION,
+ .name = "tos",
+ .family = AF_INET,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct xt_tos_match_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tos_match_info)),
+ .help = tos_mt_help,
+ .parse = tos_mt_parse,
+ .final_check = tos_mt_check,
+ .print = tos_mt_print,
+ .save = tos_mt_save,
+ .extra_opts = tos_mt_opts,
+};
+
+static struct xtables_match tos_mt6_reg = {
+ .version = IPTABLES_VERSION,
+ .name = "tos",
+ .family = AF_INET6,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct xt_tos_match_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tos_match_info)),
+ .help = tos_mt_help,
+ .parse = tos_mt_parse,
+ .final_check = tos_mt_check,
+ .print = tos_mt_print,
+ .save = tos_mt_save,
+ .extra_opts = tos_mt_opts,
+};
+
+void _init(void)
+{
+ xtables_register_match(&tos_mt_reg_v0);
+ xtables_register_match(&tos_mt_reg);
+ xtables_register_match(&tos_mt6_reg);
+}
diff --git a/extensions/libxt_tos.man b/extensions/libxt_tos.man
new file mode 100644
index 00000000..0420105e
--- /dev/null
+++ b/extensions/libxt_tos.man
@@ -0,0 +1,12 @@
+This module matches the 8-bit Type of Service field in the IPv4 header (i.e.
+including the "Precedence" bits) or the (also 8-bit) Priority field in the IPv6
+header.
+.TP
+\fB--tos\fR \fIvalue\fR[\fB/\fR\fImask\fR]
+Matches packets with the given TOS mark value. If a mask is specified, it is
+logically ANDed with the TOS mark before the comparison.
+.TP
+\fB--tos\fR \fIsymbol\fR
+You can specify a symbolic name when using the tos match for IPv4. The list of
+recognized TOS names can be obtained by calling iptables with \fB-m tos -h\fR.
+Note that this implies a mask of 0x3F, i.e. all but the ECN bits.
diff --git a/extensions/tos_values.c b/extensions/tos_values.c
new file mode 100644
index 00000000..014b65b0
--- /dev/null
+++ b/extensions/tos_values.c
@@ -0,0 +1,90 @@
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+struct tos_value_mask {
+ uint8_t value, mask;
+};
+
+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 sth. like "15/255"
+ *
+ * @s: input string
+ * @info: accompanying structure
+ * @bits: number of bits that are allowed
+ * (8 for IPv4 TOS field, 4 for IPv6 Priority Field)
+ */
+static bool tos_parse_numeric(const char *str, struct tos_value_mask *tvm,
+ unsigned int bits)
+{
+ const unsigned int max = (1 << bits) - 1;
+ unsigned int value;
+ char *end;
+
+ strtonum(str, &end, &value, 0, max);
+ tvm->value = value;
+ tvm->mask = max;
+
+ if (*end == '/') {
+ const char *p = end + 1;
+
+ if (!strtonum(p, &end, &value, 0, max))
+ exit_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"",
+ str);
+ tvm->mask = value;
+ }
+
+ if (*end != '\0')
+ exit_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str);
+ return true;
+}
+
+static bool tos_parse_symbolic(const char *str, struct tos_value_mask *tvm,
+ unsigned int def_mask)
+{
+ const unsigned int max = 255;
+ const struct tos_symbol_info *symbol;
+
+ if (strtonum(str, NULL, NULL, 0, max))
+ return tos_parse_numeric(str, tvm, max);
+
+ /* Do not consider ECN bits */
+ tvm->mask = def_mask;
+ for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+ if (strcasecmp(str, symbol->name) == 0) {
+ tvm->value = symbol->value;
+ return true;
+ }
+
+ exit_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown", str);
+ return false;
+}
+
+static bool tos_try_print_symbolic(const char *prefix,
+ u_int8_t value, u_int8_t mask)
+{
+ const struct tos_symbol_info *symbol;
+
+ if (mask != 0x3F)
+ return false;
+
+ for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+ if (value == symbol->value) {
+ printf("%s%s ", prefix, symbol->name);
+ return true;
+ }
+
+ return false;
+}