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
MARK_help(void)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
mark_tg_help(void)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
MARK_parse_v0(struct xt_option_call * cb)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
MARK_check(struct xt_fcheck_call * cb)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
MARK_parse_v1(struct xt_option_call * cb)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
mark_tg_parse(struct xt_option_call * cb)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
mark_tg_check(struct xt_fcheck_call * cb)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
print_mark(unsigned long mark)162 print_mark(unsigned long mark)
163 {
164 printf(" 0x%lx", mark);
165 }
166
MARK_print_v0(const void * ip,const struct xt_entry_target * target,int numeric)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
MARK_save_v0(const void * ip,const struct xt_entry_target * target)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
MARK_print_v1(const void * ip,const struct xt_entry_target * target,int numeric)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
mark_tg_print(const void * ip,const struct xt_entry_target * target,int numeric)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
MARK_save_v1(const void * ip,const struct xt_entry_target * target)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
mark_tg_save(const void * ip,const struct xt_entry_target * target)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
mark_tg_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)248 static int mark_tg_xlate(struct xt_xlate *xl,
249 const struct xt_xlate_tg_params *params)
250 {
251 const struct xt_mark_tginfo2 *info = (const void *)params->target->data;
252
253 xt_xlate_add(xl, "meta mark set ");
254
255 if (info->mark == 0)
256 xt_xlate_add(xl, "mark and 0x%x ", ~info->mask);
257 else if (info->mark == info->mask)
258 xt_xlate_add(xl, "mark or 0x%x ", info->mark);
259 else if (info->mask == 0)
260 xt_xlate_add(xl, "mark xor 0x%x ", info->mark);
261 else if (info->mask == 0xffffffffU)
262 xt_xlate_add(xl, "0x%x ", info->mark);
263 else
264 xt_xlate_add(xl, "mark and 0x%x xor 0x%x ", ~info->mask,
265 info->mark);
266
267 return 1;
268 }
269
MARK_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)270 static int MARK_xlate(struct xt_xlate *xl,
271 const struct xt_xlate_tg_params *params)
272 {
273 const struct xt_mark_target_info_v1 *markinfo =
274 (const struct xt_mark_target_info_v1 *)params->target->data;
275
276 xt_xlate_add(xl, "meta mark set ");
277
278 switch(markinfo->mode) {
279 case XT_MARK_SET:
280 xt_xlate_add(xl, "0x%x ", markinfo->mark);
281 break;
282 case XT_MARK_AND:
283 xt_xlate_add(xl, "mark and 0x%x ", markinfo->mark);
284 break;
285 case XT_MARK_OR:
286 xt_xlate_add(xl, "mark or 0x%x ", markinfo->mark);
287 break;
288 }
289
290 return 1;
291 }
292
293 static struct xtables_target mark_tg_reg[] = {
294 {
295 .family = NFPROTO_UNSPEC,
296 .name = "MARK",
297 .version = XTABLES_VERSION,
298 .revision = 0,
299 .size = XT_ALIGN(sizeof(struct xt_mark_target_info)),
300 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
301 .help = MARK_help,
302 .print = MARK_print_v0,
303 .save = MARK_save_v0,
304 .x6_parse = MARK_parse_v0,
305 .x6_fcheck = MARK_check,
306 .x6_options = MARK_opts,
307 },
308 {
309 .family = NFPROTO_IPV4,
310 .name = "MARK",
311 .version = XTABLES_VERSION,
312 .revision = 1,
313 .size = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
314 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
315 .help = MARK_help,
316 .print = MARK_print_v1,
317 .save = MARK_save_v1,
318 .x6_parse = MARK_parse_v1,
319 .x6_fcheck = MARK_check,
320 .x6_options = MARK_opts,
321 .xlate = MARK_xlate,
322 },
323 {
324 .version = XTABLES_VERSION,
325 .name = "MARK",
326 .revision = 2,
327 .family = NFPROTO_UNSPEC,
328 .size = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
329 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
330 .help = mark_tg_help,
331 .print = mark_tg_print,
332 .save = mark_tg_save,
333 .x6_parse = mark_tg_parse,
334 .x6_fcheck = mark_tg_check,
335 .x6_options = mark_tg_opts,
336 .xlate = mark_tg_xlate,
337 },
338 };
339
_init(void)340 void _init(void)
341 {
342 xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
343 }
344