[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: C code to find interface IP address



mtsouk@freemail.gr wrote:
> I am looking for C code in order to find the IP address of each ethX
> interface in a Linux machine.

Curious as to why you need that information.  Very few programs ever
need to tread there.

Note that network devices can be configured or unconfigured at any
time.  Which means you need to check ever so often to see if the list
has changed.  Be ready for a device to drop out at any time.  People
routinely up and down interfaces at their own whims.

Here are some snippets which might help you.  This is from one of my
own programs.  It is getting a list of broadcast addresses.  Putting
in the error checking is left as an exercise to the reader.  I
probably broken it splitting it out of its working environment.  YMMV.

Bob Proulx

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>

enum { ADDRS_SIZE = 8 };	/* Plenty of initial broadcast addresses. */

static struct in_addr bcast_arr[ADDRS_SIZE];
static int numbaddrs;		/* The actual number. */

/******************************************************************/
/*
 * Get the interface device list, walk through it and deduce those
 * interfaces which can broadcast.
 */
static int get_device_info(void)
{
  int i, sd, numdevs;
  struct ifconf ifc_conf;
  char ifc_conf_buf[BUFSIZ];	/* 1024/32 == space for 32 interfaces */
  struct ifreq *devptr;
  int ifc_conf_buf_size;

  numbaddrs = 0;

  /*
   * Open a socket, any type will do so we choose UDP, and ask it with
   * an ioctl call what devices are behind it.
   */
  if ((sd = socket(AF_INET,SOCK_DGRAM,0)) < 0)
    {
      fprintf(stderr,"Error: Unable to create socket\n");
      perror("socket");
      return -1;
    }

  /*
   * Fill the buffer with our static buffer, probably big enough, and get
   * the interface configuration.
   */
  ifc_conf_buf_size = sizeof ifc_conf_buf;
  ifc_conf.ifc_len = ifc_conf_buf_size;
  ifc_conf.ifc_buf = ifc_conf_buf;
  if (ioctl(sd,SIOCGIFCONF,&ifc_conf) < 0)
    {
      fprintf(stderr,"Error: Unable to get network interface conf\n");
      perror("ioctl");
      close(sd);
      return -1;
    }
  if ((sizeof ifc_conf_buf - ifc_conf.ifc_len) <= sizeof (struct ifreq))
    fprintf(stderr,"Info: More interfaces then we anticipated.\n");

  /*
   * Excess space should be larger than one ifreq or we need more.  If
   * the buffer was not big enough then we need to malloc a larger space
   * and try again.  There is no number of retries.  We either get them
   * all or we run out of memory.
   */
  while ((sizeof ifc_conf_buf - ifc_conf.ifc_len) <= sizeof (struct ifreq))
    {
      if (ifc_conf_buf_size != sizeof ifc_conf_buf)
	free(ifc_conf.ifc_buf);	/* We allocated it last time around. */
      ifc_conf_buf_size *= 2;
      ifc_conf.ifc_len = ifc_conf_buf_size;
      if ((ifc_conf.ifc_buf = malloc(ifc_conf_buf_size)) == 0)
	{
	  fprintf(stderr,"Error: Out of memory allocating interfaces.\n");
	  close(sd);
	  return -1;
	}
      if (ioctl(sd,SIOCGIFCONF,&ifc_conf) < 0)
	{
	  fprintf(stderr,"Error: Unable to get network interface conf\n");
	  perror("ioctl");
	  close(sd);
	  return -1;
	}
    }

  /*
   * An array of devices were returned.  Which ones are up right now and
   * have broadcast capability?
   */
  numdevs = ifc_conf.ifc_len / sizeof (struct ifreq);
  for (i = 0; i < numdevs; i++)
    {
      /* devptr points into an array of ifreq structs. */
      devptr = &ifc_conf.ifc_req[i];

      if (devptr->ifr_addr.sa_family != AF_INET)
	continue;

      if (ioctl(sd,SIOCGIFFLAGS,devptr) < 0)
	{
	  fprintf(stderr,"Error: Unable to get device interface flags.\n");
	  perror("ioctl");
	  close(sd);
	  return -1;
	}

      if ((devptr->ifr_flags & IFF_LOOPBACK) != 0)
	continue;

      if ((devptr->ifr_flags & IFF_UP) == 0)
	continue;

      if ((devptr->ifr_flags & IFF_BROADCAST) == 0)
	continue;

      /* Get the broadcast address. */
      if (ioctl(sd,SIOCGIFBRDADDR,devptr) < 0)
	{
	  fprintf(stderr,"%s: Error: Unable to get broadcast address.\n",
		  devptr->ifr_name);
	  perror("ioctl");
	  close(sd);
	  return -1;
	}
      bcast_arr[numbaddrs].s_addr
	= ((struct sockaddr_in *)&devptr->ifr_broadaddr)->sin_addr.s_addr;

      /* FIXME: should dynamically allocate more space. */
      if (++numbaddrs > ADDRS_SIZE)
	{
	  fprintf(stderr,"Warning: More broadcast devs than anticipated.\n");
	  break;
	}
    }

  close(sd);

  return 0;
}

Attachment: pgpb74qrXpbog.pgp
Description: PGP signature


Reply to: