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