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> 20c1ebd7dfSPablo Neira Ayuso #include <net/netfilter/nf_conntrack_l4proto.h> 2124de58f4SPablo Neira Ayuso #include <net/netfilter/nf_conntrack_timeout.h> 225d0aa2ccSPatrick McHardy #include <net/netfilter/nf_conntrack_zones.h> 2384f3bb9aSPatrick McHardy 2424de58f4SPablo Neira Ayuso static unsigned int xt_ct_target_v0(struct sk_buff *skb, 254b560b44SJan Engelhardt const struct xt_action_param *par) 2684f3bb9aSPatrick McHardy { 2784f3bb9aSPatrick McHardy const struct xt_ct_target_info *info = par->targinfo; 2884f3bb9aSPatrick McHardy struct nf_conn *ct = info->ct; 2984f3bb9aSPatrick McHardy 3084f3bb9aSPatrick McHardy /* Previously seen (loopback)? Ignore. */ 3184f3bb9aSPatrick McHardy if (skb->nfct != NULL) 3284f3bb9aSPatrick McHardy return XT_CONTINUE; 3384f3bb9aSPatrick McHardy 3484f3bb9aSPatrick McHardy atomic_inc(&ct->ct_general.use); 3584f3bb9aSPatrick McHardy skb->nfct = &ct->ct_general; 3684f3bb9aSPatrick McHardy skb->nfctinfo = IP_CT_NEW; 3784f3bb9aSPatrick McHardy 3884f3bb9aSPatrick McHardy return XT_CONTINUE; 3984f3bb9aSPatrick McHardy } 4084f3bb9aSPatrick McHardy 4124de58f4SPablo Neira Ayuso static unsigned int xt_ct_target_v1(struct sk_buff *skb, 4224de58f4SPablo Neira Ayuso const struct xt_action_param *par) 4324de58f4SPablo Neira Ayuso { 4424de58f4SPablo Neira Ayuso const struct xt_ct_target_info_v1 *info = par->targinfo; 4524de58f4SPablo Neira Ayuso struct nf_conn *ct = info->ct; 4624de58f4SPablo Neira Ayuso 4724de58f4SPablo Neira Ayuso /* Previously seen (loopback)? Ignore. */ 4824de58f4SPablo Neira Ayuso if (skb->nfct != NULL) 4924de58f4SPablo Neira Ayuso return XT_CONTINUE; 5024de58f4SPablo Neira Ayuso 5124de58f4SPablo Neira Ayuso atomic_inc(&ct->ct_general.use); 5224de58f4SPablo Neira Ayuso skb->nfct = &ct->ct_general; 5324de58f4SPablo Neira Ayuso skb->nfctinfo = IP_CT_NEW; 5424de58f4SPablo Neira Ayuso 5524de58f4SPablo Neira Ayuso return XT_CONTINUE; 5624de58f4SPablo Neira Ayuso } 5724de58f4SPablo Neira Ayuso 5884f3bb9aSPatrick McHardy static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) 5984f3bb9aSPatrick McHardy { 60076f7839SJan Engelhardt if (par->family == NFPROTO_IPV4) { 6184f3bb9aSPatrick McHardy const struct ipt_entry *e = par->entryinfo; 6284f3bb9aSPatrick McHardy 6384f3bb9aSPatrick McHardy if (e->ip.invflags & IPT_INV_PROTO) 6484f3bb9aSPatrick McHardy return 0; 6584f3bb9aSPatrick McHardy return e->ip.proto; 66076f7839SJan Engelhardt } else if (par->family == NFPROTO_IPV6) { 6784f3bb9aSPatrick McHardy const struct ip6t_entry *e = par->entryinfo; 6884f3bb9aSPatrick McHardy 6984f3bb9aSPatrick McHardy if (e->ipv6.invflags & IP6T_INV_PROTO) 7084f3bb9aSPatrick McHardy return 0; 7184f3bb9aSPatrick McHardy return e->ipv6.proto; 7284f3bb9aSPatrick McHardy } else 7384f3bb9aSPatrick McHardy return 0; 7484f3bb9aSPatrick McHardy } 7584f3bb9aSPatrick McHardy 7624de58f4SPablo Neira Ayuso static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) 7784f3bb9aSPatrick McHardy { 7884f3bb9aSPatrick McHardy struct xt_ct_target_info *info = par->targinfo; 7984f3bb9aSPatrick McHardy struct nf_conntrack_tuple t; 8084f3bb9aSPatrick McHardy struct nf_conn_help *help; 8184f3bb9aSPatrick McHardy struct nf_conn *ct; 824a5a5c73SJan Engelhardt int ret = 0; 8384f3bb9aSPatrick McHardy u8 proto; 8484f3bb9aSPatrick McHardy 859bf04646SPablo Neira Ayuso if (info->flags & ~XT_CT_NOTRACK) 869bf04646SPablo Neira Ayuso return -EINVAL; 8784f3bb9aSPatrick McHardy 8884f3bb9aSPatrick McHardy if (info->flags & XT_CT_NOTRACK) { 895bfddbd4SEric Dumazet ct = nf_ct_untracked_get(); 9084f3bb9aSPatrick McHardy atomic_inc(&ct->ct_general.use); 9184f3bb9aSPatrick McHardy goto out; 9284f3bb9aSPatrick McHardy } 9384f3bb9aSPatrick McHardy 945d0aa2ccSPatrick McHardy #ifndef CONFIG_NF_CONNTRACK_ZONES 955d0aa2ccSPatrick McHardy if (info->zone) 965d0aa2ccSPatrick McHardy goto err1; 975d0aa2ccSPatrick McHardy #endif 985d0aa2ccSPatrick McHardy 994a5a5c73SJan Engelhardt ret = nf_ct_l3proto_try_module_get(par->family); 1004a5a5c73SJan Engelhardt if (ret < 0) 10184f3bb9aSPatrick McHardy goto err1; 10284f3bb9aSPatrick McHardy 10384f3bb9aSPatrick McHardy memset(&t, 0, sizeof(t)); 1045d0aa2ccSPatrick McHardy ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); 1054a5a5c73SJan Engelhardt ret = PTR_ERR(ct); 10684f3bb9aSPatrick McHardy if (IS_ERR(ct)) 10784f3bb9aSPatrick McHardy goto err2; 10884f3bb9aSPatrick McHardy 1094a5a5c73SJan Engelhardt ret = 0; 11084f3bb9aSPatrick McHardy if ((info->ct_events || info->exp_events) && 11184f3bb9aSPatrick McHardy !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, 11284f3bb9aSPatrick McHardy GFP_KERNEL)) 11384f3bb9aSPatrick McHardy goto err3; 11484f3bb9aSPatrick McHardy 1159bf04646SPablo Neira Ayuso if (info->helper[0]) { 1164a5a5c73SJan Engelhardt ret = -ENOENT; 11784f3bb9aSPatrick McHardy proto = xt_ct_find_proto(par); 118a7fed762SJan Engelhardt if (!proto) { 119a7fed762SJan Engelhardt pr_info("You must specify a L4 protocol, " 120a7fed762SJan Engelhardt "and not use inversions on it.\n"); 12184f3bb9aSPatrick McHardy goto err3; 122a7fed762SJan Engelhardt } 12384f3bb9aSPatrick McHardy 1244a5a5c73SJan Engelhardt ret = -ENOMEM; 12584f3bb9aSPatrick McHardy help = nf_ct_helper_ext_add(ct, GFP_KERNEL); 12684f3bb9aSPatrick McHardy if (help == NULL) 12784f3bb9aSPatrick McHardy goto err3; 12884f3bb9aSPatrick McHardy 1294a5a5c73SJan Engelhardt ret = -ENOENT; 13084f3bb9aSPatrick McHardy help->helper = nf_conntrack_helper_try_module_get(info->helper, 13184f3bb9aSPatrick McHardy par->family, 13284f3bb9aSPatrick McHardy proto); 133a7fed762SJan Engelhardt if (help->helper == NULL) { 134a7fed762SJan Engelhardt pr_info("No such helper \"%s\"\n", info->helper); 13584f3bb9aSPatrick McHardy goto err3; 13684f3bb9aSPatrick McHardy } 137a7fed762SJan Engelhardt } 13884f3bb9aSPatrick McHardy 13984f3bb9aSPatrick McHardy __set_bit(IPS_TEMPLATE_BIT, &ct->status); 14084f3bb9aSPatrick McHardy __set_bit(IPS_CONFIRMED_BIT, &ct->status); 14184f3bb9aSPatrick McHardy out: 14284f3bb9aSPatrick McHardy info->ct = ct; 143d6b00a53SJan Engelhardt return 0; 14484f3bb9aSPatrick McHardy 14584f3bb9aSPatrick McHardy err3: 14684f3bb9aSPatrick McHardy nf_conntrack_free(ct); 14784f3bb9aSPatrick McHardy err2: 14884f3bb9aSPatrick McHardy nf_ct_l3proto_module_put(par->family); 14984f3bb9aSPatrick McHardy err1: 1504a5a5c73SJan Engelhardt return ret; 15184f3bb9aSPatrick McHardy } 15284f3bb9aSPatrick McHardy 15324de58f4SPablo Neira Ayuso static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) 15424de58f4SPablo Neira Ayuso { 15524de58f4SPablo Neira Ayuso struct xt_ct_target_info_v1 *info = par->targinfo; 15624de58f4SPablo Neira Ayuso struct nf_conntrack_tuple t; 15724de58f4SPablo Neira Ayuso struct nf_conn_help *help; 15824de58f4SPablo Neira Ayuso struct nf_conn *ct; 15924de58f4SPablo Neira Ayuso int ret = 0; 16024de58f4SPablo Neira Ayuso u8 proto; 16124de58f4SPablo Neira Ayuso 16224de58f4SPablo Neira Ayuso if (info->flags & ~XT_CT_NOTRACK) 16324de58f4SPablo Neira Ayuso return -EINVAL; 16424de58f4SPablo Neira Ayuso 16524de58f4SPablo Neira Ayuso if (info->flags & XT_CT_NOTRACK) { 16624de58f4SPablo Neira Ayuso ct = nf_ct_untracked_get(); 16724de58f4SPablo Neira Ayuso atomic_inc(&ct->ct_general.use); 16824de58f4SPablo Neira Ayuso goto out; 16924de58f4SPablo Neira Ayuso } 17024de58f4SPablo Neira Ayuso 17124de58f4SPablo Neira Ayuso #ifndef CONFIG_NF_CONNTRACK_ZONES 17224de58f4SPablo Neira Ayuso if (info->zone) 17324de58f4SPablo Neira Ayuso goto err1; 17424de58f4SPablo Neira Ayuso #endif 17524de58f4SPablo Neira Ayuso 17624de58f4SPablo Neira Ayuso ret = nf_ct_l3proto_try_module_get(par->family); 17724de58f4SPablo Neira Ayuso if (ret < 0) 17824de58f4SPablo Neira Ayuso goto err1; 17924de58f4SPablo Neira Ayuso 18024de58f4SPablo Neira Ayuso memset(&t, 0, sizeof(t)); 18124de58f4SPablo Neira Ayuso ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); 18224de58f4SPablo Neira Ayuso ret = PTR_ERR(ct); 18324de58f4SPablo Neira Ayuso if (IS_ERR(ct)) 18424de58f4SPablo Neira Ayuso goto err2; 18524de58f4SPablo Neira Ayuso 18624de58f4SPablo Neira Ayuso ret = 0; 18724de58f4SPablo Neira Ayuso if ((info->ct_events || info->exp_events) && 18824de58f4SPablo Neira Ayuso !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, 18924de58f4SPablo Neira Ayuso GFP_KERNEL)) 19024de58f4SPablo Neira Ayuso goto err3; 19124de58f4SPablo Neira Ayuso 19224de58f4SPablo Neira Ayuso if (info->helper[0]) { 19324de58f4SPablo Neira Ayuso ret = -ENOENT; 19424de58f4SPablo Neira Ayuso proto = xt_ct_find_proto(par); 19524de58f4SPablo Neira Ayuso if (!proto) { 19624de58f4SPablo Neira Ayuso pr_info("You must specify a L4 protocol, " 19724de58f4SPablo Neira Ayuso "and not use inversions on it.\n"); 19824de58f4SPablo Neira Ayuso goto err3; 19924de58f4SPablo Neira Ayuso } 20024de58f4SPablo Neira Ayuso 20124de58f4SPablo Neira Ayuso ret = -ENOMEM; 20224de58f4SPablo Neira Ayuso help = nf_ct_helper_ext_add(ct, GFP_KERNEL); 20324de58f4SPablo Neira Ayuso if (help == NULL) 20424de58f4SPablo Neira Ayuso goto err3; 20524de58f4SPablo Neira Ayuso 20624de58f4SPablo Neira Ayuso ret = -ENOENT; 20724de58f4SPablo Neira Ayuso help->helper = nf_conntrack_helper_try_module_get(info->helper, 20824de58f4SPablo Neira Ayuso par->family, 20924de58f4SPablo Neira Ayuso proto); 21024de58f4SPablo Neira Ayuso if (help->helper == NULL) { 21124de58f4SPablo Neira Ayuso pr_info("No such helper \"%s\"\n", info->helper); 21224de58f4SPablo Neira Ayuso goto err3; 21324de58f4SPablo Neira Ayuso } 21424de58f4SPablo Neira Ayuso } 21524de58f4SPablo Neira Ayuso 21624de58f4SPablo Neira Ayuso #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 21724de58f4SPablo Neira Ayuso if (info->timeout) { 21824de58f4SPablo Neira Ayuso typeof(nf_ct_timeout_find_get_hook) timeout_find_get; 21924de58f4SPablo Neira Ayuso struct ctnl_timeout *timeout; 22024de58f4SPablo Neira Ayuso struct nf_conn_timeout *timeout_ext; 22124de58f4SPablo Neira Ayuso 2221ac0bf99SPablo Neira Ayuso rcu_read_lock(); 22324de58f4SPablo Neira Ayuso timeout_find_get = 22424de58f4SPablo Neira Ayuso rcu_dereference(nf_ct_timeout_find_get_hook); 22524de58f4SPablo Neira Ayuso 22624de58f4SPablo Neira Ayuso if (timeout_find_get) { 22724de58f4SPablo Neira Ayuso const struct ipt_entry *e = par->entryinfo; 228eeb4cb95SPablo Neira Ayuso struct nf_conntrack_l4proto *l4proto; 22924de58f4SPablo Neira Ayuso 23024de58f4SPablo Neira Ayuso if (e->ip.invflags & IPT_INV_PROTO) { 23124de58f4SPablo Neira Ayuso ret = -EINVAL; 23224de58f4SPablo Neira Ayuso pr_info("You cannot use inversion on " 23324de58f4SPablo Neira Ayuso "L4 protocol\n"); 2341ac0bf99SPablo Neira Ayuso goto err4; 23524de58f4SPablo Neira Ayuso } 23624de58f4SPablo Neira Ayuso timeout = timeout_find_get(info->timeout); 23724de58f4SPablo Neira Ayuso if (timeout == NULL) { 23824de58f4SPablo Neira Ayuso ret = -ENOENT; 23924de58f4SPablo Neira Ayuso pr_info("No such timeout policy \"%s\"\n", 24024de58f4SPablo Neira Ayuso info->timeout); 2411ac0bf99SPablo Neira Ayuso goto err4; 24224de58f4SPablo Neira Ayuso } 24324de58f4SPablo Neira Ayuso if (timeout->l3num != par->family) { 24424de58f4SPablo Neira Ayuso ret = -EINVAL; 24524de58f4SPablo Neira Ayuso pr_info("Timeout policy `%s' can only be " 24624de58f4SPablo Neira Ayuso "used by L3 protocol number %d\n", 24724de58f4SPablo Neira Ayuso info->timeout, timeout->l3num); 2481ac0bf99SPablo Neira Ayuso goto err4; 24924de58f4SPablo Neira Ayuso } 250eeb4cb95SPablo Neira Ayuso /* Make sure the timeout policy matches any existing 251eeb4cb95SPablo Neira Ayuso * protocol tracker, otherwise default to generic. 252eeb4cb95SPablo Neira Ayuso */ 253eeb4cb95SPablo Neira Ayuso l4proto = __nf_ct_l4proto_find(par->family, 254eeb4cb95SPablo Neira Ayuso e->ip.proto); 255eeb4cb95SPablo Neira Ayuso if (timeout->l4proto->l4proto != l4proto->l4proto) { 25624de58f4SPablo Neira Ayuso ret = -EINVAL; 25724de58f4SPablo Neira Ayuso pr_info("Timeout policy `%s' can only be " 25824de58f4SPablo Neira Ayuso "used by L4 protocol number %d\n", 259c1ebd7dfSPablo Neira Ayuso info->timeout, 260c1ebd7dfSPablo Neira Ayuso timeout->l4proto->l4proto); 2611ac0bf99SPablo Neira Ayuso goto err4; 26224de58f4SPablo Neira Ayuso } 26324de58f4SPablo Neira Ayuso timeout_ext = nf_ct_timeout_ext_add(ct, timeout, 26424de58f4SPablo Neira Ayuso GFP_KERNEL); 26524de58f4SPablo Neira Ayuso if (timeout_ext == NULL) { 26624de58f4SPablo Neira Ayuso ret = -ENOMEM; 2671ac0bf99SPablo Neira Ayuso goto err4; 26824de58f4SPablo Neira Ayuso } 26924de58f4SPablo Neira Ayuso } else { 27024de58f4SPablo Neira Ayuso ret = -ENOENT; 27124de58f4SPablo Neira Ayuso pr_info("Timeout policy base is empty\n"); 2721ac0bf99SPablo Neira Ayuso goto err4; 27324de58f4SPablo Neira Ayuso } 2741ac0bf99SPablo Neira Ayuso rcu_read_unlock(); 27524de58f4SPablo Neira Ayuso } 27624de58f4SPablo Neira Ayuso #endif 27724de58f4SPablo Neira Ayuso 27824de58f4SPablo Neira Ayuso __set_bit(IPS_TEMPLATE_BIT, &ct->status); 27924de58f4SPablo Neira Ayuso __set_bit(IPS_CONFIRMED_BIT, &ct->status); 28024de58f4SPablo Neira Ayuso out: 28124de58f4SPablo Neira Ayuso info->ct = ct; 28224de58f4SPablo Neira Ayuso return 0; 28324de58f4SPablo Neira Ayuso 2841ac0bf99SPablo Neira Ayuso err4: 2851ac0bf99SPablo Neira Ayuso rcu_read_unlock(); 28624de58f4SPablo Neira Ayuso err3: 28724de58f4SPablo Neira Ayuso nf_conntrack_free(ct); 28824de58f4SPablo Neira Ayuso err2: 28924de58f4SPablo Neira Ayuso nf_ct_l3proto_module_put(par->family); 29024de58f4SPablo Neira Ayuso err1: 29124de58f4SPablo Neira Ayuso return ret; 29224de58f4SPablo Neira Ayuso } 29324de58f4SPablo Neira Ayuso 29424de58f4SPablo Neira Ayuso static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) 29584f3bb9aSPatrick McHardy { 29684f3bb9aSPatrick McHardy struct xt_ct_target_info *info = par->targinfo; 29784f3bb9aSPatrick McHardy struct nf_conn *ct = info->ct; 29884f3bb9aSPatrick McHardy struct nf_conn_help *help; 29984f3bb9aSPatrick McHardy 3005bfddbd4SEric Dumazet if (!nf_ct_is_untracked(ct)) { 30184f3bb9aSPatrick McHardy help = nfct_help(ct); 30284f3bb9aSPatrick McHardy if (help) 30384f3bb9aSPatrick McHardy module_put(help->helper->me); 30484f3bb9aSPatrick McHardy 30584f3bb9aSPatrick McHardy nf_ct_l3proto_module_put(par->family); 30684f3bb9aSPatrick McHardy } 30784f3bb9aSPatrick McHardy nf_ct_put(info->ct); 30884f3bb9aSPatrick McHardy } 30984f3bb9aSPatrick McHardy 31024de58f4SPablo Neira Ayuso static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) 31124de58f4SPablo Neira Ayuso { 31224de58f4SPablo Neira Ayuso struct xt_ct_target_info_v1 *info = par->targinfo; 31324de58f4SPablo Neira Ayuso struct nf_conn *ct = info->ct; 31424de58f4SPablo Neira Ayuso struct nf_conn_help *help; 31524de58f4SPablo Neira Ayuso #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 31624de58f4SPablo Neira Ayuso struct nf_conn_timeout *timeout_ext; 31724de58f4SPablo Neira Ayuso typeof(nf_ct_timeout_put_hook) timeout_put; 31824de58f4SPablo Neira Ayuso #endif 31924de58f4SPablo Neira Ayuso if (!nf_ct_is_untracked(ct)) { 32024de58f4SPablo Neira Ayuso help = nfct_help(ct); 32124de58f4SPablo Neira Ayuso if (help) 32224de58f4SPablo Neira Ayuso module_put(help->helper->me); 32324de58f4SPablo Neira Ayuso 32424de58f4SPablo Neira Ayuso nf_ct_l3proto_module_put(par->family); 32524de58f4SPablo Neira Ayuso 32624de58f4SPablo Neira Ayuso #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 3271ac0bf99SPablo Neira Ayuso rcu_read_lock(); 32824de58f4SPablo Neira Ayuso timeout_put = rcu_dereference(nf_ct_timeout_put_hook); 32924de58f4SPablo Neira Ayuso 33024de58f4SPablo Neira Ayuso if (timeout_put) { 33124de58f4SPablo Neira Ayuso timeout_ext = nf_ct_timeout_find(ct); 33224de58f4SPablo Neira Ayuso if (timeout_ext) 33324de58f4SPablo Neira Ayuso timeout_put(timeout_ext->timeout); 33424de58f4SPablo Neira Ayuso } 3351ac0bf99SPablo Neira Ayuso rcu_read_unlock(); 33624de58f4SPablo Neira Ayuso #endif 33724de58f4SPablo Neira Ayuso } 33824de58f4SPablo Neira Ayuso nf_ct_put(info->ct); 33924de58f4SPablo Neira Ayuso } 34024de58f4SPablo Neira Ayuso 34124de58f4SPablo Neira Ayuso static struct xt_target xt_ct_tg_reg[] __read_mostly = { 34224de58f4SPablo Neira Ayuso { 34384f3bb9aSPatrick McHardy .name = "CT", 34484f3bb9aSPatrick McHardy .family = NFPROTO_UNSPEC, 3457d5f7ed8SJan Engelhardt .targetsize = sizeof(struct xt_ct_target_info), 34624de58f4SPablo Neira Ayuso .checkentry = xt_ct_tg_check_v0, 34724de58f4SPablo Neira Ayuso .destroy = xt_ct_tg_destroy_v0, 34824de58f4SPablo Neira Ayuso .target = xt_ct_target_v0, 34984f3bb9aSPatrick McHardy .table = "raw", 35084f3bb9aSPatrick McHardy .me = THIS_MODULE, 35124de58f4SPablo Neira Ayuso }, 35224de58f4SPablo Neira Ayuso { 35324de58f4SPablo Neira Ayuso .name = "CT", 35424de58f4SPablo Neira Ayuso .family = NFPROTO_UNSPEC, 35524de58f4SPablo Neira Ayuso .revision = 1, 35624de58f4SPablo Neira Ayuso .targetsize = sizeof(struct xt_ct_target_info_v1), 35724de58f4SPablo Neira Ayuso .checkentry = xt_ct_tg_check_v1, 35824de58f4SPablo Neira Ayuso .destroy = xt_ct_tg_destroy_v1, 35924de58f4SPablo Neira Ayuso .target = xt_ct_target_v1, 36024de58f4SPablo Neira Ayuso .table = "raw", 36124de58f4SPablo Neira Ayuso .me = THIS_MODULE, 36224de58f4SPablo Neira Ayuso }, 36384f3bb9aSPatrick McHardy }; 36484f3bb9aSPatrick McHardy 36584f3bb9aSPatrick McHardy static int __init xt_ct_tg_init(void) 36684f3bb9aSPatrick McHardy { 36724de58f4SPablo Neira Ayuso return xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg)); 36884f3bb9aSPatrick McHardy } 36984f3bb9aSPatrick McHardy 37084f3bb9aSPatrick McHardy static void __exit xt_ct_tg_exit(void) 37184f3bb9aSPatrick McHardy { 37224de58f4SPablo Neira Ayuso xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg)); 37384f3bb9aSPatrick McHardy } 37484f3bb9aSPatrick McHardy 37584f3bb9aSPatrick McHardy module_init(xt_ct_tg_init); 37684f3bb9aSPatrick McHardy module_exit(xt_ct_tg_exit); 37784f3bb9aSPatrick McHardy 37884f3bb9aSPatrick McHardy MODULE_LICENSE("GPL"); 37984f3bb9aSPatrick McHardy MODULE_DESCRIPTION("Xtables: connection tracking target"); 38084f3bb9aSPatrick McHardy MODULE_ALIAS("ipt_CT"); 38184f3bb9aSPatrick McHardy MODULE_ALIAS("ip6t_CT"); 382