Accessing ifnet variables (a la netstat)

Hi there,

I’m writing a program that needs access to network interface information
contained in the ifnet structure (in net/if.h). There is no “sysctl” in
QNX4, and as far as I can tell, there are no ioctls to give me the data
either. Is there a special request to get Net or Socket to give me that
info?

I’m using Watcom C 10.6, under 4.25J

Thanks,

-Jim

“There’s always one more bug…”
– Bubba DuPree (1986)

James Winton <spamthis@home.com> wrote:

Hi there,

I’m writing a program that needs access to network interface information
contained in the ifnet structure (in net/if.h). There is no “sysctl” in
QNX4, and as far as I can tell, there are no ioctls to give me the data
either. Is there a special request to get Net or Socket to give me that
info?

I’m using Watcom C 10.6, under 4.25J

Thanks,

-Jim

“There’s always one more bug…”
– Bubba DuPree (1986)

Here is a simple program I cooked up. Should work on both Q4 and Q6.
Make sure you all -lsocket on the compile line.

Of course the hostname environment variable is not overly usefull. In
Q6 I am using confstr, and in Q4 I am using code snippet 2 to set and read
the host name from Sock[l]et.

regards,
Tom



-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <sys/iomsg.h>
#include <net/if.h>
#include <sys/sockio.h>
#include <errno.h>
#include <sys/netmgr.h>
#include <arpa/inet.h>

int main()

{

int sock;
struct ifreq ifreq;
struct sockaddr_in server;
strcpy( ifreq.ifr_name, “en0” );

sock = socket(AF_INET, SOCK_STREAM, 0);
if ( sock < 0 )
{
perror(“socket”);
return 1;
}

ioctl( sock, SIOCGIFADDR, &ifreq );
memcpy( &server, &ifreq.ifr_ifru.ifru_addr, sizeof( server ));
printf( “IP Address = %s\n”, inet_ntoa( server.sin_addr ));

printf( “Host Name = %s\n”, getenv(“HOSTNAME”) );

ioctl( sock, SIOCGIFNETMASK, &ifreq );
memcpy( &server, &ifreq.ifr_ifru.ifru_addr, sizeof( server ));
printf( “Mask = %s\n”, inet_ntoa( server.sin_addr ));
}


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

////////////////////////////////////////////////////////////////////////////////

#define _SOCK_GETHOSTNAME 0x193
struct _sock_gethostname {
msg_t code;
short namelen;
char name[];
};
struct _sock_gethostname_reply {
msg_t status;
short namelen;
char name[];
};


#define _SOCK_SETHOSTNAME 0x194
struct _sock_sethostname {
msg_t code;
short namelen;
char name[];
};

struct _sock_sethostname_reply {
msg_t status;
short namelen;
char name[];
};

typedef union SocketMsg {
struct _sock_gethostname gethostname;
struct _sock_gethostname_reply gethostnameReply;
struct sock_sethostname sethostname;
struct sock_sethostname_reply sethostnameReply;
char zero[ 300 ];
} SocketMsg_t;


////////////////////////////////////////////////////////////////////////////////
int NetworkManager::GetHostName( char *name
, size_t len
)
{
SocketMsg msg;
pid_t pid;

msg.gethostname.code = _SOCK_GETHOSTNAME;
msg.gethostname.namelen = (short) _min( len, 256 );

pid = qnx_name_locate( 0, “qnx/socket”, 1024, 0 );
Send( pid, &msg, &msg, sizeof( msg ), sizeof( msg ) );

if( msg.gethostnameReply.status == 0 )
{
strncpy( name_, msg.gethostnameReply.name, msg.gethostnameReply.namelen );
}
else
{
name_[ 0 ] = ‘\0’;
}

return msg.gethostnameReply.status;
}


