punchnet-macos/Tun/Punchnet/Inbound/SDLHoleDataProcessor.swift
2026-05-20 16:44:57 +08:00

109 lines
4.0 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// SDLHoleDataProcessor.swift
// Tun
//
// Created by on 2026/4/14.
//
import Foundation
final class SDLHoleDataProcessor {
enum ProcessingAction {
case sendARPReply(dstMac: Data, data: Data)
case appendARP(ip: UInt32, mac: Data)
case writeToTun(packetData: Data, identityID: UInt32)
case requestPolicy(srcIdentityID: UInt32)
case none
}
struct ProcessingPlan {
let inboundBytes: Int
let action: ProcessingAction
}
private let networkAddress: SDLConfiguration.NetworkAddress
private let dataCipher: CCDataCipher?
private let policyService: PolicyService
init(networkAddress: SDLConfiguration.NetworkAddress,
dataCipher: CCDataCipher?,
policyService: PolicyService) {
self.networkAddress = networkAddress
self.dataCipher = dataCipher
self.policyService = policyService
}
func makeProcessingPlan(data: SDLData) async throws -> ProcessingPlan? {
guard let dataCipher = self.dataCipher else {
return nil
}
let mac = LayerPacket.MacAddress(data: data.dstMac)
guard (data.dstMac == self.networkAddress.mac || mac.isBroadcast() || mac.isMulticast()) else {
return nil
}
let decryptedData = try dataCipher.decrypt(cipherText: Data(data.data))
let layerPacket = try LayerPacket(layerData: decryptedData)
let inboundBytes = decryptedData.count
// arp
switch layerPacket.type {
case .arp:
return self.makeARPPlan(layerData: layerPacket.data, inboundBytes: inboundBytes)
case .ipv4:
return await self.makeIPv4Plan(layerData: layerPacket.data, identityID: data.identityID, inboundBytes: inboundBytes)
default:
SDLLogger.log("[SDLContext] get invalid packet", for: .debug)
return .init(inboundBytes: inboundBytes, action: .none)
}
}
private func makeARPPlan(layerData: Data, inboundBytes: Int) -> ProcessingPlan {
// arp
if let arpPacket = ARPPacket(data: layerData) {
if arpPacket.targetIP == self.networkAddress.ip {
switch arpPacket.opcode {
case .request:
let response = ARPPacket.arpResponse(for: arpPacket, mac: self.networkAddress.mac, ip: self.networkAddress.ip)
return .init(
inboundBytes: inboundBytes,
action: .sendARPReply(dstMac: arpPacket.senderMAC, data: response.marshal())
)
case .response:
return .init(
inboundBytes: inboundBytes,
action: .appendARP(ip: arpPacket.senderIP, mac: arpPacket.senderMAC)
)
}
} else {
SDLLogger.log("[SDLContext] get invalid arp packet: \(arpPacket), target_ip: \(SDLUtil.int32ToIp(arpPacket.targetIP)), net ip: \(SDLUtil.int32ToIp(self.networkAddress.ip))")
}
} else {
SDLLogger.log("[SDLContext] get invalid arp packet")
}
return .init(inboundBytes: inboundBytes, action: .none)
}
private func makeIPv4Plan(layerData: Data, identityID: UInt32, inboundBytes: Int) async -> ProcessingPlan {
// ip
guard let ipPacket = IPPacket(layerData) else {
return .init(inboundBytes: inboundBytes, action: .none)
}
//
if await self.policyService.checkPolicy(srcIdentityID: identityID, ipPacket: ipPacket) {
return .init(
inboundBytes: inboundBytes,
action: .writeToTun(packetData: ipPacket.data, identityID: identityID)
)
}
return .init(
inboundBytes: inboundBytes,
action: .requestPolicy(srcIdentityID: identityID)
)
}
}