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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 */
22#include <stdbool.h>
23#include <stdint.h>
24#include <stdio.h>
25#include <xtables.h>
26#include <linux/netfilter/xt_connmark.h>
27
28struct xt_connmark_info {
29	unsigned long mark, mask;
30	uint8_t invert;
31};
32
33enum {
34	O_MARK = 0,
35};
36
37static void connmark_mt_help(void)
38{
39	printf(
40"connmark match options:\n"
41"[!] --mark value[/mask]    Match ctmark value with optional mask\n");
42}
43
44static const struct xt_option_entry connmark_mt_opts[] = {
45	{.name = "mark", .id = O_MARK, .type = XTTYPE_MARKMASK32,
46	 .flags = XTOPT_MAND | XTOPT_INVERT},
47	XTOPT_TABLEEND,
48};
49
50static void connmark_mt_parse(struct xt_option_call *cb)
51{
52	struct xt_connmark_mtinfo1 *info = cb->data;
53
54	xtables_option_parse(cb);
55	if (cb->invert)
56		info->invert = true;
57	info->mark = cb->val.mark;
58	info->mask = cb->val.mask;
59}
60
61static void connmark_parse(struct xt_option_call *cb)
62{
63	struct xt_connmark_info *markinfo = cb->data;
64
65	xtables_option_parse(cb);
66	markinfo->mark = cb->val.mark;
67	markinfo->mask = cb->val.mask;
68	if (cb->invert)
69		markinfo->invert = 1;
70}
71
72static void print_mark(unsigned int mark, unsigned int mask)
73{
74	if (mask != 0xffffffffU)
75		printf(" 0x%x/0x%x", mark, mask);
76	else
77		printf(" 0x%x", mark);
78}
79
80static void
81connmark_print(const void *ip, const struct xt_entry_match *match, int numeric)
82{
83	const struct xt_connmark_info *info = (const void *)match->data;
84
85	printf(" CONNMARK match ");
86	if (info->invert)
87		printf("!");
88	print_mark(info->mark, info->mask);
89}
90
91static void
92connmark_mt_print(const void *ip, const struct xt_entry_match *match,
93		  int numeric)
94{
95	const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
96
97	printf(" connmark match ");
98	if (info->invert)
99		printf("!");
100	print_mark(info->mark, info->mask);
101}
102
103static void connmark_save(const void *ip, const struct xt_entry_match *match)
104{
105	const struct xt_connmark_info *info = (const void *)match->data;
106
107	if (info->invert)
108		printf(" !");
109
110	printf(" --mark");
111	print_mark(info->mark, info->mask);
112}
113
114static void
115connmark_mt_save(const void *ip, const struct xt_entry_match *match)
116{
117	const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
118
119	if (info->invert)
120		printf(" !");
121
122	printf(" --mark");
123	print_mark(info->mark, info->mask);
124}
125
126static void print_mark_xlate(unsigned int mark, unsigned int mask,
127			     struct xt_xlate *xl, uint32_t op)
128{
129	if (mask != 0xffffffffU)
130		xt_xlate_add(xl, " and 0x%x %s 0x%x", mask,
131			   op == XT_OP_EQ ? "==" : "!=", mark);
132	else
133		xt_xlate_add(xl, " %s0x%x",
134			   op == XT_OP_EQ ? "" : "!= ", mark);
135}
136
137static int connmark_xlate(struct xt_xlate *xl,
138			  const struct xt_xlate_mt_params *params)
139{
140	const struct xt_connmark_info *info = (const void *)params->match->data;
141	enum xt_op op = XT_OP_EQ;
142
143	if (info->invert)
144		op = XT_OP_NEQ;
145
146	xt_xlate_add(xl, "ct mark");
147	print_mark_xlate(info->mark, info->mask, xl, op);
148
149	return 1;
150}
151
152static int
153connmark_mt_xlate(struct xt_xlate *xl,
154		  const struct xt_xlate_mt_params *params)
155{
156	const struct xt_connmark_mtinfo1 *info =
157		(const void *)params->match->data;
158	enum xt_op op = XT_OP_EQ;
159
160	if (info->invert)
161		op = XT_OP_NEQ;
162
163	xt_xlate_add(xl, "ct mark");
164	print_mark_xlate(info->mark, info->mask, xl, op);
165
166	return 1;
167}
168
169static struct xtables_match connmark_mt_reg[] = {
170	{
171		.family        = NFPROTO_UNSPEC,
172		.name          = "connmark",
173		.revision      = 0,
174		.version       = XTABLES_VERSION,
175		.size          = XT_ALIGN(sizeof(struct xt_connmark_info)),
176		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_info)),
177		.help          = connmark_mt_help,
178		.print         = connmark_print,
179		.save          = connmark_save,
180		.x6_parse      = connmark_parse,
181		.x6_options    = connmark_mt_opts,
182		.xlate	       = connmark_xlate,
183	},
184	{
185		.version       = XTABLES_VERSION,
186		.name          = "connmark",
187		.revision      = 1,
188		.family        = NFPROTO_UNSPEC,
189		.size          = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
190		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
191		.help          = connmark_mt_help,
192		.print         = connmark_mt_print,
193		.save          = connmark_mt_save,
194		.x6_parse      = connmark_mt_parse,
195		.x6_options    = connmark_mt_opts,
196		.xlate	       = connmark_mt_xlate,
197	},
198};
199
200void _init(void)
201{
202	xtables_register_matches(connmark_mt_reg, ARRAY_SIZE(connmark_mt_reg));
203}
204