mirror of
https://github.com/status-im/consul.git
synced 2025-01-10 05:45:46 +00:00
5fb9df1640
* Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at <Blog URL>, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
167 lines
6.3 KiB
Go
167 lines
6.3 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package agent
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
)
|
|
|
|
type TranslateAddressAccept int
|
|
|
|
const (
|
|
TranslateAddressAcceptDomain TranslateAddressAccept = 1 << iota
|
|
TranslateAddressAcceptIPv4
|
|
TranslateAddressAcceptIPv6
|
|
|
|
TranslateAddressAcceptAny TranslateAddressAccept = ^0
|
|
)
|
|
|
|
// TranslateServicePort is used to provide the final, translated port for a service,
|
|
// depending on how the agent and the other node are configured. The dc
|
|
// parameter is the dc the datacenter this node is from.
|
|
func (a *Agent) TranslateServicePort(dc string, port int, taggedAddresses map[string]structs.ServiceAddress) int {
|
|
if a.config.TranslateWANAddrs && (a.config.Datacenter != dc) {
|
|
if wanAddr, ok := taggedAddresses[structs.TaggedAddressWAN]; ok && wanAddr.Port != 0 {
|
|
return wanAddr.Port
|
|
}
|
|
}
|
|
return port
|
|
}
|
|
|
|
// TranslateServiceAddress is used to provide the final, translated address for a node,
|
|
// depending on how the agent and the other node are configured. The dc
|
|
// parameter is the dc the datacenter this node is from.
|
|
func (a *Agent) TranslateServiceAddress(dc string, addr string, taggedAddresses map[string]structs.ServiceAddress, accept TranslateAddressAccept) string {
|
|
def := addr
|
|
v4 := taggedAddresses[structs.TaggedAddressLANIPv4].Address
|
|
v6 := taggedAddresses[structs.TaggedAddressLANIPv6].Address
|
|
|
|
shouldUseWan := a.config.TranslateWANAddrs && (a.config.Datacenter != dc)
|
|
if shouldUseWan {
|
|
if v, ok := taggedAddresses[structs.TaggedAddressWAN]; ok {
|
|
def = v.Address
|
|
}
|
|
if v, ok := taggedAddresses[structs.TaggedAddressWANIPv4]; ok {
|
|
v4 = v.Address
|
|
}
|
|
if v, ok := taggedAddresses[structs.TaggedAddressWANIPv6]; ok {
|
|
v6 = v.Address
|
|
}
|
|
}
|
|
|
|
return translateAddressAccept(accept, def, v4, v6)
|
|
}
|
|
|
|
// TranslateAddress is used to provide the final, translated address for a node,
|
|
// depending on how the agent and the other node are configured. The dc
|
|
// parameter is the dc the datacenter this node is from.
|
|
func (a *Agent) TranslateAddress(dc string, addr string, taggedAddresses map[string]string, accept TranslateAddressAccept) string {
|
|
def := addr
|
|
v4 := taggedAddresses[structs.TaggedAddressLANIPv4]
|
|
v6 := taggedAddresses[structs.TaggedAddressLANIPv6]
|
|
|
|
shouldUseWan := a.config.TranslateWANAddrs && (a.config.Datacenter != dc)
|
|
if shouldUseWan {
|
|
if v, ok := taggedAddresses[structs.TaggedAddressWAN]; ok {
|
|
def = v
|
|
}
|
|
if v, ok := taggedAddresses[structs.TaggedAddressWANIPv4]; ok {
|
|
v4 = v
|
|
}
|
|
if v, ok := taggedAddresses[structs.TaggedAddressWANIPv6]; ok {
|
|
v6 = v
|
|
}
|
|
}
|
|
|
|
return translateAddressAccept(accept, def, v4, v6)
|
|
}
|
|
|
|
func translateAddressAccept(accept TranslateAddressAccept, def, v4, v6 string) string {
|
|
switch {
|
|
case accept&TranslateAddressAcceptIPv6 > 0 && v6 != "":
|
|
return v6
|
|
case accept&TranslateAddressAcceptIPv4 > 0 && v4 != "":
|
|
return v4
|
|
case accept&TranslateAddressAcceptAny > 0 && def != "":
|
|
return def
|
|
default:
|
|
defIP := net.ParseIP(def)
|
|
switch {
|
|
case defIP != nil && defIP.To4() != nil && accept&TranslateAddressAcceptIPv4 > 0:
|
|
return def
|
|
case defIP != nil && defIP.To4() == nil && accept&TranslateAddressAcceptIPv6 > 0:
|
|
return def
|
|
case defIP == nil && accept&TranslateAddressAcceptDomain > 0:
|
|
return def
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// TranslateAddresses translates addresses in the given structure into the
|
|
// final, translated address, depending on how the agent and the other node are
|
|
// configured. The dc parameter is the datacenter this structure is from.
|
|
func (a *Agent) TranslateAddresses(dc string, subj interface{}, accept TranslateAddressAccept) {
|
|
// CAUTION - SUBTLE! An agent running on a server can, in some cases,
|
|
// return pointers directly into the immutable state store for
|
|
// performance (it's via the in-memory RPC mechanism). It's never safe
|
|
// to modify those values, so we short circuit here so that we never
|
|
// update any structures that are from our own datacenter. This works
|
|
// for address translation because we *never* need to translate local
|
|
// addresses, but this is super subtle, so we've piped all the in-place
|
|
// address translation into this function which makes sure this check is
|
|
// done. This also happens to skip looking at any of the incoming
|
|
// structure for the common case of not needing to translate, so it will
|
|
// skip a lot of work if no translation needs to be done.
|
|
if !a.config.TranslateWANAddrs || (a.config.Datacenter == dc) {
|
|
return
|
|
}
|
|
|
|
// Translate addresses in-place, subject to the condition checked above
|
|
// which ensures this is safe to do since we are operating on a local
|
|
// copy of the data.
|
|
switch v := subj.(type) {
|
|
case structs.CheckServiceNodes:
|
|
for _, entry := range v {
|
|
entry.Node.Address = a.TranslateAddress(dc, entry.Node.Address, entry.Node.TaggedAddresses, accept)
|
|
entry.Service.Address = a.TranslateServiceAddress(dc, entry.Service.Address, entry.Service.TaggedAddresses, accept)
|
|
entry.Service.Port = a.TranslateServicePort(dc, entry.Service.Port, entry.Service.TaggedAddresses)
|
|
}
|
|
case *structs.Node:
|
|
v.Address = a.TranslateAddress(dc, v.Address, v.TaggedAddresses, accept)
|
|
case structs.Nodes:
|
|
for _, node := range v {
|
|
node.Address = a.TranslateAddress(dc, node.Address, node.TaggedAddresses, accept)
|
|
}
|
|
case structs.ServiceNodes:
|
|
for _, entry := range v {
|
|
entry.Address = a.TranslateAddress(dc, entry.Address, entry.TaggedAddresses, accept)
|
|
entry.ServiceAddress = a.TranslateServiceAddress(dc, entry.ServiceAddress, entry.ServiceTaggedAddresses, accept)
|
|
entry.ServicePort = a.TranslateServicePort(dc, entry.ServicePort, entry.ServiceTaggedAddresses)
|
|
}
|
|
case *structs.NodeServices:
|
|
if v.Node != nil {
|
|
v.Node.Address = a.TranslateAddress(dc, v.Node.Address, v.Node.TaggedAddresses, accept)
|
|
}
|
|
for _, entry := range v.Services {
|
|
entry.Address = a.TranslateServiceAddress(dc, entry.Address, entry.TaggedAddresses, accept)
|
|
entry.Port = a.TranslateServicePort(dc, entry.Port, entry.TaggedAddresses)
|
|
}
|
|
case *structs.NodeServiceList:
|
|
if v.Node != nil {
|
|
v.Node.Address = a.TranslateAddress(dc, v.Node.Address, v.Node.TaggedAddresses, accept)
|
|
}
|
|
for _, entry := range v.Services {
|
|
entry.Address = a.TranslateServiceAddress(dc, entry.Address, entry.TaggedAddresses, accept)
|
|
entry.Port = a.TranslateServicePort(dc, entry.Port, entry.TaggedAddresses)
|
|
}
|
|
default:
|
|
panic(fmt.Errorf("Unhandled type passed to address translator: %#v", subj))
|
|
}
|
|
}
|