// // IPPacket.swift // Tun // // Created by 安礼成 on 2024/1/18. // import Foundation struct IPHeader { let version: UInt8 let headerLength: UInt8 let typeOfService: UInt8 let totalLength: UInt16 let id: UInt16 let offset: UInt16 let timeToLive: UInt8 let proto:UInt8 let checksum: UInt16 let source: UInt32 let destination: UInt32 var source_ip: String { return intToIp(source) } var destination_ip: String { return intToIp(destination) } private func intToIp(_ num: UInt32) -> String { let ip0 = (UInt8) (num >> 24 & 0xFF) let ip1 = (UInt8) (num >> 16 & 0xFF) let ip2 = (UInt8) (num >> 8 & 0xFF) let ip3 = (UInt8) (num & 0xFF) return "\(ip0).\(ip1).\(ip2).\(ip3)" } public var description: String { """ IPHeader version: \(version), header length: \(headerLength), type of service: \(typeOfService), total length: \(totalLength), id: \(id), offset: \(offset), time ot live: \(timeToLive), proto: \(proto), checksum: \(checksum), source ip: \(source_ip), destination ip:\(destination_ip) """ } } enum IPVersion: UInt8 { case ipv4 = 4 case ipv6 = 6 } enum TransportProtocol: UInt8 { case icmp = 1 case tcp = 6 case udp = 17 } struct IPPacket { let header: IPHeader let data: Data init?(_ data: Data) { guard data.count >= 20 else { return nil } self.header = IPHeader(version: data[0] >> 4, headerLength: (data[0] & 0b1111) * 4, typeOfService: data[1], totalLength: UInt16(bytes: (data[2], data[3])), id: UInt16(bytes: (data[4], data[5])), offset: 1, timeToLive: data[8], proto: data[9], checksum: UInt16(bytes: (data[10], data[11])), source: UInt32(bytes: (data[12], data[13], data[14], data[15])), destination: UInt32(bytes: (data[16], data[17], data[18], data[19]))) self.data = data } }