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

Re: Перечисление сетевых интерфейсов.



>>>>> On Fri, 22 Feb 2002 19:11:47 +0300
>>>>> "Mikhail" == Mikhail Nikitin <mouse@uslugionline.ru> wrote:
Mikhail> 
>> > Есть такая проблема: необходимо получить список всех активных сетевых
>> > интерфейсов (eth0, lo, eth1.. etc), а также присвоенные им ip-адреса при
>> > условии, что программа запускается от обычного пользователя а также
>> > (возможно), что в /proc/ прочитать ничего нельзя (/proc/net/dev.. etc...)
>> >
>> > Чем бы это дело обстряпать? (Прога пишется на С++)
>> 
>> Сделать сокет и подергать за его ioctl-и. Есть перловый модуль
>> IO::Interface на CPAN. Его стоит взять и прочитать.
>> Исходник там, кстати, C-шный. А в книжке Линкольна Штайна
>> "Сетевое программирование на Perl" есть перловый эквивалент.
>> 
Mikhail> Хм... вот про ioctl было интересно (к перлу у меня органическое отвращение
Mikhail> ;-(, так что он не подходит...)
Mikhail> Как это за него дергать?

# include <stdio.h>
# include <stdlib.h>
# include <errno.h>
# include <unistd.h>
# include <sys/types.h>

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

int main(int argc, char* argv[]){
  struct ifconf ifc;
  struct ifreq *ifr, ifrcopy;
  int flags;
  char *buf, *ptr;
  int len;
  int sockfd;
  struct sockaddr_in *sad;

  sockfd = socket(AF_INET,SOCK_DGRAM,0);

  if ( sockfd == -1 ) {
    perror ("socket");
    return 1;
  }

  len = 100 * sizeof(struct ifreq);
  buf = malloc(len);
  ifc.ifc_len = len;
  ifc.ifc_buf = buf;
  if ( ioctl(sockfd, SIOCGIFCONF, &ifc ) == -1) {
    if ( errno != EINVAL ) {
      perror("ioctl");
      return 2;
    }
    else
      printf("not all interfaces fit in buf\n");
  }
  for (ptr = buf; ptr < buf + ifc.ifc_len; ){
    ifr = (struct ifreq *)ptr;
# if 1
    ptr += sizeof (ifr->ifr_name) + sizeof(struct sockaddr);
# else
    ptr += sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len;
# endif

    ifrcopy = *ifr;
    ioctl(sockfd,SIOCGIFFLAGS,&ifrcopy);
    flags = ifrcopy.ifr_flags;

    if ( (flags & IFF_UP) == 0 ) continue; /* interface is down */

    sad = (struct sockaddr_in *)(&ifr->ifr_addr);
    printf("%s %s\n", ifr->ifr_name, 
	              inet_ntoa( sad->sin_addr) );

  }
  return 0;
}
Есть там некоторый тарабл с тем, что ioctl заполняет массив из 
struct ifreq {
 ...
 union {
   struct sockaddr
   ...
 }
 ...
}
так у struct sockaddr может быть (более или менее свежий BSD), а может
и не быть (linux, например) sin_len, соответствеено в коде есть # if 1
под linux, дабы под BSD работало надо 1 заменить на 0.

Mikhail> Сокет-то мы создадим, а вот дальше? У меня тут злой MFC-программер под
Mikhail> боком сидит и жужжит что под виндами это enum-одной функцией а дальше в
Mikhail> цикле перечисление интерфесов... нужели в Linux такого нет?

Да ну... что-то не верится

-- 
Alexander Kotelnikov
Saint-Petersburg, Russia

Reply to: