81 lines
2.2 KiB
Go
81 lines
2.2 KiB
Go
// Package route owns RemLink Remote routes and performs conflict/lookup checks.
|
|
package route
|
|
|
|
import (
|
|
"errors"
|
|
"net/netip"
|
|
|
|
"remlink/internal/platform/windows/netinfo"
|
|
)
|
|
|
|
type LookupResult string
|
|
|
|
const (
|
|
LookupDirect LookupResult = "DIRECT"
|
|
LookupRouted LookupResult = "ROUTED"
|
|
LookupDefaultOnly LookupResult = "DEFAULT_ONLY"
|
|
LookupNoRoute LookupResult = "NO_ROUTE"
|
|
LookupOverlayConflict LookupResult = "OVERLAY_CONFLICT"
|
|
)
|
|
|
|
type Entry struct {
|
|
InterfaceLUID uint64
|
|
Destination netip.Prefix
|
|
NextHop netip.Addr
|
|
}
|
|
|
|
// ConflictsFrom applies the Engineer rule: ignore default and RemLink-owned
|
|
// routes, reject any other prefix overlap.
|
|
func ConflictsFrom(entries []Entry, desired netip.Prefix, remLinkLUID uint64) []Entry {
|
|
var conflicts []Entry
|
|
for _, entry := range entries {
|
|
if entry.InterfaceLUID == remLinkLUID || !entry.Destination.Addr().Is4() || entry.Destination.Bits() == 0 {
|
|
continue
|
|
}
|
|
if netinfo.PrefixesOverlap(desired, entry.Destination) {
|
|
conflicts = append(conflicts, entry)
|
|
}
|
|
}
|
|
return conflicts
|
|
}
|
|
|
|
// LookupFrom returns the most-specific Windows route classification used by Site PREPARE.
|
|
func LookupFrom(entries []Entry, target netip.Addr, overlay netip.Prefix, remLinkLUID uint64) LookupResult {
|
|
if !target.Is4() {
|
|
return LookupNoRoute
|
|
}
|
|
if overlay.Contains(target) {
|
|
return LookupOverlayConflict
|
|
}
|
|
var best *Entry
|
|
for index := range entries {
|
|
entry := &entries[index]
|
|
if !entry.Destination.Contains(target) || entry.InterfaceLUID == remLinkLUID {
|
|
continue
|
|
}
|
|
if best == nil || entry.Destination.Bits() > best.Destination.Bits() {
|
|
best = entry
|
|
}
|
|
}
|
|
if best == nil {
|
|
return LookupNoRoute
|
|
}
|
|
if best.Destination.Bits() == 0 {
|
|
return LookupDefaultOnly
|
|
}
|
|
if !best.NextHop.IsValid() || best.NextHop.IsUnspecified() {
|
|
return LookupDirect
|
|
}
|
|
return LookupRouted
|
|
}
|
|
|
|
func validateRemote(prefix, overlay netip.Prefix) error {
|
|
if !prefix.Addr().Is4() || prefix != prefix.Masked() || prefix.Bits() == 0 {
|
|
return errors.New("Remote CIDR must be canonical IPv4 and must not be 0.0.0.0/0")
|
|
}
|
|
if netinfo.PrefixesOverlap(prefix, overlay) {
|
|
return errors.New("Remote CIDR overlaps Overlay CIDR")
|
|
}
|
|
return nil
|
|
}
|