[PATCH] using an interface without IP address

Chris Hanson <[email protected]>
Newsgroups gmane.comp.security.libnet
Message-ID <[email protected]>
   Date: Thu, 29 Jan 2004 06:21:25 +0100
   From: =?iso-8859-1?Q?Fr=E9d=E9ric_Raynal?= <[email protected]>

   Currently, I still havent found the ioct() giving me all the devices,
   even those that are down (I even sent a mail to net-linux to get the
   solution but got no answer).  So, results bellow are "normal"

Hi, I'm helping out Domenico by co-maintaining libnet for Debian.

I have some experience with this, having had to solve this problem for
another program.  AFAIK, the only way to get all the interfaces is to
read and parse "/proc/net/dev".

I've attached some code that does this.  This code is a fragment from
my program.  I'm going to try to integrate this into libnet 1.1.1, and
if that works I'll send you a patch.
foo.c (text/x-csrc, 3.1 KB)
/* Use /proc/net/dev if available, since that will give us a list of
   all of the interfaces.  Otherwise use SIOCGIFCONF, which will at
   least give us the interfaces that are up.  */

static struct ifreq *
get_interface_list (unsigned int * n_ifcs_return)
{
  struct ifreq * ifcs = (proc_interface_list (n_ifcs_return));
  return
    ((ifcs == 0)
     ? (conf_interface_list (n_ifcs_return))
     : ifcs);
}

static struct ifreq *
conf_interface_list (unsigned int * n_ifcs_return)
{
  struct ifconf ifc;
  unsigned int n_ifcs = 4;
  unsigned int n_bytes = ((sizeof (struct ifreq)) * n_ifcs);

  (ifc . ifc_len) = n_bytes;
  (ifc . ifc_req) = (xmalloc (n_bytes));
  while (1)
    {
      if ((ioctl (kernel_connection, SIOCGIFCONF, (&ifc))) < 0)
	{
	  log_perror ("SIOCGIFCONF");
	  free (ifc . ifc_req);
	  return (0);
	}
      if ((ifc . ifc_len) < n_bytes)
	break;
      n_ifcs *= 2;
      n_bytes = ((sizeof (struct ifreq)) * n_ifcs);
      (ifc . ifc_req) = (xrealloc ((ifc . ifc_req), n_bytes));
    }

  (*n_ifcs_return) = ((ifc . ifc_len) / (sizeof (struct ifreq)));
  return (ifc . ifc_req);
}

static struct ifreq *
proc_interface_list (unsigned int * n_ifcs_return)
{
  FILE * s = (fopen ("/proc/net/dev", "r"));
  if (s == 0)
    {
      log_perror ("Unable to open /proc/net/dev");
      return (0);
    }
  discard_line (s);
  discard_line (s);
  {
    unsigned int i = 0;
    unsigned int n = 4;
    struct ifreq * ifcs = (xmalloc ((sizeof (struct ifreq)) * n));
    struct ifreq ifc;
    while (proc_interface_name (s, (&ifc)))
      {
	if (i == n)
	  {
	    n *= 2;
	    ifcs = (xrealloc (ifcs, ((sizeof (struct ifreq)) * n)));
	  }
	(ifcs[i++]) = ifc;
      }
    fclose (s);
    (*n_ifcs_return) = i;
    return (ifcs);
  }
}

static void
discard_line (FILE * s)
{
  while (1)
    {
      int c = (getc (s));
      if ((c == EOF) || (c == '\n'))
	break;
    }
}

#define PIN_GETC(c, s)							\
{									\
  c = (getc (s));							\
  if (c == EOF)								\
    return (0);								\
  if (c == '\0')							\
    {									\
      discard_line (s);							\
      goto restart;							\
    }									\
}

#define PIN_ACCUM(c)							\
{									\
  if (i < n)								\
    (name[i++]) = (c);							\
  else									\
    {									\
      discard_line (s);							\
      goto restart;							\
    }									\
}

static int
proc_interface_name (FILE * s, struct ifreq * ifc)
{
  char * name = (ifc -> ifr_name);
  unsigned int n = (sizeof (ifc -> ifr_name));
  unsigned int i;
  int c;

 restart:
  do
    {
      PIN_GETC (c, s);
    }
  while (isspace (c));
  i = 0;
  while (1)
    {
      PIN_ACCUM (c);
      PIN_GETC (c, s);
      if (isspace (c))
	{
	  if (c != '\n')
	    discard_line (s);
	  break;
	}
      if (c == ':')
	{
	  if (i < n)
	    /* Might be part of an alias; check.  */
	    {
	      unsigned int saved_i = i;
	      while (1)
		{
		  PIN_ACCUM (c);
		  PIN_GETC (c, s);
		  if (!isdigit (c))
		    {
		      if (c != ':')
			/* Not an alias; first colon was name terminator.  */
			i = saved_i;
		      if (c != '\n')
			discard_line (s);
		      break;
		    }
		}
	    }
	  break;
	}
    }
  if (i < n)
    (name[i]) = '\0';
  return (1);
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.