Skip to content

Commit

Permalink
Fix non-root hosts failing on resolving DNS
Browse files Browse the repository at this point in the history
A fix for a bug introduced by btcsuite#2168

Previously, config.Host worked in the following way:
1. Documented as supporting ip addresses only
2. In fact supported "host/path" syntax
3. Did not support "scheme" prefixes, i.e. https://

Not sure this is the desired approach, probably the best thing would
have been to extend config to contain "Scheme" and "Path" fields as well.

However, this was the way it worked.

1. Now Host can contain scheme prefixes "unix://..."
2. Host can no longer contain ".../path"

This PR solves this behavior while maintaining support of the "unix://" flow
as well.

For some reason, "scheme" is named "network" in btcsuite#2168 - I did not change that.

Also remove disambiguation in "network:address:port", where it parsed
"myhost:8888" as network:address instead address:port.
  • Loading branch information
same-id committed Oct 29, 2024
1 parent 24eb815 commit c7dae61
Showing 1 changed file with 28 additions and 34 deletions.
62 changes: 28 additions & 34 deletions rpcclient/infrastructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -1733,48 +1733,42 @@ func (c *Client) Send() error {
return nil
}

// CutPrefix returns s without the provided leading prefix string
// and reports whether it found the prefix.
// If s doesn't start with prefix, CutPrefix returns s, false.
// If prefix is the empty string, CutPrefix returns s, true.
// Copied from go1.20 version.
func cutPrefix(s, prefix string) (after string, found bool) {
if !strings.HasPrefix(s, prefix) {
return s, false
}
return s[len(prefix):], true
}

// ParseAddressString converts an address in string format to a net.Addr that is
// compatible with btcd. UDP is not supported because btcd needs reliable
// connections. We accept a custom function to resolve any TCP addresses so
// that caller is able control exactly how resolution is performed.
func ParseAddressString(strAddress string) (net.Addr, error) {
var parsedNetwork, parsedAddr string

// Addresses can either be in network://address:port format,
// network:address:port, address:port, or just port. We want to support
// all possible types.
// Addresses can either be in unix://address, unixpacket://address URL
// format, or just address:port host format for tcp.
if after, ok := cutPrefix(strAddress, "unix://"); ok {
return net.ResolveUnixAddr("unix", after)
}
if after, ok := cutPrefix(strAddress, "unixpacket://"); ok {
return net.ResolveUnixAddr("unixpacket", after)
}
if strings.Contains(strAddress, "://") {
parts := strings.Split(strAddress, "://")
parsedNetwork, parsedAddr = parts[0], parts[1]
} else if strings.Contains(strAddress, ":") {
parts := strings.Split(strAddress, ":")
parsedNetwork = parts[0]
parsedAddr = strings.Join(parts[1:], ":")
} else {
parsedAddr = strAddress
// Not supporting :// anywhere in the host or path.
return nil, fmt.Errorf(
"unsupported protocol in address: %s", strAddress,
)
}

// Only TCP and Unix socket addresses are valid. We can't use IP or
// UDP only connections for anything we do in lnd.
switch parsedNetwork {
case "unix", "unixpacket":
return net.ResolveUnixAddr(parsedNetwork, parsedAddr)

case "tcp", "tcp4", "tcp6":
return net.ResolveTCPAddr(parsedNetwork, verifyPort(parsedAddr))

case "ip", "ip4", "ip6", "udp", "udp4", "udp6", "unixgram":
return nil, fmt.Errorf("only TCP or unix socket "+
"addresses are supported: %s", parsedAddr)

default:
// We'll now possibly use the local host short circuit
// or parse out an all interfaces listen.
addrWithPort := verifyPort(strAddress)

// Otherwise, we'll attempt to resolve the host.
return net.ResolveTCPAddr("tcp", addrWithPort)
u, err := url.Parse("dummy://" + strAddress)
if err != nil {
return nil, err
}
return net.ResolveTCPAddr("tcp", verifyPort(u.Host))
}

// verifyPort makes sure that an address string has both a host and a port.
Expand Down

0 comments on commit c7dae61

Please sign in to comment.