summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Schnelle <svens@bitebene.org>2008-01-20 13:45:16 +0000
committerPatrick McHardy <kaber@trash.net>2008-01-20 13:45:16 +0000
commitaef4c1e7275633e4650d16440faaf4cb7163ac0e (patch)
tree9ef00f3a2aec50521ce3a284ea25576786119e81
parentfc11b0b24ca2f808adcca3fd6b1aad581538171d (diff)
libxt_TCPOPTSTRIP
Import libxt_TCPOPTSTRIP into iptables. Signed-off-by: Sven Schnelle <svens@bitebene.org> Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
-rw-r--r--extensions/libxt_TCPOPTSTRIP.c212
-rw-r--r--extensions/libxt_TCPOPTSTRIP.man7
-rw-r--r--include/linux/netfilter/xt_TCPOPTSTRIP.h13
3 files changed, 232 insertions, 0 deletions
diff --git a/extensions/libxt_TCPOPTSTRIP.c b/extensions/libxt_TCPOPTSTRIP.c
new file mode 100644
index 00000000..c3d558dc
--- /dev/null
+++ b/extensions/libxt_TCPOPTSTRIP.c
@@ -0,0 +1,212 @@
+/*
+ * Shared library add-on to iptables to add TCPOPTSTRIP target support.
+ * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org>
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+#ifndef TCPOPT_MD5SIG
+# define TCPOPT_MD5SIG 19
+#endif
+
+enum {
+ FLAG_STRIP = 1 << 0,
+};
+
+struct tcp_optionmap {
+ const char *name, *desc;
+ const int option;
+};
+
+static const struct option tcpoptstrip_tg_opts[] = {
+ {.name = "strip-options", .has_arg = true, .val = 's'},
+ {},
+};
+
+static const struct tcp_optionmap tcp_optionmap[] = {
+ {"wscale", "Window scale", TCPOPT_WINDOW},
+ {"mss", "Maximum Segment Size", TCPOPT_MAXSEG},
+ {"sack-permitted", "SACK permitted", TCPOPT_SACK_PERMITTED},
+ {"sack", "Selective ACK", TCPOPT_SACK},
+ {"timestamp", "Timestamp", TCPOPT_TIMESTAMP},
+ {"md5", "MD5 signature", TCPOPT_MD5SIG},
+ {NULL},
+};
+
+static void tcpoptstrip_tg_help(void)
+{
+ const struct tcp_optionmap *w;
+
+ printf(
+"TCPOPTSTRIP target options:\n"
+" --strip-options value strip specified TCP options denoted by value\n"
+" (separated by comma) from TCP header\n"
+" Instead of the numeric value, you can also use the following names:\n"
+ );
+
+ for (w = tcp_optionmap; w->name != NULL; ++w)
+ printf(" %-14s strip \"%s\" option\n", w->name, w->desc);
+}
+
+static void tcpoptstrip_tg_init(struct xt_entry_target *t)
+{
+ struct xt_tcpoptstrip_target_info *info = (void *)t->data;
+
+ /* strictly necessary? play safe for now. */
+ memset(info->strip_bmap, 0, sizeof(info->strip_bmap));
+}
+
+static void parse_list(struct xt_tcpoptstrip_target_info *info, char *arg)
+{
+ unsigned int option;
+ char *p;
+ int i;
+
+ while (true) {
+ p = strchr(arg, ',');
+ if (p != NULL)
+ *p = '\0';
+
+ option = 0;
+ for (i = 0; tcp_optionmap[i].name != NULL; ++i)
+ if (strcmp(tcp_optionmap[i].name, arg) == 0) {
+ option = tcp_optionmap[i].option;
+ break;
+ }
+
+ if (option == 0 && string_to_number(arg, 0, 255, &option) == -1)
+ exit_error(PARAMETER_PROBLEM,
+ "Bad TCP option value \"%s\"", arg);
+
+ if (option < 2)
+ exit_error(PARAMETER_PROBLEM,
+ "Option value may not be 0 or 1");
+
+ if (tcpoptstrip_test_bit(info->strip_bmap, option))
+ exit_error(PARAMETER_PROBLEM,
+ "Option \"%s\" already specified", arg);
+
+ tcpoptstrip_set_bit(info->strip_bmap, option);
+ if (p == NULL)
+ break;
+ arg = p + 1;
+ }
+}
+
+static int tcpoptstrip_tg_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ struct xt_tcpoptstrip_target_info *info = (void *)(*target)->data;
+
+ switch (c) {
+ case 's':
+ if (*flags & FLAG_STRIP)
+ exit_error(PARAMETER_PROBLEM,
+ "You can specify --strip-options only once");
+ parse_list(info, optarg);
+ *flags |= FLAG_STRIP;
+ return true;
+ }
+
+ return false;
+}
+
+static void tcpoptstrip_tg_check(unsigned int flags)
+{
+ if (flags == 0)
+ exit_error(PARAMETER_PROBLEM,
+ "TCPOPTSTRIP: --strip-options parameter required");
+}
+
+static void
+tcpoptstrip_print_list(const struct xt_tcpoptstrip_target_info *info,
+ bool numeric)
+{
+ unsigned int i, j;
+ const char *name;
+ bool first = true;
+
+ for (i = 0; i < 256; ++i) {
+ if (!tcpoptstrip_test_bit(info->strip_bmap, i))
+ continue;
+ if (!first)
+ printf(",");
+
+ first = false;
+ name = NULL;
+ if (!numeric)
+ for (j = 0; tcp_optionmap[j].name != NULL; ++j)
+ if (tcp_optionmap[j].option == i)
+ name = tcp_optionmap[j].name;
+
+ if (name != NULL)
+ printf("%s", name);
+ else
+ printf("%u", i);
+ }
+}
+
+static void
+tcpoptstrip_tg_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_tcpoptstrip_target_info *info =
+ (const void *)target->data;
+
+ printf("TCPOPTSTRIP options ");
+ tcpoptstrip_print_list(info, numeric);
+}
+
+static void
+tcpoptstrip_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_tcpoptstrip_target_info *info =
+ (const void *)target->data;
+
+ printf("--strip-options ");
+ tcpoptstrip_print_list(info, true);
+}
+
+static struct xtables_target tcpoptstrip_tg_reg = {
+ .version = IPTABLES_VERSION,
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)),
+ .help = tcpoptstrip_tg_help,
+ .init = tcpoptstrip_tg_init,
+ .parse = tcpoptstrip_tg_parse,
+ .final_check = tcpoptstrip_tg_check,
+ .print = tcpoptstrip_tg_print,
+ .save = tcpoptstrip_tg_save,
+ .extra_opts = tcpoptstrip_tg_opts,
+};
+
+static struct xtables_target tcpoptstrip_tg6_reg = {
+ .version = IPTABLES_VERSION,
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)),
+ .help = tcpoptstrip_tg_help,
+ .init = tcpoptstrip_tg_init,
+ .parse = tcpoptstrip_tg_parse,
+ .final_check = tcpoptstrip_tg_check,
+ .print = tcpoptstrip_tg_print,
+ .save = tcpoptstrip_tg_save,
+ .extra_opts = tcpoptstrip_tg_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&tcpoptstrip_tg_reg);
+ xtables_register_target(&tcpoptstrip_tg6_reg);
+}
diff --git a/extensions/libxt_TCPOPTSTRIP.man b/extensions/libxt_TCPOPTSTRIP.man
new file mode 100644
index 00000000..0a8bd205
--- /dev/null
+++ b/extensions/libxt_TCPOPTSTRIP.man
@@ -0,0 +1,7 @@
+This target will strip TCP options off a TCP packet. (It will actually replace
+them by NO-OPs.) As such, you will need to add the \fB-p tcp\fR parameters.
+.TP
+\fB--strip-options\fR \fIoption\fR[\fB,\fR\fI...\fR]
+Strip the given option(s). The options may be specified by TCP option number or
+by symbolic name. The list of recognized options can be obtained by calling
+iptables with \fB-j TCPOPTSTRIP -h\fR.
diff --git a/include/linux/netfilter/xt_TCPOPTSTRIP.h b/include/linux/netfilter/xt_TCPOPTSTRIP.h
new file mode 100644
index 00000000..2db54321
--- /dev/null
+++ b/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -0,0 +1,13 @@
+#ifndef _XT_TCPOPTSTRIP_H
+#define _XT_TCPOPTSTRIP_H
+
+#define tcpoptstrip_set_bit(bmap, idx) \
+ (bmap[(idx) >> 5] |= 1U << (idx & 31))
+#define tcpoptstrip_test_bit(bmap, idx) \
+ (((1U << (idx & 31)) & bmap[(idx) >> 5]) != 0)
+
+struct xt_tcpoptstrip_target_info {
+ u_int32_t strip_bmap[8];
+};
+
+#endif /* _XT_TCPOPTSTRIP_H */