You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
boundary/internal/util/net.go

73 lines
2.5 KiB

// 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
}