Commit ebbf41df authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by Patrick McHardy

netfilter: ctnetlink: add expectation deletion events

This patch allows to listen to events that inform about
expectations destroyed.
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent 43f974cd
...@@ -98,6 +98,7 @@ enum ip_conntrack_events { ...@@ -98,6 +98,7 @@ enum ip_conntrack_events {
enum ip_conntrack_expect_events { enum ip_conntrack_expect_events {
IPEXP_NEW, /* new expectation */ IPEXP_NEW, /* new expectation */
IPEXP_DESTROY, /* destroyed expectation */
}; };
/* expectation flags */ /* expectation flags */
......
...@@ -82,7 +82,13 @@ struct nf_conntrack_expect * ...@@ -82,7 +82,13 @@ struct nf_conntrack_expect *
nf_ct_find_expectation(struct net *net, u16 zone, nf_ct_find_expectation(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple); const struct nf_conntrack_tuple *tuple);
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp); void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
u32 pid, int report);
static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
{
nf_ct_unlink_expect_report(exp, 0, 0);
}
void nf_ct_remove_expectations(struct nf_conn *ct); void nf_ct_remove_expectations(struct nf_conn *ct);
void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
void nf_ct_remove_userspace_expectations(void); void nf_ct_remove_userspace_expectations(void);
......
...@@ -41,7 +41,8 @@ static struct kmem_cache *nf_ct_expect_cachep __read_mostly; ...@@ -41,7 +41,8 @@ static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
static HLIST_HEAD(nf_ct_userspace_expect_list); static HLIST_HEAD(nf_ct_userspace_expect_list);
/* nf_conntrack_expect helper functions */ /* nf_conntrack_expect helper functions */
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
u32 pid, int report)
{ {
struct nf_conn_help *master_help = nfct_help(exp->master); struct nf_conn_help *master_help = nfct_help(exp->master);
struct net *net = nf_ct_exp_net(exp); struct net *net = nf_ct_exp_net(exp);
...@@ -55,11 +56,12 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) ...@@ -55,11 +56,12 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
if (!(exp->flags & NF_CT_EXPECT_USERSPACE)) if (!(exp->flags & NF_CT_EXPECT_USERSPACE))
master_help->expecting[exp->class]--; master_help->expecting[exp->class]--;
nf_ct_expect_event_report(IPEXP_DESTROY, exp, pid, report);
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
NF_CT_STAT_INC(net, expect_delete); NF_CT_STAT_INC(net, expect_delete);
} }
EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); EXPORT_SYMBOL_GPL(nf_ct_unlink_expect_report);
static void nf_ct_expectation_timed_out(unsigned long ul_expect) static void nf_ct_expectation_timed_out(unsigned long ul_expect)
{ {
......
...@@ -1632,17 +1632,20 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) ...@@ -1632,17 +1632,20 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct nfgenmsg *nfmsg; struct nfgenmsg *nfmsg;
struct sk_buff *skb; struct sk_buff *skb;
unsigned int type; unsigned int type, group;
int flags = 0; int flags = 0;
if (events & (1 << IPEXP_NEW)) { if (events & (1 << IPEXP_DESTROY)) {
type = IPCTNL_MSG_EXP_DELETE;
group = NFNLGRP_CONNTRACK_EXP_DESTROY;
} else if (events & (1 << IPEXP_NEW)) {
type = IPCTNL_MSG_EXP_NEW; type = IPCTNL_MSG_EXP_NEW;
flags = NLM_F_CREATE|NLM_F_EXCL; flags = NLM_F_CREATE|NLM_F_EXCL;
group = NFNLGRP_CONNTRACK_EXP_NEW;
} else } else
return 0; return 0;
if (!item->report && if (!item->report && !nfnetlink_has_listeners(net, group))
!nfnetlink_has_listeners(net, NFNLGRP_CONNTRACK_EXP_NEW))
return 0; return 0;
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
...@@ -1665,8 +1668,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) ...@@ -1665,8 +1668,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
rcu_read_unlock(); rcu_read_unlock();
nlmsg_end(skb, nlh); nlmsg_end(skb, nlh);
nfnetlink_send(skb, net, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, nfnetlink_send(skb, net, item->pid, group, item->report, GFP_ATOMIC);
item->report, GFP_ATOMIC);
return 0; return 0;
nla_put_failure: nla_put_failure:
...@@ -1849,7 +1851,13 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, ...@@ -1849,7 +1851,13 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
} }
/* after list removal, usage count == 1 */ /* after list removal, usage count == 1 */
nf_ct_unexpect_related(exp); spin_lock_bh(&nf_conntrack_lock);
if (del_timer(&exp->timeout)) {
nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).pid,
nlmsg_report(nlh));
nf_ct_expect_put(exp);
}
spin_unlock_bh(&nf_conntrack_lock);
/* have to put what we 'get' above. /* have to put what we 'get' above.
* after this line usage count == 0 */ * after this line usage count == 0 */
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
...@@ -1866,7 +1874,9 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, ...@@ -1866,7 +1874,9 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
m_help = nfct_help(exp->master); m_help = nfct_help(exp->master);
if (!strcmp(m_help->helper->name, name) && if (!strcmp(m_help->helper->name, name) &&
del_timer(&exp->timeout)) { del_timer(&exp->timeout)) {
nf_ct_unlink_expect(exp); nf_ct_unlink_expect_report(exp,
NETLINK_CB(skb).pid,
nlmsg_report(nlh));
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
} }
} }
...@@ -1880,7 +1890,9 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, ...@@ -1880,7 +1890,9 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
&net->ct.expect_hash[i], &net->ct.expect_hash[i],
hnode) { hnode) {
if (del_timer(&exp->timeout)) { if (del_timer(&exp->timeout)) {
nf_ct_unlink_expect(exp); nf_ct_unlink_expect_report(exp,
NETLINK_CB(skb).pid,
nlmsg_report(nlh));
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment