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 35d3c5ee6dSJan Engelhardt connmark_mt(const struct sk_buff *skb, const struct net_device *in, 36d3c5ee6dSJan Engelhardt const struct net_device *out, const struct xt_match *match, 37d3c5ee6dSJan Engelhardt const void *matchinfo, int offset, unsigned int protoff, 38cff533acSJan Engelhardt bool *hotdrop) 392e4e6a17SHarald Welte { 402e4e6a17SHarald Welte const struct xt_connmark_info *info = matchinfo; 41a47362a2SJan Engelhardt const struct nf_conn *ct; 42587aa641SPatrick McHardy enum ip_conntrack_info ctinfo; 43587aa641SPatrick McHardy 44587aa641SPatrick McHardy ct = nf_ct_get(skb, &ctinfo); 45587aa641SPatrick McHardy if (!ct) 461d93a9cbSJan Engelhardt return false; 472e4e6a17SHarald Welte 487c4e36bcSJan Engelhardt return ((ct->mark & info->mask) == info->mark) ^ info->invert; 492e4e6a17SHarald Welte } 502e4e6a17SHarald Welte 51ccb79bdcSJan Engelhardt static bool 52d3c5ee6dSJan Engelhardt connmark_mt_check(const char *tablename, const void *ip, 53d3c5ee6dSJan Engelhardt const struct xt_match *match, void *matchinfo, 542e4e6a17SHarald Welte unsigned int hook_mask) 552e4e6a17SHarald Welte { 56a47362a2SJan Engelhardt const struct xt_connmark_info *cm = matchinfo; 572e4e6a17SHarald Welte 582e4e6a17SHarald Welte if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { 592e4e6a17SHarald Welte printk(KERN_WARNING "connmark: only support 32bit mark\n"); 60ccb79bdcSJan Engelhardt return false; 612e4e6a17SHarald Welte } 62b9f78f9fSPablo Neira Ayuso if (nf_ct_l3proto_try_module_get(match->family) < 0) { 63fe0b9294SYasuyuki Kozakai printk(KERN_WARNING "can't load conntrack support for " 64b9f78f9fSPablo Neira Ayuso "proto=%d\n", match->family); 65ccb79bdcSJan Engelhardt return false; 66b9f78f9fSPablo Neira Ayuso } 67ccb79bdcSJan Engelhardt return true; 682e4e6a17SHarald Welte } 692e4e6a17SHarald Welte 70b9f78f9fSPablo Neira Ayuso static void 71d3c5ee6dSJan Engelhardt connmark_mt_destroy(const struct xt_match *match, void *matchinfo) 72b9f78f9fSPablo Neira Ayuso { 73b9f78f9fSPablo Neira Ayuso nf_ct_l3proto_module_put(match->family); 74b9f78f9fSPablo Neira Ayuso } 75b9f78f9fSPablo Neira Ayuso 76f1eda053SPatrick McHardy #ifdef CONFIG_COMPAT 77f1eda053SPatrick McHardy struct compat_xt_connmark_info { 78f1eda053SPatrick McHardy compat_ulong_t mark, mask; 79f1eda053SPatrick McHardy u_int8_t invert; 80f1eda053SPatrick McHardy u_int8_t __pad1; 81f1eda053SPatrick McHardy u_int16_t __pad2; 82f1eda053SPatrick McHardy }; 83f1eda053SPatrick McHardy 84d3c5ee6dSJan Engelhardt static void connmark_mt_compat_from_user(void *dst, void *src) 85f1eda053SPatrick McHardy { 86a47362a2SJan Engelhardt const struct compat_xt_connmark_info *cm = src; 87f1eda053SPatrick McHardy struct xt_connmark_info m = { 88f1eda053SPatrick McHardy .mark = cm->mark, 89f1eda053SPatrick McHardy .mask = cm->mask, 90f1eda053SPatrick McHardy .invert = cm->invert, 91f1eda053SPatrick McHardy }; 92f1eda053SPatrick McHardy memcpy(dst, &m, sizeof(m)); 93f1eda053SPatrick McHardy } 94f1eda053SPatrick McHardy 95d3c5ee6dSJan Engelhardt static int connmark_mt_compat_to_user(void __user *dst, void *src) 96f1eda053SPatrick McHardy { 97a47362a2SJan Engelhardt const struct xt_connmark_info *m = src; 98f1eda053SPatrick McHardy struct compat_xt_connmark_info cm = { 99f1eda053SPatrick McHardy .mark = m->mark, 100f1eda053SPatrick McHardy .mask = m->mask, 101f1eda053SPatrick McHardy .invert = m->invert, 102f1eda053SPatrick McHardy }; 103f1eda053SPatrick McHardy return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; 104f1eda053SPatrick McHardy } 105f1eda053SPatrick McHardy #endif /* CONFIG_COMPAT */ 106f1eda053SPatrick McHardy 107d3c5ee6dSJan Engelhardt static struct xt_match connmark_mt_reg[] __read_mostly = { 1084470bbc7SPatrick McHardy { 1092e4e6a17SHarald Welte .name = "connmark", 110a45049c5SPablo Neira Ayuso .family = AF_INET, 111d3c5ee6dSJan Engelhardt .checkentry = connmark_mt_check, 112d3c5ee6dSJan Engelhardt .match = connmark_mt, 113d3c5ee6dSJan Engelhardt .destroy = connmark_mt_destroy, 1144470bbc7SPatrick McHardy .matchsize = sizeof(struct xt_connmark_info), 115f1eda053SPatrick McHardy #ifdef CONFIG_COMPAT 116f1eda053SPatrick McHardy .compatsize = sizeof(struct compat_xt_connmark_info), 117d3c5ee6dSJan Engelhardt .compat_from_user = connmark_mt_compat_from_user, 118d3c5ee6dSJan Engelhardt .compat_to_user = connmark_mt_compat_to_user, 119f1eda053SPatrick McHardy #endif 1205d04bff0SPatrick McHardy .me = THIS_MODULE 1214470bbc7SPatrick McHardy }, 1224470bbc7SPatrick McHardy { 1234470bbc7SPatrick McHardy .name = "connmark", 1244470bbc7SPatrick McHardy .family = AF_INET6, 125d3c5ee6dSJan Engelhardt .checkentry = connmark_mt_check, 126d3c5ee6dSJan Engelhardt .match = connmark_mt, 127d3c5ee6dSJan Engelhardt .destroy = connmark_mt_destroy, 1284470bbc7SPatrick McHardy .matchsize = sizeof(struct xt_connmark_info), 12934f4c429SPatrick McHardy #ifdef CONFIG_COMPAT 13034f4c429SPatrick McHardy .compatsize = sizeof(struct compat_xt_connmark_info), 13134f4c429SPatrick McHardy .compat_from_user = connmark_mt_compat_from_user, 13234f4c429SPatrick McHardy .compat_to_user = connmark_mt_compat_to_user, 13334f4c429SPatrick McHardy #endif 1344470bbc7SPatrick McHardy .me = THIS_MODULE 1354470bbc7SPatrick McHardy }, 1365d04bff0SPatrick McHardy }; 1372e4e6a17SHarald Welte 138d3c5ee6dSJan Engelhardt static int __init connmark_mt_init(void) 1392e4e6a17SHarald Welte { 140d3c5ee6dSJan Engelhardt return xt_register_matches(connmark_mt_reg, 141d3c5ee6dSJan Engelhardt ARRAY_SIZE(connmark_mt_reg)); 1422e4e6a17SHarald Welte } 1432e4e6a17SHarald Welte 144d3c5ee6dSJan Engelhardt static void __exit connmark_mt_exit(void) 1452e4e6a17SHarald Welte { 146d3c5ee6dSJan Engelhardt xt_unregister_matches(connmark_mt_reg, ARRAY_SIZE(connmark_mt_reg)); 1472e4e6a17SHarald Welte } 1482e4e6a17SHarald Welte 149d3c5ee6dSJan Engelhardt module_init(connmark_mt_init); 150d3c5ee6dSJan Engelhardt module_exit(connmark_mt_exit); 151