#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netdb.h>

# define lifconf if_laddrconf
# define lifc_len iflc_len
# define lifc_buf iflc_buf
# define lifc_req iflc_req
# define lifreq if_laddrreq
# define lifr_addr iflr_addr
# define lifr_name iflr_name
# define lifr_dstaddr iflr_dstaddr
# define lifr_broadaddr iflr_broadaddr
# define lifr_flags iflr_flags
# define lifr_index iflr_index

static void die(const char *call) {
	perror(call);
	exit(1);
}

int main(void) {
	int fd;
	int err;
	struct lifconf ifconf;
	char buf[8192];
	struct lifreq *ifreq;

	fd = socket(PF_INET6, SOCK_DGRAM, 0);
	if (fd < 0)
		die("socket");

	memset(&ifconf, 0, sizeof(ifconf));
	ifconf.lifc_buf = buf;
	ifconf.lifc_len = sizeof(buf);

	err = ioctl(fd, SIOCGLIFCONF, &ifconf);

	if (err)
		die("ioctl");

	for (ifreq = (struct lifreq*) ifconf.lifc_buf;
			(void*)ifreq < ((void*)ifconf.lifc_buf) + ifconf.lifc_len;
			++ifreq)
	{
		struct lifreq ifreq_addr;
		char addrstr[INET6_ADDRSTRLEN];

		printf("%.*s\n", IFNAMSIZ, ifreq->lifr_name);

		memset(&ifreq_addr, 0, sizeof(ifreq_addr));
		memcpy(ifreq_addr.lifr_name, ifreq->lifr_name, sizeof(ifreq_addr.lifr_name));

		err = ioctl(fd, SIOCGLIFADDR, &ifreq_addr);
		if (err)
			die("ifaddr ioctl");

		err = getnameinfo(&ifreq_addr.lifr_addr, sizeof(ifreq_addr.lifr_addr),
				addrstr, sizeof(addrstr),
				NULL, 0, NI_NUMERICHOST);

		if (err)
			die("getnameinfo");

		printf("%.*s\n", (int)sizeof(addrstr), addrstr);
	}

    return 0;
}

/* vim: set ts=4 sw=4 noet: */

