Imported Upstream version 1.4.14
[platform/upstream/iptables.git] / extensions / libxt_MARK.c
1 #include <stdbool.h>
2 #include <stdio.h>
3 #include <xtables.h>
4 #include <linux/netfilter/xt_MARK.h>
5
6 /* Version 0 */
7 struct xt_mark_target_info {
8         unsigned long mark;
9 };
10
11 /* Version 1 */
12 enum {
13         XT_MARK_SET=0,
14         XT_MARK_AND,
15         XT_MARK_OR,
16 };
17
18 struct xt_mark_target_info_v1 {
19         unsigned long mark;
20         uint8_t mode;
21 };
22
23 enum {
24         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,
36 };
37
38 static void MARK_help(void)
39 {
40         printf(
41 "MARK target options:\n"
42 "  --set-mark value                   Set nfmark value\n"
43 "  --and-mark value                   Binary AND the nfmark with value\n"
44 "  --or-mark  value                   Binary OR  the nfmark with value\n");
45 }
46
47 static 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,
55 };
56
57 static 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,
69 };
70
71 static 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
83 static void MARK_parse_v0(struct xt_option_call *cb)
84 {
85         struct xt_mark_target_info *markinfo = cb->data;
86
87         xtables_option_parse(cb);
88         switch (cb->entry->id) {
89         case O_SET_MARK:
90                 markinfo->mark = cb->val.mark;
91                 break;
92         default:
93                 xtables_error(PARAMETER_PROBLEM,
94                            "MARK target: kernel too old for --%s",
95                            cb->entry->name);
96         }
97 }
98
99 static void MARK_check(struct xt_fcheck_call *cb)
100 {
101         if (cb->xflags == 0)
102                 xtables_error(PARAMETER_PROBLEM,
103                            "MARK target: Parameter --set/and/or-mark"
104                            " is required");
105 }
106
107 static void MARK_parse_v1(struct xt_option_call *cb)
108 {
109         struct xt_mark_target_info_v1 *markinfo = cb->data;
110
111         xtables_option_parse(cb);
112         switch (cb->entry->id) {
113         case O_SET_MARK:
114                 markinfo->mode = XT_MARK_SET;
115                 break;
116         case O_AND_MARK:
117                 markinfo->mode = XT_MARK_AND;
118                 break;
119         case O_OR_MARK:
120                 markinfo->mode = XT_MARK_OR;
121                 break;
122         }
123         markinfo->mark = cb->val.u32;
124 }
125
126 static void mark_tg_parse(struct xt_option_call *cb)
127 {
128         struct xt_mark_tginfo2 *info = cb->data;
129
130         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;
135                 break;
136         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:
141                 info->mark = 0;
142                 info->mask = ~cb->val.u32;
143                 break;
144         case O_OR_MARK:
145                 info->mark = info->mask = cb->val.u32;
146                 break;
147         case O_XOR_MARK:
148                 info->mark = cb->val.u32;
149                 info->mask = 0;
150                 break;
151         }
152 }
153
154 static void mark_tg_check(struct xt_fcheck_call *cb)
155 {
156         if (cb->xflags == 0)
157                 xtables_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, "
158                            "--{and,or,xor,set}-mark options is required");
159 }
160
161 static void
162 print_mark(unsigned long mark)
163 {
164         printf(" 0x%lx", mark);
165 }
166
167 static void MARK_print_v0(const void *ip,
168                           const struct xt_entry_target *target, int numeric)
169 {
170         const struct xt_mark_target_info *markinfo =
171                 (const struct xt_mark_target_info *)target->data;
172         printf(" MARK set");
173         print_mark(markinfo->mark);
174 }
175
176 static void MARK_save_v0(const void *ip, const struct xt_entry_target *target)
177 {
178         const struct xt_mark_target_info *markinfo =
179                 (const struct xt_mark_target_info *)target->data;
180
181         printf(" --set-mark");
182         print_mark(markinfo->mark);
183 }
184
185 static void MARK_print_v1(const void *ip, const struct xt_entry_target *target,
186                           int numeric)
187 {
188         const struct xt_mark_target_info_v1 *markinfo =
189                 (const struct xt_mark_target_info_v1 *)target->data;
190
191         switch (markinfo->mode) {
192         case XT_MARK_SET:
193                 printf(" MARK set");
194                 break;
195         case XT_MARK_AND:
196                 printf(" MARK and");
197                 break;
198         case XT_MARK_OR: 
199                 printf(" MARK or");
200                 break;
201         }
202         print_mark(markinfo->mark);
203 }
204
205 static 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)
211                 printf(" MARK and 0x%x", (unsigned int)(uint32_t)~info->mask);
212         else if (info->mark == info->mask)
213                 printf(" MARK or 0x%x", info->mark);
214         else if (info->mask == 0)
215                 printf(" MARK xor 0x%x", info->mark);
216         else if (info->mask == 0xffffffffU)
217                 printf(" MARK set 0x%x", info->mark);
218         else
219                 printf(" MARK xset 0x%x/0x%x", info->mark, info->mask);
220 }
221
222 static void MARK_save_v1(const void *ip, const struct xt_entry_target *target)
223 {
224         const struct xt_mark_target_info_v1 *markinfo =
225                 (const struct xt_mark_target_info_v1 *)target->data;
226
227         switch (markinfo->mode) {
228         case XT_MARK_SET:
229                 printf(" --set-mark");
230                 break;
231         case XT_MARK_AND:
232                 printf(" --and-mark");
233                 break;
234         case XT_MARK_OR: 
235                 printf(" --or-mark");
236                 break;
237         }
238         print_mark(markinfo->mark);
239 }
240
241 static 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
245         printf(" --set-xmark 0x%x/0x%x", info->mark, info->mask);
246 }
247
248 static 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,
257                 .print         = MARK_print_v0,
258                 .save          = MARK_save_v0,
259                 .x6_parse      = MARK_parse_v0,
260                 .x6_fcheck     = MARK_check,
261                 .x6_options    = MARK_opts,
262         },
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,
271                 .print         = MARK_print_v1,
272                 .save          = MARK_save_v1,
273                 .x6_parse      = MARK_parse_v1,
274                 .x6_fcheck     = MARK_check,
275                 .x6_options    = MARK_opts,
276         },
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,
285                 .print         = mark_tg_print,
286                 .save          = mark_tg_save,
287                 .x6_parse      = mark_tg_parse,
288                 .x6_fcheck     = mark_tg_check,
289                 .x6_options    = mark_tg_opts,
290         },
291 };
292
293 void _init(void)
294 {
295         xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
296 }