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 77135367b8SJan Engelhardt static int connmark_tg_check(const struct xt_tgchk_param *par) 78b8f00ba2SJan Engelhardt { 794a5a5c73SJan Engelhardt int ret; 804a5a5c73SJan Engelhardt 814a5a5c73SJan Engelhardt ret = nf_ct_l3proto_try_module_get(par->family); 824a5a5c73SJan Engelhardt if (ret < 0) { 838bee4badSJan Engelhardt pr_info("cannot load conntrack support for proto=%u\n", 848bee4badSJan Engelhardt par->family); 854a5a5c73SJan Engelhardt return ret; 86b8f00ba2SJan Engelhardt } 87bd414ee6SJan Engelhardt return 0; 88b8f00ba2SJan Engelhardt } 89b8f00ba2SJan Engelhardt 90b8f00ba2SJan Engelhardt static void connmark_tg_destroy(const struct xt_tgdtor_param *par) 91b8f00ba2SJan Engelhardt { 92b8f00ba2SJan Engelhardt nf_ct_l3proto_module_put(par->family); 93b8f00ba2SJan Engelhardt } 94b8f00ba2SJan Engelhardt 951d93a9cbSJan Engelhardt static bool 96f7108a20SJan Engelhardt connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par) 972e4e6a17SHarald Welte { 98f7108a20SJan Engelhardt const struct xt_connmark_mtinfo1 *info = par->matchinfo; 9996e32272SJan Engelhardt enum ip_conntrack_info ctinfo; 10096e32272SJan Engelhardt const struct nf_conn *ct; 10196e32272SJan Engelhardt 10296e32272SJan Engelhardt ct = nf_ct_get(skb, &ctinfo); 10396e32272SJan Engelhardt if (ct == NULL) 10496e32272SJan Engelhardt return false; 10596e32272SJan Engelhardt 10696e32272SJan Engelhardt return ((ct->mark & info->mask) == info->mark) ^ info->invert; 10796e32272SJan Engelhardt } 10896e32272SJan Engelhardt 109b0f38452SJan Engelhardt static int connmark_mt_check(const struct xt_mtchk_param *par) 11096e32272SJan Engelhardt { 1114a5a5c73SJan Engelhardt int ret; 1124a5a5c73SJan Engelhardt 1134a5a5c73SJan Engelhardt ret = nf_ct_l3proto_try_module_get(par->family); 1144a5a5c73SJan Engelhardt if (ret < 0) { 1158bee4badSJan Engelhardt pr_info("cannot load conntrack support for proto=%u\n", 1168bee4badSJan Engelhardt par->family); 1174a5a5c73SJan Engelhardt return ret; 11896e32272SJan Engelhardt } 119bd414ee6SJan Engelhardt return 0; 12096e32272SJan Engelhardt } 12196e32272SJan Engelhardt 1226be3d859SJan Engelhardt static void connmark_mt_destroy(const struct xt_mtdtor_param *par) 123b9f78f9fSPablo Neira Ayuso { 12492f3b2b1SJan Engelhardt nf_ct_l3proto_module_put(par->family); 125b9f78f9fSPablo Neira Ayuso } 126b9f78f9fSPablo Neira Ayuso 127b8f00ba2SJan Engelhardt static struct xt_target connmark_tg_reg __read_mostly = { 128b8f00ba2SJan Engelhardt .name = "CONNMARK", 129b8f00ba2SJan Engelhardt .revision = 1, 130b8f00ba2SJan Engelhardt .family = NFPROTO_UNSPEC, 131b8f00ba2SJan Engelhardt .checkentry = connmark_tg_check, 132b8f00ba2SJan Engelhardt .target = connmark_tg, 133b8f00ba2SJan Engelhardt .targetsize = sizeof(struct xt_connmark_tginfo1), 134b8f00ba2SJan Engelhardt .destroy = connmark_tg_destroy, 135b8f00ba2SJan Engelhardt .me = THIS_MODULE, 136b8f00ba2SJan Engelhardt }; 137b8f00ba2SJan Engelhardt 13884899a2bSJan Engelhardt static struct xt_match connmark_mt_reg __read_mostly = { 13996e32272SJan Engelhardt .name = "connmark", 14096e32272SJan Engelhardt .revision = 1, 14192f3b2b1SJan Engelhardt .family = NFPROTO_UNSPEC, 14296e32272SJan Engelhardt .checkentry = connmark_mt_check, 14396e32272SJan Engelhardt .match = connmark_mt, 14496e32272SJan Engelhardt .matchsize = sizeof(struct xt_connmark_mtinfo1), 14596e32272SJan Engelhardt .destroy = connmark_mt_destroy, 14696e32272SJan Engelhardt .me = THIS_MODULE, 1475d04bff0SPatrick McHardy }; 1482e4e6a17SHarald Welte 149d3c5ee6dSJan Engelhardt static int __init connmark_mt_init(void) 1502e4e6a17SHarald Welte { 151b8f00ba2SJan Engelhardt int ret; 152b8f00ba2SJan Engelhardt 153b8f00ba2SJan Engelhardt ret = xt_register_target(&connmark_tg_reg); 154b8f00ba2SJan Engelhardt if (ret < 0) 155b8f00ba2SJan Engelhardt return ret; 156b8f00ba2SJan Engelhardt ret = xt_register_match(&connmark_mt_reg); 157b8f00ba2SJan Engelhardt if (ret < 0) { 158b8f00ba2SJan Engelhardt xt_unregister_target(&connmark_tg_reg); 159b8f00ba2SJan Engelhardt return ret; 160b8f00ba2SJan Engelhardt } 161b8f00ba2SJan Engelhardt return 0; 1622e4e6a17SHarald Welte } 1632e4e6a17SHarald Welte 164d3c5ee6dSJan Engelhardt static void __exit connmark_mt_exit(void) 1652e4e6a17SHarald Welte { 16684899a2bSJan Engelhardt xt_unregister_match(&connmark_mt_reg); 167b8f00ba2SJan Engelhardt xt_unregister_target(&connmark_tg_reg); 1682e4e6a17SHarald Welte } 1692e4e6a17SHarald Welte 170d3c5ee6dSJan Engelhardt module_init(connmark_mt_init); 171d3c5ee6dSJan Engelhardt module_exit(connmark_mt_exit); 172