libxt_esp.c revision 181dead3f13befe02769ef479bcbb51801b7fc4e
1524518261009f3f81febfdd8398becc4a80cc941Rusty Russell/* Shared library add-on to iptables to add ESP support. */
2524518261009f3f81febfdd8398becc4a80cc941Rusty Russell#include <stdio.h>
3524518261009f3f81febfdd8398becc4a80cc941Rusty Russell#include <netdb.h>
4524518261009f3f81febfdd8398becc4a80cc941Rusty Russell#include <string.h>
5524518261009f3f81febfdd8398becc4a80cc941Rusty Russell#include <stdlib.h>
6524518261009f3f81febfdd8398becc4a80cc941Rusty Russell#include <getopt.h>
7524518261009f3f81febfdd8398becc4a80cc941Rusty Russell#include <errno.h>
80a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI#include <xtables.h>
90a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI#include <linux/netfilter/xt_esp.h>
10524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
11524518261009f3f81febfdd8398becc4a80cc941Rusty Russell/* Function which prints out usage message. */
12181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void esp_help(void)
13524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
14524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	printf(
15524518261009f3f81febfdd8398becc4a80cc941Rusty Russell"ESP v%s options:\n"
16524518261009f3f81febfdd8398becc4a80cc941Rusty Russell" --espspi [!] spi[:spi]\n"
17524518261009f3f81febfdd8398becc4a80cc941Rusty Russell"				match spi (range)\n",
1880fe35d6339b53a12ddaec41885613e4e37ed031Harald WelteIPTABLES_VERSION);
19524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
20524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
21181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic const struct option esp_opts[] = {
22500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy	{ "espspi", 1, NULL, '1' },
23500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy	{ }
24524518261009f3f81febfdd8398becc4a80cc941Rusty Russell};
25524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
26524518261009f3f81febfdd8398becc4a80cc941Rusty Russellstatic u_int32_t
27524518261009f3f81febfdd8398becc4a80cc941Rusty Russellparse_esp_spi(const char *spistr)
28524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
29524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	unsigned long int spi;
30524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	char* ep;
31524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
32524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	spi =  strtoul(spistr,&ep,0) ;
33524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
34524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	if ( spistr == ep ) {
35524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		exit_error(PARAMETER_PROBLEM,
36524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			   "ESP no valid digits in spi `%s'", spistr);
37524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
38524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	if ( spi == ULONG_MAX  && errno == ERANGE ) {
39524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		exit_error(PARAMETER_PROBLEM,
40524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			   "spi `%s' specified too big: would overflow", spistr);
41524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
42524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	if ( *spistr != '\0'  && *ep != '\0' ) {
43524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		exit_error(PARAMETER_PROBLEM,
44524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			   "ESP error parsing spi `%s'", spistr);
45524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
46524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	return (u_int32_t) spi;
47524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
48524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
49524518261009f3f81febfdd8398becc4a80cc941Rusty Russellstatic void
50524518261009f3f81febfdd8398becc4a80cc941Rusty Russellparse_esp_spis(const char *spistring, u_int32_t *spis)
51524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
52524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	char *buffer;
53524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	char *cp;
54524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
55524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	buffer = strdup(spistring);
56524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	if ((cp = strchr(buffer, ':')) == NULL)
57524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		spis[0] = spis[1] = parse_esp_spi(buffer);
58524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	else {
59524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		*cp = '\0';
60524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		cp++;
61524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
62524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		spis[0] = buffer[0] ? parse_esp_spi(buffer) : 0;
63524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		spis[1] = cp[0] ? parse_esp_spi(cp) : 0xFFFFFFFF;
642c627cf60cfb1a4e67aea1b2333f2a11e23fecd8Yasuyuki KOZAKAI		if (spis[0] > spis[1])
652c627cf60cfb1a4e67aea1b2333f2a11e23fecd8Yasuyuki KOZAKAI			exit_error(PARAMETER_PROBLEM,
662c627cf60cfb1a4e67aea1b2333f2a11e23fecd8Yasuyuki KOZAKAI				   "Invalid ESP spi range: %s", spistring);
67524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
68524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	free(buffer);
69524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
70524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
71524518261009f3f81febfdd8398becc4a80cc941Rusty Russell/* Initialize the match. */
72181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void esp_init(struct xt_entry_match *m)
73524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
740a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	struct xt_esp *espinfo = (struct xt_esp *)m->data;
75524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
76524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	espinfo->spis[1] = 0xFFFFFFFF;
77524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
78524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
79524518261009f3f81febfdd8398becc4a80cc941Rusty Russell#define ESP_SPI 0x01
80524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
81524518261009f3f81febfdd8398becc4a80cc941Rusty Russell/* Function which parses command options; returns true if it
82524518261009f3f81febfdd8398becc4a80cc941Rusty Russell   ate an option */
83524518261009f3f81febfdd8398becc4a80cc941Rusty Russellstatic int
84181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtesp_parse(int c, char **argv, int invert, unsigned int *flags,
85181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt          const void *entry, struct xt_entry_match **match)
86524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
870a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	struct xt_esp *espinfo = (struct xt_esp *)(*match)->data;
88524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
89524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	switch (c) {
90524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	case '1':
91524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		if (*flags & ESP_SPI)
92524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			exit_error(PARAMETER_PROBLEM,
93f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte				   "Only one `--espspi' allowed");
94b77f1dafb9f35752bb9685323bcacb32a0e6ddc5Harald Welte		check_inverse(optarg, &invert, &optind, 0);
95524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		parse_esp_spis(argv[optind-1], espinfo->spis);
96524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		if (invert)
970a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI			espinfo->invflags |= XT_ESP_INV_SPI;
98524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		*flags |= ESP_SPI;
99524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		break;
100524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	default:
101524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		return 0;
102524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
103524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
104524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	return 1;
105524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
106524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
107524518261009f3f81febfdd8398becc4a80cc941Rusty Russellstatic void
108524518261009f3f81febfdd8398becc4a80cc941Rusty Russellprint_spis(const char *name, u_int32_t min, u_int32_t max,
109524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	    int invert)
110524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
111524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	const char *inv = invert ? "!" : "";
112524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
113524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	if (min != 0 || max != 0xFFFFFFFF || invert) {
1140a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI		if (min == max)
1150a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI			printf("%s:%s%u ", name, inv, min);
1160a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI		else
1170a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI			printf("%ss:%s%u:%u ", name, inv, min, max);
118524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
119524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
120524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
121524518261009f3f81febfdd8398becc4a80cc941Rusty Russell/* Prints out the union ipt_matchinfo. */
122524518261009f3f81febfdd8398becc4a80cc941Rusty Russellstatic void
123181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtesp_print(const void *ip, const struct xt_entry_match *match, int numeric)
124524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
1250a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	const struct xt_esp *esp = (struct xt_esp *)match->data;
126524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
127524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	printf("esp ");
128524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	print_spis("spi", esp->spis[0], esp->spis[1],
1290a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI		    esp->invflags & XT_ESP_INV_SPI);
1300a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	if (esp->invflags & ~XT_ESP_INV_MASK)
131524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		printf("Unknown invflags: 0x%X ",
1320a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI		       esp->invflags & ~XT_ESP_INV_MASK);
133524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
134524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
135524518261009f3f81febfdd8398becc4a80cc941Rusty Russell/* Saves the union ipt_matchinfo in parsable form to stdout. */
136181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void esp_save(const void *ip, const struct xt_entry_match *match)
137524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
1380a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	const struct xt_esp *espinfo = (struct xt_esp *)match->data;
139524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
140f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte	if (!(espinfo->spis[0] == 0
141f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte	    && espinfo->spis[1] == 0xFFFFFFFF)) {
142f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte		printf("--espspi %s",
1430a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI			(espinfo->invflags & XT_ESP_INV_SPI) ? "! " : "");
144524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		if (espinfo->spis[0]
145524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		    != espinfo->spis[1])
146f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte			printf("%u:%u ",
147524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			       espinfo->spis[0],
148524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			       espinfo->spis[1]);
149524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		else
150f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte			printf("%u ",
151524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			       espinfo->spis[0]);
152524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
153524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
154524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
155524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
156181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match esp_match = {
1570a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.family		= AF_INET,
1580a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.name 		= "esp",
1590a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.version 	= IPTABLES_VERSION,
1600a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.size		= XT_ALIGN(sizeof(struct xt_esp)),
1610a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.userspacesize	= XT_ALIGN(sizeof(struct xt_esp)),
162181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.help		= esp_help,
163181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.init		= esp_init,
164181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.parse		= esp_parse,
165181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.print		= esp_print,
166181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.save		= esp_save,
167181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.extra_opts	= esp_opts,
1680a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI};
1690a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI
170181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match esp_match6 = {
1710a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.family		= AF_INET6,
1728caee8b9e34fed4562fcff553197c161fc9d9979Pablo Neira	.name 		= "esp",
1738caee8b9e34fed4562fcff553197c161fc9d9979Pablo Neira	.version 	= IPTABLES_VERSION,
1740a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.size		= XT_ALIGN(sizeof(struct xt_esp)),
1750a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.userspacesize	= XT_ALIGN(sizeof(struct xt_esp)),
176181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.help		= esp_help,
177181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.init		= esp_init,
178181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.parse		= esp_parse,
179181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.print		= esp_print,
180181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.save		= esp_save,
181181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.extra_opts	= esp_opts,
182524518261009f3f81febfdd8398becc4a80cc941Rusty Russell};
183524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
184524518261009f3f81febfdd8398becc4a80cc941Rusty Russellvoid
185524518261009f3f81febfdd8398becc4a80cc941Rusty Russell_init(void)
186524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
187181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	xtables_register_match(&esp_match);
188181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	xtables_register_match(&esp_match6);
189524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
190