196e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt/*
2b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt *	xt_connmark - Netfilter module to operate on connection marks
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
496e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt *	Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
596e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt *	by Henrik Nordstrom <hno@marasystems.com>
696e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
7408ffaa4a11ddd6f730be520479fd5cd890c57d3Jan Engelhardt *	Jan Engelhardt <jengelh@medozas.de>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful,
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
20e664eabd18c4581b21ea6f62e2e599df5a719a5bJeff Kirsher * along with this program; if not, see <http://www.gnu.org/licenses/>.
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
25587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <net/netfilter/nf_conntrack.h>
26b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt#include <net/netfilter/nf_conntrack_ecache.h>
27587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <linux/netfilter/x_tables.h>
28587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <linux/netfilter/xt_connmark.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
303a4fa0a25da81600ea0bcd75692ae8ca6050d165Robert P. J. DayMODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>");
31b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_DESCRIPTION("Xtables: connection mark operations");
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
33b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_ALIAS("ipt_CONNMARK");
34b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_ALIAS("ip6t_CONNMARK");
352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteMODULE_ALIAS("ipt_connmark");
3673aaf9355b71d295fd72dc0b93fcdd275c56648fJan EngelhardtMODULE_ALIAS("ip6t_connmark");
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtstatic unsigned int
394b560b447df83368df44bd3712c0c39b1d79ba04Jan Engelhardtconnmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
40b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt{
41b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	const struct xt_connmark_tginfo1 *info = par->targinfo;
42b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	enum ip_conntrack_info ctinfo;
43b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	struct nf_conn *ct;
44b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	u_int32_t newmark;
45b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
46b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	ct = nf_ct_get(skb, &ctinfo);
47b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	if (ct == NULL)
48b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		return XT_CONTINUE;
49b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
50b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	switch (info->mode) {
51b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	case XT_CONNMARK_SET:
52b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		newmark = (ct->mark & ~info->ctmask) ^ info->ctmark;
53b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		if (ct->mark != newmark) {
54b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt			ct->mark = newmark;
55b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt			nf_conntrack_event_cache(IPCT_MARK, ct);
56b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		}
57b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		break;
58b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	case XT_CONNMARK_SAVE:
59b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		newmark = (ct->mark & ~info->ctmask) ^
60b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		          (skb->mark & info->nfmask);
61b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		if (ct->mark != newmark) {
62b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt			ct->mark = newmark;
63b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt			nf_conntrack_event_cache(IPCT_MARK, ct);
64b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		}
65b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		break;
66b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	case XT_CONNMARK_RESTORE:
67b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		newmark = (skb->mark & ~info->nfmask) ^
68b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		          (ct->mark & info->ctmask);
69b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		skb->mark = newmark;
70b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		break;
71b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	}
72b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
73b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	return XT_CONTINUE;
74b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt}
75b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
76135367b8f6a18507af6b9a6910a14b5699415309Jan Engelhardtstatic int connmark_tg_check(const struct xt_tgchk_param *par)
77b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt{
784a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt	int ret;
794a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt
804a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt	ret = nf_ct_l3proto_try_module_get(par->family);
81f95c74e33eff5e3fe9798e2dc0a7749150ea3f80Jan Engelhardt	if (ret < 0)
828bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt		pr_info("cannot load conntrack support for proto=%u\n",
838bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt			par->family);
84f95c74e33eff5e3fe9798e2dc0a7749150ea3f80Jan Engelhardt	return ret;
85b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt}
86b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
87b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtstatic void connmark_tg_destroy(const struct xt_tgdtor_param *par)
88b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt{
89b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	nf_ct_l3proto_module_put(par->family);
90b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt}
91b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
921d93a9cbad608f6398ba6c5b588c504ccd35a2caJan Engelhardtstatic bool
9362fc8051083a334578c3f4b3488808f210b4565fJan Engelhardtconnmark_mt(const struct sk_buff *skb, struct xt_action_param *par)
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
95f7108a20dee44e5bb037f9e48f6a207b42e6ae1cJan Engelhardt	const struct xt_connmark_mtinfo1 *info = par->matchinfo;
9696e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt	enum ip_conntrack_info ctinfo;
9796e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt	const struct nf_conn *ct;
9896e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt
9996e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt	ct = nf_ct_get(skb, &ctinfo);
10096e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt	if (ct == NULL)
10196e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt		return false;
10296e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt
10396e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt	return ((ct->mark & info->mask) == info->mark) ^ info->invert;
10496e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt}
10596e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt
106b0f38452ff73da7e9e0ddc68cd5c6b93c897ca0dJan Engelhardtstatic int connmark_mt_check(const struct xt_mtchk_param *par)
10796e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt{
1084a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt	int ret;
1094a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt
1104a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt	ret = nf_ct_l3proto_try_module_get(par->family);
111f95c74e33eff5e3fe9798e2dc0a7749150ea3f80Jan Engelhardt	if (ret < 0)
1128bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt		pr_info("cannot load conntrack support for proto=%u\n",
1138bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt			par->family);
114f95c74e33eff5e3fe9798e2dc0a7749150ea3f80Jan Engelhardt	return ret;
11596e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt}
11696e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt
1176be3d8598e883fb632edf059ba2f8d1b9f4da138Jan Engelhardtstatic void connmark_mt_destroy(const struct xt_mtdtor_param *par)
118b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso{
11992f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt	nf_ct_l3proto_module_put(par->family);
120b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso}
121b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso
122b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtstatic struct xt_target connmark_tg_reg __read_mostly = {
123b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.name           = "CONNMARK",
124b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.revision       = 1,
125b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.family         = NFPROTO_UNSPEC,
126b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.checkentry     = connmark_tg_check,
127b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.target         = connmark_tg,
128b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.targetsize     = sizeof(struct xt_connmark_tginfo1),
129b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.destroy        = connmark_tg_destroy,
130b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.me             = THIS_MODULE,
131b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt};
132b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
13384899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardtstatic struct xt_match connmark_mt_reg __read_mostly = {
13484899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.name           = "connmark",
13584899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.revision       = 1,
13684899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.family         = NFPROTO_UNSPEC,
13784899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.checkentry     = connmark_mt_check,
13884899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.match          = connmark_mt,
13984899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.matchsize      = sizeof(struct xt_connmark_mtinfo1),
14084899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.destroy        = connmark_mt_destroy,
14184899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.me             = THIS_MODULE,
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
144d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic int __init connmark_mt_init(void)
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
146b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	int ret;
147b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
148b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	ret = xt_register_target(&connmark_tg_reg);
149b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	if (ret < 0)
150b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		return ret;
151b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	ret = xt_register_match(&connmark_mt_reg);
152b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	if (ret < 0) {
153b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		xt_unregister_target(&connmark_tg_reg);
154b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		return ret;
155b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	}
156b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	return 0;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
159d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic void __exit connmark_mt_exit(void)
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16184899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	xt_unregister_match(&connmark_mt_reg);
162b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	xt_unregister_target(&connmark_tg_reg);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
165d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_init(connmark_mt_init);
166d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_exit(connmark_mt_exit);
167