netfilter: ctnetlink: support selective event delivery
Add two masks for conntrack end expectation events to struct nf_conntrack_ecache and use them to filter events. Their default value is "all events" when the event sysctl is on and "no events" when it is off. A following patch will add specific initializations. Expectation events depend on the ecache struct of their master conntrack. Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Родитель
858b313300
Коммит
0cebe4b416
|
@ -74,6 +74,24 @@ enum ip_conntrack_status {
|
||||||
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
|
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Connection tracking event types */
|
||||||
|
enum ip_conntrack_events {
|
||||||
|
IPCT_NEW, /* new conntrack */
|
||||||
|
IPCT_RELATED, /* related conntrack */
|
||||||
|
IPCT_DESTROY, /* destroyed conntrack */
|
||||||
|
IPCT_REPLY, /* connection has seen two-way traffic */
|
||||||
|
IPCT_ASSURED, /* connection status has changed to assured */
|
||||||
|
IPCT_PROTOINFO, /* protocol information has changed */
|
||||||
|
IPCT_HELPER, /* new helper has been set */
|
||||||
|
IPCT_MARK, /* new mark has been set */
|
||||||
|
IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */
|
||||||
|
IPCT_SECMARK, /* new security mark has been set */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ip_conntrack_expect_events {
|
||||||
|
IPEXP_NEW, /* new expectation */
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
struct ip_conntrack_stat {
|
struct ip_conntrack_stat {
|
||||||
unsigned int searched;
|
unsigned int searched;
|
||||||
|
|
|
@ -12,27 +12,11 @@
|
||||||
#include <linux/netfilter/nf_conntrack_tuple_common.h>
|
#include <linux/netfilter/nf_conntrack_tuple_common.h>
|
||||||
#include <net/netfilter/nf_conntrack_extend.h>
|
#include <net/netfilter/nf_conntrack_extend.h>
|
||||||
|
|
||||||
/* Connection tracking event types */
|
|
||||||
enum ip_conntrack_events {
|
|
||||||
IPCT_NEW, /* new conntrack */
|
|
||||||
IPCT_RELATED, /* related conntrack */
|
|
||||||
IPCT_DESTROY, /* destroyed conntrack */
|
|
||||||
IPCT_REPLY, /* connection has seen two-way traffic */
|
|
||||||
IPCT_ASSURED, /* connection status has changed to assured */
|
|
||||||
IPCT_PROTOINFO, /* protocol information has changed */
|
|
||||||
IPCT_HELPER, /* new helper has been set */
|
|
||||||
IPCT_MARK, /* new mark has been set */
|
|
||||||
IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */
|
|
||||||
IPCT_SECMARK, /* new security mark has been set */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ip_conntrack_expect_events {
|
|
||||||
IPEXP_NEW, /* new expectation */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nf_conntrack_ecache {
|
struct nf_conntrack_ecache {
|
||||||
unsigned long cache; /* bitops want long */
|
unsigned long cache; /* bitops want long */
|
||||||
unsigned long missed; /* missed events */
|
unsigned long missed; /* missed events */
|
||||||
|
u16 ctmask; /* bitmask of ct events to be delivered */
|
||||||
|
u16 expmask; /* bitmask of expect events to be delivered */
|
||||||
u32 pid; /* netlink pid of destroyer */
|
u32 pid; /* netlink pid of destroyer */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,14 +27,24 @@ nf_ct_ecache_find(const struct nf_conn *ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct nf_conntrack_ecache *
|
static inline struct nf_conntrack_ecache *
|
||||||
nf_ct_ecache_ext_add(struct nf_conn *ct, gfp_t gfp)
|
nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
|
||||||
{
|
{
|
||||||
struct net *net = nf_ct_net(ct);
|
struct net *net = nf_ct_net(ct);
|
||||||
|
struct nf_conntrack_ecache *e;
|
||||||
|
|
||||||
if (!net->ct.sysctl_events)
|
if (!ctmask && !expmask && net->ct.sysctl_events) {
|
||||||
|
ctmask = ~0;
|
||||||
|
expmask = ~0;
|
||||||
|
}
|
||||||
|
if (!ctmask && !expmask)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
|
e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
|
||||||
|
if (e) {
|
||||||
|
e->ctmask = ctmask;
|
||||||
|
e->expmask = expmask;
|
||||||
|
}
|
||||||
|
return e;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||||
|
@ -83,6 +77,9 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
|
||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!(e->ctmask & (1 << event)))
|
||||||
|
return;
|
||||||
|
|
||||||
set_bit(event, &e->cache);
|
set_bit(event, &e->cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +90,6 @@ nf_conntrack_eventmask_report(unsigned int eventmask,
|
||||||
int report)
|
int report)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct net *net = nf_ct_net(ct);
|
|
||||||
struct nf_ct_event_notifier *notify;
|
struct nf_ct_event_notifier *notify;
|
||||||
struct nf_conntrack_ecache *e;
|
struct nf_conntrack_ecache *e;
|
||||||
|
|
||||||
|
@ -102,9 +98,6 @@ nf_conntrack_eventmask_report(unsigned int eventmask,
|
||||||
if (notify == NULL)
|
if (notify == NULL)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
if (!net->ct.sysctl_events)
|
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
e = nf_ct_ecache_find(ct);
|
e = nf_ct_ecache_find(ct);
|
||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@ -118,6 +111,9 @@ nf_conntrack_eventmask_report(unsigned int eventmask,
|
||||||
/* This is a resent of a destroy event? If so, skip missed */
|
/* This is a resent of a destroy event? If so, skip missed */
|
||||||
unsigned long missed = e->pid ? 0 : e->missed;
|
unsigned long missed = e->pid ? 0 : e->missed;
|
||||||
|
|
||||||
|
if (!((eventmask | missed) & e->ctmask))
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
ret = notify->fcn(eventmask | missed, &item);
|
ret = notify->fcn(eventmask | missed, &item);
|
||||||
if (unlikely(ret < 0 || missed)) {
|
if (unlikely(ret < 0 || missed)) {
|
||||||
spin_lock_bh(&ct->lock);
|
spin_lock_bh(&ct->lock);
|
||||||
|
@ -173,18 +169,19 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
|
||||||
u32 pid,
|
u32 pid,
|
||||||
int report)
|
int report)
|
||||||
{
|
{
|
||||||
struct net *net = nf_ct_exp_net(exp);
|
|
||||||
struct nf_exp_event_notifier *notify;
|
struct nf_exp_event_notifier *notify;
|
||||||
|
struct nf_conntrack_ecache *e;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
notify = rcu_dereference(nf_expect_event_cb);
|
notify = rcu_dereference(nf_expect_event_cb);
|
||||||
if (notify == NULL)
|
if (notify == NULL)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
if (!net->ct.sysctl_events)
|
e = nf_ct_ecache_find(exp->master);
|
||||||
|
if (e == NULL)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
{
|
if (e->expmask & (1 << event)) {
|
||||||
struct nf_exp_event item = {
|
struct nf_exp_event item = {
|
||||||
.exp = exp,
|
.exp = exp,
|
||||||
.pid = pid,
|
.pid = pid,
|
||||||
|
|
|
@ -648,7 +648,7 @@ init_conntrack(struct net *net,
|
||||||
}
|
}
|
||||||
|
|
||||||
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
|
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
|
||||||
nf_ct_ecache_ext_add(ct, GFP_ATOMIC);
|
nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
|
||||||
|
|
||||||
spin_lock_bh(&nf_conntrack_lock);
|
spin_lock_bh(&nf_conntrack_lock);
|
||||||
exp = nf_ct_find_expectation(net, tuple);
|
exp = nf_ct_find_expectation(net, tuple);
|
||||||
|
|
|
@ -1281,7 +1281,7 @@ ctnetlink_create_conntrack(struct net *net,
|
||||||
}
|
}
|
||||||
|
|
||||||
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
|
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
|
||||||
nf_ct_ecache_ext_add(ct, GFP_ATOMIC);
|
nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
|
||||||
|
|
||||||
#if defined(CONFIG_NF_CONNTRACK_MARK)
|
#if defined(CONFIG_NF_CONNTRACK_MARK)
|
||||||
if (cda[CTA_MARK])
|
if (cda[CTA_MARK])
|
||||||
|
|
Загрузка…
Ссылка в новой задаче