Skip to content

Commit

Permalink
fix host:port joining for ipv6 listen addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
chappjc committed Dec 28, 2020
1 parent 7c087e8 commit f0ef965
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 11 deletions.
5 changes: 3 additions & 2 deletions client/cmd/dexc/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package main

import (
"fmt"
"net"
"os"
"os/user"
"path/filepath"
Expand Down Expand Up @@ -184,10 +185,10 @@ func configure() (*Config, error) {
// If web or RPC server addresses not set, use network specific
// defaults
if cfg.WebAddr == "" {
cfg.WebAddr = defaultHost + ":" + defaultWebPort
cfg.WebAddr = net.JoinHostPort(defaultHost, defaultWebPort)
}
if cfg.RPCAddr == "" {
cfg.RPCAddr = defaultHost + ":" + defaultRPCPort
cfg.RPCAddr = net.JoinHostPort(defaultHost, defaultRPCPort)
}

if cfg.RPCCert == "" {
Expand Down
5 changes: 3 additions & 2 deletions client/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,8 @@ func addrHost(addr string) (string, error) {
// Any address with no colons is appended with the default port.
var addrErr *net.AddrError
if errors.As(splitErr, &addrErr) && addrErr.Err == missingPort {
return addr + ":" + defaultDEXPort, nil
host = strings.Trim(addrErr.Addr, "[]") // JoinHostPort expects no brackets for ipv6 hosts
return net.JoinHostPort(host, defaultDEXPort), nil
}
// These are addresses with at least one colon in an unexpected
// position.
Expand All @@ -958,7 +959,7 @@ func addrHost(addr string) (string, error) {
host, port = a.Hostname(), a.Port()
// If the address parses but there is no port, append the default port.
if port == "" {
return host + ":" + defaultDEXPort, nil
return net.JoinHostPort(host, defaultDEXPort), nil
}
}
// We have a port but no host. Replace with localhost.
Expand Down
4 changes: 4 additions & 0 deletions client/core/core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4168,6 +4168,10 @@ func TestAddrHost(t *testing.T) {
name: "scheme, host, and port",
addr: "https://localhost:5758",
want: "localhost:5758",
}, {
name: "scheme, ipv6 host, and port",
addr: "https://[::1]:5758",
want: "[::1]:5758",
}, {
name: "host and port",
addr: "localhost:5758",
Expand Down
19 changes: 12 additions & 7 deletions server/cmd/dcrdex/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package main

import (
"errors"
"fmt"
"net"
"os"
Expand Down Expand Up @@ -254,26 +255,30 @@ func parseAndSetDebugLevels(debugLevel string, UTC bool) (*dex.LoggerMaker, erro
return lm, nil
}

const missingPort = "missing port in address"

// normalizeNetworkAddress checks for a valid local network address format and
// adds default host and port if not present. Invalidates addresses that include
// a protocol identifier.
func normalizeNetworkAddress(a, defaultHost, defaultPort string) (string, error) {
if strings.Contains(a, "://") {
return a, fmt.Errorf("Address %s contains a protocol identifier, which is not allowed", a)
return a, fmt.Errorf("address %s contains a protocol identifier, which is not allowed", a)
}
if a == "" {
return defaultHost + ":" + defaultPort, nil
return net.JoinHostPort(defaultHost, defaultPort), nil
}
host, port, err := net.SplitHostPort(a)
if err != nil {
if strings.Contains(err.Error(), "missing port in address") {
normalized := a + ":" + defaultPort
var addrErr *net.AddrError
if errors.As(err, &addrErr) && addrErr.Err == missingPort {
host = strings.Trim(addrErr.Addr, "[]") // JoinHostPort expects no brackets for ipv6 hosts
normalized := net.JoinHostPort(host, defaultPort)
host, port, err = net.SplitHostPort(normalized)
if err != nil {
return a, fmt.Errorf("Unable to address %s after port resolution: %v", normalized, err)
return a, fmt.Errorf("unable to address %s after port resolution: %w", normalized, err)
}
} else {
return a, fmt.Errorf("Unable to normalize address %s: %v", a, err)
return a, fmt.Errorf("unable to normalize address %s: %w", a, err)
}
}
if host == "" {
Expand All @@ -282,7 +287,7 @@ func normalizeNetworkAddress(a, defaultHost, defaultPort string) (string, error)
if port == "" {
port = defaultPort
}
return host + ":" + port, nil
return net.JoinHostPort(host, port), nil
}

// loadConfig initializes and parses the config using a config file and command
Expand Down
52 changes: 52 additions & 0 deletions server/cmd/dcrdex/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// This code is available on the terms of the project LICENSE.md file,
// also available online at https://blueoakcouncil.org/license/1.0.0.

package main

import "testing"

const (
defaultHost = "127.0.0.1"
defaultPort = "17232"
)

func Test_normalizeNetworkAddress(t *testing.T) {
tests := []struct {
listen string
want string
wantErr bool
}{
{
listen: "[::1]",
want: "[::1]:17232",
},
{
listen: "[::]:",
want: "[::]:17232",
},
{
listen: "",
want: "127.0.0.1:17232",
},
{
listen: "127.0.0.2",
want: "127.0.0.2:17232",
},
{
listen: ":7222",
want: "127.0.0.1:7222",
},
}
for _, tt := range tests {
t.Run(tt.listen, func(t *testing.T) {
got, err := normalizeNetworkAddress(tt.listen, defaultHost, defaultPort)
if (err != nil) != tt.wantErr {
t.Errorf("normalizeNetworkAddress() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("normalizeNetworkAddress() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit f0ef965

Please sign in to comment.