libipt_ah.c revision 59d164019340d110d302634e429320577f0db7be
1/* Shared library add-on to iptables to add AH support. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
7#include <errno.h>
8#include <iptables.h>
9#include <linux/netfilter_ipv4/ipt_ah.h>
10
11/* Function which prints out usage message. */
12static void ah_help(void)
13{
14	printf(
15"AH v%s options:\n"
16" --ahspi [!] spi[:spi]\n"
17"				match spi (range)\n",
18IPTABLES_VERSION);
19}
20
21static const struct option ah_opts[] = {
22	{ "ahspi", 1, NULL, '1' },
23	{ }
24};
25
26static u_int32_t
27parse_ah_spi(const char *spistr)
28{
29	unsigned long int spi;
30	char* ep;
31
32	spi =  strtoul(spistr,&ep,0) ;
33
34	if ( spistr == ep ) {
35		exit_error(PARAMETER_PROBLEM,
36			   "AH no valid digits in spi `%s'", spistr);
37	}
38	if ( spi == ULONG_MAX  && errno == ERANGE ) {
39		exit_error(PARAMETER_PROBLEM,
40			   "spi `%s' specified too big: would overflow", spistr);
41	}
42	if ( *spistr != '\0'  && *ep != '\0' ) {
43		exit_error(PARAMETER_PROBLEM,
44			   "AH error parsing spi `%s'", spistr);
45	}
46	return (u_int32_t) spi;
47}
48
49static void
50parse_ah_spis(const char *spistring, u_int32_t *spis)
51{
52	char *buffer;
53	char *cp;
54
55	buffer = strdup(spistring);
56	if ((cp = strchr(buffer, ':')) == NULL)
57		spis[0] = spis[1] = parse_ah_spi(buffer);
58	else {
59		*cp = '\0';
60		cp++;
61
62		spis[0] = buffer[0] ? parse_ah_spi(buffer) : 0;
63		spis[1] = cp[0] ? parse_ah_spi(cp) : 0xFFFFFFFF;
64	}
65	free(buffer);
66}
67
68/* Initialize the match. */
69static void ah_init(struct xt_entry_match *m)
70{
71	struct ipt_ah *ahinfo = (struct ipt_ah *)m->data;
72
73	ahinfo->spis[1] = 0xFFFFFFFF;
74}
75
76#define AH_SPI 0x01
77
78/* Function which parses command options; returns true if it
79   ate an option */
80static int ah_parse(int c, char **argv, int invert, unsigned int *flags,
81                    const void *entry, struct xt_entry_match **match)
82{
83	struct ipt_ah *ahinfo = (struct ipt_ah *)(*match)->data;
84
85	switch (c) {
86	case '1':
87		if (*flags & AH_SPI)
88			exit_error(PARAMETER_PROBLEM,
89				   "Only one `--ahspi' allowed");
90		check_inverse(optarg, &invert, &optind, 0);
91		parse_ah_spis(argv[optind-1], ahinfo->spis);
92		if (invert)
93			ahinfo->invflags |= IPT_AH_INV_SPI;
94		*flags |= AH_SPI;
95		break;
96	default:
97		return 0;
98	}
99
100	return 1;
101}
102
103static void
104print_spis(const char *name, u_int32_t min, u_int32_t max,
105	    int invert)
106{
107	const char *inv = invert ? "!" : "";
108
109	if (min != 0 || max != 0xFFFFFFFF || invert) {
110		printf("%s", name);
111		if (min == max) {
112			printf(":%s", inv);
113			printf("%u", min);
114		} else {
115			printf("s:%s", inv);
116			printf("%u",min);
117			printf(":");
118			printf("%u",max);
119		}
120		printf(" ");
121	}
122}
123
124/* Prints out the union ipt_matchinfo. */
125static void ah_print(const void *ip, const struct xt_entry_match *match,
126                     int numeric)
127{
128	const struct ipt_ah *ah = (struct ipt_ah *)match->data;
129
130	printf("ah ");
131	print_spis("spi", ah->spis[0], ah->spis[1],
132		    ah->invflags & IPT_AH_INV_SPI);
133	if (ah->invflags & ~IPT_AH_INV_MASK)
134		printf("Unknown invflags: 0x%X ",
135		       ah->invflags & ~IPT_AH_INV_MASK);
136}
137
138/* Saves the union ipt_matchinfo in parsable form to stdout. */
139static void ah_save(const void *ip, const struct xt_entry_match *match)
140{
141	const struct ipt_ah *ahinfo = (struct ipt_ah *)match->data;
142
143	if (!(ahinfo->spis[0] == 0
144	    && ahinfo->spis[1] == 0xFFFFFFFF)) {
145		printf("--ahspi %s",
146			(ahinfo->invflags & IPT_AH_INV_SPI) ? "! " : "");
147		if (ahinfo->spis[0]
148		    != ahinfo->spis[1])
149			printf("%u:%u ",
150			       ahinfo->spis[0],
151			       ahinfo->spis[1]);
152		else
153			printf("%u ",
154			       ahinfo->spis[0]);
155	}
156
157}
158
159static struct iptables_match ah_match = {
160	.name 		= "ah",
161	.version 	= IPTABLES_VERSION,
162	.size		= IPT_ALIGN(sizeof(struct ipt_ah)),
163	.userspacesize 	= IPT_ALIGN(sizeof(struct ipt_ah)),
164	.help 		= ah_help,
165	.init 		= ah_init,
166	.parse 		= ah_parse,
167	.print 		= ah_print,
168	.save 		= ah_save,
169	.extra_opts 	= ah_opts,
170};
171
172void
173_init(void)
174{
175	register_match(&ah_match);
176}
177