Thanks for the multiple seq_skew changes David. Its easy enough to support although I wonder if it is standard and the added usefulness seems minimal. comments inline
On Thu, Dec 20, 2018 at 5:33 AM David Marchand <david.march...@redhat.com> wrote: > The ftp alg deals with packets in two ways for the command connection: > either they are inspected and can be mangled when nat is enabled > (CT_FTP_CTL_INTEREST) or they just go through without being modified > (CT_FTP_CTL_OTHER). > > For CT_FTP_CTL_INTEREST packets, we must both adjust the packet tcp seq > number by the connection current offset, then prepare for the next > packets by setting an accumulated offset in the ct object. > > The tests are updated so that ftp+NAT checks send multiple commands in a > single tcp command connection: wget is not able to do this, so switch to > lftp. > > Signed-off-by: David Marchand <david.march...@redhat.com> > --- > Vagrantfile | 9 ++++++--- > Vagrantfile-FreeBSD | 2 +- > lib/conntrack.c | 52 > ++++++++++++++++++++++++++----------------------- > tests/system-traffic.at | 11 ++++++++++- > 4 files changed, 45 insertions(+), 29 deletions(-) > > diff --git a/Vagrantfile b/Vagrantfile > index 0192f66..fbd772a 100644 > --- a/Vagrantfile > +++ b/Vagrantfile > @@ -12,7 +12,8 @@ dnf -y install autoconf automake openssl-devel libtool \ > python-twisted python-zope-interface \ > desktop-file-utils groff graphviz rpmdevtools nc curl \ > wget python-six pyftpdlib checkpolicy selinux-policy-devel > \ > - libcap-ng-devel kernel-devel-`uname -r` ethtool > python-tftpy > + libcap-ng-devel kernel-devel-`uname -r` ethtool > python-tftpy \ > + lftp > echo "search extra update built-in" >/etc/depmod.d/search_path.conf > SCRIPT > > @@ -28,7 +29,8 @@ aptitude -y install -R \ > wget python-six ethtool \ > libcap-ng-dev libssl-dev python-dev openssl \ > python-pyftpdlib python-flake8 python-tftpy \ > - linux-headers-`uname -r` > + linux-headers-`uname -r` \ > + lftp > SCRIPT > > $bootstrap_centos = <<SCRIPT > @@ -37,7 +39,8 @@ yum -y install autoconf automake openssl-devel libtool \ > python-twisted-core python-zope-interface \ > desktop-file-utils groff graphviz rpmdevtools nc curl \ > wget python-six pyftpdlib checkpolicy selinux-policy-devel > \ > - libcap-ng-devel kernel-devel-`uname -r` ethtool net-tools > + libcap-ng-devel kernel-devel-`uname -r` ethtool net-tools \ > + lftp > SCRIPT > > $configure_ovs = <<SCRIPT > diff --git a/Vagrantfile-FreeBSD b/Vagrantfile-FreeBSD > index 8f00abe..52599ee 100644 > --- a/Vagrantfile-FreeBSD > +++ b/Vagrantfile-FreeBSD > @@ -12,7 +12,7 @@ Vagrant.require_version ">=1.7.0" > $bootstrap_freebsd = <<SCRIPT > sed -e 's/\#DEFAULT_ALWAYS_YES = false/DEFAULT_ALWAYS_YES = true/g' -e > 's/\#ASSUME_ALWAYS_YES = false/ASSUME_ALWAYS_YES = true/g' > /usr/local/etc/pkg.conf > /tmp/pkg.conf > mv -f /tmp/pkg.conf /usr/local/etc/pkg.conf > -pkg install automake libtool wget python py27-six gmake > +pkg install automake libtool wget python py27-six gmake lftp > SCRIPT > > $configure_ovs = <<SCRIPT > diff --git a/lib/conntrack.c b/lib/conntrack.c > index 6f6021a..2e4141a 100644 > --- a/lib/conntrack.c > +++ b/lib/conntrack.c > @@ -3214,30 +3214,34 @@ handle_ftp_ctl(struct conntrack *ct, const struct > conn_lookup_ctx *ctx, > pkt->md.ct_state |= CS_TRACKED | CS_INVALID; > return; > } else if (rc == CT_FTP_CTL_INTEREST) { > - uint16_t ip_len; > - > - if (ctx->key.dl_type == htons(ETH_TYPE_IPV6)) { > - seq_skew = repl_ftp_v6_addr(pkt, v6_addr_rep, > ftp_data_start, > - > addr_offset_from_ftp_data_start, > - addr_size, mode); > - if (seq_skew) { > - ip_len = ntohs(nh6->ip6_ctlun.ip6_un1.ip6_un1_plen); > - ip_len += seq_skew; > - nh6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(ip_len); > - conn_seq_skew_set(ct, &conn_for_expectation->key, now, > - seq_skew, ctx->reply); > - } > - } else { > - seq_skew = repl_ftp_v4_addr(pkt, v4_addr_rep, > ftp_data_start, > - > addr_offset_from_ftp_data_start); > - ip_len = ntohs(l3_hdr->ip_tot_len); > - if (seq_skew) { > - ip_len += seq_skew; > - l3_hdr->ip_csum = recalc_csum16(l3_hdr->ip_csum, > - l3_hdr->ip_tot_len, > htons(ip_len)); > - l3_hdr->ip_tot_len = htons(ip_len); > - conn_seq_skew_set(ct, &conn_for_expectation->key, now, > - seq_skew, ctx->reply); > + seq_skew = conn_for_expectation->seq_skew; > + if (nat) { > + uint16_t ip_len; > + int64_t new_skew; > + > + if (ctx->key.dl_type == htons(ETH_TYPE_IPV6)) { > + new_skew = repl_ftp_v6_addr(pkt, v6_addr_rep, > ftp_data_start, > + > addr_offset_from_ftp_data_start, > + addr_size, mode); > + if (new_skew) { > + ip_len = > ntohs(nh6->ip6_ctlun.ip6_un1.ip6_un1_plen); > + ip_len += new_skew; > + nh6->ip6_ctlun.ip6_un1.ip6_un1_plen = > htons(ip_len); > + conn_seq_skew_set(ct, &conn_for_expectation->key, > now, > + new_skew + seq_skew, > ctx->reply); > + } > + } else { > + new_skew = repl_ftp_v4_addr(pkt, v4_addr_rep, > ftp_data_start, > + > addr_offset_from_ftp_data_start); > + ip_len = ntohs(l3_hdr->ip_tot_len); > + if (new_skew) { > + ip_len += new_skew; > + l3_hdr->ip_csum = recalc_csum16(l3_hdr->ip_csum, > + l3_hdr->ip_tot_len, > htons(ip_len)); > + l3_hdr->ip_tot_len = htons(ip_len); > + conn_seq_skew_set(ct, &conn_for_expectation->key, > now, > + new_skew + seq_skew, > ctx->reply); > + } > } > } > } else { > 1/ I don't think we need another local variable since conn_for_expectation->seq_skew keeps the previous seq_skew, so we can just use it. 2/ The "nat" check is semantically correct around the repl_ftp_v4/6_addr() calls if (nat) { seq_skew = repl_ftp_v4_addr(pkt, v4_addr_rep, ftp_data_start, addr_offset_from_ftp_data_start); } This yields: @@ -3217,27 +3225,37 @@ handle_ftp_ctl(struct conntrack *ct, const struct conn_lookup_ctx *ctx, uint16_t ip_len; if (ctx->key.dl_type == htons(ETH_TYPE_IPV6)) { - seq_skew = repl_ftp_v6_addr(pkt, v6_addr_rep, ftp_data_start, - addr_offset_from_ftp_data_start, - addr_size, mode); + if (nat) { + seq_skew = repl_ftp_v6_addr(pkt, v6_addr_rep, + ftp_data_start, + addr_offset_from_ftp_data_start, + addr_size, mode); + } + if (seq_skew) { ip_len = ntohs(nh6->ip6_ctlun.ip6_un1.ip6_un1_plen); ip_len += seq_skew; nh6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(ip_len); conn_seq_skew_set(ct, &conn_for_expectation->key, now, - seq_skew, ctx->reply); + seq_skew + conn_for_expectation->seq_skew, + ctx->reply); } } else { - seq_skew = repl_ftp_v4_addr(pkt, v4_addr_rep, ftp_data_start, - addr_offset_from_ftp_data_start); - ip_len = ntohs(l3_hdr->ip_tot_len); + if (nat) { + seq_skew = repl_ftp_v4_addr(pkt, v4_addr_rep, + ftp_data_start, + addr_offset_from_ftp_data_start); + } + if (seq_skew) { + ip_len = ntohs(l3_hdr->ip_tot_len); ip_len += seq_skew; l3_hdr->ip_csum = recalc_csum16(l3_hdr->ip_csum, l3_hdr->ip_tot_len, htons(ip_len)); l3_hdr->ip_tot_len = htons(ip_len); conn_seq_skew_set(ct, &conn_for_expectation->key, now, - seq_skew, ctx->reply); + seq_skew + conn_for_expectation->seq_skew, + ctx->reply); } } } else { (END) > diff --git a/tests/system-traffic.at b/tests/system-traffic.at > index 4c52431..3734497 100644 > --- a/tests/system-traffic.at > +++ b/tests/system-traffic.at > @@ -4240,7 +4240,16 @@ m4_define([CHECK_FTP_NAT], > OVS_START_L7([at_ns1], [ftp]) > > dnl FTP requests from p0->p1 should work fine. > - NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.2 -4 --no-passive-ftp -t > 3 -T 1 --retry-connrefused -v --server-response --no-remove-listing -o > wget0.log -d]) > + AT_DATA([ftp.cmd], [dnl > +set net:max-retries 1 > +set net:timeout 1 > +set ftp:passive-mode off > +cache off > +connect ftp://anonymous:@10.1.1.2 > +ls > +ls > +]) > + NS_CHECK_EXEC([at_ns0], [lftp -f ftp.cmd > lftp.log]) > A check is needed for running outside of vagrant which is how I ran it: see atlocal.in and add "find_command lftp" then check for it in system_traffic.at > > dnl Discards CLOSE_WAIT and CLOSING > AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], > [0], [$4]) > -- > 1.8.3.1 > > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev