libxt_mark.c revision 350661a6eb089f3e54e67e022db9e16ea280499f
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
12struct xt_mark_info {
13	unsigned long mark, mask;
14	u_int8_t invert;
15};
16
17enum {
18	F_MARK = 1 << 0,
19};
20
21static 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
28static const struct option mark_mt_opts[] = {
29	{.name = "mark", .has_arg = true, .val = '1'},
30	{ .name = NULL }
31};
32
33static 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
61static int
62mark_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
89static 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
97static 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
104static void
105mark_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
115static void
116mark_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
128static 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
139static void
140mark_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
151static 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
182void _init(void)
183{
184	xtables_register_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg));
185}
186