56 lines
1.6 KiB
Swift
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: IPPacketView) -> 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: IPPacketView) -> Bool {
|
|
let proto = ipPacket.header.proto
|
|
|
|
switch ipPacket.transportPacket {
|
|
case .tcp(_, let dstPort):
|
|
return ruleMap.isAllow(proto: proto, port: dstPort)
|
|
case .udp(_, let dstPort, _):
|
|
return ruleMap.isAllow(proto: proto, port: dstPort)
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
}
|