Files
elmprodvpn/selective-vpn-api/app/traffic_mode_state.go

138 lines
4.3 KiB
Go

package app
import (
"encoding/json"
"os"
trafficmodepkg "selective-vpn-api/app/trafficmode"
"strings"
"time"
)
func normalizeTrafficMode(raw TrafficMode) TrafficMode {
switch strings.ToLower(strings.TrimSpace(string(raw))) {
case string(TrafficModeFullTunnel):
return TrafficModeFullTunnel
case string(TrafficModeDirect):
return TrafficModeDirect
case string(TrafficModeSelective):
return TrafficModeSelective
default:
return TrafficModeSelective
}
}
func normalizePreferredIface(raw string) string {
return trafficmodepkg.NormalizePreferredIface(raw)
}
func tokenizeList(raw []string) []string {
return trafficmodepkg.TokenizeList(raw)
}
func normalizeSubnetList(raw []string) []string {
return trafficmodepkg.NormalizeSubnetList(raw)
}
func normalizeUIDToken(tok string) (string, bool) {
return trafficmodepkg.NormalizeUIDToken(tok)
}
func normalizeUIDList(raw []string) []string {
return trafficmodepkg.NormalizeUIDList(raw)
}
func normalizeCgroupList(raw []string) []string {
return trafficmodepkg.NormalizeCgroupList(raw)
}
func normalizeTrafficModeState(st TrafficModeState) TrafficModeState {
st.Mode = normalizeTrafficMode(st.Mode)
st.PreferredIface = normalizePreferredIface(st.PreferredIface)
st.ForceVPNSubnets = normalizeSubnetList(st.ForceVPNSubnets)
st.ForceVPNUIDs = normalizeUIDList(st.ForceVPNUIDs)
st.ForceVPNCGroups = normalizeCgroupList(st.ForceVPNCGroups)
st.ForceDirectSubnets = normalizeSubnetList(st.ForceDirectSubnets)
st.ForceDirectUIDs = normalizeUIDList(st.ForceDirectUIDs)
st.ForceDirectCGroups = normalizeCgroupList(st.ForceDirectCGroups)
return st
}
func loadTrafficModeState() TrafficModeState {
data, err := os.ReadFile(trafficModePath)
if err != nil {
return inferTrafficModeState()
}
type diskState struct {
Mode TrafficMode `json:"mode"`
PreferredIface string `json:"preferred_iface,omitempty"`
AutoLocalBypass *bool `json:"auto_local_bypass,omitempty"`
IngressReplyBypass *bool `json:"ingress_reply_bypass,omitempty"`
ForceVPNSubnets []string `json:"force_vpn_subnets,omitempty"`
ForceVPNUIDs []string `json:"force_vpn_uids,omitempty"`
ForceVPNCGroups []string `json:"force_vpn_cgroups,omitempty"`
ForceDirectSubnets []string `json:"force_direct_subnets,omitempty"`
ForceDirectUIDs []string `json:"force_direct_uids,omitempty"`
ForceDirectCGroups []string `json:"force_direct_cgroups,omitempty"`
}
var raw diskState
if err := json.Unmarshal(data, &raw); err != nil {
return inferTrafficModeState()
}
st := TrafficModeState{
Mode: raw.Mode,
PreferredIface: raw.PreferredIface,
AutoLocalBypass: trafficAutoLocalDefault,
IngressReplyBypass: trafficIngressReplyDefault,
ForceVPNSubnets: append([]string(nil), raw.ForceVPNSubnets...),
ForceVPNUIDs: append([]string(nil), raw.ForceVPNUIDs...),
ForceVPNCGroups: append([]string(nil), raw.ForceVPNCGroups...),
ForceDirectSubnets: append([]string(nil), raw.ForceDirectSubnets...),
ForceDirectUIDs: append([]string(nil), raw.ForceDirectUIDs...),
ForceDirectCGroups: append([]string(nil), raw.ForceDirectCGroups...),
}
if raw.AutoLocalBypass != nil {
st.AutoLocalBypass = *raw.AutoLocalBypass
}
if raw.IngressReplyBypass != nil {
st.IngressReplyBypass = *raw.IngressReplyBypass
}
return normalizeTrafficModeState(st)
}
func saveTrafficModeState(st TrafficModeState) error {
st = normalizeTrafficModeState(st)
st.UpdatedAt = time.Now().UTC().Format(time.RFC3339)
data, err := json.MarshalIndent(st, "", " ")
if err != nil {
return err
}
if err := os.MkdirAll(stateDir, 0o755); err != nil {
return err
}
tmp := trafficModePath + ".tmp"
if err := os.WriteFile(tmp, data, 0o644); err != nil {
return err
}
return os.Rename(tmp, trafficModePath)
}
func inferTrafficModeState() TrafficModeState {
rules := readTrafficRules()
mode := detectAppliedTrafficMode(rules)
iface, _ := resolveTrafficIface("")
return normalizeTrafficModeState(TrafficModeState{
Mode: mode,
PreferredIface: iface,
AutoLocalBypass: trafficAutoLocalDefault,
IngressReplyBypass: trafficIngressReplyDefault,
ForceVPNSubnets: nil,
ForceVPNUIDs: nil,
ForceVPNCGroups: nil,
ForceDirectSubnets: nil,
ForceDirectUIDs: nil,
ForceDirectCGroups: nil,
})
}