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

#define BUFFER_SIZE 1024 /* bytes */

/***************************************************************************
 This program displays all network interfaces in the system.  First, a
 buffer is allocated so that proper address alignment is maintained.  Next,
 ioctl() is invoked so that a list of all interfaces is retrieved into the
 newly allocated buffer.  Finally, the interface names are displayed, and
 the buffer is released.  This program is a hack whose only purpose is to
 illustrate the use of an ioctl() for network programming.  Use and hack
 it for your enjoyment!
***************************************************************************/
int main(int argc, char **argv)
{
  int sockfd, i, len;
  char *buf, *ptr;
  struct ifconf ifc;
  struct ifreq *ifrp;
  struct sockaddr_in *sockaddr_ptr;

  /* used for buffer increments later on */
  len = sizeof(struct sockaddr);

  /* socket needed for ioctl() operations */
  sockfd = socket(AF_INET,SOCK_DGRAM,0);

  /* get ourself a buffer that is properly aligned */
  buf = malloc(BUFFER_SIZE);

  /* buffer length and reference are configured in ifconf{} structure */
  ifc.ifc_len = BUFFER_SIZE;
  ifc.ifc_ifcu.ifcu_buf = buf;

  /* if we have an error condition, just exit */
  if (ioctl(sockfd,SIOCGIFCONF,&ifc) < 0)
  {
    printf("ioctl() failure\n");
    free(buf); /* release resources -- yes, it's redundant */
    exit(1);
  } /* if */

  /* traverse array of ifreq{} structures and display interface names */
  for (ptr = buf; ptr < (buf + ifc.ifc_len);)
  {
    ifrp = (struct ifreq *)ptr;
    sockaddr_ptr = (struct sockaddr_in *)&ifrp->ifr_ifru.ifru_addr;

    printf("%s: ",ifrp->ifr_ifrn.ifrn_name);
    printf("%s\n",inet_ntoa(sockaddr_ptr->sin_addr.s_addr));

    ptr += sizeof(ifrp->ifr_ifrn.ifrn_name) + len;
  } /* for */

  /* release resources */
  free(buf);

  exit(0);

} /* main */
