Commit | Line | Data |
---|---|---|
0a49a7a4 | 1 | /* $Cambridge: exim/src/src/os.c,v 1.8 2009/11/16 19:50:37 nm4 Exp $ */ |
059ec3d9 PH |
2 | |
3 | /************************************************* | |
4 | * Exim - an Internet mail transport agent * | |
5 | *************************************************/ | |
6 | ||
0a49a7a4 | 7 | /* Copyright (c) University of Cambridge 1995 - 2009 */ |
059ec3d9 PH |
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 | ||
1ba28e2b PP |
170 | const char * |
171 | os_strsignal(const int n) | |
059ec3d9 PH |
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 | ||
1ba28e2b PP |
287 | const char * |
288 | os_strexit(const int n) | |
059ec3d9 PH |
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 | ||
92f9ced0 NM |
466 | getifaddrs() provides a sane consistent way to query this on modern OSs, |
467 | otherwise fall back to a maze of twisty ioctl() calls | |
468 | ||
469 | Arguments: none | |
470 | Returns: a chain of ip_address_items, each pointing to a textual | |
471 | version of an IP address, with the port field set to zero | |
472 | */ | |
473 | ||
474 | ||
475 | #ifndef NO_FIND_INTERFACES | |
476 | ||
477 | #ifdef HAVE_GETIFADDRS | |
478 | ||
479 | #include <ifaddrs.h> | |
480 | ||
481 | ip_address_item * | |
482 | os_common_find_running_interfaces(void) | |
483 | { | |
484 | struct ifaddrs *ifalist = NULL; | |
485 | ip_address_item *yield = NULL; | |
486 | ip_address_item *last = NULL; | |
487 | ip_address_item *next; | |
488 | ||
489 | if (getifaddrs(&ifalist) != 0) | |
490 | log_write(0, LOG_PANIC_DIE, "Unable to call getifaddrs: %d %s", | |
491 | errno, strerror(errno)); | |
492 | ||
493 | struct ifaddrs *ifa; | |
494 | for (ifa = ifalist; ifa != NULL; ifa = ifa->ifa_next) | |
495 | { | |
496 | if (ifa->ifa_addr->sa_family != AF_INET | |
497 | #if HAVE_IPV6 | |
498 | && ifa->ifa_addr->sa_family != AF_INET6 | |
499 | #endif /* HAVE_IPV6 */ | |
500 | ) | |
501 | continue; | |
502 | ||
503 | if ( !(ifa->ifa_flags & IFF_UP) ) /* Only want 'UP' interfaces */ | |
504 | continue; | |
505 | ||
506 | /* Create a data block for the address, fill in the data, and put it on the | |
507 | chain. */ | |
508 | ||
509 | next = store_get(sizeof(ip_address_item)); | |
510 | next->next = NULL; | |
511 | next->port = 0; | |
512 | (void)host_ntoa(-1, ifa->ifa_addr, next->address, NULL); | |
513 | ||
514 | if (yield == NULL) | |
515 | yield = last = next; | |
516 | else | |
517 | { | |
518 | last->next = next; | |
519 | last = next; | |
520 | } | |
521 | ||
522 | DEBUG(D_interface) debug_printf("Actual local interface address is %s (%s)\n", | |
523 | last->address, ifa->ifa_name); | |
524 | } | |
525 | ||
526 | /* free the list of addresses, and return the chain of data blocks. */ | |
527 | ||
528 | freeifaddrs (ifalist); | |
529 | return yield; | |
530 | } | |
531 | ||
532 | #else /* HAVE_GETIFADDRS */ | |
533 | ||
534 | /* | |
059ec3d9 PH |
535 | Problems: |
536 | ||
537 | (1) Solaris 2 has the SIOGIFNUM call to get the number of interfaces, but | |
538 | other OS (including Solaris 1) appear not to. So just screw in a largeish | |
539 | fixed number, defined by MAX_INTERFACES. This is in the config.h file and | |
540 | can be changed in Local/Makefile. Unfortunately, the www addressing scheme | |
541 | means that some hosts have a very large number of virtual interfaces. Such | |
542 | hosts are recommended to set local_interfaces to avoid problems with this. | |
543 | ||
544 | (2) If the standard code is run on IRIX, it does not return any alias | |
545 | interfaces. There is special purpose code for that operating system, which | |
546 | uses the sysctl() function. The code is in OS/os.c-IRIX, and this code isn't | |
547 | used on that OS. | |
548 | ||
549 | (3) Some experimental/developing OS (e.g. GNU/Hurd) do not have any means | |
550 | of finding the interfaces. If NO_FIND_INTERFACES is set, a fudge-up is used | |
551 | instead. | |
552 | ||
553 | (4) Some operating systems set the IP address in what SIOCGIFCONF returns; | |
554 | others do not, and require SIOCGIFADDR to be called to get it. For most of | |
555 | the former, calling the latter does no harm, but it causes grief on Linux and | |
556 | BSD systems in the case of IP aliasing, so a means of cutting it out is | |
557 | provided. | |
059ec3d9 PH |
558 | */ |
559 | ||
059ec3d9 PH |
560 | /* If there is IPv6 support, and SIOCGLIFCONF is defined, define macros to |
561 | use these new, longer versions of the old IPv4 interfaces. Otherwise, define | |
562 | the macros to use the historical versions. */ | |
563 | ||
564 | #if HAVE_IPV6 && defined SIOCGLIFCONF | |
565 | #define V_ifconf lifconf | |
566 | #define V_ifreq lifreq | |
567 | #define V_GIFADDR SIOCGLIFADDR | |
568 | #define V_GIFCONF SIOCGLIFCONF | |
569 | #define V_GIFFLAGS SIOCGLIFFLAGS | |
570 | #define V_ifc_buf lifc_buf | |
571 | #define V_ifc_family lifc_family | |
572 | #define V_ifc_flags lifc_flags | |
573 | #define V_ifc_len lifc_len | |
574 | #define V_ifr_addr lifr_addr | |
575 | #define V_ifr_flags lifr_flags | |
576 | #define V_ifr_name lifr_name | |
577 | #define V_FAMILY_QUERY AF_UNSPEC | |
578 | #define V_family ss_family | |
579 | #else | |
580 | #define V_ifconf ifconf | |
581 | #define V_ifreq ifreq | |
582 | #define V_GIFADDR SIOCGIFADDR | |
583 | #define V_GIFCONF SIOCGIFCONF | |
584 | #define V_GIFFLAGS SIOCGIFFLAGS | |
585 | #define V_ifc_buf ifc_buf | |
586 | #define V_ifc_family ifc_family | |
587 | #define V_ifc_flags ifc_flags | |
588 | #define V_ifc_len ifc_len | |
589 | #define V_ifr_addr ifr_addr | |
590 | #define V_ifr_flags ifr_flags | |
591 | #define V_ifr_name ifr_name | |
592 | #define V_family sa_family | |
593 | #endif | |
594 | ||
595 | /* In all cases of IPv6 support, use an IPv6 socket. Otherwise (at least on | |
596 | Solaris 8) the call to read the flags doesn't work for IPv6 interfaces. If | |
597 | we find we can't actually make an IPv6 socket, the code will revert to trying | |
598 | an IPv4 socket. */ | |
599 | ||
600 | #if HAVE_IPV6 | |
601 | #define FAMILY AF_INET6 | |
602 | #else | |
603 | #define FAMILY AF_INET | |
604 | #endif | |
605 | ||
606 | /* OK, after all that preliminary stuff, here's the code. */ | |
607 | ||
608 | ip_address_item * | |
609 | os_common_find_running_interfaces(void) | |
610 | { | |
611 | struct V_ifconf ifc; | |
612 | struct V_ifreq ifreq; | |
613 | int vs; | |
614 | ip_address_item *yield = NULL; | |
615 | ip_address_item *last = NULL; | |
616 | ip_address_item *next; | |
617 | char *cp; | |
618 | char buf[MAX_INTERFACES*sizeof(struct V_ifreq)]; | |
619 | struct sockaddr *addrp; | |
620 | size_t len = 0; | |
92f9ced0 | 621 | char addrbuf[512]; |
059ec3d9 PH |
622 | |
623 | /* We have to create a socket in order to do ioctls on it to find out | |
624 | what we want to know. */ | |
625 | ||
626 | if ((vs = socket(FAMILY, SOCK_DGRAM, 0)) < 0) | |
627 | { | |
628 | #if HAVE_IPV6 | |
629 | DEBUG(D_interface) | |
630 | debug_printf("Unable to create IPv6 socket to find interface addresses:\n " | |
631 | "error %d %s\nTrying for an IPv4 socket\n", errno, strerror(errno)); | |
632 | vs = socket(AF_INET, SOCK_DGRAM, 0); | |
633 | if (vs < 0) | |
634 | #endif | |
635 | log_write(0, LOG_PANIC_DIE, "Unable to create IPv4 socket to find interface " | |
636 | "addresses: %d %s", errno, strerror(errno)); | |
637 | } | |
638 | ||
639 | /* Get the interface configuration. Some additional data is required when the | |
640 | new structures are in use. */ | |
641 | ||
642 | ifc.V_ifc_len = sizeof(buf); | |
643 | ifc.V_ifc_buf = buf; | |
644 | ||
645 | #ifdef V_FAMILY_QUERY | |
646 | ifc.V_ifc_family = V_FAMILY_QUERY; | |
647 | ifc.V_ifc_flags = 0; | |
648 | #endif | |
649 | ||
650 | if (ioctl(vs, V_GIFCONF, (char *)&ifc) < 0) | |
651 | log_write(0, LOG_PANIC_DIE, "Unable to get interface configuration: %d %s", | |
652 | errno, strerror(errno)); | |
653 | ||
654 | /* If the buffer is big enough, the ioctl sets the value of ifc.V_ifc_len to | |
655 | the amount actually used. If the buffer isn't big enough, at least on some | |
656 | operating systems, ifc.V_ifc_len still gets set to correspond to the total | |
657 | number of interfaces, even though they don't all fit in the buffer. */ | |
658 | ||
659 | if (ifc.V_ifc_len > sizeof(buf)) | |
660 | { | |
661 | ifc.V_ifc_len = sizeof(buf); | |
662 | DEBUG(D_interface) | |
663 | debug_printf("more than %d interfaces found: remainder not used\n" | |
664 | "(set MAX_INTERFACES in Local/Makefile and rebuild if you want more)\n", | |
665 | MAX_INTERFACES); | |
666 | } | |
667 | ||
668 | /* For each interface, check it is an IP interface, get its flags, and see if | |
669 | it is up; if not, skip. | |
670 | ||
671 | BSD systems differ from others in what SIOCGIFCONF returns. Other systems | |
672 | return a vector of ifreq structures whose size is as defined by the structure. | |
673 | BSD systems allow sockaddrs to be longer than their sizeof, which in turn makes | |
674 | the ifreq structures longer than their sizeof. The code below has its origins | |
675 | in amd and ifconfig; it uses the sa_len field of each sockaddr to determine | |
676 | each item's length. | |
677 | ||
678 | This is complicated by the fact that, at least on BSD systems, the data in the | |
679 | buffer is not guaranteed to be aligned. Thus, we must first copy the basic | |
680 | struct to some aligned memory before looking at the field in the fixed part to | |
681 | find its length, and then recopy the correct length. */ | |
682 | ||
683 | for (cp = buf; cp < buf + ifc.V_ifc_len; cp += len) | |
684 | { | |
685 | memcpy((char *)&ifreq, cp, sizeof(ifreq)); | |
686 | ||
687 | #ifndef HAVE_SA_LEN | |
688 | len = sizeof(struct V_ifreq); | |
689 | ||
690 | #else | |
691 | len = ((ifreq.ifr_addr.sa_len > sizeof(ifreq.ifr_addr))? | |
692 | ifreq.ifr_addr.sa_len : sizeof(ifreq.ifr_addr)) + | |
693 | sizeof(ifreq.V_ifr_name); | |
694 | if (len > sizeof(addrbuf)) | |
695 | log_write(0, LOG_PANIC_DIE, "Address for %s interface is absurdly long", | |
696 | ifreq.V_ifr_name); | |
697 | ||
698 | #endif | |
699 | ||
700 | /* If not an IP interface, skip */ | |
701 | ||
702 | if (ifreq.V_ifr_addr.V_family != AF_INET | |
703 | #if HAVE_IPV6 | |
704 | && ifreq.V_ifr_addr.V_family != AF_INET6 | |
705 | #endif | |
706 | ) continue; | |
707 | ||
708 | /* Get the interface flags, and if the interface is down, continue. Formerly, | |
709 | we treated the inability to get the flags as a panic-die error. However, it | |
710 | seems that on some OS (Solaris 9 being the case noted), it is possible to | |
711 | have an interface in this list for which this call fails because the | |
712 | interface hasn't been "plumbed" to any protocol (IPv4 or IPv6). Therefore, | |
713 | we now just treat this case as "down" as well. */ | |
714 | ||
715 | if (ioctl(vs, V_GIFFLAGS, (char *)&ifreq) < 0) | |
716 | { | |
717 | continue; | |
718 | /************* | |
719 | log_write(0, LOG_PANIC_DIE, "Unable to get flags for %s interface: %d %s", | |
720 | ifreq.V_ifr_name, errno, strerror(errno)); | |
721 | *************/ | |
722 | } | |
723 | if ((ifreq.V_ifr_flags & IFF_UP) == 0) continue; | |
724 | ||
725 | /* On some operating systems we have to get the IP address of the interface | |
214e2000 PH |
726 | by another call. On others, it's already there, but we must copy the full |
727 | length because we only copied the basic length above, and anyway, | |
728 | GIFFLAGS may have wrecked the data. */ | |
059ec3d9 PH |
729 | |
730 | #ifndef SIOCGIFCONF_GIVES_ADDR | |
731 | if (ioctl(vs, V_GIFADDR, (char *)&ifreq) < 0) | |
732 | log_write(0, LOG_PANIC_DIE, "Unable to get IP address for %s interface: " | |
733 | "%d %s", ifreq.V_ifr_name, errno, strerror(errno)); | |
734 | addrp = &ifreq.V_ifr_addr; | |
735 | ||
736 | #else | |
214e2000 PH |
737 | memcpy(addrbuf, cp + offsetof(struct V_ifreq, V_ifr_addr), |
738 | len - sizeof(ifreq.V_ifr_name)); | |
059ec3d9 PH |
739 | addrp = (struct sockaddr *)addrbuf; |
740 | #endif | |
741 | ||
742 | /* Create a data block for the address, fill in the data, and put it on the | |
743 | chain. */ | |
744 | ||
745 | next = store_get(sizeof(ip_address_item)); | |
746 | next->next = NULL; | |
747 | next->port = 0; | |
748 | (void)host_ntoa(-1, addrp, next->address, NULL); | |
749 | ||
750 | if (yield == NULL) yield = last = next; else | |
751 | { | |
752 | last->next = next; | |
753 | last = next; | |
754 | } | |
755 | ||
756 | DEBUG(D_interface) debug_printf("Actual local interface address is %s (%s)\n", | |
757 | last->address, ifreq.V_ifr_name); | |
758 | } | |
759 | ||
760 | /* Close the socket, and return the chain of data blocks. */ | |
761 | ||
f1e894f3 | 762 | (void)close(vs); |
059ec3d9 PH |
763 | return yield; |
764 | } | |
765 | ||
92f9ced0 NM |
766 | #endif /* HAVE_GETIFADDRS */ |
767 | ||
059ec3d9 PH |
768 | #else /* NO_FIND_INTERFACES */ |
769 | ||
770 | /* Some experimental or developing OS (e.g. GNU/Hurd) do not have the ioctls, | |
771 | and there is no other way to get a list of the (IP addresses of) local | |
772 | interfaces. We just return the loopback address(es). */ | |
773 | ||
774 | ip_address_item * | |
775 | os_common_find_running_interfaces(void) | |
776 | { | |
777 | ip_address_item *yield = store_get(sizeof(address_item)); | |
778 | yield->address = US"127.0.0.1"; | |
779 | yield->port = 0; | |
780 | yield->next = NULL; | |
781 | ||
782 | #if HAVE_IPV6 | |
783 | yield->next = store_get(sizeof(address_item)); | |
784 | yield->next->address = US"::1"; | |
785 | yield->next->port = 0; | |
786 | yield->next->next = NULL; | |
787 | #endif | |
788 | ||
789 | DEBUG(D_interface) debug_printf("Unable to find local interface addresses " | |
790 | "on this OS: returning loopback address(es)\n"); | |
791 | return yield; | |
792 | } | |
793 | ||
794 | #endif /* NO_FIND_INTERFACES */ | |
795 | #endif /* FIND_RUNNING_INTERFACES */ | |
796 | ||
797 | ||
798 | ||
799 | ||
800 | ||
801 | /************************************************* | |
802 | ************************************************** | |
803 | * Stand-alone test program * | |
804 | ************************************************** | |
805 | *************************************************/ | |
806 | ||
807 | ||
808 | #ifdef STAND_ALONE | |
809 | ||
810 | #ifdef CLOCKS_PER_SEC | |
811 | #define REAL_CLOCK_TICK CLOCKS_PER_SEC | |
812 | #else | |
813 | #ifdef CLK_TCK | |
814 | #define REAL_CLOCK_TICK CLK_TCK | |
815 | #else | |
816 | #define REAL_CLOCK_TICK 1000000 /* SunOS4 */ | |
817 | #endif | |
818 | #endif | |
819 | ||
820 | ||
821 | int main(int argc, char **argv) | |
822 | { | |
823 | char buffer[128]; | |
824 | int fd = fileno(stdin); | |
825 | int rc; | |
826 | ||
827 | printf("Testing restarting signal; wait for handler message, then type a line\n"); | |
828 | strcpy(buffer, "*** default ***\n"); | |
829 | os_restarting_signal(SIGALRM, sigalrm_handler); | |
830 | alarm(2); | |
831 | if ((rc = read(fd, buffer, sizeof(buffer))) < 0) | |
832 | printf("No data read\n"); | |
833 | else | |
834 | { | |
835 | buffer[rc] = 0; | |
836 | printf("Read: %s", buffer); | |
837 | } | |
838 | alarm(0); | |
839 | ||
840 | printf("Testing non-restarting signal; should read no data after handler message\n"); | |
841 | strcpy(buffer, "*** default ***\n"); | |
842 | os_non_restarting_signal(SIGALRM, sigalrm_handler); | |
843 | alarm(2); | |
844 | if ((rc = read(fd, buffer, sizeof(buffer))) < 0) | |
845 | printf("No data read\n"); | |
846 | else | |
847 | { | |
848 | buffer[rc] = 0; | |
849 | printf("Read: %s", buffer); | |
850 | } | |
851 | alarm(0); | |
852 | ||
853 | printf("Testing load averages (last test - ^C to kill)\n"); | |
854 | for (;;) | |
855 | { | |
856 | int avg; | |
857 | clock_t used; | |
858 | clock_t before = clock(); | |
859 | avg = os_getloadavg(); | |
860 | used = clock() - before; | |
861 | printf("cpu time = %.2f ", (double)used/REAL_CLOCK_TICK); | |
862 | if (avg < 0) | |
863 | { | |
864 | printf("load average not available\n"); | |
865 | break; | |
866 | } | |
867 | printf("load average = %.2f\n", (double)avg/1000.0); | |
868 | sleep(2); | |
869 | } | |
870 | return 0; | |
871 | } | |
872 | ||
873 | #endif | |
874 | ||
875 | /* End of os.c */ |