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