From 5026f823fa2708404302aa59d03401635a435c0b Mon Sep 17 00:00:00 2001 From: Anton Kling Date: Fri, 27 Oct 2023 00:48:21 +0200 Subject: Kernel/Networking/LibC: Add syscalls and libc functions for UDP This allows a UDP server to be created in userland and read data. Currently it can't send data and is very very simplistic. Code is horrible and probably needs some fixing until it can be further built upon. --- network/arp.c | 5 +++-- network/arp.h | 2 +- network/ethernet.c | 8 +++++--- network/ethernet.h | 2 +- network/ipv4.c | 27 +++++++++++++++++++++++++++ network/ipv4.h | 3 +++ network/udp.c | 26 ++++++++++++++++++++++++++ network/udp.h | 3 +++ 8 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 network/ipv4.c create mode 100644 network/ipv4.h create mode 100644 network/udp.c create mode 100644 network/udp.h (limited to 'network') diff --git a/network/arp.c b/network/arp.c index eb8aca3..f86c732 100644 --- a/network/arp.c +++ b/network/arp.c @@ -43,7 +43,7 @@ void print_ip(const char *str, uint8_t *ip) { kprintf("\n"); } -void handle_arp(uint8_t *payload) { +void handle_arp(const uint8_t *payload) { struct ARP_DATA *data = (struct ARP_DATA *)payload; // Assert that communication is over ethernet @@ -79,5 +79,6 @@ void handle_arp(uint8_t *payload) { memcpy(response.dsthw, data->srchw, sizeof(uint8_t[6])); memcpy(response.dstpr, data->srcpr, sizeof(uint8_t[4])); - send_ethernet_packet(data->srchw, 0x0806, (uint8_t*)&response, sizeof(response)); + send_ethernet_packet(data->srchw, 0x0806, (uint8_t *)&response, + sizeof(response)); } diff --git a/network/arp.h b/network/arp.h index 1e8df1b..8efda97 100644 --- a/network/arp.h +++ b/network/arp.h @@ -1,3 +1,3 @@ #include -void handle_arp(uint8_t *payload); +void handle_arp(const uint8_t *payload); diff --git a/network/ethernet.c b/network/ethernet.c index ae8e814..11a3876 100644 --- a/network/ethernet.c +++ b/network/ethernet.c @@ -4,6 +4,7 @@ #include #include #include +#include #include struct ETHERNET_HEADER { @@ -44,10 +45,10 @@ uint32_t crc32(const char *buf, size_t len) { return ~crc; } -void handle_ethernet(uint8_t *packet, uint64_t packet_length) { +void handle_ethernet(const uint8_t *packet, uint64_t packet_length) { struct ETHERNET_HEADER *eth_header = (struct ETHERNET_HEADER *)packet; packet += sizeof(struct ETHERNET_HEADER); - uint8_t *payload = packet; + const uint8_t *payload = packet; packet += packet_length - sizeof(struct ETHERNET_HEADER); uint32_t crc = *((uint32_t *)packet - 1); kprintf("PACKET crc: %x\n", crc); @@ -70,7 +71,7 @@ void handle_ethernet(uint8_t *packet, uint64_t packet_length) { handle_arp(payload); break; case 0x0800: - kprintf("IPV4 message\n"); + handle_ipv4(payload, packet_length - sizeof(struct ETHERNET_HEADER) - 4); break; default: kprintf("Can't handle ethernet type\n"); @@ -97,5 +98,6 @@ void send_ethernet_packet(uint8_t mac_dst[6], uint16_t type, uint8_t *payload, htonl(crc32((const char *)buffer_start, buffer_size - 4)); assert(rtl8139_send_data(buffer_start, buffer_size)); + kfree(buffer_start); kprintf("sent data\n"); } diff --git a/network/ethernet.h b/network/ethernet.h index 88a4dc6..0fdcee3 100644 --- a/network/ethernet.h +++ b/network/ethernet.h @@ -1,5 +1,5 @@ #include -void handle_ethernet(uint8_t *packet, uint64_t packet_length); +void handle_ethernet(const uint8_t *packet, uint64_t packet_length); void send_ethernet_packet(uint8_t mac_dst[6], uint16_t type, uint8_t *payload, uint64_t payload_length); diff --git a/network/ipv4.c b/network/ipv4.c new file mode 100644 index 0000000..27b38ec --- /dev/null +++ b/network/ipv4.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +void handle_ipv4(const uint8_t *payload, uint32_t packet_length) { + assert(packet_length > 4); + uint8_t version = (*payload & 0xF0) >> 4; + uint8_t IHL = (*payload & 0xF); + kprintf("version: %x\n", version); + assert(4 == version); + assert(5 == IHL); + uint16_t ipv4_total_length = ntohs(*(uint16_t *)(payload + 2)); + assert(ipv4_total_length >= 20); + // Make sure the ipv4 header is not trying to get uninitalized memory + assert(ipv4_total_length <= packet_length); + + uint8_t protocol = *(payload + 9); + switch (protocol) { + case 0x11: + handle_udp(payload + 20, ipv4_total_length - 20); + break; + default: + kprintf("Protocol given in IPv4 header not handeld: %x\n", protocol); + break; + } +} diff --git a/network/ipv4.h b/network/ipv4.h new file mode 100644 index 0000000..294a0ef --- /dev/null +++ b/network/ipv4.h @@ -0,0 +1,3 @@ +#include + +void handle_ipv4(const uint8_t *payload, uint32_t packet_length); diff --git a/network/udp.c b/network/udp.c new file mode 100644 index 0000000..fb8ba44 --- /dev/null +++ b/network/udp.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +void handle_udp(const uint8_t *payload, uint32_t packet_length) { + assert(packet_length >= 8); + uint16_t source_port = ntohs(*(uint16_t *)payload); + uint16_t dst_port = ntohs(*(uint16_t *)(payload + 2)); + uint16_t length = ntohs(*(uint16_t *)(payload + 4)); + assert(length == packet_length); + kprintf("source_port: %d\n", source_port); + kprintf("dst_port: %d\n", dst_port); + uint32_t data_length = length - 8; + const uint8_t *data = payload + 8; + + // Find the open port + OPEN_INET_SOCKET *in_s = find_open_udp_port(htons(dst_port)); + assert(in_s); + SOCKET *s = in_s->s; + vfs_fd_t *fifo_file = s->ptr_socket_fd; + raw_vfs_pwrite(fifo_file, (char *)data, data_length, 0); + for (uint32_t i = 0; i < data_length; i++) { + kprintf("%c", data[i]); + } +} diff --git a/network/udp.h b/network/udp.h new file mode 100644 index 0000000..c6ac753 --- /dev/null +++ b/network/udp.h @@ -0,0 +1,3 @@ +#include + +void handle_udp(const uint8_t *payload, uint32_t packet_length); -- cgit v1.2.3