Опрос имен интерфейсов через SIOCGIFCONF в Linux - PullRequest
4 голосов
/ 08 февраля 2011

Я пытаюсь опросить имена сетевых устройств. Я собрал это воедино из разных фрагментов,

  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

Но мой вывод - просто бред.

#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;
}

Выход:

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?$?|??|?@

Я попытался вывести каждый символ массива ifr_name один за другим, чтобы увидеть, завершены ли они нулем, но это мало что изменило. Каждая итерация моей программы выводит что-то свое, и это заставляет меня думать, что я ссылаюсь на что-то неправильно. Может ли кто-нибудь дать мне представление о том, что я могу делать неправильно?

Ответы [ 3 ]

7 голосов
/ 04 ноября 2011

Вот код, который я собрал для 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;
}
1 голос
/ 09 февраля 2011

Опрос как вы хотите получать уведомления, если интерфейс добавлен или удален? Или опросили, так как вы просто хотите узнать имена интерфейсов один раз из системы? Если последнее, взгляните на getifaddrs () .

0 голосов
/ 09 февраля 2011

Пожалуйста, смотрите http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libmnl.git;a=blob;f=examples/rtnl/rtnl-link-dump.c;hb=HEAD о том, как получить список интерфейсов в Linux.AF_ROUTE - это что-то вроде BSD, и использование ioctl не рекомендуется в Linux из-за очевидных ограничений (таких как передача нескольких адресов в одном интерфейсе).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...