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