net: initial loopback interface support
This commit is contained in:
parent
b4c84ee919
commit
f300386d13
@ -10,6 +10,7 @@
|
||||
|
||||
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_route(uint32_t addr);
|
||||
|
||||
typedef struct SockData {
|
||||
fs_node_t _fnode;
|
||||
|
@ -31,7 +31,6 @@
|
||||
#define DEFAULT_TCP_WINDOW_SIZE 65535
|
||||
|
||||
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) {
|
||||
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;
|
||||
fs_node_t * nic = net_if_any();
|
||||
fs_node_t * nic = net_if_route(name->sin_addr.s_addr);
|
||||
if (!nic) return -ENONET;
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
fs_node_t * nic = net_if_any();
|
||||
fs_node_t * nic = net_if_route(dest->sin_addr.s_addr);
|
||||
if (!nic) return -ENONET;
|
||||
|
||||
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 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;
|
||||
|
||||
struct ipv4_packet * response = malloc(total_length);
|
||||
|
122
kernel/net/loop.c
Normal file
122
kernel/net/loop.c
Normal 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;
|
||||
}
|
||||
|
@ -22,10 +22,13 @@
|
||||
static hashmap_t * interfaces = NULL;
|
||||
extern list_t * net_raw_sockets_list;
|
||||
static fs_node_t * _if_first = NULL;
|
||||
static fs_node_t * _if_loop = NULL;
|
||||
|
||||
extern void ipv4_install(void);
|
||||
extern hashmap_t * net_arp_cache;
|
||||
|
||||
extern fs_node_t * loopbook_install(void);
|
||||
|
||||
void net_install(void) {
|
||||
/* Set up virtual devices */
|
||||
map_vfs_directory("/dev/net");
|
||||
@ -33,6 +36,8 @@ void net_install(void) {
|
||||
net_raw_sockets_list = list_create("raw sockets", NULL);
|
||||
net_arp_cache = hashmap_create_int(10);
|
||||
ipv4_install();
|
||||
_if_loop = loopbook_install();
|
||||
_if_first = NULL;
|
||||
}
|
||||
|
||||
/* kinda temporary for now */
|
||||
@ -55,3 +60,9 @@ fs_node_t * net_if_lookup(const char * name) {
|
||||
fs_node_t * net_if_any(void) {
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user