xt_connmark.c revision 135367b8f6a18507af6b9a6910a14b5699415309
196e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt/* 2b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt * xt_connmark - Netfilter module to operate on connection marks 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 496e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> 596e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt * by Henrik Nordstrom <hno@marasystems.com> 696e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt * Copyright © CC Computer Consultants GmbH, 2007 - 2008 7408ffaa4a11ddd6f730be520479fd5cd890c57d3Jan Engelhardt * Jan Engelhardt <jengelh@medozas.de> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 26587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <net/netfilter/nf_conntrack.h> 27b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt#include <net/netfilter/nf_conntrack_ecache.h> 28587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <linux/netfilter/x_tables.h> 29587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <linux/netfilter/xt_connmark.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 313a4fa0a25da81600ea0bcd75692ae8ca6050d165Robert P. J. DayMODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>"); 32b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_DESCRIPTION("Xtables: connection mark operations"); 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 34b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_ALIAS("ipt_CONNMARK"); 35b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_ALIAS("ip6t_CONNMARK"); 362e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteMODULE_ALIAS("ipt_connmark"); 3773aaf9355b71d295fd72dc0b93fcdd275c56648fJan EngelhardtMODULE_ALIAS("ip6t_connmark"); 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtstatic unsigned int 40b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtconnmark_tg(struct sk_buff *skb, const struct xt_target_param *par) 41b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt{ 42b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt const struct xt_connmark_tginfo1 *info = par->targinfo; 43b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt enum ip_conntrack_info ctinfo; 44b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt struct nf_conn *ct; 45b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt u_int32_t newmark; 46b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 47b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt ct = nf_ct_get(skb, &ctinfo); 48b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (ct == NULL) 49b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return XT_CONTINUE; 50b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 51b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt switch (info->mode) { 52b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt case XT_CONNMARK_SET: 53b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; 54b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (ct->mark != newmark) { 55b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt ct->mark = newmark; 56b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt nf_conntrack_event_cache(IPCT_MARK, ct); 57b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt } 58b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt break; 59b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt case XT_CONNMARK_SAVE: 60b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt newmark = (ct->mark & ~info->ctmask) ^ 61b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt (skb->mark & info->nfmask); 62b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (ct->mark != newmark) { 63b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt ct->mark = newmark; 64b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt nf_conntrack_event_cache(IPCT_MARK, ct); 65b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt } 66b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt break; 67b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt case XT_CONNMARK_RESTORE: 68b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt newmark = (skb->mark & ~info->nfmask) ^ 69b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt (ct->mark & info->ctmask); 70b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt skb->mark = newmark; 71b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt break; 72b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt } 73b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 74b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return XT_CONTINUE; 75b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt} 76b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 77135367b8f6a18507af6b9a6910a14b5699415309Jan Engelhardtstatic int connmark_tg_check(const struct xt_tgchk_param *par) 78b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt{ 79b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (nf_ct_l3proto_try_module_get(par->family) < 0) { 808bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt pr_info("cannot load conntrack support for proto=%u\n", 818bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt par->family); 82b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return false; 83b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt } 84b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return true; 85b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt} 86b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 87b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtstatic void connmark_tg_destroy(const struct xt_tgdtor_param *par) 88b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt{ 89b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt nf_ct_l3proto_module_put(par->family); 90b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt} 91b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 921d93a9cbad608f6398ba6c5b588c504ccd35a2caJan Engelhardtstatic bool 93f7108a20dee44e5bb037f9e48f6a207b42e6ae1cJan Engelhardtconnmark_mt(const struct sk_buff *skb, const struct xt_match_param *par) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 95f7108a20dee44e5bb037f9e48f6a207b42e6ae1cJan Engelhardt const struct xt_connmark_mtinfo1 *info = par->matchinfo; 9696e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt enum ip_conntrack_info ctinfo; 9796e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt const struct nf_conn *ct; 9896e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt 9996e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt ct = nf_ct_get(skb, &ctinfo); 10096e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt if (ct == NULL) 10196e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt return false; 10296e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt 10396e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt return ((ct->mark & info->mask) == info->mark) ^ info->invert; 10496e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt} 10596e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt 106b0f38452ff73da7e9e0ddc68cd5c6b93c897ca0dJan Engelhardtstatic int connmark_mt_check(const struct xt_mtchk_param *par) 10796e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt{ 10892f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt if (nf_ct_l3proto_try_module_get(par->family) < 0) { 1098bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt pr_info("cannot load conntrack support for proto=%u\n", 1108bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt par->family); 11196e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt return false; 11296e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt } 11396e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt return true; 11496e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt} 11596e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt 1166be3d8598e883fb632edf059ba2f8d1b9f4da138Jan Engelhardtstatic void connmark_mt_destroy(const struct xt_mtdtor_param *par) 117b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso{ 11892f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt nf_ct_l3proto_module_put(par->family); 119b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso} 120b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso 121b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtstatic struct xt_target connmark_tg_reg __read_mostly = { 122b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .name = "CONNMARK", 123b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .revision = 1, 124b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .family = NFPROTO_UNSPEC, 125b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .checkentry = connmark_tg_check, 126b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .target = connmark_tg, 127b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .targetsize = sizeof(struct xt_connmark_tginfo1), 128b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .destroy = connmark_tg_destroy, 129b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .me = THIS_MODULE, 130b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt}; 131b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 13284899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardtstatic struct xt_match connmark_mt_reg __read_mostly = { 13384899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .name = "connmark", 13484899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .revision = 1, 13584899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .family = NFPROTO_UNSPEC, 13684899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .checkentry = connmark_mt_check, 13784899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .match = connmark_mt, 13884899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .matchsize = sizeof(struct xt_connmark_mtinfo1), 13984899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .destroy = connmark_mt_destroy, 14084899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .me = THIS_MODULE, 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 143d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic int __init connmark_mt_init(void) 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 145b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt int ret; 146b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 147b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt ret = xt_register_target(&connmark_tg_reg); 148b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (ret < 0) 149b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return ret; 150b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt ret = xt_register_match(&connmark_mt_reg); 151b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (ret < 0) { 152b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt xt_unregister_target(&connmark_tg_reg); 153b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return ret; 154b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt } 155b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return 0; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 158d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic void __exit connmark_mt_exit(void) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16084899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt xt_unregister_match(&connmark_mt_reg); 161b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt xt_unregister_target(&connmark_tg_reg); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 164d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_init(connmark_mt_init); 165d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_exit(connmark_mt_exit); 166