Commit b86c0e64 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: ecache: prepare for event notifier merge



This prepares for merge for ct and exp notifier structs.

The 'fcn' member is renamed to something unique.
Second, the register/unregister api is simplified.  There is only
one implementation so there is no need to do any error checking.

Replace the EBUSY logic with WARN_ON_ONCE.  This allows to remove
error unwinding.

The exp notifier register/unregister function is removed in
a followup patch.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent b3afdc17
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -73,13 +73,12 @@ struct nf_ct_event {
};

struct nf_ct_event_notifier {
	int (*fcn)(unsigned int events, const struct nf_ct_event *item);
	int (*ct_event)(unsigned int events, const struct nf_ct_event *item);
};

int nf_conntrack_register_notifier(struct net *net,
				   struct nf_ct_event_notifier *nb);
void nf_conntrack_unregister_notifier(struct net *net,
				      struct nf_ct_event_notifier *nb);
void nf_conntrack_register_notifier(struct net *net,
				   const struct nf_ct_event_notifier *nb);
void nf_conntrack_unregister_notifier(struct net *net);

void nf_ct_deliver_cached_events(struct nf_conn *ct);
int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
@@ -159,7 +158,7 @@ struct nf_exp_event {
};

struct nf_exp_event_notifier {
	int (*fcn)(unsigned int events, struct nf_exp_event *item);
	int (*exp_event)(unsigned int events, struct nf_exp_event *item);
};

int nf_ct_expect_register_notifier(struct net *net,
+6 −20
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ static int __nf_conntrack_eventmask_report(struct nf_conntrack_ecache *e,
		return 0;
	}

	ret = notify->fcn(events | missed, item);
	ret = notify->ct_event(events | missed, item);
	rcu_read_unlock();

	if (likely(ret >= 0 && missed == 0))
@@ -258,43 +258,29 @@ void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
			.portid	= portid,
			.report = report
		};
		notify->fcn(1 << event, &item);
		notify->exp_event(1 << event, &item);
	}
out_unlock:
	rcu_read_unlock();
}

int nf_conntrack_register_notifier(struct net *net,
				   struct nf_ct_event_notifier *new)
void nf_conntrack_register_notifier(struct net *net,
				    const struct nf_ct_event_notifier *new)
{
	int ret;
	struct nf_ct_event_notifier *notify;

	mutex_lock(&nf_ct_ecache_mutex);
	notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb,
					   lockdep_is_held(&nf_ct_ecache_mutex));
	if (notify != NULL) {
		ret = -EBUSY;
		goto out_unlock;
	}
	WARN_ON_ONCE(notify);
	rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new);
	ret = 0;

out_unlock:
	mutex_unlock(&nf_ct_ecache_mutex);
	return ret;
}
EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier);

void nf_conntrack_unregister_notifier(struct net *net,
				      struct nf_ct_event_notifier *new)
void nf_conntrack_unregister_notifier(struct net *net)
{
	struct nf_ct_event_notifier *notify;

	mutex_lock(&nf_ct_ecache_mutex);
	notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb,
					   lockdep_is_held(&nf_ct_ecache_mutex));
	BUG_ON(notify != new);
	RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL);
	mutex_unlock(&nf_ct_ecache_mutex);
	/* synchronize_rcu() is called from ctnetlink_exit. */
+6 −16
Original line number Diff line number Diff line
@@ -3755,11 +3755,11 @@ static int ctnetlink_stat_exp_cpu(struct sk_buff *skb,

#ifdef CONFIG_NF_CONNTRACK_EVENTS
static struct nf_ct_event_notifier ctnl_notifier = {
	.fcn = ctnetlink_conntrack_event,
	.ct_event = ctnetlink_conntrack_event,
};

static struct nf_exp_event_notifier ctnl_notifier_exp = {
	.fcn = ctnetlink_expect_event,
	.exp_event = ctnetlink_expect_event,
};
#endif

@@ -3854,33 +3854,23 @@ static int __net_init ctnetlink_net_init(struct net *net)
#ifdef CONFIG_NF_CONNTRACK_EVENTS
	int ret;

	ret = nf_conntrack_register_notifier(net, &ctnl_notifier);
	if (ret < 0) {
		pr_err("ctnetlink_init: cannot register notifier.\n");
		goto err_out;
	}
	nf_conntrack_register_notifier(net, &ctnl_notifier);

	ret = nf_ct_expect_register_notifier(net, &ctnl_notifier_exp);
	if (ret < 0) {
		pr_err("ctnetlink_init: cannot expect register notifier.\n");
		goto err_unreg_notifier;
		nf_conntrack_unregister_notifier(net);
		return ret;
	}
#endif
	return 0;

#ifdef CONFIG_NF_CONNTRACK_EVENTS
err_unreg_notifier:
	nf_conntrack_unregister_notifier(net, &ctnl_notifier);
err_out:
	return ret;
#endif
}

static void ctnetlink_net_exit(struct net *net)
{
#ifdef CONFIG_NF_CONNTRACK_EVENTS
	nf_ct_expect_unregister_notifier(net, &ctnl_notifier_exp);
	nf_conntrack_unregister_notifier(net, &ctnl_notifier);
	nf_conntrack_unregister_notifier(net);
#endif
}