libxt_TCPOPTSTRIP.c revision e88a7c2c7175742b58b6aa03f2b5aba2d80330a1
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 <getopt.h> 8#include <stdbool.h> 9#include <stdio.h> 10#include <string.h> 11#include <stdlib.h> 12#include <xtables.h> 13#include <netinet/tcp.h> 14#include <linux/netfilter/x_tables.h> 15#include <linux/netfilter/xt_TCPOPTSTRIP.h> 16#ifndef TCPOPT_MD5SIG 17# define TCPOPT_MD5SIG 19 18#endif 19 20enum { 21 FLAG_STRIP = 1 << 0, 22}; 23 24struct tcp_optionmap { 25 const char *name, *desc; 26 const unsigned int option; 27}; 28 29static const struct option tcpoptstrip_tg_opts[] = { 30 {.name = "strip-options", .has_arg = true, .val = 's'}, 31 XT_GETOPT_TABLEEND, 32}; 33 34static const struct tcp_optionmap tcp_optionmap[] = { 35 {"wscale", "Window scale", TCPOPT_WINDOW}, 36 {"mss", "Maximum Segment Size", TCPOPT_MAXSEG}, 37 {"sack-permitted", "SACK permitted", TCPOPT_SACK_PERMITTED}, 38 {"sack", "Selective ACK", TCPOPT_SACK}, 39 {"timestamp", "Timestamp", TCPOPT_TIMESTAMP}, 40 {"md5", "MD5 signature", TCPOPT_MD5SIG}, 41 XT_GETOPT_TABLEEND, 42}; 43 44static void tcpoptstrip_tg_help(void) 45{ 46 const struct tcp_optionmap *w; 47 48 printf( 49"TCPOPTSTRIP target options:\n" 50" --strip-options value strip specified TCP options denoted by value\n" 51" (separated by comma) from TCP header\n" 52" Instead of the numeric value, you can also use the following names:\n" 53 ); 54 55 for (w = tcp_optionmap; w->name != NULL; ++w) 56 printf(" %-14s strip \"%s\" option\n", w->name, w->desc); 57} 58 59static void parse_list(struct xt_tcpoptstrip_target_info *info, char *arg) 60{ 61 unsigned int option; 62 char *p; 63 int i; 64 65 while (true) { 66 p = strchr(arg, ','); 67 if (p != NULL) 68 *p = '\0'; 69 70 option = 0; 71 for (i = 0; tcp_optionmap[i].name != NULL; ++i) 72 if (strcmp(tcp_optionmap[i].name, arg) == 0) { 73 option = tcp_optionmap[i].option; 74 break; 75 } 76 77 if (option == 0 && 78 !xtables_strtoui(arg, NULL, &option, 0, UINT8_MAX)) 79 xtables_error(PARAMETER_PROBLEM, 80 "Bad TCP option value \"%s\"", arg); 81 82 if (option < 2) 83 xtables_error(PARAMETER_PROBLEM, 84 "Option value may not be 0 or 1"); 85 86 if (tcpoptstrip_test_bit(info->strip_bmap, option)) 87 xtables_error(PARAMETER_PROBLEM, 88 "Option \"%s\" already specified", arg); 89 90 tcpoptstrip_set_bit(info->strip_bmap, option); 91 if (p == NULL) 92 break; 93 arg = p + 1; 94 } 95} 96 97static int tcpoptstrip_tg_parse(int c, char **argv, int invert, 98 unsigned int *flags, const void *entry, 99 struct xt_entry_target **target) 100{ 101 struct xt_tcpoptstrip_target_info *info = (void *)(*target)->data; 102 103 switch (c) { 104 case 's': 105 if (*flags & FLAG_STRIP) 106 xtables_error(PARAMETER_PROBLEM, 107 "You can specify --strip-options only once"); 108 parse_list(info, optarg); 109 *flags |= FLAG_STRIP; 110 return true; 111 } 112 113 return false; 114} 115 116static void tcpoptstrip_tg_check(unsigned int flags) 117{ 118 if (flags == 0) 119 xtables_error(PARAMETER_PROBLEM, 120 "TCPOPTSTRIP: --strip-options parameter required"); 121} 122 123static void 124tcpoptstrip_print_list(const struct xt_tcpoptstrip_target_info *info, 125 bool numeric) 126{ 127 unsigned int i, j; 128 const char *name; 129 bool first = true; 130 131 for (i = 0; i < 256; ++i) { 132 if (!tcpoptstrip_test_bit(info->strip_bmap, i)) 133 continue; 134 if (!first) 135 printf(","); 136 137 first = false; 138 name = NULL; 139 if (!numeric) 140 for (j = 0; tcp_optionmap[j].name != NULL; ++j) 141 if (tcp_optionmap[j].option == i) 142 name = tcp_optionmap[j].name; 143 144 if (name != NULL) 145 printf("%s", name); 146 else 147 printf("%u", i); 148 } 149} 150 151static void 152tcpoptstrip_tg_print(const void *ip, const struct xt_entry_target *target, 153 int numeric) 154{ 155 const struct xt_tcpoptstrip_target_info *info = 156 (const void *)target->data; 157 158 printf(" TCPOPTSTRIP options "); 159 tcpoptstrip_print_list(info, numeric); 160} 161 162static void 163tcpoptstrip_tg_save(const void *ip, const struct xt_entry_target *target) 164{ 165 const struct xt_tcpoptstrip_target_info *info = 166 (const void *)target->data; 167 168 printf(" --strip-options "); 169 tcpoptstrip_print_list(info, true); 170} 171 172static struct xtables_target tcpoptstrip_tg_reg = { 173 .version = XTABLES_VERSION, 174 .name = "TCPOPTSTRIP", 175 .family = NFPROTO_UNSPEC, 176 .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), 177 .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), 178 .help = tcpoptstrip_tg_help, 179 .parse = tcpoptstrip_tg_parse, 180 .final_check = tcpoptstrip_tg_check, 181 .print = tcpoptstrip_tg_print, 182 .save = tcpoptstrip_tg_save, 183 .extra_opts = tcpoptstrip_tg_opts, 184}; 185 186void _init(void) 187{ 188 xtables_register_target(&tcpoptstrip_tg_reg); 189} 190