my c program not able to detect en0 interface

Hi,
I have written the below program which will detect all the ethernet interface name. it is running fine and detect all interface name in linux but when i run the same program in qnx i m getting only " lo "
interface name i.e loopback interface name. i dont know why it is not detecting the en0. please tell me the solution.

#include<sys/types.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include <errno.h>
#include <net/if.h>
#include<stdio.h>

int main()
{
struct ifconf ifc;
char buff[2048];
struct ifreq *ifr;
struct sockaddr *sa;
int i,skfd;
char netaddr[1048];
struct sockaddr_in *ptr;

ifc.ifc_len = sizeof(buff);
ifc.ifc_buf = buff;

if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
    printf("new socket failed\n");
    exit(1);
}

if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
    printf("SIOCGIFCONF:Failed \n");
    exit(1);
}

ifr = ifc.ifc_req;

for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
{
        printf("found device %s,\n", ifr->ifr_name);
        printf ("\n");
}
return 0

}

Debjyoti,

Maybe there aren’t any other ethernet interfaces.

Can you post the result of ‘ifconfig’

You just may have ethernet cards that aren’t supported by QNX or may need to start the drivers manually in order to get your cards recognized.

Tim

I’m using getifaddrs instead of the ioctl. I believe ioctl is limited in size, or it return only the interfaced binded to the socket, not sure.

int rc = getifaddrs(&ifaphead);
if (rc) …

for (struct ifaddrs* ifap = ifaphead; ifap; ifap = ifap->ifa_next)
{
if (ifap->ifa_addr)
{

}
}

freeifaddrs( ifaphead );

Hi Tim,
my ithernet card driver is installed. and i m getting this information after giving command
ifconfig.

lo0: flags=8009<UP,LOOPBACK,MULTICAST> mtu 33212
capabilities=7<IP4CSUM,TCP4CSUM,UDP4CSUM>
enabled=0<>
inet 127.0.0.1 netmask 0xff000000
en0: flags=8c43<UP,BROADCAST,RUNNING,OACTIVE,SIMPLEX,MULTICAST> mtu 1500
capabilities rx=7<IP4CSUM,TCP4CSUM,UDP4CSUM>
capabilities tx=6<TCP4CSUM,UDP4CSUM>
enabled=0<>
address: 00:0f:fe:28:76:a6
inet 192.168.7.65 netmask 0xffffff00 broadcast 192.168.7.255

Tim .
i am sure that en0 interface is up and running . My program is bit alright it seems. please tell me any changes i have to make ,

#include<sys/types.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include <errno.h>
#include <net/if.h>
#include<stdio.h>

int main()
{
struct ifconf ifc;
char buff[2048];
struct ifreq *ifr;
struct sockaddr *sa;
int i,skfd;
char netaddr[1048];
struct sockaddr_in *ptr;

ifc.ifc_len = sizeof(buff);
ifc.ifc_buf = buff;

if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
printf(“new socket failed\n”);
exit(1);
}

if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
printf(“SIOCGIFCONF:Failed \n”);
exit(1);
}

ifr = ifc.ifc_req;

for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
{
printf(“found device %s,\n”, ifr->ifr_name);
printf ("\n");
}
return 0
}

Debjyoti,

Why don’t you try Mario’s suggestion.

Tim

Tim,
i use getifaddrs as Mario suggested me to do. But i dont know why SIOCGIFCONF is not working

Debjyoti,

OK, I took your sample code, looked at it in the debugger and got it to work by doing the following:

#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <errno.h> 
#include <net/if.h> 
#include <stdio.h> 
#include <stdlib.h>
#include <string.h>

int main() 
{ 
	struct ifconf ifc; 
	char buff[2048]; 
	struct ifreq *ifr; 
	struct sockaddr *sa; 
	int i,skfd; 
	char netaddr[1048]; 
	struct sockaddr_in *ptr; 
	struct ifreq data;
	
	
	ifc.ifc_len = sizeof(buff); 
	ifc.ifc_buf = buff; 
	
	if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0)
	{ 
		printf("new socket failed\n"); 
		exit(1); 
	} 
	
	if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
	{ 
		printf("SIOCGIFCONF:Failed \n"); 
		exit(1); 
	} 
	
	ifr = ifc.ifc_req; 
	printf ("Length is %d vs %d\n", ifc.ifc_len, sizeof(struct ifreq));
	memcpy (&buff, ifc.ifc_req, ifc.ifc_len);

	int offset = 0;
	for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0;) 
	{ 
		memcpy(&data, buff+offset, sizeof(struct ifreq));
		if (i&1)
		{
			offset += sizeof(struct ifreq)+4;
		}
		else
		{
			offset += sizeof(struct ifreq);
		}
		printf("found device %s,\n", data.ifr_name); 
		printf ("\n"); 
	} 
	return 0;
}

What I first noticed was that the length didn’t divide into structure size evenly. That mean there were some extra bytes someplace that was messing up your ptr code.

So I copied the data into buff and looked at it in the debugger and noticed that every every interface (I have lo0 and en0) was repeated twice with 4 extra bytes on the 2nd repeat. I have NO idea why this is but it means the header file (net/if.h) is not correct with the union definition.

So I manually computed the offsets to the data and now it prints:

lo0
lo0
en0
en0

Tim

Here is some other code I digged up:

