Sorry to bother all of you with this, but there's been a problem with
IRIX for which I have potential solution, and it would be helpful to
have it tried out widely. Non-IRIX readers can stop reading now...
The short program below should produce a list of all IP interfaces on an
IRIX system, including the "alias" IP addresses. The code used in Exim,
which does this on other versions of Unix, omits the alias interfaces
when run on IRIX. I'd be grateful if any IRIX users out there could
compile and run this program and check that it does produce the correct
list of addresses. In particular, it would be nice if somebody running
the recently-released IRIX 6.5 could do this.
A comment that came with the code (which originated in a message from
an SGI support person) was: "On 6.2 you need the libc patch to get the
sysctl() stub and the networking kernel patch to get the support."
--
Philip Hazel University of Cambridge Computing Service,
ph10@??? Cambridge, England. Phone: +44 1223 334714.
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/soioctl.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
void p_sockaddr(struct sockaddr *sa, int flags, int width) ;
void
error(char *s)
{
perror(s);
}
void
p_ifentry(struct if_msghdr *ifm)
{
register struct sockaddr_dl *sdl = (struct sockaddr_dl *)(ifm +1);
static int loop = 0;
if (ifm->ifm_type == RTM_IFINFO) return;
{
struct ifa_msghdr *ifam = (struct ifa_msghdr *)ifm;
struct sockaddr_in *dest = 0, *mask = 0, *addr = 0;
struct sockaddr *sa;
char *cp;
if (ifam->ifam_addrs & RTA_NETMASK)
mask = (struct sockaddr_in *)(ifam + 1);
if (ifam->ifam_addrs & RTA_IFA)
{
#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
cp = (char *)mask;
sa = (struct sockaddr *)mask;
ADVANCE(cp, sa);
addr = (struct sockaddr_in *)cp;
}
if (ifam->ifam_addrs & RTA_BRD) dest = addr + 1;
if (addr)
{
printf("\tinet ");
addr->sin_family = AF_INET;
p_sockaddr(addr, 0, 16);
}
printf("\n");
}
}
void
p_sockaddr(struct sockaddr *sa, int flags, int width)
{
char workbuf[128], *cplim;
register char *cp = workbuf;
switch(sa->sa_family)
{
case AF_INET:
{
register struct sockaddr_in *sin = (struct sockaddr_in*)sa;
printf("%s",inet_ntoa(sin->sin_addr));
return;
}
}
}
void
iflist(void)
{
size_t needed;
int mib[6];
char *buf, *next, *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;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
{ perror("iflist-sysctl-estimate"); exit(1);}
if ((buf = malloc(needed)) == 0)
{ printf("out of space\n"); exit(1);}
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
{ perror("sysctl of ifnet list"); exit(1);}
lim = buf + needed;
for (next = buf; next < lim; next += ifm->ifm_msglen)
{
ifm = (struct if_msghdr *)next;
(void)p_ifentry(ifm);
}
}
main(int argc, char **argv)
{
iflist();
exit(0);
}
--
*** Exim information can be found at
http://www.exim.org/ ***