Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 Aug 2018 17:42:06 +0200
From:      Andreas Longwitz <longwitz@incore.de>
To:        freebsd-net@freebsd.org
Subject:   Re: natd sends wrong sequence number when a retransmitted PASV packet comes in
Message-ID:  <5B6F03CE.8090105@incore.de>
In-Reply-To: <5B6B2725.9030306@incore.de>
References:  <5B6B2725.9030306@incore.de>

next in thread | previous in thread | raw e-mail | index | archive | help
At first I have to correct a typo in my former post: "must have sequence
number 465" (not 455).

In the meantime I have build a complete test environment to debug this
problem and I am rather sure, there is a bug in natd.

For every ftp connection natd creates a little table (struct
ack_data_record ack) of size N_LINK_TCP_DATA to save the information
about altered length for TCP packets. This table is filled in function
AddSeq() in a circular list each time when "227 Entering Passive Mode"
is sent out to the ftp client. In TcpAliasOut there is a lookup in this
table by calling GetDelteSeqOut() to get the correct delta value to
create the value of seq for the outgoing packet. GetDeltaSeqOut searches
the table in a sequential manner and looks for the biggest ack_old value
not bigger than the actual seq and returns delta from the matching table
line. As long as all ack_old in the table are different, there is no
problem with this procedure. But if for what reason ever one of the "227
Entering" packets must be retransmitted, then we have two entries in the
table with the same value of ack_old and maybe different delta because
of port numbers with different decimal lenght. In this case if the delta
information of the original "227 Entering" packet is placed in the table
before the information of the replayed "227 Entering" packet the
function GetDeltaSeqOut() returns for the next outgoing packet the wrong
old delta value and the connection to the ftp client breaks.

I think the function GetDeltaSeqOut() should also treat the table in a
circular manner, so we can search the table from newer to older entries.
Especially if there are identical ack_new values in the table, we can
take the delta value of the last entry. The following patch solved the
problem for me:

--- alias_db.c.orig     2015-07-03 16:40:03.000000000 +0200
+++ alias_db.c  2018-08-10 23:31:09.242105000 +0200
@@ -2031,14 +2035,18 @@
 packet size was altered is searched.
 */

-       int i;
+       int i, j;
        int delta, seq_diff_min;

        delta = 0;
        seq_diff_min = -1;
-       for (i = 0; i < N_LINK_TCP_DATA; i++) {
+       i = lnk->data.tcp->state.index;
+       for (j = 0; j < N_LINK_TCP_DATA; j++) {
                struct ack_data_record x;

+               if (i == 0)
+                       i = N_LINK_TCP_DATA;
+               i--;
                x = lnk->data.tcp->ack[i];
                if (x.active == 1) {
                        int seq_diff;

Please can somebody review this patch. I am not sure if the same
modification should also be done in the function GetDeltaAckIn().

-- 
Andreas Longwitz




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5B6F03CE.8090105>