diff --git a/protocols/arp_test.go b/protocols/arp_test.go new file mode 100644 index 0000000..06a5a3a --- /dev/null +++ b/protocols/arp_test.go @@ -0,0 +1,155 @@ +package protocols + +import ( + "net" + "reflect" + "testing" +) + +func TestARPPacketFromBytes(t *testing.T) { + tests := []struct { + name string + raw []byte + expectedPacket *ARPPacket + expectedErr error + }{ + { + name: "Valid ARP Request Packet", + raw: []byte{ + // Ethernet Frame Header + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, // Destination MAC + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f, // Source MAC + 0x08, 0x06, // EtherType (ARP) + + // ARP Packet + 0x00, 0x01, // Hardware Type (Ethernet) + 0x08, 0x00, // Protocol Type (IPv4) + 0x06, // Hardware Address Length (6 bytes) + 0x04, // Protocol Address Length (4 bytes) + 0x00, 0x01, // Operation (ARP Request) + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, // Sender HW Address + 0xc0, 0xa8, 0x01, 0x01, // Sender Protocol Address (192.168.1.1) + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f, // Target HW Address + 0xc0, 0xa8, 0x01, 0x02, // Target Protocol Address (192.168.1.2) + }, + expectedPacket: &ARPPacket{ + EthFrame: EthernetFrame{ + DestinationMAC: net.HardwareAddr{0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e}, + SourceMAC: net.HardwareAddr{0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f}, + EtherType: 0x0806, + Payload: []byte{ + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0xc0, 0xa8, + 0x01, 0x01, 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f, + 0xc0, 0xa8, 0x01, 0x02, + }, + }, + HardwareType: 0x0001, + ProtocolType: 0x0800, + HardwareAddrLen: 6, + ProtocolAddrLen: 4, + Operation: 0x0001, + SenderHWAddr: net.HardwareAddr{0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e}, + SenderProtoAddr: net.IP{0xc0, 0xa8, 0x01, 0x01}, + TargetHWAddr: net.HardwareAddr{0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f}, + TargetProtoAddr: net.IP{0xc0, 0xa8, 0x01, 0x02}, + }, + expectedErr: nil, + }, + { + name: "Valid ARP Reply Packet", + raw: []byte{ + // Ethernet Frame Header + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f, // Destination MAC + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, // Source MAC + 0x08, 0x06, // EtherType (ARP) + + // ARP Packet + 0x00, 0x01, // Hardware Type (Ethernet) + 0x08, 0x00, // Protocol Type (IPv4) + 0x06, // Hardware Address Length (6 bytes) + 0x04, // Protocol Address Length (4 bytes) + 0x00, 0x02, // Operation (ARP Reply) + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f, // Sender HW Address + 0xc0, 0xa8, 0x01, 0x02, // Sender Protocol Address (192.168.1.2) + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, // Target HW Address + 0xc0, 0xa8, 0x01, 0x01, // Target Protocol Address (192.168.1.1) + }, + expectedPacket: &ARPPacket{ + EthFrame: EthernetFrame{ + DestinationMAC: net.HardwareAddr{0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f}, + SourceMAC: net.HardwareAddr{0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e}, + EtherType: 0x0806, + Payload: []byte{ + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f, 0xc0, 0xa8, + 0x01, 0x02, 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, + 0xc0, 0xa8, 0x01, 0x01, + }, + }, + HardwareType: 0x0001, + ProtocolType: 0x0800, + HardwareAddrLen: 6, + ProtocolAddrLen: 4, + Operation: 0x0002, + SenderHWAddr: net.HardwareAddr{0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f}, + SenderProtoAddr: net.IP{0xc0, 0xa8, 0x01, 0x02}, + TargetHWAddr: net.HardwareAddr{0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e}, + TargetProtoAddr: net.IP{0xc0, 0xa8, 0x01, 0x01}, + }, + expectedErr: nil, + }, + { + name: "Invalid ARP Packet (Too Short)", + raw: []byte{ + // Ethernet Frame Header + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, // Destination MAC + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f, // Source MAC + 0x08, 0x06, // EtherType (ARP) + + // ARP Packet (too short) + 0x00, 0x01, + 0x08, 0x00, + 0x06, + 0x04, + }, + expectedPacket: nil, + expectedErr: errInvalidARPPacket, + }, + { + name: "Invalid ARP Packet (Malformed)", + raw: []byte{ + // Ethernet Frame Header + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, // Destination MAC + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f, // Source MAC + 0x08, 0x06, // EtherType (ARP) + + // ARP Packet (malformed) + 0x00, 0x01, // Hardware Type + 0x08, 0x00, // Protocol Type + 0x06, // Hardware Address Length + 0x04, // Protocol Address Length + 0x00, 0x01, // Operation + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, // Sender HW Address + 0xc0, 0xa8, 0x01, 0x01, // Sender Protocol Address + 0x00, 0x1a, 0x2b, 0x3c, 0x4d, 0x5f, // Target HW Address + // Missing Target Protocol Address + }, + expectedPacket: nil, + expectedErr: errInvalidARPPacket, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p, err := ARPPacketFromBytes(tt.raw) + if tt.expectedErr != err { + t.Errorf("expected error to be: %v - got: %v", tt.expectedErr, err) + } + + if !reflect.DeepEqual(tt.expectedPacket, p) { + t.Errorf("expected packet to be %v - got %v", tt.expectedPacket, p) + } + }) + } +}