libxt_mark.c revision 73866357e4a7a0fdc1b293bf8863fee2bd56da9e
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	uint8_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	XT_GETOPT_TABLEEND,
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	return 1;
84}
85
86static void print_mark(unsigned int mark, unsigned int mask)
87{
88	if (mask != 0xffffffffU)
89		printf(" 0x%x/0x%x", mark, mask);
90	else
91		printf(" 0x%x", mark);
92}
93
94static void mark_mt_check(unsigned int flags)
95{
96	if (flags == 0)
97		xtables_error(PARAMETER_PROBLEM,
98			   "mark match: The --mark option is required");
99}
100
101static void
102mark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
103{
104	const struct xt_mark_mtinfo1 *info = (const void *)match->data;
105
106	printf(" mark match");
107	if (info->invert)
108		printf(" !");
109	print_mark(info->mark, info->mask);
110}
111
112static void
113mark_print(const void *ip, const struct xt_entry_match *match, int numeric)
114{
115	const struct xt_mark_info *info = (const void *)match->data;
116
117	printf(" MARK match");
118
119	if (info->invert)
120		printf(" !");
121
122	print_mark(info->mark, info->mask);
123}
124
125static void mark_mt_save(const void *ip, const struct xt_entry_match *match)
126{
127	const struct xt_mark_mtinfo1 *info = (const void *)match->data;
128
129	if (info->invert)
130		printf(" !");
131
132	printf(" --mark");
133	print_mark(info->mark, info->mask);
134}
135
136static void
137mark_save(const void *ip, const struct xt_entry_match *match)
138{
139	const struct xt_mark_info *info = (const void *)match->data;
140
141	if (info->invert)
142		printf(" !");
143
144	printf(" --mark");
145	print_mark(info->mark, info->mask);
146}
147
148static struct xtables_match mark_mt_reg[] = {
149	{
150		.family        = NFPROTO_UNSPEC,
151		.name          = "mark",
152		.revision      = 0,
153		.version       = XTABLES_VERSION,
154		.size          = XT_ALIGN(sizeof(struct xt_mark_info)),
155		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_info)),
156		.help          = mark_mt_help,
157		.parse         = mark_parse,
158		.final_check   = mark_mt_check,
159		.print         = mark_print,
160		.save          = mark_save,
161		.extra_opts    = mark_mt_opts,
162	},
163	{
164		.version       = XTABLES_VERSION,
165		.name          = "mark",
166		.revision      = 1,
167		.family        = NFPROTO_UNSPEC,
168		.size          = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
169		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
170		.help          = mark_mt_help,
171		.parse         = mark_mt_parse,
172		.final_check   = mark_mt_check,
173		.print         = mark_mt_print,
174		.save          = mark_mt_save,
175		.extra_opts    = mark_mt_opts,
176	},
177};
178
179void _init(void)
180{
181	xtables_register_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg));
182}
183