diff --git a/.gitignore b/.gitignore index 2ac5bbb..14378ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ *.pcapng -loop loop2 -test_arp -test_arp_cov -report_arp_cov \ No newline at end of file +loop2.exe +3p/lib/* +3p/src/* +3p/include/* \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8e15dbc --- /dev/null +++ b/.gitmodules @@ -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 diff --git a/3p/lib/libtuntap.a b/3p/lib/libtuntap.a deleted file mode 100644 index 11c7c8b..0000000 Binary files a/3p/lib/libtuntap.a and /dev/null differ diff --git a/3p/libtuntap b/3p/libtuntap index ef7ed7b..5d4a7aa 160000 --- a/3p/libtuntap +++ b/3p/libtuntap @@ -1 +1 @@ -Subproject commit ef7ed7b4441624f825c1798ae79e0ddfc8edd4cb +Subproject commit 5d4a7aa886e2c1887c4b1b1193d569628509e564 diff --git a/3p/tinycthread b/3p/tinycthread new file mode 160000 index 0000000..6957fc8 --- /dev/null +++ b/3p/tinycthread @@ -0,0 +1 @@ +Subproject commit 6957fc8383d6c7db25b60b8c849b29caab1caaee diff --git a/makefile b/makefile index 224689e..1984870 100644 --- a/makefile +++ b/makefile @@ -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 -loop2: - 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/ +3p/lib/libtuntap.a: 3p/libtuntap/build/lib/libtuntap.a + cp 3p/libtuntap/build/lib/libtuntap.a $(LIBDIR) -loop: - 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 +3p/include/tuntap.h: 3p/libtuntap/tuntap.h + cp 3p/libtuntap/tuntap.h $(INCDIR) -test_arp: - gcc src/arp.c test/test_arp.c test/test_arp_util.c -o test_arp -Wall -Wextra -g -Iinclude/ +3p/include/tuntap-export.h: 3p/libtuntap/build/tuntap-export.h + cp 3p/libtuntap/build/tuntap-export.h $(INCDIR) -test_arp_cov: - 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 +3p/libtuntap/build/lib/libtuntap.a 3p/libtuntap/tuntap.h 3p/libtuntap/build/tuntap-export.h: + 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 - ./test_arp_cov - 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 - rm *.gcda *.gcno coverage.info +3p/include/tinycthread.h: 3p/tinycthread/source/tinycthread.h + cp 3p/tinycthread/source/tinycthread.h 3p/include + +3p/src/tinycthread.c: 3p/tinycthread/source/tinycthread.c + 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: - rm -f loop \ No newline at end of file + rm -f loop2 loop2.exe + rm -fr 3p/libtuntap/build + rm -f 3p/lib/* 3p/include/* \ No newline at end of file diff --git a/src/arp.c b/src/arp.c index 32b43d1..a1b6c53 100644 --- a/src/arp.c +++ b/src/arp.c @@ -115,7 +115,7 @@ struct ethhdr { */ #include -#include +#include "endian.h" #include "arp.h" #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); arp_packet_t *packet = state->output; - packet->hardware_type = htons(ARP_HARDWARE_ETHERNET); - packet->protocol_type = htons(ARP_PROTOCOL_IP); + packet->hardware_type = cpu_to_net_u16(ARP_HARDWARE_ETHERNET); + packet->protocol_type = cpu_to_net_u16(ARP_PROTOCOL_IP); packet->hardware_len = 6; 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_protocol_address = state->self_ip; 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; - if (packet2->hardware_type != htons(ARP_HARDWARE_ETHERNET)) { + if (packet2->hardware_type != cpu_to_net_u16(ARP_HARDWARE_ETHERNET)) { /* Level 2 protocol not supported */ ARP_DEBUG_LOG("Hardware type %d not supported", packet2->hardware_type); 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 */ ARP_DEBUG_LOG("Protocol type %d not supported", packet2->protocol_type); 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); } - if (packet2->operation_type == htons(ARP_OPERATION_REQUEST)) { + if (packet2->operation_type == cpu_to_net_u16(ARP_OPERATION_REQUEST)) { // 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->hardware_len = packet2->hardware_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_protocol_address = state->self_ip; response->target_hardware_address = packet2->sender_hardware_address; diff --git a/src/endian.c b/src/endian.c new file mode 100644 index 0000000..1e3c67c --- /dev/null +++ b/src/endian.c @@ -0,0 +1,51 @@ +#include +#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; +} + diff --git a/src/endian.h b/src/endian.h new file mode 100644 index 0000000..d0e99bb --- /dev/null +++ b/src/endian.h @@ -0,0 +1,6 @@ +#include + +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); diff --git a/src/icmp.c b/src/icmp.c index 5e58bf4..bd84919 100644 --- a/src/icmp.c +++ b/src/icmp.c @@ -1,5 +1,5 @@ #include -#include +#include "endian.h" #include "icmp.h" #ifdef ICMP_DEBUG @@ -57,12 +57,12 @@ static uint16_t calculate_checksum_icmp(const void *src, size_t len) uint32_t sum = 0xffff; for (size_t i = 0; i < len/2; i++) { - sum += ntohs(src2[i]); + sum += net_to_cpu_u16(src2[i]); if (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) diff --git a/src/ip.c b/src/ip.c index aa53ce0..cdb62b5 100644 --- a/src/ip.c +++ b/src/ip.c @@ -1,5 +1,5 @@ #include -#include // ntohs() +#include "endian.h" #include "ip.h" #ifdef IP_DEBUG @@ -18,12 +18,12 @@ static uint16_t calculate_checksum_ip(const void *src, size_t len) uint32_t sum = 0xffff; for (size_t i = 0; i < len/2; i++) { - sum += ntohs(src2[i]); + sum += net_to_cpu_u16(src2[i]); if (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) { - size_t offset = ntohs(packet->fragment_offset) & 0x1FFF; - bool more_fragments = ntohs(packet->fragment_offset) & 0x2000; + size_t offset = net_to_cpu_u16(packet->fragment_offset) & 0x1FFF; + bool more_fragments = net_to_cpu_u16(packet->fragment_offset) & 0x2000; 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->header_length = 5; 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->fragment_offset = 0; // ??? 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->header_length = 5; 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->fragment_offset = 0; // ??? 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); 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) handler->process_packet(handler->data, packet2->src_ip, packet3_ptr, packet3_len); diff --git a/src/microtcp.c b/src/microtcp.c index ae0d1cf..7b0b578 100644 --- a/src/microtcp.c +++ b/src/microtcp.c @@ -1,13 +1,13 @@ #include // time() +#include #include #include // strerror() #include #include -#include -#include // inet_pton #include "ip.h" #include "arp.h" #include "tcp.h" +#include "endian.h" #include #ifdef MICROTCP_USING_TAP @@ -15,7 +15,7 @@ #endif #ifdef MICROTCP_BACKGROUND_THREAD -#include +#include "tinycthread.h" #endif #ifdef MICROTCP_DEBUG @@ -26,8 +26,8 @@ #endif #ifdef MICROTCP_BACKGROUND_THREAD -#define LOCK_WHEN_THREADED(mtcp) do { pthread_mutex_lock(&(mtcp)->lock); } while (0); -#define UNLOCK_WHEN_THREADED(mtcp) do { pthread_mutex_unlock(&(mtcp)->lock); } while (0); +#define LOCK_WHEN_THREADED(mtcp) do { mtx_lock(&(mtcp)->lock); } while (0); +#define UNLOCK_WHEN_THREADED(mtcp) do { mtx_unlock(&(mtcp)->lock); } while (0); #else #define LOCK_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 union { - pthread_cond_t something_to_accept; + cnd_t something_to_accept; struct { - pthread_cond_t something_to_recv; - pthread_cond_t something_to_send; + cnd_t something_to_recv; + cnd_t something_to_send; }; }; #endif @@ -73,8 +73,8 @@ struct microtcp_t { #ifdef MICROTCP_BACKGROUND_THREAD bool thread_should_stop; - pthread_t thread_id; - pthread_mutex_t lock; + thrd_t thread_id; + mtx_t lock; #endif 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; frame->dst = dst; frame->src = mtcp->mac; - frame->proto = htons(ETHERNET_PROTOCOL_ARP); + frame->proto = cpu_to_net_u16(ETHERNET_PROTOCOL_ARP); // TODO: What about the 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; frame->src = mtcp->mac; 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); } @@ -337,7 +337,7 @@ process_packet(microtcp_t *mtcp, const void *packet, size_t len) const ethernet_frame_t *frame = packet; - switch (ntohs(frame->proto)) { + switch (net_to_cpu_u16(frame->proto)) { case ETHERNET_PROTOCOL_ARP: arp_process_packet(&mtcp->arp_state, frame+1, len - sizeof(ethernet_frame_t)); break; @@ -362,8 +362,9 @@ void microtcp_process_packet(microtcp_t *mtcp, const void *packet, size_t len) 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) // needs to be out of the critical section to give other // threads the ability to progress in the mean time. @@ -389,12 +390,12 @@ void microtcp_step(microtcp_t *mtcp) } #ifdef MICROTCP_BACKGROUND_THREAD -static void *loop(void *data) +static int loop(void *data) { microtcp_t *mtcp = data; while (!mtcp->thread_should_stop) microtcp_step(mtcp); - return NULL; + return 0; } #endif @@ -474,7 +475,46 @@ static mac_address_t generate_random_mac() 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, @@ -542,7 +582,7 @@ microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac, #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); arp_free(&mtcp->arp_state); tcp_free(&mtcp->tcp_state); @@ -550,10 +590,11 @@ microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac, return NULL; } 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); arp_free(&mtcp->arp_state); tcp_free(&mtcp->tcp_state); + mtx_destroy(&mtcp->lock); free(mtcp); return NULL; } @@ -581,6 +622,28 @@ microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac, #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, microtcp_callbacks_t *callbacks) { @@ -590,15 +653,21 @@ bool microtcp_callbacks_create_for_tap(const char *ip, const char *mac, if (!dev) 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 - if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY) || - tuntap_set_ip(dev, ip, netmask) || - tuntap_set_hwaddr(dev, mac ? mac : "random") || - tuntap_up(dev)) { - tuntap_release(dev); - return false; - } + if (tuntap_start(dev, TUNTAP_MODE_ETHERNET, TUNTAP_ID_ANY)) + goto cleanup; + + tuntap_set_ip(dev, ip, netmask); + tuntap_set_hwaddr(dev, mac ? mac : "random"); + + if (tuntap_up(dev)) + goto cleanup; *callbacks = (microtcp_callbacks_t) { .data = dev, @@ -608,6 +677,10 @@ bool microtcp_callbacks_create_for_tap(const char *ip, const char *mac, }; return true; + +cleanup: + tuntap_release(dev); + return false; } 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 MICROTCP_DEBUG_LOG("Stopping thread"); mtcp->thread_should_stop = true; - pthread_join(mtcp->thread_id, NULL); - pthread_mutex_destroy(&mtcp->lock); + thrd_join(mtcp->thread_id, NULL); + mtx_destroy(&mtcp->lock); MICROTCP_DEBUG_LOG("Thread stopped"); #endif @@ -689,7 +762,7 @@ static void ready_to_accept(void *data) { #ifdef MICROTCP_BACKGROUND_THREAD microtcp_socket_t *socket = data; - pthread_cond_signal(&socket->something_to_accept); + cnd_signal(&socket->something_to_accept); #else (void) data; #endif @@ -723,7 +796,7 @@ microtcp_socket_t *microtcp_open(microtcp_t *mtcp, uint16_t port, socket->listener = listener; #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; push_unlinked_socket_into_free_list(mtcp, socket); tcp_listener_destroy(listener); @@ -752,7 +825,7 @@ void microtcp_close(microtcp_socket_t *socket) case SOCKET_LISTENER: #ifdef MICROTCP_BACKGROUND_THREAD - pthread_cond_destroy(&socket->something_to_accept); + cnd_destroy(&socket->something_to_accept); #endif tcp_listener_destroy(socket->listener); break; @@ -772,7 +845,7 @@ static void ready_to_recv(void *data) { #ifdef MICROTCP_BACKGROUND_THREAD microtcp_socket_t *socket = data; - pthread_cond_signal(&socket->something_to_recv); + cnd_signal(&socket->something_to_recv); #else (void) data; #endif @@ -782,7 +855,7 @@ static void ready_to_send(void *data) { #ifdef MICROTCP_BACKGROUND_THREAD microtcp_socket_t *socket = data; - pthread_cond_signal(&socket->something_to_send); + cnd_signal(&socket->something_to_send); #else (void) data; #endif @@ -813,7 +886,8 @@ microtcp_socket_t *microtcp_accept(microtcp_socket_t *socket, #ifdef MICROTCP_BACKGROUND_THREAD 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); } #else @@ -831,14 +905,15 @@ microtcp_socket_t *microtcp_accept(microtcp_socket_t *socket, socket2->connection = connection; #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; push_unlinked_socket_into_free_list(mtcp, socket2); tcp_connection_destroy(connection); 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; + cnd_destroy(&socket2->something_to_recv); push_unlinked_socket_into_free_list(mtcp, socket2); tcp_connection_destroy(connection); goto unlock_and_exit; @@ -878,7 +953,8 @@ size_t microtcp_recv(microtcp_socket_t *socket, #ifdef MICROTCP_BACKGROUND_THREAD 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); } #else @@ -918,19 +994,15 @@ size_t microtcp_send(microtcp_socket_t *socket, #ifdef MICROTCP_BACKGROUND_THREAD 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); } #else - if (num == 0 && !no_block) { + if (num == 0 && !no_block) errcode2 = MICROTCP_ERRCODE_CANTBLOCK; - goto unlock_and_exit; - } #endif - } - -unlock_and_exit: UNLOCK_WHEN_THREADED(mtcp); if (errcode) diff --git a/src/microtcp_linux.c b/src/microtcp_linux.c deleted file mode 100644 index 1c54f7a..0000000 --- a/src/microtcp_linux.c +++ /dev/null @@ -1,182 +0,0 @@ -/* -#ifdef MICROTCP_LINUX - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 */ \ No newline at end of file diff --git a/src/tcp.c b/src/tcp.c index 466f194..bddbe3f 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -1,6 +1,6 @@ #include #include -#include +#include "endian.h" #include "tcp.h" #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; for (size_t i = 0; i < len/2; i++) { - sum += ntohs(src[i]); + sum += net_to_cpu_u16(src[i]); if (sum > 0xffff) sum -= 0xffff; } } - return htons(~sum); + return cpu_to_net_u32(~sum); } static void @@ -249,14 +249,14 @@ static void emit_segment(tcp_connection_t *connection, bool ack, bool syn, size_ // seq_no++; tcp_segment_t header = { - .src_port = htons(listener->port), - .dst_port = htons(connection->peer_port), + .src_port = cpu_to_net_u32(listener->port), + .dst_port = cpu_to_net_u32(connection->peer_port), .flags = flags, - .seq_no = htonl(seq_no), - .ack_no = htonl(ack_no), + .seq_no = cpu_to_net_u32(seq_no), + .ack_no = cpu_to_net_u32(ack_no), .offset = 5, // No options .unused = 0, - .window = htons(connection->rcv_wnd), + .window = cpu_to_net_u32(connection->rcv_wnd), .checksum = 0, // Will be calculated later .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, .reserved = 0, .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[]) { @@ -329,8 +329,8 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender, if (len < sizeof(tcp_segment_t)) return; - uint16_t reordered_dst_port = ntohs(segment->dst_port); - uint16_t reordered_src_port = ntohs(segment->src_port); + uint16_t reordered_dst_port = net_to_cpu_u16(segment->dst_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); if (listener == NULL) { @@ -362,7 +362,7 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender, // Temporary 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); if (connection == NULL) { @@ -389,7 +389,7 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender, 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) TCP_DEBUG_LOG("Received segment acknowledged again %d", ack_no); diff --git a/test/loop.c b/test/loop.c index 9d94cae..631e494 100644 --- a/test/loop.c +++ b/test/loop.c @@ -1,3 +1,4 @@ +/* #include #include @@ -54,3 +55,4 @@ handled: microtcp_destroy(mtcp); return 0; } +*/ \ No newline at end of file diff --git a/test/loop2.c b/test/loop2.c index 318b551..914f820 100644 --- a/test/loop2.c +++ b/test/loop2.c @@ -6,8 +6,10 @@ int main(void) microtcp_errcode_t errcode; 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; + } uint16_t port = 80; microtcp_socket_t *server = microtcp_open(mtcp, port, &errcode); @@ -36,21 +38,21 @@ int main(void) fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode)); 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); if (errcode) { fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode)); 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); if (errcode) { fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode)); goto handled; } - fprintf(stderr, "(%ld bytes sent 2)\n", sent2); + fprintf(stderr, "(%d bytes sent 2)\n", (int) sent2); handled: microtcp_close(client);