Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ enum ip_conntrack_events {

enum ip_conntrack_expect_events {
	IPEXP_NEW,		/* new expectation */
	IPEXP_DESTROY,		/* destroyed expectation */
};

/* expectation flags */
+7 −1
Original line number Diff line number Diff line
@@ -82,7 +82,13 @@ struct nf_conntrack_expect *
nf_ct_find_expectation(struct net *net, u16 zone,
		       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_unexpect_related(struct nf_conntrack_expect *exp);
void nf_ct_remove_userspace_expectations(void);
+4 −2
Original line number Diff line number Diff line
@@ -41,7 +41,8 @@ static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
static HLIST_HEAD(nf_ct_userspace_expect_list);

/* 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 net *net = nf_ct_exp_net(exp);
@@ -55,11 +56,12 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
	if (!(exp->flags & NF_CT_EXPECT_USERSPACE))
		master_help->expecting[exp->class]--;

	nf_ct_expect_event_report(IPEXP_DESTROY, exp, pid, report);
	nf_ct_expect_put(exp);

	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)
{
+21 −9
Original line number Diff line number Diff line
@@ -1632,17 +1632,20 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
	struct nlmsghdr *nlh;
	struct nfgenmsg *nfmsg;
	struct sk_buff *skb;
	unsigned int type;
	unsigned int type, group;
	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;
		flags = NLM_F_CREATE|NLM_F_EXCL;
		group = NFNLGRP_CONNTRACK_EXP_NEW;
	} else
		return 0;

	if (!item->report &&
	    !nfnetlink_has_listeners(net, NFNLGRP_CONNTRACK_EXP_NEW))
	if (!item->report && !nfnetlink_has_listeners(net, group))
		return 0;

	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
@@ -1665,8 +1668,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
	rcu_read_unlock();

	nlmsg_end(skb, nlh);
	nfnetlink_send(skb, net, item->pid, NFNLGRP_CONNTRACK_EXP_NEW,
		       item->report, GFP_ATOMIC);
	nfnetlink_send(skb, net, item->pid, group, item->report, GFP_ATOMIC);
	return 0;

nla_put_failure:
@@ -1849,7 +1851,13 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
		}

		/* 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.
		 * after this line usage count == 0 */
		nf_ct_expect_put(exp);
@@ -1866,7 +1874,9 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
				m_help = nfct_help(exp->master);
				if (!strcmp(m_help->helper->name, name) &&
				    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);
				}
			}
@@ -1880,7 +1890,9 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
						  &net->ct.expect_hash[i],
						  hnode) {
				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);
				}
			}