Roecrew Roecrew - 2 months ago 6
C Question

ifreq's ifr_names are incorrect?

The following function determines if a given string is a valid network device name.




int isValidNDevice(char *name) {

char data[4096];
struct ifconf ifc;
struct ifreq *ifr;
int sk;
int nIntfcs;

sk = socket(AF_INET, SOCK_DGRAM, 0);
if(sk < 0)
{
perror("socket");
return 0;
}

ifc.ifc_len = sizeof(data);
ifc.ifc_buf = (caddr_t)data;
if(ioctl(sk, SIOCGIFCONF, &ifc) < 0)
{
perror("ioctl(SIOCGIFCONF)");
return 0;
}

ifr = (struct ifreq*)data;
nIntfcs = ifc.ifc_len / sizeof(struct ifreq);
for(int i=0; i < nIntfcs; i++)
{
safe_printf("%s\n", (&ifr[i])->ifr_name);
if (!strcmp((&ifr[i])->ifr_name, name)) {
return 1;
}
}

return 0;
}





When I run this function, I receive the following output.





lo0

stf0

�2�>S

en1j

0





This code worked fine a few months ago. What has changed? Am I doing something incorrectly?

OS: OSX El Capitan

Answer

The array of structures returned by the SIOCGIFCONF IOCTL are not of the same size in OSX. They will have a field ifr->ifr_addr.sa_lenwhich will be different for each structure

Modified function to take care of this. Hope it helps:

int isValidNDevice(char *name) {

    char data[4096];
    struct ifconf ifc;
    struct ifreq *ifr;
    int sk,length;

    sk = socket(AF_INET, SOCK_DGRAM, 0);
    if(sk < 0)
    {
        perror("socket");
        return 0;
    }

    ifc.ifc_len = sizeof(data);
    ifc.ifc_buf = (caddr_t)data;
    if(ioctl(sk, SIOCGIFCONF, &ifc) < 0)
    {
        perror("ioctl(SIOCGIFCONF)");
        return 0;
    }

    ifr = (struct ifreq*)data;
    for(int i=0;i<ifc.ifc_len;)
    {
        length=IFNAMSIZ + ifr->ifr_addr.sa_len;
        printf("%s\n", ifr->ifr_name);
        if (!strcmp(ifr->ifr_name,name)) {
            printf("Interface Found!\n");
            return 1;
        }
        ifr=(struct ifr*)((char*)ifr+length);
        i+=length;
    }

    return 0;
}