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"
static bool cpu_is_little_endian(void)
bool cpu_is_little_endian(void)
{
uint16_t x = 1;
return *((uint8_t*) &x);
+2
View File
@@ -1,5 +1,7 @@
#include <stdint.h>
#include <stdbool.h>
bool cpu_is_little_endian(void);
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);
+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
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->total_length = cpu_to_net_u16(sizeof(ip_packet_t) + len);
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->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);
}
@@ -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);
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->total_length = cpu_to_net_u16(sizeof(ip_packet_t) + considered_payload);
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++;
}
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]
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;
if (packet2->version != 4 || packet2->header_length < 5) {
IP_DEBUG_LOG("Only supported IPv4 (received %d) with no options", packet2->version);
int 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;
}
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) {
#warning "TODO: Handle IP options"
return;
@@ -218,7 +245,7 @@ void ip_process_packet(ip_state_t *ip_state, const void *packet, size_t len)
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");
return;
}
+2 -7
View File
@@ -7,13 +7,8 @@
#define IP_PLUGGED_PROTOCOLS_MAX 4
typedef struct {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
uint8_t header_length: 4;
uint8_t version: 4;
#else
uint8_t version: 4;
uint8_t header_length: 4;
#endif
uint8_t header_length_or_version1: 4; // Header length when little endian
uint8_t header_length_or_version2: 4; // Header length when big endian
uint8_t type_of_service;
uint16_t total_length;
uint16_t id;
+20 -7
View File
@@ -10,6 +10,8 @@
#define TCP_DEBUG_LOG(...)
#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)
{
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)
@@ -158,15 +160,16 @@ static void emit_segment(tcp_connection_t *connection, bool ack, bool syn, size_
//if (payload_being_sent > 0)
// seq_no++;
int offset = 5; // No options
tcp_segment_t header = {
.src_port = cpu_to_net_u16(listener->port),
.dst_port = cpu_to_net_u16(connection->peer_port),
.flags = flags,
.seq_no = cpu_to_net_u32(seq_no),
.ack_no = cpu_to_net_u32(ack_no),
.offset = 5, // No options
.unused = 0,
.window = cpu_to_net_u32(connection->rcv_wnd),
.offset1 = cpu_is_little_endian() ? 0 : offset,
.offset2 = cpu_is_little_endian() ? offset : 0,
.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
.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,
.reserved = 0,
.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[]) {
@@ -250,7 +253,17 @@ find_connection_associated_to_listener(tcp_listener_t *listener,
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;
}
@@ -286,7 +299,7 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender,
TCP_DEBUG_LOG("Received TCP segment");
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.
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;
uint32_t seq_no;
uint32_t ack_no;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
uint8_t unused: 4;
uint8_t offset: 4;
#else
uint8_t offset: 4;
uint8_t unused: 4;
#endif
uint8_t offset1: 4; // When CPU is big endian
uint8_t offset2: 4; // When CPU is little endian
uint8_t flags;
uint16_t window;
uint16_t checksum;
uint16_t urgent_pointer;
char payload[];
} tcp_segment_t;
static_assert(sizeof(tcp_segment_t) == 20);
typedef struct tcp_connection_t tcp_connection_t;
typedef struct tcp_listener_t tcp_listener_t;