• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <getopt.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <xtables.h>
5 #include <linux/netfilter/xt_MARK.h>
6 
7 /* Version 0 */
8 struct xt_mark_target_info {
9 	unsigned long mark;
10 };
11 
12 /* Version 1 */
13 enum {
14 	XT_MARK_SET=0,
15 	XT_MARK_AND,
16 	XT_MARK_OR,
17 };
18 
19 struct xt_mark_target_info_v1 {
20 	unsigned long mark;
21 	uint8_t mode;
22 };
23 
24 enum {
25 	O_SET_MARK = 0,
26 	O_AND_MARK,
27 	O_OR_MARK,
28 	O_XOR_MARK,
29 	O_SET_XMARK,
30 	F_SET_MARK  = 1 << O_SET_MARK,
31 	F_AND_MARK  = 1 << O_AND_MARK,
32 	F_OR_MARK   = 1 << O_OR_MARK,
33 	F_XOR_MARK  = 1 << O_XOR_MARK,
34 	F_SET_XMARK = 1 << O_SET_XMARK,
35 	F_ANY       = F_SET_MARK | F_AND_MARK | F_OR_MARK |
36 	              F_XOR_MARK | F_SET_XMARK,
37 };
38 
MARK_help(void)39 static void MARK_help(void)
40 {
41 	printf(
42 "MARK target options:\n"
43 "  --set-mark value                   Set nfmark value\n"
44 "  --and-mark value                   Binary AND the nfmark with value\n"
45 "  --or-mark  value                   Binary OR  the nfmark with value\n");
46 }
47 
48 static const struct xt_option_entry MARK_opts[] = {
49 	{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32,
50 	 .excl = F_ANY},
51 	{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
52 	 .excl = F_ANY},
53 	{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
54 	 .excl = F_ANY},
55 	XTOPT_TABLEEND,
56 };
57 
58 static const struct xt_option_entry mark_tg_opts[] = {
59 	{.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
60 	 .excl = F_ANY},
61 	{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
62 	 .excl = F_ANY},
63 	{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
64 	 .excl = F_ANY},
65 	{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
66 	 .excl = F_ANY},
67 	{.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
68 	 .excl = F_ANY},
69 	XTOPT_TABLEEND,
70 };
71 
mark_tg_help(void)72 static void mark_tg_help(void)
73 {
74 	printf(
75 "MARK target options:\n"
76 "  --set-xmark value[/mask]  Clear bits in mask and XOR value into nfmark\n"
77 "  --set-mark value[/mask]   Clear bits in mask and OR value into nfmark\n"
78 "  --and-mark bits           Binary AND the nfmark with bits\n"
79 "  --or-mark bits            Binary OR the nfmark with bits\n"
80 "  --xor-mark bits           Binary XOR the nfmark with bits\n"
81 "\n");
82 }
83 
MARK_parse_v0(struct xt_option_call * cb)84 static void MARK_parse_v0(struct xt_option_call *cb)
85 {
86 	struct xt_mark_target_info *markinfo = cb->data;
87 
88 	xtables_option_parse(cb);
89 	switch (cb->entry->id) {
90 	case O_SET_MARK:
91 		markinfo->mark = cb->val.mark;
92 		break;
93 	default:
94 		xtables_error(PARAMETER_PROBLEM,
95 			   "MARK target: kernel too old for --%s",
96 			   cb->entry->name);
97 	}
98 }
99 
MARK_check(struct xt_fcheck_call * cb)100 static void MARK_check(struct xt_fcheck_call *cb)
101 {
102 	if (cb->xflags == 0)
103 		xtables_error(PARAMETER_PROBLEM,
104 		           "MARK target: Parameter --set/and/or-mark"
105 			   " is required");
106 }
107 
MARK_parse_v1(struct xt_option_call * cb)108 static void MARK_parse_v1(struct xt_option_call *cb)
109 {
110 	struct xt_mark_target_info_v1 *markinfo = cb->data;
111 
112 	xtables_option_parse(cb);
113 	switch (cb->entry->id) {
114 	case O_SET_MARK:
115 	        markinfo->mode = XT_MARK_SET;
116 		break;
117 	case O_AND_MARK:
118 	        markinfo->mode = XT_MARK_AND;
119 		break;
120 	case O_OR_MARK:
121 	        markinfo->mode = XT_MARK_OR;
122 		break;
123 	}
124 	markinfo->mark = cb->val.u32;
125 }
126 
mark_tg_parse(struct xt_option_call * cb)127 static void mark_tg_parse(struct xt_option_call *cb)
128 {
129 	struct xt_mark_tginfo2 *info = cb->data;
130 
131 	xtables_option_parse(cb);
132 	switch (cb->entry->id) {
133 	case O_SET_XMARK:
134 		info->mark = cb->val.mark;
135 		info->mask = cb->val.mask;
136 		break;
137 	case O_SET_MARK:
138 		info->mark = cb->val.mark;
139 		info->mask = cb->val.mark | cb->val.mask;
140 		break;
141 	case O_AND_MARK:
142 		info->mark = 0;
143 		info->mask = ~cb->val.u32;
144 		break;
145 	case O_OR_MARK:
146 		info->mark = info->mask = cb->val.u32;
147 		break;
148 	case O_XOR_MARK:
149 		info->mark = cb->val.u32;
150 		info->mask = 0;
151 		break;
152 	}
153 }
154 
mark_tg_check(struct xt_fcheck_call * cb)155 static void mark_tg_check(struct xt_fcheck_call *cb)
156 {
157 	if (cb->xflags == 0)
158 		xtables_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, "
159 		           "--{and,or,xor,set}-mark options is required");
160 }
161 
162 static void
print_mark(unsigned long mark)163 print_mark(unsigned long mark)
164 {
165 	printf(" 0x%lx", mark);
166 }
167 
MARK_print_v0(const void * ip,const struct xt_entry_target * target,int numeric)168 static void MARK_print_v0(const void *ip,
169                           const struct xt_entry_target *target, int numeric)
170 {
171 	const struct xt_mark_target_info *markinfo =
172 		(const struct xt_mark_target_info *)target->data;
173 	printf(" MARK set");
174 	print_mark(markinfo->mark);
175 }
176 
MARK_save_v0(const void * ip,const struct xt_entry_target * target)177 static void MARK_save_v0(const void *ip, const struct xt_entry_target *target)
178 {
179 	const struct xt_mark_target_info *markinfo =
180 		(const struct xt_mark_target_info *)target->data;
181 
182 	printf(" --set-mark");
183 	print_mark(markinfo->mark);
184 }
185 
MARK_print_v1(const void * ip,const struct xt_entry_target * target,int numeric)186 static void MARK_print_v1(const void *ip, const struct xt_entry_target *target,
187                           int numeric)
188 {
189 	const struct xt_mark_target_info_v1 *markinfo =
190 		(const struct xt_mark_target_info_v1 *)target->data;
191 
192 	switch (markinfo->mode) {
193 	case XT_MARK_SET:
194 		printf(" MARK set");
195 		break;
196 	case XT_MARK_AND:
197 		printf(" MARK and");
198 		break;
199 	case XT_MARK_OR:
200 		printf(" MARK or");
201 		break;
202 	}
203 	print_mark(markinfo->mark);
204 }
205 
mark_tg_print(const void * ip,const struct xt_entry_target * target,int numeric)206 static void mark_tg_print(const void *ip, const struct xt_entry_target *target,
207                           int numeric)
208 {
209 	const struct xt_mark_tginfo2 *info = (const void *)target->data;
210 
211 	if (info->mark == 0)
212 		printf(" MARK and 0x%x", (unsigned int)(uint32_t)~info->mask);
213 	else if (info->mark == info->mask)
214 		printf(" MARK or 0x%x", info->mark);
215 	else if (info->mask == 0)
216 		printf(" MARK xor 0x%x", info->mark);
217 	else if (info->mask == 0xffffffffU)
218 		printf(" MARK set 0x%x", info->mark);
219 	else
220 		printf(" MARK xset 0x%x/0x%x", info->mark, info->mask);
221 }
222 
MARK_save_v1(const void * ip,const struct xt_entry_target * target)223 static void MARK_save_v1(const void *ip, const struct xt_entry_target *target)
224 {
225 	const struct xt_mark_target_info_v1 *markinfo =
226 		(const struct xt_mark_target_info_v1 *)target->data;
227 
228 	switch (markinfo->mode) {
229 	case XT_MARK_SET:
230 		printf(" --set-mark");
231 		break;
232 	case XT_MARK_AND:
233 		printf(" --and-mark");
234 		break;
235 	case XT_MARK_OR:
236 		printf(" --or-mark");
237 		break;
238 	}
239 	print_mark(markinfo->mark);
240 }
241 
mark_tg_save(const void * ip,const struct xt_entry_target * target)242 static void mark_tg_save(const void *ip, const struct xt_entry_target *target)
243 {
244 	const struct xt_mark_tginfo2 *info = (const void *)target->data;
245 
246 	printf(" --set-xmark 0x%x/0x%x", info->mark, info->mask);
247 }
248 
mark_tg_arp_save(const void * ip,const struct xt_entry_target * target)249 static void mark_tg_arp_save(const void *ip, const struct xt_entry_target *target)
250 {
251 	const struct xt_mark_tginfo2 *info = (const void *)target->data;
252 
253 	if (info->mark == 0)
254 		printf(" --and-mark %x", (unsigned int)(uint32_t)~info->mask);
255 	else if (info->mark == info->mask)
256 		printf(" --or-mark %x", info->mark);
257 	else
258 		printf(" --set-mark %x", info->mark);
259 }
260 
mark_tg_arp_print(const void * ip,const struct xt_entry_target * target,int numeric)261 static void mark_tg_arp_print(const void *ip,
262 			      const struct xt_entry_target *target, int numeric)
263 {
264 	mark_tg_arp_save(ip, target);
265 }
266 
267 #define MARK_OPT 1
268 #define AND_MARK_OPT 2
269 #define OR_MARK_OPT 3
270 
271 static struct option mark_tg_arp_opts[] = {
272 	{ .name = "set-mark", .has_arg = required_argument, .flag = 0, .val = MARK_OPT },
273 	{ .name = "and-mark", .has_arg = required_argument, .flag = 0, .val = AND_MARK_OPT },
274 	{ .name = "or-mark", .has_arg = required_argument, .flag = 0, .val =  OR_MARK_OPT },
275 	{ .name = NULL}
276 };
277 
278 static int
mark_tg_arp_parse(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_target ** target)279 mark_tg_arp_parse(int c, char **argv, int invert, unsigned int *flags,
280 		  const void *entry, struct xt_entry_target **target)
281 {
282 	struct xt_mark_tginfo2 *info =
283 		(struct xt_mark_tginfo2 *)(*target)->data;
284 	int i;
285 
286 	switch (c) {
287 	case MARK_OPT:
288 		if (sscanf(argv[optind-1], "%x", &i) != 1) {
289 			xtables_error(PARAMETER_PROBLEM,
290 				"Bad mark value `%s'", optarg);
291 			return 0;
292 		}
293 		info->mark = i;
294 		if (*flags)
295 			xtables_error(PARAMETER_PROBLEM,
296 				"MARK: Can't specify --set-mark twice");
297 		*flags = 1;
298 		break;
299 	case AND_MARK_OPT:
300 		if (sscanf(argv[optind-1], "%x", &i) != 1) {
301 			xtables_error(PARAMETER_PROBLEM,
302 				"Bad mark value `%s'", optarg);
303 			return 0;
304 		}
305 		info->mark = 0;
306 		info->mask = ~i;
307 		if (*flags)
308 			xtables_error(PARAMETER_PROBLEM,
309 				"MARK: Can't specify --and-mark twice");
310 		*flags = 1;
311 		break;
312 	case OR_MARK_OPT:
313 		if (sscanf(argv[optind-1], "%x", &i) != 1) {
314 			xtables_error(PARAMETER_PROBLEM,
315 				"Bad mark value `%s'", optarg);
316 			return 0;
317 		}
318 		info->mark = info->mask = i;
319 		if (*flags)
320 			xtables_error(PARAMETER_PROBLEM,
321 				"MARK: Can't specify --or-mark twice");
322 		*flags = 1;
323 		break;
324 	default:
325 		return 0;
326 	}
327 	return 1;
328 }
329 
mark_tg_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)330 static int mark_tg_xlate(struct xt_xlate *xl,
331 			 const struct xt_xlate_tg_params *params)
332 {
333 	const struct xt_mark_tginfo2 *info = (const void *)params->target->data;
334 
335 	xt_xlate_add(xl, "meta mark set ");
336 
337 	if (info->mask == 0xffffffffU)
338 		xt_xlate_add(xl, "0x%x ", info->mark);
339 	else if (info->mark == 0)
340 		xt_xlate_add(xl, "mark and 0x%x ", ~info->mask);
341 	else if (info->mark == info->mask)
342 		xt_xlate_add(xl, "mark or 0x%x ", info->mark);
343 	else if (info->mask == 0)
344 		xt_xlate_add(xl, "mark xor 0x%x ", info->mark);
345 	else
346 		xt_xlate_add(xl, "mark and 0x%x xor 0x%x ", ~info->mask,
347 			     info->mark);
348 
349 	return 1;
350 }
351 
MARK_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)352 static int MARK_xlate(struct xt_xlate *xl,
353 		      const struct xt_xlate_tg_params *params)
354 {
355 	const struct xt_mark_target_info_v1 *markinfo =
356 		(const struct xt_mark_target_info_v1 *)params->target->data;
357 
358 	xt_xlate_add(xl, "meta mark set ");
359 
360 	switch(markinfo->mode) {
361 	case XT_MARK_SET:
362 		xt_xlate_add(xl, "0x%x ", (uint32_t)markinfo->mark);
363 		break;
364 	case XT_MARK_AND:
365 		xt_xlate_add(xl, "mark and 0x%x ", (uint32_t)markinfo->mark);
366 		break;
367 	case XT_MARK_OR:
368 		xt_xlate_add(xl, "mark or 0x%x ", (uint32_t)markinfo->mark);
369 		break;
370 	}
371 
372 	return 1;
373 }
374 
375 static struct xtables_target mark_tg_reg[] = {
376 	{
377 		.family        = NFPROTO_UNSPEC,
378 		.name          = "MARK",
379 		.version       = XTABLES_VERSION,
380 		.revision      = 0,
381 		.size          = XT_ALIGN(sizeof(struct xt_mark_target_info)),
382 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
383 		.help          = MARK_help,
384 		.print         = MARK_print_v0,
385 		.save          = MARK_save_v0,
386 		.x6_parse      = MARK_parse_v0,
387 		.x6_fcheck     = MARK_check,
388 		.x6_options    = MARK_opts,
389 	},
390 	{
391 		.family        = NFPROTO_IPV4,
392 		.name          = "MARK",
393 		.version       = XTABLES_VERSION,
394 		.revision      = 1,
395 		.size          = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
396 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
397 		.help          = MARK_help,
398 		.print         = MARK_print_v1,
399 		.save          = MARK_save_v1,
400 		.x6_parse      = MARK_parse_v1,
401 		.x6_fcheck     = MARK_check,
402 		.x6_options    = MARK_opts,
403 		.xlate	       = MARK_xlate,
404 	},
405 	{
406 		.version       = XTABLES_VERSION,
407 		.name          = "MARK",
408 		.revision      = 2,
409 		.family        = NFPROTO_UNSPEC,
410 		.size          = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
411 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
412 		.help          = mark_tg_help,
413 		.print         = mark_tg_print,
414 		.save          = mark_tg_save,
415 		.x6_parse      = mark_tg_parse,
416 		.x6_fcheck     = mark_tg_check,
417 		.x6_options    = mark_tg_opts,
418 		.xlate	       = mark_tg_xlate,
419 	},
420 	{
421 		.version       = XTABLES_VERSION,
422 		.name          = "MARK",
423 		.revision      = 2,
424 		.family        = NFPROTO_ARP,
425 		.size          = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
426 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
427 		.help          = mark_tg_help,
428 		.print         = mark_tg_arp_print,
429 		.save          = mark_tg_arp_save,
430 		.parse         = mark_tg_arp_parse,
431 		.extra_opts    = mark_tg_arp_opts,
432 	},
433 };
434 
_init(void)435 void _init(void)
436 {
437 	xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
438 }
439