From 691fac98afcd3dece8b4625565365d4cf33c3e1b Mon Sep 17 00:00:00 2001 From: Arnaud Ysmal Date: Wed, 4 Dec 2013 19:12:09 +0100 Subject: [PATCH 1/3] Force EPSV for IPv6 hosts and fix split of IPv6:port --- client_test.go | 20 ++++++++++++++++++++ ftp.go | 8 ++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/client_test.go b/client_test.go index d93d310..d92e2b0 100644 --- a/client_test.go +++ b/client_test.go @@ -130,3 +130,23 @@ func TestConn2(t *testing.T) { c.Quit() } + +// antioche.antioche.eu.org with IPv6 +func TestConnIPv6(t *testing.T) { + c, err := Connect("[2001:660:3302:282a:204:75ff:fe9f:9e11]:21") + if err != nil { + t.Fatal(err) + } + + err = c.Login("anonymous", "anonymous") + if err != nil { + t.Fatal(err) + } + + _, err = c.List(".") + if err != nil { + t.Error(err) + } + + c.Quit() +} diff --git a/ftp.go b/ftp.go index 93d7dfa..542565a 100644 --- a/ftp.go +++ b/ftp.go @@ -53,10 +53,10 @@ func Connect(addr string) (*ServerConn, error) { return nil, err } - a := strings.SplitN(addr, ":", 2) + a := addr[:strings.LastIndex(addr, ":")] c := &ServerConn{ conn: conn, - host: a[0], + host: a, features: make(map[string]string), } @@ -197,6 +197,10 @@ func (c *ServerConn) openDataConn() (net.Conn, error) { // else -> PASV _, nat6Supported := c.features["nat6"] _, epsvSupported := c.features["EPSV"] + // If host is IPv6 => EPSV + if c.host[0] == '[' { + epsvSupported = true + } if nat6Supported || epsvSupported { port, err = c.epsv() if err != nil { From a3bb5b871464c64feefdf3c87d4db2ce85ec0152 Mon Sep 17 00:00:00 2001 From: Arnaud Ysmal Date: Wed, 4 Dec 2013 23:42:17 +0100 Subject: [PATCH 2/3] Use net.JoinHostPort and net.SplitHostPort --- ftp.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ftp.go b/ftp.go index 542565a..949a7b6 100644 --- a/ftp.go +++ b/ftp.go @@ -4,7 +4,6 @@ package ftp import ( "bufio" "errors" - "fmt" "io" "net" "net/textproto" @@ -53,10 +52,14 @@ func Connect(addr string) (*ServerConn, error) { return nil, err } - a := addr[:strings.LastIndex(addr, ":")] + host, _, err := net.SplitHostPort(addr) + if err != nil { + conn.Close() + return nil, err + } c := &ServerConn{ conn: conn, - host: a, + host: host, features: make(map[string]string), } @@ -198,7 +201,7 @@ func (c *ServerConn) openDataConn() (net.Conn, error) { _, nat6Supported := c.features["nat6"] _, epsvSupported := c.features["EPSV"] // If host is IPv6 => EPSV - if c.host[0] == '[' { + if strings.ContainsAny(c.host, ":%") { epsvSupported = true } if nat6Supported || epsvSupported { @@ -214,7 +217,7 @@ func (c *ServerConn) openDataConn() (net.Conn, error) { } // Build the new net address string - addr := fmt.Sprintf("%s:%d", c.host, port) + addr := net.JoinHostPort(c.host, strconv.Itoa(port)) conn, err := net.Dial("tcp", addr) if err != nil { From 6bad3e176cc15f1846f122b65d487720055dc82f Mon Sep 17 00:00:00 2001 From: Arnaud Ysmal Date: Thu, 5 Dec 2013 19:29:22 +0100 Subject: [PATCH 3/3] Try EPSV when PASV fails --- ftp.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/ftp.go b/ftp.go index 949a7b6..02f3c4c 100644 --- a/ftp.go +++ b/ftp.go @@ -200,20 +200,15 @@ func (c *ServerConn) openDataConn() (net.Conn, error) { // else -> PASV _, nat6Supported := c.features["nat6"] _, epsvSupported := c.features["EPSV"] - // If host is IPv6 => EPSV - if strings.ContainsAny(c.host, ":%") { - epsvSupported = true + + if !nat6Supported && !epsvSupported { + port, _ = c.pasv() } - if nat6Supported || epsvSupported { + if port == 0 { port, err = c.epsv() if err != nil { return nil, err } - } else { - port, err = c.pasv() - if err != nil { - return nil, err - } } // Build the new net address string