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_parse(struct xt_option_call *cb)
25{
26	struct ipt_ah *ahinfo = cb->data;
27
28	xtables_option_parse(cb);
29	if (cb->nvals == 1)
30		ahinfo->spis[1] = ahinfo->spis[0];
31	if (cb->invert)
32		ahinfo->invflags |= IPT_AH_INV_SPI;
33}
34
35static void
36print_spis(const char *name, uint32_t min, uint32_t max,
37	    int invert)
38{
39	const char *inv = invert ? "!" : "";
40
41	if (min != 0 || max != 0xFFFFFFFF || invert) {
42		printf("%s", name);
43		if (min == max) {
44			printf(":%s", inv);
45			printf("%u", min);
46		} else {
47			printf("s:%s", inv);
48			printf("%u",min);
49			printf(":");
50			printf("%u",max);
51		}
52	}
53}
54
55static void ah_print(const void *ip, const struct xt_entry_match *match,
56                     int numeric)
57{
58	const struct ipt_ah *ah = (struct ipt_ah *)match->data;
59
60	printf(" ah ");
61	print_spis("spi", ah->spis[0], ah->spis[1],
62		    ah->invflags & IPT_AH_INV_SPI);
63	if (ah->invflags & ~IPT_AH_INV_MASK)
64		printf(" Unknown invflags: 0x%X",
65		       ah->invflags & ~IPT_AH_INV_MASK);
66}
67
68static void ah_save(const void *ip, const struct xt_entry_match *match)
69{
70	const struct ipt_ah *ahinfo = (struct ipt_ah *)match->data;
71
72	if (!(ahinfo->spis[0] == 0
73	    && ahinfo->spis[1] == 0xFFFFFFFF)) {
74		printf("%s --ahspi ",
75			(ahinfo->invflags & IPT_AH_INV_SPI) ? " !" : "");
76		if (ahinfo->spis[0]
77		    != ahinfo->spis[1])
78			printf("%u:%u",
79			       ahinfo->spis[0],
80			       ahinfo->spis[1]);
81		else
82			printf("%u",
83			       ahinfo->spis[0]);
84	}
85
86}
87
88static struct xtables_match ah_mt_reg = {
89	.name 		= "ah",
90	.version 	= XTABLES_VERSION,
91	.family		= NFPROTO_IPV4,
92	.size		= XT_ALIGN(sizeof(struct ipt_ah)),
93	.userspacesize 	= XT_ALIGN(sizeof(struct ipt_ah)),
94	.help 		= ah_help,
95	.print 		= ah_print,
96	.save 		= ah_save,
97	.x6_parse	= ah_parse,
98	.x6_options	= ah_opts,
99};
100
101void
102_init(void)
103{
104	xtables_register_match(&ah_mt_reg);
105}
106