LINUX.ORG.RU

знаю только по поводу имени хоста:

#include <unistd.h> ... char* p; int c; c=gethostname(p,80); ...

BreadFan ★★
()

вообще если тебе известно то IP адреса привязаны не к хосту а к сетевому интрефейсу. У хоста же может быть более одного таких интерфейсов - таким образом если к каждому интрфейсу привязан IP адрес то у хоста получается более одного IP адреса.. как ты думаешь как бы был устроен интернет если бы у хоста было не более одного IP адреса? :)

Если тебе интересно знать некий IP адрес значит скорее всего у тебя есть какой-то сокет с которым ты работаешь - например всял и приконнектился куда-нибудь. Когда ты начинаешь коннектиться [без bind()] то IP стек твоей ОС должен произвести это за тебя, он в соответствии со своей таблицей роутинга и всяких дополнительных хрений определяет к какому интерфейсу а соответственно к какому IP адресу тебя забиндить. После этого ты сможешь узнать куда тебя зацепили с помощью вызова getsockname() из libc

lg ★★
()

Просто первый попавшийся IP твоей тачки, если первый аргумент "":
/*
    ATTENTION! The following function uses non-reentrant gethostbyname() and
    inet_ntoa() functions! Not thread-safe, not re-entrant!

    ATTENTION! Some linux libc6 + ldap will chrash on gethostbyname(), when the program is
    linked statically!

    This function tries to find the current host IP, if buf="", otherwise
    it determines the IP of the named host:
*/
char *defip(char *buf, size_t len)
{
    struct hostent *hp;
    size_t i;
    char *ptr;
         
       if( (*buf == '\0')&&
           ( gethostname(buf,len)!=0 )
         )  return NULL;
       /*Now in buf is the name!*/
            
       if( (hp=gethostbyname(buf))==NULL ) /*Crash under Linux? Set "ldap" after "dns"
                                  in "hosts" entry in /etc/nsswitch.conf */
          return NULL;
       len--;/*What about he last '\0'?*/
       ptr=inet_ntoa(*(struct in_addr *)(hp->h_addr));
       /*Just copy - to be independent on "string.h":*/
       for(i=0;i<len; i++)
          if(  (buf[i] = ptr[i])=='\0'  )break;
       buf[i]='\0';

       return buf;

}/*defip*/

Die-Hard ★★★★★
()

2Die-Hard: все замечательно, но что если у хоста нет hostname или нет записи в /etc/hosts и в DNS ? на самом деле можно по очереди пройтись по всем интерфесам и снять с них IPишники.

lg ★★
()
Ответ на: комментарий от lg

lg (*) (2002-11-28 01:00:51.606):
> но что если у хоста нет hostname или нет записи в /etc/hosts и в DNS
А такое возможно?
В смысле, IMHO половина сетевых служб просто не будет работать.
Т.е. отсутствие hostname я воспринимал как криво поставленную систему.
Или я не прав?

> ...можно по очереди пройтись по всем интерфесам и снять с них IPишники.
А как?

Die-Hard ★★★★★
()

2Die-Hard:
> Т.е. отсутствие hostname я воспринимал как криво поставленную систему
Впринципе оно то так и есть, но все равно, например sendmail, sshd, apache должны работать без проблем. У чувака вообще может не быть этих служб и ему не нужно иметь в хостах или днс свой hostname или вообще иметь hostname.

>> ...можно по очереди пройтись по всем интерфесам и снять с них IPишники.
> А как?
как это делает ifconfig например

lg ★★
()
Ответ на: комментарий от lg

lg (*) (2002-11-28 18:30:49.794):
>> А как?
> как это делает ifconfig например
А ты знаешь, как она это делает? Я, конечно, как-нибудь сам исходники поищу,
но, сильно сдается мне, ifconfig в каждой системе взаимодействует с ядром
по-своему. Меня же интересует только достаточно портабильное решение.

Die-Hard ★★★★★
()

портабельное решение это создать сокет - начать куда нибудь коннектиться и брать getsockname() от него ..

lg ★★
()
Ответ на: комментарий от lg

