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:
+1
-2
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user