Skip to content

Commit

Permalink
lib: Add support for tftp ct helper.
Browse files Browse the repository at this point in the history
The kernel datapath provides support for TFTP helpers, so add support
for this ALG to the commandline and OpenFlow encoding/decoding.

Signed-off-by: Joe Stringer <[email protected]>
Acked-by: Daniele Di Proietto <[email protected]>
Acked-by: Ben Pfaff <[email protected]>
  • Loading branch information
joestringer committed Jan 3, 2017
1 parent c26ed9c commit 40c7b2f
Show file tree
Hide file tree
Showing 13 changed files with 178 additions and 32 deletions.
4 changes: 4 additions & 0 deletions Documentation/intro/install/general.rst
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ The datapath tests for userspace and Linux datapaths also rely upon:

- netcat. Several common implementations are known to work.

- curl. Version 7.47.0 is known to work. Earlier versions should also work.

- tftpy. Version 0.6.2 is known to work. Earlier versions should also work.

The ovs-vswitchd.conf.db(5) manpage will include an E-R diagram, in formats
other than plain text, only if you have the following:

Expand Down
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Post-v2.6.0
"selection_method" and related options in ovs-ofctl(8) for
details.
* The "sample" action now supports "ingress" and "egress" options.
* The "ct" action now supports the TFTP ALG where support is available.
- ovs-ofctl:
* 'bundle' command now supports packet-out messages.
* New syntax for 'ovs-ofctl packet-out' command, which uses the
Expand Down
10 changes: 5 additions & 5 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ $bootstrap_fedora = <<SCRIPT
dnf -y update
dnf -y install autoconf automake openssl-devel libtool \
python-twisted-core python-zope-interface \
desktop-file-utils groff graphviz rpmdevtools nc \
desktop-file-utils groff graphviz rpmdevtools nc curl \
wget python-six pyftpdlib checkpolicy selinux-policy-devel \
libcap-ng-devel kernel-devel-`uname -r` ethtool
libcap-ng-devel kernel-devel-`uname -r` ethtool python-tftpy
echo "search extra update built-in" >/etc/depmod.d/search_path.conf
SCRIPT

Expand All @@ -23,18 +23,18 @@ aptitude -y install -R \
debhelper dh-autoreconf uuid-runtime \
autoconf automake libtool \
python-all python-twisted-core python-twisted-conch \
xdg-utils groff graphviz netcat \
xdg-utils groff graphviz netcat curl \
wget python-six ethtool \
libcap-ng-dev libssl-dev python-dev openssl \
python-pyftpdlib python-flake8 \
python-pyftpdlib python-flake8 python-tftpy \
linux-headers-`uname -r`
SCRIPT

