blob: 6897857317b6cbe2473fa336b25a0caf297c69dc [file] [log] [blame]
Sven Schnelleaef4c1e2008-01-20 13:45:16 +00001/*
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 */
Sven Schnelleaef4c1e2008-01-20 13:45:16 +00007#include <stdio.h>
8#include <string.h>
Sven Schnelleaef4c1e2008-01-20 13:45:16 +00009#include <xtables.h>
Jan Engelhardtef18e812008-08-04 12:47:48 +020010#include <netinet/tcp.h>
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000011#include <linux/netfilter/xt_TCPOPTSTRIP.h>
12#ifndef TCPOPT_MD5SIG
13# define TCPOPT_MD5SIG 19
14#endif
15
16enum {
Jan Engelhardt693420f2011-03-02 22:57:52 +010017 O_STRIP_OPTION = 0,
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000018};
19
20struct tcp_optionmap {
21 const char *name, *desc;
Jan Engelhardt7a236f42008-03-03 12:30:41 +010022 const unsigned int option;
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000023};
24
Jan Engelhardt693420f2011-03-02 22:57:52 +010025static const struct xt_option_entry tcpoptstrip_tg_opts[] = {
26 {.name = "strip-options", .id = O_STRIP_OPTION, .type = XTTYPE_STRING},
27 XTOPT_TABLEEND,
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000028};
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},
Jan Engelhardt104fb312011-05-07 04:01:25 +020037 {NULL},
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000038};
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
Jan Engelhardt693420f2011-03-02 22:57:52 +010055static void
56parse_list(struct xt_tcpoptstrip_target_info *info, const char *arg)
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000057{
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
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010074 if (option == 0 &&
75 !xtables_strtoui(arg, NULL, &option, 0, UINT8_MAX))
Jan Engelhardt1829ed42009-02-21 03:29:44 +010076 xtables_error(PARAMETER_PROBLEM,
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000077 "Bad TCP option value \"%s\"", arg);
78
79 if (option < 2)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010080 xtables_error(PARAMETER_PROBLEM,
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000081 "Option value may not be 0 or 1");
82
83 if (tcpoptstrip_test_bit(info->strip_bmap, option))
Jan Engelhardt1829ed42009-02-21 03:29:44 +010084 xtables_error(PARAMETER_PROBLEM,
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000085 "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
Jan Engelhardt693420f2011-03-02 22:57:52 +010094static void tcpoptstrip_tg_parse(struct xt_option_call *cb)
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000095{
Jan Engelhardt693420f2011-03-02 22:57:52 +010096 struct xt_tcpoptstrip_target_info *info = cb->data;
Sven Schnelleaef4c1e2008-01-20 13:45:16 +000097
Jan Engelhardt693420f2011-03-02 22:57:52 +010098 xtables_option_parse(cb);
99 parse_list(info, cb->arg);
Sven Schnelleaef4c1e2008-01-20 13:45:16 +0000100}
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
Jan Engelhardt73866352010-12-18 02:04:59 +0100137 printf(" TCPOPTSTRIP options ");
Sven Schnelleaef4c1e2008-01-20 13:45:16 +0000138 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
Jan Engelhardt73866352010-12-18 02:04:59 +0100147 printf(" --strip-options ");
Sven Schnelleaef4c1e2008-01-20 13:45:16 +0000148 tcpoptstrip_print_list(info, true);
149}
150
151static struct xtables_target tcpoptstrip_tg_reg = {
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200152 .version = XTABLES_VERSION,
Sven Schnelleaef4c1e2008-01-20 13:45:16 +0000153 .name = "TCPOPTSTRIP",
Jan Engelhardtc5e85732009-06-12 20:55:44 +0200154 .family = NFPROTO_UNSPEC,
Sven Schnelleaef4c1e2008-01-20 13:45:16 +0000155 .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)),
156 .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)),
157 .help = tcpoptstrip_tg_help,
Sven Schnelleaef4c1e2008-01-20 13:45:16 +0000158 .print = tcpoptstrip_tg_print,
159 .save = tcpoptstrip_tg_save,
Jan Engelhardt693420f2011-03-02 22:57:52 +0100160 .x6_parse = tcpoptstrip_tg_parse,
161 .x6_options = tcpoptstrip_tg_opts,
Sven Schnelleaef4c1e2008-01-20 13:45:16 +0000162};
163
164void _init(void)
165{
166 xtables_register_target(&tcpoptstrip_tg_reg);
Sven Schnelleaef4c1e2008-01-20 13:45:16 +0000167}