osbase/net/dump: correct address prefixes if not on-link
Currently if an interface address has an on-link prefix (i.e. is not a
/32 or /128) this gets automatically added as a route. Certain
in-the-wild configs have these but also a route with a gateway, making
the prefix not on-link. Fix the interface addresses in these cases to a
single IP to avoid the spurious on-link route.
Change-Id: If601c61cbbab7f05e72c7f4908071def2dcdb44b
Reviewed-on: https://review.monogon.dev/c/monogon/+/3771
Reviewed-by: Leopold Schabel <leo@monogon.tech>
Tested-by: Jenkins CI
diff --git a/build/bazel/go.MODULE.bazel b/build/bazel/go.MODULE.bazel
index 0dee36f..1a9285f 100644
--- a/build/bazel/go.MODULE.bazel
+++ b/build/bazel/go.MODULE.bazel
@@ -88,6 +88,7 @@
"io_k8s_kubernetes",
"io_k8s_pod_security_admission",
"io_k8s_utils",
+ "org_go4_netipx",
"org_golang_google_api",
"org_golang_google_genproto_googleapis_api",
"org_golang_google_grpc",
diff --git a/go.mod b/go.mod
index c850dc8..bfa5c0e 100644
--- a/go.mod
+++ b/go.mod
@@ -122,6 +122,7 @@
go.etcd.io/etcd/tests/v3 v3.5.13
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
+ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/crypto v0.28.0
golang.org/x/net v0.30.0
golang.org/x/sync v0.8.0
diff --git a/go.sum b/go.sum
index 94e127d..3b5885c 100644
--- a/go.sum
+++ b/go.sum
@@ -3717,6 +3717,8 @@
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
+go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI=
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
diff --git a/osbase/net/dump/BUILD.bazel b/osbase/net/dump/BUILD.bazel
index 3175e4e..a3e38de 100644
--- a/osbase/net/dump/BUILD.bazel
+++ b/osbase/net/dump/BUILD.bazel
@@ -11,6 +11,7 @@
deps = [
"//osbase/net/proto",
"@com_github_vishvananda_netlink//:netlink",
+ "@org_go4_netipx//:netipx",
"@org_golang_x_sys//unix",
],
)
diff --git a/osbase/net/dump/netdump.go b/osbase/net/dump/netdump.go
index c3bf9f7..7ea9ae2 100644
--- a/osbase/net/dump/netdump.go
+++ b/osbase/net/dump/netdump.go
@@ -4,12 +4,14 @@
"bytes"
"fmt"
"math"
+ "net/netip"
"os"
"sort"
"strconv"
"strings"
"github.com/vishvananda/netlink"
+ "go4.org/netipx"
"golang.org/x/sys/unix"
netapi "source.monogon.dev/osbase/net/proto"
@@ -28,6 +30,11 @@
protoStatic = 4
)
+type ifaceAddrRef struct {
+ iface *netapi.Interface
+ addrIdx int
+}
+
// Dump dumps the network configuration of the current network namespace into
// a osbase.net.proto.Net structure. This is currently only expected to work for
// systems which do not use a dynamic routing protocol to establish basic
@@ -48,6 +55,8 @@
ifIdxMap := make(map[int]*netapi.Interface)
// Map interface index -> names of children
ifChildren := make(map[int][]string)
+ // Interface address implied on-link routes
+ impliedOnLinkRoutes := make(map[netip.Prefix]ifaceAddrRef)
// Map interface index -> number of reverse dependencies
ifNRevDeps := make(map[int]int)
for _, link := range links {
@@ -151,7 +160,17 @@
SourceIp: a.IP.String(),
})
}
- iface.Address = append(iface.Address, a.IPNet.String())
+ ones, bits := a.Mask.Size()
+ baseAddr, ok := netip.AddrFromSlice(a.IP.Mask(a.Mask))
+ prefix := netip.PrefixFrom(baseAddr, ones)
+ if ok && bits != 0 {
+ if !prefix.IsSingleIP() {
+ impliedOnLinkRoutes[prefix] = ifaceAddrRef{iface: &iface, addrIdx: len(iface.Address)}
+ }
+ iface.Address = append(iface.Address, a.IPNet.String())
+ } else {
+ warnings = append(warnings, fmt.Errorf("address %v on %q is invalid, ignoring", a.IPNet, iface.Name))
+ }
}
if linkAttrs.MasterIndex != 0 {
ifChildren[linkAttrs.MasterIndex] = append(ifChildren[linkAttrs.MasterIndex], iface.Name)
@@ -194,6 +213,16 @@
panic("route family changed under us")
}
} else {
+ dst, ok := netipx.FromStdIPNet(r.Dst)
+ if !ok {
+ warnings = append(warnings, fmt.Errorf("route %v invalid, ignoring", r.Dst))
+ }
+ if ref, ok := impliedOnLinkRoutes[dst]; ok && !r.Gw.IsUnspecified() && len(r.Gw) != 0 {
+ // Address is not on-link, remove prefix from address to not
+ // get an improper on-link route.
+ prefix := netip.MustParsePrefix(ref.iface.Address[ref.addrIdx])
+ ref.iface.Address[ref.addrIdx] = netip.PrefixFrom(prefix.Addr(), prefix.Addr().BitLen()).String()
+ }
route.Destination = r.Dst.String()
}
if !r.Gw.IsUnspecified() && len(r.Gw) != 0 {