From 0b754dce0536882785cecad4317999824a72e8eb Mon Sep 17 00:00:00 2001 From: Sam Eiderman Date: Sun, 27 Oct 2024 14:19:17 +0200 Subject: [PATCH] Fix non-root hosts failing on resolving DNS A fix for a bug introduced by #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 #2168 - I did not change that. Also remove disambiguation in "network:address:port", where it parsed "myhost:8888" as network:address instead address:port. --- rpcclient/infrastructure.go | 50 +++++++++++-------------------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 4fe1d894df8..712ab121191 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -1738,43 +1738,23 @@ func (c *Client) Send() error { // 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. - 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 + // Addresses can either be in unix://address, unixpacket://address URL format + // Or just address:port host format for tcp. + if after, ok := strings.CutPrefix(strAddress, "unix://"); ok { + return net.ResolveUnixAddr("unix://", after) } - - // 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) + if after, ok := strings.CutPrefix(strAddress, "unixpacket://"); ok { + return net.ResolveUnixAddr("unixpacket://", after) + } + urlized := strAddress + if strings.Contains(urlized, "://") { // Not supporting :// anywhere in the host or path + return nil, fmt.Errorf("unsupported protocol in address: %s", strAddress) + } + 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.