diff options
author | Thomas Habets <thomas@habets.se> | 2015-04-22 20:20:28 +0100 |
---|---|---|
committer | Thomas Habets <thomas@habets.se> | 2015-04-22 20:22:48 +0100 |
commit | 13bf641a0153ef7fe3342c2fc4db8f0937f4c4a0 (patch) | |
tree | 7e9b56d5bd370b00ccce682c5e88262e4c375121 | |
parent | 2a4eab7019e997eaf6a53bb124cb9cacdbccbe61 (diff) | |
download | arping-13bf641a0153ef7fe3342c2fc4db8f0937f4c4a0.tar.gz |
Add test on some borken packets.
-rw-r--r-- | src/arping.c | 14 | ||||
-rw-r--r-- | src/arping_test.c | 222 |
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; } |