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