Fix up to work with IVI kernel-headers
[profile/ivi/iptables.git] / extensions / libxt_TCPOPTSTRIP.c
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
20 enum {
21         FLAG_STRIP = 1 << 0,
22 };
23
24 struct tcp_optionmap {
25         const char *name, *desc;
26         const unsigned int option;
27 };
28
29 static const struct option tcpoptstrip_tg_opts[] = {
30         {.name = "strip-options", .has_arg = true, .val = 's'},
31         { .name = NULL }
32 };
33
34 static 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         { .name = NULL }
42 };
43
44 static 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
59 static 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
67 static 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
105 static 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
124 static 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
131 static void
132 tcpoptstrip_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
159 static void
160 tcpoptstrip_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
170 static void
171 tcpoptstrip_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
180 static 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
195 void _init(void)
196 {
197         xtables_register_target(&tcpoptstrip_tg_reg);
198 }