arm: make signal handlers work
[minix.git] / servers / inet / inet.c
blob05314080b55e970de509e57220bdc2171151b55f
1 /* this file contains the interface of the network software with rest of
2 minix. Furthermore it contains the main loop of the network task.
4 Copyright 1995 Philip Homburg
6 The valid messages and their parameters are:
8 from FS:
9 __________________________________________________________________
10 | | | | | | |
11 | m_type | DEVICE | PROC_NR | COUNT | POSITION | ADDRESS |
12 |_______________|___________|_________|_______|__________|_________|
13 | | | | | | |
14 | DEV_OPEN | minor dev | proc nr | mode | | |
15 |_______________|___________|_________|_______|__________|_________|
16 | | | | | | |
17 | DEV_CLOSE | minor dev | proc nr | | | |
18 |_______________|___________|_________|_______|__________|_________|
19 | | | | | | |
20 | DEV_IOCTL_S | minor dev | proc nr | | NWIO.. | address |
21 |_______________|___________|_________|_______|__________|_________|
22 | | | | | | |
23 | DEV_READ_S | minor dev | proc nr | count | | address |
24 |_______________|___________|_________|_______|__________|_________|
25 | | | | | | |
26 | DEV_WRITE_S | minor dev | proc nr | count | | address |
27 |_______________|___________|_________|_______|__________|_________|
28 | | | | | | |
29 | CANCEL | minor dev | proc nr | | | |
30 |_______________|___________|_________|_______|__________|_________|
32 from DL_ETH:
33 (not documented here)
36 #include "inet.h"
38 #define _MINIX_SOURCE 1
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <sys/svrctl.h>
43 #include <minix/ds.h>
44 #include <minix/endpoint.h>
45 #include <minix/chardriver.h>
46 #include <minix/rs.h>
47 #include <sys/types.h>
48 #include <pwd.h>
50 #include "mq.h"
51 #include "qp.h"
52 #include "proto.h"
53 #include "generic/type.h"
55 #include "generic/arp.h"
56 #include "generic/assert.h"
57 #include "generic/buf.h"
58 #include "generic/clock.h"
59 #include "generic/eth.h"
60 #include "generic/event.h"
61 #include "generic/ip.h"
62 #include "generic/psip.h"
63 #include "generic/rand256.h"
64 #include "generic/sr.h"
65 #include "generic/tcp.h"
66 #include "generic/udp.h"
68 THIS_FILE
70 #define RANDOM_DEV_NAME "/dev/random"
72 endpoint_t this_proc; /* Process number of this server. */
74 /* Killing Solaris */
75 int killer_inet= 0;
77 #ifdef BUF_CONSISTENCY_CHECK
78 extern int inet_buf_debug;
79 #endif
81 #if HZ_DYNAMIC
82 u32_t system_hz;
83 #endif
85 static void nw_conf(void);
86 static void nw_init(void);
87 static void ds_event(void);
89 /* SEF functions and variables. */
90 static void sef_local_startup(void);
91 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
93 int main(int argc, char *argv[])
95 mq_t *mq;
96 int ipc_status;
97 int r;
98 endpoint_t source;
99 int m_type;
101 /* SEF local startup. */
102 sef_local_startup();
104 while (TRUE)
106 #ifdef BUF_CONSISTENCY_CHECK
107 if (inet_buf_debug)
109 static int buf_debug_count= 0;
111 if (++buf_debug_count >= inet_buf_debug)
113 buf_debug_count= 0;
114 if (!bf_consistency_check())
115 break;
118 #endif
119 if (ev_head)
121 ev_process();
122 continue;
124 if (clck_call_expire)
126 clck_expire_timers();
127 continue;
129 mq= mq_get();
130 if (!mq)
131 ip_panic(("out of messages"));
133 r= sef_receive_status(ANY, &mq->mq_mess, &ipc_status);
134 if (r<0)
136 ip_panic(("unable to receive: %d", r));
138 reset_time();
139 source= mq->mq_mess.m_source;
140 m_type= mq->mq_mess.m_type;
141 if (source == VFS_PROC_NR)
143 sr_rec(mq);
145 else if (is_ipc_notify(ipc_status))
147 if (source == CLOCK)
149 clck_tick(&mq->mq_mess);
150 mq_free(mq);
152 else if (source == PM_PROC_NR)
154 /* signaled */
155 /* probably SIGTERM */
156 mq_free(mq);
158 else if (source == DS_PROC_NR)
160 /* DS notifies us of an event. */
161 ds_event();
162 mq_free(mq);
164 else
166 printf("inet: got unexpected notify from %d\n",
167 mq->mq_mess.m_source);
168 mq_free(mq);
171 else if (m_type == DL_CONF_REPLY || m_type == DL_TASK_REPLY ||
172 m_type == DL_STAT_REPLY)
174 eth_rec(&mq->mq_mess);
175 mq_free(mq);
177 else
179 printf("inet: got bad message type 0x%x from %d\n",
180 mq->mq_mess.m_type, mq->mq_mess.m_source);
181 mq_free(mq);
184 ip_panic(("task is not allowed to terminate"));
185 return 1;
188 /*===========================================================================*
189 * sef_local_startup *
190 *===========================================================================*/
191 static void sef_local_startup()
193 /* Register init callbacks. */
194 sef_setcb_init_fresh(sef_cb_init_fresh);
195 sef_setcb_init_restart(sef_cb_init_fresh);
197 /* No live update support for now. */
199 /* Let SEF perform startup. */
200 sef_startup();
203 /*===========================================================================*
204 * sef_cb_init_fresh *
205 *===========================================================================*/
206 static int sef_cb_init_fresh(int type, sef_init_info_t *info)
208 /* Initialize the inet server. */
209 int r;
210 int timerand, fd;
211 u8_t randbits[32];
212 struct timeval tv;
213 struct passwd *pw;
215 #if DEBUG
216 printf("Starting inet...\n");
217 printf("%s\n", version);
218 #endif
220 #if HZ_DYNAMIC
221 system_hz = sys_hz();
222 #endif
224 /* Read configuration. */
225 nw_conf();
227 /* Get a random number */
228 timerand= 1;
229 fd= open(RANDOM_DEV_NAME, O_RDONLY | O_NONBLOCK);
230 if (fd != -1)
232 r= read(fd, randbits, sizeof(randbits));
233 if (r == sizeof(randbits))
234 timerand= 0;
235 else
237 printf("inet: unable to read random data from %s: %s\n",
238 RANDOM_DEV_NAME, r == -1 ? strerror(errno) :
239 r == 0 ? "EOF" : "not enough data");
241 close(fd);
243 else
245 printf("inet: unable to open random device %s: %s\n",
246 RANDOM_DEV_NAME, strerror(errno));
248 if (timerand)
250 printf("inet: using current time for random-number seed\n");
251 r= gettimeofday(&tv, NULL);
252 if (r == -1)
254 printf("sysutime failed: %s\n", strerror(errno));
255 exit(1);
257 memcpy(randbits, &tv, sizeof(tv));
259 init_rand256(randbits);
261 /* Our new identity as a server. */
262 this_proc= info->endpoint;
264 #ifdef BUF_CONSISTENCY_CHECK
265 inet_buf_debug= (getenv("inetbufdebug") &&
266 (strcmp(getenv("inetbufdebug"), "on") == 0));
267 inet_buf_debug= 100;
268 if (inet_buf_debug)
270 ip_warning(( "buffer consistency check enabled" ));
272 #endif
274 if (getenv("killerinet"))
276 ip_warning(( "killer inet active" ));
277 killer_inet= 1;
280 nw_init();
282 /* Subscribe to driver events for network drivers. */
283 r = ds_subscribe("drv\\.net\\..*", DSF_INITIAL | DSF_OVERWRITE);
284 if(r != OK) {
285 ip_panic(("inet: can't subscribe to driver events"));
288 /* Drop root privileges */
289 if ((pw = getpwnam(SERVICE_LOGIN)) == NULL) {
290 printf("inet: unable to retrieve uid of SERVICE_LOGIN, "
291 "still running as root");
292 } else if (setuid(pw->pw_uid) != 0) {
293 ip_panic(("inet: unable to drop privileges"));
296 /* Announce we are up. INET announces its presence to VFS just like
297 * any other character driver.
299 chardriver_announce();
301 return(OK);
304 static void nw_conf()
306 read_conf();
307 eth_prep();
308 arp_prep();
309 psip_prep();
310 ip_prep();
311 tcp_prep();
312 udp_prep();
315 static void nw_init()
317 mq_init();
318 bf_init();
319 clck_init();
320 sr_init();
321 qp_init();
322 eth_init();
323 arp_init();
324 psip_init();
325 ip_init();
326 tcp_init();
327 udp_init();
330 /*===========================================================================*
331 * ds_event *
332 *===========================================================================*/
333 static void ds_event()
335 char key[DS_MAX_KEYLEN];
336 char *driver_prefix = "drv.net.";
337 char *label;
338 u32_t value;
339 int type;
340 endpoint_t owner_endpoint;
341 int r;
342 int prefix_len;
344 prefix_len = strlen(driver_prefix);
346 /* We may get one notification for multiple updates from DS. Get events
347 * and owners from DS, until DS tells us that there are no more.
349 while ((r = ds_check(key, &type, &owner_endpoint)) == OK) {
350 r = ds_retrieve_u32(key, &value);
351 if(r != OK) {
352 printf("inet: ds_event: ds_retrieve_u32 failed\n");
353 return;
356 /* Only check for network driver up events. */
357 if(strncmp(key, driver_prefix, prefix_len)
358 || value != DS_DRIVER_UP) {
359 return;
362 /* The driver label comes after the prefix. */
363 label = key + prefix_len;
365 /* A driver is (re)started. */
366 eth_check_driver(label, owner_endpoint);
369 if(r != ENOENT)
370 printf("inet: ds_event: ds_check failed: %d\n", r);
373 void panic0(file, line)
374 char *file;
375 int line;
377 printf("panic at %s, %d: ", file, line);
380 void inet_panic()
382 printf("\ninet stacktrace: ");
383 util_stacktrace();
384 (panic)("aborted due to a panic");
385 for(;;);
388 #if !NDEBUG
389 void bad_assertion(file, line, what)
390 char *file;
391 int line;
392 char *what;
394 panic0(file, line);
395 printf("assertion \"%s\" failed", what);
396 panic();
400 void bad_compare(file, line, lhs, what, rhs)
401 char *file;
402 int line;
403 int lhs;
404 char *what;
405 int rhs;
407 panic0(file, line);
408 printf("compare (%d) %s (%d) failed", lhs, what, rhs);
409 panic();
411 #endif /* !NDEBUG */
414 * $PchId: inet.c,v 1.23 2005/06/28 14:27:22 philip Exp $