Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions internal/peer/peers.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,7 @@ func getIdentifierFromInterface(logger logger.Logger, cfg config.Config) (string
Logf("IdentifierInterfaceName set but couldn't list addresses")
return "", err
}
var ipStr string
for _, addr := range addrs {
// ParseIP doesn't know what to do with the suffix
ip := net.ParseIP(strings.Split(addr.String(), "/")[0])
ipv6 := cfg.GetUseIPV6Identifier()
if ipv6 && ip.To16() != nil {
ipStr = fmt.Sprintf("[%s]", ip.String())
break
}
if !ipv6 && ip.To4() != nil {
ipStr = ip.String()
break
}
}
ipStr := selectIPFromAddrs(addrs, cfg.GetUseIPV6Identifier())
if ipStr == "" {
err = errors.New("could not find a valid IP to use from interface")
logger.Error().WithField("interface", ifc.Name).
Expand All @@ -99,3 +86,19 @@ func getIdentifierFromInterface(logger logger.Logger, cfg config.Config) (string

return myIdentifier, nil
}

// selectIPFromAddrs selects an IP address from a list of network addresses.
// If useIPV6 is true, it returns the first IPv6 address wrapped in brackets.
// If useIPV6 is false, it returns the first IPv4 address.
func selectIPFromAddrs(addrs []net.Addr, useIPV6 bool) string {
for _, addr := range addrs {
ip := net.ParseIP(strings.Split(addr.String(), "/")[0])
if useIPV6 && ip.To4() == nil {
return fmt.Sprintf("[%s]", ip.String())
}
if !useIPV6 && ip.To4() != nil {
return ip.String()
}
}
return ""
}
78 changes: 78 additions & 0 deletions internal/peer/peers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package peer
import (
"errors"
"fmt"
"net"
"os"
"strings"
"testing"
Expand Down Expand Up @@ -115,3 +116,80 @@ func TestPeerShutdown(t *testing.T) {
return len(peers) == 1
}, 5*time.Second, 200*time.Millisecond)
}

// mockAddr implements net.Addr for testing
type mockAddr struct {
addr string
}

func (m mockAddr) Network() string { return "ip" }
func (m mockAddr) String() string { return m.addr }

func TestSelectIPFromAddrs(t *testing.T) {
tests := []struct {
name string
addrs []net.Addr
useIPV6 bool
expected string
}{
{
name: "IPv4 only, useIPV6=false, should return IPv4",
addrs: []net.Addr{
mockAddr{"100.122.159.209/18"},
},
useIPV6: false,
expected: "100.122.159.209",
},
{
name: "IPv4 only, useIPV6=true, should return empty (no IPv6 available)",
addrs: []net.Addr{
mockAddr{"100.122.159.209/18"},
},
useIPV6: true,
expected: "",
},
{
name: "IPv6 only, useIPV6=true, should return bracketed IPv6",
addrs: []net.Addr{
mockAddr{"2600:1f18:2772:d500:a772:1d0e:8ef5:93de/128"},
},
useIPV6: true,
expected: "[2600:1f18:2772:d500:a772:1d0e:8ef5:93de]",
},
{
name: "IPv6 only, useIPV6=false, should return empty (no IPv4 available)",
addrs: []net.Addr{
mockAddr{"2600:1f18:2772:d500:a772:1d0e:8ef5:93de/128"},
},
useIPV6: false,
expected: "",
},
{
name: "Mixed IPv4 and IPv6, useIPV6=false, should return IPv4",
addrs: []net.Addr{
mockAddr{"100.122.159.209/18"},
mockAddr{"2600:1f18:2772:d500:a772:1d0e:8ef5:93de/128"},
mockAddr{"fe80::514d:14e3:9e02:b884/64"},
},
useIPV6: false,
expected: "100.122.159.209",
},
{
name: "Mixed IPv4 and IPv6, useIPV6=true, should return bracketed IPv6 (not bracketed IPv4)",
addrs: []net.Addr{
mockAddr{"100.122.159.209/18"},
mockAddr{"2600:1f18:2772:d500:a772:1d0e:8ef5:93de/128"},
mockAddr{"fe80::514d:14e3:9e02:b884/64"},
},
useIPV6: true,
expected: "[2600:1f18:2772:d500:a772:1d0e:8ef5:93de]",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := selectIPFromAddrs(tt.addrs, tt.useIPV6)
assert.Equal(t, tt.expected, result)
})
}
}