/* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved. */ package tunnel import ( "sync" "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" ) func findDefaultRoute(family winipcfg.AddressFamily, ourLUID winipcfg.LUID) (winipcfg.LUID, uint32, error) { r, err := winipcfg.GetIPForwardTable2(family) if err != nil { return 0, 0, err } lowestMetric := ^uint64(0) index := uint32(0) luid := winipcfg.LUID(0) for i := range r { if r[i].DestinationPrefix.PrefixLength != 0 || r[i].InterfaceLUID == ourLUID { continue } ifrow, err := r[i].InterfaceLUID.Interface() if err != nil || ifrow.OperStatus != winipcfg.IfOperStatusUp { continue } iface, err := r[i].InterfaceLUID.IPInterface(family) if err != nil { continue } combinedMetric := uint64(r[i].Metric) + uint64(iface.Metric) if combinedMetric < lowestMetric { lowestMetric = combinedMetric index = r[i].InterfaceIndex luid = r[i].InterfaceLUID } } return luid, index, nil } func monitorMTU(family winipcfg.AddressFamily, ourLUID winipcfg.LUID) ([]winipcfg.ChangeCallback, error) { var minMTU int if family == windows.AF_INET { minMTU = 576 } else if family == windows.AF_INET6 { minMTU = 1280 } var mu sync.Mutex lastLUID := winipcfg.LUID(0) lastMTU := uint32(0) doIt := func() error { mu.Lock() defer mu.Unlock() luid, _, err := findDefaultRoute(family, ourLUID) if err != nil { return err } lastLUID = luid mtu := uint32(0) if lastLUID != 0 { iface, err := lastLUID.Interface() if err != nil { return err } if iface.MTU > 0 { mtu = iface.MTU } } if mtu > 0 && lastMTU != mtu { iface, err := ourLUID.IPInterface(family) if err != nil { return err } iface.NLMTU = uint32(max(int(mtu)-80, minMTU)) err = iface.Set() if err != nil { return err } lastMTU = mtu } return nil } err := doIt() if err != nil { return nil, err } cbr, err := winipcfg.RegisterRouteChangeCallback(func(notificationType winipcfg.MibNotificationType, route *winipcfg.MibIPforwardRow2) { if route != nil && route.DestinationPrefix.PrefixLength == 0 { doIt() } }) if err != nil { return nil, err } cbi, err := winipcfg.RegisterInterfaceChangeCallback(func(notificationType winipcfg.MibNotificationType, iface *winipcfg.MibIPInterfaceRow) { if notificationType == winipcfg.MibParameterNotification { doIt() } }) if err != nil { cbr.Unregister() return nil, err } return []winipcfg.ChangeCallback{cbr, cbi}, nil }