punchnet-macos/Tun/Policy/PolicyRuntime.swift
2026-05-21 15:15:32 +08:00

56 lines
1.6 KiB
Swift

//
// PolicyRuntime.swift
// Tun
//
// Created by Codex on 2026/5/21.
//
import Foundation
struct PolicyRuntime: @unchecked Sendable {
enum InboundDecision {
case allow
case deny
case missingPolicy
}
private let policyRuleSnapshot: PolicyRuleSnapshot
private let flowSessionTable: FlowSessionTable
init(policyRuleSnapshot: PolicyRuleSnapshot, flowSessionTable: FlowSessionTable) {
self.policyRuleSnapshot = policyRuleSnapshot
self.flowSessionTable = flowSessionTable
}
func evaluateInbound(srcIdentityID: UInt32, ipPacket: IPPacket) -> InboundDecision {
if let reverseFlowSession = ipPacket.flowSession()?.reverse(),
self.flowSessionTable.hasSession(reverseFlowSession) {
self.flowSessionTable.updateSession(reverseFlowSession)
return .allow
}
if case .icmp = ipPacket.transportPacket {
return .allow
}
guard let ruleMap = self.policyRuleSnapshot.lookup(srcIdentityID) else {
return .missingPolicy
}
return self.isAllowedByRule(ruleMap: ruleMap, ipPacket: ipPacket) ? .allow : .deny
}
private func isAllowedByRule(ruleMap: PolicyRuleMap, ipPacket: IPPacket) -> Bool {
let proto = ipPacket.header.proto
switch ipPacket.transportPacket {
case .tcp(let tcpPacket):
return ruleMap.isAllow(proto: proto, port: tcpPacket.header.dstPort)
case .udp(let udpPacket):
return ruleMap.isAllow(proto: proto, port: udpPacket.dstPort)
default:
return false
}
}
}