#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define NADDRS 128
#define _SIZEOF_ADDR_IFREQ1(ifr) \
((ifr)->ifr_addr.sa_len > sizeof(struct sockaddr) ? \
(sizeof(struct ifreq) - sizeof(struct sockaddr) + \
(ifr)->ifr_addr.sa_len) : sizeof(struct ifreq))
static void
usage(const char *cmd)
{
fprintf(stderr, "%s [-n naddrs]\n", cmd);
exit(1);
}
int
main(int argc, char *argv[])
{
struct ifconf ifc;
struct ifreq *ifr;
caddr_t pos;
int s, naddrs, opt;
naddrs = NADDRS;
while ((opt = getopt(argc, argv, "n:")) != -1) {
switch (opt) {
case 'n':
naddrs = strtol(optarg, NULL, 10);
break;
default:
usage(argv[0]);
}
}
if (naddrs <= 0)
usage(argv[0]);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0)
err(2, "socket failed");
memset(&ifc, 0, sizeof(ifc));
ifc.ifc_len = sizeof(struct sockaddr_storage) * naddrs;
ifc.ifc_buf = malloc(ifc.ifc_len);
if (ifc.ifc_buf == NULL)
err(2, "malloc failed");
if (ioctl(s, SIOCGIFCONF, &ifc, sizeof(ifc)) < 0)
err(2, "ioctl failed");
pos = ifc.ifc_buf;
while (ifc.ifc_len >= (int)sizeof(*ifr)) {
int len;
ifr = (struct ifreq *)pos;
len = _SIZEOF_ADDR_IFREQ1(ifr);
if (ifc.ifc_len < len)
err(2, "invalid ifc.ifc_len");
if (ifr->ifr_addr.sa_family == AF_UNSPEC) {
printf("%s: no address\n", ifr->ifr_name);
} else if (ifr->ifr_addr.sa_family == AF_INET ||
ifr->ifr_addr.sa_family == AF_INET6) {
char addr_str[INET6_ADDRSTRLEN];
const void *src;
const char *ret;
if (ifr->ifr_addr.sa_family == AF_INET) {
const struct sockaddr_in *in =
(const struct sockaddr_in *)&ifr->ifr_addr;
src = &in->sin_addr;
} else {
const struct sockaddr_in6 *in6 =
(const struct sockaddr_in6 *)&ifr->ifr_addr;
src = &in6->sin6_addr;
}
ret = inet_ntop(ifr->ifr_addr.sa_family, src,
addr_str, sizeof(addr_str));
if (ret == NULL)
err(2, "inet_ntop failed");
printf("%s: inet%c %s\n", ifr->ifr_name,
ifr->ifr_addr.sa_family == AF_INET ? '4' : '6',
ret);
} else if (ifr->ifr_addr.sa_family == AF_LINK) {
const struct sockaddr_dl *dl =
(const struct sockaddr_dl *)&ifr->ifr_addr;
printf("%s: link%d\n", ifr->ifr_name, dl->sdl_index);
} else {
printf("%s: unknown family %d\n", ifr->ifr_name,
ifr->ifr_addr.sa_family);
}
ifc.ifc_len -= len;
pos += len;
}
if (ifc.ifc_len != 0)
printf("ifc_len left %d\n", ifc.ifc_len);
exit(0);
}