libxt_esp.c revision 8b7c64d6ba156a99008fcd810cba874c73294333
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(
158b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"esp match options:\n"
16524518261009f3f81febfdd8398becc4a80cc941Rusty Russell" --espspi [!] spi[:spi]\n"
178b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"				match spi (range)\n");
18524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
19524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
20181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic const struct option esp_opts[] = {
21500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy	{ "espspi", 1, NULL, '1' },
229ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann	{ .name = NULL }
23524518261009f3f81febfdd8398becc4a80cc941Rusty Russell};
24524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
25524518261009f3f81febfdd8398becc4a80cc941Rusty Russellstatic u_int32_t
26524518261009f3f81febfdd8398becc4a80cc941Rusty Russellparse_esp_spi(const char *spistr)
27524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
28524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	unsigned long int spi;
29524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	char* ep;
30524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
31524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	spi =  strtoul(spistr,&ep,0) ;
32524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
33524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	if ( spistr == ep ) {
34524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		exit_error(PARAMETER_PROBLEM,
35524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			   "ESP no valid digits in spi `%s'", spistr);
36524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
37524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	if ( spi == ULONG_MAX  && errno == ERANGE ) {
38524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		exit_error(PARAMETER_PROBLEM,
39524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			   "spi `%s' specified too big: would overflow", spistr);
40524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
41524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	if ( *spistr != '\0'  && *ep != '\0' ) {
42524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		exit_error(PARAMETER_PROBLEM,
43524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			   "ESP error parsing spi `%s'", spistr);
44524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
45524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	return (u_int32_t) spi;
46524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
47524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
48524518261009f3f81febfdd8398becc4a80cc941Rusty Russellstatic void
49524518261009f3f81febfdd8398becc4a80cc941Rusty Russellparse_esp_spis(const char *spistring, u_int32_t *spis)
50524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
51524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	char *buffer;
52524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	char *cp;
53524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
54524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	buffer = strdup(spistring);
55524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	if ((cp = strchr(buffer, ':')) == NULL)
56524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		spis[0] = spis[1] = parse_esp_spi(buffer);
57524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	else {
58524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		*cp = '\0';
59524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		cp++;
60524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
61524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		spis[0] = buffer[0] ? parse_esp_spi(buffer) : 0;
62524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		spis[1] = cp[0] ? parse_esp_spi(cp) : 0xFFFFFFFF;
632c627cf60cfb1a4e67aea1b2333f2a11e23fecd8Yasuyuki KOZAKAI		if (spis[0] > spis[1])
642c627cf60cfb1a4e67aea1b2333f2a11e23fecd8Yasuyuki KOZAKAI			exit_error(PARAMETER_PROBLEM,
652c627cf60cfb1a4e67aea1b2333f2a11e23fecd8Yasuyuki KOZAKAI				   "Invalid ESP spi range: %s", spistring);
66524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
67524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	free(buffer);
68524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
69524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
70524518261009f3f81febfdd8398becc4a80cc941Rusty Russell/* Initialize the match. */
71181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void esp_init(struct xt_entry_match *m)
72524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
730a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	struct xt_esp *espinfo = (struct xt_esp *)m->data;
74524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
75524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	espinfo->spis[1] = 0xFFFFFFFF;
76524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
77524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
78524518261009f3f81febfdd8398becc4a80cc941Rusty Russell#define ESP_SPI 0x01
79524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
80524518261009f3f81febfdd8398becc4a80cc941Rusty Russell/* Function which parses command options; returns true if it
81524518261009f3f81febfdd8398becc4a80cc941Rusty Russell   ate an option */
82524518261009f3f81febfdd8398becc4a80cc941Rusty Russellstatic int
83181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtesp_parse(int c, char **argv, int invert, unsigned int *flags,
84181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt          const void *entry, struct xt_entry_match **match)
85524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
860a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	struct xt_esp *espinfo = (struct xt_esp *)(*match)->data;
87524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
88524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	switch (c) {
89524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	case '1':
90524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		if (*flags & ESP_SPI)
91524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			exit_error(PARAMETER_PROBLEM,
92f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte				   "Only one `--espspi' allowed");
93b77f1dafb9f35752bb9685323bcacb32a0e6ddc5Harald Welte		check_inverse(optarg, &invert, &optind, 0);
94524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		parse_esp_spis(argv[optind-1], espinfo->spis);
95524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		if (invert)
960a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI			espinfo->invflags |= XT_ESP_INV_SPI;
97524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		*flags |= ESP_SPI;
98524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		break;
99524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	default:
100524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		return 0;
101524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
102524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
103524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	return 1;
104524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
105524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
106524518261009f3f81febfdd8398becc4a80cc941Rusty Russellstatic void
107524518261009f3f81febfdd8398becc4a80cc941Rusty Russellprint_spis(const char *name, u_int32_t min, u_int32_t max,
108524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	    int invert)
109524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
110524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	const char *inv = invert ? "!" : "";
111524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
112524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	if (min != 0 || max != 0xFFFFFFFF || invert) {
1130a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI		if (min == max)
1140a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI			printf("%s:%s%u ", name, inv, min);
1150a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI		else
1160a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI			printf("%ss:%s%u:%u ", name, inv, min, max);
117524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
118524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
119524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
120524518261009f3f81febfdd8398becc4a80cc941Rusty Russell/* Prints out the union ipt_matchinfo. */
121524518261009f3f81febfdd8398becc4a80cc941Rusty Russellstatic void
122181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtesp_print(const void *ip, const struct xt_entry_match *match, int numeric)
123524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
1240a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	const struct xt_esp *esp = (struct xt_esp *)match->data;
125524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
126524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	printf("esp ");
127524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	print_spis("spi", esp->spis[0], esp->spis[1],
1280a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI		    esp->invflags & XT_ESP_INV_SPI);
1290a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	if (esp->invflags & ~XT_ESP_INV_MASK)
130524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		printf("Unknown invflags: 0x%X ",
1310a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI		       esp->invflags & ~XT_ESP_INV_MASK);
132524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
133524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
134524518261009f3f81febfdd8398becc4a80cc941Rusty Russell/* Saves the union ipt_matchinfo in parsable form to stdout. */
135181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void esp_save(const void *ip, const struct xt_entry_match *match)
136524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
1370a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	const struct xt_esp *espinfo = (struct xt_esp *)match->data;
138524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
139f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte	if (!(espinfo->spis[0] == 0
140f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte	    && espinfo->spis[1] == 0xFFFFFFFF)) {
141f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte		printf("--espspi %s",
1420a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI			(espinfo->invflags & XT_ESP_INV_SPI) ? "! " : "");
143524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		if (espinfo->spis[0]
144524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		    != espinfo->spis[1])
145f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte			printf("%u:%u ",
146524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			       espinfo->spis[0],
147524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			       espinfo->spis[1]);
148524518261009f3f81febfdd8398becc4a80cc941Rusty Russell		else
149f0ac814a2137abe334bd0000d59e9be4721e1ddcHarald Welte			printf("%u ",
150524518261009f3f81febfdd8398becc4a80cc941Rusty Russell			       espinfo->spis[0]);
151524518261009f3f81febfdd8398becc4a80cc941Rusty Russell	}
152524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
153524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
154524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
155181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match esp_match = {
1560a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.family		= AF_INET,
1570a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.name 		= "esp",
1588b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.version 	= XTABLES_VERSION,
1590a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.size		= XT_ALIGN(sizeof(struct xt_esp)),
1600a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.userspacesize	= XT_ALIGN(sizeof(struct xt_esp)),
161181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.help		= esp_help,
162181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.init		= esp_init,
163181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.parse		= esp_parse,
164181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.print		= esp_print,
165181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.save		= esp_save,
166181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.extra_opts	= esp_opts,
1670a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI};
1680a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI
169181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match esp_match6 = {
1700a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.family		= AF_INET6,
1718caee8b9e34fed4562fcff553197c161fc9d9979Pablo Neira	.name 		= "esp",
1728b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.version 	= XTABLES_VERSION,
1730a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.size		= XT_ALIGN(sizeof(struct xt_esp)),
1740a04e8d695549788213f842cc99c724a564a88dfYasuyuki KOZAKAI	.userspacesize	= XT_ALIGN(sizeof(struct xt_esp)),
175181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.help		= esp_help,
176181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.init		= esp_init,
177181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.parse		= esp_parse,
178181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.print		= esp_print,
179181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.save		= esp_save,
180181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.extra_opts	= esp_opts,
181524518261009f3f81febfdd8398becc4a80cc941Rusty Russell};
182524518261009f3f81febfdd8398becc4a80cc941Rusty Russell
183524518261009f3f81febfdd8398becc4a80cc941Rusty Russellvoid
184524518261009f3f81febfdd8398becc4a80cc941Rusty Russell_init(void)
185524518261009f3f81febfdd8398becc4a80cc941Rusty Russell{
186181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	xtables_register_match(&esp_match);
187181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	xtables_register_match(&esp_match6);
188524518261009f3f81febfdd8398becc4a80cc941Rusty Russell}
189