101 lines
2.6 KiB
Swift
101 lines
2.6 KiB
Swift
//
|
|
// LayerPacket.swift
|
|
// Tun
|
|
//
|
|
// Created by 安礼成 on 2024/8/21.
|
|
//
|
|
|
|
import Foundation
|
|
import zlib
|
|
|
|
struct LayerPacket {
|
|
// 数据包类型
|
|
enum PacketType: UInt16 {
|
|
case arp = 0x0806
|
|
case ipv4 = 0x0800
|
|
case ipv6 = 0x86DD
|
|
case taggedFrame = 0x8100
|
|
}
|
|
|
|
enum LayerPacketError: Error {
|
|
case invalidLength
|
|
case crcError
|
|
case invaldPacketType
|
|
}
|
|
|
|
struct MacAddress {
|
|
let data: Data
|
|
|
|
init(data: Data) {
|
|
self.data = data
|
|
}
|
|
|
|
func isBroadcast() -> Bool {
|
|
return data.count == 6 && self.data.allSatisfy { $0 == 0xFF}
|
|
}
|
|
|
|
func isMulticast() -> Bool {
|
|
return data.count == 6 && (data[0] == 0x01 && data[1] == 0x00 && data[2] == 0x5E)
|
|
}
|
|
|
|
func format() -> String {
|
|
// 将mac地址转换成字符串
|
|
let bytes = [UInt8](data)
|
|
return bytes.map { String(format: "%02X", $0) }.joined(separator: ":").lowercased()
|
|
}
|
|
|
|
static func description(data: Data) -> String {
|
|
// 将mac地址转换成字符串
|
|
let bytes = [UInt8](data)
|
|
return bytes.map { String(format: "%02X", $0) }.joined(separator: ":").lowercased()
|
|
}
|
|
|
|
}
|
|
|
|
let dstMac: Data
|
|
let srcMac: Data
|
|
let type: PacketType
|
|
let data: Data
|
|
|
|
init(dstMac: Data, srcMac: Data, type: PacketType, data: Data) {
|
|
self.dstMac = dstMac
|
|
self.srcMac = srcMac
|
|
self.type = type
|
|
self.data = data
|
|
}
|
|
|
|
init(layerData playload: Data) throws {
|
|
guard playload.count >= 14 else {
|
|
throw LayerPacketError.invalidLength
|
|
}
|
|
|
|
self.dstMac = Data(playload[0..<6])
|
|
self.srcMac = Data(playload[6..<12])
|
|
guard let type = PacketType(rawValue: UInt16(bytes: (playload[12], playload[13]))) else {
|
|
throw LayerPacketError.invaldPacketType
|
|
}
|
|
|
|
self.type = type
|
|
self.data = Data(playload[14...])
|
|
}
|
|
|
|
func marshal() -> Data {
|
|
var packet = Data()
|
|
packet.append(dstMac)
|
|
packet.append(srcMac)
|
|
packet.append(self.type.rawValue.data())
|
|
packet.append(self.data)
|
|
|
|
return packet
|
|
}
|
|
|
|
private static func crc32(data: Data) -> UInt32 {
|
|
let crc = data.withUnsafeBytes { buffer in
|
|
return zlib.crc32(0, buffer.bindMemory(to: UInt8.self).baseAddress, uInt(buffer.count))
|
|
}
|
|
|
|
return UInt32(crc)
|
|
}
|
|
|
|
}
|