int GetLocalIPAddr ( const string &interface )
{
int sock;
struct sockaddr_in Sockaddr;
struct ifconf d;
struct ifreq *ifr,
*end,
*cur,
*temp;
char buffer[128];

printf ("GetLocalIPAddr for %s\n", interface.c_str() );
if ( ( sock = socket ( PF_INET, SOCK_DGRAM, 0 ) ) == -1 ) 
{
  	perror ("socket");
	return -1;
}

// temporary storage for getting broadcast address
temp = (struct ifreq *)buffer;

d.ifc_len= 4096;
d.ifc_buf= (char *)malloc (d.ifc_len);

if ( ioctl ( (short)sock, (long) SIOCGIFCONF, &d ) == -1) 
{
	perror ("ioctl (SIOCGIFCONF)");
	close( sock );
	return -1;
}

// Note that the ifreq structure is variable length so
// we have to step along the structure by the size of
// the previous structure 

ifr= (struct ifreq *) d.ifc_req;
end= (struct ifreq *) ((char *) ifr + d.ifc_len);
while (ifr < end) 
{
	cur = ifr;
  	//step along the array by the size of the 
    //current structure 
  	ifr= (struct ifreq *)((char *)ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);

  	// if this isn't in the INET address family ignore
	if ( cur->ifr_addr.sa_family != PF_INET )
    	continue;   

  	//save aside the ifr structure to get the broadcast addr 
	
  	memcpy ( temp, cur, cur->ifr_addr.sa_len + IFNAMSIZ );

	//ntohl ( ( (struct sockaddr_in *) &cur->ifr_addr)->sin_addr);
	memcpy ( &Sockaddr, (struct sockaddr_in *) &cur->ifr_addr,  sizeof( struct sockaddr_in) );

  	// get the flags for this interface 
  	if (ioctl ( (short)sock, (long) SIOCGIFFLAGS, (char *) cur) < 0) 
  	{
		perror ("ioctl (SIOCGIFFLAGS)");
		close( sock );
		return -1;
	}

	if ( interface == cur->ifr_name )
  	{
  		printf("got a match\n");
  		close ( sock );
		return (UINT32)htonl ( Sockaddr.sin_addr.s_addr );
  	}

/*
  	// if the interface is up, print out some information about it
  	if ( cur->ifr_flags & IFF_UP ) 
  	{
  		printf("It's up\n");
  		close( sock );
		return (UINT32)htonl ( Sockaddr.sin_addr.s_addr );
	}
*/
	
  			 
	
}

close ( sock );
return 0;

}

The issue is that a struct sockaddr_dl won’t fit in the
union of a struct ifreq (sizeof(struct sockaddr_dl) >
sizeof(struct sockaddr)). The common way to handle this
is below (eg libpcap does something similar). Note
this has been addressed in the next release and all
ioctls using a struct ifreq have been versioned. The
code below will be continue to work going forward.

-seanb

/*

  • Example demonstrating a common pitfal with SIOCGIFCONF handling.
    */

#include <sys/sockio.h>
#include <net/if.h>
#include <malloc.h>
#include <stdlib.h>
#include <err.h>
#include <ifaddrs.h>

void gifconf(int);
void gifaddrs(int);

int
main(void)
{
int s;

    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
            err(EXIT_FAILURE, "socket");

    gifconf(s);     /* Old code often used SIOCGIFCONF ioctl        */
    gifaddrs(s);    /* New code should use getifaddrs()             */

    close(s);

    return 0;

}

void
gifconf(int s)
{
struct ifconf ifc;
struct ifreq *inext, *iend, *icur;
size_t size;

    size = 4096;
    ifc.ifc_len = size;
    if ((ifc.ifc_buf = malloc(ifc.ifc_len)) == NULL)
            err(EXIT_FAILURE, "malloc");
    if (ioctl(s, SIOCGIFCONF, &ifc) == -1)
            err(EXIT_FAILURE, "SIOCGIFCONF");

    if (ifc.ifc_len >= size) {
            /* realloc and try again */
            errx(EXIT_FAILURE, "SIOCGIFCONF: buf too small");
    }

    inext = ifc.ifc_req;
    iend = (struct ifreq *)(ifc.ifc_buf + ifc.ifc_len);
    for (;;) {
            icur = inext;

#if 0
/*
* Broken code. This would happen to work for most cases
* because previously:
*
* sizeof(struct sockaddr) + IFNAMSIZ == sizeof(struct ifreq)
*
* Under this scenario the two ‘if’ cases in the working
* case below work out to the same thing.
*/
inext = (struct ifreq *)
((char )inext + inext->ifr_addr.sa_len + IFNAMSIZ);
#else
/
This will work against old / new libsocket */
if (inext->ifr_addr.sa_len + IFNAMSIZ > sizeof(struct ifreq))
inext = (struct ifreq *)
((char *)inext + inext->ifr_addr.sa_len + IFNAMSIZ);
else
inext++;
#endif
if (inext > iend)
break;

            /* process icur */
    }

    free(ifc.ifc_buf);

}

void
gifaddrs(int s)
{
struct ifaddrs *ifaddrs, *ifap;

    if (getifaddrs(&ifaddrs) == -1)
            err(EXIT_FAILURE, "getifaddrs");

    for (ifap = ifaddrs; ifap != NULL; ifap = ifap->ifa_next) {
            continue;
    }

    freeifaddrs(ifaddrs);

}

hi
Tim
Thnx for the answer. it is working fine .