UPnP/SSDP: prefer link-local addresses if available
This commit is contained in:
parent
fca628b325
commit
bb91c2e6d6
@ -78,16 +78,10 @@ func networkInterfaces(includeLinkLocal, includeLocalhost bool) ([]net.IP, error
|
|||||||
Str("iface", iface.Name).
|
Str("iface", iface.Name).
|
||||||
Logger()
|
Logger()
|
||||||
switch {
|
switch {
|
||||||
case ip.IsMulticast():
|
|
||||||
logger.Debug().Msg(" - skipping multicast")
|
|
||||||
case ip.IsMulticast():
|
case ip.IsMulticast():
|
||||||
logger.Debug().Msg(" - skipping multicast")
|
logger.Debug().Msg(" - skipping multicast")
|
||||||
case ip.IsUnspecified():
|
case ip.IsUnspecified():
|
||||||
logger.Debug().Msg(" - skipping unspecified")
|
logger.Debug().Msg(" - skipping unspecified")
|
||||||
case !includeLinkLocal && ip.IsLinkLocalUnicast():
|
|
||||||
logger.Debug().Msg(" - skipping link-local")
|
|
||||||
case !includeLocalhost && ip.IsLoopback():
|
|
||||||
logger.Debug().Msg(" - skipping localhost")
|
|
||||||
default:
|
default:
|
||||||
logger.Debug().Msg(" - usable")
|
logger.Debug().Msg(" - usable")
|
||||||
ifaceAddresses = append(ifaceAddresses, ip)
|
ifaceAddresses = append(ifaceAddresses, ip)
|
||||||
@ -104,26 +98,69 @@ func networkInterfaces(includeLinkLocal, includeLocalhost bool) ([]net.IP, error
|
|||||||
return usableAddresses, nil
|
return usableAddresses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// filterAddresses removes "privacy extension" addresses.
|
// filterAddresses reduces the number of IPv6 addresses.
|
||||||
// It assumes the list of addresses belong to the same network interface, and
|
// It prefers link-local addresses; if these are in the list, all the other IPv6
|
||||||
// that the OS reports preferred (i.e. private/random) addresses before
|
// addresses will be removed. Link-local addresses are stable and meant for
|
||||||
// non-random ones.
|
// same-network connections, which is exactly what Flamenco needs.
|
||||||
|
// Loopback addresses (localhost) are always filtered out, unless they're the only addresses available.
|
||||||
func filterAddresses(addrs []net.IP) []net.IP {
|
func filterAddresses(addrs []net.IP) []net.IP {
|
||||||
keep := make([]net.IP, 0)
|
keepAddrs := make([]net.IP, 0)
|
||||||
|
|
||||||
var lastSeenIP net.IP
|
if hasOnlyLoopback(addrs) {
|
||||||
|
return addrs
|
||||||
|
}
|
||||||
|
|
||||||
|
var keepLinkLocalv6 = hasLinkLocalv6(addrs)
|
||||||
|
var keepLinkLocalv4 = hasLinkLocalv4(addrs)
|
||||||
|
|
||||||
|
var keep bool
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
if addr.To4() != nil {
|
if addr.IsLoopback() {
|
||||||
// IPv4 addresses are always kept.
|
|
||||||
keep = append(keep, addr)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
lastSeenIP = addr
|
isv4 := isIPv4(addr)
|
||||||
}
|
if isv4 {
|
||||||
if len(lastSeenIP) > 0 {
|
keep = keepLinkLocalv4 == addr.IsLinkLocalUnicast()
|
||||||
keep = append(keep, lastSeenIP)
|
} else {
|
||||||
|
keep = keepLinkLocalv6 == addr.IsLinkLocalUnicast()
|
||||||
}
|
}
|
||||||
|
|
||||||
return keep
|
if keep {
|
||||||
|
keepAddrs = append(keepAddrs, addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keepAddrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func isIPv4(addr net.IP) bool {
|
||||||
|
return addr.To4() != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasLinkLocalv6(addrs []net.IP) bool {
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if !isIPv4(addr) && addr.IsLinkLocalUnicast() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasLinkLocalv4(addrs []net.IP) bool {
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if isIPv4(addr) && addr.IsLinkLocalUnicast() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasOnlyLoopback(addrs []net.IP) bool {
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if !addr.IsLoopback() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
76
internal/own_url/interfaces_test.go
Normal file
76
internal/own_url/interfaces_test.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package own_url
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
globalIPv6 = net.ParseIP("2a10:3780:2:52:185:93:175:46")
|
||||||
|
lanIPv6 = globalIPv6
|
||||||
|
linkLocalIPv6 = net.ParseIP("fe80::5054:ff:fede:2ad7")
|
||||||
|
localhostIPv6 = net.ParseIP("::1")
|
||||||
|
|
||||||
|
globalIPv4 = net.ParseIP("8.8.8.8")
|
||||||
|
lanIPv4 = net.ParseIP("192.168.0.1")
|
||||||
|
linkLocalIPv4 = net.ParseIP("169.254.47.42")
|
||||||
|
localhostIPv4 = net.ParseIP("127.0.0.1")
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_filterAddresses(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
expect []net.IP
|
||||||
|
input []net.IP
|
||||||
|
}{
|
||||||
|
// IPv6 tests:
|
||||||
|
// Not a link-local address present, then use all but localhost
|
||||||
|
{"IPv6 without link-local",
|
||||||
|
[]net.IP{globalIPv6, lanIPv6},
|
||||||
|
[]net.IP{globalIPv6, lanIPv6, localhostIPv6}},
|
||||||
|
// Link-local address present, just use that one.
|
||||||
|
{"IPv6 with link-local",
|
||||||
|
[]net.IP{linkLocalIPv6},
|
||||||
|
[]net.IP{linkLocalIPv6, lanIPv6, localhostIPv6}},
|
||||||
|
// Only loopback
|
||||||
|
{"IPv6 with only loopback",
|
||||||
|
[]net.IP{localhostIPv6},
|
||||||
|
[]net.IP{localhostIPv6}},
|
||||||
|
|
||||||
|
// IPv4 tests:
|
||||||
|
// Not a link-local address present, then use all but localhost
|
||||||
|
{"IPv4 without link-local",
|
||||||
|
[]net.IP{globalIPv4, lanIPv4},
|
||||||
|
[]net.IP{globalIPv4, lanIPv4, localhostIPv4}},
|
||||||
|
// Link-local address present, just use that one.
|
||||||
|
{"IPv4 with link-local",
|
||||||
|
[]net.IP{linkLocalIPv4},
|
||||||
|
[]net.IP{linkLocalIPv4, lanIPv4, localhostIPv4}},
|
||||||
|
// Only loopback
|
||||||
|
{"IPv4 with only loopback",
|
||||||
|
[]net.IP{localhostIPv4},
|
||||||
|
[]net.IP{localhostIPv4}},
|
||||||
|
|
||||||
|
// Mixed IPv4/IPv6 tests:
|
||||||
|
// IPv4 no link-local, but IPv6 with link-local:
|
||||||
|
{"IPv4 w/o, IPv6 w/ link-local",
|
||||||
|
[]net.IP{lanIPv4, linkLocalIPv6},
|
||||||
|
[]net.IP{lanIPv4, localhostIPv4, lanIPv6, linkLocalIPv6}},
|
||||||
|
// IPv4 link-local, IPv6 without:
|
||||||
|
{"IPv4 w/, IPv4 w/o link-local",
|
||||||
|
[]net.IP{linkLocalIPv4, lanIPv6},
|
||||||
|
[]net.IP{linkLocalIPv4, lanIPv4, lanIPv6}},
|
||||||
|
// Only loopback
|
||||||
|
{"IPv4 + IPv6 with only loopback",
|
||||||
|
[]net.IP{localhostIPv4, localhostIPv6},
|
||||||
|
[]net.IP{localhostIPv4, localhostIPv6}},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
got := filterAddresses(tt.input)
|
||||||
|
assert.EqualValues(t, tt.expect, got, "for test %q", tt.name)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user