package app import ( "os" trafficappmarkspkg "selective-vpn-api/app/trafficappmarks" "strings" ) func ensureAppMarksNft() error { _ = trafficappmarkspkg.EnsureBase(appMarksNFTConfig(), runCommandTimeout) // Remove legacy rules that relied on `meta cgroup @svpn_cg_*` (broken on some kernels). _ = cleanupLegacyAppMarksRules() return nil } func cleanupLegacyAppMarksRules() error { return trafficappmarkspkg.CleanupLegacyRules(appMarksNFTConfig(), runCommandTimeout) } func appMarkComment(target string, id uint64) string { return trafficappmarkspkg.AppMarkComment(appMarkCommentPrefix, target, id) } func appGuardComment(target string, id uint64) string { return trafficappmarkspkg.AppGuardComment(appGuardCommentPrefix, target, id) } func appGuardEnabled() bool { v := strings.ToLower(strings.TrimSpace(os.Getenv("SVPN_APP_GUARD"))) return v == "1" || v == "true" || v == "yes" || v == "on" } func appMarksNFTConfig() trafficappmarkspkg.NFTConfig { return trafficappmarkspkg.NFTConfig{ Table: appMarksTable, Chain: appMarksChain, GuardChain: appMarksGuardChain, LocalBypassSet: appMarksLocalBypassSet, MarkApp: MARK_APP, MarkDirect: MARK_DIRECT, MarkCommentPrefix: appMarkCommentPrefix, GuardCommentPrefix: appGuardCommentPrefix, GuardEnabled: appGuardEnabled(), } } func appMarkAutoBypassCIDRs(vpnIface string) []string { routes := detectAutoLocalBypassRoutes(vpnIface) out := make([]string, 0, len(routes)) for _, rt := range routes { dst := strings.TrimSpace(rt.Dst) if dst == "" || dst == "default" { continue } out = append(out, dst) } return out } func updateAppMarkLocalBypassSet(vpnIface string) error { _ = ensureAppMarksNft() return trafficappmarkspkg.UpdateLocalBypassSet( appMarksNFTConfig(), strings.TrimSpace(vpnIface), appMarkAutoBypassCIDRs(vpnIface), runCommandTimeout, ) } func nftInsertAppMarkRule(target string, rel string, level int, id uint64, vpnIface string) error { return trafficappmarkspkg.InsertAppMarkRule( appMarksNFTConfig(), target, rel, level, id, strings.TrimSpace(vpnIface), appMarkAutoBypassCIDRs(vpnIface), runCommandTimeout, ) } func nftDeleteAppMarkRule(target string, id uint64) error { return trafficappmarkspkg.DeleteAppMarkRule(appMarksNFTConfig(), target, id, runCommandTimeout) } func nftHasAppMarkRule(target string, id uint64) bool { return trafficappmarkspkg.HasAppMarkRule(appMarksNFTConfig(), target, id, runCommandTimeout) } func parseNftHandle(line string) int { return trafficappmarkspkg.ParseNftHandle(line) } func resolveCgroupV2PathForNft(input string) (rel string, level int, inodeID uint64, abs string, err error) { return trafficappmarkspkg.ResolveCgroupV2PathForNft(input, cgroupRootPath) } func normalizeCgroupRelOnly(raw string) string { return trafficappmarkspkg.NormalizeCgroupRelOnly(raw) } func cgroupDirInode(rel string) (uint64, error) { return trafficappmarkspkg.CgroupDirInode(cgroupRootPath, rel) } func upsertAppMarkItem(items []appMarkItem, next appMarkItem) []appMarkItem { return trafficappmarkspkg.UpsertItem(items, next) } func clearManagedAppMarkRules(chain string) { trafficappmarkspkg.ClearManagedRules(appMarksNFTConfig(), chain, runCommandTimeout) } func isAllDigits(s string) bool { return trafficappmarkspkg.IsAllDigits(s) }