diff options
author | Anton Kling <anton@kling.gg> | 2023-10-27 19:41:26 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2023-10-30 21:49:48 +0100 |
commit | 4f9ed7087cb58683d9423ab771ad76b31dac5514 (patch) | |
tree | 5364217b7d491c4321830025020ab13513067cb1 | |
parent | 715274d3a77c58510b97c3f87cd604dde9de7a4f (diff) |
Kernel: Expose source information of incoming UDP packets
-rw-r--r-- | network/ipv4.c | 6 | ||||
-rw-r--r-- | network/udp.c | 47 | ||||
-rw-r--r-- | network/udp.h | 2 | ||||
-rw-r--r-- | scalls/recvfrom.c | 52 | ||||
-rw-r--r-- | scalls/recvfrom.h | 11 | ||||
-rw-r--r-- | userland/libc/include/socket.h | 1 |
6 files changed, 99 insertions, 20 deletions
diff --git a/network/ipv4.c b/network/ipv4.c index 27b38ec..e7ef2c2 100644 --- a/network/ipv4.c +++ b/network/ipv4.c @@ -2,6 +2,7 @@ #include <network/bytes.h> #include <network/ipv4.h> #include <network/udp.h> +#include <string.h> void handle_ipv4(const uint8_t *payload, uint32_t packet_length) { assert(packet_length > 4); @@ -15,10 +16,13 @@ void handle_ipv4(const uint8_t *payload, uint32_t packet_length) { // Make sure the ipv4 header is not trying to get uninitalized memory assert(ipv4_total_length <= packet_length); + uint8_t src_ip[4]; + memcpy(src_ip, payload + 12, sizeof(uint8_t[4])); + uint8_t protocol = *(payload + 9); switch (protocol) { case 0x11: - handle_udp(payload + 20, ipv4_total_length - 20); + handle_udp(src_ip, payload + 20, ipv4_total_length - 20); break; default: kprintf("Protocol given in IPv4 header not handeld: %x\n", protocol); diff --git a/network/udp.c b/network/udp.c index fb8ba44..29f17e1 100644 --- a/network/udp.c +++ b/network/udp.c @@ -3,24 +3,47 @@ #include <network/udp.h> #include <socket.h> -void handle_udp(const uint8_t *payload, uint32_t packet_length) { +void handle_udp(uint8_t src_ip[4], 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; + // n_.* means network format(big endian) + // h_.* means host format((probably) little endian) + uint16_t n_source_port = *(uint16_t *)payload; + uint16_t h_source_port = ntohs(n_source_port); + uint16_t h_dst_port = ntohs(*(uint16_t *)(payload + 2)); + uint16_t h_length = ntohs(*(uint16_t *)(payload + 4)); + assert(h_length == packet_length); + kprintf("source_port: %d\n", h_source_port); + kprintf("dst_port: %d\n", h_dst_port); + uint16_t data_length = h_length - 8; const uint8_t *data = payload + 8; // Find the open port - OPEN_INET_SOCKET *in_s = find_open_udp_port(htons(dst_port)); + OPEN_INET_SOCKET *in_s = find_open_udp_port(htons(h_dst_port)); assert(in_s); SOCKET *s = in_s->s; vfs_fd_t *fifo_file = s->ptr_socket_fd; + + // Write the sockaddr struct such that it can later be + // given to userland if asked. + struct sockaddr_in /*{ + sa_family_t sin_family; + union { + uint32_t s_addr; + } sin_addr; + uint16_t sin_port; + }*/ in; + in.sin_family = AF_INET; + memcpy(&in.sin_addr.s_addr, src_ip, sizeof(uint32_t)); + in.sin_port = n_source_port; + socklen_t sock_length = sizeof(struct sockaddr_in); + + raw_vfs_pwrite(fifo_file, &sock_length, sizeof(sock_length), 0); + raw_vfs_pwrite(fifo_file, &in, sizeof(in), 0); + + // Write the UDP payload length(not including header) + raw_vfs_pwrite(fifo_file, &data_length, sizeof(uint16_t), 0); + + // Write the UDP payload 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 index c6ac753..8278b87 100644 --- a/network/udp.h +++ b/network/udp.h @@ -1,3 +1,3 @@ #include <stdint.h> -void handle_udp(const uint8_t *payload, uint32_t packet_length); +void handle_udp(uint8_t src_ip[4], const uint8_t *payload, uint32_t packet_length); diff --git a/scalls/recvfrom.c b/scalls/recvfrom.c index 0e37153..1770fa1 100644 --- a/scalls/recvfrom.c +++ b/scalls/recvfrom.c @@ -1,15 +1,59 @@ +#include <assert.h> #include <fs/vfs.h> +#include <math.h> #include <poll.h> #include <scalls/recvfrom.h> -size_t syscall_recvfrom(int socket, void *buffer, size_t length, int flags, - struct sockaddr *address, socklen_t *address_len) { +size_t syscall_recvfrom( + int socket, void *buffer, size_t length, int flags, + struct two_args + *extra_args /*struct sockaddr *address, socklen_t *address_len*/) { + + struct sockaddr *address = (struct sockaddr *)extra_args->a; + socklen_t *address_len = (socklen_t *)extra_args->b; + kprintf("address: %x\n", address); + kprintf("address_len: %x\n", address_len); + if (flags & MSG_WAITALL) { struct pollfd fds[1]; fds[0].fd = socket; fds[0].events = POLLIN; poll(fds, 1, 0); } - kprintf("got event\n"); - return vfs_pread(socket, buffer, length, 0); + + uint16_t data_length; + socklen_t tmp_socklen; + vfs_pread(socket, &tmp_socklen, sizeof(socklen_t), 0); + if (address_len) + *address_len = tmp_socklen; + if (address) { + vfs_pread(socket, address, tmp_socklen, 0); + } else { + // We still have to throwaway the data. + char devnull[100]; + for (; tmp_socklen;) { + int rc = vfs_pread(socket, devnull, min(tmp_socklen, 100), 0); + assert(rc >= 0); + tmp_socklen -= rc; + } + } + + vfs_pread(socket, &data_length, sizeof(data_length), 0); + // If it is reading less than the packet length that could cause + // problems as the next read will not be put at a new header. Luckily + // it seems as if other UNIX systems can discard the rest of the + // packet if not read. + + // Read in the data requested + int read_len = min(length, data_length); + int rc = vfs_pread(socket, buffer, read_len, 0); + // Discard the rest of the packet + int rest = data_length - read_len; + char devnull[100]; + for (; rest;) { + int rc = vfs_pread(socket, devnull, 100, 0); + assert(rc >= 0); + rest -= rc; + } + return rc; } diff --git a/scalls/recvfrom.h b/scalls/recvfrom.h index 9897899..d81a1e0 100644 --- a/scalls/recvfrom.h +++ b/scalls/recvfrom.h @@ -1,4 +1,11 @@ #include <socket.h> -size_t syscall_recvfrom(int socket, void *buffer, size_t length, int flags, - struct sockaddr *address, socklen_t *address_len); +struct two_args { + uint32_t a; + uint32_t b; +}; + +size_t syscall_recvfrom( + int socket, void *buffer, size_t length, int flags, + struct two_args + *extra_args /*struct sockaddr *address, socklen_t *address_len*/); diff --git a/userland/libc/include/socket.h b/userland/libc/include/socket.h index c4a3e73..2bf6345 100644 --- a/userland/libc/include/socket.h +++ b/userland/libc/include/socket.h @@ -40,6 +40,7 @@ struct sockaddr_in { sa_family_t sin_family; union { uint32_t s_addr; + uint8_t a[4]; } sin_addr; uint16_t sin_port; }; |