xref: /aosp_15_r20/external/iptables/extensions/libxt_CONNMARK.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
1 /* Shared library add-on to iptables to add CONNMARK target support.
2  *
3  * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
4  * by Henrik Nordstrom <[email protected]>
5  *
6  * Version 1.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  */
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <xtables.h>
26 #include <linux/netfilter/xt_CONNMARK.h>
27 
28 struct xt_connmark_target_info {
29 	unsigned long mark;
30 	unsigned long mask;
31 	uint8_t mode;
32 };
33 
34 enum {
35 	D_SHIFT_LEFT = 0,
36 	D_SHIFT_RIGHT,
37 };
38 
39 enum {
40 	O_SET_MARK = 0,
41 	O_SAVE_MARK,
42 	O_RESTORE_MARK,
43 	O_AND_MARK,
44 	O_OR_MARK,
45 	O_XOR_MARK,
46 	O_LEFT_SHIFT_MARK,
47 	O_RIGHT_SHIFT_MARK,
48 	O_SET_XMARK,
49 	O_CTMASK,
50 	O_NFMASK,
51 	O_MASK,
52 	F_SET_MARK         = 1 << O_SET_MARK,
53 	F_SAVE_MARK        = 1 << O_SAVE_MARK,
54 	F_RESTORE_MARK     = 1 << O_RESTORE_MARK,
55 	F_AND_MARK         = 1 << O_AND_MARK,
56 	F_OR_MARK          = 1 << O_OR_MARK,
57 	F_XOR_MARK         = 1 << O_XOR_MARK,
58 	F_LEFT_SHIFT_MARK  = 1 << O_LEFT_SHIFT_MARK,
59 	F_RIGHT_SHIFT_MARK = 1 << O_RIGHT_SHIFT_MARK,
60 	F_SET_XMARK        = 1 << O_SET_XMARK,
61 	F_CTMASK           = 1 << O_CTMASK,
62 	F_NFMASK           = 1 << O_NFMASK,
63 	F_MASK             = 1 << O_MASK,
64 	F_OP_ANY           = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK |
65 	                     F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK,
66 };
67 
68 static const char *const xt_connmark_shift_ops[] = {
69 	"left-shift-mark",
70 	"right-shift-mark"
71 };
72 
CONNMARK_help(void)73 static void CONNMARK_help(void)
74 {
75 	printf(
76 "CONNMARK target options:\n"
77 "  --set-mark value[/mask]       Set conntrack mark value\n"
78 "  --save-mark [--mask mask]     Save the packet nfmark in the connection\n"
79 "  --restore-mark [--mask mask]  Restore saved nfmark value\n");
80 }
81 
82 #define s struct xt_connmark_target_info
83 static const struct xt_option_entry CONNMARK_opts[] = {
84 	{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
85 	 .excl = F_OP_ANY},
86 	{.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
87 	 .excl = F_OP_ANY},
88 	{.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
89 	 .excl = F_OP_ANY},
90 	{.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32},
91 	XTOPT_TABLEEND,
92 };
93 #undef s
94 
95 #define s struct xt_connmark_tginfo1
96 static const struct xt_option_entry connmark_tg_opts[] = {
97 	{.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
98 	 .excl = F_OP_ANY},
99 	{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
100 	 .excl = F_OP_ANY},
101 	{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
102 	 .excl = F_OP_ANY},
103 	{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
104 	 .excl = F_OP_ANY},
105 	{.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
106 	 .excl = F_OP_ANY},
107 	{.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
108 	 .excl = F_OP_ANY},
109 	{.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
110 	 .excl = F_OP_ANY},
111 	{.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32,
112 	 .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)},
113 	{.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32,
114 	 .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
115 	{.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
116 	 .excl = F_CTMASK | F_NFMASK},
117 	XTOPT_TABLEEND,
118 };
119 #undef s
120 
121 #define s struct xt_connmark_tginfo2
122 static const struct xt_option_entry connmark_tg_opts_v2[] = {
123 	{.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
124 	 .excl = F_OP_ANY},
125 	{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
126 	 .excl = F_OP_ANY},
127 	{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
128 	 .excl = F_OP_ANY},
129 	{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
130 	 .excl = F_OP_ANY},
131 	{.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
132 	 .excl = F_OP_ANY},
133 	{.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
134 	 .excl = F_OP_ANY},
135 	{.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
136 	 .excl = F_OP_ANY},
137 	{.name = "left-shift-mark", .id = O_LEFT_SHIFT_MARK, .type = XTTYPE_UINT8,
138 	 .min = 0, .max = 32},
139 	{.name = "right-shift-mark", .id = O_RIGHT_SHIFT_MARK, .type = XTTYPE_UINT8,
140 	 .min = 0, .max = 32},
141 	{.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32,
142 	 .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)},
143 	{.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32,
144 	 .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
145 	{.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
146 	 .excl = F_CTMASK | F_NFMASK},
147 	XTOPT_TABLEEND,
148 };
149 #undef s
150 
connmark_tg_help(void)151 static void connmark_tg_help(void)
152 {
153 	printf(
154 "CONNMARK target options:\n"
155 "  --set-xmark value[/ctmask]    Zero mask bits and XOR ctmark with value\n"
156 "  --save-mark [--ctmask mask] [--nfmask mask]\n"
157 "                                Copy ctmark to nfmark using masks\n"
158 "  --restore-mark [--ctmask mask] [--nfmask mask]\n"
159 "                                Copy nfmark to ctmark using masks\n"
160 "  --set-mark value[/mask]       Set conntrack mark value\n"
161 "  --save-mark [--mask mask]     Save the packet nfmark in the connection\n"
162 "  --restore-mark [--mask mask]  Restore saved nfmark value\n"
163 "  --and-mark value              Binary AND the ctmark with bits\n"
164 "  --or-mark value               Binary OR  the ctmark with bits\n"
165 "  --xor-mark value              Binary XOR the ctmark with bits\n"
166 );
167 }
168 
connmark_tg_help_v2(void)169 static void connmark_tg_help_v2(void)
170 {
171 	connmark_tg_help();
172 	printf(
173 "  --left-shift-mark value       Left shift the ctmark with bits\n"
174 "  --right-shift-mark value      Right shift the ctmark with bits\n"
175 );
176 }
177 
connmark_tg_init(struct xt_entry_target * target)178 static void connmark_tg_init(struct xt_entry_target *target)
179 {
180 	struct xt_connmark_tginfo1 *info = (void *)target->data;
181 
182 	/*
183 	 * Need these defaults for --save-mark/--restore-mark if no
184 	 * --ctmark or --nfmask is given.
185 	 */
186 	info->ctmask = UINT32_MAX;
187 	info->nfmask = UINT32_MAX;
188 }
189 
connmark_tg_init_v2(struct xt_entry_target * target)190 static void connmark_tg_init_v2(struct xt_entry_target *target)
191 {
192 	struct xt_connmark_tginfo2 *info;
193 
194 	connmark_tg_init(target);
195 	info = (void *)target->data;
196 
197 	/* Left shift by zero bit by default. */
198 	info->shift_dir = D_SHIFT_LEFT;
199 	info->shift_bits = 0;
200 }
201 
CONNMARK_parse(struct xt_option_call * cb)202 static void CONNMARK_parse(struct xt_option_call *cb)
203 {
204 	struct xt_connmark_target_info *markinfo = cb->data;
205 
206 	xtables_option_parse(cb);
207 	switch (cb->entry->id) {
208 	case O_SET_MARK:
209 		markinfo->mode = XT_CONNMARK_SET;
210 		markinfo->mark = cb->val.mark;
211 		markinfo->mask = cb->val.mask;
212 		break;
213 	case O_SAVE_MARK:
214 		markinfo->mode = XT_CONNMARK_SAVE;
215 		break;
216 	case O_RESTORE_MARK:
217 		markinfo->mode = XT_CONNMARK_RESTORE;
218 		break;
219 	case O_MASK:
220 		markinfo->mask = cb->val.u32;
221 		break;
222 	}
223 }
224 
connmark_tg_parse(struct xt_option_call * cb)225 static void connmark_tg_parse(struct xt_option_call *cb)
226 {
227 	struct xt_connmark_tginfo1 *info = cb->data;
228 
229 	xtables_option_parse(cb);
230 	switch (cb->entry->id) {
231 	case O_SET_XMARK:
232 		info->mode   = XT_CONNMARK_SET;
233 		info->ctmark = cb->val.mark;
234 		info->ctmask = cb->val.mask;
235 		break;
236 	case O_SET_MARK:
237 		info->mode   = XT_CONNMARK_SET;
238 		info->ctmark = cb->val.mark;
239 		info->ctmask = cb->val.mark | cb->val.mask;
240 		break;
241 	case O_AND_MARK:
242 		info->mode   = XT_CONNMARK_SET;
243 		info->ctmark = 0;
244 		info->ctmask = ~cb->val.u32;
245 		break;
246 	case O_OR_MARK:
247 		info->mode   = XT_CONNMARK_SET;
248 		info->ctmark = cb->val.u32;
249 		info->ctmask = cb->val.u32;
250 		break;
251 	case O_XOR_MARK:
252 		info->mode   = XT_CONNMARK_SET;
253 		info->ctmark = cb->val.u32;
254 		info->ctmask = 0;
255 		break;
256 	case O_SAVE_MARK:
257 		info->mode = XT_CONNMARK_SAVE;
258 		break;
259 	case O_RESTORE_MARK:
260 		info->mode = XT_CONNMARK_RESTORE;
261 		break;
262 	case O_MASK:
263 		info->nfmask = info->ctmask = cb->val.u32;
264 		break;
265 	default:
266 		break;
267 	}
268 }
269 
connmark_tg_parse_v2(struct xt_option_call * cb)270 static void connmark_tg_parse_v2(struct xt_option_call *cb)
271 {
272 	struct xt_connmark_tginfo2 *info = cb->data;
273 
274 	xtables_option_parse(cb);
275 	switch (cb->entry->id) {
276 	case O_SET_XMARK:
277 		info->mode   = XT_CONNMARK_SET;
278 		info->ctmark = cb->val.mark;
279 		info->ctmask = cb->val.mask;
280 		break;
281 	case O_SET_MARK:
282 		info->mode   = XT_CONNMARK_SET;
283 		info->ctmark = cb->val.mark;
284 		info->ctmask = cb->val.mark | cb->val.mask;
285 		break;
286 	case O_AND_MARK:
287 		info->mode   = XT_CONNMARK_SET;
288 		info->ctmark = 0;
289 		info->ctmask = ~cb->val.u32;
290 		break;
291 	case O_OR_MARK:
292 		info->mode   = XT_CONNMARK_SET;
293 		info->ctmark = cb->val.u32;
294 		info->ctmask = cb->val.u32;
295 		break;
296 	case O_XOR_MARK:
297 		info->mode   = XT_CONNMARK_SET;
298 		info->ctmark = cb->val.u32;
299 		info->ctmask = 0;
300 		break;
301 	case O_SAVE_MARK:
302 		info->mode = XT_CONNMARK_SAVE;
303 		break;
304 	case O_RESTORE_MARK:
305 		info->mode = XT_CONNMARK_RESTORE;
306 		break;
307 	case O_MASK:
308 		info->nfmask = info->ctmask = cb->val.u32;
309 		break;
310 	case O_LEFT_SHIFT_MARK:
311 		info->shift_dir = D_SHIFT_LEFT;
312 		info->shift_bits = cb->val.u8;
313 		break;
314 	case O_RIGHT_SHIFT_MARK:
315 		info->shift_dir = D_SHIFT_RIGHT;
316 		info->shift_bits = cb->val.u8;
317 		break;
318 	default:
319 		break;
320 	}
321 }
322 
connmark_tg_check(struct xt_fcheck_call * cb)323 static void connmark_tg_check(struct xt_fcheck_call *cb)
324 {
325 	if (!(cb->xflags & F_OP_ANY))
326 		xtables_error(PARAMETER_PROBLEM,
327 		           "CONNMARK target: No operation specified");
328 }
329 
330 static void
print_mark(unsigned long mark)331 print_mark(unsigned long mark)
332 {
333 	printf("0x%lx", mark);
334 }
335 
336 static void
print_mask(const char * text,unsigned long mask)337 print_mask(const char *text, unsigned long mask)
338 {
339 	if (mask != 0xffffffffUL)
340 		printf("%s0x%lx", text, mask);
341 }
342 
CONNMARK_print(const void * ip,const struct xt_entry_target * target,int numeric)343 static void CONNMARK_print(const void *ip,
344                            const struct xt_entry_target *target, int numeric)
345 {
346 	const struct xt_connmark_target_info *markinfo =
347 		(const struct xt_connmark_target_info *)target->data;
348 	switch (markinfo->mode) {
349 	case XT_CONNMARK_SET:
350 	    printf(" CONNMARK set ");
351 	    print_mark(markinfo->mark);
352 	    print_mask("/", markinfo->mask);
353 	    break;
354 	case XT_CONNMARK_SAVE:
355 	    printf(" CONNMARK save ");
356 	    print_mask("mask ", markinfo->mask);
357 	    break;
358 	case XT_CONNMARK_RESTORE:
359 	    printf(" CONNMARK restore ");
360 	    print_mask("mask ", markinfo->mask);
361 	    break;
362 	default:
363 	    printf(" ERROR: UNKNOWN CONNMARK MODE");
364 	    break;
365 	}
366 }
367 
368 static void
connmark_tg_print(const void * ip,const struct xt_entry_target * target,int numeric)369 connmark_tg_print(const void *ip, const struct xt_entry_target *target,
370                   int numeric)
371 {
372 	const struct xt_connmark_tginfo1 *info = (const void *)target->data;
373 
374 	switch (info->mode) {
375 	case XT_CONNMARK_SET:
376 		if (info->ctmark == 0)
377 			printf(" CONNMARK and 0x%x",
378 			       (unsigned int)(uint32_t)~info->ctmask);
379 		else if (info->ctmark == info->ctmask)
380 			printf(" CONNMARK or 0x%x", info->ctmark);
381 		else if (info->ctmask == 0)
382 			printf(" CONNMARK xor 0x%x", info->ctmark);
383 		else if (info->ctmask == 0xFFFFFFFFU)
384 			printf(" CONNMARK set 0x%x", info->ctmark);
385 		else
386 			printf(" CONNMARK xset 0x%x/0x%x",
387 			       info->ctmark, info->ctmask);
388 		break;
389 	case XT_CONNMARK_SAVE:
390 		if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
391 			printf(" CONNMARK save");
392 		else if (info->nfmask == info->ctmask)
393 			printf(" CONNMARK save mask 0x%x", info->nfmask);
394 		else
395 			printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x",
396 			       info->nfmask, info->ctmask);
397 		break;
398 	case XT_CONNMARK_RESTORE:
399 		if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
400 			printf(" CONNMARK restore");
401 		else if (info->ctmask == info->nfmask)
402 			printf(" CONNMARK restore mask 0x%x", info->ctmask);
403 		else
404 			printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x",
405 			       info->ctmask, info->nfmask);
406 		break;
407 
408 	default:
409 		printf(" ERROR: UNKNOWN CONNMARK MODE");
410 		break;
411 	}
412 }
413 
414 static void
connmark_tg_print_v2(const void * ip,const struct xt_entry_target * target,int numeric)415 connmark_tg_print_v2(const void *ip, const struct xt_entry_target *target,
416                   int numeric)
417 {
418 	const struct xt_connmark_tginfo2 *info = (const void *)target->data;
419 	const char *shift_op = xt_connmark_shift_ops[info->shift_dir];
420 
421 	switch (info->mode) {
422 	case XT_CONNMARK_SET:
423 		if (info->ctmark == 0)
424 			printf(" CONNMARK and 0x%x",
425 			       (unsigned int)(uint32_t)~info->ctmask);
426 		else if (info->ctmark == info->ctmask)
427 			printf(" CONNMARK or 0x%x", info->ctmark);
428 		else if (info->ctmask == 0)
429 			printf(" CONNMARK xor 0x%x", info->ctmark);
430 		else if (info->ctmask == 0xFFFFFFFFU)
431 			printf(" CONNMARK set 0x%x", info->ctmark);
432 		else
433 			printf(" CONNMARK xset 0x%x/0x%x",
434 			       info->ctmark, info->ctmask);
435 		break;
436 	case XT_CONNMARK_SAVE:
437 		if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
438 			printf(" CONNMARK save");
439 		else if (info->nfmask == info->ctmask)
440 			printf(" CONNMARK save mask 0x%x", info->nfmask);
441 		else
442 			printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x",
443 			       info->nfmask, info->ctmask);
444 		break;
445 	case XT_CONNMARK_RESTORE:
446 		if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
447 			printf(" CONNMARK restore");
448 		else if (info->ctmask == info->nfmask)
449 			printf(" CONNMARK restore mask 0x%x", info->ctmask);
450 		else
451 			printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x",
452 			       info->ctmask, info->nfmask);
453 		break;
454 
455 	default:
456 		printf(" ERROR: UNKNOWN CONNMARK MODE");
457 		break;
458 	}
459 
460 	if (info->mode <= XT_CONNMARK_RESTORE &&
461 	    info->shift_bits != 0) {
462 		printf(" %s %u", shift_op, info->shift_bits);
463 	}
464 }
465 
CONNMARK_save(const void * ip,const struct xt_entry_target * target)466 static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
467 {
468 	const struct xt_connmark_target_info *markinfo =
469 		(const struct xt_connmark_target_info *)target->data;
470 
471 	switch (markinfo->mode) {
472 	case XT_CONNMARK_SET:
473 	    printf(" --set-mark ");
474 	    print_mark(markinfo->mark);
475 	    print_mask("/", markinfo->mask);
476 	    break;
477 	case XT_CONNMARK_SAVE:
478 	    printf(" --save-mark ");
479 	    print_mask("--mask ", markinfo->mask);
480 	    break;
481 	case XT_CONNMARK_RESTORE:
482 	    printf(" --restore-mark ");
483 	    print_mask("--mask ", markinfo->mask);
484 	    break;
485 	default:
486 	    printf(" ERROR: UNKNOWN CONNMARK MODE");
487 	    break;
488 	}
489 }
490 
CONNMARK_init(struct xt_entry_target * t)491 static void CONNMARK_init(struct xt_entry_target *t)
492 {
493 	struct xt_connmark_target_info *markinfo
494 		= (struct xt_connmark_target_info *)t->data;
495 
496 	markinfo->mask = 0xffffffffUL;
497 }
498 
499 static void
connmark_tg_save(const void * ip,const struct xt_entry_target * target)500 connmark_tg_save(const void *ip, const struct xt_entry_target *target)
501 {
502 	const struct xt_connmark_tginfo1 *info = (const void *)target->data;
503 
504 	switch (info->mode) {
505 	case XT_CONNMARK_SET:
506 		printf(" --set-xmark 0x%x/0x%x", info->ctmark, info->ctmask);
507 		break;
508 	case XT_CONNMARK_SAVE:
509 		printf(" --save-mark --nfmask 0x%x --ctmask 0x%x",
510 		       info->nfmask, info->ctmask);
511 		break;
512 	case XT_CONNMARK_RESTORE:
513 		printf(" --restore-mark --nfmask 0x%x --ctmask 0x%x",
514 		       info->nfmask, info->ctmask);
515 		break;
516 	default:
517 		printf(" ERROR: UNKNOWN CONNMARK MODE");
518 		break;
519 	}
520 }
521 
522 static void
connmark_tg_save_v2(const void * ip,const struct xt_entry_target * target)523 connmark_tg_save_v2(const void *ip, const struct xt_entry_target *target)
524 {
525 	const struct xt_connmark_tginfo2 *info = (const void *)target->data;
526 	const char *shift_op = xt_connmark_shift_ops[info->shift_dir];
527 
528 	switch (info->mode) {
529 	case XT_CONNMARK_SET:
530 		printf(" --set-xmark 0x%x/0x%x", info->ctmark, info->ctmask);
531 		break;
532 	case XT_CONNMARK_SAVE:
533 		printf(" --save-mark --nfmask 0x%x --ctmask 0x%x",
534 		       info->nfmask, info->ctmask);
535 		break;
536 	case XT_CONNMARK_RESTORE:
537 		printf(" --restore-mark --nfmask 0x%x --ctmask 0x%x",
538 		       info->nfmask, info->ctmask);
539 		break;
540 	default:
541 		printf(" ERROR: UNKNOWN CONNMARK MODE");
542 		break;
543 	}
544 
545 	if (info->mode <= XT_CONNMARK_RESTORE &&
546 	    info->shift_bits != 0) {
547 		printf(" --%s %u", shift_op, info->shift_bits);
548 	}
549 }
550 
connmark_tg_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)551 static int connmark_tg_xlate(struct xt_xlate *xl,
552 			     const struct xt_xlate_tg_params *params)
553 {
554 	const struct xt_connmark_tginfo1 *info =
555 		(const void *)params->target->data;
556 
557 	switch (info->mode) {
558 	case XT_CONNMARK_SET:
559 		xt_xlate_add(xl, "ct mark set ");
560 		if (info->ctmask == 0xFFFFFFFFU)
561 			xt_xlate_add(xl, "0x%x ", info->ctmark);
562 		else if (info->ctmark == 0)
563 			xt_xlate_add(xl, "ct mark and 0x%x", ~info->ctmask);
564 		else if (info->ctmark == info->ctmask)
565 			xt_xlate_add(xl, "ct mark or 0x%x",
566 				     info->ctmark);
567 		else if (info->ctmask == 0)
568 			xt_xlate_add(xl, "ct mark xor 0x%x",
569 				     info->ctmark);
570 		else
571 			xt_xlate_add(xl, "ct mark xor 0x%x and 0x%x",
572 				     info->ctmark, ~info->ctmask);
573 		break;
574 	case XT_CONNMARK_SAVE:
575 		if (info->nfmask == info->ctmask &&
576 		    info->nfmask == UINT32_MAX)
577 			xt_xlate_add(xl, "ct mark set mark");
578 		else
579 			return 0;
580 		break;
581 	case XT_CONNMARK_RESTORE:
582 		if (info->nfmask == info->ctmask &&
583 		    info->nfmask == UINT32_MAX)
584 			xt_xlate_add(xl, "meta mark set ct mark");
585 		else
586 			return 0;
587 		break;
588 	}
589 
590 	return 1;
591 }
592 
connmark_tg_xlate_v2(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)593 static int connmark_tg_xlate_v2(struct xt_xlate *xl,
594 			     const struct xt_xlate_tg_params *params)
595 {
596 	const struct xt_connmark_tginfo2 *info =
597 		(const void *)params->target->data;
598 	const char *braces = info->shift_bits ? "( " : "";
599 
600 	switch (info->mode) {
601 	case XT_CONNMARK_SET:
602 		xt_xlate_add(xl, "ct mark set %s", braces);
603 		if (info->ctmask == 0xFFFFFFFFU)
604 			xt_xlate_add(xl, "0x%x ", info->ctmark);
605 		else if (info->ctmark == 0)
606 			xt_xlate_add(xl, "ct mark and 0x%x", ~info->ctmask);
607 		else if (info->ctmark == info->ctmask)
608 			xt_xlate_add(xl, "ct mark or 0x%x",
609 				     info->ctmark);
610 		else if (info->ctmask == 0)
611 			xt_xlate_add(xl, "ct mark xor 0x%x",
612 				     info->ctmark);
613 		else
614 			xt_xlate_add(xl, "ct mark xor 0x%x and 0x%x",
615 				     info->ctmark, ~info->ctmask);
616 		break;
617 	case XT_CONNMARK_SAVE:
618 		xt_xlate_add(xl, "ct mark set %smark", braces);
619 		if (!(info->nfmask == UINT32_MAX &&
620 		    info->ctmask == UINT32_MAX)) {
621 			if (info->nfmask == info->ctmask)
622 				xt_xlate_add(xl, " and 0x%x", info->nfmask);
623 			else
624 				return 0;
625 		}
626 		break;
627 	case XT_CONNMARK_RESTORE:
628 		xt_xlate_add(xl, "meta mark set %sct mark", braces);
629 		if (!(info->nfmask == UINT32_MAX &&
630 		    info->ctmask == UINT32_MAX)) {
631 			if (info->nfmask == info->ctmask)
632 				xt_xlate_add(xl, " and 0x%x", info->nfmask);
633 			else
634 				return 0;
635 		}
636 		break;
637 	}
638 
639 	if (info->mode <= XT_CONNMARK_RESTORE &&
640 	    info->shift_bits != 0) {
641 		xt_xlate_add(xl, " ) %s %u",
642 			     info->shift_dir ? ">>" : "<<", info->shift_bits);
643 	}
644 
645 	return 1;
646 }
647 static struct xtables_target connmark_tg_reg[] = {
648 	{
649 		.family        = NFPROTO_UNSPEC,
650 		.name          = "CONNMARK",
651 		.revision      = 0,
652 		.version       = XTABLES_VERSION,
653 		.size          = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
654 		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
655 		.help          = CONNMARK_help,
656 		.init          = CONNMARK_init,
657 		.print         = CONNMARK_print,
658 		.save          = CONNMARK_save,
659 		.x6_parse      = CONNMARK_parse,
660 		.x6_fcheck     = connmark_tg_check,
661 		.x6_options    = CONNMARK_opts,
662 	},
663 	{
664 		.version       = XTABLES_VERSION,
665 		.name          = "CONNMARK",
666 		.revision      = 1,
667 		.family        = NFPROTO_UNSPEC,
668 		.size          = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
669 		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
670 		.help          = connmark_tg_help,
671 		.init          = connmark_tg_init,
672 		.print         = connmark_tg_print,
673 		.save          = connmark_tg_save,
674 		.x6_parse      = connmark_tg_parse,
675 		.x6_fcheck     = connmark_tg_check,
676 		.x6_options    = connmark_tg_opts,
677 		.xlate         = connmark_tg_xlate,
678 	},
679 	{
680 		.version       = XTABLES_VERSION,
681 		.name          = "CONNMARK",
682 		.revision      = 2,
683 		.family        = NFPROTO_UNSPEC,
684 		.size          = XT_ALIGN(sizeof(struct xt_connmark_tginfo2)),
685 		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo2)),
686 		.help          = connmark_tg_help_v2,
687 		.init          = connmark_tg_init_v2,
688 		.print         = connmark_tg_print_v2,
689 		.save          = connmark_tg_save_v2,
690 		.x6_parse      = connmark_tg_parse_v2,
691 		.x6_fcheck     = connmark_tg_check,
692 		.x6_options    = connmark_tg_opts_v2,
693 		.xlate         = connmark_tg_xlate_v2,
694 	},
695 };
696 
_init(void)697 void _init(void)
698 {
699 	xtables_register_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
700 }
701