Skip to content

Commit 3a551b4

Browse files
Wenriclaude
andcommitted
fix: handle EAFNOSUPPORT in RouteList for Virtuozzo/OpenVZ kernels
Virtuozzo/OpenVZ 3.10.x kernels do not support RTM_GETROUTE dump with AF_UNSPEC, returning EAFNOSUPPORT. This caused netclient to fail on interface configuration and default gateway detection, preventing the daemon from applying any peer updates. Add routeListAll and routeListFilteredAll helpers that try FAMILY_ALL first and fall back to querying FAMILY_V4 and FAMILY_V6 separately. Also set WG_QUICK_USERSPACE_IMPLEMENTATION in Dockerfile. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 13a39d5 commit 3a551b4

2 files changed

Lines changed: 43 additions & 3 deletions

File tree

Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ COPY --from=builder /app/netclient-app ./netclient
3131
COPY --from=builder /app/scripts/netclient.sh .
3232
RUN chmod 0755 netclient && chmod 0755 netclient.sh
3333

34+
ENV WG_QUICK_USERSPACE_IMPLEMENTATION=wireguard-go
35+
3436
ENTRYPOINT ["/bin/bash", "./netclient.sh"]

wireguard/wireguard_linux.go

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func (nc *NCIface) ApplyAddrs() error {
117117
if err != nil {
118118
return err
119119
}
120-
routes, err := netlink.RouteList(l, 0)
120+
routes, err := routeListAll(l)
121121
if err != nil {
122122
return err
123123
}
@@ -213,7 +213,7 @@ func GetDefaultGatewayIp() (ip net.IP, err error) {
213213
//build the gateway route, with Table ROUTE_TABLE_NAME, metric 1
214214
tRoute := netlink.Route{Dst: nil, Table: RouteTableName}
215215
//Check if table ROUTE_TABLE_NAME existed
216-
routes, _ := netlink.RouteListFiltered(netlink.FAMILY_ALL, &tRoute, netlink.RT_FILTER_TABLE)
216+
routes, _ := routeListFilteredAll(&tRoute, netlink.RT_FILTER_TABLE)
217217
if len(routes) == 1 {
218218
return routes[0].Gw, nil
219219
} else if len(routes) > 1 {
@@ -273,7 +273,7 @@ func GetDefaultGatewayV6() (gwRoute netlink.Route, err error) {
273273
func GetDefaultGateway() (gwRoute netlink.Route, err error) {
274274

275275
//get the present route list
276-
routes, err := netlink.RouteList(nil, netlink.FAMILY_ALL)
276+
routes, err := routeListAll(nil)
277277
if err != nil {
278278
slog.Error("error loading route tables", "error", err.Error())
279279
return gwRoute, err
@@ -711,6 +711,44 @@ func restoreInternetGwV4() (err error) {
711711
return config.WriteNetclientConfig()
712712
}
713713

714+
// routeListAll returns routes for all address families.
715+
// Some kernels (notably Virtuozzo/OpenVZ 3.10.x) do not support RTM_GETROUTE
716+
// dump with AF_UNSPEC, returning EAFNOSUPPORT. In that case, query V4 and V6
717+
// separately and merge the results.
718+
func routeListAll(link netlink.Link) ([]netlink.Route, error) {
719+
routes, err := netlink.RouteList(link, netlink.FAMILY_ALL)
720+
if err == nil {
721+
return routes, nil
722+
}
723+
if !errors.Is(err, unix.EAFNOSUPPORT) {
724+
return nil, err
725+
}
726+
v4, err4 := netlink.RouteList(link, netlink.FAMILY_V4)
727+
if err4 != nil {
728+
return nil, err4
729+
}
730+
v6, _ := netlink.RouteList(link, netlink.FAMILY_V6)
731+
return append(v4, v6...), nil
732+
}
733+
734+
// routeListFilteredAll is like netlink.RouteListFiltered but falls back to
735+
// querying V4 and V6 separately when AF_UNSPEC is not supported.
736+
func routeListFilteredAll(filter *netlink.Route, filterMask uint64) ([]netlink.Route, error) {
737+
routes, err := netlink.RouteListFiltered(netlink.FAMILY_ALL, filter, filterMask)
738+
if err == nil {
739+
return routes, nil
740+
}
741+
if !errors.Is(err, unix.EAFNOSUPPORT) {
742+
return nil, err
743+
}
744+
v4, err4 := netlink.RouteListFiltered(netlink.FAMILY_V4, filter, filterMask)
745+
if err4 != nil {
746+
return nil, err4
747+
}
748+
v6, _ := netlink.RouteListFiltered(netlink.FAMILY_V6, filter, filterMask)
749+
return append(v4, v6...), nil
750+
}
751+
714752
// == private ==
715753

716754
type netLink struct {

0 commit comments

Comments
 (0)