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> 242e4e6a17SHarald Welte 252e4e6a17SHarald Welte MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); 262e4e6a17SHarald Welte MODULE_DESCRIPTION("IP tables connmark match module"); 272e4e6a17SHarald Welte MODULE_LICENSE("GPL"); 282e4e6a17SHarald Welte MODULE_ALIAS("ipt_connmark"); 292e4e6a17SHarald Welte 302e4e6a17SHarald Welte #include <linux/netfilter/x_tables.h> 312e4e6a17SHarald Welte #include <linux/netfilter/xt_connmark.h> 322e4e6a17SHarald Welte #include <net/netfilter/nf_conntrack_compat.h> 332e4e6a17SHarald Welte 342e4e6a17SHarald Welte static int 352e4e6a17SHarald Welte match(const struct sk_buff *skb, 362e4e6a17SHarald Welte const struct net_device *in, 372e4e6a17SHarald Welte const struct net_device *out, 38c4986734SPatrick McHardy const struct xt_match *match, 392e4e6a17SHarald Welte const void *matchinfo, 402e4e6a17SHarald Welte int offset, 412e4e6a17SHarald Welte unsigned int protoff, 422e4e6a17SHarald Welte int *hotdrop) 432e4e6a17SHarald Welte { 442e4e6a17SHarald Welte const struct xt_connmark_info *info = matchinfo; 452e4e6a17SHarald Welte u_int32_t ctinfo; 462e4e6a17SHarald Welte const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); 472e4e6a17SHarald Welte if (!ctmark) 482e4e6a17SHarald Welte return 0; 492e4e6a17SHarald Welte 502e4e6a17SHarald Welte return (((*ctmark) & info->mask) == info->mark) ^ info->invert; 512e4e6a17SHarald Welte } 522e4e6a17SHarald Welte 532e4e6a17SHarald Welte static int 542e4e6a17SHarald Welte checkentry(const char *tablename, 552e4e6a17SHarald Welte const void *ip, 56c4986734SPatrick McHardy const struct xt_match *match, 572e4e6a17SHarald Welte void *matchinfo, 582e4e6a17SHarald Welte unsigned int hook_mask) 592e4e6a17SHarald Welte { 603e72b2feSPatrick McHardy struct xt_connmark_info *cm = matchinfo; 612e4e6a17SHarald Welte 622e4e6a17SHarald Welte if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { 632e4e6a17SHarald Welte printk(KERN_WARNING "connmark: only support 32bit mark\n"); 642e4e6a17SHarald Welte return 0; 652e4e6a17SHarald Welte } 66b9f78f9fSPablo Neira Ayuso #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 67b9f78f9fSPablo Neira Ayuso if (nf_ct_l3proto_try_module_get(match->family) < 0) { 68b9f78f9fSPablo Neira Ayuso printk(KERN_WARNING "can't load nf_conntrack support for " 69b9f78f9fSPablo Neira Ayuso "proto=%d\n", match->family); 70b9f78f9fSPablo Neira Ayuso return 0; 71b9f78f9fSPablo Neira Ayuso } 72b9f78f9fSPablo Neira Ayuso #endif 732e4e6a17SHarald Welte return 1; 742e4e6a17SHarald Welte } 752e4e6a17SHarald Welte 76b9f78f9fSPablo Neira Ayuso static void 77efa74165SPatrick McHardy destroy(const struct xt_match *match, void *matchinfo) 78b9f78f9fSPablo Neira Ayuso { 79b9f78f9fSPablo Neira Ayuso #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 80b9f78f9fSPablo Neira Ayuso nf_ct_l3proto_module_put(match->family); 81b9f78f9fSPablo Neira Ayuso #endif 82b9f78f9fSPablo Neira Ayuso } 83b9f78f9fSPablo Neira Ayuso 84f1eda053SPatrick McHardy #ifdef CONFIG_COMPAT 85f1eda053SPatrick McHardy struct compat_xt_connmark_info { 86f1eda053SPatrick McHardy compat_ulong_t mark, mask; 87f1eda053SPatrick McHardy u_int8_t invert; 88f1eda053SPatrick McHardy u_int8_t __pad1; 89f1eda053SPatrick McHardy u_int16_t __pad2; 90f1eda053SPatrick McHardy }; 91f1eda053SPatrick McHardy 92f1eda053SPatrick McHardy static void compat_from_user(void *dst, void *src) 93f1eda053SPatrick McHardy { 94f1eda053SPatrick McHardy struct compat_xt_connmark_info *cm = src; 95f1eda053SPatrick McHardy struct xt_connmark_info m = { 96f1eda053SPatrick McHardy .mark = cm->mark, 97f1eda053SPatrick McHardy .mask = cm->mask, 98f1eda053SPatrick McHardy .invert = cm->invert, 99f1eda053SPatrick McHardy }; 100f1eda053SPatrick McHardy memcpy(dst, &m, sizeof(m)); 101f1eda053SPatrick McHardy } 102f1eda053SPatrick McHardy 103f1eda053SPatrick McHardy static int compat_to_user(void __user *dst, void *src) 104f1eda053SPatrick McHardy { 105f1eda053SPatrick McHardy struct xt_connmark_info *m = src; 106f1eda053SPatrick McHardy struct compat_xt_connmark_info cm = { 107f1eda053SPatrick McHardy .mark = m->mark, 108f1eda053SPatrick McHardy .mask = m->mask, 109f1eda053SPatrick McHardy .invert = m->invert, 110f1eda053SPatrick McHardy }; 111f1eda053SPatrick McHardy return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; 112f1eda053SPatrick McHardy } 113f1eda053SPatrick McHardy #endif /* CONFIG_COMPAT */ 114f1eda053SPatrick McHardy 1154470bbc7SPatrick McHardy static struct xt_match xt_connmark_match[] = { 1164470bbc7SPatrick McHardy { 1172e4e6a17SHarald Welte .name = "connmark", 118a45049c5SPablo Neira Ayuso .family = AF_INET, 1195d04bff0SPatrick McHardy .checkentry = checkentry, 1204470bbc7SPatrick McHardy .match = match, 121b9f78f9fSPablo Neira Ayuso .destroy = destroy, 1224470bbc7SPatrick McHardy .matchsize = sizeof(struct xt_connmark_info), 123f1eda053SPatrick McHardy #ifdef CONFIG_COMPAT 124f1eda053SPatrick McHardy .compatsize = sizeof(struct compat_xt_connmark_info), 125f1eda053SPatrick McHardy .compat_from_user = compat_from_user, 126f1eda053SPatrick McHardy .compat_to_user = compat_to_user, 127f1eda053SPatrick McHardy #endif 1285d04bff0SPatrick McHardy .me = THIS_MODULE 1294470bbc7SPatrick McHardy }, 1304470bbc7SPatrick McHardy { 1314470bbc7SPatrick McHardy .name = "connmark", 1324470bbc7SPatrick McHardy .family = AF_INET6, 1334470bbc7SPatrick McHardy .checkentry = checkentry, 1344470bbc7SPatrick McHardy .match = match, 1354470bbc7SPatrick McHardy .destroy = destroy, 1364470bbc7SPatrick McHardy .matchsize = sizeof(struct xt_connmark_info), 1374470bbc7SPatrick McHardy .me = THIS_MODULE 1384470bbc7SPatrick McHardy }, 1395d04bff0SPatrick McHardy }; 1402e4e6a17SHarald Welte 14165b4b4e8SAndrew Morton static int __init xt_connmark_init(void) 1422e4e6a17SHarald Welte { 1432e4e6a17SHarald Welte need_conntrack(); 1444470bbc7SPatrick McHardy return xt_register_matches(xt_connmark_match, 1454470bbc7SPatrick McHardy ARRAY_SIZE(xt_connmark_match)); 1462e4e6a17SHarald Welte } 1472e4e6a17SHarald Welte 14865b4b4e8SAndrew Morton static void __exit xt_connmark_fini(void) 1492e4e6a17SHarald Welte { 150f64ad5bbSPatrick McHardy xt_unregister_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match)); 1512e4e6a17SHarald Welte } 1522e4e6a17SHarald Welte 15365b4b4e8SAndrew Morton module_init(xt_connmark_init); 15465b4b4e8SAndrew Morton module_exit(xt_connmark_fini); 155