net: initial loopback interface support

This commit is contained in:
K. Lange 2021-10-22 15:36:03 +09:00
parent b4c84ee919
commit f300386d13
4 changed files with 139 additions and 6 deletions

View File

@ -10,6 +10,7 @@
int net_add_interface(const char * name, fs_node_t * deviceNode); int net_add_interface(const char * name, fs_node_t * deviceNode);
fs_node_t * net_if_lookup(const char * name); fs_node_t * net_if_lookup(const char * name);
fs_node_t * net_if_route(uint32_t addr);
typedef struct SockData { typedef struct SockData {
fs_node_t _fnode; fs_node_t _fnode;

View File

@ -31,7 +31,6 @@
#define DEFAULT_TCP_WINDOW_SIZE 65535 #define DEFAULT_TCP_WINDOW_SIZE 65535
static int _debug __attribute__((unused)) = 0; static int _debug __attribute__((unused)) = 0;
extern fs_node_t * net_if_any(void);
static void ip_ntoa(const uint32_t src_addr, char * out) { static void ip_ntoa(const uint32_t src_addr, char * out) {
snprintf(out, 16, "%d.%d.%d.%d", snprintf(out, 16, "%d.%d.%d.%d",
@ -225,7 +224,7 @@ static long sock_icmp_send(sock_t * sock, const struct msghdr *msg, int flags) {
} }
struct sockaddr_in * name = msg->msg_name; struct sockaddr_in * name = msg->msg_name;
fs_node_t * nic = net_if_any(); fs_node_t * nic = net_if_route(name->sin_addr.s_addr);
if (!nic) return -ENONET; if (!nic) return -ENONET;
size_t total_length = sizeof(struct ipv4_packet) + msg->msg_iov[0].iov_len; size_t total_length = sizeof(struct ipv4_packet) + msg->msg_iov[0].iov_len;
@ -470,7 +469,7 @@ static long sock_udp_send(sock_t * sock, const struct msghdr *msg, int flags) {
printf("udp: want to send to %s\n", dest); printf("udp: want to send to %s\n", dest);
/* Routing: We need a device to send this on... */ /* Routing: We need a device to send this on... */
fs_node_t * nic = net_if_any(); fs_node_t * nic = net_if_route(name->sin_addr.s_addr);
if (!nic) return 0; if (!nic) return 0;
size_t total_length = sizeof(struct ipv4_packet) + msg->msg_iov[0].iov_len + sizeof(struct udp_packet); size_t total_length = sizeof(struct ipv4_packet) + msg->msg_iov[0].iov_len + sizeof(struct udp_packet);
@ -582,7 +581,7 @@ static void sock_tcp_close(sock_t * sock) {
spin_unlock(tcp_port_lock); spin_unlock(tcp_port_lock);
size_t total_length = sizeof(struct ipv4_packet) + sizeof(struct tcp_header); size_t total_length = sizeof(struct ipv4_packet) + sizeof(struct tcp_header);
fs_node_t * nic = net_if_any(); fs_node_t * nic = net_if_route(((struct sockaddr_in*)&sock->dest)->sin_addr.s_addr);
if (!nic) return; if (!nic) return;
struct ipv4_packet * response = malloc(total_length); struct ipv4_packet * response = malloc(total_length);
@ -719,7 +718,7 @@ static long sock_tcp_connect(sock_t * sock, const struct sockaddr *addr, socklen
memcpy(&sock->dest, addr, addrlen); memcpy(&sock->dest, addr, addrlen);
fs_node_t * nic = net_if_any(); fs_node_t * nic = net_if_route(dest->sin_addr.s_addr);
if (!nic) return -ENONET; if (!nic) return -ENONET;
size_t total_length = sizeof(struct ipv4_packet) + sizeof(struct tcp_header); size_t total_length = sizeof(struct ipv4_packet) + sizeof(struct tcp_header);
@ -844,7 +843,7 @@ static long sock_tcp_send(sock_t * sock, const struct msghdr *msg, int flags) {
size_t size_to_send = size_remaining > 1024 ? 1024 : size_remaining; size_t size_to_send = size_remaining > 1024 ? 1024 : size_remaining;
size_t total_length = sizeof(struct ipv4_packet) + sizeof(struct tcp_header) + size_to_send; size_t total_length = sizeof(struct ipv4_packet) + sizeof(struct tcp_header) + size_to_send;
fs_node_t * nic = net_if_any(); fs_node_t * nic = net_if_route(((struct sockaddr_in*)&sock->dest)->sin_addr.s_addr);
if (!nic) return -ENONET; if (!nic) return -ENONET;
struct ipv4_packet * response = malloc(total_length); struct ipv4_packet * response = malloc(total_length);

122
kernel/net/loop.c Normal file
View File

@ -0,0 +1,122 @@
/**
* @file kernel/net/loop.c
* @brief Loopback interface
*
* @copyright
* This file is part of ToaruOS and is released under the terms
* of the NCSA / University of Illinois License - see LICENSE.md
* Copyright (C) 2021 K. Lange
*/
#include <kernel/types.h>
#include <kernel/string.h>
#include <kernel/printf.h>
#include <kernel/vfs.h>
#include <kernel/spinlock.h>
#include <kernel/list.h>
#include <kernel/mod/net.h>
#include <kernel/net/netif.h>
#include <kernel/net/eth.h>
#include <errno.h>
#include <sys/socket.h>
#include <net/if.h>
struct loop_nic {
struct EthernetDevice eth;
netif_counters_t counts;
};
static int ioctl_loop(fs_node_t * node, unsigned long request, void * argp) {
struct loop_nic * nic = node->device;
switch (request) {
case SIOCGIFHWADDR:
return 1;
case SIOCGIFADDR:
if (nic->eth.ipv4_addr == 0) return -ENOENT;
memcpy(argp, &nic->eth.ipv4_addr, sizeof(nic->eth.ipv4_addr));
return 0;
case SIOCSIFADDR:
memcpy(&nic->eth.ipv4_addr, argp, sizeof(nic->eth.ipv4_addr));
return 0;
case SIOCGIFNETMASK:
if (nic->eth.ipv4_subnet == 0) return -ENOENT;
memcpy(argp, &nic->eth.ipv4_subnet, sizeof(nic->eth.ipv4_subnet));
return 0;
case SIOCSIFNETMASK:
memcpy(&nic->eth.ipv4_subnet, argp, sizeof(nic->eth.ipv4_subnet));
return 0;
case SIOCGIFGATEWAY:
if (nic->eth.ipv4_subnet == 0) return -ENOENT;
memcpy(argp, &nic->eth.ipv4_gateway, sizeof(nic->eth.ipv4_gateway));
return 0;
case SIOCSIFGATEWAY:
memcpy(&nic->eth.ipv4_gateway, argp, sizeof(nic->eth.ipv4_gateway));
net_arp_ask(nic->eth.ipv4_gateway, node);
return 0;
case SIOCGIFADDR6:
return -ENOENT;
case SIOCSIFADDR6:
memcpy(&nic->eth.ipv6_addr, argp, sizeof(nic->eth.ipv6_addr));
return 0;
case SIOCGIFFLAGS: {
uint32_t * flags = argp;
*flags = IFF_RUNNING;
*flags |= IFF_UP;
*flags |= IFF_LOOPBACK;
return 0;
}
case SIOCGIFMTU: {
uint32_t * mtu = argp;
*mtu = nic->eth.mtu;
return 0;
}
case SIOCGIFCOUNTS: {
memcpy(argp, &nic->counts, sizeof(netif_counters_t));
return 0;
}
default:
return -EINVAL;
}
}
static ssize_t write_loop(fs_node_t *node, off_t offset, size_t size, uint8_t *buffer) {
struct loop_nic * nic = node->device;
nic->counts.rx_count++;
nic->counts.tx_count++;
nic->counts.rx_bytes += size;
nic->counts.tx_bytes += size;
net_eth_handle((void*)buffer, node);
return size;
}
static void loop_init(struct loop_nic * nic) {
nic->eth.device_node = calloc(sizeof(fs_node_t),1);
snprintf(nic->eth.device_node->name, 100, "%s", nic->eth.if_name);
nic->eth.device_node->flags = FS_BLOCKDEVICE;
nic->eth.device_node->mask = 0666;
nic->eth.device_node->ioctl = ioctl_loop;
nic->eth.device_node->write = write_loop;
nic->eth.device_node->device = nic;
nic->eth.mtu = 65536; /* guess */
nic->eth.ipv4_addr = 0x0100007F;
nic->eth.ipv4_subnet = 0x000000FF;
net_add_interface(nic->eth.if_name, nic->eth.device_node);
}
fs_node_t * loopbook_install(void) {
struct loop_nic * nic = calloc(1,sizeof(struct loop_nic));
snprintf(nic->eth.if_name, 31, "lo");
loop_init(nic);
return nic->eth.device_node;
return 0;
}

View File

@ -22,10 +22,13 @@
static hashmap_t * interfaces = NULL; static hashmap_t * interfaces = NULL;
extern list_t * net_raw_sockets_list; extern list_t * net_raw_sockets_list;
static fs_node_t * _if_first = NULL; static fs_node_t * _if_first = NULL;
static fs_node_t * _if_loop = NULL;
extern void ipv4_install(void); extern void ipv4_install(void);
extern hashmap_t * net_arp_cache; extern hashmap_t * net_arp_cache;
extern fs_node_t * loopbook_install(void);
void net_install(void) { void net_install(void) {
/* Set up virtual devices */ /* Set up virtual devices */
map_vfs_directory("/dev/net"); map_vfs_directory("/dev/net");
@ -33,6 +36,8 @@ void net_install(void) {
net_raw_sockets_list = list_create("raw sockets", NULL); net_raw_sockets_list = list_create("raw sockets", NULL);
net_arp_cache = hashmap_create_int(10); net_arp_cache = hashmap_create_int(10);
ipv4_install(); ipv4_install();
_if_loop = loopbook_install();
_if_first = NULL;
} }
/* kinda temporary for now */ /* kinda temporary for now */
@ -55,3 +60,9 @@ fs_node_t * net_if_lookup(const char * name) {
fs_node_t * net_if_any(void) { fs_node_t * net_if_any(void) {
return _if_first; return _if_first;
} }
fs_node_t * net_if_route(uint32_t addr) {
/* First off, let's do stupid stuff. */
if (addr == 0x0100007F) return _if_loop;
return _if_first;
}