mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-15 22:10:26 +00:00
https://github.com/XTLS/Xray-core/pull/6691#issuecomment-5445818753 Closes https://github.com/XTLS/Xray-core/issues/5594#issuecomment-4789101025
151 lines
4.3 KiB
Go
151 lines
4.3 KiB
Go
//go:build freebsd
|
|
|
|
package tun
|
|
|
|
import (
|
|
"net/netip"
|
|
"testing"
|
|
|
|
"golang.org/x/net/route"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func TestSelectFreeBSDGatewayDefault(t *testing.T) {
|
|
gateway, local, err := selectFreeBSDGateway(nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if gateway != netip.MustParsePrefix(defaultFreeBSDGateway) {
|
|
t.Fatal("expected default gateway, got ", gateway)
|
|
}
|
|
if local != netip.MustParseAddr("169.254.10.2") {
|
|
t.Fatal("wrong local address: ", local)
|
|
}
|
|
}
|
|
|
|
func TestSelectFreeBSDGatewayPicksFirstIPv4(t *testing.T) {
|
|
gateway, local, err := selectFreeBSDGateway([]string{"fd00::1/64", "10.0.0.1/30", "10.9.9.9/24"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if gateway != netip.MustParsePrefix("10.0.0.1/30") {
|
|
t.Fatal("wrong gateway: ", gateway)
|
|
}
|
|
if local != netip.MustParseAddr("10.0.0.2") {
|
|
t.Fatal("wrong local address: ", local)
|
|
}
|
|
}
|
|
|
|
func TestSelectFreeBSDGatewayRequiresIPv4(t *testing.T) {
|
|
if _, _, err := selectFreeBSDGateway([]string{"fd00::1/64"}); err == nil {
|
|
t.Fatal("expected error when no IPv4 gateway is configured")
|
|
}
|
|
}
|
|
|
|
func TestSelectFreeBSDGatewayRejectsGarbage(t *testing.T) {
|
|
if _, _, err := selectFreeBSDGateway([]string{"not-a-prefix"}); err == nil {
|
|
t.Fatal("expected error for invalid gateway")
|
|
}
|
|
}
|
|
|
|
func TestSelectFreeBSDGatewayRejectsFullPrefix(t *testing.T) {
|
|
// 10.0.0.255/30: the "next" local address falls outside the prefix
|
|
if _, _, err := selectFreeBSDGateway([]string{"10.0.0.255/30"}); err == nil {
|
|
t.Fatal("expected error when no usable local address follows the gateway")
|
|
}
|
|
}
|
|
|
|
func TestNextLocalIPv4(t *testing.T) {
|
|
local, ok := nextLocalIPv4(netip.MustParsePrefix("169.254.10.1/30"))
|
|
if !ok || local != netip.MustParseAddr("169.254.10.2") {
|
|
t.Fatal("wrong local address: ", local)
|
|
}
|
|
}
|
|
|
|
func TestBuildSystemRoutesSplitsDefault(t *testing.T) {
|
|
routes, err := buildSystemRoutes([]string{"0.0.0.0/0"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := []string{
|
|
"1.0.0.0/8", "2.0.0.0/7", "4.0.0.0/6", "8.0.0.0/5",
|
|
"16.0.0.0/4", "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/1",
|
|
}
|
|
if len(routes) != len(expected) {
|
|
t.Fatal("expected ", len(expected), " routes, got ", routes)
|
|
}
|
|
for i, want := range expected {
|
|
if routes[i] != netip.MustParsePrefix(want) {
|
|
t.Fatal("route ", i, ": expected ", want, ", got ", routes[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBuildSystemRoutesSplitsDefaultIPv6(t *testing.T) {
|
|
routes, err := buildSystemRoutes([]string{"::/0"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(routes) != 8 || routes[7] != netip.MustParsePrefix("8000::/1") {
|
|
t.Fatal("unexpected v6 split: ", routes)
|
|
}
|
|
}
|
|
|
|
func TestBuildSystemRoutesDeduplicates(t *testing.T) {
|
|
routes, err := buildSystemRoutes([]string{"10.0.0.0/8", "10.1.2.3/8", "0.0.0.0/0", "0.0.0.0/0"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(routes) != 9 { // 10.0.0.0/8 once + 8 splits once
|
|
t.Fatal("expected 9 routes, got ", routes)
|
|
}
|
|
}
|
|
|
|
func TestBuildSystemRoutesRejectsGarbage(t *testing.T) {
|
|
if _, err := buildSystemRoutes([]string{"10.0.0.0/33"}); err == nil {
|
|
t.Fatal("expected error for invalid route")
|
|
}
|
|
}
|
|
|
|
func routeMessage(dst, mask route.Addr) *route.RouteMessage {
|
|
addrs := make([]route.Addr, unix.RTAX_NETMASK+1)
|
|
addrs[unix.RTAX_DST] = dst
|
|
addrs[unix.RTAX_NETMASK] = mask
|
|
return &route.RouteMessage{Addrs: addrs}
|
|
}
|
|
|
|
func TestDefaultRouteFamilyMatchesIPv4Default(t *testing.T) {
|
|
family, ok := defaultRouteFamily(routeMessage(&route.Inet4Addr{}, &route.Inet4Addr{}))
|
|
if !ok || family != unix.AF_INET {
|
|
t.Fatal("expected IPv4 default route match")
|
|
}
|
|
}
|
|
|
|
func TestDefaultRouteFamilyMatchesIPv6Default(t *testing.T) {
|
|
family, ok := defaultRouteFamily(routeMessage(&route.Inet6Addr{}, &route.Inet6Addr{}))
|
|
if !ok || family != unix.AF_INET6 {
|
|
t.Fatal("expected IPv6 default route match")
|
|
}
|
|
}
|
|
|
|
func TestDefaultRouteFamilyRejectsNonDefault(t *testing.T) {
|
|
if _, ok := defaultRouteFamily(routeMessage(
|
|
&route.Inet4Addr{IP: [4]byte{10, 0, 0, 0}},
|
|
&route.Inet4Addr{IP: [4]byte{255, 0, 0, 0}},
|
|
)); ok {
|
|
t.Fatal("non-default destination must not match")
|
|
}
|
|
if _, ok := defaultRouteFamily(routeMessage(
|
|
&route.Inet4Addr{},
|
|
&route.Inet4Addr{IP: [4]byte{255, 0, 0, 0}},
|
|
)); ok {
|
|
t.Fatal("non-zero mask must not match")
|
|
}
|
|
}
|
|
|
|
func TestDefaultRouteFamilyRejectsShortAddrs(t *testing.T) {
|
|
if _, ok := defaultRouteFamily(&route.RouteMessage{}); ok {
|
|
t.Fatal("message without addresses must not match")
|
|
}
|
|
}
|