blob: 556dbde5fa64967bf44ce9d0b9f4c6e22989c8fe [file] [log] [blame]
Jan Engelhardtf4b737f2008-01-20 13:31:13 +00001#include <stdbool.h>
Marc Bouchere6869a82000-03-20 06:03:29 +00002#include <stdio.h>
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +00003#include <xtables.h>
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +00004#include <linux/netfilter/xt_MARK.h>
Marc Bouchere6869a82000-03-20 06:03:29 +00005
Jan Engelhardt350661a2010-01-31 22:42:52 +01006/* Version 0 */
7struct xt_mark_target_info {
8 unsigned long mark;
9};
10
11/* Version 1 */
12enum {
13 XT_MARK_SET=0,
14 XT_MARK_AND,
15 XT_MARK_OR,
16};
17
18struct xt_mark_target_info_v1 {
19 unsigned long mark;
Jan Engelhardt7ac40522011-01-07 12:34:04 +010020 uint8_t mode;
Jan Engelhardt350661a2010-01-31 22:42:52 +010021};
22
Jan Engelhardtf4b737f2008-01-20 13:31:13 +000023enum {
Jan Engelhardt60756e72011-03-06 15:21:24 +010024 O_SET_MARK = 0,
25 O_AND_MARK,
26 O_OR_MARK,
27 O_XOR_MARK,
28 O_SET_XMARK,
29 F_SET_MARK = 1 << O_SET_MARK,
30 F_AND_MARK = 1 << O_AND_MARK,
31 F_OR_MARK = 1 << O_OR_MARK,
32 F_XOR_MARK = 1 << O_XOR_MARK,
33 F_SET_XMARK = 1 << O_SET_XMARK,
34 F_ANY = F_SET_MARK | F_AND_MARK | F_OR_MARK |
35 F_XOR_MARK | F_SET_XMARK,
Jan Engelhardtf4b737f2008-01-20 13:31:13 +000036};
37
Jan Engelhardt932e6482007-10-04 16:27:30 +000038static void MARK_help(void)
Marc Bouchere6869a82000-03-20 06:03:29 +000039{
40 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020041"MARK target options:\n"
Marc Bouchere6869a82000-03-20 06:03:29 +000042" --set-mark value Set nfmark value\n"
Rusty Russell3aef54d2005-01-03 03:48:40 +000043" --and-mark value Binary AND the nfmark with value\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020044" --or-mark value Binary OR the nfmark with value\n");
Marc Bouchere6869a82000-03-20 06:03:29 +000045}
46
Jan Engelhardt60756e72011-03-06 15:21:24 +010047static const struct xt_option_entry MARK_opts[] = {
48 {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32,
49 .excl = F_ANY},
50 {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
51 .excl = F_ANY},
52 {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
53 .excl = F_ANY},
54 XTOPT_TABLEEND,
Marc Bouchere6869a82000-03-20 06:03:29 +000055};
56
Jan Engelhardt60756e72011-03-06 15:21:24 +010057static const struct xt_option_entry mark_tg_opts[] = {
58 {.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
59 .excl = F_ANY},
60 {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
61 .excl = F_ANY},
62 {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
63 .excl = F_ANY},
64 {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
65 .excl = F_ANY},
66 {.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
67 .excl = F_ANY},
68 XTOPT_TABLEEND,
Jan Engelhardtf4b737f2008-01-20 13:31:13 +000069};
70
71static void mark_tg_help(void)
72{
73 printf(
74"MARK target options:\n"
75" --set-xmark value[/mask] Clear bits in mask and XOR value into nfmark\n"
76" --set-mark value[/mask] Clear bits in mask and OR value into nfmark\n"
77" --and-mark bits Binary AND the nfmark with bits\n"
78" --or-mark bits Binary OR the nfmark with bits\n"
79" --xor-mask bits Binary XOR the nfmark with bits\n"
80"\n");
81}
82
Jan Engelhardt60756e72011-03-06 15:21:24 +010083static void MARK_parse_v0(struct xt_option_call *cb)
Marc Bouchere6869a82000-03-20 06:03:29 +000084{
Jan Engelhardt60756e72011-03-06 15:21:24 +010085 struct xt_mark_target_info *markinfo = cb->data;
Marc Bouchere6869a82000-03-20 06:03:29 +000086
Jan Engelhardt60756e72011-03-06 15:21:24 +010087 xtables_option_parse(cb);
88 switch (cb->entry->id) {
89 case O_SET_MARK:
90 markinfo->mark = cb->val.mark;
Marc Bouchere6869a82000-03-20 06:03:29 +000091 break;
Jan Engelhardt60756e72011-03-06 15:21:24 +010092 default:
Jan Engelhardt1829ed42009-02-21 03:29:44 +010093 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardt60756e72011-03-06 15:21:24 +010094 "MARK target: kernel too old for --%s",
95 cb->entry->name);
Marc Bouchere6869a82000-03-20 06:03:29 +000096 }
Marc Bouchere6869a82000-03-20 06:03:29 +000097}
98
Jan Engelhardt60756e72011-03-06 15:21:24 +010099static void MARK_check(struct xt_fcheck_call *cb)
Marc Bouchere6869a82000-03-20 06:03:29 +0000100{
Jan Engelhardt60756e72011-03-06 15:21:24 +0100101 if (cb->xflags == 0)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100102 xtables_error(PARAMETER_PROBLEM,
Rusty Russell3aef54d2005-01-03 03:48:40 +0000103 "MARK target: Parameter --set/and/or-mark"
104 " is required");
105}
106
Jan Engelhardt60756e72011-03-06 15:21:24 +0100107static void MARK_parse_v1(struct xt_option_call *cb)
Rusty Russell3aef54d2005-01-03 03:48:40 +0000108{
Jan Engelhardt60756e72011-03-06 15:21:24 +0100109 struct xt_mark_target_info_v1 *markinfo = cb->data;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000110
Jan Engelhardt60756e72011-03-06 15:21:24 +0100111 xtables_option_parse(cb);
112 switch (cb->entry->id) {
113 case O_SET_MARK:
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000114 markinfo->mode = XT_MARK_SET;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000115 break;
Jan Engelhardt60756e72011-03-06 15:21:24 +0100116 case O_AND_MARK:
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000117 markinfo->mode = XT_MARK_AND;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000118 break;
Jan Engelhardt60756e72011-03-06 15:21:24 +0100119 case O_OR_MARK:
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000120 markinfo->mode = XT_MARK_OR;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000121 break;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000122 }
Jan Engelhardt60756e72011-03-06 15:21:24 +0100123 markinfo->mark = cb->val.u32;
Marc Bouchere6869a82000-03-20 06:03:29 +0000124}
125
Jan Engelhardt60756e72011-03-06 15:21:24 +0100126static void mark_tg_parse(struct xt_option_call *cb)
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000127{
Jan Engelhardt60756e72011-03-06 15:21:24 +0100128 struct xt_mark_tginfo2 *info = cb->data;
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000129
Jan Engelhardt60756e72011-03-06 15:21:24 +0100130 xtables_option_parse(cb);
131 switch (cb->entry->id) {
132 case O_SET_XMARK:
133 info->mark = cb->val.mark;
134 info->mask = cb->val.mask;
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000135 break;
Jan Engelhardt60756e72011-03-06 15:21:24 +0100136 case O_SET_MARK:
137 info->mark = cb->val.mark;
138 info->mask = cb->val.mark | cb->val.mask;
139 break;
140 case O_AND_MARK:
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000141 info->mark = 0;
Jan Engelhardt60756e72011-03-06 15:21:24 +0100142 info->mask = ~cb->val.u32;
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000143 break;
Jan Engelhardt60756e72011-03-06 15:21:24 +0100144 case O_OR_MARK:
145 info->mark = info->mask = cb->val.u32;
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000146 break;
Jan Engelhardt60756e72011-03-06 15:21:24 +0100147 case O_XOR_MARK:
148 info->mark = cb->val.u32;
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000149 info->mask = 0;
150 break;
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000151 }
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000152}
153
Jan Engelhardt60756e72011-03-06 15:21:24 +0100154static void mark_tg_check(struct xt_fcheck_call *cb)
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000155{
Jan Engelhardt60756e72011-03-06 15:21:24 +0100156 if (cb->xflags == 0)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100157 xtables_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, "
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000158 "--{and,or,xor,set}-mark options is required");
159}
160
Martin Josefssonc5617bf2004-05-26 21:56:26 +0000161static void
162print_mark(unsigned long mark)
Marc Bouchere6869a82000-03-20 06:03:29 +0000163{
Jan Engelhardt73866352010-12-18 02:04:59 +0100164 printf(" 0x%lx", mark);
Marc Bouchere6869a82000-03-20 06:03:29 +0000165}
166
Jan Engelhardt932e6482007-10-04 16:27:30 +0000167static void MARK_print_v0(const void *ip,
168 const struct xt_entry_target *target, int numeric)
Marc Bouchere6869a82000-03-20 06:03:29 +0000169{
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000170 const struct xt_mark_target_info *markinfo =
171 (const struct xt_mark_target_info *)target->data;
Jan Engelhardt73866352010-12-18 02:04:59 +0100172 printf(" MARK set");
Martin Josefssonc5617bf2004-05-26 21:56:26 +0000173 print_mark(markinfo->mark);
Marc Bouchere6869a82000-03-20 06:03:29 +0000174}
175
Jan Engelhardt932e6482007-10-04 16:27:30 +0000176static void MARK_save_v0(const void *ip, const struct xt_entry_target *target)
Marc Bouchere6869a82000-03-20 06:03:29 +0000177{
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000178 const struct xt_mark_target_info *markinfo =
179 (const struct xt_mark_target_info *)target->data;
Rusty Russell7e53bf92000-03-20 07:03:28 +0000180
Jan Engelhardt73866352010-12-18 02:04:59 +0100181 printf(" --set-mark");
Martin Josefssonc5617bf2004-05-26 21:56:26 +0000182 print_mark(markinfo->mark);
Marc Bouchere6869a82000-03-20 06:03:29 +0000183}
184
Jan Engelhardt932e6482007-10-04 16:27:30 +0000185static void MARK_print_v1(const void *ip, const struct xt_entry_target *target,
186 int numeric)
Rusty Russell3aef54d2005-01-03 03:48:40 +0000187{
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000188 const struct xt_mark_target_info_v1 *markinfo =
189 (const struct xt_mark_target_info_v1 *)target->data;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000190
191 switch (markinfo->mode) {
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000192 case XT_MARK_SET:
Jan Engelhardt73866352010-12-18 02:04:59 +0100193 printf(" MARK set");
Rusty Russell3aef54d2005-01-03 03:48:40 +0000194 break;
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000195 case XT_MARK_AND:
Jan Engelhardt73866352010-12-18 02:04:59 +0100196 printf(" MARK and");
Rusty Russell3aef54d2005-01-03 03:48:40 +0000197 break;
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000198 case XT_MARK_OR:
Jan Engelhardt73866352010-12-18 02:04:59 +0100199 printf(" MARK or");
Rusty Russell3aef54d2005-01-03 03:48:40 +0000200 break;
201 }
202 print_mark(markinfo->mark);
203}
204
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000205static void mark_tg_print(const void *ip, const struct xt_entry_target *target,
206 int numeric)
207{
208 const struct xt_mark_tginfo2 *info = (const void *)target->data;
209
210 if (info->mark == 0)
Jan Engelhardt73866352010-12-18 02:04:59 +0100211 printf(" MARK and 0x%x", (unsigned int)(uint32_t)~info->mask);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000212 else if (info->mark == info->mask)
Jan Engelhardt73866352010-12-18 02:04:59 +0100213 printf(" MARK or 0x%x", info->mark);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000214 else if (info->mask == 0)
Jan Engelhardt73866352010-12-18 02:04:59 +0100215 printf(" MARK xor 0x%x", info->mark);
Patrick McHardy3d915e12009-11-04 13:03:50 +0100216 else if (info->mask == 0xffffffffU)
Jan Engelhardt73866352010-12-18 02:04:59 +0100217 printf(" MARK set 0x%x", info->mark);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000218 else
Jan Engelhardt73866352010-12-18 02:04:59 +0100219 printf(" MARK xset 0x%x/0x%x", info->mark, info->mask);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000220}
221
Jan Engelhardt932e6482007-10-04 16:27:30 +0000222static void MARK_save_v1(const void *ip, const struct xt_entry_target *target)
Rusty Russell3aef54d2005-01-03 03:48:40 +0000223{
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000224 const struct xt_mark_target_info_v1 *markinfo =
225 (const struct xt_mark_target_info_v1 *)target->data;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000226
227 switch (markinfo->mode) {
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000228 case XT_MARK_SET:
Jan Engelhardt73866352010-12-18 02:04:59 +0100229 printf(" --set-mark");
Rusty Russell3aef54d2005-01-03 03:48:40 +0000230 break;
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000231 case XT_MARK_AND:
Jan Engelhardt73866352010-12-18 02:04:59 +0100232 printf(" --and-mark");
Rusty Russell3aef54d2005-01-03 03:48:40 +0000233 break;
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000234 case XT_MARK_OR:
Jan Engelhardt73866352010-12-18 02:04:59 +0100235 printf(" --or-mark");
Rusty Russell3aef54d2005-01-03 03:48:40 +0000236 break;
237 }
238 print_mark(markinfo->mark);
239}
240
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000241static void mark_tg_save(const void *ip, const struct xt_entry_target *target)
242{
243 const struct xt_mark_tginfo2 *info = (const void *)target->data;
244
Jan Engelhardt73866352010-12-18 02:04:59 +0100245 printf(" --set-xmark 0x%x/0x%x", info->mark, info->mask);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000246}
247
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200248static struct xtables_target mark_tg_reg[] = {
249 {
250 .family = NFPROTO_UNSPEC,
251 .name = "MARK",
252 .version = XTABLES_VERSION,
253 .revision = 0,
254 .size = XT_ALIGN(sizeof(struct xt_mark_target_info)),
255 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
256 .help = MARK_help,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200257 .print = MARK_print_v0,
258 .save = MARK_save_v0,
Jan Engelhardt60756e72011-03-06 15:21:24 +0100259 .x6_parse = MARK_parse_v0,
260 .x6_fcheck = MARK_check,
261 .x6_options = MARK_opts,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200262 },
263 {
264 .family = NFPROTO_IPV4,
265 .name = "MARK",
266 .version = XTABLES_VERSION,
267 .revision = 1,
268 .size = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
269 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
270 .help = MARK_help,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200271 .print = MARK_print_v1,
272 .save = MARK_save_v1,
Jan Engelhardt60756e72011-03-06 15:21:24 +0100273 .x6_parse = MARK_parse_v1,
274 .x6_fcheck = MARK_check,
275 .x6_options = MARK_opts,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200276 },
277 {
278 .version = XTABLES_VERSION,
279 .name = "MARK",
280 .revision = 2,
281 .family = NFPROTO_UNSPEC,
282 .size = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
283 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
284 .help = mark_tg_help,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200285 .print = mark_tg_print,
286 .save = mark_tg_save,
Jan Engelhardt60756e72011-03-06 15:21:24 +0100287 .x6_parse = mark_tg_parse,
288 .x6_fcheck = mark_tg_check,
289 .x6_options = mark_tg_opts,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200290 },
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000291};
292
Marc Bouchere6869a82000-03-20 06:03:29 +0000293void _init(void)
294{
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200295 xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
Marc Bouchere6869a82000-03-20 06:03:29 +0000296}