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 <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, int numeric)
93{
94	const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
95
96	printf(" connmark match ");
97	if (info->invert)
98		printf("!");
99	print_mark(info->mark, info->mask);
100}
101
102static void connmark_save(const void *ip, const struct xt_entry_match *match)
103{
104	const struct xt_connmark_info *info = (const void *)match->data;
105
106	if (info->invert)
107		printf(" !");
108
109	printf(" --mark");
110	print_mark(info->mark, info->mask);
111}
112
113static void
114connmark_mt_save(const void *ip, const struct xt_entry_match *match)
115{
116	const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
117
118	if (info->invert)
119		printf(" !");
120
121	printf(" --mark");
122	print_mark(info->mark, info->mask);
123}
124
125static struct xtables_match connmark_mt_reg[] = {
126	{
127		.family        = NFPROTO_UNSPEC,
128		.name          = "connmark",
129		.revision      = 0,
130		.version       = XTABLES_VERSION,
131		.size          = XT_ALIGN(sizeof(struct xt_connmark_info)),
132		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_info)),
133		.help          = connmark_mt_help,
134		.print         = connmark_print,
135		.save          = connmark_save,
136		.x6_parse      = connmark_parse,
137		.x6_options    = connmark_mt_opts,
138	},
139	{
140		.version       = XTABLES_VERSION,
141		.name          = "connmark",
142		.revision      = 1,
143		.family        = NFPROTO_UNSPEC,
144		.size          = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
145		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
146		.help          = connmark_mt_help,
147		.print         = connmark_mt_print,
148		.save          = connmark_mt_save,
149		.x6_parse      = connmark_mt_parse,
150		.x6_options    = connmark_mt_opts,
151	},
152};
153
154void _init(void)
155{
156	xtables_register_matches(connmark_mt_reg, ARRAY_SIZE(connmark_mt_reg));
157}
158