• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
71 static const struct xt_option_entry mark_tg_arp_opts[] = {
72 	{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32,
73 	 .base = 16, .excl = F_ANY},
74 	{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
75 	 .base = 16, .excl = F_ANY},
76 	{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
77 	 .base = 16, .excl = F_ANY},
78 	XTOPT_TABLEEND,
79 };
80 
mark_tg_help(void)81 static void mark_tg_help(void)
82 {
83 	printf(
84 "MARK target options:\n"
85 "  --set-xmark value[/mask]  Clear bits in mask and XOR value into nfmark\n"
86 "  --set-mark value[/mask]   Clear bits in mask and OR value into nfmark\n"
87 "  --and-mark bits           Binary AND the nfmark with bits\n"
88 "  --or-mark bits            Binary OR the nfmark with bits\n"
89 "  --xor-mark bits           Binary XOR the nfmark with bits\n");
90 }
91 
MARK_parse_v0(struct xt_option_call * cb)92 static void MARK_parse_v0(struct xt_option_call *cb)
93 {
94 	struct xt_mark_target_info *markinfo = cb->data;
95 
96 	xtables_option_parse(cb);
97 	switch (cb->entry->id) {
98 	case O_SET_MARK:
99 		markinfo->mark = cb->val.mark;
100 		break;
101 	default:
102 		xtables_error(PARAMETER_PROBLEM,
103 			   "MARK target: kernel too old for --%s",
104 			   cb->entry->name);
105 	}
106 }
107 
MARK_check(struct xt_fcheck_call * cb)108 static void MARK_check(struct xt_fcheck_call *cb)
109 {
110 	if (cb->xflags == 0)
111 		xtables_error(PARAMETER_PROBLEM,
112 		           "MARK target: Parameter --set/and/or-mark"
113 			   " is required");
114 }
115 
MARK_parse_v1(struct xt_option_call * cb)116 static void MARK_parse_v1(struct xt_option_call *cb)
117 {
118 	struct xt_mark_target_info_v1 *markinfo = cb->data;
119 
120 	xtables_option_parse(cb);
121 	switch (cb->entry->id) {
122 	case O_SET_MARK:
123 	        markinfo->mode = XT_MARK_SET;
124 		break;
125 	case O_AND_MARK:
126 	        markinfo->mode = XT_MARK_AND;
127 		break;
128 	case O_OR_MARK:
129 	        markinfo->mode = XT_MARK_OR;
130 		break;
131 	}
132 	markinfo->mark = cb->val.u32;
133 }
134 
mark_tg_parse(struct xt_option_call * cb)135 static void mark_tg_parse(struct xt_option_call *cb)
136 {
137 	struct xt_mark_tginfo2 *info = cb->data;
138 
139 	xtables_option_parse(cb);
140 	switch (cb->entry->id) {
141 	case O_SET_XMARK:
142 		info->mark = cb->val.mark;
143 		info->mask = cb->val.mask;
144 		break;
145 	case O_SET_MARK:
146 		info->mark = cb->val.mark;
147 		info->mask = cb->val.mark | cb->val.mask;
148 		if (cb->entry->type == XTTYPE_UINT32)
149 			info->mask = UINT32_MAX;
150 		break;
151 	case O_AND_MARK:
152 		info->mark = 0;
153 		info->mask = ~cb->val.u32;
154 		break;
155 	case O_OR_MARK:
156 		info->mark = info->mask = cb->val.u32;
157 		break;
158 	case O_XOR_MARK:
159 		info->mark = cb->val.u32;
160 		info->mask = 0;
161 		break;
162 	}
163 }
164 
mark_tg_check(struct xt_fcheck_call * cb)165 static void mark_tg_check(struct xt_fcheck_call *cb)
166 {
167 	if (cb->xflags == 0)
168 		xtables_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, "
169 		           "--{and,or,xor,set}-mark options is required");
170 }
171 
172 static void
print_mark(unsigned long mark)173 print_mark(unsigned long mark)
174 {
175 	printf(" 0x%lx", mark);
176 }
177 
MARK_print_v0(const void * ip,const struct xt_entry_target * target,int numeric)178 static void MARK_print_v0(const void *ip,
179                           const struct xt_entry_target *target, int numeric)
180 {
181 	const struct xt_mark_target_info *markinfo =
182 		(const struct xt_mark_target_info *)target->data;
183 	printf(" MARK set");
184 	print_mark(markinfo->mark);
185 }
186 
MARK_save_v0(const void * ip,const struct xt_entry_target * target)187 static void MARK_save_v0(const void *ip, const struct xt_entry_target *target)
188 {
189 	const struct xt_mark_target_info *markinfo =
190 		(const struct xt_mark_target_info *)target->data;
191 
192 	printf(" --set-mark");
193 	print_mark(markinfo->mark);
194 }
195 
MARK_print_v1(const void * ip,const struct xt_entry_target * target,int numeric)196 static void MARK_print_v1(const void *ip, const struct xt_entry_target *target,
197                           int numeric)
198 {
199 	const struct xt_mark_target_info_v1 *markinfo =
200 		(const struct xt_mark_target_info_v1 *)target->data;
201 
202 	switch (markinfo->mode) {
203 	case XT_MARK_SET:
204 		printf(" MARK set");
205 		break;
206 	case XT_MARK_AND:
207 		printf(" MARK and");
208 		break;
209 	case XT_MARK_OR:
210 		printf(" MARK or");
211 		break;
212 	}
213 	print_mark(markinfo->mark);
214 }
215 
mark_tg_print(const void * ip,const struct xt_entry_target * target,int numeric)216 static void mark_tg_print(const void *ip, const struct xt_entry_target *target,
217                           int numeric)
218 {
219 	const struct xt_mark_tginfo2 *info = (const void *)target->data;
220 
221 	if (info->mark == 0)
222 		printf(" MARK and 0x%x", (unsigned int)(uint32_t)~info->mask);
223 	else if (info->mark == info->mask)
224 		printf(" MARK or 0x%x", info->mark);
225 	else if (info->mask == 0)
226 		printf(" MARK xor 0x%x", info->mark);
227 	else if (info->mask == 0xffffffffU)
228 		printf(" MARK set 0x%x", info->mark);
229 	else
230 		printf(" MARK xset 0x%x/0x%x", info->mark, info->mask);
231 }
232 
MARK_save_v1(const void * ip,const struct xt_entry_target * target)233 static void MARK_save_v1(const void *ip, const struct xt_entry_target *target)
234 {
235 	const struct xt_mark_target_info_v1 *markinfo =
236 		(const struct xt_mark_target_info_v1 *)target->data;
237 
238 	switch (markinfo->mode) {
239 	case XT_MARK_SET:
240 		printf(" --set-mark");
241 		break;
242 	case XT_MARK_AND:
243 		printf(" --and-mark");
244 		break;
245 	case XT_MARK_OR:
246 		printf(" --or-mark");
247 		break;
248 	}
249 	print_mark(markinfo->mark);
250 }
251 
mark_tg_save(const void * ip,const struct xt_entry_target * target)252 static void mark_tg_save(const void *ip, const struct xt_entry_target *target)
253 {
254 	const struct xt_mark_tginfo2 *info = (const void *)target->data;
255 
256 	printf(" --set-xmark 0x%x/0x%x", info->mark, info->mask);
257 }
258 
mark_tg_arp_save(const void * ip,const struct xt_entry_target * target)259 static void mark_tg_arp_save(const void *ip, const struct xt_entry_target *target)
260 {
261 	const struct xt_mark_tginfo2 *info = (const void *)target->data;
262 
263 	if (info->mark == 0)
264 		printf(" --and-mark %x", (unsigned int)(uint32_t)~info->mask);
265 	else if (info->mark == info->mask)
266 		printf(" --or-mark %x", info->mark);
267 	else
268 		printf(" --set-mark %x", info->mark);
269 }
270 
mark_tg_arp_print(const void * ip,const struct xt_entry_target * target,int numeric)271 static void mark_tg_arp_print(const void *ip,
272 			      const struct xt_entry_target *target, int numeric)
273 {
274 	mark_tg_arp_save(ip, target);
275 }
276 
mark_tg_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)277 static int mark_tg_xlate(struct xt_xlate *xl,
278 			 const struct xt_xlate_tg_params *params)
279 {
280 	const struct xt_mark_tginfo2 *info = (const void *)params->target->data;
281 
282 	xt_xlate_add(xl, "meta mark set ");
283 
284 	if (info->mask == 0xffffffffU)
285 		xt_xlate_add(xl, "0x%x ", info->mark);
286 	else if (info->mark == 0)
287 		xt_xlate_add(xl, "mark and 0x%x ", ~info->mask);
288 	else if (info->mark == info->mask)
289 		xt_xlate_add(xl, "mark or 0x%x ", info->mark);
290 	else if (info->mask == 0)
291 		xt_xlate_add(xl, "mark xor 0x%x ", info->mark);
292 	else
293 		xt_xlate_add(xl, "mark and 0x%x xor 0x%x ", ~info->mask,
294 			     info->mark);
295 
296 	return 1;
297 }
298 
MARK_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)299 static int MARK_xlate(struct xt_xlate *xl,
300 		      const struct xt_xlate_tg_params *params)
301 {
302 	const struct xt_mark_target_info_v1 *markinfo =
303 		(const struct xt_mark_target_info_v1 *)params->target->data;
304 
305 	xt_xlate_add(xl, "meta mark set ");
306 
307 	switch(markinfo->mode) {
308 	case XT_MARK_SET:
309 		xt_xlate_add(xl, "0x%x ", (uint32_t)markinfo->mark);
310 		break;
311 	case XT_MARK_AND:
312 		xt_xlate_add(xl, "mark and 0x%x ", (uint32_t)markinfo->mark);
313 		break;
314 	case XT_MARK_OR:
315 		xt_xlate_add(xl, "mark or 0x%x ", (uint32_t)markinfo->mark);
316 		break;
317 	default:
318 		return 0;
319 	}
320 
321 	return 1;
322 }
323 
324 static struct xtables_target mark_tg_reg[] = {
325 	{
326 		.family        = NFPROTO_UNSPEC,
327 		.name          = "MARK",
328 		.version       = XTABLES_VERSION,
329 		.revision      = 0,
330 		.size          = XT_ALIGN(sizeof(struct xt_mark_target_info)),
331 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
332 		.help          = MARK_help,
333 		.print         = MARK_print_v0,
334 		.save          = MARK_save_v0,
335 		.x6_parse      = MARK_parse_v0,
336 		.x6_fcheck     = MARK_check,
337 		.x6_options    = MARK_opts,
338 	},
339 	{
340 		.family        = NFPROTO_IPV4,
341 		.name          = "MARK",
342 		.version       = XTABLES_VERSION,
343 		.revision      = 1,
344 		.size          = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
345 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
346 		.help          = MARK_help,
347 		.print         = MARK_print_v1,
348 		.save          = MARK_save_v1,
349 		.x6_parse      = MARK_parse_v1,
350 		.x6_fcheck     = MARK_check,
351 		.x6_options    = MARK_opts,
352 		.xlate	       = MARK_xlate,
353 	},
354 	{
355 		.version       = XTABLES_VERSION,
356 		.name          = "MARK",
357 		.revision      = 2,
358 		.family        = NFPROTO_UNSPEC,
359 		.size          = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
360 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
361 		.help          = mark_tg_help,
362 		.print         = mark_tg_print,
363 		.save          = mark_tg_save,
364 		.x6_parse      = mark_tg_parse,
365 		.x6_fcheck     = mark_tg_check,
366 		.x6_options    = mark_tg_opts,
367 		.xlate	       = mark_tg_xlate,
368 	},
369 	{
370 		.version       = XTABLES_VERSION,
371 		.name          = "MARK",
372 		.revision      = 2,
373 		.family        = NFPROTO_ARP,
374 		.size          = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
375 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
376 		.help          = mark_tg_help,
377 		.print         = mark_tg_arp_print,
378 		.save          = mark_tg_arp_save,
379 		.x6_parse      = mark_tg_parse,
380 		.x6_fcheck     = mark_tg_check,
381 		.x6_options    = mark_tg_arp_opts,
382 		.xlate	       = mark_tg_xlate,
383 	},
384 };
385 
_init(void)386 void _init(void)
387 {
388 	xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
389 }
390