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