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 283a4fa0a2SRobert P. J. Day MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>"); 292e4e6a17SHarald Welte MODULE_DESCRIPTION("IP tables connmark match module"); 302e4e6a17SHarald Welte MODULE_LICENSE("GPL"); 312e4e6a17SHarald Welte MODULE_ALIAS("ipt_connmark"); 3273aaf935SJan Engelhardt MODULE_ALIAS("ip6t_connmark"); 332e4e6a17SHarald Welte 341d93a9cbSJan Engelhardt static bool 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, 42cff533acSJan Engelhardt bool *hotdrop) 432e4e6a17SHarald Welte { 442e4e6a17SHarald Welte const struct xt_connmark_info *info = matchinfo; 45a47362a2SJan Engelhardt const struct nf_conn *ct; 46587aa641SPatrick McHardy enum ip_conntrack_info ctinfo; 47587aa641SPatrick McHardy 48587aa641SPatrick McHardy ct = nf_ct_get(skb, &ctinfo); 49587aa641SPatrick McHardy if (!ct) 501d93a9cbSJan Engelhardt return false; 512e4e6a17SHarald Welte 527c4e36bcSJan Engelhardt return ((ct->mark & info->mask) == info->mark) ^ info->invert; 532e4e6a17SHarald Welte } 542e4e6a17SHarald Welte 55ccb79bdcSJan Engelhardt static bool 562e4e6a17SHarald Welte checkentry(const char *tablename, 572e4e6a17SHarald Welte const void *ip, 58c4986734SPatrick McHardy const struct xt_match *match, 592e4e6a17SHarald Welte void *matchinfo, 602e4e6a17SHarald Welte unsigned int hook_mask) 612e4e6a17SHarald Welte { 62a47362a2SJan Engelhardt const struct xt_connmark_info *cm = matchinfo; 632e4e6a17SHarald Welte 642e4e6a17SHarald Welte if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { 652e4e6a17SHarald Welte printk(KERN_WARNING "connmark: only support 32bit mark\n"); 66ccb79bdcSJan Engelhardt return false; 672e4e6a17SHarald Welte } 68b9f78f9fSPablo Neira Ayuso if (nf_ct_l3proto_try_module_get(match->family) < 0) { 69fe0b9294SYasuyuki Kozakai printk(KERN_WARNING "can't load conntrack support for " 70b9f78f9fSPablo Neira Ayuso "proto=%d\n", match->family); 71ccb79bdcSJan Engelhardt return false; 72b9f78f9fSPablo Neira Ayuso } 73ccb79bdcSJan Engelhardt return true; 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 nf_ct_l3proto_module_put(match->family); 80b9f78f9fSPablo Neira Ayuso } 81b9f78f9fSPablo Neira Ayuso 82f1eda053SPatrick McHardy #ifdef CONFIG_COMPAT 83f1eda053SPatrick McHardy struct compat_xt_connmark_info { 84f1eda053SPatrick McHardy compat_ulong_t mark, mask; 85f1eda053SPatrick McHardy u_int8_t invert; 86f1eda053SPatrick McHardy u_int8_t __pad1; 87f1eda053SPatrick McHardy u_int16_t __pad2; 88f1eda053SPatrick McHardy }; 89f1eda053SPatrick McHardy 90f1eda053SPatrick McHardy static void compat_from_user(void *dst, void *src) 91f1eda053SPatrick McHardy { 92a47362a2SJan Engelhardt const struct compat_xt_connmark_info *cm = src; 93f1eda053SPatrick McHardy struct xt_connmark_info m = { 94f1eda053SPatrick McHardy .mark = cm->mark, 95f1eda053SPatrick McHardy .mask = cm->mask, 96f1eda053SPatrick McHardy .invert = cm->invert, 97f1eda053SPatrick McHardy }; 98f1eda053SPatrick McHardy memcpy(dst, &m, sizeof(m)); 99f1eda053SPatrick McHardy } 100f1eda053SPatrick McHardy 101f1eda053SPatrick McHardy static int compat_to_user(void __user *dst, void *src) 102f1eda053SPatrick McHardy { 103a47362a2SJan Engelhardt const struct xt_connmark_info *m = src; 104f1eda053SPatrick McHardy struct compat_xt_connmark_info cm = { 105f1eda053SPatrick McHardy .mark = m->mark, 106f1eda053SPatrick McHardy .mask = m->mask, 107f1eda053SPatrick McHardy .invert = m->invert, 108f1eda053SPatrick McHardy }; 109f1eda053SPatrick McHardy return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; 110f1eda053SPatrick McHardy } 111f1eda053SPatrick McHardy #endif /* CONFIG_COMPAT */ 112f1eda053SPatrick McHardy 1139f15c530SPatrick McHardy static struct xt_match xt_connmark_match[] __read_mostly = { 1144470bbc7SPatrick McHardy { 1152e4e6a17SHarald Welte .name = "connmark", 116a45049c5SPablo Neira Ayuso .family = AF_INET, 1175d04bff0SPatrick McHardy .checkentry = checkentry, 1184470bbc7SPatrick McHardy .match = match, 119b9f78f9fSPablo Neira Ayuso .destroy = destroy, 1204470bbc7SPatrick McHardy .matchsize = sizeof(struct xt_connmark_info), 121f1eda053SPatrick McHardy #ifdef CONFIG_COMPAT 122f1eda053SPatrick McHardy .compatsize = sizeof(struct compat_xt_connmark_info), 123f1eda053SPatrick McHardy .compat_from_user = compat_from_user, 124f1eda053SPatrick McHardy .compat_to_user = compat_to_user, 125f1eda053SPatrick McHardy #endif 1265d04bff0SPatrick McHardy .me = THIS_MODULE 1274470bbc7SPatrick McHardy }, 1284470bbc7SPatrick McHardy { 1294470bbc7SPatrick McHardy .name = "connmark", 1304470bbc7SPatrick McHardy .family = AF_INET6, 1314470bbc7SPatrick McHardy .checkentry = checkentry, 1324470bbc7SPatrick McHardy .match = match, 1334470bbc7SPatrick McHardy .destroy = destroy, 1344470bbc7SPatrick McHardy .matchsize = sizeof(struct xt_connmark_info), 1354470bbc7SPatrick McHardy .me = THIS_MODULE 1364470bbc7SPatrick McHardy }, 1375d04bff0SPatrick McHardy }; 1382e4e6a17SHarald Welte 13965b4b4e8SAndrew Morton static int __init xt_connmark_init(void) 1402e4e6a17SHarald Welte { 1414470bbc7SPatrick McHardy return xt_register_matches(xt_connmark_match, 1424470bbc7SPatrick McHardy ARRAY_SIZE(xt_connmark_match)); 1432e4e6a17SHarald Welte } 1442e4e6a17SHarald Welte 14565b4b4e8SAndrew Morton static void __exit xt_connmark_fini(void) 1462e4e6a17SHarald Welte { 147f64ad5bbSPatrick McHardy xt_unregister_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match)); 1482e4e6a17SHarald Welte } 1492e4e6a17SHarald Welte 15065b4b4e8SAndrew Morton module_init(xt_connmark_init); 15165b4b4e8SAndrew Morton module_exit(xt_connmark_fini); 152