first commit

This commit is contained in:
Francesco Cozzuto
2023-03-20 09:43:11 +01:00
commit 00e68532d1
22 changed files with 3401 additions and 0 deletions
+56
View File
@@ -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
View File
@@ -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;
}
+146
View File
@@ -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;
}
+36
View File
@@ -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);