libxt_connmark.c revision ddac6c5bc636003d664d25c08ea3fe176565096c
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
31enum {
32	F_MARK = 1 << 0,
33};
34
35static void connmark_mt_help(void)
36{
37	printf(
38"connmark match options:\n"
39"[!] --mark value[/mask]    Match ctmark value with optional mask\n");
40}
41
42static const struct option connmark_mt_opts[] = {
43	{.name = "mark", .has_arg = true, .val = '1'},
44	{ .name = NULL }
45};
46
47static int
48connmark_mt_parse(int c, char **argv, int invert, unsigned int *flags,
49                  const void *entry, struct xt_entry_match **match)
50{
51	struct xt_connmark_mtinfo1 *info = (void *)(*match)->data;
52	unsigned int mark, mask = ~0U;
53	char *end;
54
55	switch (c) {
56	case '1': /* --mark */
57		param_act(P_ONLY_ONCE, "connmark", "--mark", *flags & F_MARK);
58		if (!strtonum(optarg, &end, &mark, 0, ~0U))
59			param_act(P_BAD_VALUE, "connmark", "--mark", optarg);
60		if (*end == '/')
61			if (!strtonum(end + 1, &end, &mask, 0, ~0U))
62				param_act(P_BAD_VALUE, "connmark", "--mark", optarg);
63		if (*end != '\0')
64			param_act(P_BAD_VALUE, "connmark", "--mark", optarg);
65
66		if (invert)
67			info->invert = true;
68		info->mark = mark;
69		info->mask = mask;
70		*flags    |= F_MARK;
71		return true;
72	}
73	return false;
74}
75
76static int
77connmark_parse(int c, char **argv, int invert, unsigned int *flags,
78               const void *entry, struct xt_entry_match **match)
79{
80	struct xt_connmark_info *markinfo = (struct xt_connmark_info *)(*match)->data;
81
82	switch (c) {
83		char *end;
84	case '1':
85		check_inverse(optarg, &invert, &optind, 0);
86
87		markinfo->mark = strtoul(optarg, &end, 0);
88		markinfo->mask = 0xffffffffUL;
89
90		if (*end == '/')
91			markinfo->mask = strtoul(end+1, &end, 0);
92
93		if (*end != '\0' || end == optarg)
94			exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
95		if (invert)
96			markinfo->invert = 1;
97		*flags = 1;
98		break;
99
100	default:
101		return 0;
102	}
103	return 1;
104}
105
106static void print_mark(unsigned int mark, unsigned int mask)
107{
108	if (mask != 0xffffffffU)
109		printf("0x%x/0x%x ", mark, mask);
110	else
111		printf("0x%x ", mark);
112}
113
114static void connmark_mt_check(unsigned int flags)
115{
116	if (flags == 0)
117		exit_error(PARAMETER_PROBLEM,
118		           "connmark: The --mark option is required");
119}
120
121static void
122connmark_print(const void *ip, const struct xt_entry_match *match, int numeric)
123{
124	struct xt_connmark_info *info = (struct xt_connmark_info *)match->data;
125
126	printf("CONNMARK match ");
127	if (info->invert)
128		printf("!");
129	print_mark(info->mark, info->mask);
130}
131
132static void
133connmark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
134{
135	const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
136
137	printf("connmark match ");
138	if (info->invert)
139		printf("!");
140	print_mark(info->mark, info->mask);
141}
142
143static void connmark_save(const void *ip, const struct xt_entry_match *match)
144{
145	struct xt_connmark_info *info = (struct xt_connmark_info *)match->data;
146
147	if (info->invert)
148		printf("! ");
149
150	printf("--mark ");
151	print_mark(info->mark, info->mask);
152}
153
154static void
155connmark_mt_save(const void *ip, const struct xt_entry_match *match)
156{
157	const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
158
159	if (info->invert)
160		printf("! ");
161
162	printf("--mark ");
163	print_mark(info->mark, info->mask);
164}
165
166static struct xtables_match connmark_mt_reg_v0 = {
167	.family		= AF_INET,
168	.name		= "connmark",
169	.revision	= 0,
170	.version	= XTABLES_VERSION,
171	.size		= XT_ALIGN(sizeof(struct xt_connmark_info)),
172	.userspacesize	= XT_ALIGN(sizeof(struct xt_connmark_info)),
173	.help		= connmark_mt_help,
174	.parse		= connmark_parse,
175	.final_check	= connmark_mt_check,
176	.print		= connmark_print,
177	.save		= connmark_save,
178	.extra_opts	= connmark_mt_opts,
179};
180
181static struct xtables_match connmark_mt6_reg_v0 = {
182	.family		= AF_INET6,
183	.name		= "connmark",
184	.revision	= 0,
185	.version	= XTABLES_VERSION,
186	.size		= XT_ALIGN(sizeof(struct xt_connmark_info)),
187	.userspacesize	= XT_ALIGN(sizeof(struct xt_connmark_info)),
188	.help		= connmark_mt_help,
189	.parse		= connmark_parse,
190	.final_check	= connmark_mt_check,
191	.print		= connmark_print,
192	.save		= connmark_save,
193	.extra_opts	= connmark_mt_opts,
194};
195
196static struct xtables_match connmark_mt_reg = {
197	.version        = XTABLES_VERSION,
198	.name           = "connmark",
199	.revision       = 1,
200	.family         = AF_INET,
201	.size           = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
202	.userspacesize  = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
203	.help           = connmark_mt_help,
204	.parse          = connmark_mt_parse,
205	.final_check    = connmark_mt_check,
206	.print          = connmark_mt_print,
207	.save           = connmark_mt_save,
208	.extra_opts     = connmark_mt_opts,
209};
210
211static struct xtables_match connmark_mt6_reg = {
212	.version        = XTABLES_VERSION,
213	.name           = "connmark",
214	.revision       = 1,
215	.family         = AF_INET6,
216	.size           = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
217	.userspacesize  = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
218	.help           = connmark_mt_help,
219	.parse          = connmark_mt_parse,
220	.final_check    = connmark_mt_check,
221	.print          = connmark_mt_print,
222	.save           = connmark_mt_save,
223	.extra_opts     = connmark_mt_opts,
224};
225
226void _init(void)
227{
228	xtables_register_match(&connmark_mt_reg_v0);
229	xtables_register_match(&connmark_mt6_reg_v0);
230	xtables_register_match(&connmark_mt_reg);
231	xtables_register_match(&connmark_mt6_reg);
232}
233