196e32272SJan Engelhardt /* 2b8f00ba2SJan Engelhardt * xt_connmark - Netfilter module to operate on connection marks 32e4e6a17SHarald Welte * 42e4e6a17SHarald Welte * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> 52e4e6a17SHarald Welte * by Henrik Nordstrom <hno@marasystems.com> 696e32272SJan Engelhardt * Copyright © CC Computer Consultants GmbH, 2007 - 2008 7408ffaa4SJan Engelhardt * Jan Engelhardt <jengelh@medozas.de> 82e4e6a17SHarald Welte * 92e4e6a17SHarald Welte * This program is free software; you can redistribute it and/or modify 102e4e6a17SHarald Welte * it under the terms of the GNU General Public License as published by 112e4e6a17SHarald Welte * the Free Software Foundation; either version 2 of the License, or 122e4e6a17SHarald Welte * (at your option) any later version. 132e4e6a17SHarald Welte * 142e4e6a17SHarald Welte * This program is distributed in the hope that it will be useful, 152e4e6a17SHarald Welte * but WITHOUT ANY WARRANTY; without even the implied warranty of 162e4e6a17SHarald Welte * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 172e4e6a17SHarald Welte * GNU General Public License for more details. 182e4e6a17SHarald Welte * 192e4e6a17SHarald Welte * You should have received a copy of the GNU General Public License 202e4e6a17SHarald Welte * along with this program; if not, write to the Free Software 212e4e6a17SHarald Welte * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 222e4e6a17SHarald Welte */ 232e4e6a17SHarald Welte 242e4e6a17SHarald Welte #include <linux/module.h> 252e4e6a17SHarald Welte #include <linux/skbuff.h> 26587aa641SPatrick McHardy #include <net/netfilter/nf_conntrack.h> 27b8f00ba2SJan Engelhardt #include <net/netfilter/nf_conntrack_ecache.h> 28587aa641SPatrick McHardy #include <linux/netfilter/x_tables.h> 29587aa641SPatrick McHardy #include <linux/netfilter/xt_connmark.h> 302e4e6a17SHarald Welte 313a4fa0a2SRobert P. J. Day MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>"); 32b8f00ba2SJan Engelhardt MODULE_DESCRIPTION("Xtables: connection mark operations"); 332e4e6a17SHarald Welte MODULE_LICENSE("GPL"); 34b8f00ba2SJan Engelhardt MODULE_ALIAS("ipt_CONNMARK"); 35b8f00ba2SJan Engelhardt MODULE_ALIAS("ip6t_CONNMARK"); 362e4e6a17SHarald Welte MODULE_ALIAS("ipt_connmark"); 3773aaf935SJan Engelhardt MODULE_ALIAS("ip6t_connmark"); 382e4e6a17SHarald Welte 39b8f00ba2SJan Engelhardt static unsigned int 40b8f00ba2SJan Engelhardt connmark_tg(struct sk_buff *skb, const struct xt_target_param *par) 41b8f00ba2SJan Engelhardt { 42b8f00ba2SJan Engelhardt const struct xt_connmark_tginfo1 *info = par->targinfo; 43b8f00ba2SJan Engelhardt enum ip_conntrack_info ctinfo; 44b8f00ba2SJan Engelhardt struct nf_conn *ct; 45b8f00ba2SJan Engelhardt u_int32_t newmark; 46b8f00ba2SJan Engelhardt 47b8f00ba2SJan Engelhardt ct = nf_ct_get(skb, &ctinfo); 48b8f00ba2SJan Engelhardt if (ct == NULL) 49b8f00ba2SJan Engelhardt return XT_CONTINUE; 50b8f00ba2SJan Engelhardt 51b8f00ba2SJan Engelhardt switch (info->mode) { 52b8f00ba2SJan Engelhardt case XT_CONNMARK_SET: 53b8f00ba2SJan Engelhardt newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; 54b8f00ba2SJan Engelhardt if (ct->mark != newmark) { 55b8f00ba2SJan Engelhardt ct->mark = newmark; 56b8f00ba2SJan Engelhardt nf_conntrack_event_cache(IPCT_MARK, ct); 57b8f00ba2SJan Engelhardt } 58b8f00ba2SJan Engelhardt break; 59b8f00ba2SJan Engelhardt case XT_CONNMARK_SAVE: 60b8f00ba2SJan Engelhardt newmark = (ct->mark & ~info->ctmask) ^ 61b8f00ba2SJan Engelhardt (skb->mark & info->nfmask); 62b8f00ba2SJan Engelhardt if (ct->mark != newmark) { 63b8f00ba2SJan Engelhardt ct->mark = newmark; 64b8f00ba2SJan Engelhardt nf_conntrack_event_cache(IPCT_MARK, ct); 65b8f00ba2SJan Engelhardt } 66b8f00ba2SJan Engelhardt break; 67b8f00ba2SJan Engelhardt case XT_CONNMARK_RESTORE: 68b8f00ba2SJan Engelhardt newmark = (skb->mark & ~info->nfmask) ^ 69b8f00ba2SJan Engelhardt (ct->mark & info->ctmask); 70b8f00ba2SJan Engelhardt skb->mark = newmark; 71b8f00ba2SJan Engelhardt break; 72b8f00ba2SJan Engelhardt } 73b8f00ba2SJan Engelhardt 74b8f00ba2SJan Engelhardt return XT_CONTINUE; 75b8f00ba2SJan Engelhardt } 76b8f00ba2SJan Engelhardt 77b8f00ba2SJan Engelhardt static bool connmark_tg_check(const struct xt_tgchk_param *par) 78b8f00ba2SJan Engelhardt { 79b8f00ba2SJan Engelhardt if (nf_ct_l3proto_try_module_get(par->family) < 0) { 808bee4badSJan Engelhardt pr_info("cannot load conntrack support for proto=%u\n", 818bee4badSJan Engelhardt par->family); 82b8f00ba2SJan Engelhardt return false; 83b8f00ba2SJan Engelhardt } 84b8f00ba2SJan Engelhardt return true; 85b8f00ba2SJan Engelhardt } 86b8f00ba2SJan Engelhardt 87b8f00ba2SJan Engelhardt static void connmark_tg_destroy(const struct xt_tgdtor_param *par) 88b8f00ba2SJan Engelhardt { 89b8f00ba2SJan Engelhardt nf_ct_l3proto_module_put(par->family); 90b8f00ba2SJan Engelhardt } 91b8f00ba2SJan Engelhardt 921d93a9cbSJan Engelhardt static bool 93f7108a20SJan Engelhardt connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par) 942e4e6a17SHarald Welte { 95f7108a20SJan Engelhardt const struct xt_connmark_mtinfo1 *info = par->matchinfo; 9696e32272SJan Engelhardt enum ip_conntrack_info ctinfo; 9796e32272SJan Engelhardt const struct nf_conn *ct; 9896e32272SJan Engelhardt 9996e32272SJan Engelhardt ct = nf_ct_get(skb, &ctinfo); 10096e32272SJan Engelhardt if (ct == NULL) 10196e32272SJan Engelhardt return false; 10296e32272SJan Engelhardt 10396e32272SJan Engelhardt return ((ct->mark & info->mask) == info->mark) ^ info->invert; 10496e32272SJan Engelhardt } 10596e32272SJan Engelhardt 1069b4fce7aSJan Engelhardt static bool connmark_mt_check(const struct xt_mtchk_param *par) 10796e32272SJan Engelhardt { 10892f3b2b1SJan Engelhardt if (nf_ct_l3proto_try_module_get(par->family) < 0) { 1098bee4badSJan Engelhardt pr_info("cannot load conntrack support for proto=%u\n", 1108bee4badSJan Engelhardt par->family); 11196e32272SJan Engelhardt return false; 11296e32272SJan Engelhardt } 11396e32272SJan Engelhardt return true; 11496e32272SJan Engelhardt } 11596e32272SJan Engelhardt 1166be3d859SJan Engelhardt static void connmark_mt_destroy(const struct xt_mtdtor_param *par) 117b9f78f9fSPablo Neira Ayuso { 11892f3b2b1SJan Engelhardt nf_ct_l3proto_module_put(par->family); 119b9f78f9fSPablo Neira Ayuso } 120b9f78f9fSPablo Neira Ayuso 121b8f00ba2SJan Engelhardt static struct xt_target connmark_tg_reg __read_mostly = { 122b8f00ba2SJan Engelhardt .name = "CONNMARK", 123b8f00ba2SJan Engelhardt .revision = 1, 124b8f00ba2SJan Engelhardt .family = NFPROTO_UNSPEC, 125b8f00ba2SJan Engelhardt .checkentry = connmark_tg_check, 126b8f00ba2SJan Engelhardt .target = connmark_tg, 127b8f00ba2SJan Engelhardt .targetsize = sizeof(struct xt_connmark_tginfo1), 128b8f00ba2SJan Engelhardt .destroy = connmark_tg_destroy, 129b8f00ba2SJan Engelhardt .me = THIS_MODULE, 130b8f00ba2SJan Engelhardt }; 131b8f00ba2SJan Engelhardt 13284899a2bSJan Engelhardt static struct xt_match connmark_mt_reg __read_mostly = { 13396e32272SJan Engelhardt .name = "connmark", 13496e32272SJan Engelhardt .revision = 1, 13592f3b2b1SJan Engelhardt .family = NFPROTO_UNSPEC, 13696e32272SJan Engelhardt .checkentry = connmark_mt_check, 13796e32272SJan Engelhardt .match = connmark_mt, 13896e32272SJan Engelhardt .matchsize = sizeof(struct xt_connmark_mtinfo1), 13996e32272SJan Engelhardt .destroy = connmark_mt_destroy, 14096e32272SJan Engelhardt .me = THIS_MODULE, 1415d04bff0SPatrick McHardy }; 1422e4e6a17SHarald Welte 143d3c5ee6dSJan Engelhardt static int __init connmark_mt_init(void) 1442e4e6a17SHarald Welte { 145b8f00ba2SJan Engelhardt int ret; 146b8f00ba2SJan Engelhardt 147b8f00ba2SJan Engelhardt ret = xt_register_target(&connmark_tg_reg); 148b8f00ba2SJan Engelhardt if (ret < 0) 149b8f00ba2SJan Engelhardt return ret; 150b8f00ba2SJan Engelhardt ret = xt_register_match(&connmark_mt_reg); 151b8f00ba2SJan Engelhardt if (ret < 0) { 152b8f00ba2SJan Engelhardt xt_unregister_target(&connmark_tg_reg); 153b8f00ba2SJan Engelhardt return ret; 154b8f00ba2SJan Engelhardt } 155b8f00ba2SJan Engelhardt return 0; 1562e4e6a17SHarald Welte } 1572e4e6a17SHarald Welte 158d3c5ee6dSJan Engelhardt static void __exit connmark_mt_exit(void) 1592e4e6a17SHarald Welte { 16084899a2bSJan Engelhardt xt_unregister_match(&connmark_mt_reg); 161b8f00ba2SJan Engelhardt xt_unregister_target(&connmark_tg_reg); 1622e4e6a17SHarald Welte } 1632e4e6a17SHarald Welte 164d3c5ee6dSJan Engelhardt module_init(connmark_mt_init); 165d3c5ee6dSJan Engelhardt module_exit(connmark_mt_exit); 166