From 0720c1226381f5c71748673c43c12499f1f254c7 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 20 Jan 2008 13:22:42 +0000 Subject: libxt_tos Move libipt_tos revision 0 to libxt_tos revision 0 and add support for xt_tos match revision 1. Signed-off-by: Jan Engelhardt --- extensions/libipt_tos.c | 163 -------------------------------- extensions/libipt_tos.man | 9 -- extensions/libxt_tos.c | 190 ++++++++++++++++++++++++++++++++++++++ extensions/libxt_tos.man | 12 +++ extensions/tos_values.c | 90 ++++++++++++++++++ include/linux/netfilter/xt_dscp.h | 6 ++ 6 files changed, 298 insertions(+), 172 deletions(-) delete mode 100644 extensions/libipt_tos.c delete mode 100644 extensions/libipt_tos.man create mode 100644 extensions/libxt_tos.c create mode 100644 extensions/libxt_tos.man create mode 100644 extensions/tos_values.c 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 -#include -#include -#include -#include - -#include -#include - -/* 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; itos = 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; idata; - - 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 + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#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 +#include +#include + +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; +} diff --git a/include/linux/netfilter/xt_dscp.h b/include/linux/netfilter/xt_dscp.h index 1da61e6a..f49bc1a6 100644 --- a/include/linux/netfilter/xt_dscp.h +++ b/include/linux/netfilter/xt_dscp.h @@ -20,4 +20,10 @@ struct xt_dscp_info { u_int8_t invert; }; +struct xt_tos_match_info { + u_int8_t tos_mask; + u_int8_t tos_value; + u_int8_t invert; +}; + #endif /* _XT_DSCP_H */ -- cgit v1.2.3