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

#define MAX_IFACES 64
#define SA_IN struct sockaddr_in

int main(int argc, char *argv[]) {
  struct ifconf ifaces;
  size_t i, iface_buf_size, arg_len;
  char *arg, *name;
  int sock;
  u_int32_t addr;

  /* if a command-line argument was specified, then grab the value and
   * the length */
  arg = NULL; arg_len = 0;
  if (argc > 1) {
    arg = argv[1];
    arg_len = strlen(argv[1]);
  }

  /* create new socket */
  sock = socket(PF_INET, SOCK_STREAM, 0);

  /* clear ioctl buffer */
  memset(&ifaces, 0, sizeof(struct ifconf));

  /* calculate size */
  iface_buf_size = sizeof(struct ifreq) * MAX_IFACES;
  ifaces.ifc_len = iface_buf_size;

  /* allocate memory for interface list */
  if ((ifaces.ifc_req = malloc(iface_buf_size)) == NULL) {
    perror("couldn't allocate interface buffer:");
    exit(EXIT_FAILURE);
  }
  memset(ifaces.ifc_req, 0, iface_buf_size);
  
  /* get list of interfaces */
  if (ioctl(sock, SIOCGIFCONF, &ifaces)) {
    perror("couldn't get address list:");
    exit(EXIT_FAILURE);
  }

  /* iterate over list of interfaces and print out addresses associated
   * with each one */
  for (i = 0; i < (ifaces.ifc_len / sizeof(struct ifreq)); i++) {
    /* grab interface name */
    name = ifaces.ifc_req[i].ifr_name;

    /* if a command-line argument was specified, then compare the
     * interface name against the argument.  if the command-line
     * argument name is longer than the interface name, or if the
     * command-line argument doesn't match the prefix of the device,
     * then skip the interface.
     */
    if (arg && (arg_len > strlen(name) || memcmp(arg, name, arg_len)))
      continue;

    /* grab address */
    addr = ((SA_IN*) &(ifaces.ifc_req[i].ifr_addr))->sin_addr.s_addr;

    /* print row (not endian safe) */
    printf(
      "%s,%d.%d.%d.%d\n", 
      ifaces.ifc_req[i].ifr_name,
      (addr & 0x000000ff) >> 0,
      (addr & 0x0000ff00) >> 8,
      (addr & 0x00ff0000) >> 16,
      (addr & 0xff000000) >> 24
    );
  }

  /* free interface list, then shut down socket (silently ignore err) */
  free(ifaces.ifc_req);
  shutdown(sock, SHUT_RDWR);

  /* return success */
  return EXIT_SUCCESS;
}

