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