////////////////////////////////////////////////////////////////////////////////
int NetworkManager::SetHostName( char *name_ )
{
SocketMsg msg;
pid_t pid;

msg.sethostname.code = SOCK_SETHOSTNAME;
msg.sethostname.namelen = (short) strlen( name
) + 1; // must include null terminator

strcpy( msg.gethostnameReply.name, name_ );

pid = qnx_name_locate( 0, “qnx/socket”, 1024, 0 );
Send( pid, &msg, &msg, sizeof( msg ), sizeof( msg ) );

return msg.sethostnameReply.status;
}

Thanks, Thomas. I’m able to get the hostname just fine using other means, but I can’t find a
way to get to interface stats described by the “ifnet” structure in “net/if.h”.

However, your suggestion pointed me in some interesting directions. There’s a socket request
in “sys/sock_msg.h” called _SOCK_GETKERNINFO. Above it is a reference to an undocumented
function call, “getkerninfo”. Googling “getkerninfo” yields some info on its BSD heritage.
One reference:

http://www.neosoft.com/neosoft/man/getkerninfo.2.html

So I called it. It’s in the “socket_s” library (-lsocket_s). I had to experiment with a
number of “op” and “arg” values. Significant “op” values are 0x0101 and 0x0102. “arg” values
seem to yield interesting results on modulo 8 numbers (0-7 yield about the same data as 8-15,
etc.)

Some examples:

getkerninfo(0x0101, 0): size’310’ ret’282’
0000 5e 00 02 04 01 00 00 00 07 00 00 00 00 00 03 00
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0030 00 00 00 00 00 00 00 00 00 00 10 02 00 00 00 00
0040 00 00 00 00 00 00 00 00 00 00 10 02 00 00 0a 00
0050 00 01 00 00 00 00 00 00 00 00 00 00 00 00 62 00
0060 02 04 01 00 00 00 07 00 00 00 00 00 01 00 57 b9
0070 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0090 fc ac 06 00 fc ac 06 00 10 02 00 00 0a 00 00 00
00a0 00 00 00 00 00 00 00 00 10 02 00 00 0a 20 12 02
00b0 00 00 00 00 00 00 00 00 05 00 00 00 ff 00 00 00
00c0 5a 00 02 04 02 00 00 00 03 00 00 00 00 00 05 00
00d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00f0 00 00 00 00 00 00 00 00 00 00 10 02 00 00 7f 00
0100 00 01 00 00 00 00 00 00 00 00 10 02 00 00 7f 00
0110 00 01 00 00 00 00 00 00 00 00
getkerninfo(0x0102, 0): size’0’ ret’0’
my_getkerninfo(0x0101, 0): size’310’ ret’282’
0000 5e 00 02 04 01 00 00 00 07 00 00 00 00 00 03 00
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0030 00 00 00 00 00 00 00 00 00 00 10 02 00 00 00 00
0040 00 00 00 00 00 00 00 00 00 00 10 02 00 00 0a 00
0050 00 01 00 00 00 00 00 00 00 00 00 00 00 00 62 00
0060 02 04 01 00 00 00 07 00 00 00 00 00 01 00 57 b9
0070 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0090 fc ac 06 00 fc ac 06 00 10 02 00 00 0a 00 00 00
00a0 00 00 00 00 00 00 00 00 10 02 00 00 0a 20 12 02
00b0 00 00 00 00 00 00 00 00 05 00 00 00 ff 00 00 00
00c0 5a 00 02 04 02 00 00 00 03 00 00 00 00 00 05 00
00d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00f0 00 00 00 00 00 00 00 00 00 00 10 02 00 00 7f 00
0100 00 01 00 00 00 00 00 00 00 00 10 02 00 00 7f 00
0110 00 01 00 00 00 00 00 00 00 00

I also wrote a direct “socket Send” version like your example. It yields the same results as
the “getkerninfo()” call:

#include <unix.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/sock_msg.h>
#include <nlist.h>

/*****************************************************************************/
/
Types */

