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