ported to windows
This commit is contained in:
@@ -115,7 +115,7 @@ struct ethhdr {
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <arpa/inet.h>
|
||||
#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;
|
||||
|
||||
@@ -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 <arpa/inet.h>
|
||||
#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)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h> // 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);
|
||||
|
||||
+117
-45
@@ -1,13 +1,13 @@
|
||||
#include <time.h> // time()
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h> // strerror()
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h> // inet_pton
|
||||
#include "ip.h"
|
||||
#include "arp.h"
|
||||
#include "tcp.h"
|
||||
#include "endian.h"
|
||||
#include <microtcp.h>
|
||||
|
||||
#ifdef MICROTCP_USING_TAP
|
||||
@@ -15,7 +15,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef MICROTCP_BACKGROUND_THREAD
|
||||
#include <pthread.h>
|
||||
#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)
|
||||
|
||||
@@ -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 <stdbool.h>
|
||||
#include <arpa/inet.h>
|
||||
#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);
|
||||
|
||||
Reference in New Issue
Block a user