298 lines
6.4 KiB
C
298 lines
6.4 KiB
C
#include <unistd.h>
|
|
#include <minix/timers.h>
|
|
#include <sys/svrctl.h>
|
|
#include <minix/ds.h>
|
|
#include <minix/endpoint.h>
|
|
#include <errno.h>
|
|
#include <minix/sef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <minix/chardriver.h>
|
|
#include <minix/syslib.h>
|
|
#include <minix/sysutil.h>
|
|
#include <minix/timers.h>
|
|
#include <minix/netsock.h>
|
|
|
|
#include "proto.h"
|
|
|
|
#include <lwip/mem.h>
|
|
#include <lwip/pbuf.h>
|
|
#include <lwip/stats.h>
|
|
#include <lwip/netif.h>
|
|
#include <netif/etharp.h>
|
|
#include <lwip/tcp_impl.h>
|
|
|
|
endpoint_t lwip_ep;
|
|
|
|
static minix_timer_t tcp_ftmr, tcp_stmr, arp_tmr;
|
|
static int arp_ticks, tcp_fticks, tcp_sticks;
|
|
|
|
static struct netif * netif_lo;
|
|
|
|
extern struct sock_ops sock_udp_ops;
|
|
extern struct sock_ops sock_tcp_ops;
|
|
extern struct sock_ops sock_raw_ip_ops;
|
|
|
|
static void sys_init(void)
|
|
{
|
|
}
|
|
|
|
static void arp_watchdog(__unused minix_timer_t *tp)
|
|
{
|
|
etharp_tmr();
|
|
set_timer(&arp_tmr, arp_ticks, arp_watchdog, 0);
|
|
}
|
|
|
|
static void tcp_fwatchdog(__unused minix_timer_t *tp)
|
|
{
|
|
tcp_fasttmr();
|
|
set_timer(&tcp_ftmr, tcp_fticks, tcp_fwatchdog, 0);
|
|
}
|
|
|
|
static void tcp_swatchdog(__unused minix_timer_t *tp)
|
|
{
|
|
tcp_slowtmr();
|
|
set_timer(&tcp_ftmr, tcp_sticks, tcp_swatchdog, 0);
|
|
}
|
|
|
|
static int sef_cb_init_fresh(__unused int type, __unused sef_init_info_t *info)
|
|
{
|
|
int err;
|
|
unsigned int hz;
|
|
|
|
char my_name[16];
|
|
int my_priv;
|
|
|
|
err = sys_whoami(&lwip_ep, my_name, sizeof(my_name), &my_priv);
|
|
if (err != OK)
|
|
panic("Cannot get own endpoint");
|
|
|
|
nic_init_all();
|
|
inet_read_conf();
|
|
|
|
/* init lwip library */
|
|
stats_init();
|
|
sys_init();
|
|
mem_init();
|
|
memp_init();
|
|
pbuf_init();
|
|
|
|
hz = sys_hz();
|
|
|
|
arp_ticks = ARP_TMR_INTERVAL / (1000 / hz);
|
|
tcp_fticks = TCP_FAST_INTERVAL / (1000 / hz);
|
|
tcp_sticks = TCP_SLOW_INTERVAL / (1000 / hz);
|
|
|
|
etharp_init();
|
|
|
|
set_timer(&arp_tmr, arp_ticks, arp_watchdog, 0);
|
|
set_timer(&tcp_ftmr, tcp_fticks, tcp_fwatchdog, 0);
|
|
set_timer(&tcp_stmr, tcp_sticks, tcp_swatchdog, 0);
|
|
|
|
netif_init();
|
|
netif_lo = netif_find(__UNCONST("lo0"));
|
|
|
|
/* Read configuration. */
|
|
#if 0
|
|
nw_conf();
|
|
|
|
/* Get a random number */
|
|
timerand= 1;
|
|
fd = open(RANDOM_DEV_NAME, O_RDONLY | O_NONBLOCK);
|
|
if (fd != -1)
|
|
{
|
|
err= read(fd, randbits, sizeof(randbits));
|
|
if (err == sizeof(randbits))
|
|
timerand= 0;
|
|
else
|
|
{
|
|
printf("inet: unable to read random data from %s: %s\n",
|
|
RANDOM_DEV_NAME, err == -1 ? strerror(errno) :
|
|
err == 0 ? "EOF" : "not enough data");
|
|
}
|
|
close(fd);
|
|
}
|
|
else
|
|
{
|
|
printf("inet: unable to open random device %s: %s\n",
|
|
RANDOM_DEV_NAME, strerror(errno));
|
|
}
|
|
if (timerand)
|
|
{
|
|
printf("inet: using current time for random-number seed\n");
|
|
err= gettimeofday(&tv, NULL);
|
|
if (err == -1)
|
|
{
|
|
printf("sysutime failed: %s\n", strerror(errno));
|
|
exit(1);
|
|
}
|
|
memcpy(randbits, &tv, sizeof(tv));
|
|
}
|
|
init_rand256(randbits);
|
|
#endif
|
|
|
|
/* Subscribe to driver events for network drivers. */
|
|
if ((err = ds_subscribe("drv\\.net\\..*",
|
|
DSF_INITIAL | DSF_OVERWRITE)) != OK)
|
|
panic(("inet: can't subscribe to driver events"));
|
|
|
|
/* Announce we are up. LWIP announces its presence to VFS just like
|
|
* any other character driver.
|
|
*/
|
|
chardriver_announce();
|
|
|
|
return(OK);
|
|
}
|
|
|
|
static void sef_local_startup(void)
|
|
{
|
|
/* Register init callbacks. */
|
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
|
sef_setcb_init_restart(sef_cb_init_fresh);
|
|
|
|
/* No live update support for now. */
|
|
|
|
/* Let SEF perform startup. */
|
|
sef_startup();
|
|
}
|
|
|
|
static void ds_event(void)
|
|
{
|
|
char key[DS_MAX_KEYLEN];
|
|
const char *driver_prefix = "drv.net.";
|
|
char *label;
|
|
u32_t value;
|
|
int type;
|
|
endpoint_t owner_endpoint;
|
|
int r;
|
|
int prefix_len;
|
|
|
|
prefix_len = strlen(driver_prefix);
|
|
|
|
/* We may get one notification for multiple updates from DS. Get events
|
|
* and owners from DS, until DS tells us that there are no more.
|
|
*/
|
|
while ((r = ds_check(key, &type, &owner_endpoint)) == OK) {
|
|
r = ds_retrieve_u32(key, &value);
|
|
if(r != OK) {
|
|
printf("LWIP : ds_event: ds_retrieve_u32 failed\n");
|
|
return;
|
|
}
|
|
|
|
/* Only check for network driver up events. */
|
|
if(strncmp(key, driver_prefix, prefix_len)
|
|
|| value != DS_DRIVER_UP) {
|
|
return;
|
|
}
|
|
|
|
/* The driver label comes after the prefix. */
|
|
label = key + strlen(driver_prefix);
|
|
|
|
/* A driver is (re)started. */
|
|
driver_up(label, owner_endpoint);
|
|
}
|
|
|
|
if(r != ENOENT)
|
|
printf("LWIP : ds_event: ds_check failed: %d\n", r);
|
|
}
|
|
|
|
static void netif_poll_lo(void)
|
|
{
|
|
if (netif_lo == NULL)
|
|
return;
|
|
|
|
while (netif_lo->loop_first)
|
|
netif_poll(netif_lo);
|
|
}
|
|
|
|
int socket_open(devminor_t minor)
|
|
{
|
|
struct sock_ops * ops;
|
|
struct socket * sock;
|
|
int ret = OK;
|
|
|
|
switch (minor) {
|
|
case SOCK_TYPE_TCP:
|
|
ops = &sock_tcp_ops;
|
|
break;
|
|
case SOCK_TYPE_UDP:
|
|
ops = &sock_udp_ops;
|
|
break;
|
|
case SOCK_TYPE_IP:
|
|
ops = &sock_raw_ip_ops;
|
|
break;
|
|
default:
|
|
if (minor - SOCK_TYPES < MAX_DEVS)
|
|
return nic_open(minor - SOCK_TYPES);
|
|
|
|
printf("LWIP unknown socket type %d\n", minor);
|
|
return EINVAL;
|
|
}
|
|
|
|
sock = get_unused_sock();
|
|
if (!sock) {
|
|
printf("LWIP : no free socket\n");
|
|
return EAGAIN;
|
|
}
|
|
|
|
sock->ops = ops;
|
|
sock->select_ep = NONE;
|
|
sock->recv_data_size = 0;
|
|
|
|
if (sock->ops && sock->ops->open)
|
|
ret = sock->ops->open(sock);
|
|
|
|
if (ret == OK) {
|
|
debug_print("new socket %ld", get_sock_num(sock));
|
|
ret = get_sock_num(sock);
|
|
} else {
|
|
debug_print("failed %d", ret);
|
|
/* FIXME: shouldn't sock be freed now? */
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int main(__unused int argc, __unused char ** argv)
|
|
{
|
|
sef_local_startup();
|
|
|
|
for(;;) {
|
|
int err, ipc_status;
|
|
message m;
|
|
|
|
netif_poll_lo();
|
|
|
|
mq_process();
|
|
|
|
if ((err = sef_receive_status(ANY, &m, &ipc_status)) != OK) {
|
|
printf("LWIP : sef_receive_status errr %d\n", err);
|
|
continue;
|
|
}
|
|
|
|
if (m.m_source == VFS_PROC_NR)
|
|
socket_request(&m, ipc_status);
|
|
else if (is_ipc_notify(ipc_status)) {
|
|
switch (m.m_source) {
|
|
case CLOCK:
|
|
expire_timers(m.m_notify.timestamp);
|
|
break;
|
|
case DS_PROC_NR:
|
|
ds_event();
|
|
break;
|
|
case PM_PROC_NR:
|
|
panic("LWIP : unhandled event from PM");
|
|
break;
|
|
default:
|
|
printf("LWIP : unexpected notify from %d\n",
|
|
m.m_source);
|
|
continue;
|
|
}
|
|
} else
|
|
/* all other request can be from drivers only */
|
|
driver_request(&m);
|
|
}
|
|
|
|
return 0;
|
|
}
|