summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-06-09 22:05:53 +0200
committerAnton Kling <anton@kling.gg>2024-06-09 22:05:53 +0200
commit15003d1b0abccc8bcef84386c4a6da176e41f883 (patch)
treed4f8c4f1602ee9e6c4332f3b0585d0e284d0f695
parentddd796325c9c703f007f046ed9f6fd9eb0ba6383 (diff)
Add UDP
-rw-r--r--include/dirent.h2
-rw-r--r--kernel/arch/i386/mmu.c8
-rw-r--r--kernel/cpu/idt.h4
-rw-r--r--kernel/drivers/rtl8139.c6
-rw-r--r--kernel/fs/ext2.c13
-rw-r--r--kernel/fs/shm.c2
-rw-r--r--kernel/fs/tmpfs.c4
-rw-r--r--kernel/fs/vfs.c5
-rw-r--r--kernel/fs/vfs.h6
-rw-r--r--kernel/kmalloc.c17
-rw-r--r--kernel/lib/buffered_write.c1
-rw-r--r--kernel/lib/relist.c1
-rw-r--r--kernel/lib/ringbuffer.c6
-rw-r--r--kernel/libc/string/copy.c1
-rw-r--r--kernel/network/ethernet.c1
-rw-r--r--kernel/network/tcp.c4
-rw-r--r--kernel/network/udp.c43
-rw-r--r--kernel/socket.c141
-rw-r--r--kernel/socket.h16
-rw-r--r--kernel/syscalls/open_process.c2
20 files changed, 245 insertions, 38 deletions
diff --git a/include/dirent.h b/include/dirent.h
index fd2eace..53b3f70 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -1,11 +1,11 @@
#ifndef DIRENT_H
#define DIRENT_H
-#include <fcntl.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include <sys/types.h>
#ifndef KERNEL
+#include <fcntl.h>
#include <unistd.h>
#endif
diff --git a/kernel/arch/i386/mmu.c b/kernel/arch/i386/mmu.c
index cfcb63b..28f6fd2 100644
--- a/kernel/arch/i386/mmu.c
+++ b/kernel/arch/i386/mmu.c
@@ -157,9 +157,9 @@ int get_free_frame(u32 *frame) {
int write_to_frame(u32 frame_address, u8 on) {
u32 frame = frame_address / 0x1000;
- if (INDEX_FROM_BIT(frame) >= num_array_frames) {
- return 0;
- }
+ if (INDEX_FROM_BIT(frame) >= num_array_frames) {
+ return 0;
+ }
if (on) {
int frame_is_used = (0 != (tmp_small_frames[INDEX_FROM_BIT(frame)] &
((u32)0x1 << OFFSET_FROM_BIT(frame))));
@@ -545,7 +545,7 @@ void *physical_to_virtual(void *address) {
}
void *virtual_to_physical(void *address, PageDirectory *directory) {
- if (0 == directory) {
+ if (!directory) {
directory = get_active_pagedirectory();
}
Page *p = get_page((void *)address, directory, PAGE_NO_ALLOCATE, 0);
diff --git a/kernel/cpu/idt.h b/kernel/cpu/idt.h
index 06e63ba..9a47ec0 100644
--- a/kernel/cpu/idt.h
+++ b/kernel/cpu/idt.h
@@ -1,5 +1,3 @@
-typedef struct kernel_registers kernel_registers_t;
-typedef struct registers registers_t;
#ifndef IDT_H
#define IDT_H
#include <cpu/gdt.h>
@@ -7,6 +5,8 @@ typedef struct registers registers_t;
#include <log.h>
#include <stdio.h>
#include <typedefs.h>
+typedef struct kernel_registers kernel_registers_t;
+typedef struct registers registers_t;
/*
* the type_attribute in the IDT_Entry struct
diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c
index 78e6570..c0aa0b2 100644
--- a/kernel/drivers/rtl8139.c
+++ b/kernel/drivers/rtl8139.c
@@ -194,11 +194,9 @@ void rtl8139_init(void) {
outl(base_address + 0x44,
0xf); // 0xf is AB+AM+APM+AAP
- install_handler((interrupt_handler)rtl8139_handler, INT_32_INTERRUPT_GATE(0x3),
- 0x20 + interrupt_line);
+ install_handler((interrupt_handler)rtl8139_handler,
+ INT_32_INTERRUPT_GATE(0x3), 0x20 + interrupt_line);
- // ksbrk() seems to have the magical ability of disabling interrupts?
- // I have no fucking clue why that happens and it was a pain to debug.
for (int i = 0; i < 4; i++) {
send_buffers[i] = ksbrk(0x1000);
}
diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c
index 61c16eb..18ce8c7 100644
--- a/kernel/fs/ext2.c
+++ b/kernel/fs/ext2.c
@@ -612,12 +612,11 @@ vfs_inode_t *ext2_open(const char *path) {
break;
}
- return vfs_create_inode(inode_num, type, NULL, NULL,
- 1 /*is_open*/, NULL /*internal_object*/, file_size,
- ext2_open, ext2_create_file, ext2_read, ext2_write,
- ext2_close, ext2_create_directory,
- NULL /*get_vm_object*/, ext2_truncate /*truncate*/,
- ext2_stat, NULL /*send_signal*/);
+ return vfs_create_inode(
+ inode_num, type, NULL, NULL, 1 /*is_open*/, NULL /*internal_object*/,
+ file_size, ext2_open, ext2_create_file, ext2_read, ext2_write, ext2_close,
+ ext2_create_directory, NULL /*get_vm_object*/, ext2_truncate /*truncate*/,
+ ext2_stat, NULL /*send_signal*/, NULL /*connect*/);
}
u64 end_of_last_entry_position(int dir_inode, u64 *entry_offset,
@@ -829,7 +828,7 @@ vfs_inode_t *ext2_mount(void) {
0 /*is_open*/, NULL /*internal_object*/, 0 /*file_size*/, ext2_open,
ext2_create_file, ext2_read, ext2_write, ext2_close,
ext2_create_directory, NULL /*get_vm_object*/, ext2_truncate /*truncate*/,
- ext2_stat, NULL /*send_signal*/);
+ ext2_stat, NULL /*send_signal*/, NULL /*connect*/);
}
void parse_superblock(void) {
diff --git a/kernel/fs/shm.c b/kernel/fs/shm.c
index caf356c..ec7286f 100644
--- a/kernel/fs/shm.c
+++ b/kernel/fs/shm.c
@@ -90,7 +90,7 @@ int shm_open(const char *name, int oflag, mode_t mode) {
0 /*inode_num*/, 0 /*type*/, NULL, NULL, 1 /*is_open*/,
internal_object, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/,
shm_read, shm_write, NULL /*close*/, NULL /*create_directory*/,
- shm_get_vm_object, shm_ftruncate, NULL /*stat*/, NULL /*send_signal*/);
+ shm_get_vm_object, shm_ftruncate, NULL /*stat*/, NULL /*send_signal*/, NULL /*connect*/);
vfs_fd_t *fd_ptr;
int fd = vfs_create_fd(oflag, mode, 0 /*is_tty*/, inode, &fd_ptr);
diff --git a/kernel/fs/tmpfs.c b/kernel/fs/tmpfs.c
index eb6ae34..cd48b93 100644
--- a/kernel/fs/tmpfs.c
+++ b/kernel/fs/tmpfs.c
@@ -52,7 +52,7 @@ void dual_pipe(int fd[2]) {
internal_object, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/,
tmp_read, tmp_write, tmp_close, NULL /*create_directory*/,
NULL /*get_vm_object*/, NULL /*truncate*/, NULL /*stat*/,
- NULL /*send_signal*/);
+ NULL /*send_signal*/, NULL /*connect*/);
assert(inode);
fd[i] =
@@ -85,7 +85,7 @@ void pipe(int fd[2]) {
internal_object, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/,
tmp_read, tmp_write, tmp_close, NULL /*create_directory*/,
NULL /*get_vm_object*/, NULL /*truncate*/, NULL /*stat*/,
- NULL /*send_signal*/);
+ NULL /*send_signal*/, NULL /*connect*/);
assert(inode);
fd[i] = vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, &fd_ptrs[i]);
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c
index cd3f854..59149f5 100644
--- a/kernel/fs/vfs.c
+++ b/kernel/fs/vfs.c
@@ -36,7 +36,9 @@ vfs_inode_t *vfs_create_inode(
vfs_vm_object_t *(*get_vm_object)(u64 length, u64 offset, vfs_fd_t *fd),
int (*truncate)(vfs_fd_t *fd, size_t length),
int (*stat)(vfs_fd_t *fd, struct stat *buf),
- int (*send_signal)(vfs_fd_t *fd, int signal)) {
+ int (*send_signal)(vfs_fd_t *fd, int signal),
+ int (*connect)(vfs_fd_t *fd, const struct sockaddr *addr,
+ socklen_t addrlen)) {
vfs_inode_t *r = kmalloc(sizeof(inode_t));
r->inode_num = inode_num;
r->type = type;
@@ -56,6 +58,7 @@ vfs_inode_t *vfs_create_inode(
r->stat = stat;
r->send_signal = send_signal;
r->ref = 0;
+ r->connect = connect;
return r;
}
diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h
index 83f1375..bce3925 100644
--- a/kernel/fs/vfs.h
+++ b/kernel/fs/vfs.h
@@ -9,6 +9,7 @@ typedef struct vfs_mounts vfs_mounts_t;
#include <sched/scheduler.h>
#include <socket.h>
#include <stddef.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <typedefs.h>
@@ -70,6 +71,7 @@ struct vfs_inode {
int (*truncate)(vfs_fd_t *fd, size_t length);
int (*stat)(vfs_fd_t *fd, struct stat *buf);
int (*send_signal)(vfs_fd_t *fd, int signal);
+ int (*connect)(vfs_fd_t *fd, const struct sockaddr *addr, socklen_t addrlen);
};
int vfs_close(int fd);
@@ -103,5 +105,7 @@ vfs_inode_t *vfs_create_inode(
vfs_vm_object_t *(*get_vm_object)(u64 length, u64 offset, vfs_fd_t *fd),
int (*truncate)(vfs_fd_t *fd, size_t length),
int (*stat)(vfs_fd_t *fd, struct stat *buf),
- int (*send_signal)(vfs_fd_t *fd, int signal));
+ int (*send_signal)(vfs_fd_t *fd, int signal),
+ int (*connect)(vfs_fd_t *fd, const struct sockaddr *addr,
+ socklen_t addrlen));
#endif
diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c
index 08b4821..a652962 100644
--- a/kernel/kmalloc.c
+++ b/kernel/kmalloc.c
@@ -246,14 +246,23 @@ size_t get_mem_size(void *ptr) {
}
void *krealloc(void *ptr, size_t size) {
+ if (!ptr) {
+ return kmalloc(size);
+ }
+ size_t l = get_mem_size(ptr);
+ if (l == size) {
+ return ptr;
+ }
+ if (l > size) {
+ MallocHeader *header = (MallocHeader *)((u8 *)ptr - sizeof(MallocHeader));
+ header->size = size;
+ return ptr;
+ }
+
void *rc = kmalloc(size);
if (!rc) {
return NULL;
}
- if (!ptr) {
- return rc;
- }
- size_t l = get_mem_size(ptr);
size_t to_copy = min(l, size);
memcpy(rc, ptr, to_copy);
kfree(ptr);
diff --git a/kernel/lib/buffered_write.c b/kernel/lib/buffered_write.c
index b6b78f9..8642c89 100644
--- a/kernel/lib/buffered_write.c
+++ b/kernel/lib/buffered_write.c
@@ -1,5 +1,6 @@
#include <kmalloc.h>
#include <lib/buffered_write.h>
+#include <string.h>
int buffered_init(struct buffered *ctx, u16 size) {
ctx->data = kmalloc(size);
diff --git a/kernel/lib/relist.c b/kernel/lib/relist.c
index a2f9ce5..01af884 100644
--- a/kernel/lib/relist.c
+++ b/kernel/lib/relist.c
@@ -2,6 +2,7 @@
#include <kmalloc.h>
#include <lib/relist.h>
#include <math.h>
+#include <string.h>
void relist_init(struct relist *list) {
list->bitmap_capacity = 1;
diff --git a/kernel/lib/ringbuffer.c b/kernel/lib/ringbuffer.c
index 9caf555..643e6b9 100644
--- a/kernel/lib/ringbuffer.c
+++ b/kernel/lib/ringbuffer.c
@@ -74,9 +74,11 @@ u32 ringbuffer_read(struct ringbuffer *rb, u8 *buffer, u32 len) {
}
read_len = min(len, read_len);
- memcpy(buffer, rb->buffer + rb->read_ptr, read_len);
+ if (buffer) {
+ memcpy(buffer, rb->buffer + rb->read_ptr, read_len);
+ buffer += read_len;
+ }
len -= read_len;
- buffer += read_len;
rb->read_ptr = (rb->read_ptr + read_len) % rb->buffer_size;
}
return orig_len - len;
diff --git a/kernel/libc/string/copy.c b/kernel/libc/string/copy.c
index 4acbbf4..3ab5618 100644
--- a/kernel/libc/string/copy.c
+++ b/kernel/libc/string/copy.c
@@ -2,6 +2,7 @@
#include <kmalloc.h>
#include <stddef.h>
#include <string.h>
+#include <mmu.h>
char *copy_and_allocate_string(const char *s) {
size_t l = strlen(s) + 1;
diff --git a/kernel/network/ethernet.c b/kernel/network/ethernet.c
index 9fa5ef8..cf2e047 100644
--- a/kernel/network/ethernet.c
+++ b/kernel/network/ethernet.c
@@ -1,6 +1,7 @@
#include <assert.h>
#include <drivers/rtl8139.h>
#include <kmalloc.h>
+#include <string.h>
#include <network/arp.h>
#include <network/bytes.h>
#include <network/ethernet.h>
diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c
index 68628d8..aeabbf2 100644
--- a/kernel/network/tcp.c
+++ b/kernel/network/tcp.c
@@ -182,7 +182,9 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) {
if (SYN == flags) {
struct TcpConnection *con =
internal_tcp_incoming(src_ip.d, src_port, 0, dst_port);
- assert(con);
+ if(!con) {
+ return;
+ }
con->ack = seq_num + 1;
tcp_send_empty_payload(con, SYN | ACK);
con->seq++;
diff --git a/kernel/network/udp.c b/kernel/network/udp.c
index 1112c3d..724c97a 100644
--- a/kernel/network/udp.c
+++ b/kernel/network/udp.c
@@ -6,6 +6,10 @@
void send_udp_packet(struct sockaddr_in *src, const struct sockaddr_in *dst,
const u8 *payload, u16 payload_length) {
+ assert(src);
+
+ assert(dst);
+
u16 header[4] = {0};
header[0] = src->sin_port;
header[1] = dst->sin_port;
@@ -15,11 +19,44 @@ void send_udp_packet(struct sockaddr_in *src, const struct sockaddr_in *dst,
u8 *packet = kmalloc(packet_length);
memcpy(packet, header, sizeof(header));
memcpy(packet + sizeof(header), payload, payload_length);
- send_ipv4_packet((ipv4_t){.d = dst->sin_addr.s_addr}, 0x11, packet, packet_length);
+ send_ipv4_packet((ipv4_t){.d = dst->sin_addr.s_addr}, 0x11, packet,
+ packet_length);
kfree(packet);
}
void handle_udp(ipv4_t src_ip, const u8 *payload, u32 packet_length) {
- // TODO: Reimplement
- assert(NULL);
+ if (packet_length < sizeof(u16[4])) {
+ return;
+ }
+ const u16 *header = (u16 *)payload;
+ u16 src_port = ntohs(*header);
+ u16 dst_port = ntohs(*(header + 1));
+ u16 length = ntohs(*(header + 2));
+ u16 checksum = ntohs(*(header + 3));
+ (void)checksum; // TODO
+ if (length < 8) {
+ return;
+ }
+ if (length != packet_length) {
+ return;
+ }
+
+ struct UdpConnection *con = udp_find_connection(src_ip, src_port, dst_port);
+ if (!con) {
+ return;
+ }
+
+ u32 len = length - 8 + sizeof(struct sockaddr_in);
+
+ if (ringbuffer_unused(&con->incoming_buffer) < len + sizeof(u32)) {
+ return;
+ }
+
+ ringbuffer_write(&con->incoming_buffer, (void *)&len, sizeof(len));
+
+ struct sockaddr_in from;
+ from.sin_addr.s_addr = src_ip.d;
+ from.sin_port = src_port;
+ ringbuffer_write(&con->incoming_buffer, (void *)&from, sizeof(from));
+ ringbuffer_write(&con->incoming_buffer, payload + 8, length - 8);
}
diff --git a/kernel/socket.c b/kernel/socket.c
index d952052..fa37efd 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -3,17 +3,21 @@
#include <fs/devfs.h>
#include <fs/tmpfs.h>
#include <interrupts.h>
+#include <math.h>
#include <network/bytes.h>
#include <network/tcp.h>
+#include <network/udp.h>
#include <poll.h>
#include <sched/scheduler.h>
#include <socket.h>
#include <sys/socket.h>
+struct list open_udp_connections;
struct list open_tcp_connections;
struct list open_tcp_listen;
void global_socket_init(void) {
+ list_init(&open_udp_connections);
list_init(&open_tcp_connections);
list_init(&open_tcp_listen);
}
@@ -42,6 +46,24 @@ struct TcpConnection *tcp_find_connection(ipv4_t src_ip, u16 src_port,
return NULL;
}
+struct UdpConnection *udp_find_connection(ipv4_t src_ip, u16 src_port,
+ u16 dst_port) {
+ (void)src_ip;
+ for (int i = 0;; i++) {
+ struct UdpConnection *c;
+ if (!list_get(&open_udp_connections, i, (void **)&c)) {
+ break;
+ }
+ if (c->dead) {
+ continue;
+ }
+ if (c->incoming_port == dst_port && c->outgoing_port == src_port) {
+ return c;
+ }
+ }
+ return NULL;
+}
+
struct TcpListen *tcp_find_listen(u16 port) {
for (int i = 0;; i++) {
struct TcpListen *c;
@@ -149,12 +171,114 @@ int tcp_has_data(vfs_inode_t *inode) {
return !(ringbuffer_isempty(&con->incoming_buffer));
}
+int udp_recvfrom(vfs_fd_t *fd, void *buffer, size_t len, int flags,
+ struct sockaddr *src_addr, socklen_t *addrlen) {
+ struct UdpConnection *con = fd->inode->internal_object;
+ assert(con);
+ if (con->dead) {
+ return -EBADF; // TODO: Check if this is correct.
+ }
+
+ u32 packet_length;
+ u32 rc = ringbuffer_read(&con->incoming_buffer, (void *)&packet_length,
+ sizeof(u32));
+ if (0 == rc) {
+ return -EWOULDBLOCK;
+ }
+ assert(sizeof(u32) == rc);
+ assert(sizeof(struct sockaddr_in) <= packet_length);
+
+ struct sockaddr_in from;
+ ringbuffer_read(&con->incoming_buffer, (void *)&from, sizeof(from));
+
+ if (addrlen) {
+ if (src_addr) {
+ memcpy(src_addr, &from, min(sizeof(from), *addrlen));
+ }
+ *addrlen = sizeof(from);
+ }
+
+ u32 rest = packet_length - sizeof(from);
+ u32 to_read = min(rest, len);
+ rest = rest - to_read;
+
+ rc = ringbuffer_read(&con->incoming_buffer, buffer, to_read);
+ // Discard the rest of the packet
+ // FIXME Maybe the rest of the packet can be kept? But unsure how that
+ // would be done while preserving the header and not messing up other
+ // packets.
+ (void)ringbuffer_read(&con->incoming_buffer, NULL, rest);
+ return rc;
+}
+
+int udp_read(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
+ return udp_recvfrom(fd, buffer, len, 0, NULL, NULL);
+}
+
+int udp_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
+ (void)offset;
+ struct UdpConnection *con = fd->inode->internal_object;
+ assert(con);
+ if (con->dead) {
+ return -EBADF; // TODO: Check if this is correct.
+ }
+
+ struct sockaddr_in dst;
+ dst.sin_addr.s_addr = con->outgoing_ip;
+ dst.sin_port = htons(con->outgoing_port);
+ struct sockaddr_in src;
+ src.sin_addr.s_addr = con->incoming_ip;
+ src.sin_port = htons(con->incoming_port);
+ send_udp_packet(&src, &dst, buffer, (u16)len);
+ return len;
+}
+
+int udp_has_data(vfs_inode_t *inode) {
+ struct UdpConnection *con = inode->internal_object;
+ return !(ringbuffer_isempty(&con->incoming_buffer));
+}
+
+void udp_close(vfs_fd_t *fd) {
+ struct UdpConnection *con = fd->inode->internal_object;
+ con->dead = 1;
+ ringbuffer_free(&con->incoming_buffer);
+ return;
+}
+
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
vfs_fd_t *fd = get_vfs_fd(sockfd, NULL);
if (!fd) {
return -EBADF;
}
+ assert(fd->inode);
+ assert(fd->inode->connect);
+ return fd->inode->connect(fd, addr, addrlen);
+}
+
+int udp_connect(vfs_fd_t *fd, const struct sockaddr *addr, socklen_t addrlen) {
+ assert(AF_INET == addr->sa_family);
+ const struct sockaddr_in *in_addr = (const struct sockaddr_in *)addr;
+ struct UdpConnection *con = kcalloc(1, sizeof(struct UdpConnection));
+ if (!con) {
+ return -ENOMEM;
+ }
+
+ con->incoming_port = 1337; // TODO
+ con->outgoing_ip = in_addr->sin_addr.s_addr;
+ con->outgoing_port = ntohs(in_addr->sin_port);
+ assert(ringbuffer_init(&con->incoming_buffer, 8192));
+ assert(list_add(&open_udp_connections, con, NULL));
+
+ fd->inode->_has_data = udp_has_data;
+ fd->inode->write = udp_write;
+ fd->inode->read = udp_read;
+ fd->inode->close = udp_close;
+ fd->inode->internal_object = con;
+ return 0;
+}
+
+int tcp_connect(vfs_fd_t *fd, const struct sockaddr *addr, socklen_t addrlen) {
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));
@@ -306,7 +430,7 @@ int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
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*/);
+ NULL /*send_signal*/, NULL /*connect*/);
assert(inode);
return vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, NULL);
}
@@ -434,7 +558,8 @@ int socket(int domain, int type, int protocol) {
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*/);
+ NULL /*truncate*/, NULL /*stat*/, NULL /*send_signal*/,
+ NULL /*connect*/);
if (!inode) {
rc = -ENOMEM;
goto socket_error;
@@ -453,11 +578,21 @@ int socket(int domain, int type, int protocol) {
return n;
}
if (AF_INET == domain) {
+ int is_udp = (SOCK_DGRAM == type);
+
+ void *connect_handler = NULL;
+ if (is_udp) {
+ connect_handler = udp_connect;
+ } else {
+ connect_handler = tcp_connect;
+ }
+
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*/);
+ NULL /*truncate*/, NULL /*stat*/, NULL /*send_signal*/,
+ connect_handler);
if (!inode) {
rc = -ENOMEM;
goto socket_error;
diff --git a/kernel/socket.h b/kernel/socket.h
index 3d1025d..ef5863d 100644
--- a/kernel/socket.h
+++ b/kernel/socket.h
@@ -1,3 +1,5 @@
+struct sockaddr;
+typedef int socklen_t;
#ifndef SOCKET_H
#define SOCKET_H
#include <fs/fifo.h>
@@ -27,6 +29,17 @@ struct TcpListen {
struct stack incoming_connections;
};
+struct UdpConnection {
+ u16 incoming_port;
+ u32 incoming_ip;
+ u32 outgoing_ip;
+ u16 outgoing_port;
+
+ int dead;
+
+ struct ringbuffer incoming_buffer;
+};
+
struct TcpConnection {
int dead;
u16 incoming_port;
@@ -52,6 +65,8 @@ struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port,
struct TcpConnection *tcp_find_connection(ipv4_t src_ip, u16 src_port,
u16 dst_port);
+struct UdpConnection *udp_find_connection(ipv4_t src_ip, u16 src_port,
+ u16 dst_port);
typedef struct {
vfs_fd_t *ptr_socket_fd;
@@ -83,7 +98,6 @@ typedef struct {
typedef u32 in_addr_t;
typedef u16 in_port_t;
typedef unsigned int sa_family_t;
-typedef int socklen_t;
struct sockaddr {
sa_family_t sa_family; /* Address family */
diff --git a/kernel/syscalls/open_process.c b/kernel/syscalls/open_process.c
index 8e3a35e..2acc744 100644
--- a/kernel/syscalls/open_process.c
+++ b/kernel/syscalls/open_process.c
@@ -19,7 +19,7 @@ int syscall_open_process(int pid) {
process /*internal_object*/, 0 /*file_size*/, NULL /*open*/,
NULL /*create_file*/, NULL /*read*/, NULL /*write*/, NULL /*close*/,
NULL /*create_directory*/, NULL /*get_vm_object*/, NULL /*truncate*/,
- NULL /*stat*/, process_signal);
+ NULL /*stat*/, process_signal, NULL /*connect*/);
int rc = vfs_create_fd(0, 0, 0, inode, NULL);
assert(rc >= 0);
return rc;