Co-authored-by: Damian Debkowski <damian.debkowski@hashicorp.com>
73 lines
2.5 KiB
Go
73 lines
2.5 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package util
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/boundary/globals"
|
|
)
|
|
|
|
const (
|
|
// MinAddressLength
|
|
MinAddressLength = 3
|
|
// MaxAddressLength
|
|
MaxAddressLength = 255
|
|
)
|
|
|
|
// This regular expression is used to find all instances of square brackets within a string.
|
|
// This regular expression is used to remove the square brackets from an IPv6 address.
|
|
var squareBrackets = regexp.MustCompile("\\[|\\]")
|
|
|
|
// JoinHostPort combines host and port into a network address of the form "host:port".
|
|
// If host contains a colon, as found in literal IPv6 addresses, then JoinHostPort returns "[host]:port".
|
|
func JoinHostPort(host, port string) string {
|
|
host = squareBrackets.ReplaceAllString(host, "")
|
|
return net.JoinHostPort(host, port)
|
|
}
|
|
|
|
// SplitHostPort splits a network address of the form "host:port", "host%zone:port", "[host]:port" or "[host%zone]:port" into host or host%zone and port.
|
|
//
|
|
// A literal IPv6 address in hostport must be enclosed in square brackets, as in "[::1]:80", "[::1%lo0]:80".
|
|
func SplitHostPort(hostport string) (host string, port string, err error) {
|
|
host, port, err = net.SplitHostPort(hostport)
|
|
// use the hostport value as a backup when we have a missing port error
|
|
if err != nil && strings.Contains(err.Error(), globals.MissingPortErrStr) {
|
|
// incase the hostport value is an ipv6, we must remove the enclosed square
|
|
// brackets to retain the same behavior as the net.SplitHostPort() method
|
|
host = squareBrackets.ReplaceAllString(hostport, "")
|
|
err = nil
|
|
}
|
|
return
|
|
}
|
|
|
|
// ParseAddress trims and validates the input address string. It checks whether
|
|
// the address is within the allowed length and attempts to split it into a host and
|
|
// port. If the address contains a port, it returns an error. The function supports
|
|
// both valid IP addresses (IPv4 or IPv6) and DNS names. If the address is valid
|
|
// and does not include a port, it returns the host (either an IP or a DNS name).
|
|
func ParseAddress(ctx context.Context, address string) (string, error) {
|
|
const op = "util.ParseAddress"
|
|
address = strings.TrimSpace(address)
|
|
if len(address) < MinAddressLength || len(address) > MaxAddressLength {
|
|
return "", errors.New("invalid address length")
|
|
}
|
|
host, port, err := SplitHostPort(address)
|
|
if err != nil {
|
|
ip := net.ParseIP(address)
|
|
if ip.To4() == nil && ip.To16() == nil {
|
|
return "", err
|
|
}
|
|
host = ip.String()
|
|
}
|
|
if port != "" {
|
|
return "", errors.New("address contains a port")
|
|
}
|
|
return host, nil
|
|
}
|