Sapan says vnet_tun is obsolete.
[iptables.git] / extensions / libxt_MARK.c
1 /* Shared library add-on to iptables to add MARK target support. */
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7
8 #include <xtables.h>
9 #include <linux/netfilter/x_tables.h>
10 #include <linux/netfilter/xt_MARK.h>
11
12 enum {
13         F_MARK = 1 << 0,
14 };
15
16 /* Function which prints out usage message. */
17 static void MARK_help(void)
18 {
19         printf(
20 "MARK target options:\n"
21 "  --set-mark value                   Set nfmark value\n"
22 "  --and-mark value                   Binary AND the nfmark with value\n"
23 "  --or-mark  value                   Binary OR  the nfmark with value\n"
24 "  --copy-xid                         Set nfmark to be the connection xid (PlanetLab specific)\n"
25 );
26 }
27
28 static const struct option MARK_opts[] = {
29         { "set-mark", 1, NULL, '1' },
30         { "and-mark", 1, NULL, '2' },
31         { "or-mark", 1, NULL, '3' },
32         { "copy-xid", 1, 0, '4' },
33         { .name = NULL }
34 };
35
36 static const struct option mark_tg_opts[] = {
37         {.name = "set-xmark", .has_arg = true, .val = 'X'},
38         {.name = "set-mark",  .has_arg = true, .val = '='},
39         {.name = "and-mark",  .has_arg = true, .val = '&'},
40         {.name = "or-mark",   .has_arg = true, .val = '|'},
41         {.name = "xor-mark",  .has_arg = true, .val = '^'},
42         {.name = "copy-xid",  .has_arg = true, .val = '%'},
43         { .name = NULL }
44 };
45
46 static void mark_tg_help(void)
47 {
48         printf(
49 "MARK target options:\n"
50 "  --set-xmark value[/mask]  Clear bits in mask and XOR value into nfmark\n"
51 "  --set-mark value[/mask]   Clear bits in mask and OR value into nfmark\n"
52 "  --and-mark bits           Binary AND the nfmark with bits\n"
53 "  --or-mark bits            Binary OR the nfmark with bits\n"
54 "  --copy-xid                Set nfmark to be the connection xid (PlanetLab specific)\n"
55 "  --xor-mask bits           Binary XOR the nfmark with bits\n"
56 "\n");
57 }
58
59 /* Function which parses command options; returns true if it
60    ate an option */
61 static int
62 MARK_parse_v0(int c, char **argv, int invert, unsigned int *flags,
63               const void *entry, struct xt_entry_target **target)
64 {
65         struct xt_mark_target_info *markinfo
66                 = (struct xt_mark_target_info *)(*target)->data;
67
68         switch (c) {
69         case '1':
70                 if (string_to_number_l(optarg, 0, 0, 
71                                      &markinfo->mark))
72                         exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
73                 if (*flags)
74                         exit_error(PARAMETER_PROBLEM,
75                                    "MARK target: Can't specify --set-mark twice");
76                 *flags = 1;
77                 break;
78         case '2':
79                 exit_error(PARAMETER_PROBLEM,
80                            "MARK target: kernel too old for --and-mark");
81         case '3':
82                 exit_error(PARAMETER_PROBLEM,
83                            "MARK target: kernel too old for --or-mark");
84         default:
85                 return 0;
86         }
87
88         return 1;
89 }
90
91 static void MARK_check(unsigned int flags)
92 {
93         if (!flags)
94                 exit_error(PARAMETER_PROBLEM,
95                            "MARK target: Parameter --set/and/or-mark"
96                            " is required");
97 }
98
99 /* Function which parses command options; returns true if it
100    ate an option */
101 static int
102 MARK_parse_v1(int c, char **argv, int invert, unsigned int *flags,
103               const void *entry, struct xt_entry_target **target)
104 {
105         struct xt_mark_target_info_v1 *markinfo
106                 = (struct xt_mark_target_info_v1 *)(*target)->data;
107
108         switch (c) {
109         case '1':
110                 markinfo->mode = XT_MARK_SET;
111                 break;
112         case '2':
113                 markinfo->mode = XT_MARK_AND;
114                 break;
115         case '3':
116                 markinfo->mode = XT_MARK_OR;
117                 break;
118         case '4':
119                 markinfo->mode = IPT_MARK_COPYXID;
120                 break;
121         default:
122                 return 0;
123         }
124
125         if (string_to_number_l(optarg, 0, 0, &markinfo->mark))
126                 exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
127
128         if (*flags)
129                 exit_error(PARAMETER_PROBLEM,
130                            "MARK target: Can't specify --set-mark twice");
131
132         *flags = 1;
133         return 1;
134 }
135
136 static int mark_tg_parse(int c, char **argv, int invert, unsigned int *flags,
137                          const void *entry, struct xt_entry_target **target)
138 {
139         struct xt_mark_tginfo2 *info = (void *)(*target)->data;
140         unsigned int value, mask = ~0U;
141         char *end;
142
143         switch (c) {
144         case 'X': /* --set-xmark */
145         case '=': /* --set-mark */
146                 param_act(P_ONE_ACTION, "MARK", *flags & F_MARK);
147                 param_act(P_NO_INVERT, "MARK", "--set-xmark/--set-mark", invert);
148                 if (!strtonum(optarg, &end, &value, 0, ~0U))
149                         param_act(P_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
150                 if (*end == '/')
151                         if (!strtonum(end + 1, &end, &mask, 0, ~0U))
152                                 param_act(P_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
153                 if (*end != '\0')
154                         param_act(P_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
155                 info->mark = value;
156                 info->mask = mask;
157
158                 if (c == '=')
159                         info->mask = value | mask;
160                 break;
161
162         case '&': /* --and-mark */
163                 param_act(P_ONE_ACTION, "MARK", *flags & F_MARK);
164                 param_act(P_NO_INVERT, "MARK", "--and-mark", invert);
165                 if (!strtonum(optarg, NULL, &mask, 0, ~0U))
166                         param_act(P_BAD_VALUE, "MARK", "--and-mark", optarg);
167                 info->mark = 0;
168                 info->mask = ~mask;
169                 break;
170
171         case '|': /* --or-mark */
172                 param_act(P_ONE_ACTION, "MARK", *flags & F_MARK);
173                 param_act(P_NO_INVERT, "MARK", "--or-mark", invert);
174                 if (!strtonum(optarg, NULL, &value, 0, ~0U))
175                         param_act(P_BAD_VALUE, "MARK", "--or-mark", optarg);
176                 info->mark = value;
177                 info->mask = value;
178                 break;
179
180         case '^': /* --xor-mark */
181                 param_act(P_ONE_ACTION, "MARK", *flags & F_MARK);
182                 param_act(P_NO_INVERT, "MARK", "--xor-mark", invert);
183                 if (!strtonum(optarg, NULL, &value, 0, ~0U))
184                         param_act(P_BAD_VALUE, "MARK", "--xor-mark", optarg);
185                 info->mark = value;
186                 info->mask = 0;
187                 break;
188
189     case '%': /* --copy-xid */
190         param_act(P_ONE_ACTION, "MARK", *flags & F_MARK);
191         info->mark = ~0U; /* Consistency check */
192         info->mask = mask;
193         break;
194
195         default:
196                 return false;
197         }
198
199         *flags |= F_MARK;
200         return true;
201 }
202
203 static void mark_tg_check(unsigned int flags)
204 {
205         if (flags == 0)
206                 exit_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, "
207                            "--{and,or,xor,set}-mark, or --copy-xid options is required");
208 }
209
210 static void
211 print_mark(unsigned long mark)
212 {
213         printf("0x%lx ", mark);
214 }
215
216 /* Prints out the targinfo. */
217 static void MARK_print_v0(const void *ip,
218                           const struct xt_entry_target *target, int numeric)
219 {
220         const struct xt_mark_target_info *markinfo =
221                 (const struct xt_mark_target_info *)target->data;
222         printf("MARK set ");
223         print_mark(markinfo->mark);
224 }
225
226 /* Saves the union ipt_targinfo in parsable form to stdout. */
227 static void MARK_save_v0(const void *ip, const struct xt_entry_target *target)
228 {
229         const struct xt_mark_target_info *markinfo =
230                 (const struct xt_mark_target_info *)target->data;
231
232         printf("--set-mark ");
233         print_mark(markinfo->mark);
234 }
235
236 /* Prints out the targinfo. */
237 static void MARK_print_v1(const void *ip, const struct xt_entry_target *target,
238                           int numeric)
239 {
240         const struct xt_mark_target_info_v1 *markinfo =
241                 (const struct xt_mark_target_info_v1 *)target->data;
242
243         switch (markinfo->mode) {
244         case XT_MARK_SET:
245                 printf("MARK set ");
246                 break;
247         case XT_MARK_AND:
248                 printf("MARK and ");
249                 break;
250         case XT_MARK_OR: 
251                 printf("MARK or ");
252                 break;
253         case IPT_MARK_COPYXID: 
254                 printf("MARK copyxid ");
255                 break;
256         }
257         print_mark(markinfo->mark);
258 }
259
260 static void mark_tg_print(const void *ip, const struct xt_entry_target *target,
261         int numeric)
262 {
263     const struct xt_mark_tginfo2 *info = (const void *)target->data;
264
265     if (info->mark == ~0U) 
266         printf("MARK copy-xid");
267     else if (info->mark == 0)
268         printf("MARK and 0x%x ", (unsigned int)(u_int32_t)~info->mask);
269     else if (info->mark == info->mask)
270         printf("MARK or 0x%x ", info->mark);
271     else if (info->mask == 0)
272         printf("MARK xor 0x%x ", info->mark);
273     else
274         printf("MARK xset 0x%x/0x%x ", info->mark, info->mask);
275 }
276
277 /* Saves the union ipt_targinfo in parsable form to stdout. */
278 static void MARK_save_v1(const void *ip, const struct xt_entry_target *target)
279 {
280         const struct xt_mark_target_info_v1 *markinfo =
281                 (const struct xt_mark_target_info_v1 *)target->data;
282
283         switch (markinfo->mode) {
284         case XT_MARK_SET:
285                 printf("--set-mark ");
286                 break;
287         case XT_MARK_AND:
288                 printf("--and-mark ");
289                 break;
290         case XT_MARK_OR: 
291                 printf("--or-mark ");
292                 break;
293         case IPT_MARK_COPYXID: 
294                 printf("--copy-xid ");
295                 break;
296         }
297         print_mark(markinfo->mark);
298 }
299
300 static void mark_tg_save(const void *ip, const struct xt_entry_target *target)
301 {
302         const struct xt_mark_tginfo2 *info = (const void *)target->data;
303
304     if (info->mark==~0U)
305         printf("--copy-xid 0x0");
306     else
307             printf("--set-xmark 0x%x/0x%x ", info->mark, info->mask);
308 }
309
310 static struct xtables_target mark_target_v0 = {
311         .family         = AF_INET,
312         .name           = "MARK",
313         .version        = XTABLES_VERSION,
314         .revision       = 0,
315         .size           = XT_ALIGN(sizeof(struct xt_mark_target_info)),
316         .userspacesize  = XT_ALIGN(sizeof(struct xt_mark_target_info)),
317         .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,
323 };
324
325 static struct xtables_target mark_target_v1 = {
326         .family         = AF_INET,
327         .name           = "MARK",
328         .version        = XTABLES_VERSION,
329         .revision       = 1,
330         .size           = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
331         .userspacesize  = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
332         .help           = MARK_help,
333         .parse          = MARK_parse_v1,
334         .final_check    = MARK_check,
335         .print          = MARK_print_v1,
336         .save           = MARK_save_v1,
337         .extra_opts     = MARK_opts,
338 };
339
340 static struct xtables_target mark_target6_v0 = {
341         .family         = AF_INET6,
342         .name           = "MARK",
343         .version        = XTABLES_VERSION,
344         .revision       = 0,
345         .size           = XT_ALIGN(sizeof(struct xt_mark_target_info)),
346         .userspacesize  = XT_ALIGN(sizeof(struct xt_mark_target_info)),
347         .help           = MARK_help,
348         .parse          = MARK_parse_v0,
349         .final_check    = MARK_check,
350         .print          = MARK_print_v0,
351         .save           = MARK_save_v0,
352         .extra_opts     = MARK_opts,
353 };
354
355 static struct xtables_target mark_tg_reg_v2 = {
356         .version       = XTABLES_VERSION,
357         .name          = "MARK",
358         .revision      = 2,
359         .family        = AF_UNSPEC,
360         .size          = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
361         .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
362         .help          = mark_tg_help,
363         .parse         = mark_tg_parse,
364         .final_check   = mark_tg_check,
365         .print         = mark_tg_print,
366         .save          = mark_tg_save,
367         .extra_opts    = mark_tg_opts,
368 };
369
370 void _init(void)
371 {
372         xtables_register_target(&mark_target_v0);
373         xtables_register_target(&mark_target_v1);
374         xtables_register_target(&mark_target6_v0);
375         xtables_register_target(&mark_tg_reg_v2);
376 }