From 8fb9008c9564899fdbd3a621437eea17b79b9f52 Mon Sep 17 00:00:00 2001 From: Jean-Louis Huynen Date: Mon, 1 Apr 2019 15:01:01 +0200 Subject: [PATCH] Fix #4 --- .gitignore | 4 +--- d4-goclient.go | 35 ++++++++++++++++++++++------------- d4-goclient_test.go | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 d4-goclient_test.go diff --git a/.gitignore b/.gitignore index 9b5e95c..ebe06e1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,7 @@ *.so *.dylib *.vscode - -# Test binary, build with `go test -c` -*.test +*.idea # Output of the go coverage tool, specifically when used with LiteIDE *.out diff --git a/d4-goclient.go b/d4-goclient.go index f0291a9..7155287 100644 --- a/d4-goclient.go +++ b/d4-goclient.go @@ -16,6 +16,7 @@ import ( "net" "os" "os/signal" + "regexp" "strconv" "strings" "time" @@ -46,7 +47,6 @@ const ( ) type ( - // A d4 writer implements the io.Writer Interface by implementing Write() and Close() // it accepts an io.Writer as sink d4Writer struct { @@ -362,7 +362,6 @@ func setReaderWriters(d4 *d4S) bool { isn, dstnet := isNet((*d4).conf.destination) if isn { dial := net.Dialer{ - DualStack: true, Timeout: (*d4).ct, KeepAlive: (*d4).cka, FallbackDelay: 0, @@ -410,32 +409,42 @@ func setReaderWriters(d4 *d4S) bool { } func isNet(host string) (bool, string) { + // DNS regex + validDNS := regexp.MustCompile(`^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z + ]{2,3})$`) // Check ipv6 if strings.HasPrefix(host, "[") { // Parse an IP-Literal in RFC 3986 and RFC 6874. - // E.g., "[fe80::1]", "[fe80::1%25en0]", "[fe80::1]:80". + // E.g., "[fe80::1]:80". i := strings.LastIndex(host, "]") if i < 0 { - panic("Unmatched [ in destination config") + infof("Unmatched [ in destination config") + return false, "" } if !validPort(host[i+1:]) { - panic("No valid port specified") + infof("No valid port specified") + return false, "" } // trim brackets - if net.ParseIP(strings.Trim(host[:i+1], "[]")) != nil { infof(fmt.Sprintf("Server IP: %s, Server Port: %s\n", host[:i+1], host[i+1:])) return true, host } } else { - // Ipv4 + // Ipv4 or DNS name ss := strings.Split(string(host), ":") - if !validPort(":" + ss[1]) { - panic("No valid port specified") - } - if net.ParseIP(ss[0]) != nil { - infof(fmt.Sprintf("Server IP: %s, Server Port: %s\n", ss[0], ss[1])) - return true, host + if len(ss) > 1 { + if !validPort(":" + ss[1]) { + infof("No valid port specified") + return false, "" + } + if net.ParseIP(ss[0]) != nil { + infof(fmt.Sprintf("Server IP: %s, Server Port: %s\n", ss[0], ss[1])) + return true, host + } else if validDNS.MatchString(ss[0]) { + infof(fmt.Sprintf("DNS: %s, Server Port: %s\n", ss[0], ss[1])) + return true, host + } } } return false, host diff --git a/d4-goclient_test.go b/d4-goclient_test.go new file mode 100644 index 0000000..0bc2b28 --- /dev/null +++ b/d4-goclient_test.go @@ -0,0 +1,35 @@ +package main + +import ( + "testing" +) + +var testCases = []struct { + name string + str string + expected bool +}{ + {"Well-formed IPv4 with port", "127.0.0.1:4443", true}, + {"Well-formed IPv4 without port", "127.0.0.1", false}, + {"Malformed IPv4 with port", "127..0.1:4443", false}, + {"Malformed IPv4 without port", "127..0.1", false}, + {"Well-formed IPv6 with port - 2", "[::1]:4443", true}, + {"Well-formed IPv6 without port", "[fe80::1%25en0]", false}, + {"Malformed IPv6 with port", "[::::1]:4443", false}, + {"Malformed IPv6 without port", "[::::::::1]", false}, + {"Malformed IPv6 : missing square brackets", "::::::::1:4443", false}, + {"Well-formed DNS name with port", "toto.circl.lu:4443", true}, + {"Well-formed DNS name without port", "toto.circl.lu", false}, + {"Malformed DNS name with port", ".:4443", false}, +} + +func TestIsNet(t *testing.T) { + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + b, _ := isNet(tc.str) + if b != tc.expected { + t.Fail() + } + }) + } +}