184f3bb9aSPatrick McHardy /* 284f3bb9aSPatrick McHardy * Copyright (c) 2010 Patrick McHardy <kaber@trash.net> 384f3bb9aSPatrick McHardy * 484f3bb9aSPatrick McHardy * This program is free software; you can redistribute it and/or modify 584f3bb9aSPatrick McHardy * it under the terms of the GNU General Public License version 2 as 684f3bb9aSPatrick McHardy * published by the Free Software Foundation. 784f3bb9aSPatrick McHardy */ 8a7fed762SJan Engelhardt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 984f3bb9aSPatrick McHardy #include <linux/module.h> 105a0e3ad6STejun Heo #include <linux/gfp.h> 1184f3bb9aSPatrick McHardy #include <linux/skbuff.h> 1284f3bb9aSPatrick McHardy #include <linux/netfilter_ipv4/ip_tables.h> 1384f3bb9aSPatrick McHardy #include <linux/netfilter_ipv6/ip6_tables.h> 1484f3bb9aSPatrick McHardy #include <linux/netfilter/x_tables.h> 1584f3bb9aSPatrick McHardy #include <linux/netfilter/xt_CT.h> 1684f3bb9aSPatrick McHardy #include <net/netfilter/nf_conntrack.h> 17eeb4cb95SPablo Neira Ayuso #include <net/netfilter/nf_conntrack_l4proto.h> 1884f3bb9aSPatrick McHardy #include <net/netfilter/nf_conntrack_helper.h> 1984f3bb9aSPatrick McHardy #include <net/netfilter/nf_conntrack_ecache.h> 2024de58f4SPablo Neira Ayuso #include <net/netfilter/nf_conntrack_timeout.h> 215d0aa2ccSPatrick McHardy #include <net/netfilter/nf_conntrack_zones.h> 2284f3bb9aSPatrick McHardy 23d52ed437SPablo Neira Ayuso static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct) 2484f3bb9aSPatrick McHardy { 2584f3bb9aSPatrick McHardy /* Previously seen (loopback)? Ignore. */ 2684f3bb9aSPatrick McHardy if (skb->nfct != NULL) 2784f3bb9aSPatrick McHardy return XT_CONTINUE; 2884f3bb9aSPatrick McHardy 2927e7190eSEric Dumazet /* special case the untracked ct : we want the percpu object */ 3027e7190eSEric Dumazet if (!ct) 3127e7190eSEric Dumazet ct = nf_ct_untracked_get(); 3284f3bb9aSPatrick McHardy atomic_inc(&ct->ct_general.use); 3384f3bb9aSPatrick McHardy skb->nfct = &ct->ct_general; 3484f3bb9aSPatrick McHardy skb->nfctinfo = IP_CT_NEW; 3584f3bb9aSPatrick McHardy 3684f3bb9aSPatrick McHardy return XT_CONTINUE; 3784f3bb9aSPatrick McHardy } 3884f3bb9aSPatrick McHardy 39d52ed437SPablo Neira Ayuso static unsigned int xt_ct_target_v0(struct sk_buff *skb, 40d52ed437SPablo Neira Ayuso const struct xt_action_param *par) 41d52ed437SPablo Neira Ayuso { 42d52ed437SPablo Neira Ayuso const struct xt_ct_target_info *info = par->targinfo; 43d52ed437SPablo Neira Ayuso struct nf_conn *ct = info->ct; 44d52ed437SPablo Neira Ayuso 45d52ed437SPablo Neira Ayuso return xt_ct_target(skb, ct); 46d52ed437SPablo Neira Ayuso } 47d52ed437SPablo Neira Ayuso 4824de58f4SPablo Neira Ayuso static unsigned int xt_ct_target_v1(struct sk_buff *skb, 4924de58f4SPablo Neira Ayuso const struct xt_action_param *par) 5024de58f4SPablo Neira Ayuso { 5124de58f4SPablo Neira Ayuso const struct xt_ct_target_info_v1 *info = par->targinfo; 5224de58f4SPablo Neira Ayuso struct nf_conn *ct = info->ct; 5324de58f4SPablo Neira Ayuso 54d52ed437SPablo Neira Ayuso return xt_ct_target(skb, ct); 5524de58f4SPablo Neira Ayuso } 5624de58f4SPablo Neira Ayuso 5784f3bb9aSPatrick McHardy static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) 5884f3bb9aSPatrick McHardy { 59076f7839SJan Engelhardt if (par->family == NFPROTO_IPV4) { 6084f3bb9aSPatrick McHardy const struct ipt_entry *e = par->entryinfo; 6184f3bb9aSPatrick McHardy 6284f3bb9aSPatrick McHardy if (e->ip.invflags & IPT_INV_PROTO) 6384f3bb9aSPatrick McHardy return 0; 6484f3bb9aSPatrick McHardy return e->ip.proto; 65076f7839SJan Engelhardt } else if (par->family == NFPROTO_IPV6) { 6684f3bb9aSPatrick McHardy const struct ip6t_entry *e = par->entryinfo; 6784f3bb9aSPatrick McHardy 6884f3bb9aSPatrick McHardy if (e->ipv6.invflags & IP6T_INV_PROTO) 6984f3bb9aSPatrick McHardy return 0; 7084f3bb9aSPatrick McHardy return e->ipv6.proto; 7184f3bb9aSPatrick McHardy } else 7284f3bb9aSPatrick McHardy return 0; 7384f3bb9aSPatrick McHardy } 7484f3bb9aSPatrick McHardy 75236df005SPablo Neira Ayuso static int 76236df005SPablo Neira Ayuso xt_ct_set_helper(struct nf_conn *ct, const char *helper_name, 77236df005SPablo Neira Ayuso const struct xt_tgchk_param *par) 78236df005SPablo Neira Ayuso { 79236df005SPablo Neira Ayuso struct nf_conntrack_helper *helper; 80236df005SPablo Neira Ayuso struct nf_conn_help *help; 81236df005SPablo Neira Ayuso u8 proto; 82236df005SPablo Neira Ayuso 83236df005SPablo Neira Ayuso proto = xt_ct_find_proto(par); 84236df005SPablo Neira Ayuso if (!proto) { 85236df005SPablo Neira Ayuso pr_info("You must specify a L4 protocol, and not use " 86236df005SPablo Neira Ayuso "inversions on it.\n"); 87236df005SPablo Neira Ayuso return -ENOENT; 88236df005SPablo Neira Ayuso } 89236df005SPablo Neira Ayuso 90236df005SPablo Neira Ayuso helper = nf_conntrack_helper_try_module_get(helper_name, par->family, 91236df005SPablo Neira Ayuso proto); 92236df005SPablo Neira Ayuso if (helper == NULL) { 93236df005SPablo Neira Ayuso pr_info("No such helper \"%s\"\n", helper_name); 94236df005SPablo Neira Ayuso return -ENOENT; 95236df005SPablo Neira Ayuso } 96236df005SPablo Neira Ayuso 97236df005SPablo Neira Ayuso help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL); 98236df005SPablo Neira Ayuso if (help == NULL) { 99236df005SPablo Neira Ayuso module_put(helper->me); 100236df005SPablo Neira Ayuso return -ENOMEM; 101236df005SPablo Neira Ayuso } 102236df005SPablo Neira Ayuso 103236df005SPablo Neira Ayuso help->helper = helper; 104236df005SPablo Neira Ayuso return 0; 105236df005SPablo Neira Ayuso } 106236df005SPablo Neira Ayuso 107ee14186fSPablo Neira Ayuso #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 108ee14186fSPablo Neira Ayuso static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout) 109ee14186fSPablo Neira Ayuso { 110ee14186fSPablo Neira Ayuso typeof(nf_ct_timeout_put_hook) timeout_put; 111ee14186fSPablo Neira Ayuso 112ee14186fSPablo Neira Ayuso timeout_put = rcu_dereference(nf_ct_timeout_put_hook); 113ee14186fSPablo Neira Ayuso if (timeout_put) 114ee14186fSPablo Neira Ayuso timeout_put(timeout); 115ee14186fSPablo Neira Ayuso } 116ee14186fSPablo Neira Ayuso #endif 117ee14186fSPablo Neira Ayuso 118236df005SPablo Neira Ayuso static int 119236df005SPablo Neira Ayuso xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, 120236df005SPablo Neira Ayuso const char *timeout_name) 121236df005SPablo Neira Ayuso { 122236df005SPablo Neira Ayuso #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 123236df005SPablo Neira Ayuso typeof(nf_ct_timeout_find_get_hook) timeout_find_get; 124236df005SPablo Neira Ayuso struct ctnl_timeout *timeout; 125236df005SPablo Neira Ayuso struct nf_conn_timeout *timeout_ext; 126236df005SPablo Neira Ayuso struct nf_conntrack_l4proto *l4proto; 127236df005SPablo Neira Ayuso int ret = 0; 1280153d5a8SPablo Neira Ayuso u8 proto; 129236df005SPablo Neira Ayuso 130236df005SPablo Neira Ayuso rcu_read_lock(); 131236df005SPablo Neira Ayuso timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); 132236df005SPablo Neira Ayuso if (timeout_find_get == NULL) { 133236df005SPablo Neira Ayuso ret = -ENOENT; 134236df005SPablo Neira Ayuso pr_info("Timeout policy base is empty\n"); 135236df005SPablo Neira Ayuso goto out; 136236df005SPablo Neira Ayuso } 137236df005SPablo Neira Ayuso 1380153d5a8SPablo Neira Ayuso proto = xt_ct_find_proto(par); 1390153d5a8SPablo Neira Ayuso if (!proto) { 140236df005SPablo Neira Ayuso ret = -EINVAL; 1410153d5a8SPablo Neira Ayuso pr_info("You must specify a L4 protocol, and not use " 1420153d5a8SPablo Neira Ayuso "inversions on it.\n"); 143236df005SPablo Neira Ayuso goto out; 144236df005SPablo Neira Ayuso } 145236df005SPablo Neira Ayuso 146236df005SPablo Neira Ayuso timeout = timeout_find_get(timeout_name); 147236df005SPablo Neira Ayuso if (timeout == NULL) { 148236df005SPablo Neira Ayuso ret = -ENOENT; 149236df005SPablo Neira Ayuso pr_info("No such timeout policy \"%s\"\n", timeout_name); 150236df005SPablo Neira Ayuso goto out; 151236df005SPablo Neira Ayuso } 152236df005SPablo Neira Ayuso 153236df005SPablo Neira Ayuso if (timeout->l3num != par->family) { 154236df005SPablo Neira Ayuso ret = -EINVAL; 155236df005SPablo Neira Ayuso pr_info("Timeout policy `%s' can only be used by L3 protocol " 156236df005SPablo Neira Ayuso "number %d\n", timeout_name, timeout->l3num); 157236df005SPablo Neira Ayuso goto err_put_timeout; 158236df005SPablo Neira Ayuso } 159236df005SPablo Neira Ayuso /* Make sure the timeout policy matches any existing protocol tracker, 160236df005SPablo Neira Ayuso * otherwise default to generic. 161236df005SPablo Neira Ayuso */ 1620153d5a8SPablo Neira Ayuso l4proto = __nf_ct_l4proto_find(par->family, proto); 163236df005SPablo Neira Ayuso if (timeout->l4proto->l4proto != l4proto->l4proto) { 164236df005SPablo Neira Ayuso ret = -EINVAL; 165236df005SPablo Neira Ayuso pr_info("Timeout policy `%s' can only be used by L4 protocol " 166236df005SPablo Neira Ayuso "number %d\n", 167236df005SPablo Neira Ayuso timeout_name, timeout->l4proto->l4proto); 168236df005SPablo Neira Ayuso goto err_put_timeout; 169236df005SPablo Neira Ayuso } 170236df005SPablo Neira Ayuso timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); 171236df005SPablo Neira Ayuso if (timeout_ext == NULL) 172236df005SPablo Neira Ayuso ret = -ENOMEM; 173236df005SPablo Neira Ayuso 174236df005SPablo Neira Ayuso err_put_timeout: 175236df005SPablo Neira Ayuso __xt_ct_tg_timeout_put(timeout); 176236df005SPablo Neira Ayuso out: 177236df005SPablo Neira Ayuso rcu_read_unlock(); 178236df005SPablo Neira Ayuso return ret; 179236df005SPablo Neira Ayuso #else 180236df005SPablo Neira Ayuso return -EOPNOTSUPP; 181236df005SPablo Neira Ayuso #endif 182236df005SPablo Neira Ayuso } 183236df005SPablo Neira Ayuso 184d52ed437SPablo Neira Ayuso static int xt_ct_tg_check(const struct xt_tgchk_param *par, 185d52ed437SPablo Neira Ayuso struct xt_ct_target_info_v1 *info) 18624de58f4SPablo Neira Ayuso { 18724de58f4SPablo Neira Ayuso struct nf_conn *ct; 1884610476dSPablo Neira Ayuso int ret = -EOPNOTSUPP; 189236df005SPablo Neira Ayuso 19024de58f4SPablo Neira Ayuso if (info->flags & XT_CT_NOTRACK) { 19127e7190eSEric Dumazet ct = NULL; 19224de58f4SPablo Neira Ayuso goto out; 19324de58f4SPablo Neira Ayuso } 19424de58f4SPablo Neira Ayuso 19524de58f4SPablo Neira Ayuso #ifndef CONFIG_NF_CONNTRACK_ZONES 19624de58f4SPablo Neira Ayuso if (info->zone) 19724de58f4SPablo Neira Ayuso goto err1; 19824de58f4SPablo Neira Ayuso #endif 19924de58f4SPablo Neira Ayuso 20024de58f4SPablo Neira Ayuso ret = nf_ct_l3proto_try_module_get(par->family); 20124de58f4SPablo Neira Ayuso if (ret < 0) 20224de58f4SPablo Neira Ayuso goto err1; 20324de58f4SPablo Neira Ayuso 2040838aa7fSPablo Neira Ayuso ct = nf_ct_tmpl_alloc(par->net, info->zone, GFP_KERNEL); 20524de58f4SPablo Neira Ayuso ret = PTR_ERR(ct); 20624de58f4SPablo Neira Ayuso if (IS_ERR(ct)) 20724de58f4SPablo Neira Ayuso goto err2; 20824de58f4SPablo Neira Ayuso 20924de58f4SPablo Neira Ayuso ret = 0; 21024de58f4SPablo Neira Ayuso if ((info->ct_events || info->exp_events) && 21124de58f4SPablo Neira Ayuso !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, 21214abfa16SEric Leblond GFP_KERNEL)) { 21314abfa16SEric Leblond ret = -EINVAL; 21424de58f4SPablo Neira Ayuso goto err3; 21514abfa16SEric Leblond } 21624de58f4SPablo Neira Ayuso 21724de58f4SPablo Neira Ayuso if (info->helper[0]) { 218236df005SPablo Neira Ayuso ret = xt_ct_set_helper(ct, info->helper, par); 219236df005SPablo Neira Ayuso if (ret < 0) 22024de58f4SPablo Neira Ayuso goto err3; 22124de58f4SPablo Neira Ayuso } 22224de58f4SPablo Neira Ayuso 2236cf51852SPablo Neira Ayuso if (info->timeout[0]) { 224236df005SPablo Neira Ayuso ret = xt_ct_set_timeout(ct, par, info->timeout); 225236df005SPablo Neira Ayuso if (ret < 0) 226236df005SPablo Neira Ayuso goto err3; 22724de58f4SPablo Neira Ayuso } 2280838aa7fSPablo Neira Ayuso __set_bit(IPS_CONFIRMED_BIT, &ct->status); 2290838aa7fSPablo Neira Ayuso nf_conntrack_get(&ct->ct_general); 23024de58f4SPablo Neira Ayuso out: 23124de58f4SPablo Neira Ayuso info->ct = ct; 23224de58f4SPablo Neira Ayuso return 0; 23324de58f4SPablo Neira Ayuso 23424de58f4SPablo Neira Ayuso err3: 23524de58f4SPablo Neira Ayuso nf_conntrack_free(ct); 23624de58f4SPablo Neira Ayuso err2: 23724de58f4SPablo Neira Ayuso nf_ct_l3proto_module_put(par->family); 23824de58f4SPablo Neira Ayuso err1: 23924de58f4SPablo Neira Ayuso return ret; 24024de58f4SPablo Neira Ayuso } 24124de58f4SPablo Neira Ayuso 242d52ed437SPablo Neira Ayuso static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) 24384f3bb9aSPatrick McHardy { 24484f3bb9aSPatrick McHardy struct xt_ct_target_info *info = par->targinfo; 245d52ed437SPablo Neira Ayuso struct xt_ct_target_info_v1 info_v1 = { 246d52ed437SPablo Neira Ayuso .flags = info->flags, 247d52ed437SPablo Neira Ayuso .zone = info->zone, 248d52ed437SPablo Neira Ayuso .ct_events = info->ct_events, 249d52ed437SPablo Neira Ayuso .exp_events = info->exp_events, 250d52ed437SPablo Neira Ayuso }; 251d52ed437SPablo Neira Ayuso int ret; 25284f3bb9aSPatrick McHardy 2535474f57fSPablo Neira Ayuso if (info->flags & ~XT_CT_NOTRACK) 2545474f57fSPablo Neira Ayuso return -EINVAL; 2555474f57fSPablo Neira Ayuso 256d52ed437SPablo Neira Ayuso memcpy(info_v1.helper, info->helper, sizeof(info->helper)); 25784f3bb9aSPatrick McHardy 258d52ed437SPablo Neira Ayuso ret = xt_ct_tg_check(par, &info_v1); 259d52ed437SPablo Neira Ayuso if (ret < 0) 260d52ed437SPablo Neira Ayuso return ret; 261d52ed437SPablo Neira Ayuso 262d52ed437SPablo Neira Ayuso info->ct = info_v1.ct; 263d52ed437SPablo Neira Ayuso 264d52ed437SPablo Neira Ayuso return ret; 26584f3bb9aSPatrick McHardy } 266d52ed437SPablo Neira Ayuso 267d52ed437SPablo Neira Ayuso static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) 268d52ed437SPablo Neira Ayuso { 2695474f57fSPablo Neira Ayuso struct xt_ct_target_info_v1 *info = par->targinfo; 2705474f57fSPablo Neira Ayuso 2715474f57fSPablo Neira Ayuso if (info->flags & ~XT_CT_NOTRACK) 2725474f57fSPablo Neira Ayuso return -EINVAL; 2735474f57fSPablo Neira Ayuso 2745474f57fSPablo Neira Ayuso return xt_ct_tg_check(par, par->targinfo); 2755474f57fSPablo Neira Ayuso } 2765474f57fSPablo Neira Ayuso 2775474f57fSPablo Neira Ayuso static int xt_ct_tg_check_v2(const struct xt_tgchk_param *par) 2785474f57fSPablo Neira Ayuso { 2795474f57fSPablo Neira Ayuso struct xt_ct_target_info_v1 *info = par->targinfo; 2805474f57fSPablo Neira Ayuso 2815474f57fSPablo Neira Ayuso if (info->flags & ~XT_CT_MASK) 2825474f57fSPablo Neira Ayuso return -EINVAL; 2835474f57fSPablo Neira Ayuso 284d52ed437SPablo Neira Ayuso return xt_ct_tg_check(par, par->targinfo); 28584f3bb9aSPatrick McHardy } 28684f3bb9aSPatrick McHardy 287236df005SPablo Neira Ayuso static void xt_ct_destroy_timeout(struct nf_conn *ct) 28824de58f4SPablo Neira Ayuso { 28924de58f4SPablo Neira Ayuso #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 29024de58f4SPablo Neira Ayuso struct nf_conn_timeout *timeout_ext; 29124de58f4SPablo Neira Ayuso typeof(nf_ct_timeout_put_hook) timeout_put; 29224de58f4SPablo Neira Ayuso 2931ac0bf99SPablo Neira Ayuso rcu_read_lock(); 29424de58f4SPablo Neira Ayuso timeout_put = rcu_dereference(nf_ct_timeout_put_hook); 29524de58f4SPablo Neira Ayuso 29624de58f4SPablo Neira Ayuso if (timeout_put) { 29724de58f4SPablo Neira Ayuso timeout_ext = nf_ct_timeout_find(ct); 29824de58f4SPablo Neira Ayuso if (timeout_ext) 29924de58f4SPablo Neira Ayuso timeout_put(timeout_ext->timeout); 30024de58f4SPablo Neira Ayuso } 3011ac0bf99SPablo Neira Ayuso rcu_read_unlock(); 30224de58f4SPablo Neira Ayuso #endif 30324de58f4SPablo Neira Ayuso } 304236df005SPablo Neira Ayuso 305d52ed437SPablo Neira Ayuso static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par, 306d52ed437SPablo Neira Ayuso struct xt_ct_target_info_v1 *info) 307236df005SPablo Neira Ayuso { 308236df005SPablo Neira Ayuso struct nf_conn *ct = info->ct; 309236df005SPablo Neira Ayuso struct nf_conn_help *help; 310236df005SPablo Neira Ayuso 31127e7190eSEric Dumazet if (ct && !nf_ct_is_untracked(ct)) { 312236df005SPablo Neira Ayuso help = nfct_help(ct); 313236df005SPablo Neira Ayuso if (help) 314236df005SPablo Neira Ayuso module_put(help->helper->me); 315236df005SPablo Neira Ayuso 316236df005SPablo Neira Ayuso nf_ct_l3proto_module_put(par->family); 317236df005SPablo Neira Ayuso 318236df005SPablo Neira Ayuso xt_ct_destroy_timeout(ct); 31924de58f4SPablo Neira Ayuso nf_ct_put(info->ct); 32024de58f4SPablo Neira Ayuso } 32127e7190eSEric Dumazet } 32224de58f4SPablo Neira Ayuso 323d52ed437SPablo Neira Ayuso static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) 324d52ed437SPablo Neira Ayuso { 325d52ed437SPablo Neira Ayuso struct xt_ct_target_info *info = par->targinfo; 326d52ed437SPablo Neira Ayuso struct xt_ct_target_info_v1 info_v1 = { 327d52ed437SPablo Neira Ayuso .flags = info->flags, 328d52ed437SPablo Neira Ayuso .zone = info->zone, 329d52ed437SPablo Neira Ayuso .ct_events = info->ct_events, 330d52ed437SPablo Neira Ayuso .exp_events = info->exp_events, 331d52ed437SPablo Neira Ayuso .ct = info->ct, 332d52ed437SPablo Neira Ayuso }; 333d52ed437SPablo Neira Ayuso memcpy(info_v1.helper, info->helper, sizeof(info->helper)); 334d52ed437SPablo Neira Ayuso 335d52ed437SPablo Neira Ayuso xt_ct_tg_destroy(par, &info_v1); 336d52ed437SPablo Neira Ayuso } 337d52ed437SPablo Neira Ayuso 338d52ed437SPablo Neira Ayuso static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) 339d52ed437SPablo Neira Ayuso { 340d52ed437SPablo Neira Ayuso xt_ct_tg_destroy(par, par->targinfo); 341d52ed437SPablo Neira Ayuso } 342d52ed437SPablo Neira Ayuso 34324de58f4SPablo Neira Ayuso static struct xt_target xt_ct_tg_reg[] __read_mostly = { 34424de58f4SPablo Neira Ayuso { 34584f3bb9aSPatrick McHardy .name = "CT", 34684f3bb9aSPatrick McHardy .family = NFPROTO_UNSPEC, 3477d5f7ed8SJan Engelhardt .targetsize = sizeof(struct xt_ct_target_info), 34824de58f4SPablo Neira Ayuso .checkentry = xt_ct_tg_check_v0, 34924de58f4SPablo Neira Ayuso .destroy = xt_ct_tg_destroy_v0, 35024de58f4SPablo Neira Ayuso .target = xt_ct_target_v0, 35184f3bb9aSPatrick McHardy .table = "raw", 35284f3bb9aSPatrick McHardy .me = THIS_MODULE, 35324de58f4SPablo Neira Ayuso }, 35424de58f4SPablo Neira Ayuso { 35524de58f4SPablo Neira Ayuso .name = "CT", 35624de58f4SPablo Neira Ayuso .family = NFPROTO_UNSPEC, 35724de58f4SPablo Neira Ayuso .revision = 1, 35824de58f4SPablo Neira Ayuso .targetsize = sizeof(struct xt_ct_target_info_v1), 35924de58f4SPablo Neira Ayuso .checkentry = xt_ct_tg_check_v1, 36024de58f4SPablo Neira Ayuso .destroy = xt_ct_tg_destroy_v1, 36124de58f4SPablo Neira Ayuso .target = xt_ct_target_v1, 36224de58f4SPablo Neira Ayuso .table = "raw", 36324de58f4SPablo Neira Ayuso .me = THIS_MODULE, 36424de58f4SPablo Neira Ayuso }, 3655474f57fSPablo Neira Ayuso { 3665474f57fSPablo Neira Ayuso .name = "CT", 3675474f57fSPablo Neira Ayuso .family = NFPROTO_UNSPEC, 3685474f57fSPablo Neira Ayuso .revision = 2, 3695474f57fSPablo Neira Ayuso .targetsize = sizeof(struct xt_ct_target_info_v1), 3705474f57fSPablo Neira Ayuso .checkentry = xt_ct_tg_check_v2, 3715474f57fSPablo Neira Ayuso .destroy = xt_ct_tg_destroy_v1, 3725474f57fSPablo Neira Ayuso .target = xt_ct_target_v1, 3735474f57fSPablo Neira Ayuso .table = "raw", 3745474f57fSPablo Neira Ayuso .me = THIS_MODULE, 3755474f57fSPablo Neira Ayuso }, 37684f3bb9aSPatrick McHardy }; 37784f3bb9aSPatrick McHardy 37810db9069SPablo Neira Ayuso static unsigned int 37910db9069SPablo Neira Ayuso notrack_tg(struct sk_buff *skb, const struct xt_action_param *par) 38010db9069SPablo Neira Ayuso { 38110db9069SPablo Neira Ayuso /* Previously seen (loopback)? Ignore. */ 38210db9069SPablo Neira Ayuso if (skb->nfct != NULL) 38310db9069SPablo Neira Ayuso return XT_CONTINUE; 38410db9069SPablo Neira Ayuso 38510db9069SPablo Neira Ayuso skb->nfct = &nf_ct_untracked_get()->ct_general; 38610db9069SPablo Neira Ayuso skb->nfctinfo = IP_CT_NEW; 38710db9069SPablo Neira Ayuso nf_conntrack_get(skb->nfct); 38810db9069SPablo Neira Ayuso 38910db9069SPablo Neira Ayuso return XT_CONTINUE; 39010db9069SPablo Neira Ayuso } 39110db9069SPablo Neira Ayuso 39210db9069SPablo Neira Ayuso static int notrack_chk(const struct xt_tgchk_param *par) 39310db9069SPablo Neira Ayuso { 39410db9069SPablo Neira Ayuso if (!par->net->xt.notrack_deprecated_warning) { 39510db9069SPablo Neira Ayuso pr_info("netfilter: NOTRACK target is deprecated, " 39610db9069SPablo Neira Ayuso "use CT instead or upgrade iptables\n"); 39710db9069SPablo Neira Ayuso par->net->xt.notrack_deprecated_warning = true; 39810db9069SPablo Neira Ayuso } 39910db9069SPablo Neira Ayuso return 0; 40010db9069SPablo Neira Ayuso } 40110db9069SPablo Neira Ayuso 40210db9069SPablo Neira Ayuso static struct xt_target notrack_tg_reg __read_mostly = { 40310db9069SPablo Neira Ayuso .name = "NOTRACK", 40410db9069SPablo Neira Ayuso .revision = 0, 40510db9069SPablo Neira Ayuso .family = NFPROTO_UNSPEC, 40610db9069SPablo Neira Ayuso .checkentry = notrack_chk, 40710db9069SPablo Neira Ayuso .target = notrack_tg, 40810db9069SPablo Neira Ayuso .table = "raw", 40910db9069SPablo Neira Ayuso .me = THIS_MODULE, 41010db9069SPablo Neira Ayuso }; 41110db9069SPablo Neira Ayuso 41284f3bb9aSPatrick McHardy static int __init xt_ct_tg_init(void) 41384f3bb9aSPatrick McHardy { 41410db9069SPablo Neira Ayuso int ret; 41510db9069SPablo Neira Ayuso 41610db9069SPablo Neira Ayuso ret = xt_register_target(¬rack_tg_reg); 41710db9069SPablo Neira Ayuso if (ret < 0) 41810db9069SPablo Neira Ayuso return ret; 41910db9069SPablo Neira Ayuso 42010db9069SPablo Neira Ayuso ret = xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg)); 42110db9069SPablo Neira Ayuso if (ret < 0) { 42210db9069SPablo Neira Ayuso xt_unregister_target(¬rack_tg_reg); 42310db9069SPablo Neira Ayuso return ret; 42410db9069SPablo Neira Ayuso } 42510db9069SPablo Neira Ayuso return 0; 42684f3bb9aSPatrick McHardy } 42784f3bb9aSPatrick McHardy 42884f3bb9aSPatrick McHardy static void __exit xt_ct_tg_exit(void) 42984f3bb9aSPatrick McHardy { 43024de58f4SPablo Neira Ayuso xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg)); 43110db9069SPablo Neira Ayuso xt_unregister_target(¬rack_tg_reg); 43284f3bb9aSPatrick McHardy } 43384f3bb9aSPatrick McHardy 43484f3bb9aSPatrick McHardy module_init(xt_ct_tg_init); 43584f3bb9aSPatrick McHardy module_exit(xt_ct_tg_exit); 43684f3bb9aSPatrick McHardy 43784f3bb9aSPatrick McHardy MODULE_LICENSE("GPL"); 43884f3bb9aSPatrick McHardy MODULE_DESCRIPTION("Xtables: connection tracking target"); 43984f3bb9aSPatrick McHardy MODULE_ALIAS("ipt_CT"); 44084f3bb9aSPatrick McHardy MODULE_ALIAS("ip6t_CT"); 44110db9069SPablo Neira Ayuso MODULE_ALIAS("ipt_NOTRACK"); 44210db9069SPablo Neira Ayuso MODULE_ALIAS("ip6t_NOTRACK"); 443