summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Habets <thomas@habets.se>2015-04-22 20:20:28 +0100
committerThomas Habets <thomas@habets.se>2015-04-22 20:22:48 +0100
commit13bf641a0153ef7fe3342c2fc4db8f0937f4c4a0 (patch)
tree7e9b56d5bd370b00ccce682c5e88262e4c375121
parent2a4eab7019e997eaf6a53bb124cb9cacdbccbe61 (diff)
downloadarping-13bf641a0153ef7fe3342c2fc4db8f0937f4c4a0.tar.gz
Add test on some borken packets.
-rw-r--r--src/arping.c14
-rw-r--r--src/arping_test.c222
2 files changed, 228 insertions, 8 deletions
diff --git a/src/arping.c b/src/arping.c
index b073f37..ed66105 100644
--- a/src/arping.c
+++ b/src/arping.c
@@ -981,9 +981,23 @@ pingip_recv(const char *unused, struct pcap_pkthdr *h, uint8_t *packet)
harp = (void*)((char*)veth + LIBNET_802_1Q_H);
pkt_srcmac = veth->vlan_shost;
} else {
+ // Short packet.
+ if (h->caplen < LIBNET_ETH_H + LIBNET_ARP_H + 2*(ETH_ALEN + 4)) {
+ return;
+ }
+
heth = (void*)packet;
harp = (void*)((char*)heth + LIBNET_ETH_H);
pkt_srcmac = heth->_802_3_shost;
+ // Wrong length of hardware address.
+ if (harp->ar_hln != ETH_ALEN) {
+ return;
+ }
+
+ // Wrong length of protocol address.
+ if (harp->ar_pln != 4) {
+ return;
+ }
}
// ARP reply.
diff --git a/src/arping_test.c b/src/arping_test.c
index 487b5a1..fa2f877 100644
--- a/src/arping_test.c
+++ b/src/arping_test.c
@@ -23,14 +23,25 @@
#include<stdlib.h>
#include<check.h>
+#include<libnet.h>
#include<pcap.h>
#include"arping.h"
static int numtests = 0;
-static void* test_registry[1024];
+struct registered_test {
+ void* fn;
+ const char* name;
+};
+static struct registered_test test_registry[1024];
+
-#define MYTEST(a) static void a(int);__attribute__((constructor)) static void cons_##a() { test_registry[numtests++] = a;} START_TEST(a)
+#define MYTEST(a) static void a(int);__attribute__((constructor)) \
+static void cons_##a() { \
+ test_registry[numtests].fn = a; \
+ test_registry[numtests].name = #a; \
+ numtests++; \
+} START_TEST(a)
/**
*
@@ -144,21 +155,211 @@ uncapture(struct captured_output* out)
free(out);
}
+static uint8_t*
+mkpacket(struct pcap_pkthdr* pkthdr)
+{
+ uint8_t* packet = calloc(1, 1500);
+ fail_if(packet == NULL);
+
+ struct libnet_802_3_hdr* heth;
+ struct libnet_arp_hdr* harp;
+
+ // Set up ethernet header
+ heth = (void*)packet;
+ memcpy(heth->_802_3_dhost, "\x11\x22\x33\x44\x55\x66", 6);
+ memcpy(heth->_802_3_shost, "\x77\x88\x99\xaa\xbb\xcc", 6);
+ heth->_802_3_len = 0; // FIXME: is this correct?
+
+ // Set up ARP header.
+ harp = (void*)((char*)heth + LIBNET_ETH_H);
+ harp->ar_hln = 6;
+ harp->ar_pln = 4;
+ harp->ar_hrd = htons(ARPHRD_ETHER);
+ harp->ar_op = htons(ARPOP_REPLY);
+ harp->ar_pro = htons(ETHERTYPE_IP);
+
+ memcpy((char*)harp + LIBNET_ARP_H, heth->_802_3_shost, 6);
+ memcpy((char*)harp + LIBNET_ARP_H + harp->ar_hln, &dstip, 4);
+
+ memcpy((char*)harp + LIBNET_ARP_H
+ + harp->ar_hln
+ + harp->ar_pln, heth->_802_3_dhost, 6);
+ memcpy((char*)harp + LIBNET_ARP_H
+ + harp->ar_hln
+ + harp->ar_pln
+ + harp->ar_hln, &srcip, 4);
+
+ pkthdr->ts.tv_sec = time(NULL);
+ pkthdr->ts.tv_usec = 0;
+ pkthdr->len = 60;
+ pkthdr->caplen = 60;
+
+ return packet;
+}
+
+static void
+dump_packet(uint8_t* packet, int len)
+{
+ int c;
+ for (c = 0; c < len; c++) {
+ fprintf(stderr, "0x%.2x, ", (int)packet[c]);
+ if (!((c+1) % 10)) {
+ fprintf(stderr, "\n");
+ }
+ }
+ fprintf(stderr, "\n");
+}
+
+MYTEST(test_mkpacket)
+{
+ uint8_t correct_packet[] = {
+ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa,
+ 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
+ 0x00, 0x02, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0x12, 0x34,
+ 0x56, 0x78, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x87, 0x65,
+ 0x43, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ struct pcap_pkthdr pkthdr;
+ dstip = htonl(0x12345678);
+ srcip = htonl(0x87654321);
+
+ uint8_t* packet = mkpacket(&pkthdr);
+ fail_if(packet == NULL);
+ fail_unless(pkthdr.caplen == 60);
+ if (memcmp(packet, correct_packet, pkthdr.caplen)) {
+ dump_packet(packet, pkthdr.caplen);
+ }
+ fail_unless(!memcmp(packet, correct_packet, pkthdr.caplen));
+} END_TEST
+
+
// Received uninteresting packet, should not record anything.
MYTEST(pingip_uninteresting_packet)
{
struct pcap_pkthdr pkthdr;
- uint8_t packet[128];
+ uint8_t* packet;
+ struct libnet_802_3_hdr* heth;
+ struct libnet_arp_hdr* harp;
int prev_numrecvd = numrecvd;
-
struct captured_output* sout;
+
+ // Completely broken packet.
+ packet = calloc(1, 1500);
sout = capture(1);
pingip_recv(NULL, &pkthdr, packet);
stop_capture(sout);
fail_unless(strlen(sout->buffer) == 0);
+ fail_unless(prev_numrecvd == numrecvd);
+ uncapture(sout);
+ free(packet);
+ // Not ETHERTYPE_IP.
+ packet = mkpacket(&pkthdr);
+ harp = (void*)((char*)packet + LIBNET_ETH_H);
+ harp->ar_pro = 0;
+ sout = capture(1);
+ pingip_recv(NULL, &pkthdr, packet);
+ stop_capture(sout);
fail_unless(prev_numrecvd == numrecvd);
+ fail_unless(strlen(sout->buffer) == 0);
+ uncapture(sout);
+ free(packet);
+
+ // Not ARPHRD_ETHER
+ packet = mkpacket(&pkthdr);
+ harp = (void*)((char*)packet + LIBNET_ETH_H);
+ harp->ar_hrd = 0;
+ sout = capture(1);
+ pingip_recv(NULL, &pkthdr, packet);
+ stop_capture(sout);
+ fail_unless(prev_numrecvd == numrecvd);
+ fail_unless(strlen(sout->buffer) == 0);
+ uncapture(sout);
+ free(packet);
+
+ // Wrong dstip
+ if (0) {
+ uint32_t wrongip = 123;
+ packet = mkpacket(&pkthdr);
+ harp = (void*)((char*)packet + LIBNET_ETH_H);
+ memcpy((char*)harp + harp->ar_hln + LIBNET_ARP_H, &wrongip, 4);
+ sout = capture(1);
+ pingip_recv(NULL, &pkthdr, packet);
+ stop_capture(sout);
+ fail_unless(prev_numrecvd == numrecvd);
+ fail_unless(strlen(sout->buffer) == 0);
+ uncapture(sout);
+ free(packet);
+ }
+
+ // Short packet.
+ packet = mkpacket(&pkthdr);
+ pkthdr.caplen = pkthdr.len = 41;
+ sout = capture(1);
+ pingip_recv(NULL, &pkthdr, packet);
+ stop_capture(sout);
+ fail_unless(prev_numrecvd == numrecvd);
+ fail_unless(strlen(sout->buffer) == 0);
+ uncapture(sout);
+ free(packet);
+
+ // Short captured packet.
+ packet = mkpacket(&pkthdr);
+ pkthdr.caplen = 41;
+ sout = capture(1);
+ pingip_recv(NULL, &pkthdr, packet);
+ stop_capture(sout);
+ fail_unless(prev_numrecvd == numrecvd);
+ fail_unless(strlen(sout->buffer) == 0);
+ uncapture(sout);
+ free(packet);
+
+ // Wrong length of hardware address.
+ {
+ uint8_t packet[] = {
+ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, // dst
+ 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, // src
+ 0x00, 0x00, // type
+ 0x00, 0x01, // hardware
+ 0x08, 0x00, // protocol
+ 0x04, 0x04, // lengths (for this test length is wrong)
+ 0x00, 0x02, // operator
+
+ 0x77, 0x88, 0x99, 0xaa, // sender (wrong length for test)
+ 0x12, 0x34, 0x56, 0x78, // sender protocol address
+
+ 0x11, 0x22, 0x33, 0x44, // receiver (wrong length for test)
+ 0x87, 0x65, 0x43, 0x21, // receiver protocol address
+
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x6f, 0xa8, 0x58, 0x63,
+ };
+ pkthdr.len = 60;
+ pkthdr.caplen = 60;
+ sout = capture(1);
+ pingip_recv(NULL, &pkthdr, packet);
+ stop_capture(sout);
+ fail_unless(strlen(sout->buffer) == 0, sout->buffer);
+ fail_unless(prev_numrecvd == numrecvd);
+ uncapture(sout);
+ }
+
+ // Wrong length of protocol address.
+ packet = mkpacket(&pkthdr);
+ ((struct libnet_arp_hdr*)((char*)packet + LIBNET_ETH_H))->ar_pln = 6;
+ sout = capture(1);
+ pingip_recv(NULL, &pkthdr, packet);
+ stop_capture(sout);
+ fail_unless(prev_numrecvd == numrecvd);
+ fail_unless(strlen(sout->buffer) == 0);
+ uncapture(sout);
+ free(packet);
} END_TEST
// Received reply that actually matches. Things should happen.
@@ -184,6 +385,7 @@ MYTEST(pingip_interesting_packet)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6f, 0xa8, 0x58, 0x63,
};
+ numrecvd = 0;
int prev_numrecvd = numrecvd;
dstip = htonl(0x12345678);
@@ -202,8 +404,12 @@ MYTEST(pingip_interesting_packet)
sout = capture(1);
pingip_recv(NULL, &pkthdr, packet);
stop_capture(sout);
- fail_unless(!strncmp(sout->buffer, correct0, strlen(correct0)));
+
+ char* emsg = NULL;
+ asprintf(&emsg, "Captured: <%s> (%d), want <%s> %d\n", sout->buffer, strlen(sout->buffer), correct0, strlen(correct0));
+ fail_unless(!strncmp(sout->buffer, correct0, strlen(correct0)), emsg);
uncapture(sout);
+ free(emsg);
fail_unless(numrecvd == prev_numrecvd + 1,
"numrecvd not incremented");
@@ -220,11 +426,11 @@ arping_suite(void)
Suite* s = suite_create("Arping");
//tcase_add_checked_fixture (tc_core, setup, teardown);
- TCase *tc_core = tcase_create("Receiving");
for (c = 0; c < numtests; c++) {
- tcase_add_test(tc_core, test_registry[c]);
+ TCase *tc_core = tcase_create(test_registry[c].name);
+ tcase_add_test(tc_core, test_registry[c].fn);
+ suite_add_tcase(s, tc_core);
}
- suite_add_tcase(s, tc_core);
return s;
}