LINUX.ORG.RU

Как в С/С++ узнать, что интерфейс получил IP адрес?


0

1

Всем привет!

В двух словах задача примерно следующая: Когда к системе подключается USB-LAN адаптер, надо сперва запустить DHCP клиент, если тот не смог определить адрес, то надо или запустить avahi-autoipd или выставить статичеаский адрес. Имею udhcp в busybox. Понимаю, что частично можно задачу спихнуть в udhcp скрипт, но хочется все сделать в одной моей программе. Итак запустил я udhcp с конфигурацией: " выйди, если не смог определить адрес". Отслеживаю, когда udhcp заканчивает работу. Теперь надо определить получил ли адаптер «eth1» IP адрес. Делаю то, что нашел в гугле:

       sock_fd = socket( AF_INET , SOCK_DGRAM , 0 );
       strcpy( ifr.ifr_name , "eth1" );
       ioctl( sock_fd , SIOCGIFADDR , &ifr );
       printf("IP=%s\n", inet_ntoa( ((struct sockaddr_in *) (&ifr.ifr_addr))->sin_addr ) );
       close( sock_fd );
Печатает правдивый адрес, когда был в сам деле получен и что-то типа:

IP=201.0.8.107

когда Ethernet кабель был выдернут и ifconfig показвает, что адаптер никакого адреса не получил. Естественно вопрос: ЧЯДНТ и как решить проблемку?

Всем заранее спасибо velik


почему бы не посмотреть как это делает ifconfig?

s0L
()
Ответ на: комментарий от mky

почему бы не посмотреть как это делает ifconfig?

Там Хрен ногу сломит.

И при этом ioctl() не возвращает ошибку?

С чего ему возвращать ошибку? Адаптер существует ведь. Таки вот такая штука работает на ура:

    int fd;
    struct ifreq ifr;

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    ifr.ifr_addr.sa_family = AF_INET;
    strncpy(ifr.ifr_name, "eth1", IFNAMSIZ-1);

    /*
    SIOCGIFFLAGS, SIOCSIFFLAGS
                 Get or set the active flag word of the device.  ifr_flags contains a
                 bit mask of the following values:

                                            Device flags
                 IFF_UP            Interface is running.
                 IFF_BROADCAST     Valid broadcast address set.
                 IFF_DEBUG         Internal debugging flag.
                 IFF_LOOPBACK      Interface is a loopback interface.
                 IFF_POINTOPOINT   Interface is a point-to-point link.
                 IFF_RUNNING       Resources allocated.
                 IFF_NOARP         No arp protocol, L2 destination address not set.
                 IFF_PROMISC       Interface is in promiscuous mode.
                 IFF_NOTRAILERS    Avoid use of trailers.
                 IFF_ALLMULTI      Receive all multicast packets.
                 IFF_MASTER        Master of a load balancing bundle.
                 IFF_SLAVE         Slave of a load balancing bundle.
                 IFF_MULTICAST     Supports multicast
                 IFF_PORTSEL       Is able to select media type via ifmap.
                 IFF_AUTOMEDIA     Auto media selection active.
                 IFF_DYNAMIC       The addresses are lost when the interface goes
                                   down.
                 IFF_LOWER_UP      Driver signals L1 up (since Linux 2.6.17)
                 IFF_DORMANT       Driver signals dormant (since Linux 2.6.17)
                 IFF_ECHO          Echo sent packets (since Linux 2.6.25)

                 Setting the active flag word is a privileged operation, but any process
                 may read it.
*/
    ioctl(fd, SIOCGIFFLAGS, &ifr);
    printf("Flag=%x\n", ifr.ifr_flags );


    if( ( ifr.ifr_flags & ( IFF_UP | IFF_RUNNING ) ) == ( IFF_UP | IFF_RUNNING ) )
    {
        resolved = true;
    }
    else
    {
        resolved = false;
    }

velikS
() автор топика
Ответ на: комментарий от velikS

С чего ему возвращать ошибку?

Да сам не знаю, но в исходниках ifconfig зачем-то проверяют возвращаемое значение системного вызова ioctl():

#if HAVE_AFINET
    /* IPv4 address? */
    fd = get_socket_for_af(AF_INET);
    if (fd >= 0) {
        strcpy(ifr.ifr_name, ifname);
        ifr.ifr_addr.sa_family = AF_INET;
        if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
            ife->has_ip = 1;
            ife->addr = ifr.ifr_addr;
            strcpy(ifr.ifr_name, ifname);
            if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
                memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
            else
                ife->dstaddr = ifr.ifr_dstaddr;

но это явно параноя, проверять return-code, этож Си.

Но, почему то, у меня на CentOS так:

[root@ ~]# ip addr flush dev eth2
[root@ ~]# ip addr add 1.2.3.4/32 dev eth2
[root@ ~]# strace ifconfig eth2 2>&1 | grep SIOCGIFADDR
ioctl(4, SIOCGIFADDR, {ifr_name="eth2", ifr_addr={AF_INET, inet_addr("1.2.3.4")}}) = 0
[root@ ~]# ip addr flush dev eth2
[root@ ~]# strace ifconfig eth2 2>&1 | grep SIOCGIFADDR
ioctl(4, SIOCGIFADDR, {ifr_name="eth2", ???}) = -1 EADDRNOTAVAIL (Cannot assign requested address)
[root@ ~]# uname -a
Linux  2.6.18-194.32.1.el5 #1 SMP Thu Jan 20 19:06:41 EST 2011 x86_64 x86_64 x86_64 GNU/Linux
А у вас какое ядро?

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