1/* 2 * Shared library add-on to iptables to add TCPOPTSTRIP target support. 3 * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org> 4 * Copyright �� CC Computer Consultants GmbH, 2007 5 * Jan Engelhardt <jengelh@computergmbh.de> 6 */ 7#include <stdio.h> 8#include <string.h> 9#include <xtables.h> 10#include <netinet/tcp.h> 11#include <linux/netfilter/xt_TCPOPTSTRIP.h> 12#ifndef TCPOPT_MD5SIG 13# define TCPOPT_MD5SIG 19 14#endif 15 16enum { 17 O_STRIP_OPTION = 0, 18}; 19 20struct tcp_optionmap { 21 const char *name, *desc; 22 const unsigned int option; 23}; 24 25static const struct xt_option_entry tcpoptstrip_tg_opts[] = { 26 {.name = "strip-options", .id = O_STRIP_OPTION, .type = XTTYPE_STRING}, 27 XTOPT_TABLEEND, 28}; 29 30static const struct tcp_optionmap tcp_optionmap[] = { 31 {"wscale", "Window scale", TCPOPT_WINDOW}, 32 {"mss", "Maximum Segment Size", TCPOPT_MAXSEG}, 33 {"sack-permitted", "SACK permitted", TCPOPT_SACK_PERMITTED}, 34 {"sack", "Selective ACK", TCPOPT_SACK}, 35 {"timestamp", "Timestamp", TCPOPT_TIMESTAMP}, 36 {"md5", "MD5 signature", TCPOPT_MD5SIG}, 37 {NULL}, 38}; 39 40static void tcpoptstrip_tg_help(void) 41{ 42 const struct tcp_optionmap *w; 43 44 printf( 45"TCPOPTSTRIP target options:\n" 46" --strip-options value strip specified TCP options denoted by value\n" 47" (separated by comma) from TCP header\n" 48" Instead of the numeric value, you can also use the following names:\n" 49 ); 50 51 for (w = tcp_optionmap; w->name != NULL; ++w) 52 printf(" %-14s strip \"%s\" option\n", w->name, w->desc); 53} 54 55static void 56parse_list(struct xt_tcpoptstrip_target_info *info, const char *arg) 57{ 58 unsigned int option; 59 char *p; 60 int i; 61 62 while (true) { 63 p = strchr(arg, ','); 64 if (p != NULL) 65 *p = '\0'; 66 67 option = 0; 68 for (i = 0; tcp_optionmap[i].name != NULL; ++i) 69 if (strcmp(tcp_optionmap[i].name, arg) == 0) { 70 option = tcp_optionmap[i].option; 71 break; 72 } 73 74 if (option == 0 && 75 !xtables_strtoui(arg, NULL, &option, 0, UINT8_MAX)) 76 xtables_error(PARAMETER_PROBLEM, 77 "Bad TCP option value \"%s\"", arg); 78 79 if (option < 2) 80 xtables_error(PARAMETER_PROBLEM, 81 "Option value may not be 0 or 1"); 82 83 if (tcpoptstrip_test_bit(info->strip_bmap, option)) 84 xtables_error(PARAMETER_PROBLEM, 85 "Option \"%s\" already specified", arg); 86 87 tcpoptstrip_set_bit(info->strip_bmap, option); 88 if (p == NULL) 89 break; 90 arg = p + 1; 91 } 92} 93 94static void tcpoptstrip_tg_parse(struct xt_option_call *cb) 95{ 96 struct xt_tcpoptstrip_target_info *info = cb->data; 97 98 xtables_option_parse(cb); 99 parse_list(info, cb->arg); 100} 101 102static void 103tcpoptstrip_print_list(const struct xt_tcpoptstrip_target_info *info, 104 bool numeric) 105{ 106 unsigned int i, j; 107 const char *name; 108 bool first = true; 109 110 for (i = 0; i < 256; ++i) { 111 if (!tcpoptstrip_test_bit(info->strip_bmap, i)) 112 continue; 113 if (!first) 114 printf(","); 115 116 first = false; 117 name = NULL; 118 if (!numeric) 119 for (j = 0; tcp_optionmap[j].name != NULL; ++j) 120 if (tcp_optionmap[j].option == i) 121 name = tcp_optionmap[j].name; 122 123 if (name != NULL) 124 printf("%s", name); 125 else 126 printf("%u", i); 127 } 128} 129 130static void 131tcpoptstrip_tg_print(const void *ip, const struct xt_entry_target *target, 132 int numeric) 133{ 134 const struct xt_tcpoptstrip_target_info *info = 135 (const void *)target->data; 136 137 printf(" TCPOPTSTRIP options "); 138 tcpoptstrip_print_list(info, numeric); 139} 140 141static void 142tcpoptstrip_tg_save(const void *ip, const struct xt_entry_target *target) 143{ 144 const struct xt_tcpoptstrip_target_info *info = 145 (const void *)target->data; 146 147 printf(" --strip-options "); 148 tcpoptstrip_print_list(info, true); 149} 150 151static struct xtables_target tcpoptstrip_tg_reg = { 152 .version = XTABLES_VERSION, 153 .name = "TCPOPTSTRIP", 154 .family = NFPROTO_UNSPEC, 155 .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), 156 .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), 157 .help = tcpoptstrip_tg_help, 158 .print = tcpoptstrip_tg_print, 159 .save = tcpoptstrip_tg_save, 160 .x6_parse = tcpoptstrip_tg_parse, 161 .x6_options = tcpoptstrip_tg_opts, 162}; 163 164void _init(void) 165{ 166 xtables_register_target(&tcpoptstrip_tg_reg); 167} 168