初版功能完成
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user