first commit
This commit is contained in:
+56
@@ -0,0 +1,56 @@
|
||||
#include <stdio.h>
|
||||
#include <microtcp.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
microtcp_errcode_t errcode;
|
||||
|
||||
microtcp_t *mtcp = microtcp_create();
|
||||
if (mtcp == NULL)
|
||||
return -1;
|
||||
|
||||
uint16_t port = 80;
|
||||
microtcp_socket_t *server = microtcp_open(mtcp, port, &errcode);
|
||||
if (errcode) {
|
||||
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
|
||||
microtcp_destroy(mtcp);
|
||||
return -1;
|
||||
}
|
||||
assert(server);
|
||||
|
||||
fprintf(stderr, "Listening on port %d\n", port);
|
||||
|
||||
while (1) {
|
||||
fprintf(stderr, "About to accept\n");
|
||||
microtcp_socket_t *client = microtcp_accept(server, false, &errcode);
|
||||
if (errcode && errcode != MICROTCP_ERRCODE_NOTHINGTOACCEPT) {
|
||||
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Accepted a connection\n");
|
||||
|
||||
char buffer[1024];
|
||||
size_t num = microtcp_recv(client, buffer, sizeof(buffer), &errcode);
|
||||
if (errcode) {
|
||||
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
|
||||
goto handled;
|
||||
}
|
||||
microtcp_send(client, "echo: ", 6, &errcode);
|
||||
if (errcode) {
|
||||
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
|
||||
goto handled;
|
||||
}
|
||||
microtcp_send(client, buffer, num, &errcode);
|
||||
if (errcode) {
|
||||
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
|
||||
goto handled;
|
||||
}
|
||||
handled:
|
||||
microtcp_close(client);
|
||||
}
|
||||
|
||||
microtcp_close(server);
|
||||
microtcp_destroy(mtcp);
|
||||
return 0;
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "test_arp_util.h"
|
||||
|
||||
/*
|
||||
WHITE BOX TEST CASES
|
||||
|
||||
A) Peer requests host's MAC given its IP and host
|
||||
replies.
|
||||
|
||||
B) Peer requests host's non MAC level 2 address
|
||||
given its IP and host doesn't reply because it
|
||||
only supports MAC.
|
||||
|
||||
C) Peer requests host's MAC address given its non
|
||||
IP level 3 address and host doesn't reply
|
||||
because it only supports IP.
|
||||
|
||||
D) Peer requests host's MAC given its IP, but the
|
||||
MAC address length field isn't 6, therefore
|
||||
host doesn't reply.
|
||||
|
||||
E) Peer requests host's MAC given its IP, but the
|
||||
IP address length field isn't 4, therefore host
|
||||
doesn't reply.
|
||||
|
||||
F) Peer sends a request/reply that doesn't refer
|
||||
to host and is from a sender with IP never seen
|
||||
by the host (no entry in the translation table).
|
||||
It's expected that no entry is added to the
|
||||
translation table.
|
||||
|
||||
G) Peer sends a request/reply that doesn't refer
|
||||
to host but is from a sender with IP already
|
||||
in the ARP translation table, therefore is
|
||||
expected that host updates the entry.
|
||||
|
||||
H) Program queries the ARP module for a MAC that
|
||||
isn't cached, therefore an ARP request is
|
||||
expected to be generated and, when replied to,
|
||||
the ARP module is expected to resolve the
|
||||
program's query.
|
||||
|
||||
I) Program queries the ARP module for a MAC that's
|
||||
cached, therefore the ARP module is expected to
|
||||
resolve it without sending packets.
|
||||
*/
|
||||
|
||||
static arp_testcase_result_t test_000(char *msg, size_t msgmax)
|
||||
{
|
||||
char host_ip[4] = {0xc0, 0xa8, 0x01, 0x05};
|
||||
char host_mac[6] = {0xcc, 0x6b, 0x1e, 0x13, 0xa8, 0x93};
|
||||
|
||||
arp_testcase_t testcase;
|
||||
arp_testcase_init(&testcase, host_mac, host_ip);
|
||||
|
||||
arp_testcase_send(&testcase, (char[]) {
|
||||
0x00, 0x01, // hardware_type=ethernet
|
||||
0x08, 0x00, // protocol_type=ip
|
||||
0x06, // hardware_len=6
|
||||
0x04, // protocol_len=4
|
||||
0x00, 0x01, // operation_type=request
|
||||
0xbc, 0x15, 0xac, 0x29, 0xe5, 0x61, // sender MAC
|
||||
0xc0, 0xa8, 0x01, 0x01, // sender IP
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // target MAC (empty)
|
||||
0xc0, 0xa8, 0x01, 0x05, // target IP
|
||||
});
|
||||
|
||||
arp_testcase_recv(&testcase, (char[]) {
|
||||
0x00, 0x01, // hardware_type=ethernet
|
||||
0x08, 0x00, // protocol_type=ip
|
||||
0x06, // hardware_len=6
|
||||
0x04, // protocol_len=4
|
||||
0x00, 0x02, // operation_type=reply
|
||||
0xcc, 0x6b, 0x1e, 0x13, 0xa8, 0x93, // sender MAC
|
||||
0xc0, 0xa8, 0x01, 0x05, // sender IP
|
||||
0xbc, 0x15, 0xac, 0x29, 0xe5, 0x61, // target MAC
|
||||
0xc0, 0xa8, 0x01, 0x01, // target IP
|
||||
});
|
||||
|
||||
arp_testcase_result_t result =
|
||||
arp_testcase_run(testcase, msg, msgmax);
|
||||
|
||||
arp_testcase_free(&testcase);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static arp_testcase_result_t test_001(char *msg, size_t msgmax)
|
||||
{
|
||||
/* This testcase simulates the host receiving
|
||||
* an ARP request not associated to it, therefore
|
||||
* the ARP module is expected to not reply.
|
||||
*/
|
||||
|
||||
char host_ip[4] = {0xc0, 0xa8, 0x01, 0x05};
|
||||
char host_mac[6] = {0xcc, 0x6b, 0x1e, 0x13, 0xa8, 0x93};
|
||||
|
||||
arp_testcase_t testcase;
|
||||
arp_testcase_init(&testcase, host_mac, host_ip);
|
||||
|
||||
arp_testcase_send(&testcase, (char[]) {
|
||||
0x00, 0x01, // hardware_type=ethernet
|
||||
0x08, 0x00, // protocol_type=ip
|
||||
0x06, // hardware_len=6
|
||||
0x04, // protocol_len=4
|
||||
0x00, 0x01, // operation_type=request
|
||||
0xbc, 0x15, 0xac, 0x29, 0xe5, 0x61, // sender MAC
|
||||
0xc0, 0xa8, 0x01, 0x01, // sender IP
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // target MAC (empty)
|
||||
0xc0, 0xa8, 0x01, 0x10, // target IP (different to the host's)
|
||||
});
|
||||
|
||||
arp_testcase_result_t result =
|
||||
arp_testcase_run(testcase, msg, msgmax);
|
||||
|
||||
arp_testcase_free(&testcase);
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef arp_testcase_result_t (*arp_testcase_routine_t)(char*, size_t);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
static const arp_testcase_routine_t routines[] = {
|
||||
test_000,
|
||||
test_001,
|
||||
NULL,
|
||||
};
|
||||
|
||||
size_t passed = 0;
|
||||
size_t failed = 0;
|
||||
size_t aborted = 0;
|
||||
|
||||
for (size_t i = 0; routines[i]; i++) {
|
||||
|
||||
char message[1024];
|
||||
arp_testcase_result_t result = routines[i](message, sizeof(message));
|
||||
|
||||
switch (result) {
|
||||
case ARP_TESTCASE_PASSED:
|
||||
fprintf(stdout, "Test %ld ... PASSED\n", i);
|
||||
passed++;
|
||||
break;
|
||||
|
||||
case ARP_TESTCASE_FAILED:
|
||||
fprintf(stdout, "Test %ld ... FAILED: %s\n", i, message);
|
||||
failed++;
|
||||
break;
|
||||
|
||||
case ARP_TESTCASE_ABORTED:
|
||||
fprintf(stdout, "Test %ld ... ABORTED: %s\n", i, message);
|
||||
aborted++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stdout, "SUMMARY: %ld passed, %ld failed and %ld aborted\n",
|
||||
passed, failed, aborted);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "test_arp_util.h"
|
||||
|
||||
void arp_testcase_init(arp_testcase_t *tcase,
|
||||
const char mac[static 6],
|
||||
const char ip[static 4])
|
||||
{
|
||||
memcpy(&tcase->self_ip, ip, 4);
|
||||
memcpy(&tcase->self_mac, mac, 6);
|
||||
tcase->failed = false;
|
||||
tcase->count = 0;
|
||||
}
|
||||
|
||||
void arp_testcase_free(arp_testcase_t *tcase)
|
||||
{
|
||||
(void) tcase;
|
||||
}
|
||||
|
||||
void arp_testcase_send(arp_testcase_t *tcase, const char data[static sizeof(arp_packet_t)])
|
||||
{
|
||||
if (tcase->failed)
|
||||
return;
|
||||
|
||||
if (tcase->count == ARP_TESTCASE_MAX_PACKETS) {
|
||||
tcase->failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
arp_testcase_packet_t *packet = tcase->packets + tcase->count;
|
||||
packet->sender = ARP_TESTCASE_SENDER_PEER;
|
||||
packet->data = data;
|
||||
|
||||
tcase->count++;
|
||||
}
|
||||
|
||||
void arp_testcase_recv(arp_testcase_t *tcase, const char data[static sizeof(arp_packet_t)])
|
||||
{
|
||||
if (tcase->failed)
|
||||
return;
|
||||
|
||||
if (tcase->count == ARP_TESTCASE_MAX_PACKETS) {
|
||||
tcase->failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
arp_testcase_packet_t *packet = tcase->packets + tcase->count;
|
||||
packet->sender = ARP_TESTCASE_SENDER_HOST;
|
||||
packet->data = data;
|
||||
|
||||
tcase->count++;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *msg;
|
||||
size_t msgmax;
|
||||
const arp_packet_t *output;
|
||||
const arp_testcase_t *tcase;
|
||||
size_t cursor;
|
||||
bool output_as_expected;
|
||||
bool aborted_while_checking_sent_packets;
|
||||
} testcase_contex_t;
|
||||
|
||||
static void send_packet(void *data, mac_address_t dest)
|
||||
{
|
||||
(void) dest; // Is this ok?
|
||||
|
||||
testcase_contex_t *context = data;
|
||||
|
||||
context->aborted_while_checking_sent_packets = false;
|
||||
|
||||
if (context->cursor == context->tcase->count) {
|
||||
snprintf(context->msg, context->msgmax, "ARP module sent an unexpected packet");
|
||||
context->output_as_expected = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const arp_testcase_packet_t *packet = context->tcase->packets + context->cursor;
|
||||
|
||||
if (packet->sender != ARP_TESTCASE_SENDER_HOST) {
|
||||
snprintf(context->msg, context->msgmax, "ARP module sent an unexpected packet");
|
||||
context->output_as_expected = false;
|
||||
return;
|
||||
}
|
||||
context->cursor++;
|
||||
|
||||
if (!memcmp(context->output, packet->data, sizeof(arp_packet_t)))
|
||||
context->output_as_expected = true;
|
||||
else {
|
||||
snprintf(context->msg, context->msgmax, "ARP module sent a different packet than expected");
|
||||
context->output_as_expected = false;
|
||||
}
|
||||
}
|
||||
|
||||
arp_testcase_result_t arp_testcase_run(arp_testcase_t tcase, char *msg, size_t msgmax)
|
||||
{
|
||||
if (tcase.failed)
|
||||
return ARP_TESTCASE_ABORTED;
|
||||
|
||||
arp_packet_t output;
|
||||
|
||||
testcase_contex_t context = {
|
||||
.output = &output,
|
||||
.tcase = &tcase,
|
||||
.cursor = 0,
|
||||
.msg = msg,
|
||||
.msgmax = msgmax,
|
||||
};
|
||||
|
||||
if (msgmax > 0)
|
||||
msg[0] = '\0';
|
||||
|
||||
arp_state_t state;
|
||||
arp_init(&state, tcase.self_ip, tcase.self_mac, &context, send_packet);
|
||||
arp_change_output_buffer(&state, &output, sizeof(output));
|
||||
|
||||
while (context.cursor < tcase.count) {
|
||||
|
||||
arp_testcase_packet_t *packet = tcase.packets + context.cursor++;
|
||||
|
||||
if (packet->sender != ARP_TESTCASE_SENDER_PEER) {
|
||||
snprintf(msg, msgmax, "ARP module didn't send packet");
|
||||
return ARP_TESTCASE_FAILED;
|
||||
}
|
||||
|
||||
// Initialize these
|
||||
context.output_as_expected = true;
|
||||
context.aborted_while_checking_sent_packets = false;
|
||||
|
||||
arp_process_result_t status = arp_process_packet(&state, packet->data, sizeof(arp_packet_t));
|
||||
|
||||
(void) status; // Not useful yet
|
||||
|
||||
// Before this point the arp_process_packet will have
|
||||
// sent some packets that were validated in the send_packet
|
||||
// callback. If the testcase didn't fail, the next
|
||||
// packet in the list will be sent by the peer.
|
||||
if (context.aborted_while_checking_sent_packets)
|
||||
return ARP_TESTCASE_ABORTED;
|
||||
if (!context.output_as_expected)
|
||||
return ARP_TESTCASE_FAILED;
|
||||
}
|
||||
|
||||
arp_free(&state);
|
||||
return ARP_TESTCASE_PASSED;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <stdbool.h>
|
||||
#include "../src/arp.h"
|
||||
|
||||
#define ARP_TESTCASE_MAX_PACKETS 1024
|
||||
|
||||
typedef enum {
|
||||
ARP_TESTCASE_SENDER_HOST,
|
||||
ARP_TESTCASE_SENDER_PEER,
|
||||
} arp_testcase_packet_sender_t;
|
||||
|
||||
typedef struct {
|
||||
arp_testcase_packet_sender_t sender;
|
||||
const char *data;
|
||||
} arp_testcase_packet_t;
|
||||
|
||||
typedef struct {
|
||||
bool failed;
|
||||
|
||||
ip_address_t self_ip;
|
||||
mac_address_t self_mac;
|
||||
|
||||
size_t count;
|
||||
arp_testcase_packet_t packets[ARP_TESTCASE_MAX_PACKETS];
|
||||
} arp_testcase_t;
|
||||
|
||||
typedef enum {
|
||||
ARP_TESTCASE_PASSED,
|
||||
ARP_TESTCASE_FAILED,
|
||||
ARP_TESTCASE_ABORTED,
|
||||
} arp_testcase_result_t;
|
||||
|
||||
void arp_testcase_init(arp_testcase_t *tcase, const char mac[static 6], const char ip[static 4]);
|
||||
void arp_testcase_free(arp_testcase_t *tcase);
|
||||
void arp_testcase_send(arp_testcase_t *tcase, const char data[static sizeof(arp_packet_t)]);
|
||||
void arp_testcase_recv(arp_testcase_t *tcase, const char data[static sizeof(arp_packet_t)]);
|
||||
arp_testcase_result_t arp_testcase_run(arp_testcase_t tcase, char *msg, size_t msgmax);
|
||||
Reference in New Issue
Block a user