| /* |
| * Shared library add-on to iptables to add TCPOPTSTRIP target support. |
| * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org> |
| * Copyright © CC Computer Consultants GmbH, 2007 |
| * Jan Engelhardt <jengelh@computergmbh.de> |
| */ |
| #include <stdio.h> |
| #include <string.h> |
| #include <xtables.h> |
| #include <netinet/tcp.h> |
| #include <linux/netfilter/xt_TCPOPTSTRIP.h> |
| #ifndef TCPOPT_MD5SIG |
| # define TCPOPT_MD5SIG 19 |
| #endif |
| #ifndef TCPOPT_MAXSEG |
| # define TCPOPT_MAXSEG 2 |
| #endif |
| #ifndef TCPOPT_WINDOW |
| # define TCPOPT_WINDOW 3 |
| #endif |
| #ifndef TCPOPT_SACK_PERMITTED |
| # define TCPOPT_SACK_PERMITTED 4 |
| #endif |
| #ifndef TCPOPT_SACK |
| # define TCPOPT_SACK 5 |
| #endif |
| #ifndef TCPOPT_TIMESTAMP |
| # define TCPOPT_TIMESTAMP 8 |
| #endif |
| |
| enum { |
| O_STRIP_OPTION = 0, |
| }; |
| |
| struct tcp_optionmap { |
| const char *name, *desc; |
| const unsigned int option; |
| }; |
| |
| static const struct xt_option_entry tcpoptstrip_tg_opts[] = { |
| {.name = "strip-options", .id = O_STRIP_OPTION, .type = XTTYPE_STRING}, |
| XTOPT_TABLEEND, |
| }; |
| |
| 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 |
| parse_list(struct xt_tcpoptstrip_target_info *info, const 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 && |
| !xtables_strtoui(arg, NULL, &option, 0, UINT8_MAX)) |
| xtables_error(PARAMETER_PROBLEM, |
| "Bad TCP option value \"%s\"", arg); |
| |
| if (option < 2) |
| xtables_error(PARAMETER_PROBLEM, |
| "Option value may not be 0 or 1"); |
| |
| if (tcpoptstrip_test_bit(info->strip_bmap, option)) |
| xtables_error(PARAMETER_PROBLEM, |
| "Option \"%s\" already specified", arg); |
| |
| tcpoptstrip_set_bit(info->strip_bmap, option); |
| if (p == NULL) |
| break; |
| arg = p + 1; |
| } |
| } |
| |
| static void tcpoptstrip_tg_parse(struct xt_option_call *cb) |
| { |
| struct xt_tcpoptstrip_target_info *info = cb->data; |
| |
| xtables_option_parse(cb); |
| parse_list(info, cb->arg); |
| } |
| |
| 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 = XTABLES_VERSION, |
| .name = "TCPOPTSTRIP", |
| .family = NFPROTO_UNSPEC, |
| .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), |
| .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), |
| .help = tcpoptstrip_tg_help, |
| .print = tcpoptstrip_tg_print, |
| .save = tcpoptstrip_tg_save, |
| .x6_parse = tcpoptstrip_tg_parse, |
| .x6_options = tcpoptstrip_tg_opts, |
| }; |
| |
| void _init(void) |
| { |
| xtables_register_target(&tcpoptstrip_tg_reg); |
| } |