$bootstrap_centos = <<SCRIPT
yum -y update
yum -y install autoconf automake openssl-devel libtool \
python-twisted-core python-zope-interface \
desktop-file-utils groff graphviz rpmdevtools nc \
desktop-file-utils groff graphviz rpmdevtools nc curl \
wget python-six pyftpdlib checkpolicy selinux-policy-devel \
libcap-ng-devel kernel-devel-`uname -r` ethtool
SCRIPT
Expand Down
4 changes: 4 additions & 0 deletions include/openvswitch/ofp-actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,10 @@ enum nx_conntrack_flags {
#define IPPORT_FTP 21
#endif

#if !defined(IPPORT_TFTP)
#define IPPORT_TFTP 69
#endif

/* OFPACT_CT.
*
* Used for NXAST_CT. */
Expand Down
16 changes: 13 additions & 3 deletions lib/ofp-actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -5454,10 +5454,19 @@ parse_CT(char *arg, struct ofpbuf *ofpacts,
static void
format_alg(int port, struct ds *s)
{
if (port == IPPORT_FTP) {
switch(port) {
case IPPORT_FTP:
ds_put_format(s, "%salg=%sftp,", colors.param, colors.end);
} else if (port) {
break;
case IPPORT_TFTP:
ds_put_format(s, "%salg=%stftp,", colors.param, colors.end);
break;
case 0:
/* Don't print. */
break;
default:
ds_put_format(s, "%salg=%s%d,", colors.param, colors.end, port);
break;
}
}

Expand Down Expand Up @@ -7170,7 +7179,8 @@ ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a,

if (!dl_type_is_ip_any(flow->dl_type)
|| (flow->ct_state & CS_INVALID && oc->flags & NX_CT_F_COMMIT)
|| (oc->alg == IPPORT_FTP && flow->nw_proto != IPPROTO_TCP)) {
|| (oc->alg == IPPORT_FTP && flow->nw_proto != IPPROTO_TCP)
|| (oc->alg == IPPORT_TFTP && flow->nw_proto != IPPROTO_UDP)) {
/* We can't downgrade to OF1.0 and expect inconsistent CT actions
* be silently discarded. Instead, datapath flow install fails, so
* it is better to flag inconsistent CT actions as hard errors. */
Expand Down
4 changes: 4 additions & 0 deletions lib/ofp-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ str_to_connhelper(const char *str, uint16_t *alg)
*alg = IPPORT_FTP;
return NULL;
}
if (!strcmp(str, "tftp")) {
*alg = IPPORT_TFTP;
return NULL;
}
return xasprintf("invalid conntrack helper \"%s\"", str);
}

Expand Down
10 changes: 8 additions & 2 deletions ofproto/ofproto-dpif-xlate.c
Original file line number Diff line number Diff line change
Expand Up @@ -4550,10 +4550,16 @@ static void
put_ct_helper(struct ofpbuf *odp_actions, struct ofpact_conntrack *ofc)
{
if (ofc->alg) {
if (ofc->alg == IPPORT_FTP) {
switch(ofc->alg) {
case IPPORT_FTP:
nl_msg_put_string(odp_actions, OVS_CT_ATTR_HELPER, "ftp");
} else {
break;
case IPPORT_TFTP:
nl_msg_put_string(odp_actions, OVS_CT_ATTR_HELPER, "tftp");
break;
default:
VLOG_WARN("Cannot serialize ct_helper %d\n", ofc->alg);
break;
}
}
}
Expand Down
26 changes: 20 additions & 6 deletions tests/atlocal.in
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,24 @@ if test "$IS_WIN32" = "yes"; then
HAVE_PYTHON3="no"
fi

if test "$HAVE_PYTHON" = "yes" \
&& test "x`$PYTHON $abs_top_srcdir/tests/test-l7.py --help | grep 'ftp'`" != x; then
HAVE_PYFTPDLIB="yes"
else
HAVE_PYFTPDLIB="no"
fi
find_l7_lib()
{
set +x
var=HAVE_`echo "$1" | tr '[a-z]' '[A-Z]'`
if test "$HAVE_PYTHON" = "yes"; then
result=$($PYTHON $abs_top_srcdir/tests/test-l7.py --help | grep "$1")
if test "x${result}" != x; then
eval ${var}="yes"
else
eval ${var}="no"
fi
else
eval ${var}="no"
fi
}

find_l7_lib ftp
find_l7_lib tftp

# Look for a commnand in the system. If it is found, defines
# HAVE_COMMAND="yes", otherwise HAVE_COMMAND="no".
Expand All @@ -148,6 +160,8 @@ else
NC_EOF_OPT="-q 1"
fi

CURL_OPT="-g -v --max-time 1 --retry 2 --retry-delay 1 --connect-timeout 1"

# Turn off proxies.
unset http_proxy
unset https_proxy
Expand Down
1 change: 1 addition & 0 deletions tests/odp.at
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ ct(commit,zone=5)
ct(commit,mark=0xa0a0a0a0/0xfefefefe)
ct(commit,label=0x1234567890abcdef1234567890abcdef/0xf1f2f3f4f5f6f7f8f9f0fafbfcfdfeff)
ct(commit,helper=ftp)
ct(commit,helper=tftp)
ct(nat)
ct(commit,nat(src))
ct(commit,nat(dst))
Expand Down
3 changes: 3 additions & 0 deletions tests/ofp-actions.at
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ ffff 0018 00002320 0007 001f 00010004 000000000000f009
# actions=ct(alg=ftp)
ffff 0018 00002320 0023 0000 00000000 0000 FF 000000 0015

# actions=ct(alg=tftp)
ffff 0018 00002320 0023 0000 00000000 0000 FF 000000 0045

# actions=ct(commit,nat(src))
ffff 0028 00002320 0023 0001 00000000 0000 FF 000000 0000 dnl
ffff 0010 00002320 0024 00 00 0001 0000
Expand Down
84 changes: 79 additions & 5 deletions tests/system-traffic.at
Original file line number Diff line number Diff line change
Expand Up @@ -1987,7 +1987,7 @@ OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - FTP])
AT_SKIP_IF([test $HAVE_PYFTPDLIB = no])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_ALG()
OVS_TRAFFIC_VSWITCHD_START()
Expand Down Expand Up @@ -2072,7 +2072,7 @@ OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - FTP over IPv6])
AT_SKIP_IF([test $HAVE_PYFTPDLIB = no])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_ALG()
OVS_TRAFFIC_VSWITCHD_START()
Expand Down Expand Up @@ -2127,7 +2127,7 @@ OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - FTP with multiple expectations])
AT_SKIP_IF([test $HAVE_PYFTPDLIB = no])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_ALG()
OVS_TRAFFIC_VSWITCHD_START()
Expand Down Expand Up @@ -2192,6 +2192,80 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - TFTP])
AT_SKIP_IF([test $HAVE_TFTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_ALG()
OVS_TRAFFIC_VSWITCHD_START()

ADD_NAMESPACES(at_ns0, at_ns1)

ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")

dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0.
AT_DATA([flows1.txt], [dnl
table=0,priority=1,action=drop
table=0,priority=10,arp,action=normal
table=0,priority=10,icmp,action=normal
table=0,priority=100,in_port=1,udp,action=ct(alg=tftp,commit),2
table=0,priority=100,in_port=2,udp,action=ct(table=1)
table=1,in_port=2,udp,ct_state=+trk+est,action=1
table=1,in_port=2,udp,ct_state=+trk+rel,action=1
])

dnl Similar policy but without allowing all traffic from ns0->ns1.
AT_DATA([flows2.txt], [dnl
table=0,priority=1,action=drop
table=0,priority=10,arp,action=normal
table=0,priority=10,icmp,action=normal

dnl Allow outgoing UDP connections, and treat them as TFTP
table=0,priority=100,in_port=1,udp,action=ct(table=1)
table=1,in_port=1,udp,ct_state=+trk+new-rel,action=ct(commit,alg=tftp),2
table=1,in_port=1,udp,ct_state=+trk+new+rel,action=ct(commit),2
table=1,in_port=1,udp,ct_state=+trk+est,action=2

dnl Allow incoming TFTP data connections and responses to existing connections
table=0,priority=100,in_port=2,udp,action=ct(table=1)
table=1,in_port=2,udp,ct_state=+trk+est,action=1
table=1,in_port=2,udp,ct_state=+trk+new+rel,action=1
])

AT_CHECK([ovs-ofctl --bundle replace-flows br0 flows1.txt])

OVS_START_L7([at_ns0], [tftp])
OVS_START_L7([at_ns1], [tftp])

dnl TFTP requests from p1->p0 should fail due to network failure.
NS_CHECK_EXEC([at_ns1], [[curl $CURL_OPT tftp://10.1.1.1/flows1.txt -o foo 2>curl0.log]], [28])
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.1)], [0], [dnl
])

dnl TFTP requests from p0->p1 should work fine.
NS_CHECK_EXEC([at_ns0], [[curl $CURL_OPT tftp://10.1.1.2/flows1.txt -o foo 2>curl1.log]])
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),helper=tftp
])

dnl Try the second set of flows.
AT_CHECK([ovs-ofctl --bundle replace-flows br0 flows2.txt])
AT_CHECK([ovs-appctl dpctl/flush-conntrack])

dnl TFTP requests from p1->p0 should fail due to network failure.
NS_CHECK_EXEC([at_ns1], [[curl $CURL_OPT tftp://10.1.1.1/flows1.txt -o foo 2>curl2.log]], [28])
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.1)], [0], [dnl
])

dnl TFTP requests from p0->p1 should work fine.
NS_CHECK_EXEC([at_ns0], [[curl $CURL_OPT tftp://10.1.1.2/flows1.txt -o foo 2>curl3.log]])
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),helper=tftp
])

OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_BANNER([conntrack - NAT])

AT_SETUP([conntrack - simple SNAT])
Expand Down Expand Up @@ -2524,7 +2598,7 @@ dnl Checks the implementation of conntrack with FTP ALGs in combination with
dnl NAT, using the provided flow table.
m4_define([CHECK_FTP_NAT],
[AT_SETUP([conntrack - FTP NAT $1])
AT_SKIP_IF([test $HAVE_PYFTPDLIB = no])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()

Expand Down Expand Up @@ -2736,7 +2810,7 @@ AT_CLEANUP


AT_SETUP([conntrack - IPv6 FTP with NAT])
AT_SKIP_IF([test $HAVE_PYFTPDLIB = no])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
OVS_TRAFFIC_VSWITCHD_START()
Expand Down
32 changes: 25 additions & 7 deletions tests/test-l7.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2015 Nicira, Inc.
# Copyright (c) 2015, 2016 Nicira, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -48,24 +48,42 @@ class OVSFTPHandler(FTPHandler):
return server


def get_tftpd():
try:
from tftpy import TftpServer, TftpShared

class OVSTFTPServer(TftpServer):
def __init__(self, listen, handler=None):
(ip, port) = listen
self.ip = ip
self.port = port
TftpServer.__init__(self, tftproot='./')

def serve_forever(self):
self.listen(self.ip, self.port)
server = [OVSTFTPServer, None, TftpShared.DEF_TFTP_PORT]
except ImportError:
server = None
pass
return server


def main():
SERVERS = {
'http': [TCPServer, SimpleHTTPRequestHandler, 80],
'http6': [TCPServerV6, SimpleHTTPRequestHandler, 80],
'ftp': get_ftpd(),
'tftp': get_tftpd(),
}

ftpd = get_ftpd()
if ftpd is not None:
SERVERS['ftp'] = ftpd

protocols = [srv for srv in SERVERS]
protocols = [srv for srv in SERVERS if SERVERS[srv] is not None]
parser = argparse.ArgumentParser(
description='Run basic application servers.')
parser.add_argument('proto', default='http', nargs='?',
help='protocol to serve (%s)' % protocols)
args = parser.parse_args()

if args.proto not in SERVERS:
if args.proto not in protocols:
parser.print_help()
exit(1)

Expand Down
15 changes: 11 additions & 4 deletions utilities/ovs-ofctl.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -1840,12 +1840,19 @@ The \fBcommit\fR parameter must be specified to use \fBexec(...)\fR.
.
.IP \fBalg=\fIalg\fR
Specify application layer gateway \fIalg\fR to track specific connection
types. Supported types include:
types. If subsequent related connections are sent through the \fBct\fR
action, then the \fBrel\fR flag in the \fBct_state\fR field will be set.
Supported types include:
.RS
.IP \fBftp\fR
Look for negotiation of FTP data connections. If a subsequent FTP data
connection arrives which is related, the \fBct\fR action will set the
\fBrel\fR flag in the \fBct_state\fR field for packets sent through \fBct\fR.
Look for negotiation of FTP data connections. Specify this option for FTP
control connections to detect related data connections and populate the
\fBrel\fR flag for the data connections.
.
.IP \fBtftp\fR
Look for negotiation of TFTP data connections. Specify this option for TFTP
control connections to detect related data connections and populate the
\fBrel\fR flag for the data connections.
.RE
.
.IP
Expand Down

0 comments on commit 40c7b2f

Please sign in to comment.