1 /* Shared library add-on to iptables to add CONNMARK target support.
3 * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
4 * by Henrik Nordstrom <hno@marasystems.com>
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <linux/netfilter/x_tables.h>
29 #include <linux/netfilter/xt_CONNMARK.h>
36 /* Function which prints out usage message. */
37 static void CONNMARK_help(void)
40 "CONNMARK target options:\n"
41 " --set-mark value[/mask] Set conntrack mark value\n"
42 " --save-mark [--mask mask] Save the packet nfmark in the connection\n"
43 " --restore-mark [--mask mask] Restore saved nfmark value\n");
46 static const struct option CONNMARK_opts[] = {
47 { "set-mark", 1, NULL, '1' },
48 { "save-mark", 0, NULL, '2' },
49 { "restore-mark", 0, NULL, '3' },
50 { "mask", 1, NULL, '4' },
54 static const struct option connmark_tg_opts[] = {
55 {.name = "set-xmark", .has_arg = true, .val = '='},
56 {.name = "set-mark", .has_arg = true, .val = '-'},
57 {.name = "and-mark", .has_arg = true, .val = '&'},
58 {.name = "or-mark", .has_arg = true, .val = '|'},
59 {.name = "xor-mark", .has_arg = true, .val = '^'},
60 {.name = "save-mark", .has_arg = false, .val = 'S'},
61 {.name = "restore-mark", .has_arg = false, .val = 'R'},
62 {.name = "ctmask", .has_arg = true, .val = 'c'},
63 {.name = "nfmask", .has_arg = true, .val = 'n'},
64 {.name = "mask", .has_arg = true, .val = 'm'},
68 static void connmark_tg_help(void)
71 "CONNMARK target options:\n"
72 " --set-xmark value[/ctmask] Zero mask bits and XOR ctmark with value\n"
73 " --save-mark [--ctmask mask] [--nfmask mask]\n"
74 " Copy ctmark to nfmark using masks\n"
75 " --restore-mark [--ctmask mask] [--nfmask mask]\n"
76 " Copy nfmark to ctmark using masks\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 " --and-mark value Binary AND the ctmark with bits\n"
81 " --or-mark value Binary OR the ctmark with bits\n"
82 " --xor-mark value Binary XOR the ctmark with bits\n"
86 static void connmark_tg_init(struct xt_entry_target *target)
88 struct xt_connmark_tginfo1 *info = (void *)target->data;
91 * Need these defaults for --save-mark/--restore-mark if no
92 * --ctmark or --nfmask is given.
98 /* Function which parses command options; returns true if it
101 CONNMARK_parse(int c, char **argv, int invert, unsigned int *flags,
102 const void *entry, struct xt_entry_target **target)
104 struct xt_connmark_target_info *markinfo
105 = (struct xt_connmark_target_info *)(*target)->data;
110 markinfo->mode = XT_CONNMARK_SET;
112 markinfo->mark = strtoul(optarg, &end, 0);
113 if (*end == '/' && end[1] != '\0')
114 markinfo->mask = strtoul(end+1, &end, 0);
116 if (*end != '\0' || end == optarg)
117 exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
119 exit_error(PARAMETER_PROBLEM,
120 "CONNMARK target: Can't specify --set-mark twice");
124 markinfo->mode = XT_CONNMARK_SAVE;
126 exit_error(PARAMETER_PROBLEM,
127 "CONNMARK target: Can't specify --save-mark twice");
131 markinfo->mode = XT_CONNMARK_RESTORE;
133 exit_error(PARAMETER_PROBLEM,
134 "CONNMARK target: Can't specify --restore-mark twice");
139 exit_error(PARAMETER_PROBLEM,
140 "CONNMARK target: Can't specify --mask without a operation");
141 markinfo->mask = strtoul(optarg, &end, 0);
143 if (*end != '\0' || end == optarg)
144 exit_error(PARAMETER_PROBLEM, "Bad MASK value `%s'", optarg);
153 static int connmark_tg_parse(int c, char **argv, int invert,
154 unsigned int *flags, const void *entry,
155 struct xt_entry_target **target)
157 struct xt_connmark_tginfo1 *info = (void *)(*target)->data;
158 unsigned int value, mask = ~0U;
162 case '=': /* --set-xmark */
163 case '-': /* --set-mark */
164 param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
165 if (!strtonum(optarg, &end, &value, 0, ~0U))
166 param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
168 if (!strtonum(end + 1, &end, &mask, 0, ~0U))
169 param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
171 param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
172 info->mode = XT_CONNMARK_SET;
173 info->ctmark = value;
176 info->ctmask |= value;
180 case '&': /* --and-mark */
181 param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
182 if (!strtonum(optarg, NULL, &mask, 0, ~0U))
183 param_act(P_BAD_VALUE, "CONNMARK", "--and-mark", optarg);
184 info->mode = XT_CONNMARK_SET;
186 info->ctmask = ~mask;
190 case '|': /* --or-mark */
191 param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
192 if (!strtonum(optarg, NULL, &value, 0, ~0U))
193 param_act(P_BAD_VALUE, "CONNMARK", "--or-mark", optarg);
194 info->mode = XT_CONNMARK_SET;
195 info->ctmark = value;
196 info->ctmask = value;
200 case '^': /* --xor-mark */
201 param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
202 if (!strtonum(optarg, NULL, &value, 0, ~0U))
203 param_act(P_BAD_VALUE, "CONNMARK", "--xor-mark", optarg);
204 info->mode = XT_CONNMARK_SET;
205 info->ctmark = value;
210 case 'S': /* --save-mark */
211 param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
212 info->mode = XT_CONNMARK_SAVE;
213 *flags |= F_MARK | F_SR_MARK;
216 case 'R': /* --restore-mark */
217 param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
218 info->mode = XT_CONNMARK_RESTORE;
219 *flags |= F_MARK | F_SR_MARK;
222 case 'n': /* --nfmask */
223 if (!(*flags & F_SR_MARK))
224 exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
225 "or --restore-mark is required for "
227 if (!strtonum(optarg, NULL, &value, 0, ~0U))
228 param_act(P_BAD_VALUE, "CONNMARK", "--nfmask", optarg);
229 info->nfmask = value;
232 case 'c': /* --ctmask */
233 if (!(*flags & F_SR_MARK))
234 exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
235 "or --restore-mark is required for "
237 if (!strtonum(optarg, NULL, &value, 0, ~0U))
238 param_act(P_BAD_VALUE, "CONNMARK", "--ctmask", optarg);
239 info->ctmask = value;
242 case 'm': /* --mask */
243 if (!(*flags & F_SR_MARK))
244 exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
245 "or --restore-mark is required for "
247 if (!strtonum(optarg, NULL, &value, 0, ~0U))
248 param_act(P_BAD_VALUE, "CONNMARK", "--mask", optarg);
249 info->nfmask = info->ctmask = value;
256 static void connmark_tg_check(unsigned int flags)
259 exit_error(PARAMETER_PROBLEM,
260 "CONNMARK target: No operation specified");
264 print_mark(unsigned long mark)
266 printf("0x%lx", mark);
270 print_mask(const char *text, unsigned long mask)
272 if (mask != 0xffffffffUL)
273 printf("%s0x%lx", text, mask);
277 /* Prints out the target info. */
278 static void CONNMARK_print(const void *ip,
279 const struct xt_entry_target *target, int numeric)
281 const struct xt_connmark_target_info *markinfo =
282 (const struct xt_connmark_target_info *)target->data;
283 switch (markinfo->mode) {
284 case XT_CONNMARK_SET:
285 printf("CONNMARK set ");
286 print_mark(markinfo->mark);
287 print_mask("/", markinfo->mask);
290 case XT_CONNMARK_SAVE:
291 printf("CONNMARK save ");
292 print_mask("mask ", markinfo->mask);
295 case XT_CONNMARK_RESTORE:
296 printf("CONNMARK restore ");
297 print_mask("mask ", markinfo->mask);
300 printf("ERROR: UNKNOWN CONNMARK MODE ");
306 connmark_tg_print(const void *ip, const struct xt_entry_target *target,
309 const struct xt_connmark_tginfo1 *info = (const void *)target->data;
311 switch (info->mode) {
312 case XT_CONNMARK_SET:
313 if (info->ctmark == 0)
314 printf("CONNMARK and 0x%x ",
315 (unsigned int)(u_int32_t)~info->ctmask);
316 else if (info->ctmark == info->ctmask)
317 printf("CONNMARK or 0x%x ", info->ctmark);
318 else if (info->ctmask == 0)
319 printf("CONNMARK xor 0x%x ", info->ctmark);
321 printf("CONNMARK xset 0x%x/0x%x ",
322 info->ctmark, info->ctmask);
324 case XT_CONNMARK_SAVE:
325 if (info->nfmask == ~0U && info->ctmask == ~0U)
326 printf("CONNMARK save ");
327 else if (info->nfmask == info->ctmask)
328 printf("CONNMARK save mask 0x%x ", info->nfmask);
330 printf("CONNMARK save nfmask 0x%x ctmask ~0x%x ",
331 info->nfmask, info->ctmask);
333 case XT_CONNMARK_RESTORE:
334 if (info->ctmask == ~0U && info->nfmask == ~0U)
335 printf("CONNMARK restore ");
336 else if (info->ctmask == info->nfmask)
337 printf("CONNMARK restore mask 0x%x ", info->ctmask);
339 printf("CONNMARK restore ctmask 0x%x nfmask ~0x%x ",
340 info->ctmask, info->nfmask);
344 printf("ERROR: UNKNOWN CONNMARK MODE");
349 /* Saves the target into in parsable form to stdout. */
350 static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
352 const struct xt_connmark_target_info *markinfo =
353 (const struct xt_connmark_target_info *)target->data;
355 switch (markinfo->mode) {
356 case XT_CONNMARK_SET:
357 printf("--set-mark ");
358 print_mark(markinfo->mark);
359 print_mask("/", markinfo->mask);
362 case XT_CONNMARK_SAVE:
363 printf("--save-mark ");
364 print_mask("--mask ", markinfo->mask);
366 case XT_CONNMARK_RESTORE:
367 printf("--restore-mark ");
368 print_mask("--mask ", markinfo->mask);
371 printf("ERROR: UNKNOWN CONNMARK MODE ");
376 static void CONNMARK_init(struct xt_entry_target *t)
378 struct xt_connmark_target_info *markinfo
379 = (struct xt_connmark_target_info *)t->data;
381 markinfo->mask = 0xffffffffUL;
385 connmark_tg_save(const void *ip, const struct xt_entry_target *target)
387 const struct xt_connmark_tginfo1 *info = (const void *)target->data;
389 switch (info->mode) {
390 case XT_CONNMARK_SET:
391 printf("--set-xmark 0x%x/0x%x ", info->ctmark, info->ctmask);
393 case XT_CONNMARK_SAVE:
394 printf("--save-mark --nfmask 0x%x --ctmask 0x%x ",
395 info->nfmask, info->ctmask);
397 case XT_CONNMARK_RESTORE:
398 printf("--restore-mark --nfmask 0x%x --ctmask 0x%x ",
399 info->nfmask, info->ctmask);
402 printf("ERROR: UNKNOWN CONNMARK MODE");
407 static struct xtables_target connmark_target = {
411 .version = XTABLES_VERSION,
412 .size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
413 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
414 .help = CONNMARK_help,
415 .init = CONNMARK_init,
416 .parse = CONNMARK_parse,
417 .final_check = connmark_tg_check,
418 .print = CONNMARK_print,
419 .save = CONNMARK_save,
420 .extra_opts = CONNMARK_opts,
423 static struct xtables_target connmark_target6 = {
427 .version = XTABLES_VERSION,
428 .size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
429 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
430 .help = CONNMARK_help,
431 .init = CONNMARK_init,
432 .parse = CONNMARK_parse,
433 .final_check = connmark_tg_check,
434 .print = CONNMARK_print,
435 .save = CONNMARK_save,
436 .extra_opts = CONNMARK_opts,
439 static struct xtables_target connmark_tg_reg = {
440 .version = XTABLES_VERSION,
444 .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
445 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
446 .help = connmark_tg_help,
447 .init = connmark_tg_init,
448 .parse = connmark_tg_parse,
449 .final_check = connmark_tg_check,
450 .print = connmark_tg_print,
451 .save = connmark_tg_save,
452 .extra_opts = connmark_tg_opts,
455 static struct xtables_target connmark_tg6_reg = {
456 .version = XTABLES_VERSION,
460 .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
461 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
462 .help = connmark_tg_help,
463 .init = connmark_tg_init,
464 .parse = connmark_tg_parse,
465 .final_check = connmark_tg_check,
466 .print = connmark_tg_print,
467 .save = connmark_tg_save,
468 .extra_opts = connmark_tg_opts,
473 xtables_register_target(&connmark_target);
474 xtables_register_target(&connmark_target6);
475 xtables_register_target(&connmark_tg_reg);
476 xtables_register_target(&connmark_tg6_reg);