1 #include <stdio.h>
2 #include <xtables.h>
3 #include <linux/netfilter_ipv6/ip6t_ah.h>
4
5 enum {
6 O_AHSPI = 0,
7 O_AHLEN,
8 O_AHRES,
9 };
10
ah_help(void)11 static 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
21 static 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
ah_init(struct xt_entry_match * m)31 static void ah_init(struct xt_entry_match *m)
32 {
33 struct ip6t_ah *ahinfo = (void *)m->data;
34
35 /* Defaults for when no --ahspi is used at all */
36 ahinfo->spis[1] = ~0U;
37 }
38
ah_parse(struct xt_option_call * cb)39 static void ah_parse(struct xt_option_call *cb)
40 {
41 struct ip6t_ah *ahinfo = cb->data;
42
43 xtables_option_parse(cb);
44 switch (cb->entry->id) {
45 case O_AHSPI:
46 if (cb->nvals == 1)
47 ahinfo->spis[1] = ahinfo->spis[0];
48 if (cb->invert)
49 ahinfo->invflags |= IP6T_AH_INV_SPI;
50 break;
51 case O_AHLEN:
52 if (cb->invert)
53 ahinfo->invflags |= IP6T_AH_INV_LEN;
54 break;
55 case O_AHRES:
56 ahinfo->hdrres = 1;
57 break;
58 }
59 }
60
61 static void
print_spis(const char * name,uint32_t min,uint32_t max,int invert)62 print_spis(const char *name, uint32_t min, uint32_t max,
63 int invert)
64 {
65 const char *inv = invert ? "!" : "";
66
67 if (min != 0 || max != 0xFFFFFFFF || invert) {
68 if (min == max)
69 printf("%s:%s%u", name, inv, min);
70 else
71 printf("%ss:%s%u:%u", name, inv, min, max);
72 }
73 }
74
75 static void
print_len(const char * name,uint32_t len,int invert)76 print_len(const char *name, uint32_t len, int invert)
77 {
78 const char *inv = invert ? "!" : "";
79
80 if (len != 0 || invert)
81 printf("%s:%s%u", name, inv, len);
82 }
83
ah_print(const void * ip,const struct xt_entry_match * match,int numeric)84 static void ah_print(const void *ip, const struct xt_entry_match *match,
85 int numeric)
86 {
87 const struct ip6t_ah *ah = (struct ip6t_ah *)match->data;
88
89 printf(" ah ");
90 print_spis("spi", ah->spis[0], ah->spis[1],
91 ah->invflags & IP6T_AH_INV_SPI);
92 print_len("length", ah->hdrlen,
93 ah->invflags & IP6T_AH_INV_LEN);
94
95 if (ah->hdrres)
96 printf(" reserved");
97
98 if (ah->invflags & ~IP6T_AH_INV_MASK)
99 printf(" Unknown invflags: 0x%X",
100 ah->invflags & ~IP6T_AH_INV_MASK);
101 }
102
ah_save(const void * ip,const struct xt_entry_match * match)103 static void ah_save(const void *ip, const struct xt_entry_match *match)
104 {
105 const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data;
106
107 if (!(ahinfo->spis[0] == 0
108 && ahinfo->spis[1] == 0xFFFFFFFF)) {
109 printf("%s --ahspi ",
110 (ahinfo->invflags & IP6T_AH_INV_SPI) ? " !" : "");
111 if (ahinfo->spis[0]
112 != ahinfo->spis[1])
113 printf("%u:%u",
114 ahinfo->spis[0],
115 ahinfo->spis[1]);
116 else
117 printf("%u",
118 ahinfo->spis[0]);
119 }
120
121 if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) {
122 printf("%s --ahlen %u",
123 (ahinfo->invflags & IP6T_AH_INV_LEN) ? " !" : "",
124 ahinfo->hdrlen);
125 }
126
127 if (ahinfo->hdrres != 0 )
128 printf(" --ahres");
129 }
130
ah_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)131 static int ah_xlate(struct xt_xlate *xl,
132 const struct xt_xlate_mt_params *params)
133 {
134 const struct ip6t_ah *ahinfo = (struct ip6t_ah *)params->match->data;
135 char *space = "";
136
137 if (!(ahinfo->spis[0] == 0 && ahinfo->spis[1] == 0xFFFFFFFF)) {
138 xt_xlate_add(xl, "ah spi%s ",
139 (ahinfo->invflags & IP6T_AH_INV_SPI) ? " !=" : "");
140 if (ahinfo->spis[0] != ahinfo->spis[1])
141 xt_xlate_add(xl, "%u-%u", ahinfo->spis[0],
142 ahinfo->spis[1]);
143 else
144 xt_xlate_add(xl, "%u", ahinfo->spis[0]);
145 space = " ";
146 }
147
148 if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN)) {
149 xt_xlate_add(xl, "%sah hdrlength%s %u", space,
150 (ahinfo->invflags & IP6T_AH_INV_LEN) ? " !=" : "",
151 ahinfo->hdrlen);
152 space = " ";
153 }
154
155 if (ahinfo->hdrres != 0) {
156 xt_xlate_add(xl, "%sah reserved %u", space, ahinfo->hdrres);
157 space = " ";
158 }
159
160 if (!space[0]) /* plain '-m ah' */
161 xt_xlate_add(xl, "meta l4proto ah");
162
163 return 1;
164 }
165
166 static struct xtables_match ah_mt6_reg = {
167 .name = "ah",
168 .version = XTABLES_VERSION,
169 .family = NFPROTO_IPV6,
170 .size = XT_ALIGN(sizeof(struct ip6t_ah)),
171 .userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)),
172 .help = ah_help,
173 .init = ah_init,
174 .print = ah_print,
175 .save = ah_save,
176 .x6_parse = ah_parse,
177 .x6_options = ah_opts,
178 .xlate = ah_xlate,
179 };
180
181 void
_init(void)182 _init(void)
183 {
184 xtables_register_match(&ah_mt6_reg);
185 }
186