diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/drivers/rtl8139.c | 1 | ||||
| -rw-r--r-- | kernel/fs/vfs.c | 10 | ||||
| -rw-r--r-- | kernel/fs/vfs.h | 1 | ||||
| -rw-r--r-- | kernel/init/kernel.c | 1 | ||||
| -rw-r--r-- | kernel/kmalloc.c | 2 | ||||
| -rw-r--r-- | kernel/network/ethernet.c | 14 | ||||
| -rw-r--r-- | kernel/network/ipv4.c | 5 | ||||
| -rw-r--r-- | kernel/network/tcp.c | 17 | ||||
| -rw-r--r-- | kernel/queue.c | 9 | ||||
| -rw-r--r-- | kernel/queue.h | 1 | ||||
| -rw-r--r-- | kernel/socket.c | 69 | ||||
| -rw-r--r-- | kernel/socket.h | 1 | 
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; |