phunix/minix/net/lwip/mibtree.c
David van Moolenbroek ef8d499e2d Add lwip: a new lwIP-based TCP/IP service
This commit adds a new TCP/IP service to MINIX 3.  As its core, the
service uses the lwIP TCP/IP stack for maintenance reasons.  The
service aims to be compatible with NetBSD userland, including its
low-level network management utilities.  It also aims to support
modern features such as IPv6.  In summary, the new LWIP service has
support for the following main features:

- TCP, UDP, RAW sockets with mostly standard BSD API semantics;
- IPv6 support: host mode (complete) and router mode (partial);
- most of the standard BSD API socket options (SO_);
- all of the standard BSD API message flags (MSG_);
- the most used protocol-specific socket and control options;
- a default loopback interface and the ability to create one more;
- configuration-free ethernet interfaces and driver tracking;
- queuing and multiple concurrent requests to each ethernet driver;
- standard ioctl(2)-based BSD interface management;
- radix tree backed, destination-based routing;
- routing sockets for standard BSD route reporting and management;
- multicast traffic and multicast group membership tracking;
- Berkeley Packet Filter (BPF) devices;
- standard and custom sysctl(7) nodes for many internals;
- a slab allocation based, hybrid static/dynamic memory pool model.

Many of its modules come with fairly elaborate comments that cover
many aspects of what is going on.  The service is primarily a socket
driver built on top of the libsockdriver library, but for BPF devices
it is at the same time also a character driver.

Change-Id: Ib0c02736234b21143915e5fcc0fda8fe408f046f
2017-04-30 13:16:03 +00:00

142 lines
4.1 KiB
C

/* LWIP service - mibtree.c - sysctl support for */
/*
* This file acts as a dispatcher for the net.inet, net.inet6, and minix.lwip
* sysctl trees. It does not cover the other net.* trees; these are taken care
* of in other source files.
*/
#include "lwip.h"
#include <minix/sysctl.h>
#define MAX_PROTO 6 /* maximum # of INET protocols with subtrees */
static struct rmib_indir net_inet_indir[MAX_PROTO];
static unsigned int net_inet_indir_count = 0;
static struct rmib_node net_inet_node =
RMIB_SNODE(RMIB_RO, net_inet_indir, "inet", "PF_INET related settings");
#ifdef INET6
static struct rmib_indir net_inet6_indir[MAX_PROTO];
static unsigned int net_inet6_indir_count = 0;
static struct rmib_node net_inet6_node =
RMIB_SNODE(RMIB_RO, net_inet6_indir, "inet6", "PF_INET6 related settings");
#endif /* INET6 */
#define MAX_LWIP 4 /* maximum # of miscellaneous LWIP subtrees */
static struct rmib_indir minix_lwip_indir[MAX_LWIP];
static unsigned int minix_lwip_indir_count = 0;
static struct rmib_node minix_lwip_node =
RMIB_SNODE(RMIB_RO, minix_lwip_indir, "lwip",
"LWIP service information and settings");
/*
* Initialize the status module by registering the net.inet, net.inet6, and
* minix.lwip trees with the MIB service. Other modules must have added all
* subtrees to those trees through mibtree_register_*() before this point.
*/
void
mibtree_init(void)
{
const int inet_mib[] = { CTL_NET, PF_INET };
#ifdef INET6
const int inet6_mib[] = { CTL_NET, PF_INET6 };
#endif /* INET6 */
const int lwip_mib[] = { CTL_MINIX, MINIX_LWIP };
int r;
/*
* Register the "net.inet", "net.inet6", and "minix.lwip" subtrees with
* the MIB service.
*
* These calls only return local failures. Remote failures (in the MIB
* service) are silently ignored. So, we can safely panic on failure.
*/
if ((r = rmib_register(inet_mib, __arraycount(inet_mib),
&net_inet_node)) != OK)
panic("unable to register net.inet RMIB tree: %d", r);
#ifdef INET6
if ((r = rmib_register(inet6_mib, __arraycount(inet6_mib),
&net_inet6_node)) != OK)
panic("unable to register net.inet6 RMIB tree: %d", r);
#endif /* INET6 */
if ((r = rmib_register(lwip_mib, __arraycount(lwip_mib),
&minix_lwip_node)) != OK)
panic("unable to register minix.lwip RMIB tree: %d", r);
}
/*
* Add a subtree to the local net.inet or net.inet6 tree. This function must
* only be called *before* mibtree_init(), as the latter will register the
* final tree with the MIB service.
*/
void
mibtree_register_inet(int domain, int protocol, struct rmib_node * node)
{
struct rmib_node *parent;
struct rmib_indir *indir;
unsigned int i, *count;
switch (domain) {
case PF_INET:
parent = &net_inet_node;
indir = net_inet_indir;
count = &net_inet_indir_count;
break;
case PF_INET6:
#ifdef INET6
parent = &net_inet6_node;
indir = net_inet6_indir;
count = &net_inet6_indir_count;
break;
#else /* !INET6 */
return;
#endif /* !INET6 */
default:
panic("invalid domain %d", domain);
}
assert(*count < MAX_PROTO);
/* Insertion sort. */
for (i = 0; i < *count; i++) {
assert(indir[i].rindir_id != (unsigned int)protocol);
if (indir[i].rindir_id > (unsigned int)protocol)
break;
}
if (i < *count)
memmove(&indir[i + 1], &indir[i],
sizeof(indir[0]) * (*count - i));
indir[i].rindir_id = protocol;
indir[i].rindir_node = node;
parent->rnode_size = ++*count;
}
/*
* Add a miscellaneous subtree to the local minix.lwip tree. This function
* must only be called *before* mibtree_init(), as the latter will register the
* final tree with the MIB service. Note that the given subtrees are numbered
* arbitrarily. We use sparse trees here only to avoid having to declare
* external variables, which is a bit of a hack, but with the expected low
* number of miscellaneous subtrees there will be no performance penalty.
*/
void
mibtree_register_lwip(struct rmib_node * node)
{
unsigned int i;
i = minix_lwip_indir_count;
assert(i < __arraycount(minix_lwip_indir));
minix_lwip_indir[i].rindir_id = i;
minix_lwip_indir[i].rindir_node = node;
minix_lwip_node.rnode_size = ++minix_lwip_indir_count;
}