75 lines
2.1 KiB
Go
75 lines
2.1 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"net/netip"
|
|
"strings"
|
|
)
|
|
|
|
func normalizeTransportIntent(in TransportPolicyIntent) (TransportPolicyIntent, string, netip.Prefix, error) {
|
|
out := TransportPolicyIntent{
|
|
SelectorType: strings.ToLower(strings.TrimSpace(in.SelectorType)),
|
|
SelectorValue: strings.TrimSpace(in.SelectorValue),
|
|
ClientID: sanitizeID(in.ClientID),
|
|
Priority: in.Priority,
|
|
Mode: strings.ToLower(strings.TrimSpace(in.Mode)),
|
|
}
|
|
if out.ClientID == "" {
|
|
return out, "", netip.Prefix{}, fmt.Errorf("missing client_id")
|
|
}
|
|
if out.Priority <= 0 {
|
|
out.Priority = 100
|
|
}
|
|
if out.Mode == "" {
|
|
out.Mode = "strict"
|
|
}
|
|
if out.Mode != "strict" && out.Mode != "fallback" {
|
|
return out, "", netip.Prefix{}, fmt.Errorf("mode must be strict|fallback")
|
|
}
|
|
switch out.SelectorType {
|
|
case "domain":
|
|
out.SelectorValue = strings.ToLower(out.SelectorValue)
|
|
case "cidr":
|
|
pfx, err := parseIntentCIDR(out.SelectorValue)
|
|
if err != nil {
|
|
return out, "", netip.Prefix{}, err
|
|
}
|
|
out.SelectorValue = pfx.String()
|
|
return out, out.SelectorType + ":" + out.SelectorValue, pfx, nil
|
|
case "app_key", "cgroup", "uid":
|
|
// keep as-is
|
|
default:
|
|
return out, "", netip.Prefix{}, fmt.Errorf("selector_type must be domain|cidr|app_key|cgroup|uid")
|
|
}
|
|
if out.SelectorValue == "" {
|
|
return out, "", netip.Prefix{}, fmt.Errorf("selector_value is empty")
|
|
}
|
|
return out, out.SelectorType + ":" + out.SelectorValue, netip.Prefix{}, nil
|
|
}
|
|
|
|
func parseIntentCIDR(raw string) (netip.Prefix, error) {
|
|
v := strings.TrimSpace(raw)
|
|
if v == "" {
|
|
return netip.Prefix{}, fmt.Errorf("selector_value is empty")
|
|
}
|
|
if strings.Contains(v, "/") {
|
|
pfx, err := netip.ParsePrefix(v)
|
|
if err != nil || !pfx.Addr().Is4() {
|
|
return netip.Prefix{}, fmt.Errorf("invalid cidr: %q", raw)
|
|
}
|
|
return pfx.Masked(), nil
|
|
}
|
|
ip, err := netip.ParseAddr(v)
|
|
if err != nil || !ip.Is4() {
|
|
return netip.Prefix{}, fmt.Errorf("invalid cidr: %q", raw)
|
|
}
|
|
return netip.PrefixFrom(ip, 32), nil
|
|
}
|
|
|
|
func prefixOverlap(a, b netip.Prefix) bool {
|
|
if !a.IsValid() || !b.IsValid() {
|
|
return false
|
|
}
|
|
return a.Contains(b.Addr()) || b.Contains(a.Addr())
|
|
}
|