From c5fe5e8b63d2d7552924386a70a29ec372c088d8 Mon Sep 17 00:00:00 2001 From: William Durand Date: Thu, 10 Feb 2022 21:58:43 +0100 Subject: [PATCH] kernel: add linux compatibility layer --- Makefile | 6 + Makefile-cfg.include | 2 + data/initrd/etc/hosts | 1 + data/initrd/etc/passwd | 1 + include/kernel/proc/descriptor.h | 8 + include/libc/fcntl.h | 3 + include/libc/sys/linux_compat.h | 95 +++++++++ include/libc/sys/socket.h | 5 +- include/libc/sys/syscall.h | 8 + src/kernel/arch/x86_64/Makefile.include | 2 +- src/kernel/arch/x86_64/asm/boot.asm | 23 +++ src/kernel/arch/x86_64/proc/process.c | 33 ++- src/kernel/arch/x86_64/proc/process.h | 11 +- src/kernel/net/ipv4.c | 9 + src/kernel/net/udp.c | 2 +- src/kernel/proc/descriptor.c | 37 +++- src/kernel/sys/k_read.c | 11 +- src/kernel/sys/k_recvfrom.c | 30 ++- src/kernel/sys/k_sendto.c | 89 ++++++-- src/kernel/sys/k_socket.c | 18 +- src/kernel/sys/k_syscall.c | 256 +++++++++++++++++++++++- src/kernel/sys/k_write.c | 19 +- src/libc/putchar.c | 3 +- src/userland/Makefile.include | 4 + 24 files changed, 612 insertions(+), 64 deletions(-) create mode 100644 data/initrd/etc/hosts create mode 100644 data/initrd/etc/passwd create mode 100644 include/libc/sys/linux_compat.h diff --git a/Makefile b/Makefile index ec34e4cca..61cca7c92 100644 --- a/Makefile +++ b/Makefile @@ -160,6 +160,11 @@ ifeq ($(CONFIG_USE_FAKE_CLOCK), 1) libk_c_files += $(kernel_src_dir)/time/fake_clock.c endif +ifeq ($(CONFIG_LINUX_COMPAT), 1) + KERNEL_CONFIG += -DCONFIG_LINUX_COMPAT + LIBC_CONFIG += -DCONFIG_LINUX_COMPAT +endif + # This file exists in a Docker container because we copy it in `Dockerfile`. in_docker = $(wildcard /tmp/install-linux-deps) ifneq ($(in_docker),) @@ -429,6 +434,7 @@ what: ## display some information about the current configuration echo "OS_NAME : $(OS_NAME)" echo "ARCH : $(ARCH)" echo "" + echo "CONFIG_LINUX_COMPAT = $(CONFIG_LINUX_COMPAT)" echo "CONFIG_SEMIHOSTING = $(CONFIG_SEMIHOSTING)" echo "CONFIG_USE_DLMALLOC = $(CONFIG_USE_DLMALLOC)" echo "CONFIG_USE_FAKE_CLOCK = $(CONFIG_USE_FAKE_CLOCK)" diff --git a/Makefile-cfg.include b/Makefile-cfg.include index 9f7794b7c..ec370f177 100644 --- a/Makefile-cfg.include +++ b/Makefile-cfg.include @@ -6,6 +6,8 @@ LLVM_SUFFIX ?= # When set to 1, enable the Undefined Behavior SANitizer. UBSAN ?= +# When set to 1, enable Linux (binary) compatibility. +CONFIG_LINUX_COMPAT ?= # When set to 1, enable semi-hosting mode (QEMU, mainly). CONFIG_SEMIHOSTING ?= # When set to 1, use dlmalloc for malloc/free/realloc (instead of liballoc). diff --git a/data/initrd/etc/hosts b/data/initrd/etc/hosts new file mode 100644 index 000000000..988ed358d --- /dev/null +++ b/data/initrd/etc/hosts @@ -0,0 +1 @@ +140.82.121.4 github diff --git a/data/initrd/etc/passwd b/data/initrd/etc/passwd new file mode 100644 index 000000000..038b4bfad --- /dev/null +++ b/data/initrd/etc/passwd @@ -0,0 +1 @@ +root:x:0:0::/:none diff --git a/include/kernel/proc/descriptor.h b/include/kernel/proc/descriptor.h index 1fc452a1e..de27a62ce 100644 --- a/include/kernel/proc/descriptor.h +++ b/include/kernel/proc/descriptor.h @@ -2,9 +2,11 @@ #ifndef PROC_DESCRIPTOR_H #define PROC_DESCRIPTOR_H +#include #include #include #include +#include #include #define STDIN 0 @@ -23,6 +25,8 @@ typedef struct descriptor uint32_t type; uint32_t protocol; uint16_t port; + struct sockaddr_in addr; + socklen_t addr_len; } descriptor_t; /** @@ -82,4 +86,8 @@ int descriptor_udp_lookup(uint16_t port); */ bool is_protocol_supported(uint32_t type, uint32_t protocol); +void duplicate_descriptor(int oldfd, int newfd); + +int descriptor_raw_lookup(uint32_t protocol, in_addr_t src_addr); + #endif diff --git a/include/libc/fcntl.h b/include/libc/fcntl.h index 740f3a5f8..f321f2b2c 100644 --- a/include/libc/fcntl.h +++ b/include/libc/fcntl.h @@ -15,6 +15,9 @@ /// Truncate file. #define O_TRUNC 0x0200 +/// Mask to determine the file access mode. +#define O_ACCMODE 0x3 + /// Set file descriptor offset to offset. #define SEEK_SET 0 /// Set file descriptor offset to current plus offset. diff --git a/include/libc/sys/linux_compat.h b/include/libc/sys/linux_compat.h new file mode 100644 index 000000000..6712ffe2f --- /dev/null +++ b/include/libc/sys/linux_compat.h @@ -0,0 +1,95 @@ +// https://chromium.googlesource.com/chromiumos/docs/+/HEAD/constants/syscalls.md +#ifndef SYS_LINUX_COMPAT_H +#define SYS_LINUX_COMPAT_H + +#ifdef __x86_64__ + +#define SYSCALL_READ 0 +#define SYSCALL_WRITE 1 +#define SYSCALL_OPEN 2 +#define SYSCALL_CLOSE 3 +#define SYSCALL_FSTAT 5 +#define SYSCALL_LSEEK 8 +#define SYSCALL_BRK 12 +#define SYSCALL_IOCTL 16 +#define SYSCALL_WRITEV 20 +#define SYSCALL_DUP2 33 +#define SYSCALL_GETPID 39 +#define SYSCALL_SOCKET 41 +#define SYSCALL_SENDTO 44 +#define SYSCALL_RECVFROM 45 +#define SYSCALL_EXECV 49 +#define SYSCALL_EXIT 60 +#define SYSCALL_GETTIMEOFDAY 96 +#define SYSCALL_GETEUID 107 +#define SYSCALL_ARCH_PRCTL 158 +#define SYSCALL_REBOOT 169 +#define SYSCALL_SET_TID_ADDR 218 +#define SYSCALL_EXIT_GROUP 231 +#define SYSCALL_OPENAT 257 + +#elif __arm__ + +#define SYSCALL_EXIT 1 +#define SYSCALL_READ 3 +#define SYSCALL_WRITE 4 +#define SYSCALL_OPEN 5 +#define SYSCALL_CLOSE 6 +#define SYSCALL_EXECV 11 +#define SYSCALL_LSEEK 19 +#define SYSCALL_GETPID 20 +#define SYSCALL_BRK 45 +#define SYSCALL_GETEUID 49 +#define SYSCALL_IOCTL 54 +#define SYSCALL_DUP2 63 +#define SYSCALL_GETTIMEOFDAY 78 +#define SYSCALL_REBOOT 88 +#define SYSCALL_FSTAT 108 +#define SYSCALL_WRITEV 146 +#define SYSCALL_EXIT_GROUP 248 +#define SYSCALL_SET_TID_ADDR 256 +#define SYSCALL_SOCKET 281 +#define SYSCALL_SENDTO 290 +#define SYSCALL_RECVFROM 292 +#define SYSCALL_OPENAT 322 + +// Not available on AArch32: +// +// - SYSCALL_ARCH_PRCTL + +#elif __aarch64__ + +#define SYSCALL_IOCTL 29 +#define SYSCALL_OPENAT 56 +#define SYSCALL_CLOSE 57 +#define SYSCALL_LSEEK 62 +#define SYSCALL_READ 63 +#define SYSCALL_WRITE 64 +#define SYSCALL_WRITEV 66 +#define SYSCALL_FSTAT 80 +#define SYSCALL_EXIT 93 +#define SYSCALL_EXIT_GROUP 94 +#define SYSCALL_SET_TID_ADDR 96 +#define SYSCALL_REBOOT 142 +#define SYSCALL_GETTIMEOFDAY 169 +#define SYSCALL_GETPID 172 +#define SYSCALL_GETEUID 175 +#define SYSCALL_SOCKET 198 +#define SYSCALL_SENDTO 206 +#define SYSCALL_RECVFROM 207 +#define SYSCALL_BRK 214 +#define SYSCALL_EXECV 221 + +// Not available on AArch64: +// +// - SYSCALL_OPEN +// - SYSCALL_DUP2 +// - SYSCALL_ARCH_PRCTL + +#endif + +// Not available outside ArvernOS: +#define SYSCALL_TEST 348 +#define SYSCALL_GETHOSTBYNAME2 349 + +#endif diff --git a/include/libc/sys/socket.h b/include/libc/sys/socket.h index 1279a09dc..1172a639b 100644 --- a/include/libc/sys/socket.h +++ b/include/libc/sys/socket.h @@ -8,8 +8,11 @@ #define AF_INET 2 // Types #define SOCK_DGRAM 2 +#define SOCK_RAW 3 // Protocols -#define IPPROTO_UDP 17 +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_UDP 17 typedef uint16_t sa_family_t; diff --git a/include/libc/sys/syscall.h b/include/libc/sys/syscall.h index 276f7fc41..c37818ba4 100644 --- a/include/libc/sys/syscall.h +++ b/include/libc/sys/syscall.h @@ -11,6 +11,12 @@ #include #include +#ifdef CONFIG_LINUX_COMPAT + +#include + +#else + #define SYSCALL_TEST 1 #define SYSCALL_WRITE 2 #define SYSCALL_READ 3 @@ -29,6 +35,8 @@ #define SYSCALL_EXIT 16 #define SYSCALL_OPENAT 17 +#endif // CONFIG_LINUX_COMPAT + #define SYSCALL_SET_ERRNO() \ if (retval < 0) { \ errno = -retval; \ diff --git a/src/kernel/arch/x86_64/Makefile.include b/src/kernel/arch/x86_64/Makefile.include index 1f7089498..0190bab75 100644 --- a/src/kernel/arch/x86_64/Makefile.include +++ b/src/kernel/arch/x86_64/Makefile.include @@ -27,7 +27,7 @@ QEMU = qemu-system-x86_64 # Options for the different tools ############################################################################### -QEMU_OPTIONS += -m 512M +QEMU_OPTIONS += -m 512M -cpu IvyBridge QEMU_OPTIONS += -serial file:$(log_file) QEMU_OPTIONS += -netdev user,id=u1,ipv6=off,dhcpstart=10.0.2.20 QEMU_OPTIONS += -device rtl8139,netdev=u1 diff --git a/src/kernel/arch/x86_64/asm/boot.asm b/src/kernel/arch/x86_64/asm/boot.asm index 545004b0c..120713fb3 100644 --- a/src/kernel/arch/x86_64/asm/boot.asm +++ b/src/kernel/arch/x86_64/asm/boot.asm @@ -28,11 +28,34 @@ start: ; load the 64-bit GDT lgdt [gdt64.pointer] + call enable_sse + + mov eax, cr4 + or eax, 1 << 16 + mov cr4, eax + jmp gdt64.kernel_code:long_mode_start ; Should not be reached. hlt +enable_sse: + mov eax, 0x1 ; check for SSE + cpuid + test edx, 1 << 25 + jz .no_sse ; after this, SSE can be enabled + mov eax, cr0 + and ax, 0xFFFB ; clear coprocessor emulation CR0.EM + or ax, 0x2 ; set coprocessor monitoring CR0.MP + mov cr0, eax + mov eax, cr4 + or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time + mov cr4, eax + ret + +.no_sse: + ret + ; ----------------------------------------------------------------------------- ; make sure the kernel was really loaded by a Multiboot compliant bootloader %define MULTIBOOT2_MAGIC_VALUE 0x36d76289 diff --git a/src/kernel/arch/x86_64/proc/process.c b/src/kernel/arch/x86_64/proc/process.c index 41b9f2742..0259d7b30 100644 --- a/src/kernel/arch/x86_64/proc/process.c +++ b/src/kernel/arch/x86_64/proc/process.c @@ -36,11 +36,16 @@ process_t* process_exec(uint8_t* image, const char* name, char* const argv[]) } // Load ELF in current process. + // TODO: Handle the case where the image isn't a valid/supported ELF. elf_header_t* elf = elf_load(image); current_process->elf = elf; // Set current process name. current_process->name = strdup(name); + + memset(current_process->user_heap, 0, USER_HEAP_SIZE); + current_process->user_brk = (uintptr_t)current_process->user_heap; + // Set up user stack. memset(current_process->user_stack, 0, USER_STACK_SIZE); @@ -66,8 +71,35 @@ process_t* process_exec(uint8_t* image, const char* name, char* const argv[]) void* stack = (void*)¤t_process->user_stack[USER_STACK_TOP]; char* buf = (char*)¤t_process->user_stack[USER_STACK_BUF]; + size_t off = 0; + // auxv + uint8_t rand_bytes[16] = { + 0xaa, 0xc0, 0xff, 0xee, 0xc0, 0xff, 0xee, 0xc0, + 0xff, 0xee, 0xc0, 0xff, 0xee, 0xc0, 0xff, 0xee, + }; + memcpy(&buf[off], rand_bytes, sizeof(rand_bytes)); + char* rand_ptr = &buf[off]; + off += sizeof(rand_bytes); + + // aux: AT_NULL + PUSH_TO_STACK(stack, uintptr_t, (uintptr_t)NULL); PUSH_TO_STACK(stack, uintptr_t, (uintptr_t)NULL); + // aux: AT_RANDOM + PUSH_TO_STACK(stack, uintptr_t, (uintptr_t)rand_ptr); + PUSH_TO_STACK(stack, uint64_t, 25); + // aux: AT_PAGESZ + PUSH_TO_STACK(stack, uint64_t, 4096); + PUSH_TO_STACK(stack, uint64_t, 6); + // aux: AT_PHNUM + PUSH_TO_STACK(stack, uint64_t, elf->ph_num); + PUSH_TO_STACK(stack, uint64_t, 5); + // aux: AT_PHENT + PUSH_TO_STACK(stack, uint64_t, elf->ph_size); + PUSH_TO_STACK(stack, uint64_t, 4); + // aux: AT_PHDR + PUSH_TO_STACK(stack, uintptr_t, (uintptr_t)image + elf->ph_offset); + PUSH_TO_STACK(stack, uint64_t, 3); // envp PUSH_TO_STACK(stack, uintptr_t, (uintptr_t)NULL); @@ -81,7 +113,6 @@ process_t* process_exec(uint8_t* image, const char* name, char* const argv[]) // argv PUSH_TO_STACK(stack, uintptr_t, (uintptr_t)NULL); - size_t off = 0; for (int i = argc - 1; i >= 0; i--) { size_t len = strlen(argv[i]); // Copy argv[i] to high address in initial process stack. diff --git a/src/kernel/arch/x86_64/proc/process.h b/src/kernel/arch/x86_64/proc/process.h index a1c453789..f5a097cb2 100644 --- a/src/kernel/arch/x86_64/proc/process.h +++ b/src/kernel/arch/x86_64/proc/process.h @@ -4,9 +4,10 @@ #include #include -#define USER_STACK_SIZE 0x3000 -#define USER_STACK_TOP 0x1000 -#define USER_STACK_BUF 0x2000 +#define USER_STACK_SIZE 0x30000 +#define USER_STACK_TOP 0x01000 +#define USER_STACK_BUF 0x02000 +#define USER_HEAP_SIZE 0x10000 typedef struct process { @@ -14,7 +15,9 @@ typedef struct process char* name; elf_header_t* elf; uint64_t user_stack[USER_STACK_SIZE]; - uint64_t user_rsp; + uintptr_t user_rsp; + uint64_t user_heap[USER_HEAP_SIZE]; + uintptr_t user_brk; // TODO: We should probably retain the file descriptors that are opened by // the process so that we can close them. } process_t; diff --git a/src/kernel/net/ipv4.c b/src/kernel/net/ipv4.c index e2e309428..8fc342cea 100644 --- a/src/kernel/net/ipv4.c +++ b/src/kernel/net/ipv4.c @@ -5,9 +5,11 @@ #include #include #include +#include #include #include #include +#include ipv4_header_t ipv4_create_header(uint8_t src_ip[4], in_addr_t dst_addr, @@ -36,6 +38,13 @@ void ipv4_receive_packet(net_interface_t* interface, src_ip[3], interface->id); + int sockfd = descriptor_raw_lookup(header.proto, header.src_addr); + if (sockfd >= 0) { + // Handle SOCK_RAW. + write(sockfd, data, len); + return; + } + switch (header.proto) { case IPV4_PROTO_ICMP: icmpv4_receive_packet(interface, data, &header); diff --git a/src/kernel/net/udp.c b/src/kernel/net/udp.c index ccf9accca..9a3855049 100644 --- a/src/kernel/net/udp.c +++ b/src/kernel/net/udp.c @@ -34,7 +34,7 @@ void udp_receive_packet(net_interface_t* interface, int sockfd = descriptor_udp_lookup(udp_header.dst_port); NET_DEBUG("got sockfd=%d for dst_port=%d", sockfd, udp_header.dst_port); - if (sockfd > 0) { + if (sockfd >= 0) { write(sockfd, udp_data, udp_header.len - sizeof(udp_header_t)); return; } diff --git a/src/kernel/proc/descriptor.c b/src/kernel/proc/descriptor.c index ad2edca41..8417d121e 100644 --- a/src/kernel/proc/descriptor.c +++ b/src/kernel/proc/descriptor.c @@ -1,7 +1,6 @@ #include #include -#include #define NB_SYSTEM_DESCRIPTORS 20 @@ -39,6 +38,12 @@ descriptor_t* get_descriptor(int id) return &descriptors[id]; } +void duplicate_descriptor(int oldfd, int newfd) +{ + memcpy(&descriptors[newfd], get_descriptor(oldfd), sizeof(descriptor_t)); + delete_descriptor(oldfd); +} + void delete_descriptor(int id) { if (id >= NB_SYSTEM_DESCRIPTORS) { @@ -71,10 +76,31 @@ int create_socket_descriptor(inode_t inode, return -1; } +int descriptor_raw_lookup(uint32_t protocol, in_addr_t src_addr) +{ + for (uint8_t fd = 0; fd < NB_SYSTEM_DESCRIPTORS; fd++) { + if (!descriptors[fd].used || descriptors[fd].type != SOCK_RAW || + descriptors[fd].protocol != protocol) { + continue; + } + + struct sockaddr_in sa = { 0 }; + memcpy(&sa, &descriptors[fd].addr, descriptors[fd].addr_len); + + if (sa.sin_addr.s_addr == src_addr) { + return fd; + } + } + + return -1; +} + int descriptor_udp_lookup(uint16_t port) { for (uint8_t fd = 3; fd < NB_SYSTEM_DESCRIPTORS; fd++) { - if (descriptors[fd].used && descriptors[fd].port == port) { + if (descriptors[fd].used && descriptors[fd].type == SOCK_DGRAM && + descriptors[fd].protocol == IPPROTO_UDP && + descriptors[fd].port == port) { return fd; } } @@ -87,10 +113,17 @@ bool is_protocol_supported(uint32_t type, uint32_t protocol) switch (type) { case SOCK_DGRAM: switch (protocol) { + case IPPROTO_IP: case IPPROTO_UDP: return true; } break; + + case SOCK_RAW: + switch (protocol) { + case IPPROTO_ICMP: + return true; + } } return false; diff --git a/src/kernel/sys/k_read.c b/src/kernel/sys/k_read.c index 5b8b20591..1b01ae765 100644 --- a/src/kernel/sys/k_read.c +++ b/src/kernel/sys/k_read.c @@ -12,8 +12,12 @@ ssize_t k_read(int fd, void* buf, size_t count) { + SYS_DEBUG("fd=%d", fd); + if (fd == STDIN_FILENO) { - unsigned char c = arch_getchar(false); + // TODO: This was changed to please `read(STDIN)` for Linux compat' but I + // am not sure that's what we want... + unsigned char c = arch_getchar(true); if (c) { ((uint8_t*)buf)[0] = c; @@ -37,8 +41,9 @@ ssize_t k_read(int fd, void* buf, size_t count) return -EBADF; } - if ((desc->flags != O_RDONLY && desc->flags != O_RDWR) || - desc->flags == O_WRONLY) { + if (((desc->flags & O_RDONLY) != O_RDONLY && + (desc->flags & O_RDWR) != O_RDWR) || + (desc->flags & O_WRONLY) == O_WRONLY) { SYS_DEBUG("invalid flags for file descriptor fd=%d", fd); return -EBADF; } diff --git a/src/kernel/sys/k_recvfrom.c b/src/kernel/sys/k_recvfrom.c index fd625a911..dd9e97230 100644 --- a/src/kernel/sys/k_recvfrom.c +++ b/src/kernel/sys/k_recvfrom.c @@ -5,6 +5,7 @@ #include #include #include +#include #include ssize_t k_recvfrom(int sockfd, @@ -14,15 +15,8 @@ ssize_t k_recvfrom(int sockfd, struct sockaddr* src_addr, socklen_t* addrlen) { - UNUSED(addrlen); - UNUSED(src_addr); UNUSED(flags); - if (sockfd < 3) { - SYS_DEBUG("invalid socket descriptor sd=%d", sockfd); - return -ENOTSOCK; - } - descriptor_t* desc = get_descriptor(sockfd); if (desc == NULL) { @@ -30,11 +24,27 @@ ssize_t k_recvfrom(int sockfd, return -EBADF; } - if (desc->domain != AF_INET || desc->type != SOCK_DGRAM || - !is_protocol_supported(desc->type, desc->protocol)) { - SYS_DEBUG("invalid sockfd=%d", sockfd); + if (desc->domain != AF_INET) { + SYS_DEBUG("invalid domain for sockfd=%d", sockfd); + return -EINVAL; + } + + switch (desc->type) { + case SOCK_DGRAM: + case SOCK_RAW: + break; + default: + SYS_DEBUG("invalid type for sockfd=%d", sockfd); + return -EINVAL; + } + + if (!is_protocol_supported(desc->type, desc->protocol)) { + SYS_DEBUG("unsupported protocol for sockfd=%d", sockfd); return -EINVAL; } + memcpy(src_addr, &desc->addr, desc->addr_len); + *addrlen = desc->addr_len; + return vfs_read(desc->inode, buf, len, 0); } diff --git a/src/kernel/sys/k_sendto.c b/src/kernel/sys/k_sendto.c index 824342efa..3531b1fb2 100644 --- a/src/kernel/sys/k_sendto.c +++ b/src/kernel/sys/k_sendto.c @@ -15,12 +15,7 @@ ssize_t k_sendto(int sockfd, const struct sockaddr* dst_addr, socklen_t addrlen) { - UNUSED(flags); - - if (sockfd < 3) { - SYS_DEBUG("invalid socket descriptor sd=%d", sockfd); - return -ENOTSOCK; - } + SYS_DEBUG("sockfd=%d buf=%p len=%d flags=%d", sockfd, buf, len, flags); descriptor_t* desc = get_descriptor(sockfd); @@ -29,27 +24,79 @@ ssize_t k_sendto(int sockfd, return -EBADF; } - if (desc->domain != AF_INET || desc->type != SOCK_DGRAM || - !is_protocol_supported(desc->type, desc->protocol)) { - SYS_DEBUG("invalid sockfd=%d", sockfd); + if (desc->domain != AF_INET) { + SYS_DEBUG("invalid domain for sockfd=%d", sockfd); + return -EINVAL; + } + + switch (desc->type) { + case SOCK_DGRAM: + case SOCK_RAW: + break; + default: + SYS_DEBUG("invalid type for sockfd=%d", sockfd); + return -EINVAL; + } + + if (!is_protocol_supported(desc->type, desc->protocol)) { + SYS_DEBUG("unsupported protocol for sockfd=%d", sockfd); return -EINVAL; } + SYS_DEBUG("descriptor: domain=%d type=%d protocol=%d", + desc->domain, + desc->type, + desc->protocol); + + memcpy(&desc->addr, dst_addr, addrlen); + desc->addr_len = addrlen; + net_interface_t* interface = net_get_interface(0); - struct sockaddr_in addr = { 0 }; - memcpy(&addr, dst_addr, addrlen); + switch (desc->type) { + case SOCK_DGRAM: + switch (desc->protocol) { + case IPPROTO_IP: + ipv4_send_packet(interface, + (struct sockaddr_in*)&desc->addr, + IPV4_PROTO_ICMP, + 0, + (uint8_t*)buf, + len); + return len; - switch (desc->protocol) { - case IPPROTO_UDP: - udp_send_packet( - interface, desc->port, interface->mac, &addr, (uint8_t*)buf, len); - break; - default: - // Indicate that something went wrong, even though the type and protocol - // are supported. - len = 0; + case IPPROTO_UDP: + udp_send_packet(interface, + desc->port, + interface->mac, + (struct sockaddr_in*)&desc->addr, + (uint8_t*)buf, + len); + return len; + + default: + // Indicate that something went wrong, even though the type and + // protocol are supported. + return 0; + } + + case SOCK_RAW: + switch (desc->protocol) { + case IPPROTO_ICMP: + ipv4_send_packet(interface, + (struct sockaddr_in*)&desc->addr, + IPV4_PROTO_ICMP, + 0, + (uint8_t*)buf, + len); + return len; + + default: + // Indicate that something went wrong, even though the type and + // protocol are supported. + return 0; + } } - return len; + return 0; } diff --git a/src/kernel/sys/k_socket.c b/src/kernel/sys/k_socket.c index 9e45aa30a..c8959d8e5 100644 --- a/src/kernel/sys/k_socket.c +++ b/src/kernel/sys/k_socket.c @@ -8,12 +8,18 @@ int k_socket(int domain, int type, int protocol) { + SYS_DEBUG("domain=%d type=%d protocol=%d", domain, type, protocol); + if (domain != AF_INET) { return -EAFNOSUPPORT; } - if (type != SOCK_DGRAM) { - return -ESOCKTNOSUPPORT; + switch (type) { + case SOCK_DGRAM: + case SOCK_RAW: + break; + default: + return -ESOCKTNOSUPPORT; } if (!is_protocol_supported(type, protocol)) { @@ -43,6 +49,12 @@ int k_socket(int domain, int type, int protocol) return -ENFILE; } - SYS_DEBUG("open sd=%d", sd); + SYS_DEBUG("open sd=%d inode=%p domain=%d type=%d protocol=%d", + sd, + inode, + domain, + type, + protocol); + return sd; } diff --git a/src/kernel/sys/k_syscall.c b/src/kernel/sys/k_syscall.c index b72663223..dc1fe3327 100644 --- a/src/kernel/sys/k_syscall.c +++ b/src/kernel/sys/k_syscall.c @@ -1,15 +1,220 @@ #include #include +#include +#include +#include +#include +#include +#include #include #include +#include