ported to windows

This commit is contained in:
cozis
2023-05-16 00:21:04 +02:00
parent 43ee04a2db
commit b259bb74db
16 changed files with 317 additions and 282 deletions
+4 -4
View File
@@ -1,6 +1,6 @@
*.pcapng *.pcapng
loop
loop2 loop2
test_arp loop2.exe
test_arp_cov 3p/lib/*
report_arp_cov 3p/src/*
3p/include/*
+6
View File
@@ -0,0 +1,6 @@
[submodule "3p/libtuntap"]
path = 3p/libtuntap
url = https://github.com/cozis/libtuntap.git
[submodule "3p/tinycthread"]
path = 3p/tinycthread
url = https://github.com/tinycthread/tinycthread.git
Binary file not shown.
+1
Submodule 3p/tinycthread added at 6957fc8383
+91 -14
View File
@@ -1,22 +1,99 @@
ifeq ($(OS),Windows_NT)
OSNAME = windows
ifeq ($(PROCESSOR_ARCHITEW6432),AMD64)
ARCH = AMD64
else ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
ARCH = AMD64
else ifeq ($(PROCESSOR_ARCHITECTURE),x86)
ARCH = IA32
endif
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
OSNAME = linux
else ifeq ($(UNAME_S),Darwin)
OSNAME = osx
endif
UNAME_P := $(shell uname -p)
ifeq ($(UNAME_P),x86_64)
ARCH = AMD64
endif
ifneq ($(filter %86,$(UNAME_P)),)
ARCH = IA32
endif
ifneq ($(filter arm%,$(UNAME_P)),)
ARCH = ARM
endif
endif
ifeq ($(OSNAME),windows)
CC = gcc.exe
CXX = g++.exe
CFLAGS_PLATFORM =
LFLAGS_PLATFORM = -lws2_32
CMAKE_GENERATOR = "MinGW Makefiles"
else ifeq ($(OSNAME),linux)
CC = gcc
CXX = g++
CFLAGS_PLATFORM = -pthread
LFLAGS_PLATFORM =
CMAKE_GENERATOR = "Unix Makefiles"
else
endif
# One of: drmemory, valgrind
MEMDBG=valgrind
LIBDIR = 3p/lib/
INCDIR = 3p/include/
CFLAGS = $(CFLAGS_PLATFORM) -I$(INCDIR) -Iinclude/ -Wall -Wextra -DARP_DEBUG -DMICROTCP_DEBUG -DIP_DEBUG -DICMP_DEBUG -DTCP_DEBUG -DMICROTCP_BACKGROUND_THREAD -DMICROTCP_USING_TAP
LFLAGS = -ltuntap $(LFLAGS_PLATFORM) -L$(LIBDIR)
ifeq ($(MEMDBG),drmemory)
CFLAGS += -gdwarf-2
else
CFLAGS += -g
endif
INCDIR=3p/include
LIBDIR=3p/lib
.PHONY: all clean
all: loop2 all: loop2
loop2: 3p/lib/libtuntap.a: 3p/libtuntap/build/lib/libtuntap.a
gcc src/arp.c src/ip.c src/icmp.c src/tcp.c src/microtcp.c test/loop2.c -o loop2 -Wall -Wextra -g -DARP_DEBUG -DMICROTCP_DEBUG -DIP_DEBUG -DICMP_DEBUG -DTCP_DEBUG -DMICROTCP_BACKGROUND_THREAD -DMICROTCP_USING_TAP -pthread -ltuntap -Iinclude/ -I3p/include/ -L3p/lib/ cp 3p/libtuntap/build/lib/libtuntap.a $(LIBDIR)
loop: 3p/include/tuntap.h: 3p/libtuntap/tuntap.h
gcc src/arp.c src/ip.c src/icmp.c src/tcp.c src/microtcp.c src/microtcp_linux.c test/loop.c -o loop -Wall -Wextra -g -DARP_DEBUG -DMICROTCP_DEBUG -DIP_DEBUG -DICMP_DEBUG -DTCP_DEBUG -DMICROTCP_BACKGROUND_THREAD -DMICROTCP_LINUX -pthread -Iinclude/ # -fsanitize=thread cp 3p/libtuntap/tuntap.h $(INCDIR)
test_arp: 3p/include/tuntap-export.h: 3p/libtuntap/build/tuntap-export.h
gcc src/arp.c test/test_arp.c test/test_arp_util.c -o test_arp -Wall -Wextra -g -Iinclude/ cp 3p/libtuntap/build/tuntap-export.h $(INCDIR)
test_arp_cov: 3p/libtuntap/build/lib/libtuntap.a 3p/libtuntap/tuntap.h 3p/libtuntap/build/tuntap-export.h:
gcc src/arp.c test/test_arp.c test/test_arp_util.c -o test_arp_cov -Wall -Wextra -g -fprofile-arcs -ftest-coverage -lgcov cd 3p/libtuntap/ \
&& mkdir -p build \
&& cd build \
&& cmake .. -G $(CMAKE_GENERATOR) \
-DBUILD_TESTING=OFF \
-DCMAKE_C_COMPILER=$(CC) \
-DCMAKE_CXX_COMPILER=$(CXX) \
-DCMAKE_BUILD_TYPE=Debug \
&& make
report_arp_cov: test_arp_cov 3p/include/tinycthread.h: 3p/tinycthread/source/tinycthread.h
./test_arp_cov cp 3p/tinycthread/source/tinycthread.h 3p/include
lcov --capture --directory . --output-file coverage.info --rc lcov_branch_coverage=1
genhtml coverage.info --output-directory report_arp_cov --rc lcov_branch_coverage=1 3p/src/tinycthread.c: 3p/tinycthread/source/tinycthread.c
rm *.gcda *.gcno coverage.info cp 3p/tinycthread/source/tinycthread.c 3p/src
loop2: $(LIBDIR)/libtuntap.a 3p/include/tuntap.h 3p/include/tuntap-export.h 3p/src/tinycthread.c 3p/include/tinycthread.h
gcc src/endian.c src/arp.c src/ip.c src/icmp.c src/tcp.c src/microtcp.c test/loop2.c 3p/src/tinycthread.c -o loop2 $(CFLAGS) $(LFLAGS)
clean: clean:
rm -f loop rm -f loop2 loop2.exe
rm -fr 3p/libtuntap/build
rm -f 3p/lib/* 3p/include/*
+8 -8
View File
@@ -115,7 +115,7 @@ struct ethhdr {
*/ */
#include <stdbool.h> #include <stdbool.h>
#include <arpa/inet.h> #include "endian.h"
#include "arp.h" #include "arp.h"
#ifdef ARP_DEBUG #ifdef ARP_DEBUG
@@ -616,11 +616,11 @@ void arp_resolve_mac(arp_state_t *state, ip_address_t ip, void *userp, void (*ca
append_pending_request_to_used_list(state, pending_request); append_pending_request_to_used_list(state, pending_request);
arp_packet_t *packet = state->output; arp_packet_t *packet = state->output;
packet->hardware_type = htons(ARP_HARDWARE_ETHERNET); packet->hardware_type = cpu_to_net_u16(ARP_HARDWARE_ETHERNET);
packet->protocol_type = htons(ARP_PROTOCOL_IP); packet->protocol_type = cpu_to_net_u16(ARP_PROTOCOL_IP);
packet->hardware_len = 6; packet->hardware_len = 6;
packet->protocol_len = 4; packet->protocol_len = 4;
packet->operation_type = htons(ARP_OPERATION_REQUEST); packet->operation_type = cpu_to_net_u16(ARP_OPERATION_REQUEST);
packet->sender_hardware_address = state->self_mac; packet->sender_hardware_address = state->self_mac;
packet->sender_protocol_address = state->self_ip; packet->sender_protocol_address = state->self_ip;
packet->target_hardware_address = MAC_ZERO; // This is what we're trying to find packet->target_hardware_address = MAC_ZERO; // This is what we're trying to find
@@ -677,13 +677,13 @@ arp_process_result_t arp_process_packet(arp_state_t *state, const void *packet,
const arp_packet_t *packet2 = packet; const arp_packet_t *packet2 = packet;
if (packet2->hardware_type != htons(ARP_HARDWARE_ETHERNET)) { if (packet2->hardware_type != cpu_to_net_u16(ARP_HARDWARE_ETHERNET)) {
/* Level 2 protocol not supported */ /* Level 2 protocol not supported */
ARP_DEBUG_LOG("Hardware type %d not supported", packet2->hardware_type); ARP_DEBUG_LOG("Hardware type %d not supported", packet2->hardware_type);
return ARP_PROCESS_RESULT_HWARENOTSUPP; return ARP_PROCESS_RESULT_HWARENOTSUPP;
} }
if (packet2->protocol_type != htons(ARP_PROTOCOL_IP)) { if (packet2->protocol_type != cpu_to_net_u16(ARP_PROTOCOL_IP)) {
/* Level 3 protocol not supported */ /* Level 3 protocol not supported */
ARP_DEBUG_LOG("Protocol type %d not supported", packet2->protocol_type); ARP_DEBUG_LOG("Protocol type %d not supported", packet2->protocol_type);
return ARP_PROCESS_RESULT_PROTONOTSUPP; return ARP_PROCESS_RESULT_PROTONOTSUPP;
@@ -707,7 +707,7 @@ arp_process_result_t arp_process_packet(arp_state_t *state, const void *packet,
packet2->sender_hardware_address); packet2->sender_hardware_address);
} }
if (packet2->operation_type == htons(ARP_OPERATION_REQUEST)) { if (packet2->operation_type == cpu_to_net_u16(ARP_OPERATION_REQUEST)) {
// Generate the ARP REPLY // Generate the ARP REPLY
@@ -716,7 +716,7 @@ arp_process_result_t arp_process_packet(arp_state_t *state, const void *packet,
response->protocol_type = packet2->protocol_type; response->protocol_type = packet2->protocol_type;
response->hardware_len = packet2->hardware_len; response->hardware_len = packet2->hardware_len;
response->protocol_len = packet2->protocol_len; response->protocol_len = packet2->protocol_len;
response->operation_type = htons(ARP_OPERATION_REPLY); response->operation_type = cpu_to_net_u16(ARP_OPERATION_REPLY);
response->sender_hardware_address = state->self_mac; response->sender_hardware_address = state->self_mac;
response->sender_protocol_address = state->self_ip; response->sender_protocol_address = state->self_ip;
response->target_hardware_address = packet2->sender_hardware_address; response->target_hardware_address = packet2->sender_hardware_address;
+51
View File
@@ -0,0 +1,51 @@
#include <stdbool.h>
#include "endian.h"
static bool cpu_is_little_endian(void)
{
uint16_t x = 1;
return *((uint8_t*) &x);
}
static uint16_t invert_byte_order_u16(uint32_t n)
{
return (n >> 8)
| (n << 8);
}
static uint32_t invert_byte_order_u32(uint32_t n)
{
return ((n >> 24) & 0x000000FF)
| ((n >> 8) & 0x0000FF00)
| ((n << 8) & 0x00FF0000)
| ((n << 24) & 0xFF000000);
}
uint16_t net_to_cpu_u16(uint16_t n)
{
if (cpu_is_little_endian())
return invert_byte_order_u16(n);
return n;
}
uint32_t net_to_cpu_u32(uint32_t n)
{
if (cpu_is_little_endian())
return invert_byte_order_u32(n);
return n;
}
uint16_t cpu_to_net_u16(uint16_t n)
{
if (cpu_is_little_endian())
return invert_byte_order_u16(n);
return n;
}
uint32_t cpu_to_net_u32(uint32_t n)
{
if (cpu_is_little_endian())
return invert_byte_order_u32(n);
return n;
}
+6
View File
@@ -0,0 +1,6 @@
#include <stdint.h>
uint16_t net_to_cpu_u16(uint16_t n);
uint32_t net_to_cpu_u32(uint32_t n);
uint16_t cpu_to_net_u16(uint16_t n);
uint32_t cpu_to_net_u32(uint32_t n);
+3 -3
View File
@@ -1,5 +1,5 @@
#include <string.h> #include <string.h>
#include <arpa/inet.h> #include "endian.h"
#include "icmp.h" #include "icmp.h"
#ifdef ICMP_DEBUG #ifdef ICMP_DEBUG
@@ -57,12 +57,12 @@ static uint16_t calculate_checksum_icmp(const void *src, size_t len)
uint32_t sum = 0xffff; uint32_t sum = 0xffff;
for (size_t i = 0; i < len/2; i++) { for (size_t i = 0; i < len/2; i++) {
sum += ntohs(src2[i]); sum += net_to_cpu_u16(src2[i]);
if (sum > 0xffff) if (sum > 0xffff)
sum -= 0xffff; sum -= 0xffff;
} }
return htons(~sum); return cpu_to_net_u16(~sum);
} }
void icmp_process_packet(icmp_state_t *state, ip_address_t ip, const void *src, size_t len) void icmp_process_packet(icmp_state_t *state, ip_address_t ip, const void *src, size_t len)
+8 -8
View File
@@ -1,5 +1,5 @@
#include <string.h> #include <string.h>
#include <arpa/inet.h> // ntohs() #include "endian.h"
#include "ip.h" #include "ip.h"
#ifdef IP_DEBUG #ifdef IP_DEBUG
@@ -18,12 +18,12 @@ static uint16_t calculate_checksum_ip(const void *src, size_t len)
uint32_t sum = 0xffff; uint32_t sum = 0xffff;
for (size_t i = 0; i < len/2; i++) { for (size_t i = 0; i < len/2; i++) {
sum += ntohs(src2[i]); sum += net_to_cpu_u16(src2[i]);
if (sum > 0xffff) if (sum > 0xffff)
sum -= 0xffff; sum -= 0xffff;
} }
return htons(~sum); return cpu_to_net_u16(~sum);
} }
@@ -59,8 +59,8 @@ bool ip_plug_protocol(ip_state_t *ip_state, uint8_t protocol,
static bool is_packet_one_of_more_fragments(const ip_packet_t *packet) static bool is_packet_one_of_more_fragments(const ip_packet_t *packet)
{ {
size_t offset = ntohs(packet->fragment_offset) & 0x1FFF; size_t offset = net_to_cpu_u16(packet->fragment_offset) & 0x1FFF;
bool more_fragments = ntohs(packet->fragment_offset) & 0x2000; bool more_fragments = net_to_cpu_u16(packet->fragment_offset) & 0x2000;
return more_fragments || offset; return more_fragments || offset;
} }
@@ -73,7 +73,7 @@ static void send_icmp_packet(void *data, ip_address_t ip, size_t len)
packet->version = 4; packet->version = 4;
packet->header_length = 5; packet->header_length = 5;
packet->type_of_service = 0; // ??? packet->type_of_service = 0; // ???
packet->total_length = htons(sizeof(ip_packet_t) + len); packet->total_length = cpu_to_net_u16(sizeof(ip_packet_t) + len);
packet->id = ip_state->next_id++; packet->id = ip_state->next_id++;
packet->fragment_offset = 0; // ??? packet->fragment_offset = 0; // ???
packet->time_to_live = 32; // ??? packet->time_to_live = 32; // ???
@@ -166,7 +166,7 @@ int ip_send_2(ip_state_t *state, ip_protocol_t protocol, ip_address_t dst,
packet->version = 4; packet->version = 4;
packet->header_length = 5; packet->header_length = 5;
packet->type_of_service = 0; // ??? packet->type_of_service = 0; // ???
packet->total_length = htons(sizeof(ip_packet_t) + considered_payload); packet->total_length = cpu_to_net_u16(sizeof(ip_packet_t) + considered_payload);
packet->id = state->next_id++; packet->id = state->next_id++;
packet->fragment_offset = 0; // ??? packet->fragment_offset = 0; // ???
packet->time_to_live = 32; // ??? packet->time_to_live = 32; // ???
@@ -231,7 +231,7 @@ void ip_process_packet(ip_state_t *ip_state, const void *packet, size_t len)
ip_plugged_protocol_t *handler = find_protocol_with_id(ip_state, packet2->protocol); ip_plugged_protocol_t *handler = find_protocol_with_id(ip_state, packet2->protocol);
const void *packet3_ptr = packet2+1; const void *packet3_ptr = packet2+1;
size_t packet3_len = ntohs(packet2->total_length) - sizeof(ip_packet_t); size_t packet3_len = net_to_cpu_u16(packet2->total_length) - sizeof(ip_packet_t);
if (handler) if (handler)
handler->process_packet(handler->data, packet2->src_ip, packet3_ptr, packet3_len); handler->process_packet(handler->data, packet2->src_ip, packet3_ptr, packet3_len);
+116 -44
View File
@@ -1,13 +1,13 @@
#include <time.h> // time() #include <time.h> // time()
#include <ctype.h>
#include <errno.h> #include <errno.h>
#include <string.h> // strerror() #include <string.h> // strerror()
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h> // inet_pton
#include "ip.h" #include "ip.h"
#include "arp.h" #include "arp.h"
#include "tcp.h" #include "tcp.h"
#include "endian.h"
#include <microtcp.h> #include <microtcp.h>
#ifdef MICROTCP_USING_TAP #ifdef MICROTCP_USING_TAP
@@ -15,7 +15,7 @@
#endif #endif
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
#include <pthread.h> #include "tinycthread.h"
#endif #endif
#ifdef MICROTCP_DEBUG #ifdef MICROTCP_DEBUG
@@ -26,8 +26,8 @@
#endif #endif
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
#define LOCK_WHEN_THREADED(mtcp) do { pthread_mutex_lock(&(mtcp)->lock); } while (0); #define LOCK_WHEN_THREADED(mtcp) do { mtx_lock(&(mtcp)->lock); } while (0);
#define UNLOCK_WHEN_THREADED(mtcp) do { pthread_mutex_unlock(&(mtcp)->lock); } while (0); #define UNLOCK_WHEN_THREADED(mtcp) do { mtx_unlock(&(mtcp)->lock); } while (0);
#else #else
#define LOCK_WHEN_THREADED(mtcp) do { (void) (mtcp); } while (0); #define LOCK_WHEN_THREADED(mtcp) do { (void) (mtcp); } while (0);
#define UNLOCK_WHEN_THREADED(mtcp) do { (void) (mtcp); } while (0); #define UNLOCK_WHEN_THREADED(mtcp) do { (void) (mtcp); } while (0);
@@ -58,10 +58,10 @@ struct microtcp_socket_t {
}; };
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
union { union {
pthread_cond_t something_to_accept; cnd_t something_to_accept;
struct { struct {
pthread_cond_t something_to_recv; cnd_t something_to_recv;
pthread_cond_t something_to_send; cnd_t something_to_send;
}; };
}; };
#endif #endif
@@ -73,8 +73,8 @@ struct microtcp_t {
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
bool thread_should_stop; bool thread_should_stop;
pthread_t thread_id; thrd_t thread_id;
pthread_mutex_t lock; mtx_t lock;
#endif #endif
microtcp_callbacks_t callbacks; microtcp_callbacks_t callbacks;
@@ -147,7 +147,7 @@ static void send_arp_packet(void *data, mac_address_t dst)
ethernet_frame_t *frame = (ethernet_frame_t*) buffer->data; ethernet_frame_t *frame = (ethernet_frame_t*) buffer->data;
frame->dst = dst; frame->dst = dst;
frame->src = mtcp->mac; frame->src = mtcp->mac;
frame->proto = htons(ETHERNET_PROTOCOL_ARP); frame->proto = cpu_to_net_u16(ETHERNET_PROTOCOL_ARP);
// TODO: What about the CRC? // TODO: What about the CRC?
#warning "TODO: Calculate Ethernet CRC" #warning "TODO: Calculate Ethernet CRC"
@@ -317,7 +317,7 @@ static void send_ip_packet(void *data, ip_address_t ip, size_t len)
ethernet_frame_t *frame = (ethernet_frame_t*) buffer->data; ethernet_frame_t *frame = (ethernet_frame_t*) buffer->data;
frame->src = mtcp->mac; frame->src = mtcp->mac;
frame->dst = MAC_ZERO; // We need to determine it frame->dst = MAC_ZERO; // We need to determine it
frame->proto = htons(ETHERNET_PROTOCOL_IP); frame->proto = cpu_to_net_u16(ETHERNET_PROTOCOL_IP);
arp_resolve_mac(&mtcp->arp_state, ip, buffer, mac_resolved); arp_resolve_mac(&mtcp->arp_state, ip, buffer, mac_resolved);
} }
@@ -337,7 +337,7 @@ process_packet(microtcp_t *mtcp, const void *packet, size_t len)
const ethernet_frame_t *frame = packet; const ethernet_frame_t *frame = packet;
switch (ntohs(frame->proto)) { switch (net_to_cpu_u16(frame->proto)) {
case ETHERNET_PROTOCOL_ARP: case ETHERNET_PROTOCOL_ARP:
arp_process_packet(&mtcp->arp_state, frame+1, len - sizeof(ethernet_frame_t)); arp_process_packet(&mtcp->arp_state, frame+1, len - sizeof(ethernet_frame_t));
break; break;
@@ -362,7 +362,8 @@ void microtcp_process_packet(microtcp_t *mtcp, const void *packet, size_t len)
void microtcp_step(microtcp_t *mtcp) void microtcp_step(microtcp_t *mtcp)
{ {
char packet[UINT16_MAX]; char packet[1024]; // This buffer is the bottleneck for the
// maximum packet size that can be processed.
// The call to [recv] (which is assumed to be blocking) // The call to [recv] (which is assumed to be blocking)
// needs to be out of the critical section to give other // needs to be out of the critical section to give other
@@ -389,12 +390,12 @@ void microtcp_step(microtcp_t *mtcp)
} }
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
static void *loop(void *data) static int loop(void *data)
{ {
microtcp_t *mtcp = data; microtcp_t *mtcp = data;
while (!mtcp->thread_should_stop) while (!mtcp->thread_should_stop)
microtcp_step(mtcp); microtcp_step(mtcp);
return NULL; return 0;
} }
#endif #endif
@@ -474,7 +475,46 @@ static mac_address_t generate_random_mac()
static bool parse_ip(const char *ip, ip_address_t *parsed_ip) static bool parse_ip(const char *ip, ip_address_t *parsed_ip)
{ {
return inet_pton(AF_INET, ip, parsed_ip) == 1; size_t len = strlen(ip);
size_t i = 0;
uint32_t value = 0;
for (size_t k = 0; k < 4; k++) {
if (i == len || !isdigit(ip[i]))
return false;
int n = 0; // Used to represent a byte, but it's larger
// to detect overflows.
do {
// Convert character to number
int digit = ip[i] - '0';
if (n > (UINT8_MAX - digit)/10)
// Adding this digit would make the
// byte overflow, so it can't be part
// of the octet.
break;
n = n * 10 + digit;
i++;
} while (i < len && isdigit(ip[i]));
assert(n >= 0 && n <= UINT8_MAX);
value = (value << 8) | (uint8_t) n;
// If this isn't the last octet and there is no
// dot following it, the address is invalid.
if (k < 3) {
if (i == len || ip[i] != '.')
return false;
i++; // Consume the dot.
}
}
if (i < len)
// source string contains something
// other than the address in it.
return false;
*parsed_ip = value;
return true;
} }
microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac, microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac,
@@ -542,7 +582,7 @@ microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac,
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
{ {
if (pthread_mutex_init(&mtcp->lock, NULL)) { if (mtx_init(&mtcp->lock, mtx_plain) != thrd_success) {
ip_free(&mtcp->ip_state); ip_free(&mtcp->ip_state);
arp_free(&mtcp->arp_state); arp_free(&mtcp->arp_state);
tcp_free(&mtcp->tcp_state); tcp_free(&mtcp->tcp_state);
@@ -550,10 +590,11 @@ microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac,
return NULL; return NULL;
} }
mtcp->thread_should_stop = false; mtcp->thread_should_stop = false;
if (pthread_create(&mtcp->thread_id, NULL, loop, mtcp)) { if (thrd_create(&mtcp->thread_id, loop, mtcp) != thrd_success) {
ip_free(&mtcp->ip_state); ip_free(&mtcp->ip_state);
arp_free(&mtcp->arp_state); arp_free(&mtcp->arp_state);
tcp_free(&mtcp->tcp_state); tcp_free(&mtcp->tcp_state);
mtx_destroy(&mtcp->lock);
free(mtcp); free(mtcp);
return NULL; return NULL;
} }
@@ -581,6 +622,28 @@ microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac,
#ifdef MICROTCP_USING_TAP #ifdef MICROTCP_USING_TAP
static void log_callback_for_tuntap_library(int level, const char *errmsg)
{
const char *name;
switch(level) {
case TUNTAP_LOG_DEBUG : name = "Debug"; break;
case TUNTAP_LOG_INFO : name = "Info"; break;
case TUNTAP_LOG_NOTICE: name = "Notice"; break;
case TUNTAP_LOG_WARN : name = "Warning"; break;
case TUNTAP_LOG_ERR : name = "Error"; break;
case TUNTAP_LOG_NONE:
default:
name = NULL;
break;
}
if (name == NULL) {
MICROTCP_DEBUG_LOG("%s (from the tap library)", errmsg);
} else {
MICROTCP_DEBUG_LOG("[%s] %s (from the tap library)", name, errmsg);
}
}
bool microtcp_callbacks_create_for_tap(const char *ip, const char *mac, bool microtcp_callbacks_create_for_tap(const char *ip, const char *mac,
microtcp_callbacks_t *callbacks) microtcp_callbacks_t *callbacks)
{ {
@@ -590,15 +653,21 @@ bool microtcp_callbacks_create_for_tap(const char *ip, const char *mac,
if (!dev) if (!dev)
return false; return false;
// This must be set AFTER tuntap_init because
// it sets the callback function to the default
// callback which writes to stderr.
tuntap_log_set_cb(log_callback_for_tuntap_library);
int netmask = 24; // TODO: Make this configurable int netmask = 24; // TODO: Make this configurable
if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) || if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY))
tuntap_set_ip(dev, ip, netmask) || goto cleanup;
tuntap_set_hwaddr(dev, mac ? mac : "random") ||
tuntap_up(dev)) { tuntap_set_ip(dev, ip, netmask);
tuntap_release(dev); tuntap_set_hwaddr(dev, mac ? mac : "random");
return false;
} if (tuntap_up(dev))
goto cleanup;
*callbacks = (microtcp_callbacks_t) { *callbacks = (microtcp_callbacks_t) {
.data = dev, .data = dev,
@@ -608,6 +677,10 @@ bool microtcp_callbacks_create_for_tap(const char *ip, const char *mac,
}; };
return true; return true;
cleanup:
tuntap_release(dev);
return false;
} }
microtcp_t *microtcp_create(const char *tap_ip, const char *stack_ip, microtcp_t *microtcp_create(const char *tap_ip, const char *stack_ip,
@@ -628,8 +701,8 @@ void microtcp_destroy(microtcp_t *mtcp)
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
MICROTCP_DEBUG_LOG("Stopping thread"); MICROTCP_DEBUG_LOG("Stopping thread");
mtcp->thread_should_stop = true; mtcp->thread_should_stop = true;
pthread_join(mtcp->thread_id, NULL); thrd_join(mtcp->thread_id, NULL);
pthread_mutex_destroy(&mtcp->lock); mtx_destroy(&mtcp->lock);
MICROTCP_DEBUG_LOG("Thread stopped"); MICROTCP_DEBUG_LOG("Thread stopped");
#endif #endif
@@ -689,7 +762,7 @@ static void ready_to_accept(void *data)
{ {
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
microtcp_socket_t *socket = data; microtcp_socket_t *socket = data;
pthread_cond_signal(&socket->something_to_accept); cnd_signal(&socket->something_to_accept);
#else #else
(void) data; (void) data;
#endif #endif
@@ -723,7 +796,7 @@ microtcp_socket_t *microtcp_open(microtcp_t *mtcp, uint16_t port,
socket->listener = listener; socket->listener = listener;
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
if (pthread_cond_init(&socket->something_to_accept, NULL)) { if (cnd_init(&socket->something_to_accept) != thrd_success) {
errcode2 = MICROTCP_ERRCODE_BADCONDVAR; errcode2 = MICROTCP_ERRCODE_BADCONDVAR;
push_unlinked_socket_into_free_list(mtcp, socket); push_unlinked_socket_into_free_list(mtcp, socket);
tcp_listener_destroy(listener); tcp_listener_destroy(listener);
@@ -752,7 +825,7 @@ void microtcp_close(microtcp_socket_t *socket)
case SOCKET_LISTENER: case SOCKET_LISTENER:
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
pthread_cond_destroy(&socket->something_to_accept); cnd_destroy(&socket->something_to_accept);
#endif #endif
tcp_listener_destroy(socket->listener); tcp_listener_destroy(socket->listener);
break; break;
@@ -772,7 +845,7 @@ static void ready_to_recv(void *data)
{ {
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
microtcp_socket_t *socket = data; microtcp_socket_t *socket = data;
pthread_cond_signal(&socket->something_to_recv); cnd_signal(&socket->something_to_recv);
#else #else
(void) data; (void) data;
#endif #endif
@@ -782,7 +855,7 @@ static void ready_to_send(void *data)
{ {
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
microtcp_socket_t *socket = data; microtcp_socket_t *socket = data;
pthread_cond_signal(&socket->something_to_send); cnd_signal(&socket->something_to_send);
#else #else
(void) data; (void) data;
#endif #endif
@@ -813,7 +886,8 @@ microtcp_socket_t *microtcp_accept(microtcp_socket_t *socket,
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
while (!connection && !no_block) { while (!connection && !no_block) {
pthread_cond_wait(&socket->something_to_accept, &mtcp->lock); if (cnd_wait(&socket->something_to_accept, &mtcp->lock) != thrd_success)
abort();
connection = tcp_listener_accept(socket->listener, socket2, ready_to_recv, ready_to_send); connection = tcp_listener_accept(socket->listener, socket2, ready_to_recv, ready_to_send);
} }
#else #else
@@ -831,14 +905,15 @@ microtcp_socket_t *microtcp_accept(microtcp_socket_t *socket,
socket2->connection = connection; socket2->connection = connection;
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
if (pthread_cond_init(&socket2->something_to_recv, NULL)) { if (cnd_init(&socket2->something_to_recv) != thrd_success) {
errcode2 = MICROTCP_ERRCODE_BADCONDVAR; errcode2 = MICROTCP_ERRCODE_BADCONDVAR;
push_unlinked_socket_into_free_list(mtcp, socket2); push_unlinked_socket_into_free_list(mtcp, socket2);
tcp_connection_destroy(connection); tcp_connection_destroy(connection);
goto unlock_and_exit; goto unlock_and_exit;
} }
if (pthread_cond_init(&socket2->something_to_send, NULL)) { if (cnd_init(&socket2->something_to_send) != thrd_success) {
errcode2 = MICROTCP_ERRCODE_BADCONDVAR; errcode2 = MICROTCP_ERRCODE_BADCONDVAR;
cnd_destroy(&socket2->something_to_recv);
push_unlinked_socket_into_free_list(mtcp, socket2); push_unlinked_socket_into_free_list(mtcp, socket2);
tcp_connection_destroy(connection); tcp_connection_destroy(connection);
goto unlock_and_exit; goto unlock_and_exit;
@@ -878,7 +953,8 @@ size_t microtcp_recv(microtcp_socket_t *socket,
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
while (num == 0 && !no_block) { while (num == 0 && !no_block) {
pthread_cond_wait(&socket->something_to_recv, &mtcp->lock); if (cnd_wait(&socket->something_to_recv, &mtcp->lock) != thrd_success)
abort();
num = tcp_connection_recv(socket->connection, dst, len); num = tcp_connection_recv(socket->connection, dst, len);
} }
#else #else
@@ -918,19 +994,15 @@ size_t microtcp_send(microtcp_socket_t *socket,
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
while (num == 0 && !no_block) { while (num == 0 && !no_block) {
pthread_cond_wait(&socket->something_to_send, &mtcp->lock); if (cnd_wait(&socket->something_to_send, &mtcp->lock) != thrd_success)
abort();
num = tcp_connection_send(socket->connection, src, len); num = tcp_connection_send(socket->connection, src, len);
} }
#else #else
if (num == 0 && !no_block) { if (num == 0 && !no_block)
errcode2 = MICROTCP_ERRCODE_CANTBLOCK; errcode2 = MICROTCP_ERRCODE_CANTBLOCK;
goto unlock_and_exit;
}
#endif #endif
} }
unlock_and_exit:
UNLOCK_WHEN_THREADED(mtcp); UNLOCK_WHEN_THREADED(mtcp);
if (errcode) if (errcode)
-182
View File
@@ -1,182 +0,0 @@
/*
#ifdef MICROTCP_LINUX
#include <poll.h>
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <net/if_arp.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "defs.h"
#include "microtcp.h"
static int systemf(const char *fmt, ...)
{
char buffer[256];
va_list va;
va_start(va, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, va);
va_end(va);
fprintf(stderr, "INFO: Running [%s]\n", buffer);
return system(buffer);
}
static int create_tun_device(const char *dev, char dev2[IFNAMSIZ])
{
int fd = open("/dev/net/tun", O_RDWR);
if (fd < 0)
return -1;
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
if (dev && *dev)
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
int err = ioctl(fd, TUNSETIFF, &ifr);
if (err) {
close(fd);
return -1;
}
strncpy(dev2, ifr.ifr_name, IFNAMSIZ);
return fd;
}
static int send_callback(void *data, const void *src, size_t len)
{
int tap_fd = (int) data;
return write(tap_fd, src, len);
}
static int recv_callback(void *data, void *dst, size_t len)
{
int tap_fd = (int) data;
int timeout = 1000;
struct pollfd pfd = {.fd=tap_fd, .events=POLLIN};
int status = poll(&pfd, 1, timeout);
if (status < 1) {
return status;
}
int num = read(tap_fd, dst, len);
return num;
}
static void free_callback(void *data)
{
int tap_fd = (int) data;
close(tap_fd);
}
static bool get_ip_address(const char *dev, microtcp_ip_t *ip)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
return false;
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, dev, IFNAMSIZ-1);
ioctl(fd, SIOCGIFADDR, &ifr);
memcpy(ip, &((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr, sizeof(microtcp_ip_t));
close(fd);
return true;
}
static bool get_mac_address(const char *dev, microtcp_mac_t *mac)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
return false;
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev, IFNAMSIZ-1);
ioctl(fd, SIOCGIFHWADDR, &ifr);
if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
return false;
memcpy(mac, ifr.ifr_hwaddr.sa_data, sizeof(microtcp_mac_t));
close(fd);
return true;
}
microtcp_t *microtcp_create()
{
char dev[IFNAMSIZ];
int tap_fd = create_tun_device("tap0", dev);
if (tap_fd < 0) {
fprintf(stderr, "ERROR: Failed creating TAP device (%s)\n", strerror(errno));
return NULL;
}
fprintf(stderr, "INFO: Using TAP device %s\n", dev);
const char *tap_addr = "10.0.0.5";
const char *tap_route = "10.0.0.0/24";
systemf("ip link set dev %s up", dev);
systemf("ip route add dev %s %s", dev, tap_route);
systemf("ip address add dev %s local %s", dev, tap_addr);
systemf("sudo sysctl -w net.ipv4.ip_forward=1");
microtcp_mac_t mac;
if (!get_mac_address(dev, &mac)) {
fprintf(stderr, "FATAL: Failed to query NIC for IP or MAC (%s)\n", strerror(errno));
close(tap_fd);
return NULL;
}
mac.data[5]++;
microtcp_ip_t ip;
inet_pton(AF_INET, "10.0.0.4", &ip);
struct in_addr ip2;
ip2.s_addr = ip;
fprintf(stderr, "INFO: Using IP %s\n", inet_ntoa(ip2));
fprintf(stderr, "INFO: Using MAC %x:%x:%x:%x:%x:%x\n", mac.data[0], mac.data[1], mac.data[2], mac.data[3], mac.data[4], mac.data[5]);
microtcp_callbacks_t callbacks = {
.data = (int) tap_fd,
.send = send_callback,
.recv = recv_callback,
.free = free_callback,
};
microtcp_t *mtcp = microtcp_create_using_callbacks(ip, mac, callbacks);
if (!mtcp) {
close(tap_fd);
return NULL;
}
return mtcp;
}
#endif /* MICROTCP_LINUX */
+13 -13
View File
@@ -1,6 +1,6 @@
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <arpa/inet.h> #include "endian.h"
#include "tcp.h" #include "tcp.h"
#ifdef TCP_DEBUG #ifdef TCP_DEBUG
@@ -186,13 +186,13 @@ calculate_checksum(const slice_list_t *slices, size_t num_slices)
const size_t len = slices[slice_idx].len; const size_t len = slices[slice_idx].len;
for (size_t i = 0; i < len/2; i++) { for (size_t i = 0; i < len/2; i++) {
sum += ntohs(src[i]); sum += net_to_cpu_u16(src[i]);
if (sum > 0xffff) if (sum > 0xffff)
sum -= 0xffff; sum -= 0xffff;
} }
} }
return htons(~sum); return cpu_to_net_u32(~sum);
} }
static void static void
@@ -249,14 +249,14 @@ static void emit_segment(tcp_connection_t *connection, bool ack, bool syn, size_
// seq_no++; // seq_no++;
tcp_segment_t header = { tcp_segment_t header = {
.src_port = htons(listener->port), .src_port = cpu_to_net_u32(listener->port),
.dst_port = htons(connection->peer_port), .dst_port = cpu_to_net_u32(connection->peer_port),
.flags = flags, .flags = flags,
.seq_no = htonl(seq_no), .seq_no = cpu_to_net_u32(seq_no),
.ack_no = htonl(ack_no), .ack_no = cpu_to_net_u32(ack_no),
.offset = 5, // No options .offset = 5, // No options
.unused = 0, .unused = 0,
.window = htons(connection->rcv_wnd), .window = cpu_to_net_u32(connection->rcv_wnd),
.checksum = 0, // Will be calculated later .checksum = 0, // Will be calculated later
.urgent_pointer = 0, .urgent_pointer = 0,
}; };
@@ -266,7 +266,7 @@ static void emit_segment(tcp_connection_t *connection, bool ack, bool syn, size_
.dst_addr = connection->peer_ip, .dst_addr = connection->peer_ip,
.reserved = 0, .reserved = 0,
.protocol = 6, // TCP .protocol = 6, // TCP
.tcp_length = htons(total_segment_size), .tcp_length = cpu_to_net_u32(total_segment_size),
}; };
header.checksum = calculate_checksum((slice_list_t[]) { header.checksum = calculate_checksum((slice_list_t[]) {
@@ -329,8 +329,8 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender,
if (len < sizeof(tcp_segment_t)) if (len < sizeof(tcp_segment_t))
return; return;
uint16_t reordered_dst_port = ntohs(segment->dst_port); uint16_t reordered_dst_port = net_to_cpu_u16(segment->dst_port);
uint16_t reordered_src_port = ntohs(segment->src_port); uint16_t reordered_src_port = net_to_cpu_u16(segment->src_port);
tcp_listener_t *listener = find_listener_with_port(state, reordered_dst_port); tcp_listener_t *listener = find_listener_with_port(state, reordered_dst_port);
if (listener == NULL) { if (listener == NULL) {
@@ -362,7 +362,7 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender,
// Temporary // Temporary
uint32_t seq_no = choose_sequence_no(); uint32_t seq_no = choose_sequence_no();
uint32_t ack_no = ntohl(segment->seq_no)+1; uint32_t ack_no = net_to_cpu_u32(segment->seq_no)+1;
tcp_connection_t *connection = connection_create_waiting_for_ack(listener, seq_no, ack_no, sender, reordered_src_port); tcp_connection_t *connection = connection_create_waiting_for_ack(listener, seq_no, ack_no, sender, reordered_src_port);
if (connection == NULL) { if (connection == NULL) {
@@ -389,7 +389,7 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender,
return; return;
} }
uint32_t ack_no = ntohl(segment->ack_no); uint32_t ack_no = net_to_cpu_u32(segment->ack_no);
if (ack_no <= connection->snd_una) if (ack_no <= connection->snd_una)
TCP_DEBUG_LOG("Received segment acknowledged again %d", ack_no); TCP_DEBUG_LOG("Received segment acknowledged again %d", ack_no);
+2
View File
@@ -1,3 +1,4 @@
/*
#include <stdio.h> #include <stdio.h>
#include <microtcp.h> #include <microtcp.h>
@@ -54,3 +55,4 @@ handled:
microtcp_destroy(mtcp); microtcp_destroy(mtcp);
return 0; return 0;
} }
*/
+6 -4
View File
@@ -6,8 +6,10 @@ int main(void)
microtcp_errcode_t errcode; microtcp_errcode_t errcode;
microtcp_t *mtcp = microtcp_create("10.0.0.5", "10.0.0.4", NULL, NULL); microtcp_t *mtcp = microtcp_create("10.0.0.5", "10.0.0.4", NULL, NULL);
if (mtcp == NULL) if (mtcp == NULL) {
fprintf(stderr, "Error: Failed to instanciate microtcp stack\n");
return -1; return -1;
}
uint16_t port = 80; uint16_t port = 80;
microtcp_socket_t *server = microtcp_open(mtcp, port, &errcode); microtcp_socket_t *server = microtcp_open(mtcp, port, &errcode);
@@ -36,21 +38,21 @@ int main(void)
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode)); fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
goto handled; goto handled;
} }
fprintf(stderr, "(%ld bytes received)\n", num); fprintf(stderr, "(%d bytes received)\n", (int) num);
size_t sent1 = microtcp_send(client, "echo: ", 6, false, &errcode); size_t sent1 = microtcp_send(client, "echo: ", 6, false, &errcode);
if (errcode) { if (errcode) {
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode)); fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
goto handled; goto handled;
} }
fprintf(stderr, "(%ld bytes sent 1)\n", sent1); fprintf(stderr, "(%d bytes sent 1)\n", (int) sent1);
size_t sent2 = microtcp_send(client, buffer, num, false, &errcode); size_t sent2 = microtcp_send(client, buffer, num, false, &errcode);
if (errcode) { if (errcode) {
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode)); fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
goto handled; goto handled;
} }
fprintf(stderr, "(%ld bytes sent 2)\n", sent2); fprintf(stderr, "(%d bytes sent 2)\n", (int) sent2);
handled: handled:
microtcp_close(client); microtcp_close(client);