libxt_connmark.c revision 350661a6eb089f3e54e67e022db9e16ea280499f
1/* Shared library add-on to iptables to add connmark matching support.
2 *
3 * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
4 * by Henrik Nordstrom <hno@marasystems.com>
5 *
6 * Version 1.1
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 */
22#include <stdio.h>
23#include <netdb.h>
24#include <string.h>
25#include <stdlib.h>
26#include <getopt.h>
27
28#include <xtables.h>
29#include <linux/netfilter/xt_connmark.h>
30
31struct xt_connmark_info {
32	unsigned long mark, mask;
33	u_int8_t invert;
34};
35
36enum {
37	F_MARK = 1 << 0,
38};
39
40static void connmark_mt_help(void)
41{
42	printf(
43"connmark match options:\n"
44"[!] --mark value[/mask]    Match ctmark value with optional mask\n");
45}
46
47static const struct option connmark_mt_opts[] = {
48	{.name = "mark", .has_arg = true, .val = '1'},
49	{ .name = NULL }
50};
51
52static int
53connmark_mt_parse(int c, char **argv, int invert, unsigned int *flags,
54                  const void *entry, struct xt_entry_match **match)
55{
56	struct xt_connmark_mtinfo1 *info = (void *)(*match)->data;
57	unsigned int mark, mask = UINT32_MAX;
58	char *end;
59
60	switch (c) {
61	case '1': /* --mark */
62		xtables_param_act(XTF_ONLY_ONCE, "connmark", "--mark", *flags & F_MARK);
63		if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX))
64			xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
65		if (*end == '/')
66			if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
67				xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
68		if (*end != '\0')
69			xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
70
71		if (invert)
72			info->invert = true;
73		info->mark = mark;
74		info->mask = mask;
75		*flags    |= F_MARK;
76		return true;
77	}
78	return false;
79}
80
81static int
82connmark_parse(int c, char **argv, int invert, unsigned int *flags,
83               const void *entry, struct xt_entry_match **match)
84{
85	struct xt_connmark_info *markinfo = (struct xt_connmark_info *)(*match)->data;
86
87	switch (c) {
88		char *end;
89	case '1':
90		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
91
92		markinfo->mark = strtoul(optarg, &end, 0);
93		markinfo->mask = 0xffffffffUL;
94
95		if (*end == '/')
96			markinfo->mask = strtoul(end+1, &end, 0);
97
98		if (*end != '\0' || end == optarg)
99			xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
100		if (invert)
101			markinfo->invert = 1;
102		*flags = 1;
103		break;
104
105	default:
106		return 0;
107	}
108	return 1;
109}
110
111static void print_mark(unsigned int mark, unsigned int mask)
112{
113	if (mask != 0xffffffffU)
114		printf("0x%x/0x%x ", mark, mask);
115	else
116		printf("0x%x ", mark);
117}
118
119static void connmark_mt_check(unsigned int flags)
120{
121	if (flags == 0)
122		xtables_error(PARAMETER_PROBLEM,
123		           "connmark: The --mark option is required");
124}
125
126static void
127connmark_print(const void *ip, const struct xt_entry_match *match, int numeric)
128{
129	const struct xt_connmark_info *info = (const void *)match->data;
130
131	printf("CONNMARK match ");
132	if (info->invert)
133		printf("!");
134	print_mark(info->mark, info->mask);
135}
136
137static void
138connmark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
139{
140	const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
141
142	printf("connmark match ");
143	if (info->invert)
144		printf("!");
145	print_mark(info->mark, info->mask);
146}
147
148static void connmark_save(const void *ip, const struct xt_entry_match *match)
149{
150	const struct xt_connmark_info *info = (const void *)match->data;
151
152	if (info->invert)
153		printf("! ");
154
155	printf("--mark ");
156	print_mark(info->mark, info->mask);
157}
158
159static void
160connmark_mt_save(const void *ip, const struct xt_entry_match *match)
161{
162	const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
163
164	if (info->invert)
165		printf("! ");
166
167	printf("--mark ");
168	print_mark(info->mark, info->mask);
169}
170
171static struct xtables_match connmark_mt_reg[] = {
172	{
173		.family        = NFPROTO_UNSPEC,
174		.name          = "connmark",
175		.revision      = 0,
176		.version       = XTABLES_VERSION,
177		.size          = XT_ALIGN(sizeof(struct xt_connmark_info)),
178		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_info)),
179		.help          = connmark_mt_help,
180		.parse         = connmark_parse,
181		.final_check   = connmark_mt_check,
182		.print         = connmark_print,
183		.save          = connmark_save,
184		.extra_opts    = connmark_mt_opts,
185	},
186	{
187		.version       = XTABLES_VERSION,
188		.name          = "connmark",
189		.revision      = 1,
190		.family        = NFPROTO_UNSPEC,
191		.size          = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
192		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
193		.help          = connmark_mt_help,
194		.parse         = connmark_mt_parse,
195		.final_check   = connmark_mt_check,
196		.print         = connmark_mt_print,
197		.save          = connmark_mt_save,
198		.extra_opts    = connmark_mt_opts,
199	},
200};
201
202void _init(void)
203{
204	xtables_register_matches(connmark_mt_reg, ARRAY_SIZE(connmark_mt_reg));
205}
206