ported to windows
This commit is contained in:
+4
-4
@@ -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/*
|
||||||
@@ -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
-1
Submodule 3p/libtuntap updated: ef7ed7b444...5d4a7aa886
Submodule
+1
Submodule 3p/tinycthread added at 6957fc8383
@@ -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/*
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
@@ -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 */
|
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user