Merge branch 'dbmjz'
[exim.git] / src / OS / os.c-IRIX6
CommitLineData
61ec970d
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
5/* Copyright (c) University of Cambridge 2001 */
6/* See the file NOTICE for conditions of use and distribution. */
7
8/* Irix-specific code. This is concatenated onto the generic src/os.c file.
9Irix has a unique way of finding all the network interfaces, so we provide a
10unique function here, and define FIND_RUNNING_INTERFACES to stop src/os.c
11trying to provide the function. The macro may be set initially anyway, when
12compiling os. for utilities that don't want this function. */
13
14#ifndef FIND_RUNNING_INTERFACES
15#define FIND_RUNNING_INTERFACES
16
17/* This is the special form of the function using sysctl() which is the only
18form that returns all the aliases on IRIX systems. This code has its origins
19in a sample program that came from within SGI. */
20
21#include <sys/sysctl.h>
22#include <net/if_dl.h>
23#include <net/if_types.h>
24#include <net/soioctl.h>
25#include <net/route.h>
26
27#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) -1))) \
28 : sizeof(__uint64_t))
29#ifdef _HAVE_SA_LEN
30#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
31#else
32#define ADVANCE(x, n) (x += ROUNDUP(_FAKE_SA_LEN_DST(n)))
33#endif
34
35
36ip_address_item *
37os_find_running_interfaces(void)
38{
39ip_address_item *yield = NULL;
40ip_address_item *last = NULL;
41ip_address_item *next;
42
43size_t needed;
44int mib[6];
45char *buf, *nextaddr, *lim;
46register struct if_msghdr *ifm;
47
48mib[0] = CTL_NET;
49mib[1] = PF_ROUTE;
50mib[2] = 0;
51mib[3] = 0;
52mib[4] = NET_RT_IFLIST;
53mib[5] = 0;
54
55/* Get an estimate of the amount of store needed, then get the store and
56get the data into it. Any error causes a panic death. */
57
58if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
59 log_write(0, LOG_PANIC_DIE, "iflist-sysctl-estimate failed: %s",
60 strerror(errno));
61
62buf = store_get(needed);
63
64if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
65 log_write(0, LOG_PANIC_DIE, "sysctl of ifnet list failed: %s",
66 strerror(errno));
67
68/* Now fish out the data for each interface */
69
70lim = buf + needed;
71for (nextaddr = buf; nextaddr < lim; nextaddr += ifm->ifm_msglen)
72 {
73 ifm = (struct if_msghdr *)nextaddr;
74
75 if (ifm->ifm_type != RTM_IFINFO)
76 {
77 struct ifa_msghdr *ifam = (struct ifa_msghdr *)ifm;
78 struct sockaddr_in *mask = NULL, *addr = NULL;
79
80 if ((ifam->ifam_addrs & RTA_NETMASK) != 0)
81 mask = (struct sockaddr_in *)(ifam + 1);
82
83 if ((ifam->ifam_addrs & RTA_IFA) != 0)
84 {
85 char *cp = (char *)mask;
86 struct sockaddr *sa = (struct sockaddr *)mask;
87 ADVANCE(cp, sa);
88 addr = (struct sockaddr_in *)cp;
89 }
90
91 /* Create a data block for the address, fill in the data, and put it on
92 the chain. This data has to survive for ever, so use malloc. */
93
94 if (addr != NULL)
95 {
96 next = store_malloc(sizeof(ip_address_item));
97 next->next = NULL;
98 next->port = 0;
99 (void)host_ntoa(-1, addr, next->address, NULL);
100
101 if (yield == NULL) yield = last = next; else
102 {
103 last->next = next;
104 last = next;
105 }
106
107 DEBUG(D_interface) debug_printf("Actual local interface address is %s\n",
108 last->address);
109 }
110 }
111 }
112
113return yield;
114}
115
116#endif /* FIND_RUNNING_INTERFACES */
117
118/* End of os.c-IRIX */