1469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte/* Shared library add-on to iptables to add connmark matching support.
2469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte *
3469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
4469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * by Henrik Nordstrom <hno@marasystems.com>
5469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte *
6469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * Version 1.1
7469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte *
8469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * This program is free software; you can redistribute it and/or modify
9469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * it under the terms of the GNU General Public License as published by
10469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * the Free Software Foundation; either version 2 of the License, or
11469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * (at your option) any later version.
12469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte *
13469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * This program is distributed in the hope that it will be useful,
14469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * but WITHOUT ANY WARRANTY; without even the implied warranty of
15469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * GNU General Public License for more details.
17469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte *
18469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * You should have received a copy of the GNU General Public License
19469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte * along with this program; if not, write to the Free Software
20d6217f93926b174bb2e894c8a8fc3d73b01942e9Jiri Popelka * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte */
2232b8e61e4e5bd405d9ad07bf9468498dfbb19f9eJan Engelhardt#include <stdbool.h>
237299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt#include <stdint.h>
24469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte#include <stdio.h>
25c57c155312a544482a6b8a3c0f7224b00cfaae20Yasuyuki KOZAKAI#include <xtables.h>
26c57c155312a544482a6b8a3c0f7224b00cfaae20Yasuyuki KOZAKAI#include <linux/netfilter/xt_connmark.h>
27469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
28350661a6eb089f3e54e67e022db9e16ea280499fJan Engelhardtstruct xt_connmark_info {
29350661a6eb089f3e54e67e022db9e16ea280499fJan Engelhardt	unsigned long mark, mask;
307ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardt	uint8_t invert;
31350661a6eb089f3e54e67e022db9e16ea280499fJan Engelhardt};
32350661a6eb089f3e54e67e022db9e16ea280499fJan Engelhardt
33a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardtenum {
347299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	O_MARK = 0,
35a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt};
36a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt
37a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardtstatic void connmark_mt_help(void)
38469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte{
39469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte	printf(
40a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt"connmark match options:\n"
418b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"[!] --mark value[/mask]    Match ctmark value with optional mask\n");
42469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte}
43469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
447299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardtstatic const struct xt_option_entry connmark_mt_opts[] = {
457299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	{.name = "mark", .id = O_MARK, .type = XTTYPE_MARKMASK32,
467299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	 .flags = XTOPT_MAND | XTOPT_INVERT},
477299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	XTOPT_TABLEEND,
48469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte};
49469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
507299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardtstatic void connmark_mt_parse(struct xt_option_call *cb)
51a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt{
527299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	struct xt_connmark_mtinfo1 *info = cb->data;
537299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt
547299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	xtables_option_parse(cb);
557299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	if (cb->invert)
567299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt		info->invert = true;
577299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	info->mark = cb->val.mark;
587299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	info->mask = cb->val.mask;
59a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt}
60a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt
617299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardtstatic void connmark_parse(struct xt_option_call *cb)
62469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte{
637299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	struct xt_connmark_info *markinfo = cb->data;
647299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt
657299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	xtables_option_parse(cb);
667299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	markinfo->mark = cb->val.mark;
677299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	markinfo->mask = cb->val.mask;
687299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt	if (cb->invert)
697299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt		markinfo->invert = 1;
70469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte}
71469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
72a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardtstatic void print_mark(unsigned int mark, unsigned int mask)
73469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte{
74a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt	if (mask != 0xffffffffU)
7573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" 0x%x/0x%x", mark, mask);
76469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte	else
7773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" 0x%x", mark);
78469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte}
79469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
80469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Weltestatic void
81181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtconnmark_print(const void *ip, const struct xt_entry_match *match, int numeric)
82469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte{
8369f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardt	const struct xt_connmark_info *info = (const void *)match->data;
84469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
8573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" CONNMARK match ");
86469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte	if (info->invert)
87469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte		printf("!");
88a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt	print_mark(info->mark, info->mask);
89a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt}
90a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt
91a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardtstatic void
92bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwajconnmark_mt_print(const void *ip, const struct xt_entry_match *match,
93bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj		  int numeric)
94a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt{
95a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt	const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
96a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt
9773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" connmark match ");
98a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt	if (info->invert)
99a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt		printf("!");
100a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt	print_mark(info->mark, info->mask);
101469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte}
102469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
103181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void connmark_save(const void *ip, const struct xt_entry_match *match)
104469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte{
10569f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardt	const struct xt_connmark_info *info = (const void *)match->data;
106469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
107469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte	if (info->invert)
10873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" !");
109469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
11073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" --mark");
111a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt	print_mark(info->mark, info->mask);
112a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt}
113a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt
114a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardtstatic void
115a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardtconnmark_mt_save(const void *ip, const struct xt_entry_match *match)
116a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt{
117a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt	const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
118a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt
119a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt	if (info->invert)
12073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" !");
121a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt
12273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" --mark");
123a7b0707bd83bac30a92871872dab79ec8cebebbbJan Engelhardt	print_mark(info->mark, info->mask);
124469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte}
125469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
126bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwajstatic void print_mark_xlate(unsigned int mark, unsigned int mask,
1276b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayuso			     struct xt_xlate *xl, uint32_t op)
128bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj{
129bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj	if (mask != 0xffffffffU)
130f035be35c749d5c5cbb7ffdbcd1c548b91bd3033Pablo M. Bermudo Garay		xt_xlate_add(xl, " and 0x%x %s 0x%x", mask,
1312bd49c03c8601aff8f951a8153e95bfdeb7b84d8Shivani Bhardwaj			   op == XT_OP_EQ ? "==" : "!=", mark);
132bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj	else
133f035be35c749d5c5cbb7ffdbcd1c548b91bd3033Pablo M. Bermudo Garay		xt_xlate_add(xl, " %s0x%x",
134bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj			   op == XT_OP_EQ ? "" : "!= ", mark);
135bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj}
136bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj
1377a0992da44cfb6cab0ccd1beadcf326df8773552Pablo Neira Ayusostatic int connmark_xlate(struct xt_xlate *xl,
1387a0992da44cfb6cab0ccd1beadcf326df8773552Pablo Neira Ayuso			  const struct xt_xlate_mt_params *params)
139bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj{
1407a0992da44cfb6cab0ccd1beadcf326df8773552Pablo Neira Ayuso	const struct xt_connmark_info *info = (const void *)params->match->data;
141bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj	enum xt_op op = XT_OP_EQ;
142bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj
143bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj	if (info->invert)
144bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj		op = XT_OP_NEQ;
145bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj
1466b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayuso	xt_xlate_add(xl, "ct mark");
1476b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayuso	print_mark_xlate(info->mark, info->mask, xl, op);
148bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj
149bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj	return 1;
150bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj}
151bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj
152bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwajstatic int
1537a0992da44cfb6cab0ccd1beadcf326df8773552Pablo Neira Ayusoconnmark_mt_xlate(struct xt_xlate *xl,
1547a0992da44cfb6cab0ccd1beadcf326df8773552Pablo Neira Ayuso		  const struct xt_xlate_mt_params *params)
155bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj{
1567a0992da44cfb6cab0ccd1beadcf326df8773552Pablo Neira Ayuso	const struct xt_connmark_mtinfo1 *info =
1577a0992da44cfb6cab0ccd1beadcf326df8773552Pablo Neira Ayuso		(const void *)params->match->data;
158bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj	enum xt_op op = XT_OP_EQ;
159bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj
160bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj	if (info->invert)
161bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj		op = XT_OP_NEQ;
162bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj
1636b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayuso	xt_xlate_add(xl, "ct mark");
1646b60dc5be58a5781cacc4e6f238454d5e8421760Pablo Neira Ayuso	print_mark_xlate(info->mark, info->mask, xl, op);
165bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj
166bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj	return 1;
167bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj}
168bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj
169f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardtstatic struct xtables_match connmark_mt_reg[] = {
170f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt	{
171f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.family        = NFPROTO_UNSPEC,
172f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.name          = "connmark",
173f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.revision      = 0,
174f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.version       = XTABLES_VERSION,
175f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.size          = XT_ALIGN(sizeof(struct xt_connmark_info)),
176f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_info)),
177f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.help          = connmark_mt_help,
178f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.print         = connmark_print,
179f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.save          = connmark_save,
1807299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt		.x6_parse      = connmark_parse,
1817299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt		.x6_options    = connmark_mt_opts,
182bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj		.xlate	       = connmark_xlate,
183f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt	},
184f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt	{
185f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.version       = XTABLES_VERSION,
186f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.name          = "connmark",
187f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.revision      = 1,
188f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.family        = NFPROTO_UNSPEC,
189f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.size          = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
190f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
191f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.help          = connmark_mt_help,
192f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.print         = connmark_mt_print,
193f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt		.save          = connmark_mt_save,
1947299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt		.x6_parse      = connmark_mt_parse,
1957299fa4b615d7f7ee12cde444266f6b31f667f9fJan Engelhardt		.x6_options    = connmark_mt_opts,
196bdbf63b95176e6d7e7f968c9cb25d58d84fc729eShivani Bhardwaj		.xlate	       = connmark_mt_xlate,
197f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt	},
198469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte};
199469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte
200469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Weltevoid _init(void)
201469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte{
202f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt	xtables_register_matches(connmark_mt_reg, ARRAY_SIZE(connmark_mt_reg));
203469d18f66896ef509cac5a2ade494ea38e0c86e2Harald Welte}
204