1d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte#include <stdio.h>
25d9678ad3eabc34ac40dfe055d7f6a8e44445a5aJan Engelhardt#include <xtables.h>
3d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte#include <linux/netfilter_ipv6/ip6t_ah.h>
4ddac6c5bc636003d664d25c08ea3fe176565096cJan Engelhardt
54d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardtenum {
64d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	O_AHSPI = 0,
74d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	O_AHLEN,
84d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	O_AHRES,
94d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt};
104d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt
11997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void ah_help(void)
12d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{
13d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	printf(
148b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"ah match options:\n"
15967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt"[!] --ahspi spi[:spi]          match spi (range)\n"
16967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt"[!] --ahlen length             total length of this header\n"
1712a18d6043092bd2574b2bced635259b16317e57Jan Engelhardt" --ahres                       check the reserved field too\n");
18d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}
19d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
204d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt#define s struct ip6t_ah
214d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardtstatic const struct xt_option_entry ah_opts[] = {
224d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	{.name = "ahspi", .id = O_AHSPI, .type = XTTYPE_UINT32RC,
234d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spis)},
244d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	{.name = "ahlen", .id = O_AHLEN, .type = XTTYPE_UINT32,
254d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdrlen)},
264d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	{.name = "ahres", .id = O_AHRES, .type = XTTYPE_NONE},
274d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	XTOPT_TABLEEND,
28d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte};
294d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt#undef s
30d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
314d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardtstatic void ah_parse(struct xt_option_call *cb)
32d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{
334d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	struct ip6t_ah *ahinfo = cb->data;
344d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt
354d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	xtables_option_parse(cb);
364d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	switch (cb->entry->id) {
374d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	case O_AHSPI:
386944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt		if (cb->nvals == 1)
396944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt			ahinfo->spis[1] = ahinfo->spis[0];
404d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt		if (cb->invert)
41d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte			ahinfo->invflags |= IP6T_AH_INV_SPI;
42d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte		break;
434d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	case O_AHLEN:
444d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt		if (cb->invert)
45d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte			ahinfo->invflags |= IP6T_AH_INV_LEN;
46d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte		break;
474d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	case O_AHRES:
48d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte		ahinfo->hdrres = 1;
49d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte		break;
50d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	}
51d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}
52d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
53d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void
547ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtprint_spis(const char *name, uint32_t min, uint32_t max,
55d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	    int invert)
56d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{
57d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	const char *inv = invert ? "!" : "";
58d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
59d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	if (min != 0 || max != 0xFFFFFFFF || invert) {
60703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette		if (min == max)
6173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			printf("%s:%s%u", name, inv, min);
62703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette		else
6373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			printf("%ss:%s%u:%u", name, inv, min, max);
64d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	}
65d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}
66d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
67d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void
687ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtprint_len(const char *name, uint32_t len, int invert)
69d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{
70d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	const char *inv = invert ? "!" : "";
71d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
72703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette	if (len != 0 || invert)
7373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf("%s:%s%u", name, inv, len);
74d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}
75d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
76997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void ah_print(const void *ip, const struct xt_entry_match *match,
77997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt                     int numeric)
78d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{
79d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	const struct ip6t_ah *ah = (struct ip6t_ah *)match->data;
80d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
8173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" ah ");
82d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	print_spis("spi", ah->spis[0], ah->spis[1],
83d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte		    ah->invflags & IP6T_AH_INV_SPI);
84d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	print_len("length", ah->hdrlen,
85d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte		    ah->invflags & IP6T_AH_INV_LEN);
86703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette
87703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette	if (ah->hdrres)
8873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" reserved");
89703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette
90d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	if (ah->invflags & ~IP6T_AH_INV_MASK)
9173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" Unknown invflags: 0x%X",
92d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte		       ah->invflags & ~IP6T_AH_INV_MASK);
93d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}
94d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
95997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void ah_save(const void *ip, const struct xt_entry_match *match)
96d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{
97d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data;
98d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
99d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	if (!(ahinfo->spis[0] == 0
100d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	    && ahinfo->spis[1] == 0xFFFFFFFF)) {
10173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf("%s --ahspi ",
10273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			(ahinfo->invflags & IP6T_AH_INV_SPI) ? " !" : "");
103d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte		if (ahinfo->spis[0]
104d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte		    != ahinfo->spis[1])
10573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			printf("%u:%u",
106d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte			       ahinfo->spis[0],
107d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte			       ahinfo->spis[1]);
108d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte		else
10973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			printf("%u",
110d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte			       ahinfo->spis[0]);
111d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	}
112d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
113d8a12a841de648bd38dc52ba624d1ed1810a6333András Kis-Szabó	if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) {
11473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf("%s --ahlen %u",
11573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			(ahinfo->invflags & IP6T_AH_INV_LEN) ? " !" : "",
116d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte			ahinfo->hdrlen);
117d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte	}
118d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
119703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette	if (ahinfo->hdrres != 0 )
12073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" --ahres");
121d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}
122d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
1238b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardtstatic struct xtables_match ah_mt6_reg = {
124703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette	.name          = "ah",
1258b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.version       = XTABLES_VERSION,
12603d99486d8283552705b58dc55b6085dffc38792Jan Engelhardt	.family        = NFPROTO_IPV6,
1278b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.size          = XT_ALIGN(sizeof(struct ip6t_ah)),
1288b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)),
129997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.help          = ah_help,
130997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.print         = ah_print,
131997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.save          = ah_save,
1324d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	.x6_parse      = ah_parse,
1334d6ede0b324e5e9dcbb1d7cc2a7aebed9e56821aJan Engelhardt	.x6_options    = ah_opts,
134d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte};
135d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte
136d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltevoid
137d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte_init(void)
138d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{
1398b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	xtables_register_match(&ah_mt6_reg);
140d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}
141