How can I prevent SIOCGIFADDR from failing?

10,272

Since I was looking for the answer to the original question, I'll officially write up the answer that Mark Plotnick gave above as a comment based on the further research by the person posing the question:

SIOCGIFADDR fails with errno set to EADDRNOTAVAIL if there's no address is assigned to the interface. As the original questioner discovered, to stop it from failing, set the interface's IP address.

strerror() translates EADDRNOTAVAIL to "Cannot assign requested address" which is misleading to the point of being wrong in this situation where you're reading the address, not assigning it.

Share:
10,272

Related videos on Youtube

staroselskii
Author by

staroselskii

Updated on September 14, 2022

Comments

  • staroselskii
    staroselskii over 1 year

    I want to get the eth0's IP. Here is what I've written (maybe there is a way around it?):

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    check(sockfd > 0, "cannot create socket\n");
    
    #define INTERFACE_NAME "eth0"
    #define INTERFACE_NAME_LENGTH 4
    
    char *opt = INTERFACE_NAME;
    rc = setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, opt, INTERFACE_NAME_LENGTH);
    check(rc == 0, "BINDTODEVICE failed");
    
    struct ifreq req;
    strncpy(req.ifr_name, INTERFACE_NAME, IFNAMSIZ);
    rc = ioctl(sockfd, SIOCGIFADDR, (unsigned long)&req);
    check(rc == 0, "SIOCGIFADDR failed");
    server_ip = ((struct sockaddr_in*)&req.ifr_addr)->sin_addr.s_addr;
    char str[50];
    inet_ntop(AF_INET, &(server_ip), str, INET_ADDRSTRLEN);
    debug("serverip: %s", str);
    
    return sockfd;
    
    error:
    if (sockfd) close(sockfd);
    exit(1); 
    

    I get the following error:

    [ERROR] (src/server/server.c:43: errno: Cannot assign requested address) SIOCGIFADDR failed

    If I use the same method with wlan0, I get what I'd expected to see.

    Here is the netstat output:

    netstat -tulpn:

    Proto | Local Address   |  PID
    
    udp   | 0.0.0.0:16313   | 4666/dhclient   
    udp   | 0.0.0.0:68      | 4687/dhclient   
    udp   | 0.0.0.0:68      | 4666/dhclient 
    

    So, I figure that I can't assign the address because of the dhclients? Why there are so many of them? and why there is one on the 16313 port?

    UPD:

    I added

    auto eth0
    iface eth0 inet static
            address 192.168.1.1
            netmask 255.255.255.0
    

    to /etc/network/interfaces and restarted the networking and got some progress:

    DEBUG src/server/server.c:50: serverip: 192.168.1.1
    

    and then I can successfully bind the socket, but the connection dies for no reason in a couple of seconds.

    • Mark Plotnick
      Mark Plotnick about 10 years
      I think you need a req.ifr_addr.sa_family = AF_INET to tell the SIOCGIFADDR call what type of address you want.
    • staroselskii
      staroselskii about 10 years
      @MarkPlotnick Unfortunately, it didn't help! I used this piece of code: man7.org/linux/man-pages/man3/getifaddrs.3.html and it's said that eth0 is AF_PACKET. No idea why!
  • staroselskii
    staroselskii about 10 years
    Isn't the same as I've posted above?
  • Santhosh Pai
    Santhosh Pai about 10 years
    as the other person pointed above you have missed the line req.ifr_addr.sa_family = AF_INET
  • staroselskii
    staroselskii about 10 years
    As I've written above, the line didn't help :-(