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

[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
...@@ -56,37 +56,48 @@ static int try_eprt(const char *, size_t, u_int32_t [], char); ...@@ -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 int try_epsv_response(const char *, size_t, u_int32_t [], char);
static const struct ftp_search { static const struct ftp_search {
enum ip_conntrack_dir dir;
const char *pattern; const char *pattern;
size_t plen; size_t plen;
char skip; char skip;
char term; char term;
enum ip_ct_ftp_type ftptype; enum ip_ct_ftp_type ftptype;
int (*getnum)(const char *, size_t, u_int32_t[], char); 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', .pattern = "PORT",
IP_CT_FTP_PORT, .plen = sizeof("PORT") - 1,
try_rfc959, .skip = ' ',
.term = '\r',
.ftptype = IP_CT_FTP_PORT,
.getnum = 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_REPLY, {
"227 ", sizeof("227 ") - 1, '(', ')', .pattern = "227 ",
IP_CT_FTP_PASV, .plen = sizeof("227 ") - 1,
try_rfc959, .skip = '(',
}, .term = ')',
{ .ftptype = IP_CT_FTP_PASV,
IP_CT_DIR_ORIGINAL, .getnum = try_rfc959,
"EPRT", sizeof("EPRT") - 1, ' ', '\r', },
IP_CT_FTP_EPRT, {
try_eprt, .pattern = "229 ",
}, .plen = sizeof("229 ") - 1,
{ .skip = '(',
IP_CT_DIR_REPLY, .term = ')',
"229 ", sizeof("229 ") - 1, '(', ')', .ftptype = IP_CT_FTP_EPSV,
IP_CT_FTP_EPSV, .getnum = try_epsv_response,
try_epsv_response, },
}, },
}; };
...@@ -346,17 +357,15 @@ static int help(struct sk_buff **pskb, ...@@ -346,17 +357,15 @@ static int help(struct sk_buff **pskb,
array[2] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 8) & 0xFF; array[2] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 8) & 0xFF;
array[3] = ntohl(ct->tuplehash[dir].tuple.src.ip) & 0xFF; array[3] = ntohl(ct->tuplehash[dir].tuple.src.ip) & 0xFF;
for (i = 0; i < ARRAY_SIZE(search); i++) { for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
if (search[i].dir != dir) continue;
found = find_pattern(fb_ptr, (*pskb)->len - dataoff, found = find_pattern(fb_ptr, (*pskb)->len - dataoff,
search[i].pattern, search[dir][i].pattern,
search[i].plen, search[dir][i].plen,
search[i].skip, search[dir][i].skip,
search[i].term, search[dir][i].term,
&matchoff, &matchlen, &matchoff, &matchlen,
array, array,
search[i].getnum); search[dir][i].getnum);
if (found) break; if (found) break;
} }
if (found == -1) { if (found == -1) {
...@@ -366,7 +375,7 @@ static int help(struct sk_buff **pskb, ...@@ -366,7 +375,7 @@ static int help(struct sk_buff **pskb,
this case. */ this case. */
if (net_ratelimit()) if (net_ratelimit())
printk("conntrack_ftp: partial %s %u+%u\n", printk("conntrack_ftp: partial %s %u+%u\n",
search[i].pattern, search[dir][i].pattern,
ntohl(th->seq), datalen); ntohl(th->seq), datalen);
ret = NF_DROP; ret = NF_DROP;
goto out; goto out;
...@@ -426,7 +435,7 @@ static int help(struct sk_buff **pskb, ...@@ -426,7 +435,7 @@ static int help(struct sk_buff **pskb,
/* Now, NAT might want to mangle the packet, and register the /* Now, NAT might want to mangle the packet, and register the
* (possibly changed) expectation itself. */ * (possibly changed) expectation itself. */
if (ip_nat_ftp_hook) 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); matchoff, matchlen, exp, &seq);
else { else {
/* Can't expect this? Best to drop packet now. */ /* Can't expect this? Best to drop packet now. */
......
...@@ -67,37 +67,48 @@ static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *, ...@@ -67,37 +67,48 @@ static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
char); char);
static struct ftp_search { static struct ftp_search {
enum ip_conntrack_dir dir;
const char *pattern; const char *pattern;
size_t plen; size_t plen;
char skip; char skip;
char term; char term;
enum ip_ct_ftp_type ftptype; enum ip_ct_ftp_type ftptype;
int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char); 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', .pattern = "PORT",
IP_CT_FTP_PORT, .plen = sizeof("PORT") - 1,
try_rfc959, .skip = ' ',
.term = '\r',
.ftptype = IP_CT_FTP_PORT,
.getnum = 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_REPLY, {
"227 ", sizeof("227 ") - 1, '(', ')', .pattern = "227 ",
IP_CT_FTP_PASV, .plen = sizeof("227 ") - 1,
try_rfc959, .skip = '(',
}, .term = ')',
{ .ftptype = IP_CT_FTP_PASV,
IP_CT_DIR_ORIGINAL, .getnum = try_rfc959,
"EPRT", sizeof("EPRT") - 1, ' ', '\r', },
IP_CT_FTP_EPRT, {
try_eprt, .pattern = "229 ",
}, .plen = sizeof("229 ") - 1,
{ .skip = '(',
IP_CT_DIR_REPLY, .term = ')',
"229 ", sizeof("229 ") - 1, '(', ')', .ftptype = IP_CT_FTP_EPSV,
IP_CT_FTP_EPSV, .getnum = try_epsv_response,
try_epsv_response, },
}, },
}; };
...@@ -492,17 +503,15 @@ static int help(struct sk_buff **pskb, ...@@ -492,17 +503,15 @@ static int help(struct sk_buff **pskb,
memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all, memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
sizeof(cmd.u3.all)); sizeof(cmd.u3.all));
for (i = 0; i < ARRAY_SIZE(search); i++) { for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
if (search[i].dir != dir) continue;
found = find_pattern(fb_ptr, datalen, found = find_pattern(fb_ptr, datalen,
search[i].pattern, search[dir][i].pattern,
search[i].plen, search[dir][i].plen,
search[i].skip, search[dir][i].skip,
search[i].term, search[dir][i].term,
&matchoff, &matchlen, &matchoff, &matchlen,
&cmd, &cmd,
search[i].getnum); search[dir][i].getnum);
if (found) break; if (found) break;
} }
if (found == -1) { if (found == -1) {
...@@ -512,7 +521,7 @@ static int help(struct sk_buff **pskb, ...@@ -512,7 +521,7 @@ static int help(struct sk_buff **pskb,
this case. */ this case. */
if (net_ratelimit()) if (net_ratelimit())
printk("conntrack_ftp: partial %s %u+%u\n", printk("conntrack_ftp: partial %s %u+%u\n",
search[i].pattern, search[dir][i].pattern,
ntohl(th->seq), datalen); ntohl(th->seq), datalen);
ret = NF_DROP; ret = NF_DROP;
goto out; goto out;
...@@ -597,7 +606,7 @@ static int help(struct sk_buff **pskb, ...@@ -597,7 +606,7 @@ static int help(struct sk_buff **pskb,
/* Now, NAT might want to mangle the packet, and register the /* Now, NAT might want to mangle the packet, and register the
* (possibly changed) expectation itself. */ * (possibly changed) expectation itself. */
if (nf_nat_ftp_hook) 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); matchoff, matchlen, exp, &seq);
else { else {
/* Can't expect this? Best to drop packet now. */ /* Can't expect this? Best to drop packet now. */
......
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