Blame extensions/libxt_TCPOPTSTRIP.c

Packit 7b22a4
/*
Packit 7b22a4
 * Shared library add-on to iptables to add TCPOPTSTRIP target support.
Packit 7b22a4
 * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org>
Packit 7b22a4
 * Copyright © CC Computer Consultants GmbH, 2007
Packit 7b22a4
 * Jan Engelhardt <jengelh@computergmbh.de>
Packit 7b22a4
 */
Packit 7b22a4
#include <stdio.h>
Packit 7b22a4
#include <string.h>
Packit 7b22a4
#include <xtables.h>
Packit 7b22a4
#include <netinet/tcp.h>
Packit 7b22a4
#include <linux/netfilter/xt_TCPOPTSTRIP.h>
Packit 7b22a4
#ifndef TCPOPT_MD5SIG
Packit 7b22a4
#	define TCPOPT_MD5SIG 19
Packit 7b22a4
#endif
Packit 7b22a4
#ifndef TCPOPT_MAXSEG
Packit 7b22a4
#     define TCPOPT_MAXSEG 2
Packit 7b22a4
#endif
Packit 7b22a4
#ifndef TCPOPT_WINDOW
Packit 7b22a4
#     define TCPOPT_WINDOW 3
Packit 7b22a4
#endif
Packit 7b22a4
#ifndef TCPOPT_SACK_PERMITTED
Packit 7b22a4
#     define TCPOPT_SACK_PERMITTED 4
Packit 7b22a4
#endif
Packit 7b22a4
#ifndef TCPOPT_SACK
Packit 7b22a4
#     define TCPOPT_SACK 5
Packit 7b22a4
#endif
Packit 7b22a4
#ifndef TCPOPT_TIMESTAMP
Packit 7b22a4
#     define TCPOPT_TIMESTAMP 8
Packit 7b22a4
#endif
Packit 7b22a4
Packit 7b22a4
enum {
Packit 7b22a4
	O_STRIP_OPTION = 0,
Packit 7b22a4
};
Packit 7b22a4
Packit 7b22a4
struct tcp_optionmap {
Packit 7b22a4
	const char *name, *desc;
Packit 7b22a4
	const unsigned int option;
Packit 7b22a4
};
Packit 7b22a4
Packit 7b22a4
static const struct xt_option_entry tcpoptstrip_tg_opts[] = {
Packit 7b22a4
	{.name = "strip-options", .id = O_STRIP_OPTION, .type = XTTYPE_STRING},
Packit 7b22a4
	XTOPT_TABLEEND,
Packit 7b22a4
};
Packit 7b22a4
Packit 7b22a4
static const struct tcp_optionmap tcp_optionmap[] = {
Packit 7b22a4
	{"wscale",         "Window scale",         TCPOPT_WINDOW},
Packit 7b22a4
	{"mss",            "Maximum Segment Size", TCPOPT_MAXSEG},
Packit 7b22a4
	{"sack-permitted", "SACK permitted",       TCPOPT_SACK_PERMITTED},
Packit 7b22a4
	{"sack",           "Selective ACK",        TCPOPT_SACK},
Packit 7b22a4
	{"timestamp",      "Timestamp",            TCPOPT_TIMESTAMP},
Packit 7b22a4
	{"md5",            "MD5 signature",        TCPOPT_MD5SIG},
Packit 7b22a4
	{NULL},
Packit 7b22a4
};
Packit 7b22a4
Packit 7b22a4
static void tcpoptstrip_tg_help(void)
Packit 7b22a4
{
Packit 7b22a4
	const struct tcp_optionmap *w;
Packit 7b22a4
Packit 7b22a4
	printf(
Packit 7b22a4
"TCPOPTSTRIP target options:\n"
Packit 7b22a4
"  --strip-options value     strip specified TCP options denoted by value\n"
Packit 7b22a4
"                            (separated by comma) from TCP header\n"
Packit 7b22a4
"  Instead of the numeric value, you can also use the following names:\n"
Packit 7b22a4
	);
Packit 7b22a4
Packit 7b22a4
	for (w = tcp_optionmap; w->name != NULL; ++w)
Packit 7b22a4
		printf("    %-14s    strip \"%s\" option\n", w->name, w->desc);
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
parse_list(struct xt_tcpoptstrip_target_info *info, const char *arg)
Packit 7b22a4
{
Packit 7b22a4
	unsigned int option;
Packit 7b22a4
	char *p;
Packit 7b22a4
	int i;
Packit 7b22a4
Packit 7b22a4
	while (true) {
Packit 7b22a4
		p = strchr(arg, ',');
Packit 7b22a4
		if (p != NULL)
Packit 7b22a4
			*p = '\0';
Packit 7b22a4
Packit 7b22a4
		option = 0;
Packit 7b22a4
		for (i = 0; tcp_optionmap[i].name != NULL; ++i)
Packit 7b22a4
			if (strcmp(tcp_optionmap[i].name, arg) == 0) {
Packit 7b22a4
				option = tcp_optionmap[i].option;
Packit 7b22a4
				break;
Packit 7b22a4
			}
Packit 7b22a4
Packit 7b22a4
		if (option == 0 &&
Packit 7b22a4
		    !xtables_strtoui(arg, NULL, &option, 0, UINT8_MAX))
Packit 7b22a4
			xtables_error(PARAMETER_PROBLEM,
Packit 7b22a4
			           "Bad TCP option value \"%s\"", arg);
Packit 7b22a4
Packit 7b22a4
		if (option < 2)
Packit 7b22a4
			xtables_error(PARAMETER_PROBLEM,
Packit 7b22a4
			           "Option value may not be 0 or 1");
Packit 7b22a4
Packit 7b22a4
		if (tcpoptstrip_test_bit(info->strip_bmap, option))
Packit 7b22a4
			xtables_error(PARAMETER_PROBLEM,
Packit 7b22a4
			           "Option \"%s\" already specified", arg);
Packit 7b22a4
Packit 7b22a4
		tcpoptstrip_set_bit(info->strip_bmap, option);
Packit 7b22a4
		if (p == NULL)
Packit 7b22a4
			break;
Packit 7b22a4
		arg = p + 1;
Packit 7b22a4
	}
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void tcpoptstrip_tg_parse(struct xt_option_call *cb)
Packit 7b22a4
{
Packit 7b22a4
	struct xt_tcpoptstrip_target_info *info = cb->data;
Packit 7b22a4
Packit 7b22a4
	xtables_option_parse(cb);
Packit 7b22a4
	parse_list(info, cb->arg);
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
tcpoptstrip_print_list(const struct xt_tcpoptstrip_target_info *info,
Packit 7b22a4
                       bool numeric)
Packit 7b22a4
{
Packit 7b22a4
	unsigned int i, j;
Packit 7b22a4
	const char *name;
Packit 7b22a4
	bool first = true;
Packit 7b22a4
Packit 7b22a4
	for (i = 0; i < 256; ++i) {
Packit 7b22a4
		if (!tcpoptstrip_test_bit(info->strip_bmap, i))
Packit 7b22a4
			continue;
Packit 7b22a4
		if (!first)
Packit 7b22a4
			printf(",");
Packit 7b22a4
Packit 7b22a4
		first = false;
Packit 7b22a4
		name  = NULL;
Packit 7b22a4
		if (!numeric)
Packit 7b22a4
			for (j = 0; tcp_optionmap[j].name != NULL; ++j)
Packit 7b22a4
				if (tcp_optionmap[j].option == i)
Packit 7b22a4
					name = tcp_optionmap[j].name;
Packit 7b22a4
Packit 7b22a4
		if (name != NULL)
Packit 7b22a4
			printf("%s", name);
Packit 7b22a4
		else
Packit 7b22a4
			printf("%u", i);
Packit 7b22a4
	}
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
tcpoptstrip_tg_print(const void *ip, const struct xt_entry_target *target,
Packit 7b22a4
                     int numeric)
Packit 7b22a4
{
Packit 7b22a4
	const struct xt_tcpoptstrip_target_info *info =
Packit 7b22a4
		(const void *)target->data;
Packit 7b22a4
Packit 7b22a4
	printf(" TCPOPTSTRIP options ");
Packit 7b22a4
	tcpoptstrip_print_list(info, numeric);
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
tcpoptstrip_tg_save(const void *ip, const struct xt_entry_target *target)
Packit 7b22a4
{
Packit 7b22a4
	const struct xt_tcpoptstrip_target_info *info =
Packit 7b22a4
		(const void *)target->data;
Packit 7b22a4
Packit 7b22a4
	printf(" --strip-options ");
Packit 7b22a4
	tcpoptstrip_print_list(info, true);
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static struct xtables_target tcpoptstrip_tg_reg = {
Packit 7b22a4
	.version       = XTABLES_VERSION,
Packit 7b22a4
	.name          = "TCPOPTSTRIP",
Packit 7b22a4
	.family        = NFPROTO_UNSPEC,
Packit 7b22a4
	.size          = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)),
Packit 7b22a4
	.userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)),
Packit 7b22a4
	.help          = tcpoptstrip_tg_help,
Packit 7b22a4
	.print         = tcpoptstrip_tg_print,
Packit 7b22a4
	.save          = tcpoptstrip_tg_save,
Packit 7b22a4
	.x6_parse      = tcpoptstrip_tg_parse,
Packit 7b22a4
	.x6_options    = tcpoptstrip_tg_opts,
Packit 7b22a4
};
Packit 7b22a4
Packit 7b22a4
void _init(void)
Packit 7b22a4
{
Packit 7b22a4
	xtables_register_target(&tcpoptstrip_tg_reg);
Packit 7b22a4
}