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