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