xref: /minix3/minix/net/lwip/lwip.c (revision ef8d499e2d2af900e9b2ab297171d7b088652482)
1*ef8d499eSDavid van Moolenbroek /* LWIP service - lwip.c - main program and dispatch code */
2*ef8d499eSDavid van Moolenbroek 
3*ef8d499eSDavid van Moolenbroek #include "lwip.h"
4*ef8d499eSDavid van Moolenbroek #include "tcpisn.h"
5*ef8d499eSDavid van Moolenbroek #include "mcast.h"
6*ef8d499eSDavid van Moolenbroek #include "ethif.h"
7*ef8d499eSDavid van Moolenbroek #include "rtsock.h"
8*ef8d499eSDavid van Moolenbroek #include "route.h"
9*ef8d499eSDavid van Moolenbroek #include "bpfdev.h"
10*ef8d499eSDavid van Moolenbroek 
11*ef8d499eSDavid van Moolenbroek #include "lwip/init.h"
12*ef8d499eSDavid van Moolenbroek #include "lwip/sys.h"
13*ef8d499eSDavid van Moolenbroek #include "lwip/timeouts.h"
14*ef8d499eSDavid van Moolenbroek #include "arch/cc.h"
15*ef8d499eSDavid van Moolenbroek 
16*ef8d499eSDavid van Moolenbroek static int running, recheck_timer;
17*ef8d499eSDavid van Moolenbroek static minix_timer_t lwip_timer;
18*ef8d499eSDavid van Moolenbroek 
19*ef8d499eSDavid van Moolenbroek static void expire_lwip_timer(int);
20*ef8d499eSDavid van Moolenbroek 
21*ef8d499eSDavid van Moolenbroek /*
22*ef8d499eSDavid van Moolenbroek  * Return the system uptime in milliseconds.  Also remember that lwIP retrieved
23*ef8d499eSDavid van Moolenbroek  * the system uptime during this call, so that we know to check for timer
24*ef8d499eSDavid van Moolenbroek  * updates at the end of the current iteration of the message loop.
25*ef8d499eSDavid van Moolenbroek  */
26*ef8d499eSDavid van Moolenbroek uint32_t
sys_now(void)27*ef8d499eSDavid van Moolenbroek sys_now(void)
28*ef8d499eSDavid van Moolenbroek {
29*ef8d499eSDavid van Moolenbroek 
30*ef8d499eSDavid van Moolenbroek 	recheck_timer = TRUE;
31*ef8d499eSDavid van Moolenbroek 
32*ef8d499eSDavid van Moolenbroek 	/* TODO: avoid 64-bit arithmetic if possible. */
33*ef8d499eSDavid van Moolenbroek 	return (uint32_t)(((uint64_t)getticks() * 1000) / sys_hz());
34*ef8d499eSDavid van Moolenbroek }
35*ef8d499eSDavid van Moolenbroek 
36*ef8d499eSDavid van Moolenbroek /*
37*ef8d499eSDavid van Moolenbroek  * Check if and when lwIP has its next timeout, and set or cancel our timer
38*ef8d499eSDavid van Moolenbroek  * accordingly.
39*ef8d499eSDavid van Moolenbroek  */
40*ef8d499eSDavid van Moolenbroek static void
set_lwip_timer(void)41*ef8d499eSDavid van Moolenbroek set_lwip_timer(void)
42*ef8d499eSDavid van Moolenbroek {
43*ef8d499eSDavid van Moolenbroek 	uint32_t next_timeout;
44*ef8d499eSDavid van Moolenbroek 	clock_t ticks;
45*ef8d499eSDavid van Moolenbroek 
46*ef8d499eSDavid van Moolenbroek 	/* Ask lwIP when the next alarm is supposed to go off, if any. */
47*ef8d499eSDavid van Moolenbroek 	next_timeout = sys_timeouts_sleeptime();
48*ef8d499eSDavid van Moolenbroek 
49*ef8d499eSDavid van Moolenbroek 	/*
50*ef8d499eSDavid van Moolenbroek 	 * Set or update the lwIP timer.  We rely on set_timer() asking the
51*ef8d499eSDavid van Moolenbroek 	 * kernel for an alarm only if the timeout is different from the one we
52*ef8d499eSDavid van Moolenbroek 	 * gave it last time (if at all).  However, due to conversions between
53*ef8d499eSDavid van Moolenbroek 	 * absolute and relative times, and the fact that we cannot guarantee
54*ef8d499eSDavid van Moolenbroek 	 * that the uptime itself does not change while executing these
55*ef8d499eSDavid van Moolenbroek 	 * routines, set_timer() will sometimes be issuing a kernel call even
56*ef8d499eSDavid van Moolenbroek 	 * if the alarm has not changed.  Not a huge deal, but fixing this will
57*ef8d499eSDavid van Moolenbroek 	 * require a different interface to lwIP and/or the timers library.
58*ef8d499eSDavid van Moolenbroek 	 */
59*ef8d499eSDavid van Moolenbroek 	if (next_timeout != (uint32_t)-1) {
60*ef8d499eSDavid van Moolenbroek 		/*
61*ef8d499eSDavid van Moolenbroek 		 * Round up the next timeout (which is in milliseconds) to the
62*ef8d499eSDavid van Moolenbroek 		 * number of clock ticks to add to the current time.  Avoid any
63*ef8d499eSDavid van Moolenbroek 		 * potential for overflows, no matter how unrealistic..
64*ef8d499eSDavid van Moolenbroek 		 */
65*ef8d499eSDavid van Moolenbroek 		if (next_timeout > TMRDIFF_MAX / sys_hz())
66*ef8d499eSDavid van Moolenbroek 			ticks = TMRDIFF_MAX;
67*ef8d499eSDavid van Moolenbroek 		else
68*ef8d499eSDavid van Moolenbroek 			ticks = (next_timeout * sys_hz() + 999) / 1000;
69*ef8d499eSDavid van Moolenbroek 
70*ef8d499eSDavid van Moolenbroek 		set_timer(&lwip_timer, ticks, expire_lwip_timer, 0 /*unused*/);
71*ef8d499eSDavid van Moolenbroek 	} else
72*ef8d499eSDavid van Moolenbroek 		cancel_timer(&lwip_timer);	/* not really needed.. */
73*ef8d499eSDavid van Moolenbroek }
74*ef8d499eSDavid van Moolenbroek 
75*ef8d499eSDavid van Moolenbroek /*
76*ef8d499eSDavid van Moolenbroek  * The timer for lwIP timeouts has gone off.  Check timeouts, and possibly set
77*ef8d499eSDavid van Moolenbroek  * a new timer.
78*ef8d499eSDavid van Moolenbroek  */
79*ef8d499eSDavid van Moolenbroek static void
expire_lwip_timer(int arg __unused)80*ef8d499eSDavid van Moolenbroek expire_lwip_timer(int arg __unused)
81*ef8d499eSDavid van Moolenbroek {
82*ef8d499eSDavid van Moolenbroek 
83*ef8d499eSDavid van Moolenbroek 	/* Let lwIP do its work. */
84*ef8d499eSDavid van Moolenbroek 	sys_check_timeouts();
85*ef8d499eSDavid van Moolenbroek 
86*ef8d499eSDavid van Moolenbroek 	/*
87*ef8d499eSDavid van Moolenbroek 	 * See if we have to update our timer for the next lwIP timer.  Doing
88*ef8d499eSDavid van Moolenbroek 	 * this here, rather than from the main loop, avoids one kernel call.
89*ef8d499eSDavid van Moolenbroek 	 */
90*ef8d499eSDavid van Moolenbroek 	set_lwip_timer();
91*ef8d499eSDavid van Moolenbroek 
92*ef8d499eSDavid van Moolenbroek 	recheck_timer = FALSE;
93*ef8d499eSDavid van Moolenbroek }
94*ef8d499eSDavid van Moolenbroek 
95*ef8d499eSDavid van Moolenbroek /*
96*ef8d499eSDavid van Moolenbroek  * Check whether we should adjust our local timer based on a change in the next
97*ef8d499eSDavid van Moolenbroek  * lwIP timeout.
98*ef8d499eSDavid van Moolenbroek  */
99*ef8d499eSDavid van Moolenbroek static void
check_lwip_timer(void)100*ef8d499eSDavid van Moolenbroek check_lwip_timer(void)
101*ef8d499eSDavid van Moolenbroek {
102*ef8d499eSDavid van Moolenbroek 
103*ef8d499eSDavid van Moolenbroek 	/*
104*ef8d499eSDavid van Moolenbroek 	 * We make the assumption that whenever lwIP starts a timer, it will
105*ef8d499eSDavid van Moolenbroek 	 * need to retrieve the current time.  Thus, whenever sys_now() is
106*ef8d499eSDavid van Moolenbroek 	 * called, we set the 'recheck_timer' flag.  Here, we check whether to
107*ef8d499eSDavid van Moolenbroek 	 * (re)set our lwIP timer only if the flag is set.  As a result, we do
108*ef8d499eSDavid van Moolenbroek 	 * not have to mess with timers for literally every incoming message.
109*ef8d499eSDavid van Moolenbroek 	 *
110*ef8d499eSDavid van Moolenbroek 	 * When lwIP stops a timer, it does not call sys_now(), and thus, we
111*ef8d499eSDavid van Moolenbroek 	 * may miss such updates.  However, timers being stopped should be rare
112*ef8d499eSDavid van Moolenbroek 	 * and getting too many alarm messages is not a big deal.
113*ef8d499eSDavid van Moolenbroek 	 */
114*ef8d499eSDavid van Moolenbroek 	if (!recheck_timer)
115*ef8d499eSDavid van Moolenbroek 		return;
116*ef8d499eSDavid van Moolenbroek 
117*ef8d499eSDavid van Moolenbroek 	set_lwip_timer();
118*ef8d499eSDavid van Moolenbroek 
119*ef8d499eSDavid van Moolenbroek 	/* Reset the flag for the next message loop iteration. */
120*ef8d499eSDavid van Moolenbroek 	recheck_timer = FALSE;
121*ef8d499eSDavid van Moolenbroek }
122*ef8d499eSDavid van Moolenbroek 
123*ef8d499eSDavid van Moolenbroek /*
124*ef8d499eSDavid van Moolenbroek  * Return a random number, for use by lwIP.
125*ef8d499eSDavid van Moolenbroek  */
126*ef8d499eSDavid van Moolenbroek uint32_t
lwip_hook_rand(void)127*ef8d499eSDavid van Moolenbroek lwip_hook_rand(void)
128*ef8d499eSDavid van Moolenbroek {
129*ef8d499eSDavid van Moolenbroek 
130*ef8d499eSDavid van Moolenbroek 	/*
131*ef8d499eSDavid van Moolenbroek 	 * The current known uses of this hook are for selection of initial
132*ef8d499eSDavid van Moolenbroek 	 * TCP/UDP port numbers and for multicast-related timer randomness.
133*ef8d499eSDavid van Moolenbroek 	 * The former case exists only to avoid picking the same starting port
134*ef8d499eSDavid van Moolenbroek 	 * numbers after a reboot.  After that, simple sequential iteration of
135*ef8d499eSDavid van Moolenbroek 	 * the port numbers is used.  The latter case varies the response time
136*ef8d499eSDavid van Moolenbroek 	 * for sending multicast messages.  Thus, none of the current uses of
137*ef8d499eSDavid van Moolenbroek 	 * this function require proper randomness, and so we use the simplest
138*ef8d499eSDavid van Moolenbroek 	 * approach, with time-based initialization to cover the reboot case.
139*ef8d499eSDavid van Moolenbroek 	 * The sequential port number selection could be improved upon, but
140*ef8d499eSDavid van Moolenbroek 	 * such an extension would probably bypass this hook anyway.
141*ef8d499eSDavid van Moolenbroek 	 */
142*ef8d499eSDavid van Moolenbroek 	return lrand48();
143*ef8d499eSDavid van Moolenbroek }
144*ef8d499eSDavid van Moolenbroek 
145*ef8d499eSDavid van Moolenbroek /*
146*ef8d499eSDavid van Moolenbroek  * Create a new socket, with the given domain, type, and protocol, for the user
147*ef8d499eSDavid van Moolenbroek  * process identified by 'user_endpt'.  On success, return the new socket's
148*ef8d499eSDavid van Moolenbroek  * identifier, with the libsockevent socket stored in 'sock' and an operations
149*ef8d499eSDavid van Moolenbroek  * table stored in 'ops'.  On failure, return a negative error code.
150*ef8d499eSDavid van Moolenbroek  */
151*ef8d499eSDavid van Moolenbroek static sockid_t
alloc_socket(int domain,int type,int protocol,endpoint_t user_endpt,struct sock ** sock,const struct sockevent_ops ** ops)152*ef8d499eSDavid van Moolenbroek alloc_socket(int domain, int type, int protocol, endpoint_t user_endpt,
153*ef8d499eSDavid van Moolenbroek 	struct sock ** sock, const struct sockevent_ops **ops)
154*ef8d499eSDavid van Moolenbroek {
155*ef8d499eSDavid van Moolenbroek 
156*ef8d499eSDavid van Moolenbroek 	switch (domain) {
157*ef8d499eSDavid van Moolenbroek 	case PF_INET:
158*ef8d499eSDavid van Moolenbroek #ifdef INET6
159*ef8d499eSDavid van Moolenbroek 	case PF_INET6:
160*ef8d499eSDavid van Moolenbroek #endif /* INET6 */
161*ef8d499eSDavid van Moolenbroek 		switch (type) {
162*ef8d499eSDavid van Moolenbroek 		case SOCK_STREAM:
163*ef8d499eSDavid van Moolenbroek 			return tcpsock_socket(domain, protocol, sock, ops);
164*ef8d499eSDavid van Moolenbroek 
165*ef8d499eSDavid van Moolenbroek 		case SOCK_DGRAM:
166*ef8d499eSDavid van Moolenbroek 			return udpsock_socket(domain, protocol, sock, ops);
167*ef8d499eSDavid van Moolenbroek 
168*ef8d499eSDavid van Moolenbroek 		case SOCK_RAW:
169*ef8d499eSDavid van Moolenbroek 			if (!util_is_root(user_endpt))
170*ef8d499eSDavid van Moolenbroek 				return EACCES;
171*ef8d499eSDavid van Moolenbroek 
172*ef8d499eSDavid van Moolenbroek 			return rawsock_socket(domain, protocol, sock, ops);
173*ef8d499eSDavid van Moolenbroek 
174*ef8d499eSDavid van Moolenbroek 		default:
175*ef8d499eSDavid van Moolenbroek 			return EPROTOTYPE;
176*ef8d499eSDavid van Moolenbroek 		}
177*ef8d499eSDavid van Moolenbroek 
178*ef8d499eSDavid van Moolenbroek 	case PF_ROUTE:
179*ef8d499eSDavid van Moolenbroek 		return rtsock_socket(type, protocol, sock, ops);
180*ef8d499eSDavid van Moolenbroek 
181*ef8d499eSDavid van Moolenbroek 	case PF_LINK:
182*ef8d499eSDavid van Moolenbroek 		return lnksock_socket(type, protocol, sock, ops);
183*ef8d499eSDavid van Moolenbroek 
184*ef8d499eSDavid van Moolenbroek 	default:
185*ef8d499eSDavid van Moolenbroek 		/* This means that the service has been misconfigured. */
186*ef8d499eSDavid van Moolenbroek 		printf("socket() with unsupported domain %d\n", domain);
187*ef8d499eSDavid van Moolenbroek 
188*ef8d499eSDavid van Moolenbroek 		return EAFNOSUPPORT;
189*ef8d499eSDavid van Moolenbroek 	}
190*ef8d499eSDavid van Moolenbroek }
191*ef8d499eSDavid van Moolenbroek 
192*ef8d499eSDavid van Moolenbroek /*
193*ef8d499eSDavid van Moolenbroek  * Initialize the service.
194*ef8d499eSDavid van Moolenbroek  */
195*ef8d499eSDavid van Moolenbroek static int
init(int type __unused,sef_init_info_t * init __unused)196*ef8d499eSDavid van Moolenbroek init(int type __unused, sef_init_info_t * init __unused)
197*ef8d499eSDavid van Moolenbroek {
198*ef8d499eSDavid van Moolenbroek 
199*ef8d499eSDavid van Moolenbroek 	/*
200*ef8d499eSDavid van Moolenbroek 	 * Initialize the random number seed.  See the lwip_hook_rand() comment
201*ef8d499eSDavid van Moolenbroek 	 * on why this weak random number source is currently sufficient.
202*ef8d499eSDavid van Moolenbroek 	 */
203*ef8d499eSDavid van Moolenbroek 	srand48(clock_time(NULL));
204*ef8d499eSDavid van Moolenbroek 
205*ef8d499eSDavid van Moolenbroek 	/* Initialize the lwIP library. */
206*ef8d499eSDavid van Moolenbroek 	lwip_init();
207*ef8d499eSDavid van Moolenbroek 
208*ef8d499eSDavid van Moolenbroek 	/* Initialize the socket events library. */
209*ef8d499eSDavid van Moolenbroek 	sockevent_init(alloc_socket);
210*ef8d499eSDavid van Moolenbroek 
211*ef8d499eSDavid van Moolenbroek 	/* Initialize various helper modules. */
212*ef8d499eSDavid van Moolenbroek 	mempool_init();
213*ef8d499eSDavid van Moolenbroek 	tcpisn_init();
214*ef8d499eSDavid van Moolenbroek 	mcast_init();
215*ef8d499eSDavid van Moolenbroek 
216*ef8d499eSDavid van Moolenbroek 	/* Initialize the high-level socket modules. */
217*ef8d499eSDavid van Moolenbroek 	ipsock_init();
218*ef8d499eSDavid van Moolenbroek 	tcpsock_init();
219*ef8d499eSDavid van Moolenbroek 	udpsock_init();
220*ef8d499eSDavid van Moolenbroek 	rawsock_init();
221*ef8d499eSDavid van Moolenbroek 
222*ef8d499eSDavid van Moolenbroek 	/* Initialize the various network interface modules. */
223*ef8d499eSDavid van Moolenbroek 	ifdev_init();
224*ef8d499eSDavid van Moolenbroek 	loopif_init();
225*ef8d499eSDavid van Moolenbroek 	ethif_init();
226*ef8d499eSDavid van Moolenbroek 
227*ef8d499eSDavid van Moolenbroek 	/* Initialize the network device driver module. */
228*ef8d499eSDavid van Moolenbroek 	ndev_init();
229*ef8d499eSDavid van Moolenbroek 
230*ef8d499eSDavid van Moolenbroek 	/* Initialize the low-level socket modules. */
231*ef8d499eSDavid van Moolenbroek 	rtsock_init();
232*ef8d499eSDavid van Moolenbroek 	lnksock_init();
233*ef8d499eSDavid van Moolenbroek 
234*ef8d499eSDavid van Moolenbroek 	/* Initialize the routing module. */
235*ef8d499eSDavid van Moolenbroek 	route_init();
236*ef8d499eSDavid van Moolenbroek 
237*ef8d499eSDavid van Moolenbroek 	/* Initialize other device modules. */
238*ef8d499eSDavid van Moolenbroek 	bpfdev_init();
239*ef8d499eSDavid van Moolenbroek 
240*ef8d499eSDavid van Moolenbroek 	/*
241*ef8d499eSDavid van Moolenbroek 	 * Initialize the MIB module, after all other modules have registered
242*ef8d499eSDavid van Moolenbroek 	 * their subtrees with this module.
243*ef8d499eSDavid van Moolenbroek 	 */
244*ef8d499eSDavid van Moolenbroek 	mibtree_init();
245*ef8d499eSDavid van Moolenbroek 
246*ef8d499eSDavid van Moolenbroek 	/*
247*ef8d499eSDavid van Moolenbroek 	 * After everything else has been initialized, set up the default
248*ef8d499eSDavid van Moolenbroek 	 * configuration - in particular, a loopback interface.
249*ef8d499eSDavid van Moolenbroek 	 */
250*ef8d499eSDavid van Moolenbroek 	ifconf_init();
251*ef8d499eSDavid van Moolenbroek 
252*ef8d499eSDavid van Moolenbroek 	/*
253*ef8d499eSDavid van Moolenbroek 	 * Initialize the master timer for all the lwIP timers.  Just in case
254*ef8d499eSDavid van Moolenbroek 	 * lwIP starts a timer right away, perform a first check upon entry of
255*ef8d499eSDavid van Moolenbroek 	 * the message loop.
256*ef8d499eSDavid van Moolenbroek 	 */
257*ef8d499eSDavid van Moolenbroek 	init_timer(&lwip_timer);
258*ef8d499eSDavid van Moolenbroek 
259*ef8d499eSDavid van Moolenbroek 	recheck_timer = TRUE;
260*ef8d499eSDavid van Moolenbroek 
261*ef8d499eSDavid van Moolenbroek 	running = TRUE;
262*ef8d499eSDavid van Moolenbroek 
263*ef8d499eSDavid van Moolenbroek 	return OK;
264*ef8d499eSDavid van Moolenbroek }
265*ef8d499eSDavid van Moolenbroek 
266*ef8d499eSDavid van Moolenbroek /*
267*ef8d499eSDavid van Moolenbroek  * Perform initialization using the System Event Framework (SEF).
268*ef8d499eSDavid van Moolenbroek  */
269*ef8d499eSDavid van Moolenbroek static void
startup(void)270*ef8d499eSDavid van Moolenbroek startup(void)
271*ef8d499eSDavid van Moolenbroek {
272*ef8d499eSDavid van Moolenbroek 
273*ef8d499eSDavid van Moolenbroek 	sef_setcb_init_fresh(init);
274*ef8d499eSDavid van Moolenbroek 	/*
275*ef8d499eSDavid van Moolenbroek 	 * This service requires stateless restarts, in that several parts of
276*ef8d499eSDavid van Moolenbroek 	 * the system (including VFS and drivers) expect that if restarted,
277*ef8d499eSDavid van Moolenbroek 	 * this service comes back up with a new endpoint.  Therefore, do not
278*ef8d499eSDavid van Moolenbroek 	 * set a _restart callback here.
279*ef8d499eSDavid van Moolenbroek 	 *
280*ef8d499eSDavid van Moolenbroek 	 * TODO: support for live update.
281*ef8d499eSDavid van Moolenbroek 	 *
282*ef8d499eSDavid van Moolenbroek 	 * TODO: support for immediate shutdown if no sockets are in use, as
283*ef8d499eSDavid van Moolenbroek 	 * also done by UDS.  For now, we never shut down immediately, giving
284*ef8d499eSDavid van Moolenbroek 	 * other processes the opportunity to close sockets on system shutdown.
285*ef8d499eSDavid van Moolenbroek 	 */
286*ef8d499eSDavid van Moolenbroek 
287*ef8d499eSDavid van Moolenbroek 	sef_startup();
288*ef8d499eSDavid van Moolenbroek }
289*ef8d499eSDavid van Moolenbroek 
290*ef8d499eSDavid van Moolenbroek /*
291*ef8d499eSDavid van Moolenbroek  * The lwIP-based TCP/IP sockets driver.
292*ef8d499eSDavid van Moolenbroek  */
293*ef8d499eSDavid van Moolenbroek int
main(void)294*ef8d499eSDavid van Moolenbroek main(void)
295*ef8d499eSDavid van Moolenbroek {
296*ef8d499eSDavid van Moolenbroek 	message m;
297*ef8d499eSDavid van Moolenbroek 	int r, ipc_status;
298*ef8d499eSDavid van Moolenbroek 
299*ef8d499eSDavid van Moolenbroek 	startup();
300*ef8d499eSDavid van Moolenbroek 
301*ef8d499eSDavid van Moolenbroek 	while (running) {
302*ef8d499eSDavid van Moolenbroek 		/*
303*ef8d499eSDavid van Moolenbroek 		 * For various reasons, the loopback interface does not pass
304*ef8d499eSDavid van Moolenbroek 		 * packets back into the stack right away.  Instead, it queues
305*ef8d499eSDavid van Moolenbroek 		 * them up for later processing.  We do that processing here.
306*ef8d499eSDavid van Moolenbroek 		 */
307*ef8d499eSDavid van Moolenbroek 		ifdev_poll();
308*ef8d499eSDavid van Moolenbroek 
309*ef8d499eSDavid van Moolenbroek 		/*
310*ef8d499eSDavid van Moolenbroek 		 * Unfortunately, lwIP does not tell us when it starts or stops
311*ef8d499eSDavid van Moolenbroek 		 * timers.  This means that we have to check ourselves every
312*ef8d499eSDavid van Moolenbroek 		 * time we have called into lwIP.  For simplicity, we perform
313*ef8d499eSDavid van Moolenbroek 		 * the check here.
314*ef8d499eSDavid van Moolenbroek 		 */
315*ef8d499eSDavid van Moolenbroek 		check_lwip_timer();
316*ef8d499eSDavid van Moolenbroek 
317*ef8d499eSDavid van Moolenbroek 		if ((r = sef_receive_status(ANY, &m, &ipc_status)) != OK) {
318*ef8d499eSDavid van Moolenbroek 			if (r == EINTR)
319*ef8d499eSDavid van Moolenbroek 				continue;	/* sef_cancel() was called */
320*ef8d499eSDavid van Moolenbroek 
321*ef8d499eSDavid van Moolenbroek 			panic("sef_receive_status failed: %d", r);
322*ef8d499eSDavid van Moolenbroek 		}
323*ef8d499eSDavid van Moolenbroek 
324*ef8d499eSDavid van Moolenbroek 		/* Process the received message. */
325*ef8d499eSDavid van Moolenbroek 		if (is_ipc_notify(ipc_status)) {
326*ef8d499eSDavid van Moolenbroek 			switch (m.m_source) {
327*ef8d499eSDavid van Moolenbroek 			case CLOCK:
328*ef8d499eSDavid van Moolenbroek 				expire_timers(m.m_notify.timestamp);
329*ef8d499eSDavid van Moolenbroek 
330*ef8d499eSDavid van Moolenbroek 				break;
331*ef8d499eSDavid van Moolenbroek 
332*ef8d499eSDavid van Moolenbroek 			case DS_PROC_NR:
333*ef8d499eSDavid van Moolenbroek 				/* Network drivers went up and/or down. */
334*ef8d499eSDavid van Moolenbroek 				ndev_check();
335*ef8d499eSDavid van Moolenbroek 
336*ef8d499eSDavid van Moolenbroek 				break;
337*ef8d499eSDavid van Moolenbroek 
338*ef8d499eSDavid van Moolenbroek 			default:
339*ef8d499eSDavid van Moolenbroek 				printf("unexpected notify from %d\n",
340*ef8d499eSDavid van Moolenbroek 				    m.m_source);
341*ef8d499eSDavid van Moolenbroek 			}
342*ef8d499eSDavid van Moolenbroek 
343*ef8d499eSDavid van Moolenbroek 			continue;
344*ef8d499eSDavid van Moolenbroek 		}
345*ef8d499eSDavid van Moolenbroek 
346*ef8d499eSDavid van Moolenbroek 		switch (m.m_source) {
347*ef8d499eSDavid van Moolenbroek 		case MIB_PROC_NR:
348*ef8d499eSDavid van Moolenbroek 			rmib_process(&m, ipc_status);
349*ef8d499eSDavid van Moolenbroek 
350*ef8d499eSDavid van Moolenbroek 			break;
351*ef8d499eSDavid van Moolenbroek 
352*ef8d499eSDavid van Moolenbroek 		case VFS_PROC_NR:
353*ef8d499eSDavid van Moolenbroek 			/* Is this a socket device request? */
354*ef8d499eSDavid van Moolenbroek 			if (IS_SDEV_RQ(m.m_type)) {
355*ef8d499eSDavid van Moolenbroek 				sockevent_process(&m, ipc_status);
356*ef8d499eSDavid van Moolenbroek 
357*ef8d499eSDavid van Moolenbroek 				break;
358*ef8d499eSDavid van Moolenbroek 			}
359*ef8d499eSDavid van Moolenbroek 
360*ef8d499eSDavid van Moolenbroek 			/* Is this a character (or block) device request? */
361*ef8d499eSDavid van Moolenbroek 			if (IS_CDEV_RQ(m.m_type) || IS_BDEV_RQ(m.m_type)) {
362*ef8d499eSDavid van Moolenbroek 				bpfdev_process(&m, ipc_status);
363*ef8d499eSDavid van Moolenbroek 
364*ef8d499eSDavid van Moolenbroek 				break;
365*ef8d499eSDavid van Moolenbroek 			}
366*ef8d499eSDavid van Moolenbroek 
367*ef8d499eSDavid van Moolenbroek 			/* FALLTHROUGH */
368*ef8d499eSDavid van Moolenbroek 		default:
369*ef8d499eSDavid van Moolenbroek 			/* Is this a network device driver response? */
370*ef8d499eSDavid van Moolenbroek 			if (IS_NDEV_RS(m.m_type)) {
371*ef8d499eSDavid van Moolenbroek 				ndev_process(&m, ipc_status);
372*ef8d499eSDavid van Moolenbroek 
373*ef8d499eSDavid van Moolenbroek 				break;
374*ef8d499eSDavid van Moolenbroek 			}
375*ef8d499eSDavid van Moolenbroek 
376*ef8d499eSDavid van Moolenbroek 			printf("unexpected message %d from %d\n",
377*ef8d499eSDavid van Moolenbroek 			    m.m_type, m.m_source);
378*ef8d499eSDavid van Moolenbroek 		}
379*ef8d499eSDavid van Moolenbroek 	}
380*ef8d499eSDavid van Moolenbroek 
381*ef8d499eSDavid van Moolenbroek 	return 0;
382*ef8d499eSDavid van Moolenbroek }
383