libxt_TCPOPTSTRIP.c revision 32b8e61e4e5bd405d9ad07bf9468498dfbb19f9e
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 tcpoptstrip_tg_init(struct xt_entry_target *t) 60{ 61 struct xt_tcpoptstrip_target_info *info = (void *)t->data; 62 63 /* strictly necessary? play safe for now. */ 64 memset(info->strip_bmap, 0, sizeof(info->strip_bmap)); 65} 66 67static void parse_list(struct xt_tcpoptstrip_target_info *info, char *arg) 68{ 69 unsigned int option; 70 char *p; 71 int i; 72 73 while (true) { 74 p = strchr(arg, ','); 75 if (p != NULL) 76 *p = '\0'; 77 78 option = 0; 79 for (i = 0; tcp_optionmap[i].name != NULL; ++i) 80 if (strcmp(tcp_optionmap[i].name, arg) == 0) { 81 option = tcp_optionmap[i].option; 82 break; 83 } 84 85 if (option == 0 && 86 !xtables_strtoui(arg, NULL, &option, 0, UINT8_MAX)) 87 xtables_error(PARAMETER_PROBLEM, 88 "Bad TCP option value \"%s\"", arg); 89 90 if (option < 2) 91 xtables_error(PARAMETER_PROBLEM, 92 "Option value may not be 0 or 1"); 93 94 if (tcpoptstrip_test_bit(info->strip_bmap, option)) 95 xtables_error(PARAMETER_PROBLEM, 96 "Option \"%s\" already specified", arg); 97 98 tcpoptstrip_set_bit(info->strip_bmap, option); 99 if (p == NULL) 100 break; 101 arg = p + 1; 102 } 103} 104 105static int tcpoptstrip_tg_parse(int c, char **argv, int invert, 106 unsigned int *flags, const void *entry, 107 struct xt_entry_target **target) 108{ 109 struct xt_tcpoptstrip_target_info *info = (void *)(*target)->data; 110 111 switch (c) { 112 case 's': 113 if (*flags & FLAG_STRIP) 114 xtables_error(PARAMETER_PROBLEM, 115 "You can specify --strip-options only once"); 116 parse_list(info, optarg); 117 *flags |= FLAG_STRIP; 118 return true; 119 } 120 121 return false; 122} 123 124static void tcpoptstrip_tg_check(unsigned int flags) 125{ 126 if (flags == 0) 127 xtables_error(PARAMETER_PROBLEM, 128 "TCPOPTSTRIP: --strip-options parameter required"); 129} 130 131static void 132tcpoptstrip_print_list(const struct xt_tcpoptstrip_target_info *info, 133 bool numeric) 134{ 135 unsigned int i, j; 136 const char *name; 137 bool first = true; 138 139 for (i = 0; i < 256; ++i) { 140 if (!tcpoptstrip_test_bit(info->strip_bmap, i)) 141 continue; 142 if (!first) 143 printf(","); 144 145 first = false; 146 name = NULL; 147 if (!numeric) 148 for (j = 0; tcp_optionmap[j].name != NULL; ++j) 149 if (tcp_optionmap[j].option == i) 150 name = tcp_optionmap[j].name; 151 152 if (name != NULL) 153 printf("%s", name); 154 else 155 printf("%u", i); 156 } 157} 158 159static void 160tcpoptstrip_tg_print(const void *ip, const struct xt_entry_target *target, 161 int numeric) 162{ 163 const struct xt_tcpoptstrip_target_info *info = 164 (const void *)target->data; 165 166 printf("TCPOPTSTRIP options "); 167 tcpoptstrip_print_list(info, numeric); 168} 169 170static void 171tcpoptstrip_tg_save(const void *ip, const struct xt_entry_target *target) 172{ 173 const struct xt_tcpoptstrip_target_info *info = 174 (const void *)target->data; 175 176 printf("--strip-options "); 177 tcpoptstrip_print_list(info, true); 178} 179 180static struct xtables_target tcpoptstrip_tg_reg = { 181 .version = XTABLES_VERSION, 182 .name = "TCPOPTSTRIP", 183 .family = NFPROTO_UNSPEC, 184 .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), 185 .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)), 186 .help = tcpoptstrip_tg_help, 187 .init = tcpoptstrip_tg_init, 188 .parse = tcpoptstrip_tg_parse, 189 .final_check = tcpoptstrip_tg_check, 190 .print = tcpoptstrip_tg_print, 191 .save = tcpoptstrip_tg_save, 192 .extra_opts = tcpoptstrip_tg_opts, 193}; 194 195void _init(void) 196{ 197 xtables_register_target(&tcpoptstrip_tg_reg); 198} 199