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