summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/drivers/rtl8139.c1
-rw-r--r--kernel/fs/vfs.c10
-rw-r--r--kernel/fs/vfs.h1
-rw-r--r--kernel/init/kernel.c1
-rw-r--r--kernel/kmalloc.c2
-rw-r--r--kernel/network/ethernet.c14
-rw-r--r--kernel/network/ipv4.c5
-rw-r--r--kernel/network/tcp.c17
-rw-r--r--kernel/queue.c9
-rw-r--r--kernel/queue.h1
-rw-r--r--kernel/socket.c69
-rw-r--r--kernel/socket.h1
12 files changed, 91 insertions, 40 deletions
diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c
index 98d3f22..669cb6c 100644
--- a/kernel/drivers/rtl8139.c
+++ b/kernel/drivers/rtl8139.c
@@ -68,6 +68,7 @@ void handle_packet(void) {
(!packet_header.data.ROK);
if (error) {
+ klog(LOG_ERROR, "RTL8139 packet error");
current_packet_read = 0;
outb(rtl8139.gen.base_mem_io + 0x37, 0x4);
outb(rtl8139.gen.base_mem_io + 0x37, 0x4 | 0x8);
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c
index 65be4aa..d76e56c 100644
--- a/kernel/fs/vfs.c
+++ b/kernel/fs/vfs.c
@@ -41,7 +41,7 @@ vfs_inode_t *vfs_create_inode(
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));
+ vfs_inode_t *r = kcalloc(1, sizeof(inode_t));
r->inode_num = inode_num;
r->type = type;
r->_has_data = has_data;
@@ -325,14 +325,6 @@ int raw_vfs_pread(vfs_fd_t *vfs_fd, void *buf, u64 count, u64 offset) {
}
int vfs_pread(int fd, void *buf, u64 count, u64 offset) {
- if (fd >= 100) {
- kprintf("EBADF : %x\n", fd);
- return -EBADF;
- }
- if (fd < 0) {
- kprintf("EBADF : %x\n", fd);
- return -EBADF;
- }
vfs_fd_t *vfs_fd = get_vfs_fd(fd, NULL);
if (!vfs_fd) {
return -EBADF;
diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h
index a39982d..640cfbb 100644
--- a/kernel/fs/vfs.h
+++ b/kernel/fs/vfs.h
@@ -48,6 +48,7 @@ struct vfs_inode {
int type;
int (*_has_data)(vfs_inode_t *iinode);
int (*_can_write)(vfs_inode_t *iinode);
+ int (*_is_open)(vfs_inode_t *iinode);
u8 is_open;
int internal_object_type;
void *internal_object;
diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c
index 61e863b..2e569cb 100644
--- a/kernel/init/kernel.c
+++ b/kernel/init/kernel.c
@@ -13,6 +13,7 @@
#include <drivers/rtl8139.h>
#include <drivers/serial.h>
#include <drivers/vbe.h>
+#include <fcntl.h>
#include <fs/devfs.h>
#include <fs/ext2.h>
#include <fs/shm.h>
diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c
index b4a7f54..f5188cc 100644
--- a/kernel/kmalloc.c
+++ b/kernel/kmalloc.c
@@ -7,7 +7,7 @@
#include <mmu.h>
#include <random.h>
#include <stdint.h>
-#define NEW_ALLOC_SIZE 0x5000
+#define NEW_ALLOC_SIZE 0x40000
// #define KMALLOC_DEBUG
diff --git a/kernel/network/ethernet.c b/kernel/network/ethernet.c
index 7b1de7f..dbd1b6d 100644
--- a/kernel/network/ethernet.c
+++ b/kernel/network/ethernet.c
@@ -68,14 +68,14 @@ void handle_ethernet(const u8 *packet, u64 packet_length) {
}
}
+u8 ethernet_buffer[0x1000];
void send_ethernet_packet(u8 mac_dst[6], u16 type, u8 *payload,
u64 payload_length) {
- // FIXME: Janky allocation, do this better
u64 buffer_size =
sizeof(struct EthernetHeader) + payload_length + sizeof(u32);
- u8 *buffer = kmalloc(buffer_size);
- memset(buffer, 0, buffer_size);
- u8 *buffer_start = buffer;
+ assert(buffer_size < 0x1000);
+ memset(ethernet_buffer, 0, buffer_size);
+ u8 *buffer = ethernet_buffer;
struct EthernetHeader *eth_header = (struct EthernetHeader *)buffer;
buffer += sizeof(struct EthernetHeader);
memcpy(buffer, payload, payload_length);
@@ -84,8 +84,8 @@ void send_ethernet_packet(u8 mac_dst[6], u16 type, u8 *payload,
memcpy(eth_header->mac_dst, mac_dst, sizeof(u8[6]));
get_mac_address(eth_header->mac_src);
eth_header->type = htons(type);
- *(u32 *)(buffer) = htonl(crc32((const char *)buffer_start, buffer_size - 4));
+ *(u32 *)(buffer) =
+ htonl(crc32((const char *)ethernet_buffer, buffer_size - 4));
- rtl8139_send_data(buffer_start, buffer_size);
- kfree(buffer_start);
+ rtl8139_send_data(ethernet_buffer, buffer_size);
}
diff --git a/kernel/network/ipv4.c b/kernel/network/ipv4.c
index 69ceef7..6074141 100644
--- a/kernel/network/ipv4.c
+++ b/kernel/network/ipv4.c
@@ -26,6 +26,7 @@ static u16 ip_checksum(const u16 *data, u16 length) {
return htons(~acc);
}
+u8 ipv4_buffer[0x1000];
void send_ipv4_packet(ipv4_t ip, u8 protocol, const u8 *payload, u16 length) {
u16 header[10];
header[0] = (4 /*version*/ << 4) | (5 /*IHL*/);
@@ -46,7 +47,8 @@ void send_ipv4_packet(ipv4_t ip, u8 protocol, const u8 *payload, u16 length) {
header[5] = ip_checksum(header, 20);
u16 packet_length = length + 20;
- u8 *packet = kmalloc(packet_length);
+ assert(packet_length < sizeof(ipv4_buffer));
+ u8 *packet = ipv4_buffer;
memcpy(packet, header, 20);
memcpy(packet + 20, payload, length);
@@ -54,7 +56,6 @@ void send_ipv4_packet(ipv4_t ip, u8 protocol, const u8 *payload, u16 length) {
for (; !get_mac_from_ip(ip, mac);)
;
send_ethernet_packet(mac, 0x0800, packet, packet_length);
- kfree(packet);
}
void handle_ipv4(const u8 *payload, u32 packet_length) {
diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c
index 8a56dd1..8717250 100644
--- a/kernel/network/tcp.c
+++ b/kernel/network/tcp.c
@@ -87,6 +87,7 @@ static void tcp_send(struct TcpConnection *con, u8 *buffer, u16 length,
send_ipv4_packet((ipv4_t){.d = con->outgoing_ip}, 6, buffer, length);
}
+u8 tcp_buffer[0x1000];
void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) {
struct TcpHeader header;
memset(&header, 0, sizeof(header));
@@ -110,8 +111,10 @@ void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) {
header.checksum = tcp_calculate_checksum(
ip_address, con->outgoing_ip, (const u8 *)payload, payload_length,
&header, sizeof(struct TcpHeader) + payload_length);
- int send_len = sizeof(header) + payload_length;
- u8 *send_buffer = kmalloc(send_len);
+ u32 send_len = sizeof(header) + payload_length;
+
+ assert(send_len < sizeof(tcp_buffer));
+ u8 *send_buffer = tcp_buffer;
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), payload, payload_length);
@@ -133,13 +136,15 @@ void tcp_close_connection(struct TcpConnection *con) {
if (TCP_STATE_CLOSE_WAIT == con->state) {
tcp_send_empty_payload(con, FIN);
con->state = TCP_STATE_LAST_ACK;
+ tcp_destroy_connection(con); // Client does not appear to respond
+ // with last ack?
return;
}
if (TCP_STATE_ESTABLISHED == con->state) {
// FIXME:
// Book says it should be FIN but observed network traffic says it
// should be FIN|ACK?
- tcp_send_empty_payload(con, FIN | ACK);
+ tcp_send_empty_payload(con, FIN);
con->state = TCP_STATE_FIN_WAIT1;
return;
}
@@ -189,9 +194,9 @@ int send_tcp_packet(struct TcpConnection *con, const u8 *payload,
header.checksum = tcp_calculate_checksum(
ip_address, con->outgoing_ip, (const u8 *)payload, payload_length,
&header, sizeof(struct TcpHeader) + payload_length);
- int send_len = sizeof(header) + payload_length;
- u8 *send_buffer = kmalloc(send_len);
- assert(send_buffer);
+ u32 send_len = sizeof(header) + payload_length;
+ assert(send_len < sizeof(tcp_buffer));
+ u8 *send_buffer = tcp_buffer;
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), payload, payload_length);
diff --git a/kernel/queue.c b/kernel/queue.c
index 6d4209d..e1b2943 100644
--- a/kernel/queue.c
+++ b/kernel/queue.c
@@ -43,6 +43,13 @@ int queue_get_entries(struct queue_list *list, struct queue_entry *events,
}
}
}
+ if (QUEUE_WAIT_CLOSE & entry->listen) {
+ if (ptr->inode->_is_open) {
+ if (!ptr->inode->_is_open(ptr->inode)) {
+ should_add = 1;
+ }
+ }
+ }
if (should_add) {
if (events) {
memcpy(events + rc, entry, sizeof(struct queue_entry));
@@ -130,7 +137,7 @@ int queue_mod_entries(int fd, int flag, struct queue_entry *entries,
}
for (int j = 0; j < num_entries; j++) {
if (entry->fd == entries[j].fd) {
- relist_remove(&list->entries, i);
+ assert(relist_remove(&list->entries, i));
kfree(entry);
break;
}
diff --git a/kernel/queue.h b/kernel/queue.h
index 0885f16..4a9cd17 100644
--- a/kernel/queue.h
+++ b/kernel/queue.h
@@ -4,6 +4,7 @@
#define QUEUE_WAIT_READ (1 << 0)
#define QUEUE_WAIT_WRITE (1 << 1)
+#define QUEUE_WAIT_CLOSE (1 << 2)
#define QUEUE_MOD_ADD 0
#define QUEUE_MOD_CHANGE 1
diff --git a/kernel/socket.c b/kernel/socket.c
index fbccac5..cc5a645 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -48,12 +48,30 @@ void tcp_remove_connection(struct TcpConnection *con) {
}
if (c == con) {
relist_remove(&open_tcp_connections, i);
+ ringbuffer_free(&c->incoming_buffer);
+ ringbuffer_free(&c->outgoing_buffer);
kfree(con);
break;
}
}
}
+int num_open_connections(void) {
+ int f = 0;
+ for (int i = 0;; i++) {
+ struct TcpConnection *c;
+ int end;
+ if (!relist_get(&open_tcp_connections, i, (void **)&c, &end)) {
+ if (end) {
+ break;
+ }
+ continue;
+ }
+ f++;
+ }
+ return f;
+}
+
struct TcpConnection *tcp_connect_to_listen(ipv4_t src_ip, u16 src_port,
ipv4_t dst_ip, u16 dst_port) {
for (int i = 0;; i++) {
@@ -74,7 +92,11 @@ struct TcpConnection *tcp_connect_to_listen(ipv4_t src_ip, u16 src_port,
if (c->incoming_port == dst_port) {
struct TcpConnection *new_connection =
kmalloc(sizeof(struct TcpConnection));
- memcpy(new_connection, c, sizeof(struct TcpConnection));
+ new_connection->incoming_port = c->incoming_port;
+ new_connection->incoming_ip = c->incoming_ip;
+
+ new_connection->no_delay = c->no_delay;
+
new_connection->outgoing_port = src_port;
new_connection->outgoing_ip = src_ip.d;
new_connection->state = TCP_STATE_LISTEN;
@@ -94,10 +116,7 @@ struct TcpConnection *tcp_connect_to_listen(ipv4_t src_ip, u16 src_port,
new_connection->snd_wnd = 0;
new_connection->sent_ack = 0;
- new_connection->snd_wnd =
- ringbuffer_unused(&new_connection->outgoing_buffer);
- u32 index;
- assert(relist_add(&open_tcp_connections, new_connection, &index));
+ assert(relist_add(&open_tcp_connections, new_connection, NULL));
assert(relist_add(&c->incoming_connections, new_connection, NULL));
return new_connection;
}
@@ -137,9 +156,24 @@ void tcp_flush_buffers(void) {
}
continue;
}
+ if (TCP_STATE_TIME_WAIT == c->state) {
+ // TODO: It should actually wait
+ c->state = TCP_STATE_CLOSED;
+ tcp_remove_connection(c);
+ continue;
+ }
+ if (TCP_STATE_FIN_WAIT2 == c->state) {
+ // TODO: It should actually wait
+ c->state = TCP_STATE_CLOSED;
+ tcp_remove_connection(c);
+ continue;
+ }
if (TCP_STATE_CLOSED == c->state) {
continue;
}
+ if (TCP_STATE_ESTABLISHED != c->state) {
+ continue;
+ }
tcp_sync_buffer(c);
}
}
@@ -233,9 +267,12 @@ void tcp_strip_connection(struct TcpConnection *con) {
void tcp_close(vfs_fd_t *fd) {
struct TcpConnection *con = fd->inode->internal_object;
+ if (TCP_STATE_CLOSED == con->state) {
+ return;
+ }
assert(con);
- tcp_sync_buffer(con);
if (TCP_STATE_ESTABLISHED == con->state) {
+ tcp_sync_buffer(con);
tcp_strip_connection(con);
}
tcp_close_connection(con);
@@ -256,12 +293,16 @@ int tcp_read(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
int tcp_has_data(vfs_inode_t *inode) {
struct TcpConnection *con = inode->internal_object;
+ if (TCP_STATE_ESTABLISHED != con->state) {
+ inode->is_open = 0;
+ }
return !(ringbuffer_isempty(&con->incoming_buffer));
}
int tcp_can_write(vfs_inode_t *inode) {
struct TcpConnection *con = inode->internal_object;
if (TCP_STATE_ESTABLISHED != con->state) {
+ inode->is_open = 0;
return 0;
}
if (con->no_delay) {
@@ -271,6 +312,11 @@ int tcp_can_write(vfs_inode_t *inode) {
(0 != tcp_can_send(con));
}
+int tcp_is_open(vfs_inode_t *inode) {
+ struct TcpConnection *con = inode->internal_object;
+ return (TCP_STATE_ESTABLISHED == con->state);
+}
+
int tcp_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
(void)offset;
struct TcpConnection *con = fd->inode->internal_object;
@@ -462,6 +508,7 @@ int tcp_connect(vfs_fd_t *fd, const struct sockaddr *addr, socklen_t addrlen) {
fd->inode->_has_data = tcp_has_data;
fd->inode->_can_write = tcp_can_write;
+ fd->inode->_is_open = tcp_is_open;
fd->inode->write = tcp_write;
fd->inode->read = tcp_read;
fd->inode->close = tcp_close;
@@ -535,12 +582,6 @@ 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;
@@ -587,6 +628,7 @@ int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
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 /*connect*/);
+ inode->_is_open = tcp_is_open;
assert(inode);
return vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, NULL);
}
@@ -618,7 +660,7 @@ struct TcpConnection *tcp_get_incoming_connection(struct TcpConnection *con,
if (!c) {
continue;
}
- if (TCP_STATE_ESTABLISHED == c->state) {
+ if (TCP_STATE_LISTEN != c->state) {
if (remove) {
assert(relist_remove(&con->incoming_connections, i));
}
@@ -739,6 +781,7 @@ int tcp_create_fd(int is_nonblock) {
kfree(con);
return -ENOMEM;
}
+ inode->_is_open = tcp_is_open;
int fd = vfs_create_fd(O_RDWR | (is_nonblock ? O_NONBLOCK : 0), 0,
0 /*is_tty*/, inode, NULL);
if (fd < 0) {
diff --git a/kernel/socket.h b/kernel/socket.h
index 35074a1..efe0104 100644
--- a/kernel/socket.h
+++ b/kernel/socket.h
@@ -40,7 +40,6 @@ struct UdpConnection {
};
struct TcpConnection {
-
int state;
u16 incoming_port;