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 20e664eabd18c4581b21ea6f62e2e599df5a719a5bJeff Kirsher * along with this program; if not, see <http://www.gnu.org/licenses/>. 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 25587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <net/netfilter/nf_conntrack.h> 26b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt#include <net/netfilter/nf_conntrack_ecache.h> 27587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <linux/netfilter/x_tables.h> 28587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <linux/netfilter/xt_connmark.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 303a4fa0a25da81600ea0bcd75692ae8ca6050d165Robert P. J. DayMODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>"); 31b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_DESCRIPTION("Xtables: connection mark operations"); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 33b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_ALIAS("ipt_CONNMARK"); 34b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan EngelhardtMODULE_ALIAS("ip6t_CONNMARK"); 352e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald WelteMODULE_ALIAS("ipt_connmark"); 3673aaf9355b71d295fd72dc0b93fcdd275c56648fJan EngelhardtMODULE_ALIAS("ip6t_connmark"); 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtstatic unsigned int 394b560b447df83368df44bd3712c0c39b1d79ba04Jan Engelhardtconnmark_tg(struct sk_buff *skb, const struct xt_action_param *par) 40b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt{ 41b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt const struct xt_connmark_tginfo1 *info = par->targinfo; 42b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt enum ip_conntrack_info ctinfo; 43b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt struct nf_conn *ct; 44b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt u_int32_t newmark; 45b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 46b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt ct = nf_ct_get(skb, &ctinfo); 47b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (ct == NULL) 48b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return XT_CONTINUE; 49b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 50b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt switch (info->mode) { 51b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt case XT_CONNMARK_SET: 52b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; 53b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (ct->mark != newmark) { 54b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt ct->mark = newmark; 55b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt nf_conntrack_event_cache(IPCT_MARK, ct); 56b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt } 57b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt break; 58b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt case XT_CONNMARK_SAVE: 59b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt newmark = (ct->mark & ~info->ctmask) ^ 60b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt (skb->mark & info->nfmask); 61b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (ct->mark != newmark) { 62b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt ct->mark = newmark; 63b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt nf_conntrack_event_cache(IPCT_MARK, ct); 64b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt } 65b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt break; 66b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt case XT_CONNMARK_RESTORE: 67b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt newmark = (skb->mark & ~info->nfmask) ^ 68b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt (ct->mark & info->ctmask); 69b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt skb->mark = newmark; 70b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt break; 71b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt } 72b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 73b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return XT_CONTINUE; 74b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt} 75b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 76135367b8f6a18507af6b9a6910a14b5699415309Jan Engelhardtstatic int connmark_tg_check(const struct xt_tgchk_param *par) 77b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt{ 784a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt int ret; 794a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt 804a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt ret = nf_ct_l3proto_try_module_get(par->family); 81f95c74e33eff5e3fe9798e2dc0a7749150ea3f80Jan Engelhardt if (ret < 0) 828bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt pr_info("cannot load conntrack support for proto=%u\n", 838bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt par->family); 84f95c74e33eff5e3fe9798e2dc0a7749150ea3f80Jan Engelhardt return ret; 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 9362fc8051083a334578c3f4b3488808f210b4565fJan Engelhardtconnmark_mt(const struct sk_buff *skb, struct xt_action_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{ 1084a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt int ret; 1094a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt 1104a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt ret = nf_ct_l3proto_try_module_get(par->family); 111f95c74e33eff5e3fe9798e2dc0a7749150ea3f80Jan Engelhardt if (ret < 0) 1128bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt pr_info("cannot load conntrack support for proto=%u\n", 1138bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt par->family); 114f95c74e33eff5e3fe9798e2dc0a7749150ea3f80Jan Engelhardt return ret; 11596e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt} 11696e3227265852ffad332f911887c9cf26c85e40aJan Engelhardt 1176be3d8598e883fb632edf059ba2f8d1b9f4da138Jan Engelhardtstatic void connmark_mt_destroy(const struct xt_mtdtor_param *par) 118b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso{ 11992f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt nf_ct_l3proto_module_put(par->family); 120b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso} 121b9f78f9fca626875af8adc0f7366a38b8e625a0ePablo Neira Ayuso 122b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardtstatic struct xt_target connmark_tg_reg __read_mostly = { 123b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .name = "CONNMARK", 124b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .revision = 1, 125b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .family = NFPROTO_UNSPEC, 126b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .checkentry = connmark_tg_check, 127b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .target = connmark_tg, 128b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .targetsize = sizeof(struct xt_connmark_tginfo1), 129b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .destroy = connmark_tg_destroy, 130b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt .me = THIS_MODULE, 131b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt}; 132b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 13384899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardtstatic struct xt_match connmark_mt_reg __read_mostly = { 13484899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .name = "connmark", 13584899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .revision = 1, 13684899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .family = NFPROTO_UNSPEC, 13784899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .checkentry = connmark_mt_check, 13884899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .match = connmark_mt, 13984899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .matchsize = sizeof(struct xt_connmark_mtinfo1), 14084899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .destroy = connmark_mt_destroy, 14184899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt .me = THIS_MODULE, 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 144d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic int __init connmark_mt_init(void) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 146b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt int ret; 147b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt 148b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt ret = xt_register_target(&connmark_tg_reg); 149b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (ret < 0) 150b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return ret; 151b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt ret = xt_register_match(&connmark_mt_reg); 152b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt if (ret < 0) { 153b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt xt_unregister_target(&connmark_tg_reg); 154b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return ret; 155b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt } 156b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt return 0; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 159d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic void __exit connmark_mt_exit(void) 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16184899a2b9adaf6c2e20d198d7c24562ce6b391d8Jan Engelhardt xt_unregister_match(&connmark_mt_reg); 162b8f00ba27e4acc4a2224360ce3aa8a22354434c5Jan Engelhardt xt_unregister_target(&connmark_tg_reg); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 165d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_init(connmark_mt_init); 166d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_exit(connmark_mt_exit); 167