diff options
author | Anton Kling <anton@kling.gg> | 2023-10-27 22:17:24 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2023-10-30 21:49:48 +0100 |
commit | d50d18c9da3a125f0196bec89802dec1c5b0b800 (patch) | |
tree | d9a4e74906c5ab51708d148ad3728cc155a9893d | |
parent | 4f9ed7087cb58683d9423ab771ad76b31dac5514 (diff) |
Kernel/LibC/Networking: Be able to send UDP messages
Now it can send UDP messages to a specific IP address and libc has
enough to create a basic UDP ECHO server, that is kinda cool.
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | cpu/syscall.c | 5 | ||||
-rw-r--r-- | drivers/rtl8139.c | 1 | ||||
-rw-r--r-- | network/arp.c | 123 | ||||
-rw-r--r-- | network/arp.h | 1 | ||||
-rw-r--r-- | network/ethernet.c | 10 | ||||
-rw-r--r-- | network/ipv4.c | 67 | ||||
-rw-r--r-- | network/ipv4.h | 2 | ||||
-rw-r--r-- | network/udp.c | 19 | ||||
-rw-r--r-- | network/udp.h | 6 | ||||
-rw-r--r-- | scalls/sendto.c | 23 | ||||
-rw-r--r-- | scalls/sendto.h | 11 | ||||
-rw-r--r-- | socket.c | 2 | ||||
-rw-r--r-- | socket.h | 2 | ||||
-rw-r--r-- | userland/libc/Makefile | 2 | ||||
-rw-r--r-- | userland/libc/include/sys/socket.h | 2 | ||||
-rw-r--r-- | userland/libc/include/syscall.h | 1 | ||||
-rw-r--r-- | userland/libc/sys/socket/recvfrom.c | 17 | ||||
-rw-r--r-- | userland/libc/sys/socket/sendto.c | 16 |
19 files changed, 269 insertions, 45 deletions
@@ -1,6 +1,6 @@ CC="./sysroot/bin/i686-sb-gcc" AS="./sysroot/bin/i686-sb-as" -OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o scalls/ppoll.o scalls/ftruncate.o kubsan.o scalls/mmap.o drivers/serial.o scalls/accept.o scalls/bind.o scalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o scalls/shm.o elf.o ksbrk.o sched/scheduler.o scalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o scalls/msleep.o scalls/uptime.o scalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o scalls/recvfrom.o math.o +OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o scalls/ppoll.o scalls/ftruncate.o kubsan.o scalls/mmap.o drivers/serial.o scalls/accept.o scalls/bind.o scalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o scalls/shm.o elf.o ksbrk.o sched/scheduler.o scalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o scalls/msleep.o scalls/uptime.o scalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o scalls/recvfrom.o math.o scalls/sendto.o CFLAGS = -O2 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. INCLUDE=-I./includes/ -I./libc/include/ @@ -23,7 +23,7 @@ nk: qemu-system-i386 -d int -netdev user,id=n0,hostfwd=udp:127.0.0.1:6001-:6000 -device rtl8139,netdev=n0 -no-reboot -no-shutdown -serial file:./serial.log -hda ext2.img -m 1G -cdrom myos.iso -s run: - qemu-system-i386 -enable-kvm -netdev user,id=n0,hostfwd=udp:127.0.0.1:6001-:6000 -device rtl8139,netdev=n0 -d int -no-reboot -no-shutdown -chardev stdio,id=char0,logfile=serial.log,signal=off -serial chardev:char0 -hda ext2.img -m 1G -cdrom myos.iso -s + qemu-system-i386 -enable-kvm -netdev user,id=n0,hostfwd=udp:127.0.0.1:6001-:6000 -device rtl8139,netdev=n0 -object filter-dump,id=id,netdev=n0,file=netout -d int -no-reboot -no-shutdown -chardev stdio,id=char0,logfile=serial.log,signal=off -serial chardev:char0 -hda ext2.img -m 1G -cdrom myos.iso -s myos.iso: myos.bin cp myos.bin isodir/boot diff --git a/cpu/syscall.c b/cpu/syscall.c index 6ad5514..9bf5075 100644 --- a/cpu/syscall.c +++ b/cpu/syscall.c @@ -15,6 +15,7 @@ #include <scalls/msleep.h> #include <scalls/ppoll.h> #include <scalls/recvfrom.h> +#include <scalls/sendto.h> #include <scalls/shm.h> #include <scalls/socket.h> #include <scalls/stat.h> @@ -162,8 +163,8 @@ void (*syscall_functions[])() = { (void(*))syscall_socket, (void(*))syscall_shm_open, (void(*))syscall_ftruncate, (void(*))syscall_stat, (void(*))syscall_msleep, (void(*))syscall_uptime, - (void(*))syscall_mkdir, - (void(*))syscall_recvfrom, + (void(*))syscall_mkdir, (void(*))syscall_recvfrom, + (void(*))syscall_sendto, }; void syscall_function_handler(uint32_t eax, uint32_t arg1, uint32_t arg2, diff --git a/drivers/rtl8139.c b/drivers/rtl8139.c index 02a5159..3853eab 100644 --- a/drivers/rtl8139.c +++ b/drivers/rtl8139.c @@ -4,6 +4,7 @@ #include <drivers/pci.h> #include <drivers/rtl8139.h> #include <mmu.h> +#include <network/arp.h> #include <network/ethernet.h> #define RBSTART 0x30 diff --git a/network/arp.c b/network/arp.c index f86c732..de6d898 100644 --- a/network/arp.c +++ b/network/arp.c @@ -20,9 +20,28 @@ struct ARP_DATA { // above). If IPv4 can just be a "u32" type. }; +struct ARP_TABLE_ENTRY { + uint8_t is_used; + uint8_t mac[6]; + uint8_t ip[4]; +}; + +struct ARP_TABLE_ENTRY arp_table[10] = {0}; + // FIXME: This is hardcoded, don't do this. uint8_t ip_address[4] = {10, 0, 2, 15}; +struct ARP_TABLE_ENTRY *find_arp_entry_to_use(void) { + // This does not need to find a "free" entry as a ARP table is + // just a cache, it just has to pick a entry efficently. + for (int i = 0; i < 10; i++) { + if (!arp_table[i].is_used) { + return &arp_table[i]; + } + } + return &arp_table[0]; +} + void print_mac(const char *str, uint8_t *mac) { kprintf("%s: ", str); for (int i = 0; i < 6; i++) { @@ -33,7 +52,7 @@ void print_mac(const char *str, uint8_t *mac) { kprintf("\n"); } -void print_ip(const char *str, uint8_t *ip) { +void print_ip(const char *str, const uint8_t *ip) { kprintf("%s: ", str); for (int i = 0; i < 4; i++) { kprintf("%d", ip[i]); @@ -43,42 +62,92 @@ void print_ip(const char *str, uint8_t *ip) { kprintf("\n"); } +void send_arp_request(const uint8_t ip[4]) { + struct ARP_DATA data; + data.htype = htons(1); + data.ptype = htons(0x0800); + + data.hlen = 6; + data.plen = 4; + + data.opcode = htons(0x0001); + get_mac_address(data.srchw); + memcpy(data.srcpr, ip_address, sizeof(uint8_t[4])); + + memset(data.dsthw, 0, sizeof(uint8_t[6])); + memcpy(data.dstpr, ip, sizeof(uint8_t[4])); + + uint8_t broadcast[6]; + memset(broadcast, 0xFF, sizeof(broadcast)); + send_ethernet_packet(broadcast, 0x0806, (uint8_t *)&data, sizeof(data)); +} + +int get_mac_from_ip(const uint8_t ip[4], uint8_t mac[6]) { + print_ip("ARP GETTING MAC FROM IP: ", ip); + for (int i = 0; i < 10; i++) { + if (0 != memcmp(arp_table[i].ip, ip, sizeof(uint8_t[4]))) + continue; + memcpy(mac, arp_table[i].mac, sizeof(uint8_t[6])); + return 1; + } + klog("ARP cache miss", LOG_NOTE); + asm("sti"); + send_arp_request(ip); + // TODO: Maybe wait a bit? + for (int i = 0; i < 10; i++) { + if (0 != memcmp(arp_table[i].ip, ip, sizeof(uint8_t[4]))) + continue; + memcpy(mac, arp_table[i].mac, sizeof(uint8_t[6])); + return 1; + } + assert(0); + return 0; +} + void handle_arp(const uint8_t *payload) { struct ARP_DATA *data = (struct ARP_DATA *)payload; // Assert that communication is over ethernet assert(1 == ntohs(data->htype)); - // Assert it is a request - assert(0x0001 == ntohs(data->opcode)); // Assert that request uses IP assert(0x0800 == ntohs(data->ptype)); assert(6 == data->hlen); assert(4 == data->plen); - print_mac("srchw: ", data->srchw); - print_ip("srcpr: ", data->srcpr); + // Assert it is a request + if (0x0001 /*arp_request*/ == ntohs(data->opcode)) { + print_mac("srchw: ", data->srchw); + print_ip("srcpr: ", data->srcpr); - print_mac("dsthw: ", data->dsthw); - print_ip("dstpr: ", data->dstpr); + print_mac("dsthw: ", data->dsthw); + print_ip("dstpr: ", data->dstpr); - uint8_t mac[6]; - get_mac_address(mac); - print_mac("THIS DEVICE MAC: ", mac); - assert(0 == memcmp(data->dstpr, ip_address, sizeof(uint8_t[4]))); - - // Now we have to construct a ARP response - struct ARP_DATA response; - response.htype = htons(1); - response.ptype = htons(0x0800); - response.opcode = htons(0x00002); - response.hlen = 6; - response.plen = 4; - get_mac_address(response.srchw); - memcpy(response.srcpr, ip_address, sizeof(uint8_t[4])); - - 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)); + assert(0 == memcmp(data->dstpr, ip_address, sizeof(uint8_t[4]))); + + // Now we have to construct a ARP response + struct ARP_DATA response; + response.htype = htons(1); + response.ptype = htons(0x0800); + response.opcode = htons(0x00002); + response.hlen = 6; + response.plen = 4; + get_mac_address(response.srchw); + memcpy(response.srcpr, ip_address, sizeof(uint8_t[4])); + + 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)); + } else if (0x0002 /*arp_response*/ == ntohs(data->opcode)) { + // Find a entry to fill + struct ARP_TABLE_ENTRY *entry = find_arp_entry_to_use(); + entry->is_used = 1; + memcpy(entry->mac, data->srchw, sizeof(uint8_t[6])); + memcpy(entry->ip, data->srcpr, sizeof(uint8_t[4])); + print_ip("Added ip: ", entry->ip); + } else { + kprintf("GOT A ARP REQEUST WITH TYPE: %x\n", ntohs(data->opcode)); + assert(0); + } } diff --git a/network/arp.h b/network/arp.h index 8efda97..c2beb94 100644 --- a/network/arp.h +++ b/network/arp.h @@ -1,3 +1,4 @@ #include <stdint.h> +int get_mac_from_ip(const uint8_t ip[4], uint8_t mac[6]); void handle_arp(const uint8_t *payload); diff --git a/network/ethernet.c b/network/ethernet.c index 11a3876..e97ccbd 100644 --- a/network/ethernet.c +++ b/network/ethernet.c @@ -55,17 +55,7 @@ void handle_ethernet(const uint8_t *packet, uint64_t packet_length) { kprintf("OUR OWN CALCULATED crc: %x\n", crc32((const char *)eth_header, (packet_length - 4))); - kprintf("mac dst: "); - for (int i = 0; i < 6; i++) - kprintf("%x", eth_header->mac_dst[i]); - kprintf("\n"); - kprintf("mac src: "); - for (int i = 0; i < 6; i++) - kprintf("%x", eth_header->mac_src[i]); - kprintf("\n"); - uint16_t type = ntohs(eth_header->type); - kprintf("Etheretype: %x\n", type); switch (type) { case 0x0806: handle_arp(payload); diff --git a/network/ipv4.c b/network/ipv4.c index e7ef2c2..099aa0d 100644 --- a/network/ipv4.c +++ b/network/ipv4.c @@ -1,11 +1,78 @@ #include <assert.h> +#include <kmalloc.h> +#include <network/arp.h> #include <network/bytes.h> +#include <network/ethernet.h> #include <network/ipv4.h> #include <network/udp.h> #include <string.h> +uint16_t ip_checksum(void *vdata, size_t length) { + // Cast the data pointer to one that can be indexed. + char *data = (char *)vdata; + + // Initialise the accumulator. + uint32_t acc = 0xffff; + + // Handle complete 16-bit blocks. + for (size_t i = 0; i + 1 < length; i += 2) { + uint16_t word; + memcpy(&word, data + i, 2); + acc += ntohs(word); + if (acc > 0xffff) { + acc -= 0xffff; + } + } + + // Handle any partial block at the end of the data. + if (length & 1) { + uint16_t word = 0; + memcpy(&word, data + length - 1, 1); + acc += ntohs(word); + if (acc > 0xffff) { + acc -= 0xffff; + } + } + + // Return the checksum in network byte order. + return htons(~acc); +} + +extern uint8_t ip_address[4]; +void send_ipv4_packet(uint32_t ip, uint8_t protocol, const uint8_t *payload, + uint16_t length) { + uint8_t header[20] = {0}; + header[0] = (4 /*version*/ << 4) | (5 /*IHL*/); + *((uint16_t *)(header + 2)) = htons(length + 20); + header[8 /*TTL*/] = 0xF8; + header[9] = protocol; + + memcpy(header + 12 /*src_ip*/, ip_address, sizeof(uint8_t[4])); + memcpy(header + 16, &ip, sizeof(uint8_t[4])); + + *((uint16_t *)(header + 10 /*checksum*/)) = ip_checksum(header, 20); + uint16_t packet_length = length + 20; + uint8_t *packet = kmalloc(packet_length); + memcpy(packet, header, 20); + memcpy(packet + 20, payload, length); + + uint8_t mac[6]; + uint8_t ip_copy[4]; // TODO: Do I need to do this? + memcpy(ip_copy, &ip, sizeof(uint8_t[4])); + get_mac_from_ip(ip_copy, mac); + send_ethernet_packet(mac, 0x0800, packet, packet_length); + kfree(packet); +} + void handle_ipv4(const uint8_t *payload, uint32_t packet_length) { assert(packet_length > 4); + + uint16_t saved_checksum = *(uint16_t *)(payload + 10); + *(uint16_t *)(payload + 10) = 0; + uint16_t calc_checksum = ip_checksum((uint8_t *)payload, 20); + *(uint16_t *)(payload + 10) = saved_checksum; + assert(calc_checksum == saved_checksum); + uint8_t version = (*payload & 0xF0) >> 4; uint8_t IHL = (*payload & 0xF); kprintf("version: %x\n", version); diff --git a/network/ipv4.h b/network/ipv4.h index 294a0ef..f578202 100644 --- a/network/ipv4.h +++ b/network/ipv4.h @@ -1,3 +1,5 @@ #include <stdint.h> void handle_ipv4(const uint8_t *payload, uint32_t packet_length); +void send_ipv4_packet(uint32_t ip, uint8_t protocol, const uint8_t *payload, + uint16_t length); diff --git a/network/udp.c b/network/udp.c index 29f17e1..23411da 100644 --- a/network/udp.c +++ b/network/udp.c @@ -1,8 +1,24 @@ #include <assert.h> #include <network/bytes.h> +#include <network/ipv4.h> #include <network/udp.h> #include <socket.h> +void send_udp_packet(struct sockaddr_in *src, const struct sockaddr_in *dst, + const uint8_t *payload, uint16_t payload_length) { + uint16_t header[4] = {0}; + header[0] = src->sin_port; + header[1] = dst->sin_port; + header[2] = htons(payload_length + 8); + + uint16_t packet_length = sizeof(header) + payload_length; + uint8_t *packet = kmalloc(packet_length); + memcpy(packet, header, sizeof(header)); + memcpy(packet + sizeof(header), payload, payload_length); + send_ipv4_packet(dst->sin_addr.s_addr, 0x11, packet, packet_length); + kfree(packet); +} + void handle_udp(uint8_t src_ip[4], const uint8_t *payload, uint32_t packet_length) { assert(packet_length >= 8); @@ -10,11 +26,10 @@ void handle_udp(uint8_t src_ip[4], const uint8_t *payload, // h_.* means host format((probably) little endian) uint16_t n_source_port = *(uint16_t *)payload; uint16_t h_source_port = ntohs(n_source_port); + (void)h_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; diff --git a/network/udp.h b/network/udp.h index 8278b87..c30b8c8 100644 --- a/network/udp.h +++ b/network/udp.h @@ -1,3 +1,7 @@ +#include <socket.h> #include <stdint.h> -void handle_udp(uint8_t src_ip[4], const uint8_t *payload, uint32_t packet_length); +void handle_udp(uint8_t src_ip[4], const uint8_t *payload, + uint32_t packet_length); +void send_udp_packet(struct sockaddr_in *src, const struct sockaddr_in *dst, + const uint8_t *payload, uint16_t payload_length); diff --git a/scalls/sendto.c b/scalls/sendto.c new file mode 100644 index 0000000..48c4020 --- /dev/null +++ b/scalls/sendto.c @@ -0,0 +1,23 @@ +#include <assert.h> +#include <network/bytes.h> +#include <network/udp.h> +#include <scalls/sendto.h> + +size_t syscall_sendto(int socket, const void *message, size_t length, + int flags, struct t_two_args *extra_args /* + const struct sockaddr *dest_addr, + socklen_t dest_len*/) { + const struct sockaddr *dest_addr = (const struct sockaddr *)extra_args->a; + socklen_t dest_len = (socklen_t)extra_args->b; + (void)dest_len; + vfs_fd_t *fd = get_vfs_fd(socket); + assert(fd); + SOCKET *s = (SOCKET *)fd->inode->internal_object; + OPEN_INET_SOCKET *inet = s->child; + assert(inet); + struct sockaddr_in in; + in.sin_addr.s_addr = inet->address; + in.sin_port = inet->port; + send_udp_packet(&in, (const struct sockaddr_in *)dest_addr, message, length); + return length; // FIXME: This is probably not true. +} diff --git a/scalls/sendto.h b/scalls/sendto.h new file mode 100644 index 0000000..0f852de --- /dev/null +++ b/scalls/sendto.h @@ -0,0 +1,11 @@ +#include <socket.h> +#include <stdint.h> + +struct t_two_args { + uint32_t a; + uint32_t b; +}; +size_t syscall_sendto(int socket, const void *message, size_t length, + int flags, struct t_two_args *extra_args /* + const struct sockaddr *dest_addr, + socklen_t dest_len*/); @@ -111,6 +111,7 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { us->path = s->path; us->s = s; + s->child = us; devfs_add_file(us->path, NULL, NULL, NULL, 1, 1, FS_TYPE_UNIX_SOCKET); return 0; } @@ -127,6 +128,7 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { inet->address = in->sin_addr.s_addr; inet->port = in->sin_port; inet->s = s; + s->child = inet; return 0; } return 0; @@ -22,6 +22,7 @@ typedef struct { int domain; int type; int protocol; + void *child; // UNIX socket char *path; @@ -53,6 +54,7 @@ struct sockaddr_in { sa_family_t sin_family; union { uint32_t s_addr; + uint8_t a[4]; } sin_addr; uint16_t sin_port; }; diff --git a/userland/libc/Makefile b/userland/libc/Makefile index 02f5584..bcb82f8 100644 --- a/userland/libc/Makefile +++ b/userland/libc/Makefile @@ -2,7 +2,7 @@ CC="i686-sb-gcc" AR="i686-sb-ar" AS="i686-sb-as" CFLAGS = -ggdb -ffreestanding -O2 -Wall -pedantic -Wimplicit-fallthrough -I./include/ -static -OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o memset.o assert.o stdio/snprintf.o stdio/vfprintf.o string/memcpy.o string/memcmp.o string/strcmp.o ubsan.o string/strcpy.o isspace.o stdio/puts.o stdio/putchar.o dirent/opendir.o dirent/readdir.o dirent/closedir.o unistd/getopt.o dirent/scandir.o dirent/alphasort.o stdio/printf.o stdio/vdprintf.o stdio/vprintf.o stdio/dprintf.o stdio/vprintf.o string/strlen.o string/strnlen.o stdio/stdin.o stdio/getchar.o stdio/fgetc.o arpa/inet/htons.o arpa/inet/htonl.o stdio/fread.o stdio/fwrite.o stdio/fopen.o stdio/fclose.o stdio/fseek.o ctype/isascii.o stdio/fprintf.o stdlib/atoi.o stdlib/strtol.o ctype/toupper.o ctype/tolower.o string/strcat.o string/strchr.o string/sscanf.o sys/stat/stat.o stdlib/getenv.o string/strrchr.o stdio/ftell.o stdio/tmpfile.o stdio/fgets.o stdio/feof.o stdio/fscanf.o stdio/ungetc.o string/strncmp.o stdio/fputc.o string/strncpy.o stdio/remove.o stdio/ferror.o stdio/fputs.o stdlib/rand.o stdlib/srand.o unistd/getpid.o stdlib/strtoul.o stdio/fflush.o stdlib/abort.o string/strcspn.o time/localtime.o time/time.o time/clock_gettime.o time/gmtime.o time/strftime.o string/strpbrk.o ctype/isdigit.o ctype/isalpha.o ctype/isxdigit.o ctype/ispunct.o stdio/setvbuf.o stdio/fileno.o stdio/putc.o stdio/sprintf.o stdlib/abs.o string/strspn.o stdlib/qsort.o string/memmove.o setjmp/longjmp.o setjmp/setjmp.o libgen/basename.o string/strdup.o string/strndup.o string/strlcpy.o stdlib/atexit.o stdio/open_memstream.o libgen/dirname.o unistd/unlink.o string/strstr.o string/strcasecmp.o string/strncasecmp.o stdlib/mkstemp.o string/strtok.o unistd/execvp.o unistd/_exit.o ctype/isalnum.o time/ctime_r.o stdlib/strtold.o sys/time/gettimeofday.o stdio/fgetpos.o stdio/fsetpos.o ctype/isprint.o stdlib/system.o stdio/tmpnam.o unistd/msleep.o stdlib/atof.o stdlib/strtod.o stdio/rename.o sys/stat/mkdir.o unistd/uptime.o unistd/ftruncate.o sys/socket/recvfrom.o +OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o memset.o assert.o stdio/snprintf.o stdio/vfprintf.o string/memcpy.o string/memcmp.o string/strcmp.o ubsan.o string/strcpy.o isspace.o stdio/puts.o stdio/putchar.o dirent/opendir.o dirent/readdir.o dirent/closedir.o unistd/getopt.o dirent/scandir.o dirent/alphasort.o stdio/printf.o stdio/vdprintf.o stdio/vprintf.o stdio/dprintf.o stdio/vprintf.o string/strlen.o string/strnlen.o stdio/stdin.o stdio/getchar.o stdio/fgetc.o arpa/inet/htons.o arpa/inet/htonl.o stdio/fread.o stdio/fwrite.o stdio/fopen.o stdio/fclose.o stdio/fseek.o ctype/isascii.o stdio/fprintf.o stdlib/atoi.o stdlib/strtol.o ctype/toupper.o ctype/tolower.o string/strcat.o string/strchr.o string/sscanf.o sys/stat/stat.o stdlib/getenv.o string/strrchr.o stdio/ftell.o stdio/tmpfile.o stdio/fgets.o stdio/feof.o stdio/fscanf.o stdio/ungetc.o string/strncmp.o stdio/fputc.o string/strncpy.o stdio/remove.o stdio/ferror.o stdio/fputs.o stdlib/rand.o stdlib/srand.o unistd/getpid.o stdlib/strtoul.o stdio/fflush.o stdlib/abort.o string/strcspn.o time/localtime.o time/time.o time/clock_gettime.o time/gmtime.o time/strftime.o string/strpbrk.o ctype/isdigit.o ctype/isalpha.o ctype/isxdigit.o ctype/ispunct.o stdio/setvbuf.o stdio/fileno.o stdio/putc.o stdio/sprintf.o stdlib/abs.o string/strspn.o stdlib/qsort.o string/memmove.o setjmp/longjmp.o setjmp/setjmp.o libgen/basename.o string/strdup.o string/strndup.o string/strlcpy.o stdlib/atexit.o stdio/open_memstream.o libgen/dirname.o unistd/unlink.o string/strstr.o string/strcasecmp.o string/strncasecmp.o stdlib/mkstemp.o string/strtok.o unistd/execvp.o unistd/_exit.o ctype/isalnum.o time/ctime_r.o stdlib/strtold.o sys/time/gettimeofday.o stdio/fgetpos.o stdio/fsetpos.o ctype/isprint.o stdlib/system.o stdio/tmpnam.o unistd/msleep.o stdlib/atof.o stdlib/strtod.o stdio/rename.o sys/stat/mkdir.o unistd/uptime.o unistd/ftruncate.o sys/socket/recvfrom.o sys/socket/sendto.o all: libc.a %.o: %.c diff --git a/userland/libc/include/sys/socket.h b/userland/libc/include/sys/socket.h index 18402d0..c4f10e2 100644 --- a/userland/libc/include/sys/socket.h +++ b/userland/libc/include/sys/socket.h @@ -5,3 +5,5 @@ size_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len); +size_t sendto(int socket, const void *message, size_t length, int flags, + const struct sockaddr *dest_addr, socklen_t dest_len); diff --git a/userland/libc/include/syscall.h b/userland/libc/include/syscall.h index 7d84b8f..3af425d 100644 --- a/userland/libc/include/syscall.h +++ b/userland/libc/include/syscall.h @@ -33,6 +33,7 @@ #define SYS_UPTIME 25 #define SYS_MKDIR 26 #define SYS_RECVFROM 27 +#define SYS_SENDTO 28 int syscall(uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx, uint32_t esi, uint32_t edi); diff --git a/userland/libc/sys/socket/recvfrom.c b/userland/libc/sys/socket/recvfrom.c new file mode 100644 index 0000000..5bbfeea --- /dev/null +++ b/userland/libc/sys/socket/recvfrom.c @@ -0,0 +1,17 @@ +#include <assert.h> +#include <sys/socket.h> +#include <syscall.h> + +struct two_args { + uint32_t a; + uint32_t b; +}; + +size_t recvfrom(int socket, void *buffer, size_t length, int flags, + struct sockaddr *address, socklen_t *address_len) { + struct two_args extra_args; + extra_args.a = address; + extra_args.b = address_len; + + return syscall(SYS_RECVFROM, socket, buffer, length, flags, &extra_args); +} diff --git a/userland/libc/sys/socket/sendto.c b/userland/libc/sys/socket/sendto.c new file mode 100644 index 0000000..73437ab --- /dev/null +++ b/userland/libc/sys/socket/sendto.c @@ -0,0 +1,16 @@ +#include <sys/socket.h> +#include <syscall.h> + +struct two_args { + uint32_t a; + uint32_t b; +}; + +size_t sendto(int socket, const void *message, size_t length, int flags, + const struct sockaddr *dest_addr, socklen_t dest_len) { + struct two_args extra = { + .a = dest_addr, + .b = dest_len, + }; + return syscall(SYS_SENDTO, socket, message, length, flags, &extra); +} |