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 16 enum { 17 O_STRIP_OPTION = 0, 18 }; 19 20 struct tcp_optionmap { 21 const char *name, *desc; 22 const unsigned int option; 23 }; 24 25 static const struct xt_option_entry tcpoptstrip_tg_opts[] = { 26 {.name = "strip-options", .id = O_STRIP_OPTION, .type = XTTYPE_STRING}, 27 XTOPT_TABLEEND, 28 }; 29 30 static 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 40 static 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 55 static void 56 parse_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 94 static 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 102 static void 103 tcpoptstrip_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 130 static void 131 tcpoptstrip_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 141 static void 142 tcpoptstrip_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 151 static 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 164 void _init(void) 165 { 166 xtables_register_target(&tcpoptstrip_tg_reg); 167 } 168