1#include <stdio.h>
2#include <xtables.h>
3#include <linux/netfilter_ipv4/ipt_ah.h>
4
5enum {
6	O_AHSPI = 0,
7};
8
9static void ah_help(void)
10{
11	printf(
12"ah match options:\n"
13"[!] --ahspi spi[:spi]\n"
14"				match spi (range)\n");
15}
16
17static const struct xt_option_entry ah_opts[] = {
18	{.name = "ahspi", .id = O_AHSPI, .type = XTTYPE_UINT32RC,
19	 .flags = XTOPT_INVERT | XTOPT_PUT,
20	 XTOPT_POINTER(struct ipt_ah, spis)},
21	XTOPT_TABLEEND,
22};
23
24static void ah_init(struct xt_entry_match *m)
25{
26	struct ipt_ah *ahinfo = (void *)m->data;
27
28	ahinfo->spis[1] = ~0U;
29}
30
31static void ah_parse(struct xt_option_call *cb)
32{
33	struct ipt_ah *ahinfo = cb->data;
34
35	xtables_option_parse(cb);
36	if (cb->nvals == 1)
37		ahinfo->spis[1] = ahinfo->spis[0];
38	if (cb->invert)
39		ahinfo->invflags |= IPT_AH_INV_SPI;
40}
41
42static void
43print_spis(const char *name, uint32_t min, uint32_t max,
44	    int invert)
45{
46	const char *inv = invert ? "!" : "";
47
48	if (min != 0 || max != 0xFFFFFFFF || invert) {
49		printf("%s", name);
50		if (min == max) {
51			printf(":%s", inv);
52			printf("%u", min);
53		} else {
54			printf("s:%s", inv);
55			printf("%u",min);
56			printf(":");
57			printf("%u",max);
58		}
59	}
60}
61
62static void ah_print(const void *ip, const struct xt_entry_match *match,
63                     int numeric)
64{
65	const struct ipt_ah *ah = (struct ipt_ah *)match->data;
66
67	printf(" ah ");
68	print_spis("spi", ah->spis[0], ah->spis[1],
69		    ah->invflags & IPT_AH_INV_SPI);
70	if (ah->invflags & ~IPT_AH_INV_MASK)
71		printf(" Unknown invflags: 0x%X",
72		       ah->invflags & ~IPT_AH_INV_MASK);
73}
74
75static void ah_save(const void *ip, const struct xt_entry_match *match)
76{
77	const struct ipt_ah *ahinfo = (struct ipt_ah *)match->data;
78
79	if (!(ahinfo->spis[0] == 0
80	    && ahinfo->spis[1] == 0xFFFFFFFF)) {
81		printf("%s --ahspi ",
82			(ahinfo->invflags & IPT_AH_INV_SPI) ? " !" : "");
83		if (ahinfo->spis[0]
84		    != ahinfo->spis[1])
85			printf("%u:%u",
86			       ahinfo->spis[0],
87			       ahinfo->spis[1]);
88		else
89			printf("%u",
90			       ahinfo->spis[0]);
91	}
92
93}
94
95static int ah_xlate(struct xt_xlate *xl,
96		    const struct xt_xlate_mt_params *params)
97{
98	const struct ipt_ah *ahinfo = (struct ipt_ah *)params->match->data;
99
100	if (!(ahinfo->spis[0] == 0 && ahinfo->spis[1] == 0xFFFFFFFF)) {
101		xt_xlate_add(xl, "ah spi%s ",
102			   (ahinfo->invflags & IPT_AH_INV_SPI) ? " !=" : "");
103		if (ahinfo->spis[0] != ahinfo->spis[1])
104			xt_xlate_add(xl, "%u-%u", ahinfo->spis[0],
105				   ahinfo->spis[1]);
106		else
107			xt_xlate_add(xl, "%u", ahinfo->spis[0]);
108	}
109
110	return 1;
111}
112
113static struct xtables_match ah_mt_reg = {
114	.name		= "ah",
115	.version	= XTABLES_VERSION,
116	.family		= NFPROTO_IPV4,
117	.size		= XT_ALIGN(sizeof(struct ipt_ah)),
118	.userspacesize	= XT_ALIGN(sizeof(struct ipt_ah)),
119	.help		= ah_help,
120	.init		= ah_init,
121	.print		= ah_print,
122	.save		= ah_save,
123	.x6_parse	= ah_parse,
124	.x6_options	= ah_opts,
125	.xlate		= ah_xlate,
126};
127
128void
129_init(void)
130{
131	xtables_register_match(&ah_mt_reg);
132}
133