blob: 8f04e8e7f332aba6762186b33b3c87ad56e1e765 [file] [log] [blame]
Marc Bouchere6869a82000-03-20 06:03:29 +00001/* Shared library add-on to iptables to add MARK target support. */
Jan Engelhardtf4b737f2008-01-20 13:31:13 +00002#include <stdbool.h>
Marc Bouchere6869a82000-03-20 06:03:29 +00003#include <stdio.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
7
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +00008#include <xtables.h>
9#include <linux/netfilter/x_tables.h>
10#include <linux/netfilter/xt_MARK.h>
Marc Bouchere6869a82000-03-20 06:03:29 +000011
Jan Engelhardtf4b737f2008-01-20 13:31:13 +000012enum {
13 F_MARK = 1 << 0,
14};
15
Jan Engelhardt932e6482007-10-04 16:27:30 +000016static void MARK_help(void)
Marc Bouchere6869a82000-03-20 06:03:29 +000017{
18 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020019"MARK target options:\n"
Marc Bouchere6869a82000-03-20 06:03:29 +000020" --set-mark value Set nfmark value\n"
Rusty Russell3aef54d2005-01-03 03:48:40 +000021" --and-mark value Binary AND the nfmark with value\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020022" --or-mark value Binary OR the nfmark with value\n");
Marc Bouchere6869a82000-03-20 06:03:29 +000023}
24
Jan Engelhardt932e6482007-10-04 16:27:30 +000025static const struct option MARK_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000026 { "set-mark", 1, NULL, '1' },
27 { "and-mark", 1, NULL, '2' },
28 { "or-mark", 1, NULL, '3' },
Max Kellermann9ee386a2008-01-29 13:48:05 +000029 { .name = NULL }
Marc Bouchere6869a82000-03-20 06:03:29 +000030};
31
Jan Engelhardtf4b737f2008-01-20 13:31:13 +000032static const struct option mark_tg_opts[] = {
33 {.name = "set-xmark", .has_arg = true, .val = 'X'},
34 {.name = "set-mark", .has_arg = true, .val = '='},
35 {.name = "and-mark", .has_arg = true, .val = '&'},
36 {.name = "or-mark", .has_arg = true, .val = '|'},
37 {.name = "xor-mark", .has_arg = true, .val = '^'},
Max Kellermann9ee386a2008-01-29 13:48:05 +000038 { .name = NULL }
Jan Engelhardtf4b737f2008-01-20 13:31:13 +000039};
40
41static void mark_tg_help(void)
42{
43 printf(
44"MARK target options:\n"
45" --set-xmark value[/mask] Clear bits in mask and XOR value into nfmark\n"
46" --set-mark value[/mask] Clear bits in mask and OR value into nfmark\n"
47" --and-mark bits Binary AND the nfmark with bits\n"
48" --or-mark bits Binary OR the nfmark with bits\n"
49" --xor-mask bits Binary XOR the nfmark with bits\n"
50"\n");
51}
52
Marc Bouchere6869a82000-03-20 06:03:29 +000053/* Function which parses command options; returns true if it
54 ate an option */
55static int
Jan Engelhardt932e6482007-10-04 16:27:30 +000056MARK_parse_v0(int c, char **argv, int invert, unsigned int *flags,
57 const void *entry, struct xt_entry_target **target)
Marc Bouchere6869a82000-03-20 06:03:29 +000058{
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +000059 struct xt_mark_target_info *markinfo
60 = (struct xt_mark_target_info *)(*target)->data;
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010061 unsigned int mark = 0;
Marc Bouchere6869a82000-03-20 06:03:29 +000062
63 switch (c) {
Marc Bouchere6869a82000-03-20 06:03:29 +000064 case '1':
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010065 if (!xtables_strtoui(optarg, NULL, &mark, 0, UINT32_MAX))
Marc Bouchere6869a82000-03-20 06:03:29 +000066 exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010067 markinfo->mark = mark;
Marc Bouchere6869a82000-03-20 06:03:29 +000068 if (*flags)
69 exit_error(PARAMETER_PROBLEM,
70 "MARK target: Can't specify --set-mark twice");
71 *flags = 1;
72 break;
Rusty Russell3aef54d2005-01-03 03:48:40 +000073 case '2':
74 exit_error(PARAMETER_PROBLEM,
75 "MARK target: kernel too old for --and-mark");
76 case '3':
77 exit_error(PARAMETER_PROBLEM,
78 "MARK target: kernel too old for --or-mark");
Marc Bouchere6869a82000-03-20 06:03:29 +000079 default:
80 return 0;
81 }
82
83 return 1;
84}
85
Jan Engelhardt932e6482007-10-04 16:27:30 +000086static void MARK_check(unsigned int flags)
Marc Bouchere6869a82000-03-20 06:03:29 +000087{
88 if (!flags)
89 exit_error(PARAMETER_PROBLEM,
Rusty Russell3aef54d2005-01-03 03:48:40 +000090 "MARK target: Parameter --set/and/or-mark"
91 " is required");
92}
93
Rusty Russell3aef54d2005-01-03 03:48:40 +000094static int
Jan Engelhardt932e6482007-10-04 16:27:30 +000095MARK_parse_v1(int c, char **argv, int invert, unsigned int *flags,
96 const void *entry, struct xt_entry_target **target)
Rusty Russell3aef54d2005-01-03 03:48:40 +000097{
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +000098 struct xt_mark_target_info_v1 *markinfo
99 = (struct xt_mark_target_info_v1 *)(*target)->data;
Jan Engelhardt5f2922c2009-01-27 18:43:01 +0100100 unsigned int mark = 0;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000101
102 switch (c) {
103 case '1':
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000104 markinfo->mode = XT_MARK_SET;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000105 break;
106 case '2':
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000107 markinfo->mode = XT_MARK_AND;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000108 break;
109 case '3':
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000110 markinfo->mode = XT_MARK_OR;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000111 break;
112 default:
113 return 0;
114 }
115
Jan Engelhardt5f2922c2009-01-27 18:43:01 +0100116 if (!xtables_strtoui(optarg, NULL, &mark, 0, UINT32_MAX))
Rusty Russell3aef54d2005-01-03 03:48:40 +0000117 exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
Jan Engelhardt5f2922c2009-01-27 18:43:01 +0100118 markinfo->mark = mark;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000119 if (*flags)
120 exit_error(PARAMETER_PROBLEM,
121 "MARK target: Can't specify --set-mark twice");
122
123 *flags = 1;
124 return 1;
Marc Bouchere6869a82000-03-20 06:03:29 +0000125}
126
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000127static int mark_tg_parse(int c, char **argv, int invert, unsigned int *flags,
128 const void *entry, struct xt_entry_target **target)
129{
130 struct xt_mark_tginfo2 *info = (void *)(*target)->data;
Jan Engelhardta8097542009-01-27 17:39:01 +0100131 unsigned int value, mask = UINT32_MAX;
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000132 char *end;
133
134 switch (c) {
135 case 'X': /* --set-xmark */
136 case '=': /* --set-mark */
Jan Engelhardta41545c2009-01-27 21:27:19 +0100137 xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
138 xtables_param_act(XTF_NO_INVERT, "MARK", "--set-xmark/--set-mark", invert);
Jan Engelhardt5f2922c2009-01-27 18:43:01 +0100139 if (!xtables_strtoui(optarg, &end, &value, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +0100140 xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000141 if (*end == '/')
Jan Engelhardt5f2922c2009-01-27 18:43:01 +0100142 if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +0100143 xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000144 if (*end != '\0')
Jan Engelhardta41545c2009-01-27 21:27:19 +0100145 xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000146 info->mark = value;
147 info->mask = mask;
148
149 if (c == '=')
150 info->mask = value | mask;
151 break;
152
153 case '&': /* --and-mark */
Jan Engelhardta41545c2009-01-27 21:27:19 +0100154 xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
155 xtables_param_act(XTF_NO_INVERT, "MARK", "--and-mark", invert);
Jan Engelhardt5f2922c2009-01-27 18:43:01 +0100156 if (!xtables_strtoui(optarg, NULL, &mask, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +0100157 xtables_param_act(XTF_BAD_VALUE, "MARK", "--and-mark", optarg);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000158 info->mark = 0;
159 info->mask = ~mask;
160 break;
161
162 case '|': /* --or-mark */
Jan Engelhardta41545c2009-01-27 21:27:19 +0100163 xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
164 xtables_param_act(XTF_NO_INVERT, "MARK", "--or-mark", invert);
Jan Engelhardt5f2922c2009-01-27 18:43:01 +0100165 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +0100166 xtables_param_act(XTF_BAD_VALUE, "MARK", "--or-mark", optarg);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000167 info->mark = value;
168 info->mask = value;
169 break;
170
171 case '^': /* --xor-mark */
Jan Engelhardta41545c2009-01-27 21:27:19 +0100172 xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
173 xtables_param_act(XTF_NO_INVERT, "MARK", "--xor-mark", invert);
Jan Engelhardt5f2922c2009-01-27 18:43:01 +0100174 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +0100175 xtables_param_act(XTF_BAD_VALUE, "MARK", "--xor-mark", optarg);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000176 info->mark = value;
177 info->mask = 0;
178 break;
179
180 default:
181 return false;
182 }
183
184 *flags |= F_MARK;
185 return true;
186}
187
188static void mark_tg_check(unsigned int flags)
189{
190 if (flags == 0)
191 exit_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, "
192 "--{and,or,xor,set}-mark options is required");
193}
194
Martin Josefssonc5617bf2004-05-26 21:56:26 +0000195static void
196print_mark(unsigned long mark)
Marc Bouchere6869a82000-03-20 06:03:29 +0000197{
198 printf("0x%lx ", mark);
199}
200
Jan Engelhardt932e6482007-10-04 16:27:30 +0000201static void MARK_print_v0(const void *ip,
202 const struct xt_entry_target *target, int numeric)
Marc Bouchere6869a82000-03-20 06:03:29 +0000203{
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000204 const struct xt_mark_target_info *markinfo =
205 (const struct xt_mark_target_info *)target->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000206 printf("MARK set ");
Martin Josefssonc5617bf2004-05-26 21:56:26 +0000207 print_mark(markinfo->mark);
Marc Bouchere6869a82000-03-20 06:03:29 +0000208}
209
Jan Engelhardt932e6482007-10-04 16:27:30 +0000210static void MARK_save_v0(const void *ip, const struct xt_entry_target *target)
Marc Bouchere6869a82000-03-20 06:03:29 +0000211{
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000212 const struct xt_mark_target_info *markinfo =
213 (const struct xt_mark_target_info *)target->data;
Rusty Russell7e53bf92000-03-20 07:03:28 +0000214
Martin Josefssonc5617bf2004-05-26 21:56:26 +0000215 printf("--set-mark ");
216 print_mark(markinfo->mark);
Marc Bouchere6869a82000-03-20 06:03:29 +0000217}
218
Jan Engelhardt932e6482007-10-04 16:27:30 +0000219static void MARK_print_v1(const void *ip, const struct xt_entry_target *target,
220 int numeric)
Rusty Russell3aef54d2005-01-03 03:48:40 +0000221{
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000222 const struct xt_mark_target_info_v1 *markinfo =
223 (const struct xt_mark_target_info_v1 *)target->data;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000224
225 switch (markinfo->mode) {
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000226 case XT_MARK_SET:
Rusty Russell3aef54d2005-01-03 03:48:40 +0000227 printf("MARK set ");
228 break;
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000229 case XT_MARK_AND:
Rusty Russell3aef54d2005-01-03 03:48:40 +0000230 printf("MARK and ");
231 break;
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000232 case XT_MARK_OR:
Rusty Russell3aef54d2005-01-03 03:48:40 +0000233 printf("MARK or ");
234 break;
235 }
236 print_mark(markinfo->mark);
237}
238
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000239static void mark_tg_print(const void *ip, const struct xt_entry_target *target,
240 int numeric)
241{
242 const struct xt_mark_tginfo2 *info = (const void *)target->data;
243
244 if (info->mark == 0)
245 printf("MARK and 0x%x ", (unsigned int)(u_int32_t)~info->mask);
246 else if (info->mark == info->mask)
247 printf("MARK or 0x%x ", info->mark);
248 else if (info->mask == 0)
249 printf("MARK xor 0x%x ", info->mark);
250 else
251 printf("MARK xset 0x%x/0x%x ", info->mark, info->mask);
252}
253
Jan Engelhardt932e6482007-10-04 16:27:30 +0000254static void MARK_save_v1(const void *ip, const struct xt_entry_target *target)
Rusty Russell3aef54d2005-01-03 03:48:40 +0000255{
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000256 const struct xt_mark_target_info_v1 *markinfo =
257 (const struct xt_mark_target_info_v1 *)target->data;
Rusty Russell3aef54d2005-01-03 03:48:40 +0000258
259 switch (markinfo->mode) {
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000260 case XT_MARK_SET:
Rusty Russell3aef54d2005-01-03 03:48:40 +0000261 printf("--set-mark ");
262 break;
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000263 case XT_MARK_AND:
Rusty Russell3aef54d2005-01-03 03:48:40 +0000264 printf("--and-mark ");
265 break;
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000266 case XT_MARK_OR:
Rusty Russell3aef54d2005-01-03 03:48:40 +0000267 printf("--or-mark ");
268 break;
269 }
270 print_mark(markinfo->mark);
271}
272
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000273static void mark_tg_save(const void *ip, const struct xt_entry_target *target)
274{
275 const struct xt_mark_tginfo2 *info = (const void *)target->data;
276
277 printf("--set-xmark 0x%x/0x%x ", info->mark, info->mask);
278}
279
Jan Engelhardt932e6482007-10-04 16:27:30 +0000280static struct xtables_target mark_target_v0 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100281 .family = NFPROTO_IPV4,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000282 .name = "MARK",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200283 .version = XTABLES_VERSION,
Rusty Russell3aef54d2005-01-03 03:48:40 +0000284 .revision = 0,
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000285 .size = XT_ALIGN(sizeof(struct xt_mark_target_info)),
286 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
Jan Engelhardt932e6482007-10-04 16:27:30 +0000287 .help = MARK_help,
288 .parse = MARK_parse_v0,
289 .final_check = MARK_check,
290 .print = MARK_print_v0,
291 .save = MARK_save_v0,
292 .extra_opts = MARK_opts,
Rusty Russell3aef54d2005-01-03 03:48:40 +0000293};
294
Jan Engelhardt932e6482007-10-04 16:27:30 +0000295static struct xtables_target mark_target_v1 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100296 .family = NFPROTO_IPV4,
Rusty Russell3aef54d2005-01-03 03:48:40 +0000297 .name = "MARK",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200298 .version = XTABLES_VERSION,
Rusty Russell3aef54d2005-01-03 03:48:40 +0000299 .revision = 1,
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000300 .size = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
301 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
Jan Engelhardt932e6482007-10-04 16:27:30 +0000302 .help = MARK_help,
303 .parse = MARK_parse_v1,
304 .final_check = MARK_check,
305 .print = MARK_print_v1,
306 .save = MARK_save_v1,
307 .extra_opts = MARK_opts,
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000308};
309
Jan Engelhardt932e6482007-10-04 16:27:30 +0000310static struct xtables_target mark_target6_v0 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100311 .family = NFPROTO_IPV6,
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000312 .name = "MARK",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200313 .version = XTABLES_VERSION,
Yasuyuki KOZAKAI6e222282007-08-04 08:06:55 +0000314 .revision = 0,
315 .size = XT_ALIGN(sizeof(struct xt_mark_target_info)),
316 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
Jan Engelhardt932e6482007-10-04 16:27:30 +0000317 .help = MARK_help,
318 .parse = MARK_parse_v0,
319 .final_check = MARK_check,
320 .print = MARK_print_v0,
321 .save = MARK_save_v0,
322 .extra_opts = MARK_opts,
Marc Bouchere6869a82000-03-20 06:03:29 +0000323};
324
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000325static struct xtables_target mark_tg_reg_v2 = {
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200326 .version = XTABLES_VERSION,
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000327 .name = "MARK",
328 .revision = 2,
Jan Engelhardt23545c22008-02-14 04:23:04 +0100329 .family = AF_UNSPEC,
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000330 .size = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
331 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
332 .help = mark_tg_help,
333 .parse = mark_tg_parse,
334 .final_check = mark_tg_check,
335 .print = mark_tg_print,
336 .save = mark_tg_save,
337 .extra_opts = mark_tg_opts,
338};
339
Marc Bouchere6869a82000-03-20 06:03:29 +0000340void _init(void)
341{
Jan Engelhardt932e6482007-10-04 16:27:30 +0000342 xtables_register_target(&mark_target_v0);
343 xtables_register_target(&mark_target_v1);
344 xtables_register_target(&mark_target6_v0);
Jan Engelhardtf4b737f2008-01-20 13:31:13 +0000345 xtables_register_target(&mark_tg_reg_v2);
Marc Bouchere6869a82000-03-20 06:03:29 +0000346}