12e4e6a17SHarald Welte /* This kernel module matches connection mark values set by the 22e4e6a17SHarald Welte * CONNMARK target 32e4e6a17SHarald Welte * 42e4e6a17SHarald Welte * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> 52e4e6a17SHarald Welte * by Henrik Nordstrom <hno@marasystems.com> 62e4e6a17SHarald Welte * 72e4e6a17SHarald Welte * This program is free software; you can redistribute it and/or modify 82e4e6a17SHarald Welte * it under the terms of the GNU General Public License as published by 92e4e6a17SHarald Welte * the Free Software Foundation; either version 2 of the License, or 102e4e6a17SHarald Welte * (at your option) any later version. 112e4e6a17SHarald Welte * 122e4e6a17SHarald Welte * This program is distributed in the hope that it will be useful, 132e4e6a17SHarald Welte * but WITHOUT ANY WARRANTY; without even the implied warranty of 142e4e6a17SHarald Welte * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 152e4e6a17SHarald Welte * GNU General Public License for more details. 162e4e6a17SHarald Welte * 172e4e6a17SHarald Welte * You should have received a copy of the GNU General Public License 182e4e6a17SHarald Welte * along with this program; if not, write to the Free Software 192e4e6a17SHarald Welte * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 202e4e6a17SHarald Welte */ 212e4e6a17SHarald Welte 222e4e6a17SHarald Welte #include <linux/module.h> 232e4e6a17SHarald Welte #include <linux/skbuff.h> 24587aa641SPatrick McHardy #include <net/netfilter/nf_conntrack.h> 25587aa641SPatrick McHardy #include <linux/netfilter/x_tables.h> 26587aa641SPatrick McHardy #include <linux/netfilter/xt_connmark.h> 272e4e6a17SHarald Welte 282e4e6a17SHarald Welte MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); 292e4e6a17SHarald Welte MODULE_DESCRIPTION("IP tables connmark match module"); 302e4e6a17SHarald Welte MODULE_LICENSE("GPL"); 312e4e6a17SHarald Welte MODULE_ALIAS("ipt_connmark"); 322e4e6a17SHarald Welte 331d93a9cbSJan Engelhardt static bool 342e4e6a17SHarald Welte match(const struct sk_buff *skb, 352e4e6a17SHarald Welte const struct net_device *in, 362e4e6a17SHarald Welte const struct net_device *out, 37c4986734SPatrick McHardy const struct xt_match *match, 382e4e6a17SHarald Welte const void *matchinfo, 392e4e6a17SHarald Welte int offset, 402e4e6a17SHarald Welte unsigned int protoff, 41cff533acSJan Engelhardt bool *hotdrop) 422e4e6a17SHarald Welte { 432e4e6a17SHarald Welte const struct xt_connmark_info *info = matchinfo; 44a47362a2SJan Engelhardt const struct nf_conn *ct; 45587aa641SPatrick McHardy enum ip_conntrack_info ctinfo; 46587aa641SPatrick McHardy 47587aa641SPatrick McHardy ct = nf_ct_get(skb, &ctinfo); 48587aa641SPatrick McHardy if (!ct) 491d93a9cbSJan Engelhardt return false; 502e4e6a17SHarald Welte 517c4e36bcSJan Engelhardt return ((ct->mark & info->mask) == info->mark) ^ info->invert; 522e4e6a17SHarald Welte } 532e4e6a17SHarald Welte 54ccb79bdcSJan Engelhardt static bool 552e4e6a17SHarald Welte checkentry(const char *tablename, 562e4e6a17SHarald Welte const void *ip, 57c4986734SPatrick McHardy const struct xt_match *match, 582e4e6a17SHarald Welte void *matchinfo, 592e4e6a17SHarald Welte unsigned int hook_mask) 602e4e6a17SHarald Welte { 61a47362a2SJan Engelhardt const struct xt_connmark_info *cm = matchinfo; 622e4e6a17SHarald Welte 632e4e6a17SHarald Welte if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { 642e4e6a17SHarald Welte printk(KERN_WARNING "connmark: only support 32bit mark\n"); 65ccb79bdcSJan Engelhardt return false; 662e4e6a17SHarald Welte } 67b9f78f9fSPablo Neira Ayuso if (nf_ct_l3proto_try_module_get(match->family) < 0) { 68fe0b9294SYasuyuki Kozakai printk(KERN_WARNING "can't load conntrack support for " 69b9f78f9fSPablo Neira Ayuso "proto=%d\n", match->family); 70ccb79bdcSJan Engelhardt return false; 71b9f78f9fSPablo Neira Ayuso } 72ccb79bdcSJan Engelhardt return true; 732e4e6a17SHarald Welte } 742e4e6a17SHarald Welte 75b9f78f9fSPablo Neira Ayuso static void 76efa74165SPatrick McHardy destroy(const struct xt_match *match, void *matchinfo) 77b9f78f9fSPablo Neira Ayuso { 78b9f78f9fSPablo Neira Ayuso nf_ct_l3proto_module_put(match->family); 79b9f78f9fSPablo Neira Ayuso } 80b9f78f9fSPablo Neira Ayuso 81f1eda053SPatrick McHardy #ifdef CONFIG_COMPAT 82f1eda053SPatrick McHardy struct compat_xt_connmark_info { 83f1eda053SPatrick McHardy compat_ulong_t mark, mask; 84f1eda053SPatrick McHardy u_int8_t invert; 85f1eda053SPatrick McHardy u_int8_t __pad1; 86f1eda053SPatrick McHardy u_int16_t __pad2; 87f1eda053SPatrick McHardy }; 88f1eda053SPatrick McHardy 89f1eda053SPatrick McHardy static void compat_from_user(void *dst, void *src) 90f1eda053SPatrick McHardy { 91a47362a2SJan Engelhardt const struct compat_xt_connmark_info *cm = src; 92f1eda053SPatrick McHardy struct xt_connmark_info m = { 93f1eda053SPatrick McHardy .mark = cm->mark, 94f1eda053SPatrick McHardy .mask = cm->mask, 95f1eda053SPatrick McHardy .invert = cm->invert, 96f1eda053SPatrick McHardy }; 97f1eda053SPatrick McHardy memcpy(dst, &m, sizeof(m)); 98f1eda053SPatrick McHardy } 99f1eda053SPatrick McHardy 100f1eda053SPatrick McHardy static int compat_to_user(void __user *dst, void *src) 101f1eda053SPatrick McHardy { 102a47362a2SJan Engelhardt const struct xt_connmark_info *m = src; 103f1eda053SPatrick McHardy struct compat_xt_connmark_info cm = { 104f1eda053SPatrick McHardy .mark = m->mark, 105f1eda053SPatrick McHardy .mask = m->mask, 106f1eda053SPatrick McHardy .invert = m->invert, 107f1eda053SPatrick McHardy }; 108f1eda053SPatrick McHardy return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; 109f1eda053SPatrick McHardy } 110f1eda053SPatrick McHardy #endif /* CONFIG_COMPAT */ 111f1eda053SPatrick McHardy 1129f15c530SPatrick McHardy static struct xt_match xt_connmark_match[] __read_mostly = { 1134470bbc7SPatrick McHardy { 1142e4e6a17SHarald Welte .name = "connmark", 115a45049c5SPablo Neira Ayuso .family = AF_INET, 1165d04bff0SPatrick McHardy .checkentry = checkentry, 1174470bbc7SPatrick McHardy .match = match, 118b9f78f9fSPablo Neira Ayuso .destroy = destroy, 1194470bbc7SPatrick McHardy .matchsize = sizeof(struct xt_connmark_info), 120f1eda053SPatrick McHardy #ifdef CONFIG_COMPAT 121f1eda053SPatrick McHardy .compatsize = sizeof(struct compat_xt_connmark_info), 122f1eda053SPatrick McHardy .compat_from_user = compat_from_user, 123f1eda053SPatrick McHardy .compat_to_user = compat_to_user, 124f1eda053SPatrick McHardy #endif 1255d04bff0SPatrick McHardy .me = THIS_MODULE 1264470bbc7SPatrick McHardy }, 1274470bbc7SPatrick McHardy { 1284470bbc7SPatrick McHardy .name = "connmark", 1294470bbc7SPatrick McHardy .family = AF_INET6, 1304470bbc7SPatrick McHardy .checkentry = checkentry, 1314470bbc7SPatrick McHardy .match = match, 1324470bbc7SPatrick McHardy .destroy = destroy, 1334470bbc7SPatrick McHardy .matchsize = sizeof(struct xt_connmark_info), 1344470bbc7SPatrick McHardy .me = THIS_MODULE 1354470bbc7SPatrick McHardy }, 1365d04bff0SPatrick McHardy }; 1372e4e6a17SHarald Welte 13865b4b4e8SAndrew Morton static int __init xt_connmark_init(void) 1392e4e6a17SHarald Welte { 1404470bbc7SPatrick McHardy return xt_register_matches(xt_connmark_match, 1414470bbc7SPatrick McHardy ARRAY_SIZE(xt_connmark_match)); 1422e4e6a17SHarald Welte } 1432e4e6a17SHarald Welte 14465b4b4e8SAndrew Morton static void __exit xt_connmark_fini(void) 1452e4e6a17SHarald Welte { 146f64ad5bbSPatrick McHardy xt_unregister_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match)); 1472e4e6a17SHarald Welte } 1482e4e6a17SHarald Welte 14965b4b4e8SAndrew Morton module_init(xt_connmark_init); 15065b4b4e8SAndrew Morton module_exit(xt_connmark_fini); 151