#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include "support.h"

unsigned int if_nametoindex(const char *ifname)
{
  FILE *f;
  char buffer[54];
  char *c;
  unsigned long l;

  if (!(f = fopen("/proc/net/if_inet6", "r")))
    return 0;

  while(fgets(buffer, sizeof(buffer), f)) {
    c = buffer;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    l = strtoul(c, &c, 16);
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(*c == ' ') c++;
    if (!strcmp(c, ifname)) {
      fclose(f);
      return l;
    };
  };
  fclose(f);
  return 0;
};

char *if_indextoname(unsigned int ifindex, char *ifname)
{
  FILE *f;
  char buffer[54];
  char *c;

  if (!(f = fopen("/proc/net/if_inet6", "r")))
    return NULL;

  while(fgets(buffer, sizeof(buffer), f)) {
    c = buffer;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    if (strtoul(c, &c, 16) != ifindex)
      continue;
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(*c == ' ') c++;
    strcpy(ifname, c);
    return ifname;
  };
  fclose(f);
  return NULL;
};

struct if_nameindex *if_nameindex(void)
{
  FILE *f;
  char buffer[54];
  char *c;
  int structlen = sizeof(struct if_nameindex), namelen = 0;
  void *buf;
  struct if_nameindex *structp;
  char *namep;
  
  unsigned long l;

  if (!(f = fopen("/proc/net/if_inet6", "r")))
    return NULL;

  while(fgets(buffer, sizeof(buffer), f)) {
    c = buffer;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    l = strtoul(c, &c, 16);
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(*c == ' ') c++;

    structlen += sizeof(struct if_nameindex);
    namelen += strlen(c) + 1;
  };

  fclose(f);

  if (!(buf = malloc(structlen + namelen)))
    return NULL;

  structp = (struct if_nameindex *)buf;
  namep = (char *)buf + structlen;

  if (!(f = fopen("/proc/net/if_inet6", "r")))
    goto fail;

  while(fgets(buffer, sizeof(buffer), f)) {
    c = buffer;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    structp->if_index = strtoul(c, &c, 16);
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(isxdigit(*c)) c++;
    if (*(c++) != ' ')
      continue;
    while(*c == ' ') c++;

    if ((structlen -= sizeof(struct if_nameindex)) < 0)
      goto fail;
    if ((namelen -= strlen(c) + 1) < 0)
      goto fail;

    structp->if_name = namep;
    strcpy(namep, c);

    structp++;
    namep += strlen(c) + 1;
  };

  structp->if_index = 0;
  structp->if_name = NULL;

  fclose(f);
  return (struct if_nameindex *)buf;

fail:
  free(buf);
  if (f)
    fclose(f);
  return NULL;
};
