Fork for IVI and add .changes file
[profile/ivi/iptables.git] / extensions / libxt_mark.c
1 /* Shared library add-on to iptables to add NFMARK matching support. */
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <netdb.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <getopt.h>
8
9 #include <xtables.h>
10 #include <linux/netfilter/xt_mark.h>
11
12 struct xt_mark_info {
13         unsigned long mark, mask;
14         u_int8_t invert;
15 };
16
17 enum {
18         F_MARK = 1 << 0,
19 };
20
21 static void mark_mt_help(void)
22 {
23         printf(
24 "mark match options:\n"
25 "[!] --mark value[/mask]    Match nfmark value with optional mask\n");
26 }
27
28 static const struct option mark_mt_opts[] = {
29         {.name = "mark", .has_arg = true, .val = '1'},
30         { .name = NULL }
31 };
32
33 static int mark_mt_parse(int c, char **argv, int invert, unsigned int *flags,
34                          const void *entry, struct xt_entry_match **match)
35 {
36         struct xt_mark_mtinfo1 *info = (void *)(*match)->data;
37         unsigned int mark, mask = UINT32_MAX;
38         char *end;
39
40         switch (c) {
41         case '1': /* --mark */
42                 xtables_param_act(XTF_ONLY_ONCE, "mark", "--mark", *flags & F_MARK);
43                 if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX))
44                         xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg);
45                 if (*end == '/')
46                         if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
47                                 xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg);
48                 if (*end != '\0')
49                         xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg);
50
51                 if (invert)
52                         info->invert = true;
53                 info->mark = mark;
54                 info->mask = mask;
55                 *flags    |= F_MARK;
56                 return true;
57         }
58         return false;
59 }
60
61 static int
62 mark_parse(int c, char **argv, int invert, unsigned int *flags,
63            const void *entry, struct xt_entry_match **match)
64 {
65         struct xt_mark_info *markinfo = (struct xt_mark_info *)(*match)->data;
66
67         switch (c) {
68                 char *end;
69         case '1':
70                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
71                 markinfo->mark = strtoul(optarg, &end, 0);
72                 if (*end == '/') {
73                         markinfo->mask = strtoul(end+1, &end, 0);
74                 } else
75                         markinfo->mask = 0xffffffff;
76                 if (*end != '\0' || end == optarg)
77                         xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
78                 if (invert)
79                         markinfo->invert = 1;
80                 *flags = 1;
81                 break;
82
83         default:
84                 return 0;
85         }
86         return 1;
87 }
88
89 static void print_mark(unsigned int mark, unsigned int mask)
90 {
91         if (mask != 0xffffffffU)
92                 printf("0x%x/0x%x ", mark, mask);
93         else
94                 printf("0x%x ", mark);
95 }
96
97 static void mark_mt_check(unsigned int flags)
98 {
99         if (flags == 0)
100                 xtables_error(PARAMETER_PROBLEM,
101                            "mark match: The --mark option is required");
102 }
103
104 static void
105 mark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
106 {
107         const struct xt_mark_mtinfo1 *info = (const void *)match->data;
108
109         printf("mark match ");
110         if (info->invert)
111                 printf("!");
112         print_mark(info->mark, info->mask);
113 }
114
115 static void
116 mark_print(const void *ip, const struct xt_entry_match *match, int numeric)
117 {
118         const struct xt_mark_info *info = (const void *)match->data;
119
120         printf("MARK match ");
121
122         if (info->invert)
123                 printf("!");
124         
125         print_mark(info->mark, info->mask);
126 }
127
128 static void mark_mt_save(const void *ip, const struct xt_entry_match *match)
129 {
130         const struct xt_mark_mtinfo1 *info = (const void *)match->data;
131
132         if (info->invert)
133                 printf("! ");
134
135         printf("--mark ");
136         print_mark(info->mark, info->mask);
137 }
138
139 static void
140 mark_save(const void *ip, const struct xt_entry_match *match)
141 {
142         const struct xt_mark_info *info = (const void *)match->data;
143
144         if (info->invert)
145                 printf("! ");
146         
147         printf("--mark ");
148         print_mark(info->mark, info->mask);
149 }
150
151 static struct xtables_match mark_mt_reg[] = {
152         {
153                 .family        = NFPROTO_UNSPEC,
154                 .name          = "mark",
155                 .revision      = 0,
156                 .version       = XTABLES_VERSION,
157                 .size          = XT_ALIGN(sizeof(struct xt_mark_info)),
158                 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_info)),
159                 .help          = mark_mt_help,
160                 .parse         = mark_parse,
161                 .final_check   = mark_mt_check,
162                 .print         = mark_print,
163                 .save          = mark_save,
164                 .extra_opts    = mark_mt_opts,
165         },
166         {
167                 .version       = XTABLES_VERSION,
168                 .name          = "mark",
169                 .revision      = 1,
170                 .family        = NFPROTO_UNSPEC,
171                 .size          = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
172                 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
173                 .help          = mark_mt_help,
174                 .parse         = mark_mt_parse,
175                 .final_check   = mark_mt_check,
176                 .print         = mark_mt_print,
177                 .save          = mark_mt_save,
178                 .extra_opts    = mark_mt_opts,
179         },
180 };
181
182 void _init(void)
183 {
184         xtables_register_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg));
185 }