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

Commit 82de0be6 authored by Gao Feng's avatar Gao Feng Committed by Pablo Neira Ayuso
Browse files

netfilter: Add helper array register/unregister functions



Add nf_ct_helper_init(), nf_conntrack_helpers_register() and
nf_conntrack_helpers_unregister() functions to avoid repetitive
opencoded initialization in helpers.

This patch keeps an id parameter for nf_ct_helper_init() not to break
helper matching by name that has been inconsistently exposed to
userspace through ports, eg. ftp-2121, and through an incremental id,
eg. tftp-1.

Signed-off-by: default avatarGao Feng <fgao@ikuai8.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 590025a2
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -58,10 +58,25 @@ struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name,
struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name,
							       u16 l3num,
							       u8 protonum);
void nf_ct_helper_init(struct nf_conntrack_helper *helper,
		       u16 l3num, u16 protonum, const char *name,
		       u16 default_port, u16 spec_port, u32 id,
		       const struct nf_conntrack_expect_policy *exp_pol,
		       u32 expect_class_max, u32 data_len,
		       int (*help)(struct sk_buff *skb, unsigned int protoff,
				   struct nf_conn *ct,
				   enum ip_conntrack_info ctinfo),
		       int (*from_nlattr)(struct nlattr *attr,
					  struct nf_conn *ct),
		       struct module *module);

int nf_conntrack_helper_register(struct nf_conntrack_helper *);
void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);

int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int);
void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *,
				     unsigned int);

struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct,
					  struct nf_conntrack_helper *helper,
					  gfp_t gfp);
+18 −40
Original line number Diff line number Diff line
@@ -572,7 +572,7 @@ static int nf_ct_ftp_from_nlattr(struct nlattr *attr, struct nf_conn *ct)
	return 0;
}

static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly;
static struct nf_conntrack_helper ftp[MAX_PORTS * 2] __read_mostly;

static const struct nf_conntrack_expect_policy ftp_exp_policy = {
	.max_expected	= 1,
@@ -582,24 +582,13 @@ static const struct nf_conntrack_expect_policy ftp_exp_policy = {
/* don't make this __exit, since it's called from __init ! */
static void nf_conntrack_ftp_fini(void)
{
	int i, j;
	for (i = 0; i < ports_c; i++) {
		for (j = 0; j < 2; j++) {
			if (ftp[i][j].me == NULL)
				continue;

			pr_debug("unregistering helper for pf: %d port: %d\n",
				 ftp[i][j].tuple.src.l3num, ports[i]);
			nf_conntrack_helper_unregister(&ftp[i][j]);
		}
	}

	nf_conntrack_helpers_unregister(ftp, ports_c * 2);
	kfree(ftp_buffer);
}

static int __init nf_conntrack_ftp_init(void)
{
	int i, j = -1, ret = 0;
	int i, ret = 0;

	ftp_buffer = kmalloc(65536, GFP_KERNEL);
	if (!ftp_buffer)
@@ -611,33 +600,22 @@ static int __init nf_conntrack_ftp_init(void)
	/* FIXME should be configurable whether IPv4 and IPv6 FTP connections
		 are tracked or not - YK */
	for (i = 0; i < ports_c; i++) {
		ftp[i][0].tuple.src.l3num = PF_INET;
		ftp[i][1].tuple.src.l3num = PF_INET6;
		for (j = 0; j < 2; j++) {
			ftp[i][j].data_len = sizeof(struct nf_ct_ftp_master);
			ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
			ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
			ftp[i][j].expect_policy = &ftp_exp_policy;
			ftp[i][j].me = THIS_MODULE;
			ftp[i][j].help = help;
			ftp[i][j].from_nlattr = nf_ct_ftp_from_nlattr;
			if (ports[i] == FTP_PORT)
				sprintf(ftp[i][j].name, "ftp");
			else
				sprintf(ftp[i][j].name, "ftp-%d", ports[i]);

			pr_debug("registering helper for pf: %d port: %d\n",
				 ftp[i][j].tuple.src.l3num, ports[i]);
			ret = nf_conntrack_helper_register(&ftp[i][j]);
			if (ret) {
				pr_err("failed to register helper for pf: %d port: %d\n",
				       ftp[i][j].tuple.src.l3num, ports[i]);
				ports_c = i;
				nf_conntrack_ftp_fini();
		nf_ct_helper_init(&ftp[2 * i], AF_INET, IPPROTO_TCP, "ftp",
				  FTP_PORT, ports[i], ports[i], &ftp_exp_policy,
				  0, sizeof(struct nf_ct_ftp_master), help,
				  nf_ct_ftp_from_nlattr, THIS_MODULE);
		nf_ct_helper_init(&ftp[2 * i + 1], AF_INET6, IPPROTO_TCP, "ftp",
				  FTP_PORT, ports[i], ports[i], &ftp_exp_policy,
				  0, sizeof(struct nf_ct_ftp_master), help,
				  nf_ct_ftp_from_nlattr, THIS_MODULE);
	}

	ret = nf_conntrack_helpers_register(ftp, ports_c * 2);
	if (ret < 0) {
		pr_err("failed to register helpers\n");
		kfree(ftp_buffer);
		return ret;
	}
		}
	}

	return 0;
}
+57 −0
Original line number Diff line number Diff line
@@ -465,6 +465,63 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
}
EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);

void nf_ct_helper_init(struct nf_conntrack_helper *helper,
		       u16 l3num, u16 protonum, const char *name,
		       u16 default_port, u16 spec_port, u32 id,
		       const struct nf_conntrack_expect_policy *exp_pol,
		       u32 expect_class_max, u32 data_len,
		       int (*help)(struct sk_buff *skb, unsigned int protoff,
				   struct nf_conn *ct,
				   enum ip_conntrack_info ctinfo),
		       int (*from_nlattr)(struct nlattr *attr,
					  struct nf_conn *ct),
		       struct module *module)
{
	helper->tuple.src.l3num = l3num;
	helper->tuple.dst.protonum = protonum;
	helper->tuple.src.u.all = htons(spec_port);
	helper->expect_policy = exp_pol;
	helper->expect_class_max = expect_class_max;
	helper->data_len = data_len;
	helper->help = help;
	helper->from_nlattr = from_nlattr;
	helper->me = module;

	if (spec_port == default_port)
		snprintf(helper->name, sizeof(helper->name), "%s", name);
	else
		snprintf(helper->name, sizeof(helper->name), "%s-%u", name, id);
}
EXPORT_SYMBOL_GPL(nf_ct_helper_init);

int nf_conntrack_helpers_register(struct nf_conntrack_helper *helper,
				  unsigned int n)
{
	unsigned int i;
	int err = 0;

	for (i = 0; i < n; i++) {
		err = nf_conntrack_helper_register(&helper[i]);
		if (err < 0)
			goto err;
	}

	return err;
err:
	if (i > 0)
		nf_conntrack_helpers_unregister(helper, i);
	return err;
}
EXPORT_SYMBOL_GPL(nf_conntrack_helpers_register);

void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *helper,
				unsigned int n)
{
	while (n-- > 0)
		nf_conntrack_helper_unregister(&helper[n]);
}
EXPORT_SYMBOL_GPL(nf_conntrack_helpers_unregister);

static struct nf_ct_ext_type helper_extend __read_mostly = {
	.len	= sizeof(struct nf_conn_help),
	.align	= __alignof__(struct nf_conn_help),
+12 −24
Original line number Diff line number Diff line
@@ -255,27 +255,18 @@ static int __init nf_conntrack_irc_init(void)
		ports[ports_c++] = IRC_PORT;

	for (i = 0; i < ports_c; i++) {
		irc[i].tuple.src.l3num = AF_INET;
		irc[i].tuple.src.u.tcp.port = htons(ports[i]);
		irc[i].tuple.dst.protonum = IPPROTO_TCP;
		irc[i].expect_policy = &irc_exp_policy;
		irc[i].me = THIS_MODULE;
		irc[i].help = help;

		if (ports[i] == IRC_PORT)
			sprintf(irc[i].name, "irc");
		else
			sprintf(irc[i].name, "irc-%u", i);

		ret = nf_conntrack_helper_register(&irc[i]);
		nf_ct_helper_init(&irc[i], AF_INET, IPPROTO_TCP, "irc",
				  IRC_PORT, ports[i], i, &irc_exp_policy,
				  0, 0, help, NULL, THIS_MODULE);
	}

