libip6t_ah.c revision 6944f2c8190f1c4319aeac748470c71b0ba45025
1#include <stdio.h>
2#include <xtables.h>
3#include <linux/netfilter_ipv6/ip6t_ah.h>
4
5enum {
6	O_AHSPI = 0,
7	O_AHLEN,
8	O_AHRES,
9};
10
11static void ah_help(void)
12{
13	printf(
14"ah match options:\n"
15"[!] --ahspi spi[:spi]          match spi (range)\n"
16"[!] --ahlen length             total length of this header\n"
17" --ahres                       check the reserved field too\n");
18}
19
20#define s struct ip6t_ah
21static const struct xt_option_entry ah_opts[] = {
22	{.name = "ahspi", .id = O_AHSPI, .type = XTTYPE_UINT32RC,
23	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spis)},
24	{.name = "ahlen", .id = O_AHLEN, .type = XTTYPE_UINT32,
25	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdrlen)},
26	{.name = "ahres", .id = O_AHRES, .type = XTTYPE_NONE},
27	XTOPT_TABLEEND,
28};
29#undef s
30
31static void ah_parse(struct xt_option_call *cb)
32{
33	struct ip6t_ah *ahinfo = cb->data;
34
35	xtables_option_parse(cb);
36	switch (cb->entry->id) {
37	case O_AHSPI:
38		if (cb->nvals == 1)
39			ahinfo->spis[1] = ahinfo->spis[0];
40		if (cb->invert)
41			ahinfo->invflags |= IP6T_AH_INV_SPI;
42		break;
43	case O_AHLEN:
44		if (cb->invert)
45			ahinfo->invflags |= IP6T_AH_INV_LEN;
46		break;
47	case O_AHRES:
48		ahinfo->hdrres = 1;
49		break;
50	}
51}
52
53static void
54print_spis(const char *name, uint32_t min, uint32_t max,
55	    int invert)
56{
57	const char *inv = invert ? "!" : "";
58
59	if (min != 0 || max != 0xFFFFFFFF || invert) {
60		if (min == max)
61			printf("%s:%s%u", name, inv, min);
62		else
63			printf("%ss:%s%u:%u", name, inv, min, max);
64	}
65}
66
67static void
68print_len(const char *name, uint32_t len, int invert)
69{
70	const char *inv = invert ? "!" : "";
71
72	if (len != 0 || invert)
73		printf("%s:%s%u", name, inv, len);
74}
75
76static void ah_print(const void *ip, const struct xt_entry_match *match,
77                     int numeric)
78{
79	const struct ip6t_ah *ah = (struct ip6t_ah *)match->data;
80
81	printf(" ah ");
82	print_spis("spi", ah->spis[0], ah->spis[1],
83		    ah->invflags & IP6T_AH_INV_SPI);
84	print_len("length", ah->hdrlen,
85		    ah->invflags & IP6T_AH_INV_LEN);
86
87	if (ah->hdrres)
88		printf(" reserved");
89
90	if (ah->invflags & ~IP6T_AH_INV_MASK)
91		printf(" Unknown invflags: 0x%X",
92		       ah->invflags & ~IP6T_AH_INV_MASK);
93}
94
95static void ah_save(const void *ip, const struct xt_entry_match *match)
96{
97	const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data;
98
99	if (!(ahinfo->spis[0] == 0
100	    && ahinfo->spis[1] == 0xFFFFFFFF)) {
101		printf("%s --ahspi ",
102			(ahinfo->invflags & IP6T_AH_INV_SPI) ? " !" : "");
103		if (ahinfo->spis[0]
104		    != ahinfo->spis[1])
105			printf("%u:%u",
106			       ahinfo->spis[0],
107			       ahinfo->spis[1]);
108		else
109			printf("%u",
110			       ahinfo->spis[0]);
111	}
112
113	if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) {
114		printf("%s --ahlen %u",
115			(ahinfo->invflags & IP6T_AH_INV_LEN) ? " !" : "",
116			ahinfo->hdrlen);
117	}
118
119	if (ahinfo->hdrres != 0 )
120		printf(" --ahres");
121}
122
123static struct xtables_match ah_mt6_reg = {
124	.name          = "ah",
125	.version       = XTABLES_VERSION,
126	.family        = NFPROTO_IPV6,
127	.size          = XT_ALIGN(sizeof(struct ip6t_ah)),
128	.userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)),
129	.help          = ah_help,
130	.print         = ah_print,
131	.save          = ah_save,
132	.x6_parse      = ah_parse,
133	.x6_options    = ah_opts,
134};
135
136void
137_init(void)
138{
139	xtables_register_match(&ah_mt6_reg);
140}
141