--- zzzz-none-000/linux-2.4.17/net/ipv4/netfilter/ip_conntrack_ftp.c 2001-10-30 23:08:12.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-11-24 13:22:08.000000000 +0000 @@ -1,9 +1,9 @@ /* FTP extension for IP connection tracking. */ +#include #include #include #include #include -#include #include #include @@ -15,7 +15,7 @@ #define MAX_PORTS 8 static int ports[MAX_PORTS]; -static int ports_c; +static int ports_c = 0; #ifdef MODULE_PARM MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); #endif @@ -232,68 +232,59 @@ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { - /* tcplen not negative guaranteed by ip_conntrack_tcp.c */ + /* datalen not negative guaranteed by ip_conntrack_tcp.c */ struct tcphdr *tcph = (void *)iph + iph->ihl * 4; const char *data = (const char *)tcph + tcph->doff * 4; - unsigned int tcplen = len - iph->ihl * 4; - unsigned int datalen = tcplen - tcph->doff * 4; + unsigned int datalen = len - (iph->ihl + tcph->doff) * 4; u_int32_t old_seq_aft_nl; int old_seq_aft_nl_set; u_int32_t array[6] = { 0 }; int dir = CTINFO2DIR(ctinfo); unsigned int matchlen, matchoff; - struct ip_conntrack_tuple t, mask; - struct ip_ct_ftp *info = &ct->help.ct_ftp_info; + struct ip_ct_ftp_master *ct_ftp_info = &ct->help.ct_ftp_info; + struct ip_conntrack_expect expect, *exp = &expect; + struct ip_ct_ftp_expect *exp_ftp_info = &exp->help.exp_ftp_info; + unsigned int i; int found = 0; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) { + //printk("Until there's been traffic both ways, don't look in packets.\n"); DEBUGP("ftp: Conntrackinfo = %u\n", ctinfo); return NF_ACCEPT; } - /* Not whole TCP header? */ - if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) { - DEBUGP("ftp: tcplen = %u\n", (unsigned)tcplen); - return NF_ACCEPT; - } - - /* Checksum invalid? Ignore. */ - /* FIXME: Source route IP option packets --RR */ - if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, - csum_partial((char *)tcph, tcplen, 0))) { - DEBUGP("ftp_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", - tcph, tcplen, NIPQUAD(iph->saddr), - NIPQUAD(iph->daddr)); - return NF_ACCEPT; - } - LOCK_BH(&ip_ftp_lock); - old_seq_aft_nl_set = info->seq_aft_nl_set[dir]; - old_seq_aft_nl = info->seq_aft_nl[dir]; + old_seq_aft_nl_set = ct_ftp_info->seq_aft_nl_set[dir]; + old_seq_aft_nl = ct_ftp_info->seq_aft_nl[dir]; - DEBUGP("conntrack_ftp: datalen %u\n", datalen); + //printk("conntrack_ftp: datalen %u\n", datalen); + //printk("conntrack_ftp: len %u\n", len); + if ((datalen > 0) && (data[datalen-1] == '\n')) { - DEBUGP("conntrack_ftp: datalen %u ends in \\n\n", datalen); + //printk("conntrack_ftp: datalen %u ends in \\n\n", datalen); if (!old_seq_aft_nl_set || after(ntohl(tcph->seq) + datalen, old_seq_aft_nl)) { - DEBUGP("conntrack_ftp: updating nl to %u\n", - ntohl(tcph->seq) + datalen); - info->seq_aft_nl[dir] = ntohl(tcph->seq) + datalen; - info->seq_aft_nl_set[dir] = 1; + //printk("conntrack_ftp: updating nl to %u = (SEQ (%u)+ DLEN (%u)\n", + //ntohl(tcph->seq) + datalen, ntohl(tcph->seq), datalen); + ct_ftp_info->seq_aft_nl[dir] = + ntohl(tcph->seq) + datalen; + ct_ftp_info->seq_aft_nl_set[dir] = 1; } } UNLOCK_BH(&ip_ftp_lock); if(!old_seq_aft_nl_set || (ntohl(tcph->seq) != old_seq_aft_nl)) { - DEBUGP("ip_conntrack_ftp_help: wrong seq pos %s(%u)\n", - old_seq_aft_nl_set ? "":"(UNSET) ", old_seq_aft_nl); + //printk("ip_conntrack_ftp_help: wrong seq pos %s(old seq aft nl %u) tcp seq %u\n", old_seq_aft_nl_set ? "":"(UNSET) ", old_seq_aft_nl, ntohl(tcph->seq)); return NF_ACCEPT; + //ct_ftp_info->seq_aft_nl[dir] = ntohl(tcph->seq) + datalen; + //ct_ftp_info->seq_aft_nl_set[dir] = 1; } + //UNLOCK_BH(&ip_ftp_lock); /* Initialize IP array to expected address (it's not mentioned in EPSV responses) */ array[0] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 24) & 0xFF; @@ -319,6 +310,9 @@ connection tracking, not packet filtering. However, it is neccessary for accurate tracking in this case. */ + //printk("conntrack_ftp: partial %s %u+%u\n", + // search[i].pattern, ntohl(tcph->seq), datalen); + if (net_ratelimit()) printk("conntrack_ftp: partial %s %u+%u\n", search[i].pattern, @@ -330,16 +324,17 @@ DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n", (int)matchlen, data + matchoff, matchlen, ntohl(tcph->seq) + matchoff); + + memset(&expect, 0, sizeof(expect)); /* Update the ftp info */ LOCK_BH(&ip_ftp_lock); if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]) == ct->tuplehash[dir].tuple.src.ip) { - info->is_ftp = 21; - info->seq = ntohl(tcph->seq) + matchoff; - info->len = matchlen; - info->ftptype = search[i].ftptype; - info->port = array[4] << 8 | array[5]; + exp->seq = ntohl(tcph->seq) + matchoff; + exp_ftp_info->len = matchlen; + exp_ftp_info->ftptype = search[i].ftptype; + exp_ftp_info->port = array[4] << 8 | array[5]; } else { /* Enrico Scholz's passive FTP to partially RNAT'd ftp server: it really wants us to connect to a @@ -356,18 +351,21 @@ if (!loose) goto out; } - t = ((struct ip_conntrack_tuple) + exp->tuple = ((struct ip_conntrack_tuple) { { ct->tuplehash[!dir].tuple.src.ip, { 0 } }, { htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]), { htons(array[4] << 8 | array[5]) }, IPPROTO_TCP }}); - mask = ((struct ip_conntrack_tuple) + exp->mask = ((struct ip_conntrack_tuple) { { 0xFFFFFFFF, { 0 } }, { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }}); + + exp->expectfn = NULL; + /* Ignore failure; should only happen with NAT */ - ip_conntrack_expect_related(ct, &t, &mask, NULL); + ip_conntrack_expect_related(ct, &expect); out: UNLOCK_BH(&ip_ftp_lock); @@ -375,12 +373,13 @@ } static struct ip_conntrack_helper ftp[MAX_PORTS]; +static char ftp_names[MAX_PORTS][10]; /* Not __exit: called from init() */ static void fini(void) { int i; - for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { + for (i = 0; i < ports_c; i++) { DEBUGP("ip_ct_ftp: unregistering helper for port %d\n", ports[i]); ip_conntrack_helper_unregister(&ftp[i]); @@ -390,9 +389,10 @@ static int __init init(void) { int i, ret; + char *tmpname; if (ports[0] == 0) - ports[0] = 21; + ports[0] = FTP_PORT; for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { memset(&ftp[i], 0, sizeof(struct ip_conntrack_helper)); @@ -400,7 +400,19 @@ ftp[i].tuple.dst.protonum = IPPROTO_TCP; ftp[i].mask.src.u.tcp.port = 0xFFFF; ftp[i].mask.dst.protonum = 0xFFFF; + ftp[i].max_expected = 1; + ftp[i].timeout = 0; + ftp[i].flags = IP_CT_HELPER_F_REUSE_EXPECT; + ftp[i].me = ip_conntrack_ftp; ftp[i].help = help; + + tmpname = &ftp_names[i][0]; + if (ports[i] == FTP_PORT) + sprintf(tmpname, "ftp"); + else + sprintf(tmpname, "ftp-%d", ports[i]); + ftp[i].name = tmpname; + DEBUGP("ip_ct_ftp: registering helper for port %d\n", ports[i]); ret = ip_conntrack_helper_register(&ftp[i]); @@ -414,10 +426,10 @@ return 0; } - +#ifdef CONFIG_IP_NF_NAT_NEEDED EXPORT_SYMBOL(ip_ftp_lock); -EXPORT_SYMBOL(ip_conntrack_ftp); -MODULE_LICENSE("GPL"); +#endif +MODULE_LICENSE("GPL"); module_init(init); module_exit(fini);