mirror of
https://github.com/torvalds/linux.git
synced 2024-09-22 07:53:05 +00:00
[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: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
695ecea329
commit
7d8c501817
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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 *,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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. */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user