lg (*) (2002-11-29 10:18:24.536):
> начать куда нибудь коннектиться и брать getsockname() от него
Спробовал, действительно, можно.
Но - меня терзают смутные сомнения насчет портабильности...
 
Такая идея сходу проходит для клиента, стучащегося
на живой сервер. Иначе:

1. bind() на INADDR_ANY даст IP 0.0.0.0
2. чтобы куда-нибудь успешно законнектиться, надо по меньшей мере знать
чужой IP  и, главное, порт.
3. При попытке коннектиться на 127.0.0.1 получим его же.
4. Конечно, проигнорировав код возврата от коннекта, можно, рыпнувшись на 
некий не существующий адрес, снять потом с сокета имя, но - после могучего 
таймаута. (Кстати, помнится, пара IP адресов специально зарезервировано
для таких целей - кто помнит?)
5. Выход - сделать сокет неблокирующим. Тогда такое вот проканало
на моем Линухе с одной сетевухой:

if ((sock = socket(PF_INET,SOCK_STREAM,0)) <= 0)
  return -1;

fcntl(sock, F_SETFL, O_NONBLOCK);

memset(&address,'\0',sizeof(struct sockaddr_in));
address.sin_family = AF_INET;
address.sin_port = 0;
address.sin_addr.s_addr=inet_addr("1.1.1.1");

connect(sock,(struct sockaddr *)&address,sizeof(address));

if( getsockname(sock,(struct sockaddr *)&address,&addrlen ) )
  return 2;

printf("Local IP address is: %s\n",inet_ntoa(address.sin_addr));

close(sock);

Но на Альфе (OSF1) и Солярке возвращается 0.0.0.0

Если я заменяю address.sin_port=1, то правильно работает на всех трех 
платформах. Но - уж больно много игнорирования ошибок! Есть ли гарантия,
что оно везде сработает как надо? Например, какой-нибудь кэширующий DNS
на вторую попытку соединения немедленно ответит, что нет такого адреса, 
и IP стек грохнет привязку локального сокета - на всякий случай.

И, потом, похоже (не уверен), оно таким образом порты шибко блокирует.

Die-Hard ★★★★★
()

насколько я помню для экспериментов зарезевлены все адреса начиная с 224.0.0.0 до конца.

>Если я заменяю address.sin_port=1, то правильно работает на всех трех платформах. Но - уж больно много игнорирования ошибок!

где ошибки-то? все нормально .. чтобы сработал getsockname() главное проблема чтобы IP стек отработал и определил тебе адрес на который надо забиндиться. После этого понятное дело все будет пучком

sin_port = 0; не сработало в некоторых системах потомучто скорее всего дело обламилось в какой-нибудь тупой проверке if (sin_port == 0) goto bad; и до IP стека дело не дошло.

еще момент такой что после того как вызвал connect() надо некоторое время(чтобы хватило IP стеку определить source address) поспать и после этого делать getsockname(), например войти в select() с маленьким таймаутом .. посмотреть что вернет и это позволит узнать произошла ли ошибка во время connect() типа no route to host

вообщем мне все это не нравится

lg ★★
()

Да, ребята, была у меня тоже такая задача: узнать ипи адреса машины, причём все, причём, желательно внешние, т.е. исключая 127.0.0.1 и 192.х.х.х. Но после просмотра манов по поводу работы с системными запросами сетевых устройств, я взял слив из пайпа форкнутого процесса, где запустил ifconfig, и написал маленький парсер. Это оказалось самое реальное и быстрое. Если кто может послать исходники, как всё это вырвать из ядра без запуска ifconfig, буду очень благодарен. Васильев Иван

anonymous
()

2anonym: как ты думаешь ifconfig запускает ifconfig для того вырезать все интерфейсы и IPишники?

PS: чтобы понять рекурсию сначала надо понять рекурсию

lg ★★
()
Ответ на: комментарий от anonymous

anonymous (*) (2002-11-29 19:31:29.226):
> ...где запустил ifconfig, и написал маленький парсер.
Совсем не интересно с точки зрения портабильности: буквально каждая система
имеет свои ключи и свой формат вывода ifconfig'а

Die-Hard ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.