	ret = nf_conntrack_helpers_register(&irc[0], ports_c);
	if (ret) {
			pr_err("failed to register helper for pf: %u port: %u\n",
			       irc[i].tuple.src.l3num, ports[i]);
			ports_c = i;
			nf_conntrack_irc_fini();
		pr_err("failed to register helpers\n");
		kfree(irc_buffer);
		return ret;
	}
	}

	return 0;
}

@@ -283,10 +274,7 @@ static int __init nf_conntrack_irc_init(void)
 * it is needed by the init function */
static void nf_conntrack_irc_fini(void)
{
	int i;

	for (i = 0; i < ports_c; i++)
		nf_conntrack_helper_unregister(&irc[i]);
	nf_conntrack_helpers_unregister(irc, ports_c);
	kfree(irc_buffer);
}

+20 −37
Original line number Diff line number Diff line
@@ -166,7 +166,7 @@ static int help(struct sk_buff *skb,
	return ret;
}

static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly;
static struct nf_conntrack_helper sane[MAX_PORTS * 2] __read_mostly;

static const struct nf_conntrack_expect_policy sane_exp_policy = {
	.max_expected	= 1,
@@ -176,22 +176,13 @@ static const struct nf_conntrack_expect_policy sane_exp_policy = {
/* don't make this __exit, since it's called from __init ! */
static void nf_conntrack_sane_fini(void)
{
	int i, j;

	for (i = 0; i < ports_c; i++) {
		for (j = 0; j < 2; j++) {
			pr_debug("unregistering helper for pf: %d port: %d\n",
				 sane[i][j].tuple.src.l3num, ports[i]);
			nf_conntrack_helper_unregister(&sane[i][j]);
		}
	}

	nf_conntrack_helpers_unregister(sane, ports_c * 2);
	kfree(sane_buffer);
}

static int __init nf_conntrack_sane_init(void)
{
	int i, j = -1, ret = 0;
	int i, ret = 0;

	sane_buffer = kmalloc(65536, GFP_KERNEL);
	if (!sane_buffer)
@@ -203,31 +194,23 @@ static int __init nf_conntrack_sane_init(void)
	/* FIXME should be configurable whether IPv4 and IPv6 connections
		 are tracked or not - YK */
	for (i = 0; i < ports_c; i++) {
		sane[i][0].tuple.src.l3num = PF_INET;
		sane[i][1].tuple.src.l3num = PF_INET6;
		for (j = 0; j < 2; j++) {
			sane[i][j].data_len = sizeof(struct nf_ct_sane_master);
			sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
			sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
			sane[i][j].expect_policy = &sane_exp_policy;
			sane[i][j].me = THIS_MODULE;
			sane[i][j].help = help;
			if (ports[i] == SANE_PORT)
				sprintf(sane[i][j].name, "sane");
			else
				sprintf(sane[i][j].name, "sane-%d", ports[i]);

			pr_debug("registering helper for pf: %d port: %d\n",
				 sane[i][j].tuple.src.l3num, ports[i]);
			ret = nf_conntrack_helper_register(&sane[i][j]);
			if (ret) {
				pr_err("failed to register helper for pf: %d port: %d\n",
				       sane[i][j].tuple.src.l3num, ports[i]);
				ports_c = i;
				nf_conntrack_sane_fini();
				return ret;
			}
		nf_ct_helper_init(&sane[2 * i], AF_INET, IPPROTO_TCP, "sane",
				  SANE_PORT, ports[i], ports[i],
				  &sane_exp_policy, 0,
				  sizeof(struct nf_ct_sane_master), help, NULL,
				  THIS_MODULE);
		nf_ct_helper_init(&sane[2 * i + 1], AF_INET6, IPPROTO_TCP, "sane",
				  SANE_PORT, ports[i], ports[i],
				  &sane_exp_policy, 0,
				  sizeof(struct nf_ct_sane_master), help, NULL,
				  THIS_MODULE);
	}

	ret = nf_conntrack_helpers_register(sane, ports_c * 2);
	if (ret < 0) {
		pr_err("failed to register helpers\n");
		kfree(sane_buffer);
		return ret;
	}

	return 0;
Loading