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

Commit 7d8c5018 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[NETFILTER]: FTP helper: search optimization



Instead of skipping search entries for the wrong direction simply index
them by direction.

Based on patch by Pablo Neira <pablo@netfilter.org>

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 695ecea3
Loading
Loading
Loading
Loading
+43 −34
Original line number Diff line number Diff line
@@ -56,37 +56,48 @@ static int try_eprt(const char *, size_t, u_int32_t [], char);
static int try_epsv_response(const char *, size_t, u_int32_t [], char);

static const struct ftp_search {
	enum ip_conntrack_dir dir;
	const char *pattern;
	size_t plen;
	char skip;
	char term;
	enum ip_ct_ftp_type ftptype;
	int (*getnum)(const char *, size_t, u_int32_t[], char);
} search[] = {
} search[IP_CT_DIR_MAX][2] = {
	[IP_CT_DIR_ORIGINAL] = {
		{
		IP_CT_DIR_ORIGINAL,
		"PORT",	sizeof("PORT") - 1, ' ', '\r',
		IP_CT_FTP_PORT,
		try_rfc959,
			.pattern	=  "PORT",
			.plen		= sizeof("PORT") - 1,
			.skip		= ' ',
			.term		= '\r',
			.ftptype	= IP_CT_FTP_PORT,
			.getnum		= try_rfc959,
		},
		{
		IP_CT_DIR_REPLY,
		"227 ",	sizeof("227 ") - 1, '(', ')',
		IP_CT_FTP_PASV,
		try_rfc959,
			.pattern	= "EPRT",
			.plen		= sizeof("EPRT") - 1,
			.skip		= ' ',
			.term		= '\r',
			.ftptype	= IP_CT_FTP_EPRT,
			.getnum		= try_eprt,
		},
	},
	[IP_CT_DIR_REPLY] = {
		{
		IP_CT_DIR_ORIGINAL,
		"EPRT", sizeof("EPRT") - 1, ' ', '\r',
		IP_CT_FTP_EPRT,
		try_eprt,
			.pattern	= "227 ",
			.plen		= sizeof("227 ") - 1,
			.skip		= '(',
			.term		= ')',
			.ftptype	= IP_CT_FTP_PASV,
			.getnum		= try_rfc959,
		},
		{
		IP_CT_DIR_REPLY,
		"229 ", sizeof("229 ") - 1, '(', ')',
		IP_CT_FTP_EPSV,
		try_epsv_response,
			.pattern	= "229 ",
			.plen		= sizeof("229 ") - 1,
			.skip		= '(',
			.term		= ')',
			.ftptype	= IP_CT_FTP_EPSV,
			.getnum		= try_epsv_response,
		},
	},
};

