xt_connmark.c revision 135367b8f6a18507af6b9a6910a14b5699415309
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
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
26587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <net/netfilter/nf_conntrack.h>
27b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt#include <net/netfilter/nf_conntrack_ecache.h>
28587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <linux/netfilter/x_tables.h>
29587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <linux/netfilter/xt_connmark.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
313a4fa0a25da81600ea0bcd75692ae8ca6050d165Robert P. J. DayMODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>");
32b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_DESCRIPTION("Xtables: connection mark operations");
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
34b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_ALIAS("ipt_CONNMARK");
35b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_ALIAS("ip6t_CONNMARK");
362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteMODULE_ALIAS("ipt_connmark");
3773aaf9355b71d295fd72dc0b93fcdd275c56648fJan EngelhardtMODULE_ALIAS("ip6t_connmark");
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtstatic unsigned int
40b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtconnmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
41b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt{
42b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	const struct xt_connmark_tginfo1 *info = par->targinfo;
43b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	enum ip_conntrack_info ctinfo;
44b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	struct nf_conn *ct;
45b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	u_int32_t newmark;
46b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
47b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	ct = nf_ct_get(skb, &ctinfo);
48b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	if (ct == NULL)
49b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		return XT_CONTINUE;
50b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
51b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	switch (info->mode) {
52b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	case XT_CONNMARK_SET:
53b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		newmark = (ct->mark & ~info->ctmask) ^ info->ctmark;
54b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		if (ct->mark != newmark) {
55b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt			ct->mark = newmark;
56b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt			nf_conntrack_event_cache(IPCT_MARK, ct);
57b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		}
58b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		break;
59b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	case XT_CONNMARK_SAVE:
60b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		newmark = (ct->mark & ~info->ctmask) ^
61b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		          (skb->mark & info->nfmask);
62b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		if (ct->mark != newmark) {
63b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt			ct->mark = newmark;
64b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt			nf_conntrack_event_cache(IPCT_MARK, ct);
65b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		}
66b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		break;
67b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	case XT_CONNMARK_RESTORE:
68b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		newmark = (skb->mark & ~info->nfmask) ^
69b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		          (ct->mark & info->ctmask);
70b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		skb->mark = newmark;
71b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		break;
72b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	}
73b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
74b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	return XT_CONTINUE;
75b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt}
76b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
77135367b8f6a18507af6b9a6910a14b5699415309Jan Engelhardtstatic int connmark_tg_check(const struct xt_tgchk_param *par)
78b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt{
79b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
808bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt		pr_info("cannot load conntrack support for proto=%u\n",
818bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt			par->family);
82b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		return false;
83b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	}
84b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	return true;
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
93f7108a20dee44e5bb037f9e48f6a207b42e6ae1cJan Engelhardtconnmark_mt(const struct sk_buff *skb, const struct xt_match_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{
10892f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
1098bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt		pr_info("cannot load conntrack support for proto=%u\n",
1108bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt			par->family);
11196e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt		return false;
11296e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt	}
11396e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt	return true;
11496e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt}
11596e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt
1166be3d8598e883fb632edf059ba2f8d1b9f4da138Jan Engelhardtstatic void connmark_mt_destroy(const struct xt_mtdtor_param *par)
117b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso{
11892f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt	nf_ct_l3proto_module_put(par->family);
119b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso}
120b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso
121b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtstatic struct xt_target connmark_tg_reg __read_mostly = {
122b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.name           = "CONNMARK",
123b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.revision       = 1,
124b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.family         = NFPROTO_UNSPEC,
125b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.checkentry     = connmark_tg_check,
126b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.target         = connmark_tg,
127b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.targetsize     = sizeof(struct xt_connmark_tginfo1),
128b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.destroy        = connmark_tg_destroy,
129b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	.me             = THIS_MODULE,
130b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt};
131b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
13284899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardtstatic struct xt_match connmark_mt_reg __read_mostly = {
13384899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.name           = "connmark",
13484899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.revision       = 1,
13584899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.family         = NFPROTO_UNSPEC,
13684899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.checkentry     = connmark_mt_check,
13784899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.match          = connmark_mt,
13884899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.matchsize      = sizeof(struct xt_connmark_mtinfo1),
13984899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.destroy        = connmark_mt_destroy,
14084899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	.me             = THIS_MODULE,
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
143d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic int __init connmark_mt_init(void)
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
145b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	int ret;
146b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt
147b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	ret = xt_register_target(&connmark_tg_reg);
148b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	if (ret < 0)
149b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		return ret;
150b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	ret = xt_register_match(&connmark_mt_reg);
151b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	if (ret < 0) {
152b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		xt_unregister_target(&connmark_tg_reg);
153b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt		return ret;
154b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	}
155b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	return 0;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
158d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic void __exit connmark_mt_exit(void)
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16084899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt	xt_unregister_match(&connmark_mt_reg);
161b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt	xt_unregister_target(&connmark_tg_reg);
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
164d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_init(connmark_mt_init);
165d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_exit(connmark_mt_exit);
166