netfilter: xtables: add CT target
Add a new target for the raw table, which can be used to specify conntrack parameters for specific connections, f.i. the conntrack helper. The target attaches a "template" connection tracking entry to the skb, which is used by the conntrack core when initializing a new conntrack. Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Родитель
b2a15a604d
Коммит
84f3bb9ae9
|
@ -6,6 +6,7 @@ header-y += nfnetlink_queue.h
|
|||
header-y += xt_CLASSIFY.h
|
||||
header-y += xt_CONNMARK.h
|
||||
header-y += xt_CONNSECMARK.h
|
||||
header-y += xt_CT.h
|
||||
header-y += xt_DSCP.h
|
||||
header-y += xt_LED.h
|
||||
header-y += xt_MARK.h
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef _XT_CT_H
|
||||
#define _XT_CT_H
|
||||
|
||||
#define XT_CT_NOTRACK 0x1
|
||||
|
||||
struct xt_ct_target_info {
|
||||
u_int16_t flags;
|
||||
u_int16_t __unused;
|
||||
u_int32_t ct_events;
|
||||
u_int32_t exp_events;
|
||||
char helper[16];
|
||||
|
||||
/* Used internally by the kernel */
|
||||
struct nf_conn *ct __attribute__((aligned(8)));
|
||||
};
|
||||
|
||||
#endif /* _XT_CT_H */
|
|
@ -42,6 +42,9 @@ struct nf_conntrack_helper {
|
|||
extern struct nf_conntrack_helper *
|
||||
__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum);
|
||||
|
||||
extern struct nf_conntrack_helper *
|
||||
nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum);
|
||||
|
||||
extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
|
||||
extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
|
||||
|
||||
|
|
|
@ -341,6 +341,18 @@ config NETFILTER_XT_TARGET_CONNSECMARK
|
|||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NETFILTER_XT_TARGET_CT
|
||||
tristate '"CT" target support'
|
||||
depends on NF_CONNTRACK
|
||||
depends on IP_NF_RAW || IP6_NF_RAW
|
||||
depends on NETFILTER_ADVANCED
|
||||
help
|
||||
This options adds a `CT' target, which allows to specify initial
|
||||
connection tracking parameters like events to be delivered and
|
||||
the helper to be used.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NETFILTER_XT_TARGET_DSCP
|
||||
tristate '"DSCP" and "TOS" target support'
|
||||
depends on IP_NF_MANGLE || IP6_NF_MANGLE
|
||||
|
|
|
@ -44,6 +44,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
|
|||
obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
|
||||
|
|
|
@ -83,6 +83,25 @@ __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find);
|
||||
|
||||
struct nf_conntrack_helper *
|
||||
nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum)
|
||||
{
|
||||
struct nf_conntrack_helper *h;
|
||||
|
||||
h = __nf_conntrack_helper_find(name, l3num, protonum);
|
||||
#ifdef CONFIG_MODULES
|
||||
if (h == NULL) {
|
||||
if (request_module("nfct-helper-%s", name) == 0)
|
||||
h = __nf_conntrack_helper_find(name, l3num, protonum);
|
||||
}
|
||||
#endif
|
||||
if (h != NULL && !try_module_get(h->me))
|
||||
h = NULL;
|
||||
|
||||
return h;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get);
|
||||
|
||||
struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
|
||||
{
|
||||
struct nf_conn_help *help;
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/selinux.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/netfilter/xt_CT.h>
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_conntrack_helper.h>
|
||||
#include <net/netfilter/nf_conntrack_ecache.h>
|
||||
|
||||
static unsigned int xt_ct_target(struct sk_buff *skb,
|
||||
const struct xt_target_param *par)
|
||||
{
|
||||
const struct xt_ct_target_info *info = par->targinfo;
|
||||
struct nf_conn *ct = info->ct;
|
||||
|
||||
/* Previously seen (loopback)? Ignore. */
|
||||
if (skb->nfct != NULL)
|
||||
return XT_CONTINUE;
|
||||
|
||||
atomic_inc(&ct->ct_general.use);
|
||||
skb->nfct = &ct->ct_general;
|
||||
skb->nfctinfo = IP_CT_NEW;
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static u8 xt_ct_find_proto(const struct xt_tgchk_param *par)
|
||||
{
|
||||
if (par->family == AF_INET) {
|
||||
const struct ipt_entry *e = par->entryinfo;
|
||||
|
||||
if (e->ip.invflags & IPT_INV_PROTO)
|
||||
return 0;
|
||||
return e->ip.proto;
|
||||
} else if (par->family == AF_INET6) {
|
||||
const struct ip6t_entry *e = par->entryinfo;
|
||||
|
||||
if (e->ipv6.invflags & IP6T_INV_PROTO)
|
||||
return 0;
|
||||
return e->ipv6.proto;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool xt_ct_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
struct xt_ct_target_info *info = par->targinfo;
|
||||
struct nf_conntrack_tuple t;
|
||||
struct nf_conn_help *help;
|
||||
struct nf_conn *ct;
|
||||
u8 proto;
|
||||
|
||||
if (info->flags & ~XT_CT_NOTRACK)
|
||||
return false;
|
||||
|
||||
if (info->flags & XT_CT_NOTRACK) {
|
||||
ct = &nf_conntrack_untracked;
|
||||
atomic_inc(&ct->ct_general.use);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nf_ct_l3proto_try_module_get(par->family) < 0)
|
||||
goto err1;
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
ct = nf_conntrack_alloc(par->net, &t, &t, GFP_KERNEL);
|
||||
if (IS_ERR(ct))
|
||||
goto err2;
|
||||
|
||||
if ((info->ct_events || info->exp_events) &&
|
||||
!nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
|
||||
GFP_KERNEL))
|
||||
goto err3;
|
||||
|
||||
if (info->helper[0]) {
|
||||
proto = xt_ct_find_proto(par);
|
||||
if (!proto)
|
||||
goto err3;
|
||||
|
||||
help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
|
||||
if (help == NULL)
|
||||
goto err3;
|
||||
|
||||
help->helper = nf_conntrack_helper_try_module_get(info->helper,
|
||||
par->family,
|
||||
proto);
|
||||
if (help->helper == NULL)
|
||||
goto err3;
|
||||
}
|
||||
|
||||
__set_bit(IPS_TEMPLATE_BIT, &ct->status);
|
||||
__set_bit(IPS_CONFIRMED_BIT, &ct->status);
|
||||
out:
|
||||
info->ct = ct;
|
||||
return true;
|
||||
|
||||
err3:
|
||||
nf_conntrack_free(ct);
|
||||
err2:
|
||||
nf_ct_l3proto_module_put(par->family);
|
||||
err1:
|
||||
return false;
|
||||
}
|
||||
|
||||
static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par)
|
||||
{
|
||||
struct xt_ct_target_info *info = par->targinfo;
|
||||
struct nf_conn *ct = info->ct;
|
||||
struct nf_conn_help *help;
|
||||
|
||||
if (ct != &nf_conntrack_untracked) {
|
||||
help = nfct_help(ct);
|
||||
if (help)
|
||||
module_put(help->helper->me);
|
||||
|
||||
nf_ct_l3proto_module_put(par->family);
|
||||
}
|
||||
nf_ct_put(info->ct);
|
||||
}
|
||||
|
||||
static struct xt_target xt_ct_tg __read_mostly = {
|
||||
.name = "CT",
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.targetsize = XT_ALIGN(sizeof(struct xt_ct_target_info)),
|
||||
.checkentry = xt_ct_tg_check,
|
||||
.destroy = xt_ct_tg_destroy,
|
||||
.target = xt_ct_target,
|
||||
.table = "raw",
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init xt_ct_tg_init(void)
|
||||
{
|
||||
return xt_register_target(&xt_ct_tg);
|
||||
}
|
||||
|
||||
static void __exit xt_ct_tg_exit(void)
|
||||
{
|
||||
xt_unregister_target(&xt_ct_tg);
|
||||
}
|
||||
|
||||
module_init(xt_ct_tg_init);
|
||||
module_exit(xt_ct_tg_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Xtables: connection tracking target");
|
||||
MODULE_ALIAS("ipt_CT");
|
||||
MODULE_ALIAS("ip6t_CT");
|
Загрузка…
Ссылка в новой задаче