Import libxt_TCPOPTSTRIP into iptables. Signed-off-by: Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx> --- extensions/Makefile | 1 extensions/libxt_TCPOPTSTRIP.c | 212 +++++++++++++++++++++++++++++++ extensions/libxt_TCPOPTSTRIP.man | 7 + include/linux/netfilter/xt_TCPOPTSTRIP.h | 13 + 4 files changed, 233 insertions(+) Index: iptables-modules/extensions/Makefile =================================================================== --- iptables-modules.orig/extensions/Makefile +++ iptables-modules/extensions/Makefile @@ -54,6 +54,7 @@ PFX_EXT_SLIB += NFLOG PFX_EXT_SLIB += NFQUEUE PFX_EXT_SLIB += NOTRACK PFX_EXT_SLIB += TCPMSS +PFX_EXT_SLIB += TCPOPTSTRIP PFX_EXT_SLIB += TOS PFX_EXT_SLIB += TRACE PFX_EXT_SLIB += comment Index: iptables-modules/extensions/libxt_TCPOPTSTRIP.c =================================================================== --- /dev/null +++ iptables-modules/extensions/libxt_TCPOPTSTRIP.c @@ -0,0 +1,212 @@ +/* + * Shared library add-on to iptables to add TCPOPTSTRIP target support. + * Copyright (c) 2007 Sven Schnelle <svens@xxxxxxxxxxxx> + * Copyright © CC Computer Consultants GmbH, 2007 + * Contact: Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx> + */ +#include <getopt.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <xtables.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_TCPOPTSTRIP.h> +#ifndef TCPOPT_MD5SIG +# define TCPOPT_MD5SIG 19 +#endif + +enum { + FLAG_STRIP = 1 << 0, +}; + +struct tcp_optionmap { + const char *name, *desc; + const int option; +}; + +static const struct option tcpoptstrip_tg_opts[] = { + {.name = "strip-options", .has_arg = true, .val = 's'}, + {}, +}; + +static const struct tcp_optionmap tcp_optionmap[] = { + {"wscale", "Window scale", TCPOPT_WINDOW}, + {"mss", "Maximum Segment Size", TCPOPT_MAXSEG}, + {"sack-permitted", "SACK permitted", TCPOPT_SACK_PERMITTED}, + {"sack", "Selective ACK", TCPOPT_SACK}, + {"timestamp", "Timestamp", TCPOPT_TIMESTAMP}, + {"md5", "MD5 signature", TCPOPT_MD5SIG}, + {NULL}, +}; + +static void tcpoptstrip_tg_help(void) +{ + const struct tcp_optionmap *w; + + printf( +"TCPOPTSTRIP target options:\n" +" --strip-options value strip specified TCP options denoted by value\n" +" (separated by comma) from TCP header\n" +" Instead of the numeric value, you can also use the following names:\n" + ); + + for (w = tcp_optionmap; w->name != NULL; ++w) + printf(" %-14s strip \"%s\" option\n", w->name, w->desc); +} + +static void tcpoptstrip_tg_init(struct xt_entry_target *t) +{ + struct xt_tcpoptstrip_target_info *info = (void *)t->data; + + /* strictly necessary? play safe for now. */ + memset(info->strip_bmap, 0, sizeof(info->strip_bmap)); +} + +static void parse_list(struct xt_tcpoptstrip_target_info *info, char *arg) +{ + unsigned int option; + char *p; + int i; + + while (true) { + p = strchr(arg, ','); + if (p != NULL) + *p = '\0'; + + option = 0; + for (i = 0; tcp_optionmap[i].name != NULL; ++i) + if (strcmp(tcp_optionmap[i].name, arg) == 0) { + option = tcp_optionmap[i].option; + break; + } + + if (option == 0 && string_to_number(arg, 0, 255, &option) == -1) + exit_error(PARAMETER_PROBLEM, + "Bad TCP option value \"%s\"", arg); + + if (option < 2) + exit_error(PARAMETER_PROBLEM, + "Option value may not be 0 or 1"); + + if (tcpoptstrip_test_bit(info->strip_bmap, option)) + exit_error(PARAMETER_PROBLEM, + "Option \"%s\" already specified", arg); + + tcpoptstrip_set_bit(info->strip_bmap, option); + if (p == NULL) + break; + arg = p + 1; + } +} + +static int tcpoptstrip_tg_parse(int c, char **argv, int invert, + unsigned int *flags, const void *entry, + struct xt_entry_target **target) +{ + struct xt_tcpoptstrip_target_info *info = (void *)(*target)->data; + + switch (c) { + case 's': + if (*flags & FLAG_STRIP) + exit_error(PARAMETER_PROBLEM, + "You can specify --strip-options only once"); + parse_list(info, optarg); + *flags |= FLAG_STRIP; + return true; + } + + return false; +} + +static void tcpoptstrip_tg_check(unsigned int flags) +{ + if (flags == 0) + exit_error(PARAMETER_PROBLEM, + "TCPOPTSTRIP: --strip-options parameter required"); +} + +static void +tcpoptstrip_print_list(const struct xt_tcpoptstrip_target_info *info, + bool numeric) +{ + unsigned int i, j; + const char *name; + bool first = true; + + for (i = 0; i < 256; ++i) { + if (!tcpoptstrip_test_bit(info->strip_bmap, i)) + continue; + if (!first) + printf(","); + + first = false; + name = NULL; + if (!numeric) + for (j = 0; tcp_optionmap[j].name != NULL; ++j) + if (tcp_optionmap[j].option == i) + name = tcp_optionmap[j].name; + + if (name != NULL) + printf("%s", name); + else + printf("%u", i); + } +} + +static void +tcpoptstrip_tg_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct xt_tcpoptstrip_target_info *info = + (const void *)target->data; + + printf("TCPOPTSTRIP options "); + tcpoptstrip_print_list(info, numeric); +} + +static void +tcpoptstrip_tg_save(const void *ip, const struct xt_entry_target *target) +{ + const struct xt_tcpoptstrip_target_info *info = + (const void *)target->data; + + printf("--strip-options "); + tcpoptstrip_print_list(info, true); +} + +static struct xtables_target tcpoptstrip_tg_reg = { + .version = IPTABLES_VERSION, + .name = "TCPOPTSTRIP", + .family = AF_INET, + .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), + .help = tcpoptstrip_tg_help, + .init = tcpoptstrip_tg_init, + .parse = tcpoptstrip_tg_parse, + .final_check = tcpoptstrip_tg_check, + .print = tcpoptstrip_tg_print, + .save = tcpoptstrip_tg_save, + .extra_opts = tcpoptstrip_tg_opts, +}; + +static struct xtables_target tcpoptstrip_tg6_reg = { + .version = IPTABLES_VERSION, + .name = "TCPOPTSTRIP", + .family = AF_INET6, + .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), + .help = tcpoptstrip_tg_help, + .init = tcpoptstrip_tg_init, + .parse = tcpoptstrip_tg_parse, + .final_check = tcpoptstrip_tg_check, + .print = tcpoptstrip_tg_print, + .save = tcpoptstrip_tg_save, + .extra_opts = tcpoptstrip_tg_opts, +}; + +void _init(void) +{ + xtables_register_target(&tcpoptstrip_tg_reg); + xtables_register_target(&tcpoptstrip_tg6_reg); +} Index: iptables-modules/extensions/libxt_TCPOPTSTRIP.man =================================================================== --- /dev/null +++ iptables-modules/extensions/libxt_TCPOPTSTRIP.man @@ -0,0 +1,7 @@ +This target will strip TCP options off a TCP packet. (It will actually replace +them by NO-OPs.) As such, you will need to add the \fB-p tcp\fR parameters. +.TP +\fB--strip-options\fR \fIoption\fR[\fB,\fR\fI...\fR] +Strip the given option(s). The options may be specified by TCP option number or +by symbolic name. The list of recognized options can be obtained by calling +iptables with \fB-j TCPOPTSTRIP -h\fR. Index: iptables-modules/include/linux/netfilter/xt_TCPOPTSTRIP.h =================================================================== --- /dev/null +++ iptables-modules/include/linux/netfilter/xt_TCPOPTSTRIP.h @@ -0,0 +1,13 @@ +#ifndef _XT_TCPOPTSTRIP_H +#define _XT_TCPOPTSTRIP_H + +#define tcpoptstrip_set_bit(bmap, idx) \ + (bmap[(idx) >> 5] |= 1U << (idx & 31)) +#define tcpoptstrip_test_bit(bmap, idx) \ + (((1U << (idx & 31)) & bmap[(idx) >> 5]) != 0) + +struct xt_tcpoptstrip_target_info { + u_int32_t strip_bmap[8]; +}; + +#endif /* _XT_TCPOPTSTRIP_H */ - 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