196e32272SJan Engelhardt /* 296e32272SJan Engelhardt * xt_connmark - Netfilter module to match connection mark values 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 796e32272SJan Engelhardt * Jan Engelhardt <jengelh@computergmbh.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> 27587aa641SPatrick McHardy #include <linux/netfilter/x_tables.h> 28587aa641SPatrick McHardy #include <linux/netfilter/xt_connmark.h> 292e4e6a17SHarald Welte 303a4fa0a2SRobert P. J. Day MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>"); 312ae15b64SJan Engelhardt MODULE_DESCRIPTION("Xtables: connection mark match"); 322e4e6a17SHarald Welte MODULE_LICENSE("GPL"); 332e4e6a17SHarald Welte MODULE_ALIAS("ipt_connmark"); 3473aaf935SJan Engelhardt MODULE_ALIAS("ip6t_connmark"); 352e4e6a17SHarald Welte 361d93a9cbSJan Engelhardt static bool 37f7108a20SJan Engelhardt connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par) 382e4e6a17SHarald Welte { 39f7108a20SJan Engelhardt const struct xt_connmark_mtinfo1 *info = par->matchinfo; 4096e32272SJan Engelhardt enum ip_conntrack_info ctinfo; 4196e32272SJan Engelhardt const struct nf_conn *ct; 4296e32272SJan Engelhardt 4396e32272SJan Engelhardt ct = nf_ct_get(skb, &ctinfo); 4496e32272SJan Engelhardt if (ct == NULL) 4596e32272SJan Engelhardt return false; 4696e32272SJan Engelhardt 4796e32272SJan Engelhardt return ((ct->mark & info->mask) == info->mark) ^ info->invert; 4896e32272SJan Engelhardt } 4996e32272SJan Engelhardt 5096e32272SJan Engelhardt static bool 51f7108a20SJan Engelhardt connmark_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) 5296e32272SJan Engelhardt { 53f7108a20SJan Engelhardt const struct xt_connmark_info *info = par->matchinfo; 54a47362a2SJan Engelhardt const struct nf_conn *ct; 55587aa641SPatrick McHardy enum ip_conntrack_info ctinfo; 56587aa641SPatrick McHardy 57587aa641SPatrick McHardy ct = nf_ct_get(skb, &ctinfo); 58587aa641SPatrick McHardy if (!ct) 591d93a9cbSJan Engelhardt return false; 602e4e6a17SHarald Welte 617c4e36bcSJan Engelhardt return ((ct->mark & info->mask) == info->mark) ^ info->invert; 622e4e6a17SHarald Welte } 632e4e6a17SHarald Welte 649b4fce7aSJan Engelhardt static bool connmark_mt_check_v0(const struct xt_mtchk_param *par) 652e4e6a17SHarald Welte { 669b4fce7aSJan Engelhardt const struct xt_connmark_info *cm = par->matchinfo; 672e4e6a17SHarald Welte 682e4e6a17SHarald Welte if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { 692e4e6a17SHarald Welte printk(KERN_WARNING "connmark: only support 32bit mark\n"); 70ccb79bdcSJan Engelhardt return false; 712e4e6a17SHarald Welte } 7292f3b2b1SJan Engelhardt if (nf_ct_l3proto_try_module_get(par->family) < 0) { 73fe0b9294SYasuyuki Kozakai printk(KERN_WARNING "can't load conntrack support for " 7492f3b2b1SJan Engelhardt "proto=%u\n", par->family); 75ccb79bdcSJan Engelhardt return false; 76b9f78f9fSPablo Neira Ayuso } 77ccb79bdcSJan Engelhardt return true; 782e4e6a17SHarald Welte } 792e4e6a17SHarald Welte 809b4fce7aSJan Engelhardt static bool connmark_mt_check(const struct xt_mtchk_param *par) 8196e32272SJan Engelhardt { 8292f3b2b1SJan Engelhardt if (nf_ct_l3proto_try_module_get(par->family) < 0) { 8396e32272SJan Engelhardt printk(KERN_WARNING "cannot load conntrack support for " 8492f3b2b1SJan Engelhardt "proto=%u\n", par->family); 8596e32272SJan Engelhardt return false; 8696e32272SJan Engelhardt } 8796e32272SJan Engelhardt return true; 8896e32272SJan Engelhardt } 8996e32272SJan Engelhardt 906be3d859SJan Engelhardt static void connmark_mt_destroy(const struct xt_mtdtor_param *par) 91b9f78f9fSPablo Neira Ayuso { 9292f3b2b1SJan Engelhardt nf_ct_l3proto_module_put(par->family); 93b9f78f9fSPablo Neira Ayuso } 94b9f78f9fSPablo Neira Ayuso 95f1eda053SPatrick McHardy #ifdef CONFIG_COMPAT 96f1eda053SPatrick McHardy struct compat_xt_connmark_info { 97f1eda053SPatrick McHardy compat_ulong_t mark, mask; 98f1eda053SPatrick McHardy u_int8_t invert; 99f1eda053SPatrick McHardy u_int8_t __pad1; 100f1eda053SPatrick McHardy u_int16_t __pad2; 101f1eda053SPatrick McHardy }; 102f1eda053SPatrick McHardy 10396e32272SJan Engelhardt static void connmark_mt_compat_from_user_v0(void *dst, void *src) 104f1eda053SPatrick McHardy { 105a47362a2SJan Engelhardt const struct compat_xt_connmark_info *cm = src; 106f1eda053SPatrick McHardy struct xt_connmark_info m = { 107f1eda053SPatrick McHardy .mark = cm->mark, 108f1eda053SPatrick McHardy .mask = cm->mask, 109f1eda053SPatrick McHardy .invert = cm->invert, 110f1eda053SPatrick McHardy }; 111f1eda053SPatrick McHardy memcpy(dst, &m, sizeof(m)); 112f1eda053SPatrick McHardy } 113f1eda053SPatrick McHardy 11496e32272SJan Engelhardt static int connmark_mt_compat_to_user_v0(void __user *dst, void *src) 115f1eda053SPatrick McHardy { 116a47362a2SJan Engelhardt const struct xt_connmark_info *m = src; 117f1eda053SPatrick McHardy struct compat_xt_connmark_info cm = { 118f1eda053SPatrick McHardy .mark = m->mark, 119f1eda053SPatrick McHardy .mask = m->mask, 120f1eda053SPatrick McHardy .invert = m->invert, 121f1eda053SPatrick McHardy }; 122f1eda053SPatrick McHardy return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; 123f1eda053SPatrick McHardy } 124f1eda053SPatrick McHardy #endif /* CONFIG_COMPAT */ 125f1eda053SPatrick McHardy 126d3c5ee6dSJan Engelhardt static struct xt_match connmark_mt_reg[] __read_mostly = { 1274470bbc7SPatrick McHardy { 1282e4e6a17SHarald Welte .name = "connmark", 12996e32272SJan Engelhardt .revision = 0, 13092f3b2b1SJan Engelhardt .family = NFPROTO_UNSPEC, 13196e32272SJan Engelhardt .checkentry = connmark_mt_check_v0, 13296e32272SJan Engelhardt .match = connmark_mt_v0, 133d3c5ee6dSJan Engelhardt .destroy = connmark_mt_destroy, 1344470bbc7SPatrick McHardy .matchsize = sizeof(struct xt_connmark_info), 13534f4c429SPatrick McHardy #ifdef CONFIG_COMPAT 13634f4c429SPatrick McHardy .compatsize = sizeof(struct compat_xt_connmark_info), 13796e32272SJan Engelhardt .compat_from_user = connmark_mt_compat_from_user_v0, 13896e32272SJan Engelhardt .compat_to_user = connmark_mt_compat_to_user_v0, 13934f4c429SPatrick McHardy #endif 1404470bbc7SPatrick McHardy .me = THIS_MODULE 1414470bbc7SPatrick McHardy }, 14296e32272SJan Engelhardt { 14396e32272SJan Engelhardt .name = "connmark", 14496e32272SJan Engelhardt .revision = 1, 14592f3b2b1SJan Engelhardt .family = NFPROTO_UNSPEC, 14696e32272SJan Engelhardt .checkentry = connmark_mt_check, 14796e32272SJan Engelhardt .match = connmark_mt, 14896e32272SJan Engelhardt .matchsize = sizeof(struct xt_connmark_mtinfo1), 14996e32272SJan Engelhardt .destroy = connmark_mt_destroy, 15096e32272SJan Engelhardt .me = THIS_MODULE, 15196e32272SJan Engelhardt }, 1525d04bff0SPatrick McHardy }; 1532e4e6a17SHarald Welte 154d3c5ee6dSJan Engelhardt static int __init connmark_mt_init(void) 1552e4e6a17SHarald Welte { 156d3c5ee6dSJan Engelhardt return xt_register_matches(connmark_mt_reg, 157d3c5ee6dSJan Engelhardt ARRAY_SIZE(connmark_mt_reg)); 1582e4e6a17SHarald Welte } 1592e4e6a17SHarald Welte 160d3c5ee6dSJan Engelhardt static void __exit connmark_mt_exit(void) 1612e4e6a17SHarald Welte { 162d3c5ee6dSJan Engelhardt xt_unregister_matches(connmark_mt_reg, ARRAY_SIZE(connmark_mt_reg)); 1632e4e6a17SHarald Welte } 1642e4e6a17SHarald Welte 165d3c5ee6dSJan Engelhardt module_init(connmark_mt_init); 166d3c5ee6dSJan Engelhardt module_exit(connmark_mt_exit); 167