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>
31 struct xt_connmark_target_info {
42 static void CONNMARK_help(void)
45 "CONNMARK target options:\n"
46 " --set-mark value[/mask] Set conntrack mark value\n"
47 " --save-mark [--mask mask] Save the packet nfmark in the connection\n"
48 " --restore-mark [--mask mask] Restore saved nfmark value\n");
51 static const struct option CONNMARK_opts[] = {
52 { "set-mark", 1, NULL, '1' },
53 { "save-mark", 0, NULL, '2' },
54 { "restore-mark", 0, NULL, '3' },
55 { "mask", 1, NULL, '4' },
59 static const struct option connmark_tg_opts[] = {
60 {.name = "set-xmark", .has_arg = true, .val = '='},
61 {.name = "set-mark", .has_arg = true, .val = '-'},
62 {.name = "and-mark", .has_arg = true, .val = '&'},
63 {.name = "or-mark", .has_arg = true, .val = '|'},
64 {.name = "xor-mark", .has_arg = true, .val = '^'},
65 {.name = "save-mark", .has_arg = false, .val = 'S'},
66 {.name = "restore-mark", .has_arg = false, .val = 'R'},
67 {.name = "ctmask", .has_arg = true, .val = 'c'},
68 {.name = "nfmask", .has_arg = true, .val = 'n'},
69 {.name = "mask", .has_arg = true, .val = 'm'},
73 static void connmark_tg_help(void)
76 "CONNMARK target options:\n"
77 " --set-xmark value[/ctmask] Zero mask bits and XOR ctmark with value\n"
78 " --save-mark [--ctmask mask] [--nfmask mask]\n"
79 " Copy ctmark to nfmark using masks\n"
80 " --restore-mark [--ctmask mask] [--nfmask mask]\n"
81 " Copy nfmark to ctmark using masks\n"
82 " --set-mark value[/mask] Set conntrack mark value\n"
83 " --save-mark [--mask mask] Save the packet nfmark in the connection\n"
84 " --restore-mark [--mask mask] Restore saved nfmark value\n"
85 " --and-mark value Binary AND the ctmark with bits\n"
86 " --or-mark value Binary OR the ctmark with bits\n"
87 " --xor-mark value Binary XOR the ctmark with bits\n"
91 static void connmark_tg_init(struct xt_entry_target *target)
93 struct xt_connmark_tginfo1 *info = (void *)target->data;
96 * Need these defaults for --save-mark/--restore-mark if no
97 * --ctmark or --nfmask is given.
99 info->ctmask = UINT32_MAX;
100 info->nfmask = UINT32_MAX;
104 CONNMARK_parse(int c, char **argv, int invert, unsigned int *flags,
105 const void *entry, struct xt_entry_target **target)
107 struct xt_connmark_target_info *markinfo
108 = (struct xt_connmark_target_info *)(*target)->data;
113 markinfo->mode = XT_CONNMARK_SET;
115 markinfo->mark = strtoul(optarg, &end, 0);
116 if (*end == '/' && end[1] != '\0')
117 markinfo->mask = strtoul(end+1, &end, 0);
119 if (*end != '\0' || end == optarg)
120 xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
122 xtables_error(PARAMETER_PROBLEM,
123 "CONNMARK target: Can't specify --set-mark twice");
127 markinfo->mode = XT_CONNMARK_SAVE;
129 xtables_error(PARAMETER_PROBLEM,
130 "CONNMARK target: Can't specify --save-mark twice");
134 markinfo->mode = XT_CONNMARK_RESTORE;
136 xtables_error(PARAMETER_PROBLEM,
137 "CONNMARK target: Can't specify --restore-mark twice");
142 xtables_error(PARAMETER_PROBLEM,
143 "CONNMARK target: Can't specify --mask without a operation");
144 markinfo->mask = strtoul(optarg, &end, 0);
146 if (*end != '\0' || end == optarg)
147 xtables_error(PARAMETER_PROBLEM, "Bad MASK value \"%s\"", optarg);
156 static int connmark_tg_parse(int c, char **argv, int invert,
157 unsigned int *flags, const void *entry,
158 struct xt_entry_target **target)
160 struct xt_connmark_tginfo1 *info = (void *)(*target)->data;
161 unsigned int value, mask = UINT32_MAX;
165 case '=': /* --set-xmark */
166 case '-': /* --set-mark */
167 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
168 if (!xtables_strtoui(optarg, &end, &value, 0, UINT32_MAX))
169 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
171 if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
172 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
174 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
175 info->mode = XT_CONNMARK_SET;
176 info->ctmark = value;
179 info->ctmask |= value;
183 case '&': /* --and-mark */
184 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
185 if (!xtables_strtoui(optarg, NULL, &mask, 0, UINT32_MAX))
186 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--and-mark", optarg);
187 info->mode = XT_CONNMARK_SET;
189 info->ctmask = ~mask;
193 case '|': /* --or-mark */
194 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
195 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
196 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--or-mark", optarg);
197 info->mode = XT_CONNMARK_SET;
198 info->ctmark = value;
199 info->ctmask = value;
203 case '^': /* --xor-mark */
204 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
205 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
206 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--xor-mark", optarg);
207 info->mode = XT_CONNMARK_SET;
208 info->ctmark = value;
213 case 'S': /* --save-mark */
214 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
215 info->mode = XT_CONNMARK_SAVE;
216 *flags |= F_MARK | F_SR_MARK;
219 case 'R': /* --restore-mark */
220 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
221 info->mode = XT_CONNMARK_RESTORE;
222 *flags |= F_MARK | F_SR_MARK;
225 case 'n': /* --nfmask */
226 if (!(*flags & F_SR_MARK))
227 xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
228 "or --restore-mark is required for "
230 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
231 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--nfmask", optarg);
232 info->nfmask = value;
235 case 'c': /* --ctmask */
236 if (!(*flags & F_SR_MARK))
237 xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
238 "or --restore-mark is required for "
240 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
241 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--ctmask", optarg);
242 info->ctmask = value;
245 case 'm': /* --mask */
246 if (!(*flags & F_SR_MARK))
247 xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
248 "or --restore-mark is required for "
250 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
251 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--mask", optarg);
252 info->nfmask = info->ctmask = value;
259 static void connmark_tg_check(unsigned int flags)
262 xtables_error(PARAMETER_PROBLEM,
263 "CONNMARK target: No operation specified");
267 print_mark(unsigned long mark)
269 printf("0x%lx", mark);
273 print_mask(const char *text, unsigned long mask)
275 if (mask != 0xffffffffUL)
276 printf("%s0x%lx", text, mask);
279 static void CONNMARK_print(const void *ip,
280 const struct xt_entry_target *target, int numeric)
282 const struct xt_connmark_target_info *markinfo =
283 (const struct xt_connmark_target_info *)target->data;
284 switch (markinfo->mode) {
285 case XT_CONNMARK_SET:
286 printf("CONNMARK set ");
287 print_mark(markinfo->mark);
288 print_mask("/", markinfo->mask);
291 case XT_CONNMARK_SAVE:
292 printf("CONNMARK save ");
293 print_mask("mask ", markinfo->mask);
296 case XT_CONNMARK_RESTORE:
297 printf("CONNMARK restore ");
298 print_mask("mask ", markinfo->mask);
301 printf("ERROR: UNKNOWN CONNMARK MODE ");
307 connmark_tg_print(const void *ip, const struct xt_entry_target *target,
310 const struct xt_connmark_tginfo1 *info = (const void *)target->data;
312 switch (info->mode) {
313 case XT_CONNMARK_SET:
314 if (info->ctmark == 0)
315 printf("CONNMARK and 0x%x ",
316 (unsigned int)(u_int32_t)~info->ctmask);
317 else if (info->ctmark == info->ctmask)
318 printf("CONNMARK or 0x%x ", info->ctmark);
319 else if (info->ctmask == 0)
320 printf("CONNMARK xor 0x%x ", info->ctmark);
321 else if (info->ctmask == 0xFFFFFFFFU)
322 printf("CONNMARK set 0x%x ", info->ctmark);
324 printf("CONNMARK xset 0x%x/0x%x ",
325 info->ctmark, info->ctmask);
327 case XT_CONNMARK_SAVE:
328 if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
329 printf("CONNMARK save ");
330 else if (info->nfmask == info->ctmask)
331 printf("CONNMARK save mask 0x%x ", info->nfmask);
333 printf("CONNMARK save nfmask 0x%x ctmask ~0x%x ",
334 info->nfmask, info->ctmask);
336 case XT_CONNMARK_RESTORE:
337 if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
338 printf("CONNMARK restore ");
339 else if (info->ctmask == info->nfmask)
340 printf("CONNMARK restore mask 0x%x ", info->ctmask);
342 printf("CONNMARK restore ctmask 0x%x nfmask ~0x%x ",
343 info->ctmask, info->nfmask);
347 printf("ERROR: UNKNOWN CONNMARK MODE");
352 static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
354 const struct xt_connmark_target_info *markinfo =
355 (const struct xt_connmark_target_info *)target->data;
357 switch (markinfo->mode) {
358 case XT_CONNMARK_SET:
359 printf("--set-mark ");
360 print_mark(markinfo->mark);
361 print_mask("/", markinfo->mask);
364 case XT_CONNMARK_SAVE:
365 printf("--save-mark ");
366 print_mask("--mask ", markinfo->mask);
368 case XT_CONNMARK_RESTORE:
369 printf("--restore-mark ");
370 print_mask("--mask ", markinfo->mask);
373 printf("ERROR: UNKNOWN CONNMARK MODE ");
378 static void CONNMARK_init(struct xt_entry_target *t)
380 struct xt_connmark_target_info *markinfo
381 = (struct xt_connmark_target_info *)t->data;
383 markinfo->mask = 0xffffffffUL;
387 connmark_tg_save(const void *ip, const struct xt_entry_target *target)
389 const struct xt_connmark_tginfo1 *info = (const void *)target->data;
391 switch (info->mode) {
392 case XT_CONNMARK_SET:
393 printf("--set-xmark 0x%x/0x%x ", info->ctmark, info->ctmask);
395 case XT_CONNMARK_SAVE:
396 printf("--save-mark --nfmask 0x%x --ctmask 0x%x ",
397 info->nfmask, info->ctmask);
399 case XT_CONNMARK_RESTORE:
400 printf("--restore-mark --nfmask 0x%x --ctmask 0x%x ",
401 info->nfmask, info->ctmask);
404 printf("ERROR: UNKNOWN CONNMARK MODE");
409 static struct xtables_target connmark_tg_reg[] = {
411 .family = NFPROTO_UNSPEC,
414 .version = XTABLES_VERSION,
415 .size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
416 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
417 .help = CONNMARK_help,
418 .init = CONNMARK_init,
419 .parse = CONNMARK_parse,
420 .final_check = connmark_tg_check,
421 .print = CONNMARK_print,
422 .save = CONNMARK_save,
423 .extra_opts = CONNMARK_opts,
426 .version = XTABLES_VERSION,
429 .family = NFPROTO_UNSPEC,
430 .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
431 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
432 .help = connmark_tg_help,
433 .init = connmark_tg_init,
434 .parse = connmark_tg_parse,
435 .final_check = connmark_tg_check,
436 .print = connmark_tg_print,
437 .save = connmark_tg_save,
438 .extra_opts = connmark_tg_opts,
444 xtables_register_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));