132 lines
4.0 KiB
Swift
132 lines
4.0 KiB
Swift
//
|
|
// ARPPacket.swift
|
|
// Tun
|
|
//
|
|
// Created by 安礼成 on 2024/8/25.
|
|
//
|
|
import Foundation
|
|
|
|
struct ARPPacket: CustomStringConvertible {
|
|
var description: String {
|
|
return """
|
|
opcode: \(self.opcode), sender_ip: \(SDLUtil.int32ToIp(self.senderIP)), sender_mac: \(SDLUtil.formatMacAddress(mac: senderMAC)),
|
|
target_ip: \(SDLUtil.int32ToIp(self.targetIP)), target_mac: \(SDLUtil.formatMacAddress(mac: targetMAC))
|
|
"""
|
|
}
|
|
|
|
static let broadcastMac = Data([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
|
|
|
// ARP操作码
|
|
enum Opcode: UInt16 {
|
|
case request = 0x01
|
|
case response = 0x02
|
|
|
|
func isRequest() -> Bool {
|
|
return self == .request
|
|
}
|
|
|
|
func isResponse() -> Bool {
|
|
return self == .response
|
|
}
|
|
}
|
|
|
|
var hardwareType: UInt16
|
|
var protocolType: UInt16
|
|
var hardwareSize: UInt8
|
|
var protocolSize: UInt8
|
|
var opcode: Opcode
|
|
var senderMAC: Data
|
|
var senderIP: UInt32
|
|
var targetMAC: Data
|
|
var targetIP: UInt32
|
|
|
|
init(hardwareType: UInt16,
|
|
protocolType: UInt16,
|
|
hardwareSize: UInt8,
|
|
protocolSize: UInt8,
|
|
opcode: Opcode,
|
|
senderMAC: Data,
|
|
senderIP: UInt32,
|
|
targetMAC: Data,
|
|
targetIP: UInt32) {
|
|
|
|
self.hardwareType = hardwareType
|
|
self.protocolType = protocolType
|
|
self.hardwareSize = hardwareSize
|
|
self.protocolSize = protocolSize
|
|
self.opcode = opcode
|
|
self.senderMAC = senderMAC
|
|
self.senderIP = senderIP
|
|
self.targetMAC = targetMAC
|
|
self.targetIP = targetIP
|
|
}
|
|
|
|
init?(data: Data) {
|
|
guard data.count >= 28 else {
|
|
return nil
|
|
}
|
|
|
|
self.hardwareType = UInt16(data[0]) << 8 | UInt16(data[1])
|
|
self.protocolType = UInt16(data[2]) << 8 | UInt16(data[3])
|
|
self.hardwareSize = data[4]
|
|
self.protocolSize = data[5]
|
|
guard let opcode = Opcode(rawValue: UInt16(data[6]) << 8 | UInt16(data[7])) else {
|
|
return nil
|
|
}
|
|
|
|
self.opcode = opcode
|
|
self.senderMAC = Data(data[8..<14])
|
|
self.senderIP = UInt32(data: Data(data[14..<18]))
|
|
self.targetMAC = Data(data[18..<24])
|
|
self.targetIP = UInt32(data: Data(data[24..<28]))
|
|
}
|
|
|
|
func marshal() -> Data {
|
|
var data = Data()
|
|
data.append(self.hardwareType.data())
|
|
data.append(self.protocolType.data())
|
|
data.append(self.hardwareSize)
|
|
data.append(self.protocolSize)
|
|
data.append(self.opcode.rawValue.data())
|
|
data.append(self.senderMAC)
|
|
data.append(Data(uint32: self.senderIP))
|
|
data.append(self.targetMAC)
|
|
data.append(Data(uint32: self.targetIP))
|
|
|
|
return data
|
|
}
|
|
|
|
static func isBroadcastMac(_ macAddress: Data) -> Bool {
|
|
return macAddress == broadcastMac
|
|
}
|
|
|
|
}
|
|
|
|
extension ARPPacket {
|
|
|
|
static func arpRequest(senderIP: UInt32, senderMAC: Data, targetIP: UInt32) -> ARPPacket {
|
|
return ARPPacket(hardwareType: 0x01,
|
|
protocolType: 0x0800,
|
|
hardwareSize: 0x06,
|
|
protocolSize: 0x04,
|
|
opcode: .request,
|
|
senderMAC: senderMAC,
|
|
senderIP: senderIP,
|
|
targetMAC: Data([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
|
|
targetIP: targetIP)
|
|
}
|
|
|
|
static func arpResponse(for arp: ARPPacket, mac: Data, ip: UInt32) -> ARPPacket {
|
|
return ARPPacket(hardwareType: arp.hardwareType,
|
|
protocolType: arp.protocolType,
|
|
hardwareSize: arp.hardwareSize,
|
|
protocolSize: arp.protocolSize,
|
|
opcode: .response,
|
|
senderMAC: mac,
|
|
senderIP: ip,
|
|
targetMAC: arp.senderMAC,
|
|
targetIP: arp.senderIP)
|
|
}
|
|
|
|
}
|