Home | History | Annotate | Download | only in extensions
      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