typedef union SocketMsgHdr
{
struct _sock_nlist nlist;
struct _sock_nlist_reply nlist_reply;
struct _sock_getkerninfo getkerninfo;
struct _sock_getkerninfo_reply getkerninfo_reply;
} SocketMsgHdr_t;

typedef struct
{
SocketMsgHdr_t hdr;
char buf[1024];
} SocketMsg_t;

extern int getkerninfo(int op, caddr_t where, int *size, int arg);

/******************************************************************************/

int
my_getkerninfo(int op, caddr_t where, int *size, int arg)
{
struct _sock_getkerninfo *preq;
struct _sock_getkerninfo_reply *prpy;
SocketMsg_t msg;
int ret;
static pid_t sockpid = 0;

preq = &msg.hdr.getkerninfo;
prpy = &msg.hdr.getkerninfo_reply;

preq->code = _SOCK_GETKERNINFO;
preq->op = op;
preq->size = size ? *size : 0;
preq->arg = arg;

if (!sockpid)
{
sockpid = qnx_name_locate(0, “/qnx/socket”, 1024, 0);
if (sockpid == -1)
{
perror(“locate socket”);
exit(-1);
}
}

if (Send(sockpid, &msg, &msg, sizeof(msg), sizeof(msg)) == -1)
perror(“Send”);

if (size)
{
*size = MIN(*size, prpy->needed);
memcpy(where, prpy->where, *size);
}
return prpy->needed;
}

Does anyone have an idea what Socket is returning here? Or what I’m asking it? Some of the
fields are obviously my machine’s IP and loopback addresses, and maybe the netmask. Might be
useful.

Or not. I’m still looking for interface stats (collisions, packets sent, received, etc.) a la
netstat.

-Jim

“There’s always one more bug…”
– Bubba DuPree (1986)

Does this deafening silence mean there’s no way to access the network
interface stats in QNX4? And while I’m asking impossible questions, how
about the UDP and TCP stats which are displayed in “netstat -s”? Can they
be accessed by a user program, or even a root program?

And does anyone know what the getkerninfo() call returns?

Thanks in advance,

-Jim

James Winton wrote:

Hi there,

I’m writing a program that needs access to network interface information
contained in the ifnet structure (in net/if.h). There is no “sysctl” in
QNX4, and as far as I can tell, there are no ioctls to give me the data
either. Is there a special request to get Net or Socket to give me that
info?

I’m using Watcom C 10.6, under 4.25J

Thanks,

-Jim

“There’s always one more bug…”
– Bubba DuPree (1986)

James Winton <spamthis@home.com> wrote:

Does this deafening silence mean there’s no way to access the network
interface stats in QNX4? And while I’m asking impossible questions, how
about the UDP and TCP stats which are displayed in “netstat -s”? Can they
be accessed by a user program, or even a root program?

And does anyone know what the getkerninfo() call returns?

I have not had time to play around with it, but, and still don’t :frowning:

I would suggest you ask your sales rep for the source code to netstat.

in /usr/incluse/sys/sock_msg.h

/*

  • kernel statistics
    */

/* int nlist(char *name) */
#define _SOCK_NLIST 0x18f
struct _sock_nlist {
msg_t code;
// struct nlist nl[];
};

struct _sock_nlist_reply {
msg_t status;
// struct nlist nl[];
};

/* int getkerninfo(int op, caddr_t where, int *size, int arg) */
#define _SOCK_GETKERNINFO 0x190
struct _sock_getkerninfo {
msg_t code;
short op;
short size;
short arg;
char where[];
};
struct _sock_getkerninfo_reply {
msg_t status;
short op;
short needed;
short arg;
char where[];
};

but could not fund much more than

#pragma pack(1)
struct nlist {
char n_name[12];
long n_value;
short n_type;
};
#pragma pack()

Can’t see netstat being that propietary. Maybe a reader from QNX might
be kind enough to pass along some of the source?

Tom