123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- /* Shared library add-on to iptables to add CONNMARK target support.
- *
- * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
- * by Henrik Nordstrom <hno@marasystems.com>
- *
- * Version 1.1
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <stdbool.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <xtables.h>
- #include <linux/netfilter/xt_CONNMARK.h>
- struct xt_connmark_target_info {
- unsigned long mark;
- unsigned long mask;
- uint8_t mode;
- };
- enum {
- O_SET_MARK = 0,
- O_SAVE_MARK,
- O_RESTORE_MARK,
- O_AND_MARK,
- O_OR_MARK,
- O_XOR_MARK,
- O_SET_XMARK,
- O_CTMASK,
- O_NFMASK,
- O_MASK,
- F_SET_MARK = 1 << O_SET_MARK,
- F_SAVE_MARK = 1 << O_SAVE_MARK,
- F_RESTORE_MARK = 1 << O_RESTORE_MARK,
- F_AND_MARK = 1 << O_AND_MARK,
- F_OR_MARK = 1 << O_OR_MARK,
- F_XOR_MARK = 1 << O_XOR_MARK,
- F_SET_XMARK = 1 << O_SET_XMARK,
- F_CTMASK = 1 << O_CTMASK,
- F_NFMASK = 1 << O_NFMASK,
- F_MASK = 1 << O_MASK,
- F_OP_ANY = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK |
- F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK,
- };
- static void CONNMARK_help(void)
- {
- printf(
- "CONNMARK target options:\n"
- " --set-mark value[/mask] Set conntrack mark value\n"
- " --save-mark [--mask mask] Save the packet nfmark in the connection\n"
- " --restore-mark [--mask mask] Restore saved nfmark value\n");
- }
- #define s struct xt_connmark_target_info
- static const struct xt_option_entry CONNMARK_opts[] = {
- {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
- .excl = F_OP_ANY},
- {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
- .excl = F_OP_ANY},
- {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
- .excl = F_OP_ANY},
- {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32},
- XTOPT_TABLEEND,
- };
- #undef s
- #define s struct xt_connmark_tginfo1
- static const struct xt_option_entry connmark_tg_opts[] = {
- {.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
- .excl = F_OP_ANY},
- {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
- .excl = F_OP_ANY},
- {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
- .excl = F_OP_ANY},
- {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
- .excl = F_OP_ANY},
- {.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
- .excl = F_OP_ANY},
- {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
- .excl = F_OP_ANY},
- {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
- .excl = F_OP_ANY},
- {.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32,
- .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)},
- {.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32,
- .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
- {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
- .excl = F_CTMASK | F_NFMASK},
- XTOPT_TABLEEND,
- };
- #undef s
- static void connmark_tg_help(void)
- {
- printf(
- "CONNMARK target options:\n"
- " --set-xmark value[/ctmask] Zero mask bits and XOR ctmark with value\n"
- " --save-mark [--ctmask mask] [--nfmask mask]\n"
- " Copy ctmark to nfmark using masks\n"
- " --restore-mark [--ctmask mask] [--nfmask mask]\n"
- " Copy nfmark to ctmark using masks\n"
- " --set-mark value[/mask] Set conntrack mark value\n"
- " --save-mark [--mask mask] Save the packet nfmark in the connection\n"
- " --restore-mark [--mask mask] Restore saved nfmark value\n"
- " --and-mark value Binary AND the ctmark with bits\n"
- " --or-mark value Binary OR the ctmark with bits\n"
- " --xor-mark value Binary XOR the ctmark with bits\n"
- );
- }
- static void connmark_tg_init(struct xt_entry_target *target)
- {
- struct xt_connmark_tginfo1 *info = (void *)target->data;
- /*
- * Need these defaults for --save-mark/--restore-mark if no
- * --ctmark or --nfmask is given.
- */
- info->ctmask = UINT32_MAX;
- info->nfmask = UINT32_MAX;
- }
- static void CONNMARK_parse(struct xt_option_call *cb)
- {
- struct xt_connmark_target_info *markinfo = cb->data;
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_SET_MARK:
- markinfo->mode = XT_CONNMARK_SET;
- markinfo->mark = cb->val.mark;
- markinfo->mask = cb->val.mask;
- break;
- case O_SAVE_MARK:
- markinfo->mode = XT_CONNMARK_SAVE;
- break;
- case O_RESTORE_MARK:
- markinfo->mode = XT_CONNMARK_RESTORE;
- break;
- case O_MASK:
- markinfo->mask = cb->val.u32;
- break;
- }
- }
- static void connmark_tg_parse(struct xt_option_call *cb)
- {
- struct xt_connmark_tginfo1 *info = cb->data;
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_SET_XMARK:
- info->mode = XT_CONNMARK_SET;
- info->ctmark = cb->val.mark;
- info->ctmask = cb->val.mask;
- break;
- case O_SET_MARK:
- info->mode = XT_CONNMARK_SET;
- info->ctmark = cb->val.mark;
- info->ctmask = cb->val.mark | cb->val.mask;
- break;
- case O_AND_MARK:
- info->mode = XT_CONNMARK_SET;
- info->ctmark = 0;
- info->ctmask = ~cb->val.u32;
- break;
- case O_OR_MARK:
- info->mode = XT_CONNMARK_SET;
- info->ctmark = cb->val.u32;
- info->ctmask = cb->val.u32;
- break;
- case O_XOR_MARK:
- info->mode = XT_CONNMARK_SET;
- info->ctmark = cb->val.u32;
- info->ctmask = 0;
- break;
- case O_SAVE_MARK:
- info->mode = XT_CONNMARK_SAVE;
- break;
- case O_RESTORE_MARK:
- info->mode = XT_CONNMARK_RESTORE;
- break;
- case O_MASK:
- info->nfmask = info->ctmask = cb->val.u32;
- break;
- }
- }
- static void connmark_tg_check(struct xt_fcheck_call *cb)
- {
- if (!(cb->xflags & F_OP_ANY))
- xtables_error(PARAMETER_PROBLEM,
- "CONNMARK target: No operation specified");
- }
- static void
- print_mark(unsigned long mark)
- {
- printf("0x%lx", mark);
- }
- static void
- print_mask(const char *text, unsigned long mask)
- {
- if (mask != 0xffffffffUL)
- printf("%s0x%lx", text, mask);
- }
- static void CONNMARK_print(const void *ip,
- const struct xt_entry_target *target, int numeric)
- {
- const struct xt_connmark_target_info *markinfo =
- (const struct xt_connmark_target_info *)target->data;
- switch (markinfo->mode) {
- case XT_CONNMARK_SET:
- printf(" CONNMARK set ");
- print_mark(markinfo->mark);
- print_mask("/", markinfo->mask);
- break;
- case XT_CONNMARK_SAVE:
- printf(" CONNMARK save ");
- print_mask("mask ", markinfo->mask);
- break;
- case XT_CONNMARK_RESTORE:
- printf(" CONNMARK restore ");
- print_mask("mask ", markinfo->mask);
- break;
- default:
- printf(" ERROR: UNKNOWN CONNMARK MODE");
- break;
- }
- }
- static void
- connmark_tg_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
- {
- const struct xt_connmark_tginfo1 *info = (const void *)target->data;
- switch (info->mode) {
- case XT_CONNMARK_SET:
- if (info->ctmark == 0)
- printf(" CONNMARK and 0x%x",
- (unsigned int)(uint32_t)~info->ctmask);
- else if (info->ctmark == info->ctmask)
- printf(" CONNMARK or 0x%x", info->ctmark);
- else if (info->ctmask == 0)
- printf(" CONNMARK xor 0x%x", info->ctmark);
- else if (info->ctmask == 0xFFFFFFFFU)
- printf(" CONNMARK set 0x%x", info->ctmark);
- else
- printf(" CONNMARK xset 0x%x/0x%x",
- info->ctmark, info->ctmask);
- break;
- case XT_CONNMARK_SAVE:
- if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
- printf(" CONNMARK save");
- else if (info->nfmask == info->ctmask)
- printf(" CONNMARK save mask 0x%x", info->nfmask);
- else
- printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x",
- info->nfmask, info->ctmask);
- break;
- case XT_CONNMARK_RESTORE:
- if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
- printf(" CONNMARK restore");
- else if (info->ctmask == info->nfmask)
- printf(" CONNMARK restore mask 0x%x", info->ctmask);
- else
- printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x",
- info->ctmask, info->nfmask);
- break;
- default:
- printf(" ERROR: UNKNOWN CONNMARK MODE");
- break;
- }
- }
- static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
- {
- const struct xt_connmark_target_info *markinfo =
- (const struct xt_connmark_target_info *)target->data;
- switch (markinfo->mode) {
- case XT_CONNMARK_SET:
- printf(" --set-mark ");
- print_mark(markinfo->mark);
- print_mask("/", markinfo->mask);
- break;
- case XT_CONNMARK_SAVE:
- printf(" --save-mark ");
- print_mask("--mask ", markinfo->mask);
- break;
- case XT_CONNMARK_RESTORE:
- printf(" --restore-mark ");
- print_mask("--mask ", markinfo->mask);
- break;
- default:
- printf(" ERROR: UNKNOWN CONNMARK MODE");
- break;
- }
- }
- static void CONNMARK_init(struct xt_entry_target *t)
- {
- struct xt_connmark_target_info *markinfo
- = (struct xt_connmark_target_info *)t->data;
- markinfo->mask = 0xffffffffUL;
- }
- static void
- connmark_tg_save(const void *ip, const struct xt_entry_target *target)
- {
- const struct xt_connmark_tginfo1 *info = (const void *)target->data;
- switch (info->mode) {
- case XT_CONNMARK_SET:
- printf(" --set-xmark 0x%x/0x%x", info->ctmark, info->ctmask);
- break;
- case XT_CONNMARK_SAVE:
- printf(" --save-mark --nfmask 0x%x --ctmask 0x%x",
- info->nfmask, info->ctmask);
- break;
- case XT_CONNMARK_RESTORE:
- printf(" --restore-mark --nfmask 0x%x --ctmask 0x%x",
- info->nfmask, info->ctmask);
- break;
- default:
- printf(" ERROR: UNKNOWN CONNMARK MODE");
- break;
- }
- }
- static struct xtables_target connmark_tg_reg[] = {
- {
- .family = NFPROTO_UNSPEC,
- .name = "CONNMARK",
- .revision = 0,
- .version = XTABLES_VERSION,
- .size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
- .help = CONNMARK_help,
- .init = CONNMARK_init,
- .print = CONNMARK_print,
- .save = CONNMARK_save,
- .x6_parse = CONNMARK_parse,
- .x6_fcheck = connmark_tg_check,
- .x6_options = CONNMARK_opts,
- },
- {
- .version = XTABLES_VERSION,
- .name = "CONNMARK",
- .revision = 1,
- .family = NFPROTO_UNSPEC,
- .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
- .help = connmark_tg_help,
- .init = connmark_tg_init,
- .print = connmark_tg_print,
- .save = connmark_tg_save,
- .x6_parse = connmark_tg_parse,
- .x6_fcheck = connmark_tg_check,
- .x6_options = connmark_tg_opts,
- },
- };
- void _init(void)
- {
- xtables_register_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
- }
|