简体   繁体   中英

Polling interface names via SIOCGIFCONF in Linux

I'm attempting to poll networking device names. I've pieced this together from various snippets,

  1. http://unixhelp.ed.ac.uk/CGI/man-cgi?netdevice+7
  2. http://lists.apple.com/archives/Unix-porting/2002/Apr/msg00134.html
  3. http://ubuntuforums.org/showthread.php?t=1421487

But my output is just gibberish.

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

#define BUFLEN 1024
#define SEQ 9999

int main (int argc, const char* argv[])
{
  // File descriptor for socket
  int socketfd;
  struct ifconf conf;
  struct ifreq req[10];
  struct ifreq *ifr;

  printf("Opening socket...");
  socketfd = socket(AF_ROUTE, SOCK_RAW, 0);
  if (socketfd >= 0) {
    printf(" OK\n");
    conf.ifc_len = sizeof(req);
    conf.ifc_buf = (__caddr_t) req;
    ioctl(socketfd,SIOCGIFCONF,&conf);

    printf("Discovering interfaces...\n");
    int i;
    for (i=0; i<conf.ifc_len/sizeof(req[0]); i++) {
      ifr = &conf.ifc_req[i];
      printf("%d. %s\n", i+1, req[i].ifr_name);
    }
  }
  else {
    printf("Failed!\n");
  }
  return 0;
}

Output:

Opening socket... OK
Discovering interfaces...
?u???}??Gh???
2. p?9}?
3.
4. v?=?n??u?`?y??]g?<?~?v??
5.
6.
7.
8. ?v?T?
9. ?|?mw??j??v??h??|??v?T00~??v?$?|??|?@
10. T00~??v?$?|??|?@

I tried outputting each char of the ifr_name array one-by-one to see if they were null terminated but that didn't change much. Each iteration of my program outputs something different so this leads me to think I'm referencing something wrong. Can someone provide me some insight as to what I may be doing wrong?

Here's some code I put together for Mac OS X:

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

/* This is defined on Mac OS X */
#ifndef _SIZEOF_ADDR_IFREQ
#define _SIZEOF_ADDR_IFREQ sizeof
#endif

int main (int argc, const char* argv[])
{
  // File descriptor for socket
  int socketfd;
  struct ifconf conf;
  char data[4096];
  struct ifreq *ifr;
  char addrbuf[1024];
  int i;

  printf("Opening socket...");
  socketfd = socket(AF_INET, SOCK_DGRAM, 0);
  if (socketfd >= 0) {
    printf(" OK\n");
    conf.ifc_len = sizeof(data);
    conf.ifc_buf = (caddr_t) data;
    if (ioctl(socketfd,SIOCGIFCONF,&conf) < 0) {
      perror("ioctl");
    }

    printf("Discovering interfaces...\n");
    i = 0;
    ifr = (struct ifreq*)data;
    while ((char*)ifr < data+conf.ifc_len) {
      switch (ifr->ifr_addr.sa_family) {
        case AF_INET:
            ++i;
            printf("%d. %s : %s\n", i, ifr->ifr_name, inet_ntop(ifr->ifr_addr.sa_family, &((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr, addrbuf, sizeof(addrbuf)));
            break;
#if 0
        case AF_INET6:
            ++i;
            printf("%d. %s : %s\n", i, ifr->ifr_name, inet_ntop(ifr->ifr_addr.sa_family, &((struct sockaddr_in6*)&ifr->ifr_addr)->sin6_addr, addrbuf, sizeof(addrbuf)));
            break;
#endif
      }
      ifr = (struct ifreq*)((char*)ifr +_SIZEOF_ADDR_IFREQ(*ifr));
    }
    close(socketfd);
  }
  else {
    printf(" Failed!\n");
  }
  return 0;
}

Poll as in you want to be notified if an interface is added or removed? Or polled as in you just want to find out the interface names once from the system? If the latter, take a look at getifaddrs() .

Please see http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libmnl.git;a=blob;f=examples/rtnl/rtnl-link-dump.c;hb=HEAD on how to get the list of interfaces on Linux. AF_ROUTE is some BSD thing and the use of ioctl is discouraged on Linux for its apparent limitations (such as to convey multiple addresses on a single interface).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM