a bunch of bug fixes (changed a bunch of cpu_to_net_u32 that should have been cpu_to_net_u16 and dropped the use of the __BYTE_ORDER__ symbol that no one was defining)

This commit is contained in:
cozis
2023-05-17 23:20:14 +02:00
parent df70d98661
commit 4de61f7cc7
6 changed files with 65 additions and 33 deletions
+1 -2
View File
@@ -1,7 +1,6 @@
#include <stdbool.h>
#include "endian.h" #include "endian.h"
static bool cpu_is_little_endian(void) bool cpu_is_little_endian(void)
{ {
uint16_t x = 1; uint16_t x = 1;
return *((uint8_t*) &x); return *((uint8_t*) &x);
+2
View File
@@ -1,5 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
bool cpu_is_little_endian(void);
uint16_t net_to_cpu_u16(uint16_t n); uint16_t net_to_cpu_u16(uint16_t n);
uint32_t net_to_cpu_u32(uint32_t n); uint32_t net_to_cpu_u32(uint32_t n);
uint16_t cpu_to_net_u16(uint16_t n); uint16_t cpu_to_net_u16(uint16_t n);
+37 -10
View File
@@ -70,8 +70,16 @@ static void send_icmp_packet(void *data, ip_address_t ip, size_t len)
// The data was written in the output buffer // The data was written in the output buffer
ip_packet_t *packet = ip_state->output_ptr; // This changes every iteration ip_packet_t *packet = ip_state->output_ptr; // This changes every iteration
packet->version = 4;
packet->header_length = 5; int version = 4;
int header_length = 5;
if (cpu_is_little_endian()) {
packet->header_length_or_version1 = header_length;
packet->header_length_or_version2 = version;
} else {
packet->header_length_or_version1 = version;
packet->header_length_or_version2 = header_length;
}
packet->type_of_service = 0; // ??? packet->type_of_service = 0; // ???
packet->total_length = cpu_to_net_u16(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++;
@@ -82,7 +90,7 @@ static void send_icmp_packet(void *data, ip_address_t ip, size_t len)
packet->src_ip = ip_state->ip; packet->src_ip = ip_state->ip;
packet->dst_ip = ip; packet->dst_ip = ip;
packet->checksum = calculate_checksum_ip((uint16_t*) packet, 4 * packet->header_length); packet->checksum = calculate_checksum_ip((uint16_t*) packet, 4 * header_length);
ip_state->send(ip_state->send_data, ip, sizeof(ip_packet_t) + len); ip_state->send(ip_state->send_data, ip, sizeof(ip_packet_t) + len);
} }
@@ -163,8 +171,16 @@ int ip_send_2(ip_state_t *state, ip_protocol_t protocol, ip_address_t dst,
size_t considered_payload = MIN(current_payload_limit, remaining_payload); size_t considered_payload = MIN(current_payload_limit, remaining_payload);
ip_packet_t *packet = state->output_ptr; // This changes every iteration ip_packet_t *packet = state->output_ptr; // This changes every iteration
packet->version = 4;
packet->header_length = 5; int version = 4;
int header_length = 5;
if (cpu_is_little_endian()) {
packet->header_length_or_version1 = header_length;
packet->header_length_or_version2 = version;
} else {
packet->header_length_or_version1 = version;
packet->header_length_or_version2 = header_length;
}
packet->type_of_service = 0; // ??? packet->type_of_service = 0; // ???
packet->total_length = cpu_to_net_u16(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++;
@@ -184,7 +200,7 @@ int ip_send_2(ip_state_t *state, ip_protocol_t protocol, ip_address_t dst,
copied_slices++; copied_slices++;
} }
packet->checksum = calculate_checksum_ip((uint16_t*) packet, 4 * packet->header_length); packet->checksum = calculate_checksum_ip((uint16_t*) packet, 4 * header_length);
// Sending updates the [state->output_ptr] and [state->output_len] // Sending updates the [state->output_ptr] and [state->output_len]
state->send(state->send_data, dst, sizeof(ip_packet_t) + considered_payload); state->send(state->send_data, dst, sizeof(ip_packet_t) + considered_payload);
@@ -202,12 +218,23 @@ void ip_process_packet(ip_state_t *ip_state, const void *packet, size_t len)
const ip_packet_t *packet2 = packet; const ip_packet_t *packet2 = packet;
if (packet2->version != 4 || packet2->header_length < 5) { int version;
IP_DEBUG_LOG("Only supported IPv4 (received %d) with no options", packet2->version); int header_length;
if (cpu_is_little_endian()) {
header_length = packet2->header_length_or_version1;
version = packet2->header_length_or_version2;
} else {
version = packet2->header_length_or_version1;
header_length = packet2->header_length_or_version2;
}
if (version != 4 || header_length < 5) {
IP_DEBUG_LOG("Only supported IPv4 (received %d) with no options", version);
return; return;
} }
size_t option_count = packet2->header_length - sizeof(ip_packet_t)/4; size_t option_count = header_length - sizeof(ip_packet_t)/4;
if (option_count > 0) { if (option_count > 0) {
#warning "TODO: Handle IP options" #warning "TODO: Handle IP options"
return; return;
@@ -218,7 +245,7 @@ void ip_process_packet(ip_state_t *ip_state, const void *packet, size_t len)
return; return;
} }
if (calculate_checksum_ip((uint16_t*) packet2, 4 * packet2->header_length)) { if (calculate_checksum_ip((uint16_t*) packet2, 4 * header_length)) {
IP_DEBUG_LOG("Dropping IP packet with invalid checksum"); IP_DEBUG_LOG("Dropping IP packet with invalid checksum");
return; return;
} }
+2 -7
View File
@@ -7,13 +7,8 @@
#define IP_PLUGGED_PROTOCOLS_MAX 4 #define IP_PLUGGED_PROTOCOLS_MAX 4
typedef struct { typedef struct {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ uint8_t header_length_or_version1: 4; // Header length when little endian
uint8_t header_length: 4; uint8_t header_length_or_version2: 4; // Header length when big endian
uint8_t version: 4;
#else
uint8_t version: 4;
uint8_t header_length: 4;
#endif
uint8_t type_of_service; uint8_t type_of_service;
uint16_t total_length; uint16_t total_length;
uint16_t id; uint16_t id;
+20 -7
View File
@@ -10,6 +10,8 @@
#define TCP_DEBUG_LOG(...) #define TCP_DEBUG_LOG(...)
#endif #endif
#define SEGMENT_OFFSET(seg) (cpu_is_little_endian() ? (seg)->offset2 : (seg)->offset1)
void tcp_init(tcp_state_t *tcp_state, ip_address_t ip, tcp_callbacks_t callbacks) void tcp_init(tcp_state_t *tcp_state, ip_address_t ip, tcp_callbacks_t callbacks)
{ {
tcp_state->ip = ip; tcp_state->ip = ip;
@@ -134,7 +136,7 @@ calculate_checksum(const slice_list_t *slices, size_t num_slices)
} }
} }
return cpu_to_net_u32(~sum); return cpu_to_net_u16(~sum);
} }
static void emit_segment(tcp_connection_t *connection, bool ack, bool syn, size_t payload) static void emit_segment(tcp_connection_t *connection, bool ack, bool syn, size_t payload)
@@ -158,15 +160,16 @@ static void emit_segment(tcp_connection_t *connection, bool ack, bool syn, size_
//if (payload_being_sent > 0) //if (payload_being_sent > 0)
// seq_no++; // seq_no++;
int offset = 5; // No options
tcp_segment_t header = { tcp_segment_t header = {
.src_port = cpu_to_net_u16(listener->port), .src_port = cpu_to_net_u16(listener->port),
.dst_port = cpu_to_net_u16(connection->peer_port), .dst_port = cpu_to_net_u16(connection->peer_port),
.flags = flags, .flags = flags,
.seq_no = cpu_to_net_u32(seq_no), .seq_no = cpu_to_net_u32(seq_no),
.ack_no = cpu_to_net_u32(ack_no), .ack_no = cpu_to_net_u32(ack_no),
.offset = 5, // No options .offset1 = cpu_is_little_endian() ? 0 : offset,
.unused = 0, .offset2 = cpu_is_little_endian() ? offset : 0,
.window = cpu_to_net_u32(connection->rcv_wnd), .window = cpu_to_net_u16(connection->rcv_wnd), // Why is a 32 bit integer being backed into a 16 bit?
.checksum = 0, // Will be calculated later .checksum = 0, // Will be calculated later
.urgent_pointer = 0, .urgent_pointer = 0,
}; };
@@ -176,7 +179,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 = cpu_to_net_u32(total_segment_size), .tcp_length = cpu_to_net_u16(total_segment_size),
}; };
header.checksum = calculate_checksum((slice_list_t[]) { header.checksum = calculate_checksum((slice_list_t[]) {
@@ -250,7 +253,17 @@ find_connection_associated_to_listener(tcp_listener_t *listener,
connection = connection->next; connection = connection->next;
} }
} }
if (connection) {
// established=true
} else {
// established=false
connection = listener->non_established_list;
while (connection) {
if (connection->peer_port == peer_port && connection->peer_ip == peer_ip)
break;
connection = connection->next;
}
}
return connection; return connection;
} }
@@ -286,7 +299,7 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender,
TCP_DEBUG_LOG("Received TCP segment"); TCP_DEBUG_LOG("Received TCP segment");
assert(len >= sizeof(tcp_segment_t)); assert(len >= sizeof(tcp_segment_t));
size_t data_offset = segment->offset * sizeof(uint32_t); // Length (in bytes) of the TCP header, size_t data_offset = SEGMENT_OFFSET(segment) * sizeof(uint32_t); // Length (in bytes) of the TCP header,
// comprehensive of options. // comprehensive of options.
size_t options_len = data_offset - sizeof(tcp_segment_t); // The number of bytes of the options is size_t options_len = data_offset - sizeof(tcp_segment_t); // The number of bytes of the options is
+3 -7
View File
@@ -21,19 +21,15 @@ typedef struct {
uint16_t dst_port; uint16_t dst_port;
uint32_t seq_no; uint32_t seq_no;
uint32_t ack_no; uint32_t ack_no;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ uint8_t offset1: 4; // When CPU is big endian
uint8_t unused: 4; uint8_t offset2: 4; // When CPU is little endian
uint8_t offset: 4;
#else
uint8_t offset: 4;
uint8_t unused: 4;
#endif
uint8_t flags; uint8_t flags;
uint16_t window; uint16_t window;
uint16_t checksum; uint16_t checksum;
uint16_t urgent_pointer; uint16_t urgent_pointer;
char payload[]; char payload[];
} tcp_segment_t; } tcp_segment_t;
static_assert(sizeof(tcp_segment_t) == 20);
typedef struct tcp_connection_t tcp_connection_t; typedef struct tcp_connection_t tcp_connection_t;
typedef struct tcp_listener_t tcp_listener_t; typedef struct tcp_listener_t tcp_listener_t;