diff --git a/command/agent/agent.go b/command/agent/agent.go index 14360e04e6..1c59a0706c 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -22,6 +22,7 @@ import ( "github.com/hashicorp/consul/consul" "github.com/hashicorp/consul/consul/state" "github.com/hashicorp/consul/consul/structs" + "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logger" "github.com/hashicorp/consul/types" @@ -316,12 +317,12 @@ func (a *Agent) consulConfig() (*consul.Config, error) { } a.config.AdvertiseAddr = ipStr - case a.config.BindAddr != "" && !isAddrANY(a.config.BindAddr): + case a.config.BindAddr != "" && !ipaddr.IsAny(a.config.BindAddr): a.config.AdvertiseAddr = a.config.BindAddr default: ip, err := consul.GetPrivateIP() - if isIPv6ANY(a.config.BindAddr) { + if ipaddr.IsAnyV6(a.config.BindAddr) { ip, err = consul.GetPublicIPv6() } if err != nil { @@ -452,7 +453,7 @@ func (a *Agent) consulConfig() (*consul.Config, error) { // set the src address for outgoing rpc connections // Use port 0 so that outgoing connections use a random port. - if !isAddrANY(base.RPCAddr.IP) { + if !ipaddr.IsAny(base.RPCAddr.IP) { base.RPCSrcAddr = &net.TCPAddr{IP: base.RPCAddr.IP} } diff --git a/command/agent/agent_endpoint.go b/command/agent/agent_endpoint.go index bda65fd43e..17a2cd1e14 100644 --- a/command/agent/agent_endpoint.go +++ b/command/agent/agent_endpoint.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/consul/structs" + "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/logger" "github.com/hashicorp/consul/types" "github.com/hashicorp/logutils" @@ -454,7 +455,7 @@ func (s *HTTPServer) AgentRegisterService(resp http.ResponseWriter, req *http.Re // Check the service address here and in the catalog RPC endpoint // since service registration isn't sychronous. - if args.Address == "0.0.0.0" || args.Address == "::" || args.Address == "[::]" { + if ipaddr.IsAny(args.Address) { resp.WriteHeader(400) fmt.Fprintf(resp, "Invalid service address") return nil, nil diff --git a/command/agent/command.go b/command/agent/command.go index 61d911e5be..c7e7b2ecbd 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -18,6 +18,7 @@ import ( "github.com/hashicorp/consul/command/base" "github.com/hashicorp/consul/consul" "github.com/hashicorp/consul/consul/structs" + "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logger" "github.com/hashicorp/consul/watch" @@ -372,12 +373,12 @@ func (c *Command) readConfig() *Config { return nil } - if isAddrANY(config.AdvertiseAddr) { + if ipaddr.IsAny(config.AdvertiseAddr) { c.UI.Error("Advertise address cannot be " + config.AdvertiseAddr) return nil } - if isAddrANY(config.AdvertiseAddrWan) { + if ipaddr.IsAny(config.AdvertiseAddrWan) { c.UI.Error("Advertise WAN address cannot be " + config.AdvertiseAddrWan) return nil } diff --git a/command/agent/config.go b/command/agent/config.go index d174a0f6f9..2e07a10d86 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -1968,31 +1968,3 @@ func (d dirEnts) Less(i, j int) bool { func (d dirEnts) Swap(i, j int) { d[i], d[j] = d[j], d[i] } - -// isAddrANY checks if the given ip address is an IPv4 or IPv6 ANY address. ip -// can be either a *net.IP or a string. It panics on another type. -func isAddrANY(ip interface{}) bool { - if ip == nil { - return false - } - var ips string - switch x := ip.(type) { - case net.IP: - ips = x.String() - case *net.IP: - ips = x.String() - case string: - ips = x - default: - panic(fmt.Sprintf("invalid type: %T", ip)) - } - return isIPv4Any(ips) || isIPv6ANY(ips) -} - -func isIPv4Any(ip string) bool { - return ip == "0.0.0.0" -} - -func isIPv6ANY(ip string) bool { - return ip == "::" || ip == "[::]" -} diff --git a/consul/catalog_endpoint.go b/consul/catalog_endpoint.go index 04b4eac146..5d35786293 100644 --- a/consul/catalog_endpoint.go +++ b/consul/catalog_endpoint.go @@ -7,6 +7,7 @@ import ( "github.com/armon/go-metrics" "github.com/hashicorp/consul/consul/state" "github.com/hashicorp/consul/consul/structs" + "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/types" "github.com/hashicorp/go-memdb" "github.com/hashicorp/go-uuid" @@ -54,7 +55,7 @@ func (c *Catalog) Register(args *structs.RegisterRequest, reply *struct{}) error // Check the service address here and in the agent endpoint // since service registration isn't sychronous. - if args.Service.Address == "0.0.0.0" || args.Service.Address == "::" || args.Service.Address == "[::]" { + if ipaddr.IsAny(args.Service.Address) { return fmt.Errorf("Invalid service address") } diff --git a/ipaddr/ipaddr.go b/ipaddr/ipaddr.go new file mode 100644 index 0000000000..b75eade4a9 --- /dev/null +++ b/ipaddr/ipaddr.go @@ -0,0 +1,41 @@ +package ipaddr + +import ( + "fmt" + "net" +) + +// IsAny checks if the given ip address is an IPv4 or IPv6 ANY address. ip +// can be either a *net.IP or a string. It panics on another type. +func IsAny(ip interface{}) bool { + return IsAnyV4(ip) || IsAnyV6(ip) +} + +// IsAnyV4 checks if the given ip address is an IPv4 ANY address. ip +// can be either a *net.IP or a string. It panics on another type. +func IsAnyV4(ip interface{}) bool { + return iptos(ip) == "0.0.0.0" +} + +// IsAnyV6 checks if the given ip address is an IPv6 ANY address. ip +// can be either a *net.IP or a string. It panics on another type. +func IsAnyV6(ip interface{}) bool { + ips := iptos(ip) + return ips == "::" || ips == "[::]" +} + +func iptos(ip interface{}) string { + if ip == nil { + return "" + } + switch x := ip.(type) { + case string: + return x + case net.IP: + return x.String() + case *net.IP: + return x.String() + default: + panic(fmt.Sprintf("invalid type: %T", ip)) + } +}