Hurd: errno really uses more than a short-sized value. Bug 2476
[exim.git] / src / OS / unsupported / os.c-IRIX6
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.
9 Irix has a unique way of finding all the network interfaces, so we provide a
10 unique function here, and define FIND_RUNNING_INTERFACES to stop src/os.c
11 trying to provide the function. The macro may be set initially anyway, when
12 compiling 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
18 form that returns all the aliases on IRIX systems. This code has its origins
19 in 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
36 ip_address_item *
37 os_find_running_interfaces(void)
38 {
39 ip_address_item *yield = NULL;
40 ip_address_item *last = NULL;
41 ip_address_item *next;
42
43 size_t needed;
44 int mib[6];
45 char *buf, *nextaddr, *lim;
46 register struct if_msghdr *ifm;
47
48 mib[0] = CTL_NET;
49 mib[1] = PF_ROUTE;
50 mib[2] = 0;
51 mib[3] = 0;
52 mib[4] = NET_RT_IFLIST;
53 mib[5] = 0;
54
55 /* Get an estimate of the amount of store needed, then get the store and
56 get the data into it. Any error causes a panic death. */
57
58 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
59   log_write(0, LOG_PANIC_DIE, "iflist-sysctl-estimate failed: %s",
60     strerror(errno));
61
62 buf = store_get(needed, FALSE);
63
64 if (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
70 lim  = buf + needed;
71 for (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 = CS 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
113 return yield;
114 }
115
116 #endif  /* FIND_RUNNING_INTERFACES */
117
118 /* End of os.c-IRIX */