xref: /aosp_15_r20/external/iptables/extensions/libip6t_srh.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
1 /* Shared library to add Segment Routing Header (SRH) matching support.
2  *
3  * Author:
4  *       Ahmed Abdelsalam       <[email protected]>
5  */
6 
7 #include <stdio.h>
8 #include <xtables.h>
9 #include <linux/netfilter_ipv6/ip6t_srh.h>
10 #include <string.h>
11 
12 /* srh command-line options */
13 enum {
14 	O_SRH_NEXTHDR,
15 	O_SRH_LEN_EQ,
16 	O_SRH_LEN_GT,
17 	O_SRH_LEN_LT,
18 	O_SRH_SEGS_EQ,
19 	O_SRH_SEGS_GT,
20 	O_SRH_SEGS_LT,
21 	O_SRH_LAST_EQ,
22 	O_SRH_LAST_GT,
23 	O_SRH_LAST_LT,
24 	O_SRH_TAG,
25 	O_SRH_PSID,
26 	O_SRH_NSID,
27 	O_SRH_LSID,
28 };
29 
srh_help(void)30 static void srh_help(void)
31 {
32 	printf(
33 "srh match options:\n"
34 "[!] --srh-next-hdr		next-hdr        Next Header value of SRH\n"
35 "[!] --srh-hdr-len-eq		hdr_len         Hdr Ext Len value of SRH\n"
36 "[!] --srh-hdr-len-gt		hdr_len         Hdr Ext Len value of SRH\n"
37 "[!] --srh-hdr-len-lt		hdr_len         Hdr Ext Len value of SRH\n"
38 "[!] --srh-segs-left-eq		segs_left       Segments Left value of SRH\n"
39 "[!] --srh-segs-left-gt		segs_left       Segments Left value of SRH\n"
40 "[!] --srh-segs-left-lt		segs_left       Segments Left value of SRH\n"
41 "[!] --srh-last-entry-eq 	last_entry      Last Entry value of SRH\n"
42 "[!] --srh-last-entry-gt 	last_entry      Last Entry value of SRH\n"
43 "[!] --srh-last-entry-lt 	last_entry      Last Entry value of SRH\n"
44 "[!] --srh-tag			tag             Tag value of SRH\n"
45 "[!] --srh-psid			addr[/mask]	SRH previous SID\n"
46 "[!] --srh-nsid			addr[/mask]	SRH next SID\n"
47 "[!] --srh-lsid			addr[/mask]	SRH Last SID\n");
48 }
49 
50 #define s struct ip6t_srh
51 static const struct xt_option_entry srh_opts[] = {
52 	{ .name = "srh-next-hdr", .id = O_SRH_NEXTHDR, .type = XTTYPE_UINT8,
53 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, next_hdr)},
54 	{ .name = "srh-hdr-len-eq", .id = O_SRH_LEN_EQ, .type = XTTYPE_UINT8,
55 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
56 	{ .name = "srh-hdr-len-gt", .id = O_SRH_LEN_GT, .type = XTTYPE_UINT8,
57 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
58 	{ .name = "srh-hdr-len-lt", .id = O_SRH_LEN_LT, .type = XTTYPE_UINT8,
59 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
60 	{ .name = "srh-segs-left-eq", .id = O_SRH_SEGS_EQ, .type = XTTYPE_UINT8,
61 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
62 	{ .name = "srh-segs-left-gt", .id = O_SRH_SEGS_GT, .type = XTTYPE_UINT8,
63 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
64 	{ .name = "srh-segs-left-lt", .id = O_SRH_SEGS_LT, .type = XTTYPE_UINT8,
65 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
66 	{ .name = "srh-last-entry-eq", .id = O_SRH_LAST_EQ, .type = XTTYPE_UINT8,
67 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
68 	{ .name = "srh-last-entry-gt", .id = O_SRH_LAST_GT, .type = XTTYPE_UINT8,
69 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
70 	{ .name = "srh-last-entry-lt", .id = O_SRH_LAST_LT, .type = XTTYPE_UINT8,
71 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
72 	{ .name = "srh-tag", .id = O_SRH_TAG, .type = XTTYPE_UINT16,
73 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, tag)},
74 	{ }
75 };
76 #undef s
77 
78 #define s struct ip6t_srh1
79 static const struct xt_option_entry srh1_opts[] = {
80 	{ .name = "srh-next-hdr", .id = O_SRH_NEXTHDR, .type = XTTYPE_UINT8,
81 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, next_hdr)},
82 	{ .name = "srh-hdr-len-eq", .id = O_SRH_LEN_EQ, .type = XTTYPE_UINT8,
83 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
84 	{ .name = "srh-hdr-len-gt", .id = O_SRH_LEN_GT, .type = XTTYPE_UINT8,
85 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
86 	{ .name = "srh-hdr-len-lt", .id = O_SRH_LEN_LT, .type = XTTYPE_UINT8,
87 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
88 	{ .name = "srh-segs-left-eq", .id = O_SRH_SEGS_EQ, .type = XTTYPE_UINT8,
89 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
90 	{ .name = "srh-segs-left-gt", .id = O_SRH_SEGS_GT, .type = XTTYPE_UINT8,
91 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
92 	{ .name = "srh-segs-left-lt", .id = O_SRH_SEGS_LT, .type = XTTYPE_UINT8,
93 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
94 	{ .name = "srh-last-entry-eq", .id = O_SRH_LAST_EQ, .type = XTTYPE_UINT8,
95 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
96 	{ .name = "srh-last-entry-gt", .id = O_SRH_LAST_GT, .type = XTTYPE_UINT8,
97 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
98 	{ .name = "srh-last-entry-lt", .id = O_SRH_LAST_LT, .type = XTTYPE_UINT8,
99 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
100 	{ .name = "srh-tag", .id = O_SRH_TAG, .type = XTTYPE_UINT16,
101 	.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, tag)},
102 	{ .name = "srh-psid", .id = O_SRH_PSID, .type = XTTYPE_HOSTMASK,
103 	.flags = XTOPT_INVERT},
104 	{ .name = "srh-nsid", .id = O_SRH_NSID, .type = XTTYPE_HOSTMASK,
105 	.flags = XTOPT_INVERT},
106 	{ .name = "srh-lsid", .id = O_SRH_LSID, .type = XTTYPE_HOSTMASK,
107 	.flags = XTOPT_INVERT},
108 	{ }
109 };
110 #undef s
111 
srh_init(struct xt_entry_match * m)112 static void srh_init(struct xt_entry_match *m)
113 {
114 	struct ip6t_srh *srhinfo = (void *)m->data;
115 
116 	srhinfo->mt_flags = 0;
117 	srhinfo->mt_invflags = 0;
118 }
119 
srh1_init(struct xt_entry_match * m)120 static void srh1_init(struct xt_entry_match *m)
121 {
122 	struct ip6t_srh1 *srhinfo = (void *)m->data;
123 
124 	srhinfo->mt_flags = 0;
125 	srhinfo->mt_invflags = 0;
126 	memset(srhinfo->psid_addr.s6_addr, 0, sizeof(srhinfo->psid_addr.s6_addr));
127 	memset(srhinfo->nsid_addr.s6_addr, 0, sizeof(srhinfo->nsid_addr.s6_addr));
128 	memset(srhinfo->lsid_addr.s6_addr, 0, sizeof(srhinfo->lsid_addr.s6_addr));
129 	memset(srhinfo->psid_msk.s6_addr, 0, sizeof(srhinfo->psid_msk.s6_addr));
130 	memset(srhinfo->nsid_msk.s6_addr, 0, sizeof(srhinfo->nsid_msk.s6_addr));
131 	memset(srhinfo->lsid_msk.s6_addr, 0, sizeof(srhinfo->lsid_msk.s6_addr));
132 }
133 
srh_parse(struct xt_option_call * cb)134 static void srh_parse(struct xt_option_call *cb)
135 {
136 	struct ip6t_srh *srhinfo = cb->data;
137 
138 	xtables_option_parse(cb);
139 	switch (cb->entry->id) {
140 	case O_SRH_NEXTHDR:
141 		srhinfo->mt_flags |= IP6T_SRH_NEXTHDR;
142 		if (cb->invert)
143 			srhinfo->mt_invflags |= IP6T_SRH_INV_NEXTHDR;
144 		break;
145 	case O_SRH_LEN_EQ:
146 		srhinfo->mt_flags |= IP6T_SRH_LEN_EQ;
147 		if (cb->invert)
148 			srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_EQ;
149 		break;
150 	case O_SRH_LEN_GT:
151 		srhinfo->mt_flags |= IP6T_SRH_LEN_GT;
152 		if (cb->invert)
153 			srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_GT;
154 		break;
155 	case O_SRH_LEN_LT:
156 		srhinfo->mt_flags |= IP6T_SRH_LEN_LT;
157 		if (cb->invert)
158 			srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_LT;
159 		break;
160 	case O_SRH_SEGS_EQ:
161 		srhinfo->mt_flags |= IP6T_SRH_SEGS_EQ;
162 		if (cb->invert)
163 			srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_EQ;
164 		break;
165 	case O_SRH_SEGS_GT:
166 		srhinfo->mt_flags |= IP6T_SRH_SEGS_GT;
167 		if (cb->invert)
168 			srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_GT;
169 		break;
170 	case O_SRH_SEGS_LT:
171 		srhinfo->mt_flags |= IP6T_SRH_SEGS_LT;
172 		if (cb->invert)
173 			srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_LT;
174 		break;
175 	case O_SRH_LAST_EQ:
176 		srhinfo->mt_flags |= IP6T_SRH_LAST_EQ;
177 		if (cb->invert)
178 			srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_EQ;
179 		break;
180 	case O_SRH_LAST_GT:
181 		srhinfo->mt_flags |= IP6T_SRH_LAST_GT;
182 		if (cb->invert)
183 			srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_GT;
184 		break;
185 	case O_SRH_LAST_LT:
186 		srhinfo->mt_flags |= IP6T_SRH_LAST_LT;
187 		if (cb->invert)
188 			srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_LT;
189 		break;
190 	case O_SRH_TAG:
191 		srhinfo->mt_flags |= IP6T_SRH_TAG;
192 		if (cb->invert)
193 			srhinfo->mt_invflags |= IP6T_SRH_INV_TAG;
194 		break;
195 	}
196 }
197 
srh1_parse(struct xt_option_call * cb)198 static void srh1_parse(struct xt_option_call *cb)
199 {
200 	struct ip6t_srh1 *srhinfo = cb->data;
201 
202 	xtables_option_parse(cb);
203 	switch (cb->entry->id) {
204 	case O_SRH_NEXTHDR:
205 		srhinfo->mt_flags |= IP6T_SRH_NEXTHDR;
206 		if (cb->invert)
207 			srhinfo->mt_invflags |= IP6T_SRH_INV_NEXTHDR;
208 		break;
209 	case O_SRH_LEN_EQ:
210 		srhinfo->mt_flags |= IP6T_SRH_LEN_EQ;
211 		if (cb->invert)
212 			srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_EQ;
213 		break;
214 	case O_SRH_LEN_GT:
215 		srhinfo->mt_flags |= IP6T_SRH_LEN_GT;
216 		if (cb->invert)
217 			srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_GT;
218 		break;
219 	case O_SRH_LEN_LT:
220 		srhinfo->mt_flags |= IP6T_SRH_LEN_LT;
221 		if (cb->invert)
222 			srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_LT;
223 		break;
224 	case O_SRH_SEGS_EQ:
225 		srhinfo->mt_flags |= IP6T_SRH_SEGS_EQ;
226 		if (cb->invert)
227 			srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_EQ;
228 		break;
229 	case O_SRH_SEGS_GT:
230 		srhinfo->mt_flags |= IP6T_SRH_SEGS_GT;
231 		if (cb->invert)
232 			srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_GT;
233 		break;
234 	case O_SRH_SEGS_LT:
235 		srhinfo->mt_flags |= IP6T_SRH_SEGS_LT;
236 		if (cb->invert)
237 			srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_LT;
238 		break;
239 	case O_SRH_LAST_EQ:
240 		srhinfo->mt_flags |= IP6T_SRH_LAST_EQ;
241 		if (cb->invert)
242 			srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_EQ;
243 		break;
244 	case O_SRH_LAST_GT:
245 		srhinfo->mt_flags |= IP6T_SRH_LAST_GT;
246 		if (cb->invert)
247 			srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_GT;
248 		break;
249 	case O_SRH_LAST_LT:
250 		srhinfo->mt_flags |= IP6T_SRH_LAST_LT;
251 		if (cb->invert)
252 			srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_LT;
253 		break;
254 	case O_SRH_TAG:
255 		srhinfo->mt_flags |= IP6T_SRH_TAG;
256 		if (cb->invert)
257 			srhinfo->mt_invflags |= IP6T_SRH_INV_TAG;
258 		break;
259 	case O_SRH_PSID:
260 		srhinfo->mt_flags |= IP6T_SRH_PSID;
261 		srhinfo->psid_addr = cb->val.haddr.in6;
262 		srhinfo->psid_msk  = cb->val.hmask.in6;
263 		if (cb->invert)
264 			srhinfo->mt_invflags |= IP6T_SRH_INV_PSID;
265 		break;
266 	case O_SRH_NSID:
267 		srhinfo->mt_flags |= IP6T_SRH_NSID;
268 		srhinfo->nsid_addr = cb->val.haddr.in6;
269 		srhinfo->nsid_msk  = cb->val.hmask.in6;
270 		if (cb->invert)
271 			srhinfo->mt_invflags |= IP6T_SRH_INV_NSID;
272 		break;
273 	case O_SRH_LSID:
274 		srhinfo->mt_flags |= IP6T_SRH_LSID;
275 		srhinfo->lsid_addr = cb->val.haddr.in6;
276 		srhinfo->lsid_msk  = cb->val.hmask.in6;
277 		if (cb->invert)
278 			srhinfo->mt_invflags |= IP6T_SRH_INV_LSID;
279 		break;
280 	}
281 }
282 
srh_print(const void * ip,const struct xt_entry_match * match,int numeric)283 static void srh_print(const void *ip, const struct xt_entry_match *match,
284 			int numeric)
285 {
286 	const struct ip6t_srh *srhinfo = (struct ip6t_srh *)match->data;
287 
288 	printf(" srh");
289 	if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
290 		printf(" next-hdr:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR ? "!" : "",
291 			srhinfo->next_hdr);
292 	if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
293 		printf(" hdr-len-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ ? "!" : "",
294 			srhinfo->hdr_len);
295 	if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
296 		printf(" hdr-len-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT ? "!" : "",
297 			srhinfo->hdr_len);
298 	if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
299 		printf(" hdr-len-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT ? "!" : "",
300 			srhinfo->hdr_len);
301 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
302 		printf(" segs-left-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ ? "!" : "",
303 			srhinfo->segs_left);
304 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
305 		printf(" segs-left-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT ? "!" : "",
306 			srhinfo->segs_left);
307 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
308 		printf(" segs-left-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT ? "!" : "",
309 			srhinfo->segs_left);
310 	if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
311 		printf(" last-entry-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ ? "!" : "",
312 			srhinfo->last_entry);
313 	if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
314 		printf(" last-entry-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT ? "!" : "",
315 			srhinfo->last_entry);
316 	if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
317 		printf(" last-entry-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT ? "!" : "",
318 			srhinfo->last_entry);
319 	if (srhinfo->mt_flags & IP6T_SRH_TAG)
320 		printf(" tag:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_TAG ? "!" : "",
321 			srhinfo->tag);
322 }
323 
srh1_print(const void * ip,const struct xt_entry_match * match,int numeric)324 static void srh1_print(const void *ip, const struct xt_entry_match *match, int numeric)
325 {
326 	const struct ip6t_srh1 *srhinfo = (struct ip6t_srh1 *)match->data;
327 
328 	printf(" srh");
329 	if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
330 		printf(" next-hdr:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR ? "!" : "",
331 			srhinfo->next_hdr);
332 	if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
333 		printf(" hdr-len-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ ? "!" : "",
334 			srhinfo->hdr_len);
335 	if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
336 		printf(" hdr-len-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT ? "!" : "",
337 			srhinfo->hdr_len);
338 	if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
339 		printf(" hdr-len-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT ? "!" : "",
340 			srhinfo->hdr_len);
341 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
342 		printf(" segs-left-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ ? "!" : "",
343 			srhinfo->segs_left);
344 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
345 		printf(" segs-left-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT ? "!" : "",
346 			srhinfo->segs_left);
347 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
348 		printf(" segs-left-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT ? "!" : "",
349 			srhinfo->segs_left);
350 	if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
351 		printf(" last-entry-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ ? "!" : "",
352 			srhinfo->last_entry);
353 	if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
354 		printf(" last-entry-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT ? "!" : "",
355 			srhinfo->last_entry);
356 	if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
357 		printf(" last-entry-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT ? "!" : "",
358 			srhinfo->last_entry);
359 	if (srhinfo->mt_flags & IP6T_SRH_TAG)
360 		printf(" tag:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_TAG ? "!" : "",
361 			srhinfo->tag);
362 	if (srhinfo->mt_flags & IP6T_SRH_PSID)
363 		printf(" psid %s %s/%u", srhinfo->mt_invflags & IP6T_SRH_INV_PSID ? "!" : "",
364 			xtables_ip6addr_to_numeric(&srhinfo->psid_addr),
365 			xtables_ip6mask_to_cidr(&srhinfo->psid_msk));
366 	if (srhinfo->mt_flags & IP6T_SRH_NSID)
367 		printf(" nsid %s %s/%u", srhinfo->mt_invflags & IP6T_SRH_INV_NSID ? "!" : "",
368 			xtables_ip6addr_to_numeric(&srhinfo->nsid_addr),
369 			xtables_ip6mask_to_cidr(&srhinfo->nsid_msk));
370 	if (srhinfo->mt_flags & IP6T_SRH_LSID)
371 		printf(" lsid %s %s/%u", srhinfo->mt_invflags & IP6T_SRH_INV_LSID ? "!" : "",
372 			xtables_ip6addr_to_numeric(&srhinfo->lsid_addr),
373 			xtables_ip6mask_to_cidr(&srhinfo->lsid_msk));
374 }
375 
srh_save(const void * ip,const struct xt_entry_match * match)376 static void srh_save(const void *ip, const struct xt_entry_match *match)
377 {
378 	const struct ip6t_srh *srhinfo = (struct ip6t_srh *)match->data;
379 
380 	if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
381 		printf("%s --srh-next-hdr %u", (srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR) ? " !" : "",
382 			srhinfo->next_hdr);
383 	if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
384 		printf("%s --srh-hdr-len-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ) ? " !" : "",
385 			srhinfo->hdr_len);
386 	if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
387 		printf("%s --srh-hdr-len-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT) ? " !" : "",
388 			srhinfo->hdr_len);
389 	if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
390 		printf("%s --srh-hdr-len-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT) ? " !" : "",
391 			srhinfo->hdr_len);
392 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
393 		printf("%s --srh-segs-left-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ) ? " !" : "",
394 			srhinfo->segs_left);
395 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
396 		printf("%s --srh-segs-left-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT) ? " !" : "",
397 			srhinfo->segs_left);
398 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
399 		printf("%s --srh-segs-left-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT) ? " !" : "",
400 			srhinfo->segs_left);
401 	if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
402 		printf("%s --srh-last-entry-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ) ? " !" : "",
403 			srhinfo->last_entry);
404 	if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
405 		printf("%s --srh-last-entry-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT) ? " !" : "",
406 			srhinfo->last_entry);
407 	if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
408 		printf("%s --srh-last-entry-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT) ? " !" : "",
409 			srhinfo->last_entry);
410 	if (srhinfo->mt_flags & IP6T_SRH_TAG)
411 		printf("%s --srh-tag %u", (srhinfo->mt_invflags & IP6T_SRH_INV_TAG) ? " !" : "",
412 			srhinfo->tag);
413 }
414 
srh1_save(const void * ip,const struct xt_entry_match * match)415 static void srh1_save(const void *ip, const struct xt_entry_match *match)
416 {
417 	const struct ip6t_srh1 *srhinfo = (struct ip6t_srh1 *)match->data;
418 
419 	if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
420 		printf("%s --srh-next-hdr %u", (srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR) ? " !" : "",
421 			srhinfo->next_hdr);
422 	if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
423 		printf("%s --srh-hdr-len-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ) ? " !" : "",
424 			srhinfo->hdr_len);
425 	if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
426 		printf("%s --srh-hdr-len-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT) ? " !" : "",
427 			srhinfo->hdr_len);
428 	if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
429 		printf("%s --srh-hdr-len-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT) ? " !" : "",
430 			srhinfo->hdr_len);
431 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
432 		printf("%s --srh-segs-left-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ) ? " !" : "",
433 			srhinfo->segs_left);
434 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
435 		printf("%s --srh-segs-left-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT) ? " !" : "",
436 			srhinfo->segs_left);
437 	if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
438 		printf("%s --srh-segs-left-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT) ? " !" : "",
439 			srhinfo->segs_left);
440 	if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
441 		printf("%s --srh-last-entry-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ) ? " !" : "",
442 			srhinfo->last_entry);
443 	if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
444 		printf("%s --srh-last-entry-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT) ? " !" : "",
445 			srhinfo->last_entry);
446 	if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
447 		printf("%s --srh-last-entry-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT) ? " !" : "",
448 			srhinfo->last_entry);
449 	if (srhinfo->mt_flags & IP6T_SRH_TAG)
450 		printf("%s --srh-tag %u", (srhinfo->mt_invflags & IP6T_SRH_INV_TAG) ? " !" : "",
451 			srhinfo->tag);
452 	if (srhinfo->mt_flags & IP6T_SRH_PSID)
453 		printf("%s --srh-psid %s/%u", srhinfo->mt_invflags & IP6T_SRH_INV_PSID ? " !" : "",
454 			xtables_ip6addr_to_numeric(&srhinfo->psid_addr),
455 			xtables_ip6mask_to_cidr(&srhinfo->psid_msk));
456 	if (srhinfo->mt_flags & IP6T_SRH_NSID)
457 		printf("%s --srh-nsid %s/%u", srhinfo->mt_invflags & IP6T_SRH_INV_NSID ? " !" : "",
458 			xtables_ip6addr_to_numeric(&srhinfo->nsid_addr),
459 			xtables_ip6mask_to_cidr(&srhinfo->nsid_msk));
460 	if (srhinfo->mt_flags & IP6T_SRH_LSID)
461 		printf("%s --srh-lsid %s/%u", srhinfo->mt_invflags & IP6T_SRH_INV_LSID ? " !" : "",
462 			xtables_ip6addr_to_numeric(&srhinfo->lsid_addr),
463 			xtables_ip6mask_to_cidr(&srhinfo->lsid_msk));
464 }
465 
466 static struct xtables_match srh_mt6_reg[] = {
467 	{
468 		.name		= "srh",
469 		.version	= XTABLES_VERSION,
470 		.revision	= 0,
471 		.family		= NFPROTO_IPV6,
472 		.size		= XT_ALIGN(sizeof(struct ip6t_srh)),
473 		.userspacesize	= XT_ALIGN(sizeof(struct ip6t_srh)),
474 		.help		= srh_help,
475 		.init		= srh_init,
476 		.print		= srh_print,
477 		.save		= srh_save,
478 		.x6_parse	= srh_parse,
479 		.x6_options	= srh_opts,
480 	},
481 	{
482 		.name		= "srh",
483 		.version	= XTABLES_VERSION,
484 		.revision	= 1,
485 		.family		= NFPROTO_IPV6,
486 		.size		= XT_ALIGN(sizeof(struct ip6t_srh1)),
487 		.userspacesize	= XT_ALIGN(sizeof(struct ip6t_srh1)),
488 		.help		= srh_help,
489 		.init		= srh1_init,
490 		.print		= srh1_print,
491 		.save		= srh1_save,
492 		.x6_parse	= srh1_parse,
493 		.x6_options	= srh1_opts,
494 	}
495 };
496 
497 void
_init(void)498 _init(void)
499 {
500 	xtables_register_matches(srh_mt6_reg, ARRAY_SIZE(srh_mt6_reg));
501 }
502