Files
lk/lib/minip/netif.c
Travis Geiselbrecht 10853d3259 WIP more net stack
2022-04-04 00:49:58 -07:00

149 lines
3.6 KiB
C

/*
* Copyright (c) 2022 Travis Geiselbrecht
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/
#include <lib/minip/netif.h>
#include <lk/err.h>
#include <lk/list.h>
#include <lk/trace.h>
#include <lib/minip.h>
#include <assert.h>
#include <stdlib.h>
#include <kernel/mutex.h>
#include "minip-internal.h"
#define LOCAL_TRACE 1
static struct list_node netif_list = LIST_INITIAL_VALUE(netif_list);
static mutex_t lock = MUTEX_INITIAL_VALUE(lock);
static netif_t loopback;
static int loopback_tx_func(void *arg, pktbuf_t *p) {
LTRACEF("arg %p, pkt %p\n", arg, p);
return 0;
}
void netif_init(void) {
LTRACE;
// loopback device
netif_create(&loopback, "loopback");
loopback.flags |= NETIF_FLAG_LOOPBACK;
netif_set_eth(&loopback, loopback_tx_func, NULL, bcast_mac);
netif_set_ipv4_addr(&loopback, IPV4(127, 0, 0, 1), 8);
netif_register(&loopback);
}
netif_t *netif_create(netif_t *n, const char *name) {
LTRACEF("n %p\n", n);
if (!n) {
n = malloc(sizeof(netif_t));
}
if (!n) {
return NULL;
}
memset(n, 0, sizeof(*n));
n->magic = NETIF_MAGIC;
strlcpy(n->name, name, sizeof(n->name));
return n;
}
// generic logic to decide what to do when a netif comes up
// TODO: make this overridable
void netif_registration_callback(netif_t *n) {
// if the interface isn't already configured, kick off a dhcp thread
if ((n->flags & NETIF_FLAG_IPV4_CONFIGURED) == 0) {
minip_start_dhcp(n);
}
}
status_t netif_register(netif_t *n) {
LTRACEF("n %p\n", n);
DEBUG_ASSERT(n->magic == NETIF_MAGIC);
mutex_acquire(&lock);
// check that it is at least configured
DEBUG_ASSERT(n->flags & NETIF_FLAG_ETH_CONFIGURED);
DEBUG_ASSERT((n->flags & NETIF_FLAG_REGISTERED) == 0);
list_add_head(&netif_list, &n->node);
n->flags |= NETIF_FLAG_REGISTERED;
mutex_release(&lock);
// let overridable external logic deal with this
netif_registration_callback(n);
return NO_ERROR;
}
status_t netif_set_eth(netif_t *n, tx_func_t tx_handler, void *tx_arg, const uint8_t *macaddr) {
DEBUG_ASSERT(n->magic == NETIF_MAGIC);
DEBUG_ASSERT(tx_handler);
mutex_acquire(&lock);
// must not have been already configured
DEBUG_ASSERT((n->flags & NETIF_FLAG_ETH_CONFIGURED) == 0);
// set the state and mark configured
mac_addr_copy(n->mac_address, macaddr);
n->tx_func = tx_handler;
n->tx_func_arg = tx_arg;
n->flags |= NETIF_FLAG_ETH_CONFIGURED;
mutex_release(&lock);
return NO_ERROR;
}
status_t netif_set_ipv4_addr(netif_t *n, ipv4_addr_t addr, uint8_t subnet_width) {
DEBUG_ASSERT(n->magic == NETIF_MAGIC);
mutex_acquire(&lock);
n->ipv4_addr = addr;
n->ipv4_subnet_width = subnet_width;
n->flags |= NETIF_FLAG_IPV4_CONFIGURED;
mutex_release(&lock);
// set an ipv4 route for this
ipv4_add_route(netif_get_network_ipv4(n), netif_get_netmask_ipv4(n), n);
return NO_ERROR;
}
void netif_dump(void) {
mutex_acquire(&lock);
netif_t *n;
list_for_every_entry(&netif_list, n, netif_t, node) {
printf("net interface @%p: name '%s' mac ", n, n->name);
print_mac_address(n->mac_address);
printf(" addr ");
print_ipv4_address(n->ipv4_addr);
printf("/%u", n->ipv4_subnet_width);
printf(" netmask ");
print_ipv4_address(netif_get_netmask_ipv4(n));
printf(" bcast ");
print_ipv4_address(netif_get_broadcast_ipv4(n));
printf("\n");
}
mutex_release(&lock);
}