summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-04-29 18:00:20 +0200
committerAnton Kling <anton@kling.gg>2024-04-29 18:00:20 +0200
commit7d2ab3a71f4bda9d8ee997764d98b29e13a902c5 (patch)
tree6dcdc7a674a8047a2dba3e95d3be91b4e3161bd5
parentd60fa1fc01e600c4a163bbe82fab3f1986cb1476 (diff)
Kernel/Socket: Move sockets back to being file descriptors
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/cpu/isr.s2
-rw-r--r--kernel/cpu/syscall.c91
-rw-r--r--kernel/drivers/keyboard.c2
-rw-r--r--kernel/fs/vfs.c2
-rw-r--r--kernel/includes/syscalls.h5
-rw-r--r--kernel/init/kernel.c2
-rw-r--r--kernel/lib/ringbuffer.c17
-rw-r--r--kernel/lib/ringbuffer.h3
-rw-r--r--kernel/lib/stack.c4
-rw-r--r--kernel/lib/stack.h1
-rw-r--r--kernel/network/tcp.c14
-rw-r--r--kernel/network/tcp.h2
-rw-r--r--kernel/sched/scheduler.c31
-rw-r--r--kernel/sched/scheduler.h3
-rw-r--r--kernel/socket.c384
-rw-r--r--kernel/socket.h19
-rw-r--r--userland/libc/Makefile4
-rw-r--r--userland/libc/include/math.h14
-rw-r--r--userland/libc/include/signal.h1
-rw-r--r--userland/libc/include/sys/socket.h1
-rw-r--r--userland/libc/include/syscall.h1
22 files changed, 353 insertions, 252 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 240f7df..149b1bc 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -1,6 +1,6 @@
CC="i686-sb-gcc"
AS="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 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 syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/fstat.o libc/string/copy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o syscalls/port.o syscalls/map_frames.o syscalls/virtual_to_physical.o syscalls/install_irq.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o queue.o syscalls/queue.o syscalls/munmap.o syscalls/open_process.o syscalls/lseek.o lib/ringbuffer.o lib/relist.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 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 syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/fstat.o libc/string/copy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o syscalls/port.o syscalls/map_frames.o syscalls/virtual_to_physical.o syscalls/install_irq.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o syscalls/munmap.o syscalls/open_process.o syscalls/lseek.o lib/ringbuffer.o lib/relist.o
CFLAGS = -std=c99 -O0 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Wextra -Wno-int-conversion -Wno-unused-parameter -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
LDFLAGS=
INCLUDE=-I./includes/ -I../include/ -I./libc/include/
diff --git a/kernel/cpu/isr.s b/kernel/cpu/isr.s
index 819b22b..9fca13c 100644
--- a/kernel/cpu/isr.s
+++ b/kernel/cpu/isr.s
@@ -32,7 +32,7 @@ ISR_NOERRCODE 9
ISR_NOERRCODE 10
ISR_NOERRCODE 11
ISR_NOERRCODE 12
-ISR_NOERRCODE 13
+ISR_ERRCODE 13
ISR_ERRCODE 14
ISR_NOERRCODE 15
ISR_NOERRCODE 16
diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c
index 3765a84..84faa16 100644
--- a/kernel/cpu/syscall.c
+++ b/kernel/cpu/syscall.c
@@ -140,49 +140,64 @@ int syscall_openpty(SYS_OPENPTY_PARAMS *args) {
args->winp);
}
-u32 syscall_tcp_connect(u32 ip, u16 port, int *error) {
- // TODO: Make sure error is a user address
- return tcp_connect_ipv4(ip, port, error);
-}
-
-int syscall_tcp_write(u32 socket, const u8 *buffer, u32 len, u64 *out) {
- // TODO: Make sure out is a user address
- return tcp_write(socket, buffer, len, out);
-}
-
-int syscall_tcp_read(u32 socket, u8 *buffer, u32 buffer_size, u64 *out) {
- // TODO: Make sure out is a user address
- return tcp_read(socket, buffer, buffer_size, out);
+int syscall_connect(int sockfd, const struct sockaddr *addr,
+ socklen_t addrlen) {
+ return connect(sockfd, addr, addrlen);
}
int (*syscall_functions[])() = {
- (void(*))syscall_open, (void(*))syscall_mread,
- (void(*))syscall_write, (void(*))syscall_pread,
- (void(*))syscall_pwrite, (void(*))syscall_fork,
- (void(*))syscall_exec, (void(*))syscall_getpid,
- (void(*))syscall_exit, (void(*))syscall_wait,
- (void(*))syscall_brk, (void(*))syscall_sbrk,
- (void(*))syscall_pipe, (void(*))syscall_dup2,
- (void(*))syscall_close, (void(*))syscall_openpty,
- (void(*))syscall_poll, (void(*))syscall_mmap,
- (void(*))syscall_accept, (void(*))syscall_bind,
- (void(*))syscall_socket, (void(*))syscall_shm_open,
- (void(*))syscall_ftruncate, (void(*))syscall_fstat,
- (void(*))syscall_msleep, (void(*))syscall_uptime,
- (void(*))syscall_mkdir, (void(*))syscall_recvfrom,
- (void(*))syscall_sendto, (void(*))syscall_kill,
- (void(*))syscall_sigaction, (void(*))syscall_chdir,
- (void(*))syscall_getcwd, (void(*))syscall_isatty,
- (void(*))syscall_randomfill, (void(*))syscall_outw,
- (void(*))syscall_inl, (void(*))syscall_outl,
- (void(*))syscall_map_frames, (void(*))syscall_virtual_to_physical,
- (void(*))syscall_install_irq, (void(*))syscall_tmp_handle_packet,
- (void(*))syscall_tcp_connect, (void(*))syscall_tcp_write,
- (void(*))syscall_tcp_read,
- (void(*))syscall_queue_create, (void(*))syscall_queue_add,
- (void(*))syscall_queue_wait, (void(*))syscall_munmap,
+ (void(*))syscall_open,
+ (void(*))syscall_mread,
+ (void(*))syscall_write,
+ (void(*))syscall_pread,
+ (void(*))syscall_pwrite,
+ (void(*))syscall_fork,
+ (void(*))syscall_exec,
+ (void(*))syscall_getpid,
+ (void(*))syscall_exit,
+ (void(*))syscall_wait,
+ (void(*))syscall_brk,
+ (void(*))syscall_sbrk,
+ (void(*))syscall_pipe,
+ (void(*))syscall_dup2,
+ (void(*))syscall_close,
+ (void(*))syscall_openpty,
+ (void(*))syscall_poll,
+ (void(*))syscall_mmap,
+ (void(*))syscall_accept,
+ (void(*))syscall_bind,
+ (void(*))syscall_socket,
+ (void(*))syscall_shm_open,
+ (void(*))syscall_ftruncate,
+ (void(*))syscall_fstat,
+ (void(*))syscall_msleep,
+ (void(*))syscall_uptime,
+ (void(*))syscall_mkdir,
+ (void(*))syscall_recvfrom,
+ (void(*))syscall_sendto,
+ (void(*))syscall_kill,
+ (void(*))syscall_sigaction,
+ (void(*))syscall_chdir,
+ (void(*))syscall_getcwd,
+ (void(*))syscall_isatty,
+ (void(*))syscall_randomfill,
+ (void(*))syscall_outw,
+ (void(*))syscall_inl,
+ (void(*))syscall_outl,
+ (void(*))syscall_map_frames,
+ (void(*))syscall_virtual_to_physical,
+ (void(*))syscall_install_irq,
+ (void(*))syscall_tmp_handle_packet,
+ (void(*))NULL,
+ (void(*))NULL,
+ (void(*))NULL,
+ (void(*))NULL,
+ (void(*))NULL,
+ (void(*))NULL,
+ (void(*))syscall_munmap,
(void(*))syscall_open_process,
(void(*))syscall_lseek,
+ (void(*))syscall_connect,
};
void int_syscall(reg_t *r);
diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c
index 770c8c5..a120788 100644
--- a/kernel/drivers/keyboard.c
+++ b/kernel/drivers/keyboard.c
@@ -5,9 +5,9 @@
#include <fs/devfs.h>
#include <fs/fifo.h>
#include <fs/vfs.h>
+#include <lib/ringbuffer.h>
#include <sched/scheduler.h>
#include <typedefs.h>
-#include <lib/ringbuffer.h>
#define PS2_REG_DATA 0x60
#define PS2_REG_STATUS 0x64
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c
index 9312c2a..cd3f854 100644
--- a/kernel/fs/vfs.c
+++ b/kernel/fs/vfs.c
@@ -340,7 +340,7 @@ int vfs_pmread(int fd, void *buf, u64 count, int blocking, u64 offset) {
return -EBADF;
}
int rc = raw_vfs_pread(vfs_fd, buf, count, offset);
- if (-EAGAIN == rc && count > 0) {
+ if ((-EAGAIN == rc || -EWOULDBLOCK == rc) && count > 0) {
if (!(vfs_fd->flags & O_NONBLOCK) && blocking) {
struct pollfd fds;
do {
diff --git a/kernel/includes/syscalls.h b/kernel/includes/syscalls.h
index 6945c21..2fabb2b 100644
--- a/kernel/includes/syscalls.h
+++ b/kernel/includes/syscalls.h
@@ -1,5 +1,4 @@
#include <fs/vfs.h>
-#include <queue.h>
#include <signal.h>
#include <socket.h>
#include <stddef.h>
@@ -13,10 +12,6 @@ u32 syscall_inl(u16 port);
void syscall_outl(u16 port, u32 l);
int syscall_open_process(int pid);
-int syscall_queue_create(u32 *id);
-int syscall_queue_add(u32 queue_id, struct event *ev, u32 size);
-int syscall_queue_wait(u32 queue_id);
-
int syscall_ipc_register_endpoint(u32 endpoint);
int syscall_ipc_read(u8 *buffer, u32 length, u32 *sender_pid);
int syscall_ipc_write(int ipc_id, u8 *buffer, u32 length);
diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c
index 2b96359..0a2243d 100644
--- a/kernel/init/kernel.c
+++ b/kernel/init/kernel.c
@@ -85,6 +85,8 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
install_keyboard();
klog("PS2 Keyboard driver installed", LOG_SUCCESS);
+global_socket_init();
+
vfs_mount("/dev", devfs_mount());
assert(ahci_init());
vfs_inode_t *ext2_mount_point = ext2_mount();
diff --git a/kernel/lib/ringbuffer.c b/kernel/lib/ringbuffer.c
index 66dd17e..9caf555 100644
--- a/kernel/lib/ringbuffer.c
+++ b/kernel/lib/ringbuffer.c
@@ -16,6 +16,23 @@ int ringbuffer_init(struct ringbuffer *rb, u32 buffer_size) {
return 1;
}
+u32 ringbuffer_used(const struct ringbuffer *rb) {
+ if (rb->write_ptr < rb->read_ptr) {
+ u32 c = rb->buffer_size - rb->read_ptr;
+ c += rb->write_ptr;
+ return c;
+ }
+ return rb->write_ptr - rb->read_ptr;
+}
+
+u32 ringbuffer_capacity(const struct ringbuffer *rb) {
+ return rb->buffer_size - 1;
+}
+
+u32 ringbuffer_unused(const struct ringbuffer *rb) {
+ return ringbuffer_capacity(rb) - ringbuffer_used(rb);
+}
+
u32 ringbuffer_write(struct ringbuffer *rb, const u8 *buffer, u32 len) {
const u32 orig_len = len;
for (; len > 0;) {
diff --git a/kernel/lib/ringbuffer.h b/kernel/lib/ringbuffer.h
index 3ebc507..d6e699a 100644
--- a/kernel/lib/ringbuffer.h
+++ b/kernel/lib/ringbuffer.h
@@ -14,6 +14,9 @@ u32 ringbuffer_write(struct ringbuffer *rb, const u8 *buffer, u32 len);
u32 ringbuffer_read(struct ringbuffer *rb, u8 *buffer, u32 len);
int ringbuffer_isempty(const struct ringbuffer *rb);
void ringbuffer_free(struct ringbuffer *rb);
+u32 ringbuffer_used(const struct ringbuffer *rb);
+u32 ringbuffer_capacity(const struct ringbuffer *rb);
+u32 ringbuffer_unused(const struct ringbuffer *rb);
#ifdef KERNEL_TEST
void ringbuffer_test(void);
#endif // KERNEL_TEST
diff --git a/kernel/lib/stack.c b/kernel/lib/stack.c
index 7283b35..7c44193 100644
--- a/kernel/lib/stack.c
+++ b/kernel/lib/stack.c
@@ -7,6 +7,10 @@ void stack_init(struct stack *s) {
s->head = NULL;
}
+int stack_isempty(const struct stack *s) {
+ return (NULL == s->head);
+}
+
// 1 = Success
// 0 = Failure
int stack_push(struct stack *s, void *data) {
diff --git a/kernel/lib/stack.h b/kernel/lib/stack.h
index f47fe66..09fff66 100644
--- a/kernel/lib/stack.h
+++ b/kernel/lib/stack.h
@@ -13,6 +13,7 @@ struct stack {
};
void stack_init(struct stack *s);
+int stack_isempty(const struct stack *s);
int stack_push(struct stack *s, void *data);
void *stack_pop(struct stack *s);
#endif
diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c
index 8740a63..39b8d7c 100644
--- a/kernel/network/tcp.c
+++ b/kernel/network/tcp.c
@@ -121,6 +121,10 @@ void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) {
send_ipv4_packet((ipv4_t){.d = con->outgoing_ip}, 6, send_buffer, send_len);
}
+void tcp_close_connection(struct TcpConnection *con) {
+ tcp_send_empty_payload(con, FIN | ACK);
+}
+
void tcp_send_ack(struct TcpConnection *con) {
tcp_send_empty_payload(con, ACK);
}
@@ -170,7 +174,6 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) {
u8 flags = header->flags;
u16 src_port = htons(n_src_port);
- (void)src_port;
u16 dst_port = htons(n_dst_port);
u32 seq_num = htonl(n_seq_num);
u32 ack_num = htonl(n_ack_num);
@@ -182,10 +185,12 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) {
assert(con);
con->ack = seq_num + 1;
tcp_send_empty_payload(con, SYN | ACK);
+ con->seq++;
return;
}
- struct TcpConnection *incoming_connection = tcp_find_connection(dst_port);
+ struct TcpConnection *incoming_connection =
+ tcp_find_connection(src_ip, src_port, dst_port);
if (!incoming_connection) {
kprintf("unable to find open port for incoming connection\n");
}
@@ -214,8 +219,8 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) {
u16 tcp_payload_length = payload_length - header->data_offset * sizeof(u32);
if (tcp_payload_length > 0) {
const u8 *tcp_payload = payload + header->data_offset * sizeof(u32);
- u32 len = ringbuffer_write(&incoming_connection->buffer, tcp_payload,
- tcp_payload_length);
+ u32 len = ringbuffer_write(&incoming_connection->incoming_buffer,
+ tcp_payload, tcp_payload_length);
assert(len == tcp_payload_length);
incoming_connection->ack += len;
tcp_send_ack(incoming_connection);
@@ -224,6 +229,7 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) {
incoming_connection->ack++;
tcp_send_empty_payload(incoming_connection, FIN | ACK);
+ incoming_connection->seq++;
incoming_connection->dead = 1; // FIXME: It should wait for a ACK
// of the FIN before the connection
diff --git a/kernel/network/tcp.h b/kernel/network/tcp.h
index 0c53535..1e292b3 100644
--- a/kernel/network/tcp.h
+++ b/kernel/network/tcp.h
@@ -5,4 +5,4 @@ void tcp_wait_reply(struct TcpConnection *con);
void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length);
void send_tcp_packet(struct TcpConnection *con, const u8 *payload,
u16 payload_length);
-void tcp_close_connection(struct INCOMING_TCP_CONNECTION *s);
+void tcp_close_connection(struct TcpConnection *con);
diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c
index 639dd05..9a241ac 100644
--- a/kernel/sched/scheduler.c
+++ b/kernel/sched/scheduler.c
@@ -7,7 +7,6 @@
#include <errno.h>
#include <fs/vfs.h>
#include <interrupts.h>
-#include <queue.h>
#include <signal.h>
// FIXME: Use the process_t struct instead or keep this contained in it.
@@ -160,11 +159,6 @@ process_t *create_process(process_t *p, u32 esp, u32 eip) {
list_init(&r->write_list);
list_init(&r->disconnect_list);
- list_init(&r->tcp_sockets);
- list_init(&r->tcp_listen);
-
- list_init(&r->event_queue);
-
if (esp) {
esp -= 4;
insert_eip_on_stack(r->cr3->physical_address, esp, eip);
@@ -209,9 +203,6 @@ void free_process(process_t *p) {
list_free(&p->read_list);
list_free(&p->write_list);
list_free(&p->disconnect_list);
- list_free(&p->tcp_sockets);
- list_free(&p->tcp_listen);
- list_free(&p->event_queue);
relist_free(&p->file_descriptors);
kfree(p->tcb);
@@ -428,28 +419,6 @@ int is_halted(process_t *process) {
}
}
- int queue_block = 1;
- int wait_empty = 1;
- for (int i = 0;; i++) {
- struct event_queue *q;
- if (!list_get(&process->event_queue, i, (void **)&q)) {
- break;
- }
- int is_empty;
- int rc = queue_should_block(q, &is_empty);
- if (is_empty) {
- wait_empty = 0;
- continue;
- }
- if (0 == rc) {
- queue_block = 0;
- }
- }
- if (!queue_block && !wait_empty) {
- kprintf("skip because queue_wait has data\n");
- return 0;
- }
-
int fd_empty;
if (isset_fdhalt(process, &fd_empty) && !fd_empty) {
return 1;
diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h
index feb6aa5..7a8bf0c 100644
--- a/kernel/sched/scheduler.h
+++ b/kernel/sched/scheduler.h
@@ -68,9 +68,6 @@ struct Process {
struct list write_list;
struct list disconnect_list;
- struct list tcp_sockets;
- struct list tcp_listen;
-
struct list event_queue;
struct stack restore_context_stack;
diff --git a/kernel/socket.c b/kernel/socket.c
index e0c3f35..fbc0648 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -9,6 +9,14 @@
#include <sched/scheduler.h>
#include <socket.h>
+struct list open_tcp_connections;
+struct list open_tcp_listen;
+
+void global_socket_init(void) {
+ list_init(&open_tcp_connections);
+ list_init(&open_tcp_listen);
+}
+
OPEN_UNIX_SOCKET *un_sockets[100] = {0};
void gen_ipv4(ipv4_t *ip, u8 i1, u8 i2, u8 i3, u8 i4) {
@@ -18,44 +26,29 @@ void gen_ipv4(ipv4_t *ip, u8 i1, u8 i2, u8 i3, u8 i4) {
ip->a[3] = i4;
}
-struct TcpConnection *tcp_find_connection(u16 port) {
- process_t *p = current_task;
- p = p->next;
- for (int i = 0; i < 100; i++, p = p->next) {
- if (!p) {
- p = ready_queue;
+struct TcpConnection *tcp_find_connection(ipv4_t src_ip, u16 src_port,
+ u16 dst_port) {
+ (void)src_ip;
+ for (int i = 0;; i++) {
+ struct TcpConnection *c;
+ if (!list_get(&open_tcp_connections, i, (void **)&c)) {
+ break;
}
- struct list *connections = &p->tcp_sockets;
- for (int i = 0;; i++) {
- struct TcpConnection *c;
- if (!list_get(connections, i, (void **)&c)) {
- break;
- }
- if (c->incoming_port == port) {
- return c;
- }
+ if (c->incoming_port == dst_port && c->outgoing_port == src_port) {
+ return c;
}
}
return NULL;
}
struct TcpListen *tcp_find_listen(u16 port) {
- process_t *p = current_task;
- process_t *s = p;
- p = p->next;
- for (; p != s; p = p->next) {
- if (!p) {
- p = ready_queue;
+ for (int i = 0;; i++) {
+ struct TcpListen *c;
+ if (!list_get(&open_tcp_listen, i, (void **)&c)) {
+ break;
}
- struct list *listen_list = &p->tcp_listen;
- for (int i = 0;; i++) {
- struct TcpListen *c;
- if (!list_get(listen_list, i, (void **)&c)) {
- break;
- }
- if (c->port == port) {
- return c;
- }
+ if (c->port == port) {
+ return c;
}
}
return NULL;
@@ -71,134 +64,125 @@ struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port,
struct TcpConnection *con = kcalloc(1, sizeof(struct TcpConnection));
int connection_id;
- struct list *connections = &current_task->tcp_sockets;
- list_add(connections, con, &connection_id);
+ list_add(&open_tcp_connections, con, &connection_id);
con->outgoing_ip = src_ip;
con->outgoing_port = src_port;
- // con->incoming_ip = dst_ip;
- con->incoming_port = dst_port; // FIXME: Should be different for each
- // connection
+ con->incoming_ip = dst_ip;
+ con->incoming_port = dst_port;
- ringbuffer_init(&con->buffer, 8192);
- stack_push(&listen->incoming_connections, (void *)connection_id);
+ ringbuffer_init(&con->incoming_buffer, 8192);
+ ringbuffer_init(&con->outgoing_buffer, 8192);
+ stack_push(&listen->incoming_connections, con);
return con;
}
-u32 tcp_listen_ipv4(u32 ip, u16 port, int *error) {
- *error = 0;
+int tcp_sync_buffer(vfs_fd_t *fd) {
+ struct TcpConnection *con = fd->inode->internal_object;
+ assert(con);
+ if (con->dead) {
+ return -EBADF; // TODO: Check if this is correct.
+ }
+
+ struct ringbuffer *rb = &con->outgoing_buffer;
+ u32 send_buffer_len = ringbuffer_used(rb);
+ if (0 == send_buffer_len) {
+ return 0;
+ }
+ char *send_buffer = kmalloc(send_buffer_len);
+ assert(ringbuffer_read(rb, send_buffer, send_buffer_len) == send_buffer_len);
+ send_tcp_packet(con, send_buffer, send_buffer_len);
+ kfree(send_buffer);
+ return 0;
+}
+
+void tcp_close(vfs_fd_t *fd) {
+ struct TcpConnection *con = fd->inode->internal_object;
- struct TcpListen *listener = kcalloc(1, sizeof(struct TcpListen));
- listener->ip = ip;
- listener->port = port;
- stack_init(&listener->incoming_connections);
+ tcp_sync_buffer(fd);
- struct list *listen_list = &current_task->tcp_listen;
- int index;
- list_add(listen_list, listener, &index);
- return index;
+ tcp_close_connection(con);
}
-struct TcpConnection *tcp_get_connection(u32 socket, process_t *p) {
- if (!p) {
- p = current_task;
+int tcp_read(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
+ struct TcpConnection *con = fd->inode->internal_object;
+ assert(con);
+ if (con->dead) {
+ return -EBADF; // TODO: Check if this is correct.
}
- const struct list *connections = &p->tcp_sockets;
- struct TcpConnection *con;
- if (!list_get(connections, socket, (void **)&con)) {
- return NULL;
+
+ u32 rc = ringbuffer_read(&con->incoming_buffer, buffer, len);
+ if (0 == rc && len > 0) {
+ return -EWOULDBLOCK;
}
- return con;
+ return rc;
}
-u32 tcp_accept(u32 listen_socket, int *error) {
- *error = 0;
- struct list *listen_list = &current_task->tcp_listen;
- struct TcpListen *l;
- if (!list_get(listen_list, listen_socket, (void **)&l)) {
- *error = 1;
- return 0;
+int tcp_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
+ (void)offset;
+ struct TcpConnection *con = fd->inode->internal_object;
+ assert(con);
+ if (con->dead) {
+ return -EBADF; // TODO: Check if this is correct.
}
- for (;;) {
- // TODO: halt the process
- if (NULL != l->incoming_connections.head) {
- void *out = stack_pop(&l->incoming_connections);
- return (u32)out; // TODO: Should a pointer store a u32?
- }
+
+ struct ringbuffer *rb = &con->outgoing_buffer;
+ if (ringbuffer_unused(rb) < len) {
+ tcp_sync_buffer(fd);
+ send_tcp_packet(con, buffer, len);
+ len = 0;
+ } else {
+ assert(ringbuffer_write(rb, buffer, len) == len);
}
- ASSERT_NOT_REACHED;
+ return len;
+}
+
+int tcp_has_data(vfs_inode_t *inode) {
+ struct TcpConnection *con = inode->internal_object;
+ return !(ringbuffer_isempty(&con->incoming_buffer));
}
-u32 tcp_connect_ipv4(u32 ip, u16 port, int *error) {
- struct list *connections = &current_task->tcp_sockets;
- *error = 0;
+int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
+ vfs_fd_t *fd = get_vfs_fd(sockfd, NULL);
+ assert(fd);
+
+ if (fd->inode->internal_object) {
+ return -EISCONN;
+ }
+ assert(AF_INET == addr->sa_family);
+ const struct sockaddr_in *in_addr = (const struct sockaddr_in *)addr;
struct TcpConnection *con = kcalloc(1, sizeof(struct TcpConnection));
- int index;
- list_add(connections, con, &index);
+ if (!con) {
+ return -ENOMEM;
+ }
con->incoming_port = 1337; // TODO
- con->outgoing_ip = ip;
- con->outgoing_port = port;
+ con->outgoing_ip = in_addr->sin_addr.s_addr;
+ con->outgoing_port = in_addr->sin_port;
- ringbuffer_init(&con->buffer, 8192);
+ ringbuffer_init(&con->incoming_buffer, 8192);
+ ringbuffer_init(&con->outgoing_buffer, 8192);
+ list_add(&open_tcp_connections, con, NULL);
tcp_send_syn(con);
for (;;) {
tcp_wait_reply(con);
if (con->dead) { // Port is probably closed
- *error = 1;
- return 0;
+ return -ECONNREFUSED;
}
if (0 != con->handshake_state) {
break;
}
}
- return index;
-}
-
-int tcp_write(u32 socket, const u8 *buffer, u64 len, u64 *out) {
- if (out) {
- *out = 0;
- }
- struct TcpConnection *con = tcp_get_connection(socket, NULL);
- if (!con) {
- return 0;
- }
- if (con->dead) {
- return 0;
- }
-
- send_tcp_packet(con, buffer, len);
- if (out) {
- *out = len;
- }
- return 1;
-}
-
-int tcp_read(u32 socket, u8 *buffer, u64 buffer_size, u64 *out) {
- if (out) {
- *out = 0;
- }
- struct TcpConnection *con = tcp_get_connection(socket, NULL);
- if (!con) {
- return 0;
- }
- if (con->dead) {
- return 0;
- }
-
- u32 len = ringbuffer_read(&con->buffer, buffer, buffer_size);
- if (out) {
- *out = len;
- }
- return 1;
-}
-
-void tcp_close(u32 socket) {
- assert(NULL);
+ fd->inode->_has_data = tcp_has_data;
+ fd->inode->write = tcp_write;
+ fd->inode->read = tcp_read;
+ fd->inode->close = tcp_close;
+ fd->inode->internal_object = con;
+ return 0;
}
int uds_open(const char *path) {
@@ -238,6 +222,12 @@ int uds_open(const char *path) {
return fd[0];
}
+int tcp_listen_has_data(vfs_inode_t *inode) {
+ const SOCKET *s = (SOCKET *)inode->internal_object;
+ const struct TcpListen *tcp_listen = s->object;
+ return !stack_isempty(&tcp_listen->incoming_connections);
+}
+
int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
(void)address;
(void)address_len;
@@ -245,25 +235,50 @@ int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
assert(fd_ptr);
vfs_inode_t *inode = fd_ptr->inode;
SOCKET *s = (SOCKET *)inode->internal_object;
+ if (AF_UNIX == s->domain) {
+ for (; NULL == s->incoming_fd;) {
+ // Wait until we have gotten a connection
+ struct pollfd fds[1];
+ fds[0].fd = socket;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ poll(fds, 1, 0);
+ }
- for (; NULL == s->incoming_fd;) {
- // Wait until we have gotten a connection
- struct pollfd fds[1];
- fds[0].fd = socket;
- fds[0].events = POLLIN;
- fds[0].revents = 0;
- poll(fds, 1, 0);
+ int index;
+ assert(relist_add(&current_task->file_descriptors, s->incoming_fd, &index));
+ assert(1 <= s->incoming_fd->reference_count);
+ s->incoming_fd = NULL;
+ return index;
}
-
- int index;
- assert(relist_add(&current_task->file_descriptors, s->incoming_fd, &index));
- assert(1 <= s->incoming_fd->reference_count);
- s->incoming_fd = NULL;
- // for (char c; 0 < vfs_pread(s->fifo_fd, &c, 1, 0);)
- // ;
- // s->ptr_fifo_fd->inode->has_data = 0;
-
- return index;
+ if (AF_INET == s->domain) {
+ struct TcpListen *tcp_listen = s->object;
+ assert(tcp_listen);
+ if (stack_isempty(&tcp_listen->incoming_connections)) {
+ if (fd_ptr->flags & O_NONBLOCK) {
+ return -EWOULDBLOCK;
+ }
+ struct pollfd fds[1];
+ fds[0].fd = socket;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ poll(fds, 1, 0);
+ }
+ struct TcpConnection *connection =
+ stack_pop(&tcp_listen->incoming_connections);
+ assert(connection);
+ vfs_inode_t *inode = vfs_create_inode(
+ 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, tcp_has_data,
+ always_can_write, 1, connection, 0 /*file_size*/, NULL /*open*/,
+ NULL /*create_file*/, tcp_read, tcp_write,
+ tcp_close /*close*/, NULL /*create_directory*/,
+ NULL /*get_vm_object*/, NULL /*truncate*/, NULL /*stat*/,
+ NULL /*send_signal*/);
+ assert(inode);
+ return vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, NULL);
+ }
+ ASSERT_NOT_REACHED;
+ return 0;
}
int bind_has_data(vfs_inode_t *inode) {
@@ -286,6 +301,9 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
if (!inode) {
return -EBADF;
}
+ if (FS_TYPE_UNIX_SOCKET != inode->type) {
+ return -ENOTSOCK;
+ }
SOCKET *s = (SOCKET *)inode->internal_object;
if (AF_UNIX == s->domain) {
struct sockaddr_un *un = (struct sockaddr_un *)addr;
@@ -310,8 +328,25 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
devfs_add_file(us->path, NULL, NULL, NULL, NULL, bind_can_write,
FS_TYPE_UNIX_SOCKET);
return 0;
+ } else if (AF_INET == s->domain) {
+ struct sockaddr_in *in = (struct sockaddr_in *)addr;
+
+ struct TcpListen *tcp_listen = kmalloc(sizeof(struct TcpListen));
+ if (!tcp_listen) {
+ return -ENOMEM;
+ }
+ tcp_listen->ip = in->sin_addr.s_addr;
+ tcp_listen->port = ntohs(in->sin_port);
+ stack_init(&tcp_listen->incoming_connections);
+
+ s->object = tcp_listen;
+
+ inode->_has_data = tcp_listen_has_data;
+
+ list_add(&open_tcp_listen, tcp_listen, NULL);
+ return 0;
}
- return 0;
+ ASSERT_NOT_REACHED;
}
int socket_has_data(vfs_inode_t *inode) {
@@ -342,29 +377,68 @@ void socket_close(vfs_fd_t *fd) {
}
int socket(int domain, int type, int protocol) {
+ int rc = 0;
+ vfs_inode_t *inode = NULL;
+ SOCKET *new_socket = NULL;
if (!(AF_UNIX == domain || AF_INET == domain)) {
- return -EINVAL;
+ rc = -EINVAL;
+ goto socket_error;
}
- SOCKET *new_socket = kmalloc(sizeof(SOCKET));
- vfs_inode_t *inode = vfs_create_inode(
- 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, bind_has_data, socket_can_write,
- 1 /*is_open*/, new_socket /*internal_object*/, 0 /*file_size*/,
- NULL /*open*/, NULL /*create_file*/, socket_read, socket_write,
- socket_close, NULL /*create_directory*/, NULL /*get_vm_object*/,
- NULL /*truncate*/, NULL /*stat*/, NULL /*send_signal*/);
-
- vfs_fd_t *fd;
- int n = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, 0 /*is_tty*/, inode, &fd);
-
+ new_socket = kmalloc(sizeof(SOCKET));
+ if (!new_socket) {
+ rc = -ENOMEM;
+ goto socket_error;
+ }
new_socket->domain = domain;
new_socket->type = type;
new_socket->protocol = protocol;
new_socket->path = NULL;
new_socket->incoming_fd = NULL;
+ if (AF_UNIX == domain) {
+ vfs_inode_t *inode = vfs_create_inode(
+ 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, bind_has_data, socket_can_write,
+ 1 /*is_open*/, new_socket /*internal_object*/, 0 /*file_size*/,
+ NULL /*open*/, NULL /*create_file*/, socket_read, socket_write,
+ socket_close, NULL /*create_directory*/, NULL /*get_vm_object*/,
+ NULL /*truncate*/, NULL /*stat*/, NULL /*send_signal*/);
+ if (!inode) {
+ rc = -ENOMEM;
+ goto socket_error;
+ }
+
+ vfs_fd_t *fd;
+ int n = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, 0 /*is_tty*/, inode, &fd);
+ if (n < 0) {
+ rc = n;
+ goto socket_error;
+ }
- new_socket->fifo_file = create_fifo_object();
+ new_socket->fifo_file = create_fifo_object();
- new_socket->ptr_socket_fd = fd;
- return n;
+ new_socket->ptr_socket_fd = fd;
+ return n;
+ }
+ if (AF_INET == domain) {
+ vfs_inode_t *inode = vfs_create_inode(
+ 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, NULL, always_can_write, 1,
+ new_socket, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/, NULL,
+ NULL, NULL /*close*/, NULL /*create_directory*/, NULL /*get_vm_object*/,
+ NULL /*truncate*/, NULL /*stat*/, NULL /*send_signal*/);
+ if (!inode) {
+ rc = -ENOMEM;
+ goto socket_error;
+ }
+ int n = vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, NULL);
+ if (n < 0) {
+ rc = n;
+ goto socket_error;
+ }
+ return n;
+ }
+ ASSERT_NOT_REACHED;
+socket_error:
+ kfree(inode);
+ kfree(new_socket);
+ return rc;
}
diff --git a/kernel/socket.h b/kernel/socket.h
index ad505b8..b542c87 100644
--- a/kernel/socket.h
+++ b/kernel/socket.h
@@ -20,13 +20,6 @@
#define MSG_WAITALL 1
void gen_ipv4(ipv4_t *ip, u8 i1, u8 i2, u8 i3, u8 i4);
-u32 tcp_connect_ipv4(u32 ip, u16 port, int *error);
-
-u32 tcp_listen_ipv4(u32 ip, u16 port, int *error);
-u32 tcp_accept(u32 listen_socket, int *error);
-
-int tcp_write(u32 socket, const u8 *buffer, u64 len, u64 *out);
-int tcp_read(u32 socket, u8 *buffer, u64 buffer_size, u64 *out);
struct TcpListen {
u32 ip;
@@ -37,11 +30,13 @@ struct TcpListen {
struct TcpConnection {
int dead;
u16 incoming_port;
+ u32 incoming_ip;
u32 outgoing_ip;
u16 outgoing_port;
int unhandled_packet;
- struct ringbuffer buffer;
+ struct ringbuffer incoming_buffer;
+ struct ringbuffer outgoing_buffer;
u32 seq;
u32 ack;
@@ -53,7 +48,8 @@ struct TcpConnection *tcp_get_connection(u32 socket, process_t *p);
struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port,
u32 dst_ip, u16 dst_port);
-struct TcpConnection *tcp_find_connection(u16 port);
+struct TcpConnection *tcp_find_connection(ipv4_t src_ip, u16 src_port,
+ u16 dst_port);
typedef struct {
vfs_fd_t *ptr_socket_fd;
@@ -67,6 +63,8 @@ typedef struct {
// UNIX socket
char *path;
vfs_fd_t *incoming_fd;
+
+ void *object;
} SOCKET;
typedef struct {
@@ -115,4 +113,7 @@ struct INCOMING_TCP_CONNECTION *
handle_incoming_tcp_connection(u8 ip[4], u16 n_port, u16 dst_port);
struct INCOMING_TCP_CONNECTION *get_incoming_tcp_connection(u8 ip[4],
u16 n_port);
+int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+void global_socket_init(void);
+u16 tcp_get_free_port(void);
#endif
diff --git a/userland/libc/Makefile b/userland/libc/Makefile
index 94cf28f..af65a56 100644
--- a/userland/libc/Makefile
+++ b/userland/libc/Makefile
@@ -1,8 +1,8 @@
CC="i686-sb-gcc"
AR="i686-sb-ar"
AS="i686-sb-as"
-CFLAGS = -ggdb -ffreestanding -O2 -Wall -Wextra -pedantic -Werror -Wimplicit-fallthrough -I./include/ -static -I../../include/ -Wno-int-conversion -Wno-unused-parameter
-OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o sys/mman/munmap.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 signal/kill.o signal/sigaction.o unistd/chdir.o unistd/getcwd.o stdio/getdelim.o stdio/getline.o unistd/isatty.o sys/socket/listen.o stdlib/realpath.o systemcall.o sys/random/randomfill.o fcntl/open.o unistd/write.o unistd/pwrite.o fcntl/open_process.o tb/sb.o tb/sv.o string/memchr.o stdlib/atol.o stdlib/atoll.o stdlib/strtoll.o sys/stat/fstat.o unistd/lseek.o ctype/isupper.o ctype/islower.o ctype/isblank.o ctype/isgraph.o ctype/iscntrl.o
+CFLAGS = -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -Werror -Wimplicit-fallthrough -I./include/ -static -I../../include/ -Wno-int-conversion -Wno-unused-parameter
+OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o sys/mman/munmap.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 signal/kill.o signal/sigaction.o unistd/chdir.o unistd/getcwd.o stdio/getdelim.o stdio/getline.o unistd/isatty.o sys/socket/listen.o stdlib/realpath.o systemcall.o sys/random/randomfill.o fcntl/open.o unistd/write.o unistd/pwrite.o fcntl/open_process.o tb/sb.o tb/sv.o string/memchr.o stdlib/atol.o stdlib/atoll.o stdlib/strtoll.o sys/stat/fstat.o unistd/lseek.o ctype/isupper.o ctype/islower.o ctype/isblank.o ctype/isgraph.o ctype/iscntrl.o math/ldexp.o sys/socket/connect.o
all: libc.a
%.o: %.c
diff --git a/userland/libc/include/math.h b/userland/libc/include/math.h
index 9d4f4b4..d85b3a0 100644
--- a/userland/libc/include/math.h
+++ b/userland/libc/include/math.h
@@ -1,2 +1,16 @@
#define max(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define min(_a, _b) ((_a) < (_b) ? (_a) : (_b))
+
+#if 100*__GNUC__+__GNUC_MINOR__ >= 303
+#define NAN __builtin_nanf("")
+#define INFINITY __builtin_inff()
+#else
+#define NAN (0.0f/0.0f)
+#define INFINITY 1e40f
+#endif
+
+#define HUGE_VALF INFINITY
+#define HUGE_VAL ((double)INFINITY)
+#define HUGE_VALL ((long double)INFINITY)
+
+double ldexp(double x, int exp);
diff --git a/userland/libc/include/signal.h b/userland/libc/include/signal.h
index a241015..42702b2 100644
--- a/userland/libc/include/signal.h
+++ b/userland/libc/include/signal.h
@@ -13,6 +13,7 @@
#define SIGKILL 9
#define SIGFPE 10
#define SIGTERM 15
+#define SIG_DFL 16
typedef int pid_t;
typedef int sigset_t;
diff --git a/userland/libc/include/sys/socket.h b/userland/libc/include/sys/socket.h
index 7a2cc23..fb874a1 100644
--- a/userland/libc/include/sys/socket.h
+++ b/userland/libc/include/sys/socket.h
@@ -8,3 +8,4 @@ size_t recvfrom(int socket, void *buffer, size_t length, int flags,
size_t sendto(int socket, const void *message, size_t length, int flags,
const struct sockaddr *dest_addr, socklen_t dest_len);
int listen(int socket, int backlog);
+int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
diff --git a/userland/libc/include/syscall.h b/userland/libc/include/syscall.h
index 201ff3d..f318955 100644
--- a/userland/libc/include/syscall.h
+++ b/userland/libc/include/syscall.h
@@ -59,6 +59,7 @@
#define SYS_MUNMAP 48
#define SYS_OPEN_PROCESS 49
#define SYS_LSEEK 50
+#define SYS_CONNECT 51
int syscall(uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx,
uint32_t esi, uint32_t edi);