@@ -346,17 +357,15 @@ static int help(struct sk_buff **pskb,
	array[2] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 8) & 0xFF;
	array[3] = ntohl(ct->tuplehash[dir].tuple.src.ip) & 0xFF;

	for (i = 0; i < ARRAY_SIZE(search); i++) {
		if (search[i].dir != dir) continue;

	for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
		found = find_pattern(fb_ptr, (*pskb)->len - dataoff,
				     search[i].pattern,
				     search[i].plen,
				     search[i].skip,
				     search[i].term,
				     search[dir][i].pattern,
				     search[dir][i].plen,
				     search[dir][i].skip,
				     search[dir][i].term,
				     &matchoff, &matchlen,
				     array,
				     search[i].getnum);
				     search[dir][i].getnum);
		if (found) break;
	}
	if (found == -1) {
@@ -366,7 +375,7 @@ static int help(struct sk_buff **pskb,
		   this case. */
		if (net_ratelimit())
			printk("conntrack_ftp: partial %s %u+%u\n",
			       search[i].pattern,
			       search[dir][i].pattern,
			       ntohl(th->seq), datalen);
		ret = NF_DROP;
		goto out;
@@ -426,7 +435,7 @@ static int help(struct sk_buff **pskb,
	/* Now, NAT might want to mangle the packet, and register the
	 * (possibly changed) expectation itself. */
	if (ip_nat_ftp_hook)
		ret = ip_nat_ftp_hook(pskb, ctinfo, search[i].ftptype,
		ret = ip_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
				      matchoff, matchlen, exp, &seq);
	else {
		/* Can't expect this?  Best to drop packet now. */
+43 −34
Original line number Diff line number Diff line
@@ -67,37 +67,48 @@ static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
			     char);

static struct ftp_search {
	enum ip_conntrack_dir dir;
	const char *pattern;
	size_t plen;
	char skip;
	char term;
	enum ip_ct_ftp_type ftptype;
	int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char);
} search[] = {
} search[IP_CT_DIR_MAX][2] = {
	[IP_CT_DIR_ORIGINAL] = {
		{
		IP_CT_DIR_ORIGINAL,
		"PORT", sizeof("PORT") - 1, ' ', '\r',
		IP_CT_FTP_PORT,
		try_rfc959,
			.pattern	= "PORT",
			.plen		= sizeof("PORT") - 1,
			.skip		= ' ',
			.term		= '\r',
			.ftptype	= IP_CT_FTP_PORT,
			.getnum		= try_rfc959,
		},
		{
		IP_CT_DIR_REPLY,
		"227 ", sizeof("227 ") - 1, '(', ')',
		IP_CT_FTP_PASV,
		try_rfc959,
			.pattern	= "EPRT",
			.plen		= sizeof("EPRT") - 1,
			.skip		= ' ',
			.term		= '\r',
			.ftptype	= IP_CT_FTP_EPRT,
			.getnum		= try_eprt,
		},
	},
	[IP_CT_DIR_REPLY] = {
		{
		IP_CT_DIR_ORIGINAL,
		"EPRT", sizeof("EPRT") - 1, ' ', '\r',
		IP_CT_FTP_EPRT,
		try_eprt,
			.pattern	= "227 ",
			.plen		= sizeof("227 ") - 1,
			.skip		= '(',
			.term		= ')',
			.ftptype	= IP_CT_FTP_PASV,
			.getnum		= try_rfc959,
		},
		{
		IP_CT_DIR_REPLY,
		"229 ", sizeof("229 ") - 1, '(', ')',
		IP_CT_FTP_EPSV,
		try_epsv_response,
			.pattern	= "229 ",
			.plen		= sizeof("229 ") - 1,
			.skip		= '(',
			.term		= ')',
			.ftptype	= IP_CT_FTP_EPSV,
			.getnum		= try_epsv_response,
		},
	},
};

@@ -492,17 +503,15 @@ static int help(struct sk_buff **pskb,
	memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
	       sizeof(cmd.u3.all));

	for (i = 0; i < ARRAY_SIZE(search); i++) {
		if (search[i].dir != dir) continue;

	for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
		found = find_pattern(fb_ptr, datalen,
				     search[i].pattern,
				     search[i].plen,
				     search[i].skip,
				     search[i].term,
				     search[dir][i].pattern,
				     search[dir][i].plen,
				     search[dir][i].skip,
				     search[dir][i].term,
				     &matchoff, &matchlen,
				     &cmd,
				     search[i].getnum);
				     search[dir][i].getnum);
		if (found) break;
	}
	if (found == -1) {
@@ -512,7 +521,7 @@ static int help(struct sk_buff **pskb,
		   this case. */
		if (net_ratelimit())
			printk("conntrack_ftp: partial %s %u+%u\n",
			       search[i].pattern,
			       search[dir][i].pattern,
			       ntohl(th->seq), datalen);
		ret = NF_DROP;
		goto out;
@@ -597,7 +606,7 @@ static int help(struct sk_buff **pskb,
	/* Now, NAT might want to mangle the packet, and register the
	 * (possibly changed) expectation itself. */
	if (nf_nat_ftp_hook)
		ret = nf_nat_ftp_hook(pskb, ctinfo, search[i].ftptype,
		ret = nf_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
				      matchoff, matchlen, exp, &seq);
	else {
		/* Can't expect this?  Best to drop packet now. */