Commit | Line | Data |
---|---|---|
059ec3d9 PH |
1 | /* $Cambridge: exim/src/src/os.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */ |
2 | ||
3 | /************************************************* | |
4 | * Exim - an Internet mail transport agent * | |
5 | *************************************************/ | |
6 | ||
7 | /* Copyright (c) University of Cambridge 1995 - 2004 */ | |
8 | /* See the file NOTICE for conditions of use and distribution. */ | |
9 | ||
10 | #ifdef STAND_ALONE | |
11 | #include <signal.h> | |
12 | #include <stdio.h> | |
13 | #include <time.h> | |
14 | #endif | |
15 | ||
16 | /* This source file contains "default" system-dependent functions which | |
17 | provide functionality (or lack of it) in cases where the OS-specific os.c | |
18 | file has not. Some of them are tailored by macros defined in os.h files. */ | |
19 | ||
20 | ||
21 | #ifndef OS_RESTARTING_SIGNAL | |
22 | /************************************************* | |
23 | * Set up restarting signal * | |
24 | *************************************************/ | |
25 | ||
26 | /* This function has the same functionality as the ANSI C signal() function, | |
27 | except that it arranges that, if the signal happens during a system call, the | |
28 | system call gets restarted. (Also, it doesn't return a result.) Different | |
29 | versions of Unix have different defaults, and different ways of setting up a | |
30 | restarting signal handler. If the functionality is not available, the signal | |
31 | should be set to be ignored. This function is used only for catching SIGUSR1. | |
32 | */ | |
33 | ||
34 | void | |
35 | os_restarting_signal(int sig, void (*handler)(int)) | |
36 | { | |
37 | /* Many systems have the SA_RESTART sigaction for specifying that a signal | |
38 | should restart system calls. These include SunOS5, AIX, BSDI, IRIX, FreeBSD, | |
39 | OSF1, Linux and HP-UX 10 (but *not* HP-UX 9). */ | |
40 | ||
41 | #ifdef SA_RESTART | |
42 | struct sigaction act; | |
43 | act.sa_handler = handler; | |
44 | sigemptyset(&(act.sa_mask)); | |
45 | act.sa_flags = SA_RESTART; | |
46 | sigaction(sig, &act, NULL); | |
47 | ||
48 | #ifdef STAND_ALONE | |
49 | printf("Used SA_RESTART\n"); | |
50 | #endif | |
51 | ||
52 | /* SunOS4 and Ultrix default to non-interruptable signals, with SV_INTERRUPT | |
53 | for making them interruptable. This seems to be a dying fashion. */ | |
54 | ||
55 | #elif defined SV_INTERRUPT | |
56 | signal(sig, handler); | |
57 | ||
58 | #ifdef STAND_ALONE | |
59 | printf("Used default signal()\n"); | |
60 | #endif | |
61 | ||
62 | ||
63 | /* If neither SA_RESTART nor SV_INTERRUPT is available we don't know how to | |
64 | set up a restarting signal, so simply suppress the facility. */ | |
65 | ||
66 | #else | |
67 | signal(sig, SIG_IGN); | |
68 | ||
69 | #ifdef STAND_ALONE | |
70 | printf("Used SIG_IGN\n"); | |
71 | #endif | |
72 | ||
73 | #endif | |
74 | } | |
75 | ||
76 | #endif /* OS_RESTARTING_SIGNAL */ | |
77 | ||
78 | ||
79 | #ifndef OS_NON_RESTARTING_SIGNAL | |
80 | /************************************************* | |
81 | * Set up non-restarting signal * | |
82 | *************************************************/ | |
83 | ||
84 | /* This function has the same functionality as the ANSI C signal() function, | |
85 | except that it arranges that, if the signal happens during a system call, the | |
86 | system call gets interrupted. (Also, it doesn't return a result.) Different | |
87 | versions of Unix have different defaults, and different ways of setting up a | |
88 | non-restarting signal handler. For systems for which we don't know what to do, | |
89 | just use the normal signal() function and hope for the best. */ | |
90 | ||
91 | void | |
92 | os_non_restarting_signal(int sig, void (*handler)(int)) | |
93 | { | |
94 | /* Many systems have the SA_RESTART sigaction for specifying that a signal | |
95 | should restart system calls. These include SunOS5, AIX, BSDI, IRIX, FreeBSD, | |
96 | OSF1, Linux and HP-UX 10 (but *not* HP-UX 9). */ | |
97 | ||
98 | #ifdef SA_RESTART | |
99 | struct sigaction act; | |
100 | act.sa_handler = handler; | |
101 | sigemptyset(&(act.sa_mask)); | |
102 | act.sa_flags = 0; | |
103 | sigaction(sig, &act, NULL); | |
104 | ||
105 | #ifdef STAND_ALONE | |
106 | printf("Used sigaction() with flags = 0\n"); | |
107 | #endif | |
108 | ||
109 | /* SunOS4 and Ultrix default to non-interruptable signals, with SV_INTERRUPT | |
110 | for making them interruptable. This seems to be a dying fashion. */ | |
111 | ||
112 | #elif defined SV_INTERRUPT | |
113 | struct sigvec sv; | |
114 | sv.sv_handler = handler; | |
115 | sv.sv_flags = SV_INTERRUPT; | |
116 | sv.sv_mask = -1; | |
117 | sigvec(sig, &sv, NULL); | |
118 | ||
119 | #ifdef STAND_ALONE | |
120 | printf("Used sigvec() with flags = SV_INTERRUPT\n"); | |
121 | #endif | |
122 | ||
123 | /* If neither SA_RESTART nor SV_INTERRUPT is available we don't know how to | |
124 | set up a restarting signal, so just use the standard signal() function. */ | |
125 | ||
126 | #else | |
127 | signal(sig, handler); | |
128 | ||
129 | #ifdef STAND_ALONE | |
130 | printf("Used default signal()\n"); | |
131 | #endif | |
132 | ||
133 | #endif | |
134 | } | |
135 | ||
136 | #endif /* OS_NON_RESTARTING_SIGNAL */ | |
137 | ||
138 | ||
139 | ||
140 | #ifdef STRERROR_FROM_ERRLIST | |
141 | /************************************************* | |
142 | * Provide strerror() for non-ANSI libraries * | |
143 | *************************************************/ | |
144 | ||
145 | /* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror() | |
146 | in their libraries, but can provide the same facility by this simple | |
147 | alternative function. */ | |
148 | ||
149 | char * | |
150 | strerror(int n) | |
151 | { | |
152 | if (n < 0 || n >= sys_nerr) return "unknown error number"; | |
153 | return sys_errlist[n]; | |
154 | } | |
155 | #endif /* STRERROR_FROM_ERRLIST */ | |
156 | ||
157 | ||
158 | ||
159 | #ifndef OS_STRSIGNAL | |
160 | /************************************************* | |
161 | * Provide strsignal() for systems without * | |
162 | *************************************************/ | |
163 | ||
164 | /* Some systems have strsignal() to turn signal numbers into names; others | |
165 | may have other means of doing this. This function is used for those systems | |
166 | that have nothing. It provides a basic translation for the common standard | |
167 | signal numbers. I've been extra cautious with the ifdef's here. Probably more | |
168 | than is necessary... */ | |
169 | ||
170 | char * | |
171 | os_strsignal(int n) | |
172 | { | |
173 | switch (n) | |
174 | { | |
175 | #ifdef SIGHUP | |
176 | case SIGHUP: return "hangup"; | |
177 | #endif | |
178 | ||
179 | #ifdef SIGINT | |
180 | case SIGINT: return "interrupt"; | |
181 | #endif | |
182 | ||
183 | #ifdef SIGQUIT | |
184 | case SIGQUIT: return "quit"; | |
185 | #endif | |
186 | ||
187 | #ifdef SIGILL | |
188 | case SIGILL: return "illegal instruction"; | |
189 | #endif | |
190 | ||
191 | #ifdef SIGTRAP | |
192 | case SIGTRAP: return "trace trap"; | |
193 | #endif | |
194 | ||
195 | #ifdef SIGABRT | |
196 | case SIGABRT: return "abort"; | |
197 | #endif | |
198 | ||
199 | #ifdef SIGEMT | |
200 | case SIGEMT: return "EMT instruction"; | |
201 | #endif | |
202 | ||
203 | #ifdef SIGFPE | |
204 | case SIGFPE: return "arithmetic exception"; | |
205 | #endif | |
206 | ||
207 | #ifdef SIGKILL | |
208 | case SIGKILL: return "killed"; | |
209 | #endif | |
210 | ||
211 | #ifdef SIGBUS | |
212 | case SIGBUS: return "bus error"; | |
213 | #endif | |
214 | ||
215 | #ifdef SIGSEGV | |
216 | case SIGSEGV: return "segmentation fault"; | |
217 | #endif | |
218 | ||
219 | #ifdef SIGSYS | |
220 | case SIGSYS: return "bad system call"; | |
221 | #endif | |
222 | ||
223 | #ifdef SIGPIPE | |
224 | case SIGPIPE: return "broken pipe"; | |
225 | #endif | |
226 | ||
227 | #ifdef SIGALRM | |
228 | case SIGALRM: return "alarm"; | |
229 | #endif | |
230 | ||
231 | #ifdef SIGTERM | |
232 | case SIGTERM: return "terminated"; | |
233 | #endif | |
234 | ||
235 | #ifdef SIGUSR1 | |
236 | case SIGUSR1: return "user signal 1"; | |
237 | #endif | |
238 | ||
239 | #ifdef SIGUSR2 | |
240 | case SIGUSR2: return "user signal 2"; | |
241 | #endif | |
242 | ||
243 | #ifdef SIGCHLD | |
244 | case SIGCHLD: return "child stop or exit"; | |
245 | #endif | |
246 | ||
247 | #ifdef SIGPWR | |
248 | case SIGPWR: return "power fail/restart"; | |
249 | #endif | |
250 | ||
251 | #ifdef SIGURG | |
252 | case SIGURG: return "urgent condition on I/O channel"; | |
253 | #endif | |
254 | ||
255 | #ifdef SIGSTOP | |
256 | case SIGSTOP: return "stop"; | |
257 | #endif | |
258 | ||
259 | #ifdef SIGTSTP | |
260 | case SIGTSTP: return "stop from tty"; | |
261 | #endif | |
262 | ||
263 | #ifdef SIGXCPU | |
264 | case SIGXCPU: return "exceeded CPU limit"; | |
265 | #endif | |
266 | ||
267 | #ifdef SIGXFSZ | |
268 | case SIGXFSZ: return "exceeded file size limit"; | |
269 | #endif | |
270 | ||
271 | default: return "unrecognized signal number"; | |
272 | } | |
273 | } | |
274 | #endif /* OS_STRSIGNAL */ | |
275 | ||
276 | ||
277 | ||
278 | #ifndef OS_STREXIT | |
279 | /************************************************* | |
280 | * Provide strexit() for systems without * | |
281 | *************************************************/ | |
282 | ||
283 | /* Actually, I don't know of any system that has a strexit() function to turn | |
284 | exit codes into text, but this function is implemented this way so that if any | |
285 | OS does have such a thing, it could be used instead of this build-in one. */ | |
286 | ||
287 | char * | |
288 | os_strexit(int n) | |
289 | { | |
290 | switch (n) | |
291 | { | |
292 | /* On systems without sysexits.h we can assume only those exit codes | |
293 | that are given a default value in exim.h. */ | |
294 | ||
295 | #ifndef NO_SYSEXITS | |
296 | case EX_USAGE: return "(could mean usage or syntax error)"; | |
297 | case EX_DATAERR: return "(could mean error in input data)"; | |
298 | case EX_NOINPUT: return "(could mean input data missing)"; | |
299 | case EX_NOUSER: return "(could mean user nonexistent)"; | |
300 | case EX_NOHOST: return "(could mean host nonexistent)"; | |
301 | case EX_SOFTWARE: return "(could mean internal software error)"; | |
302 | case EX_OSERR: return "(could mean internal operating system error)"; | |
303 | case EX_OSFILE: return "(could mean system file missing)"; | |
304 | case EX_IOERR: return "(could mean input/output error)"; | |
305 | case EX_PROTOCOL: return "(could mean protocol error)"; | |
306 | case EX_NOPERM: return "(could mean permission denied)"; | |
307 | #endif | |
308 | ||
309 | case EX_EXECFAILED: return "(could mean unable to exec or command does not exist)"; | |
310 | case EX_UNAVAILABLE: return "(could mean service or program unavailable)"; | |
311 | case EX_CANTCREAT: return "(could mean can't create output file)"; | |
312 | case EX_TEMPFAIL: return "(could mean temporary error)"; | |
313 | case EX_CONFIG: return "(could mean configuration error)"; | |
314 | default: return ""; | |
315 | } | |
316 | } | |
317 | #endif /* OS_STREXIT */ | |
318 | ||
319 | ||
320 | ||
321 | ||
322 | /*********************************************************** | |
323 | * Load average function * | |
324 | ***********************************************************/ | |
325 | ||
326 | /* Although every Unix seems to have a different way of getting the load | |
327 | average, a number of them have things in common. Some common variants are | |
328 | provided below, but if an OS has unique requirements it can be handled in | |
329 | a specific os.c file. What is required is a function called os_getloadavg | |
330 | which takes no arguments and passes back the load average * 1000 as an int, | |
331 | or -1 if no data is available. */ | |
332 | ||
333 | ||
334 | /* ----------------------------------------------------------------------- */ | |
335 | /* If the OS has got a BSD getloadavg() function, life is very easy. */ | |
336 | ||
337 | #if !defined(OS_LOAD_AVERAGE) && defined(HAVE_BSD_GETLOADAVG) | |
338 | #define OS_LOAD_AVERAGE | |
339 | ||
340 | int | |
341 | os_getloadavg(void) | |
342 | { | |
343 | double avg; | |
344 | int loads = getloadavg (&avg, 1); | |
345 | if (loads != 1) return -1; | |
346 | return (int)(avg * 1000.0); | |
347 | } | |
348 | #endif | |
349 | /* ----------------------------------------------------------------------- */ | |
350 | ||
351 | ||
352 | ||
353 | /* ----------------------------------------------------------------------- */ | |
354 | /* Only SunOS5 has the kstat functions as far as I know, but put the code | |
355 | here as there is the -hal variant, and other systems might follow this road one | |
356 | day. */ | |
357 | ||
358 | #if !defined(OS_LOAD_AVERAGE) && defined(HAVE_KSTAT) | |
359 | #define OS_LOAD_AVERAGE | |
360 | ||
361 | #include <kstat.h> | |
362 | ||
363 | int | |
364 | os_getloadavg(void) | |
365 | { | |
366 | int avg; | |
367 | kstat_ctl_t *kc; | |
368 | kstat_t *ksp; | |
369 | kstat_named_t *kn; | |
370 | ||
371 | if ((kc = kstat_open()) == NULL || | |
372 | (ksp = kstat_lookup(kc, LOAD_AVG_KSTAT_MODULE, 0, LOAD_AVG_KSTAT)) | |
373 | == NULL || | |
374 | kstat_read(kc, ksp, NULL) < 0 || | |
375 | (kn = kstat_data_lookup(ksp, LOAD_AVG_SYMBOL)) == NULL) | |
376 | return -1; | |
377 | ||
378 | avg = (int)(((double)(kn->LOAD_AVG_FIELD)/FSCALE) * 1000.0); | |
379 | ||
380 | kstat_close(kc); | |
381 | return avg; | |
382 | } | |
383 | ||
384 | #endif | |
385 | /* ----------------------------------------------------------------------- */ | |
386 | ||
387 | ||
388 | ||
389 | /* ----------------------------------------------------------------------- */ | |
390 | /* Handle OS where a kernel symbol has to be read from /dev/kmem */ | |
391 | ||
392 | #if !defined(OS_LOAD_AVERAGE) && defined(HAVE_DEV_KMEM) | |
393 | #define OS_LOAD_AVERAGE | |
394 | ||
395 | #include <nlist.h> | |
396 | ||
397 | static int avg_kd = -1; | |
398 | static long avg_offset; | |
399 | ||
400 | int | |
401 | os_getloadavg(void) | |
402 | { | |
403 | LOAD_AVG_TYPE avg; | |
404 | ||
405 | if (avg_kd < 0) | |
406 | { | |
407 | struct nlist nl[2]; | |
408 | nl[0].n_name = LOAD_AVG_SYMBOL; | |
409 | nl[1].n_name = ""; | |
410 | nlist (KERNEL_PATH, nl); | |
411 | avg_offset = (long)nl[0].n_value; | |
412 | avg_kd = open ("/dev/kmem", 0); | |
413 | if (avg_kd < 0) return -1; | |
414 | (void) fcntl(avg_kd, F_SETFD, FD_CLOEXEC); | |
415 | } | |
416 | ||
417 | if (lseek (avg_kd, avg_offset, 0) == -1L | |
418 | || read (avg_kd, (char *)(&avg), sizeof (avg)) != sizeof(avg)) | |
419 | return -1; | |
420 | ||
421 | return (int)(((double)avg/FSCALE)*1000.0); | |
422 | } | |
423 | ||
424 | #endif | |
425 | /* ----------------------------------------------------------------------- */ | |
426 | ||
427 | ||
428 | ||
429 | /* ----------------------------------------------------------------------- */ | |
430 | /* If nothing is known about this OS, then the load average facility is | |
431 | not available. */ | |
432 | ||
433 | #ifndef OS_LOAD_AVERAGE | |
434 | ||
435 | int | |
436 | os_getloadavg(void) | |
437 | { | |
438 | return -1; | |
439 | } | |
440 | ||
441 | #endif | |
442 | ||
443 | /* ----------------------------------------------------------------------- */ | |
444 | ||
445 | ||
446 | ||
447 | #if !defined FIND_RUNNING_INTERFACES | |
448 | /************************************************* | |
449 | * Find all the running network interfaces * | |
450 | *************************************************/ | |
451 | ||
452 | /* Finding all the running interfaces is something that has os-dependent | |
453 | tweaks, even in the IPv4 case, and it gets worse for IPv6, which is why this | |
454 | code is now in the os-dependent source file. There is a common function which | |
455 | works on most OS (except IRIX) for IPv4 interfaces, and, with some variations | |
456 | controlled by macros, on at least one OS for IPv6 and IPv4 interfaces. On Linux | |
457 | with IPv6, the common function is used for the IPv4 interfaces and additional | |
458 | code used for IPv6. Consequently, the real function is called | |
459 | os_common_find_running_interfaces() so that it can be called from the Linux | |
460 | function. On non-Linux systems, the macro for os_find_running_interfaces just | |
461 | calls the common function; on Linux it calls the Linux function. | |
462 | ||
463 | This function finds the addresses of all the running interfaces on the machine. | |
464 | A chain of blocks containing the textual form of the addresses is returned. | |
465 | ||
466 | Problems: | |
467 | ||
468 | (1) Solaris 2 has the SIOGIFNUM call to get the number of interfaces, but | |
469 | other OS (including Solaris 1) appear not to. So just screw in a largeish | |
470 | fixed number, defined by MAX_INTERFACES. This is in the config.h file and | |
471 | can be changed in Local/Makefile. Unfortunately, the www addressing scheme | |
472 | means that some hosts have a very large number of virtual interfaces. Such | |
473 | hosts are recommended to set local_interfaces to avoid problems with this. | |
474 | ||
475 | (2) If the standard code is run on IRIX, it does not return any alias | |
476 | interfaces. There is special purpose code for that operating system, which | |
477 | uses the sysctl() function. The code is in OS/os.c-IRIX, and this code isn't | |
478 | used on that OS. | |
479 | ||
480 | (3) Some experimental/developing OS (e.g. GNU/Hurd) do not have any means | |
481 | of finding the interfaces. If NO_FIND_INTERFACES is set, a fudge-up is used | |
482 | instead. | |
483 | ||
484 | (4) Some operating systems set the IP address in what SIOCGIFCONF returns; | |
485 | others do not, and require SIOCGIFADDR to be called to get it. For most of | |
486 | the former, calling the latter does no harm, but it causes grief on Linux and | |
487 | BSD systems in the case of IP aliasing, so a means of cutting it out is | |
488 | provided. | |
489 | ||
490 | Arguments: none | |
491 | Returns: a chain of ip_address_items, each pointing to a textual | |
492 | version of an IP address, with the port field set to zero | |
493 | */ | |
494 | ||
495 | ||
496 | #ifndef NO_FIND_INTERFACES | |
497 | ||
498 | /* If there is IPv6 support, and SIOCGLIFCONF is defined, define macros to | |
499 | use these new, longer versions of the old IPv4 interfaces. Otherwise, define | |
500 | the macros to use the historical versions. */ | |
501 | ||
502 | #if HAVE_IPV6 && defined SIOCGLIFCONF | |
503 | #define V_ifconf lifconf | |
504 | #define V_ifreq lifreq | |
505 | #define V_GIFADDR SIOCGLIFADDR | |
506 | #define V_GIFCONF SIOCGLIFCONF | |
507 | #define V_GIFFLAGS SIOCGLIFFLAGS | |
508 | #define V_ifc_buf lifc_buf | |
509 | #define V_ifc_family lifc_family | |
510 | #define V_ifc_flags lifc_flags | |
511 | #define V_ifc_len lifc_len | |
512 | #define V_ifr_addr lifr_addr | |
513 | #define V_ifr_flags lifr_flags | |
514 | #define V_ifr_name lifr_name | |
515 | #define V_FAMILY_QUERY AF_UNSPEC | |
516 | #define V_family ss_family | |
517 | #else | |
518 | #define V_ifconf ifconf | |
519 | #define V_ifreq ifreq | |
520 | #define V_GIFADDR SIOCGIFADDR | |
521 | #define V_GIFCONF SIOCGIFCONF | |
522 | #define V_GIFFLAGS SIOCGIFFLAGS | |
523 | #define V_ifc_buf ifc_buf | |
524 | #define V_ifc_family ifc_family | |
525 | #define V_ifc_flags ifc_flags | |
526 | #define V_ifc_len ifc_len | |
527 | #define V_ifr_addr ifr_addr | |
528 | #define V_ifr_flags ifr_flags | |
529 | #define V_ifr_name ifr_name | |
530 | #define V_family sa_family | |
531 | #endif | |
532 | ||
533 | /* In all cases of IPv6 support, use an IPv6 socket. Otherwise (at least on | |
534 | Solaris 8) the call to read the flags doesn't work for IPv6 interfaces. If | |
535 | we find we can't actually make an IPv6 socket, the code will revert to trying | |
536 | an IPv4 socket. */ | |
537 | ||
538 | #if HAVE_IPV6 | |
539 | #define FAMILY AF_INET6 | |
540 | #else | |
541 | #define FAMILY AF_INET | |
542 | #endif | |
543 | ||
544 | /* OK, after all that preliminary stuff, here's the code. */ | |
545 | ||
546 | ip_address_item * | |
547 | os_common_find_running_interfaces(void) | |
548 | { | |
549 | struct V_ifconf ifc; | |
550 | struct V_ifreq ifreq; | |
551 | int vs; | |
552 | ip_address_item *yield = NULL; | |
553 | ip_address_item *last = NULL; | |
554 | ip_address_item *next; | |
555 | char *cp; | |
556 | char buf[MAX_INTERFACES*sizeof(struct V_ifreq)]; | |
557 | struct sockaddr *addrp; | |
558 | size_t len = 0; | |
559 | char addrbuf[256]; | |
560 | ||
561 | /* We have to create a socket in order to do ioctls on it to find out | |
562 | what we want to know. */ | |
563 | ||
564 | if ((vs = socket(FAMILY, SOCK_DGRAM, 0)) < 0) | |
565 | { | |
566 | #if HAVE_IPV6 | |
567 | DEBUG(D_interface) | |
568 | debug_printf("Unable to create IPv6 socket to find interface addresses:\n " | |
569 | "error %d %s\nTrying for an IPv4 socket\n", errno, strerror(errno)); | |
570 | vs = socket(AF_INET, SOCK_DGRAM, 0); | |
571 | if (vs < 0) | |
572 | #endif | |
573 | log_write(0, LOG_PANIC_DIE, "Unable to create IPv4 socket to find interface " | |
574 | "addresses: %d %s", errno, strerror(errno)); | |
575 | } | |
576 | ||
577 | /* Get the interface configuration. Some additional data is required when the | |
578 | new structures are in use. */ | |
579 | ||
580 | ifc.V_ifc_len = sizeof(buf); | |
581 | ifc.V_ifc_buf = buf; | |
582 | ||
583 | #ifdef V_FAMILY_QUERY | |
584 | ifc.V_ifc_family = V_FAMILY_QUERY; | |
585 | ifc.V_ifc_flags = 0; | |
586 | #endif | |
587 | ||
588 | if (ioctl(vs, V_GIFCONF, (char *)&ifc) < 0) | |
589 | log_write(0, LOG_PANIC_DIE, "Unable to get interface configuration: %d %s", | |
590 | errno, strerror(errno)); | |
591 | ||
592 | /* If the buffer is big enough, the ioctl sets the value of ifc.V_ifc_len to | |
593 | the amount actually used. If the buffer isn't big enough, at least on some | |
594 | operating systems, ifc.V_ifc_len still gets set to correspond to the total | |
595 | number of interfaces, even though they don't all fit in the buffer. */ | |
596 | ||
597 | if (ifc.V_ifc_len > sizeof(buf)) | |
598 | { | |
599 | ifc.V_ifc_len = sizeof(buf); | |
600 | DEBUG(D_interface) | |
601 | debug_printf("more than %d interfaces found: remainder not used\n" | |
602 | "(set MAX_INTERFACES in Local/Makefile and rebuild if you want more)\n", | |
603 | MAX_INTERFACES); | |
604 | } | |
605 | ||
606 | /* For each interface, check it is an IP interface, get its flags, and see if | |
607 | it is up; if not, skip. | |
608 | ||
609 | BSD systems differ from others in what SIOCGIFCONF returns. Other systems | |
610 | return a vector of ifreq structures whose size is as defined by the structure. | |
611 | BSD systems allow sockaddrs to be longer than their sizeof, which in turn makes | |
612 | the ifreq structures longer than their sizeof. The code below has its origins | |
613 | in amd and ifconfig; it uses the sa_len field of each sockaddr to determine | |
614 | each item's length. | |
615 | ||
616 | This is complicated by the fact that, at least on BSD systems, the data in the | |
617 | buffer is not guaranteed to be aligned. Thus, we must first copy the basic | |
618 | struct to some aligned memory before looking at the field in the fixed part to | |
619 | find its length, and then recopy the correct length. */ | |
620 | ||
621 | for (cp = buf; cp < buf + ifc.V_ifc_len; cp += len) | |
622 | { | |
623 | memcpy((char *)&ifreq, cp, sizeof(ifreq)); | |
624 | ||
625 | #ifndef HAVE_SA_LEN | |
626 | len = sizeof(struct V_ifreq); | |
627 | ||
628 | #else | |
629 | len = ((ifreq.ifr_addr.sa_len > sizeof(ifreq.ifr_addr))? | |
630 | ifreq.ifr_addr.sa_len : sizeof(ifreq.ifr_addr)) + | |
631 | sizeof(ifreq.V_ifr_name); | |
632 | if (len > sizeof(addrbuf)) | |
633 | log_write(0, LOG_PANIC_DIE, "Address for %s interface is absurdly long", | |
634 | ifreq.V_ifr_name); | |
635 | ||
636 | #endif | |
637 | ||
638 | /* If not an IP interface, skip */ | |
639 | ||
640 | if (ifreq.V_ifr_addr.V_family != AF_INET | |
641 | #if HAVE_IPV6 | |
642 | && ifreq.V_ifr_addr.V_family != AF_INET6 | |
643 | #endif | |
644 | ) continue; | |
645 | ||
646 | /* Get the interface flags, and if the interface is down, continue. Formerly, | |
647 | we treated the inability to get the flags as a panic-die error. However, it | |
648 | seems that on some OS (Solaris 9 being the case noted), it is possible to | |
649 | have an interface in this list for which this call fails because the | |
650 | interface hasn't been "plumbed" to any protocol (IPv4 or IPv6). Therefore, | |
651 | we now just treat this case as "down" as well. */ | |
652 | ||
653 | if (ioctl(vs, V_GIFFLAGS, (char *)&ifreq) < 0) | |
654 | { | |
655 | continue; | |
656 | /************* | |
657 | log_write(0, LOG_PANIC_DIE, "Unable to get flags for %s interface: %d %s", | |
658 | ifreq.V_ifr_name, errno, strerror(errno)); | |
659 | *************/ | |
660 | } | |
661 | if ((ifreq.V_ifr_flags & IFF_UP) == 0) continue; | |
662 | ||
663 | /* On some operating systems we have to get the IP address of the interface | |
664 | by another call. On others, it's already there, but we must reinstate the | |
665 | data in ifreq, because SIOCGIFFLAGS may wreck it. */ | |
666 | ||
667 | #ifndef SIOCGIFCONF_GIVES_ADDR | |
668 | if (ioctl(vs, V_GIFADDR, (char *)&ifreq) < 0) | |
669 | log_write(0, LOG_PANIC_DIE, "Unable to get IP address for %s interface: " | |
670 | "%d %s", ifreq.V_ifr_name, errno, strerror(errno)); | |
671 | addrp = &ifreq.V_ifr_addr; | |
672 | ||
673 | #else | |
674 | memcpy((char *)&ifreq, cp, sizeof(ifreq)); | |
675 | memcpy(addrbuf, (char *)&(ifreq.V_ifr_addr), len - sizeof(ifreq.V_ifr_name)); | |
676 | addrp = (struct sockaddr *)addrbuf; | |
677 | #endif | |
678 | ||
679 | /* Create a data block for the address, fill in the data, and put it on the | |
680 | chain. */ | |
681 | ||
682 | next = store_get(sizeof(ip_address_item)); | |
683 | next->next = NULL; | |
684 | next->port = 0; | |
685 | (void)host_ntoa(-1, addrp, next->address, NULL); | |
686 | ||
687 | if (yield == NULL) yield = last = next; else | |
688 | { | |
689 | last->next = next; | |
690 | last = next; | |
691 | } | |
692 | ||
693 | DEBUG(D_interface) debug_printf("Actual local interface address is %s (%s)\n", | |
694 | last->address, ifreq.V_ifr_name); | |
695 | } | |
696 | ||
697 | /* Close the socket, and return the chain of data blocks. */ | |
698 | ||
699 | close(vs); | |
700 | return yield; | |
701 | } | |
702 | ||
703 | #else /* NO_FIND_INTERFACES */ | |
704 | ||
705 | /* Some experimental or developing OS (e.g. GNU/Hurd) do not have the ioctls, | |
706 | and there is no other way to get a list of the (IP addresses of) local | |
707 | interfaces. We just return the loopback address(es). */ | |
708 | ||
709 | ip_address_item * | |
710 | os_common_find_running_interfaces(void) | |
711 | { | |
712 | ip_address_item *yield = store_get(sizeof(address_item)); | |
713 | yield->address = US"127.0.0.1"; | |
714 | yield->port = 0; | |
715 | yield->next = NULL; | |
716 | ||
717 | #if HAVE_IPV6 | |
718 | yield->next = store_get(sizeof(address_item)); | |
719 | yield->next->address = US"::1"; | |
720 | yield->next->port = 0; | |
721 | yield->next->next = NULL; | |
722 | #endif | |
723 | ||
724 | DEBUG(D_interface) debug_printf("Unable to find local interface addresses " | |
725 | "on this OS: returning loopback address(es)\n"); | |
726 | return yield; | |
727 | } | |
728 | ||
729 | #endif /* NO_FIND_INTERFACES */ | |
730 | #endif /* FIND_RUNNING_INTERFACES */ | |
731 | ||
732 | ||
733 | ||
734 | ||
735 | ||
736 | /************************************************* | |
737 | ************************************************** | |
738 | * Stand-alone test program * | |
739 | ************************************************** | |
740 | *************************************************/ | |
741 | ||
742 | ||
743 | #ifdef STAND_ALONE | |
744 | ||
745 | #ifdef CLOCKS_PER_SEC | |
746 | #define REAL_CLOCK_TICK CLOCKS_PER_SEC | |
747 | #else | |
748 | #ifdef CLK_TCK | |
749 | #define REAL_CLOCK_TICK CLK_TCK | |
750 | #else | |
751 | #define REAL_CLOCK_TICK 1000000 /* SunOS4 */ | |
752 | #endif | |
753 | #endif | |
754 | ||
755 | ||
756 | int main(int argc, char **argv) | |
757 | { | |
758 | char buffer[128]; | |
759 | int fd = fileno(stdin); | |
760 | int rc; | |
761 | ||
762 | printf("Testing restarting signal; wait for handler message, then type a line\n"); | |
763 | strcpy(buffer, "*** default ***\n"); | |
764 | os_restarting_signal(SIGALRM, sigalrm_handler); | |
765 | alarm(2); | |
766 | if ((rc = read(fd, buffer, sizeof(buffer))) < 0) | |
767 | printf("No data read\n"); | |
768 | else | |
769 | { | |
770 | buffer[rc] = 0; | |
771 | printf("Read: %s", buffer); | |
772 | } | |
773 | alarm(0); | |
774 | ||
775 | printf("Testing non-restarting signal; should read no data after handler message\n"); | |
776 | strcpy(buffer, "*** default ***\n"); | |
777 | os_non_restarting_signal(SIGALRM, sigalrm_handler); | |
778 | alarm(2); | |
779 | if ((rc = read(fd, buffer, sizeof(buffer))) < 0) | |
780 | printf("No data read\n"); | |
781 | else | |
782 | { | |
783 | buffer[rc] = 0; | |
784 | printf("Read: %s", buffer); | |
785 | } | |
786 | alarm(0); | |
787 | ||
788 | printf("Testing load averages (last test - ^C to kill)\n"); | |
789 | for (;;) | |
790 | { | |
791 | int avg; | |
792 | clock_t used; | |
793 | clock_t before = clock(); | |
794 | avg = os_getloadavg(); | |
795 | used = clock() - before; | |
796 | printf("cpu time = %.2f ", (double)used/REAL_CLOCK_TICK); | |
797 | if (avg < 0) | |
798 | { | |
799 | printf("load average not available\n"); | |
800 | break; | |
801 | } | |
802 | printf("load average = %.2f\n", (double)avg/1000.0); | |
803 | sleep(2); | |
804 | } | |
805 | return 0; | |
806 | } | |
807 | ||
808 | #endif | |
809 | ||
810 | /* End of os.c */ |