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).
|
||||
Logger()
|
||||
switch {
|
||||
case ip.IsMulticast():
|
||||
logger.Debug().Msg(" - skipping multicast")
|
||||
case ip.IsMulticast():
|
||||
logger.Debug().Msg(" - skipping multicast")
|
||||
case ip.IsUnspecified():
|
||||
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:
|
||||
logger.Debug().Msg(" - usable")
|
||||
ifaceAddresses = append(ifaceAddresses, ip)
|
||||
@ -104,26 +98,69 @@ func networkInterfaces(includeLinkLocal, includeLocalhost bool) ([]net.IP, error
|
||||
return usableAddresses, nil
|
||||
}
|
||||
|
||||
// filterAddresses removes "privacy extension" addresses.
|
||||
// It assumes the list of addresses belong to the same network interface, and
|
||||
// that the OS reports preferred (i.e. private/random) addresses before
|
||||
// non-random ones.
|
||||
// filterAddresses reduces the number of IPv6 addresses.
|
||||
// It prefers link-local addresses; if these are in the list, all the other IPv6
|
||||
// addresses will be removed. Link-local addresses are stable and meant for
|
||||
// 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 {
|
||||
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 {
|
||||
if addr.To4() != nil {
|
||||
// IPv4 addresses are always kept.
|
||||
keep = append(keep, addr)
|
||||
if addr.IsLoopback() {
|
||||
continue
|
||||
}
|
||||
|
||||
lastSeenIP = addr
|
||||
}
|
||||
if len(lastSeenIP) > 0 {
|
||||
keep = append(keep, lastSeenIP)
|
||||
isv4 := isIPv4(addr)
|
||||
if isv4 {
|
||||
keep = keepLinkLocalv4 == addr.IsLinkLocalUnicast()
|
||||
} else {
|
||||
keep = keepLinkLocalv6 == addr.IsLinkLocalUnicast()
|
||||
}
|
||||
|
||||
if keep {
|
||||
keepAddrs = append(keepAddrs, addr)
|
||||
}
|
||||
}
|
||||
|
||||
return keep
|
||||
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