> Another undocumented system function called devfs_find lives in
> libdevinfo. It can be used to get network devices from the kernel
> devinfo tree. The data then has to be translated into an ifreq
> structure as described in if_tcp(7) and found in /usr/include/net/if.h.
> Finally the device can be queried by passing this structure to a socket
> ioctl such as SIOCGIFCONF described in if_tcp(7) and elaborated in
> /usr/include/sys/sockio.h.
Of course I had to take it out for a spin. It turns out not so bad if
you only want to traverse the configured interfaces. Those can be found
using well documented ioctls as in the first example below. The
trickier part is finding interfaces that are present but not configured.
For that you do need to call devfs_find as in the second example. Left
as an exercise is to then ferret out all the aliases and finally remove
any configured interfaces to find the remainder.
------------------------------------------------------------------------
Example 1: Use of SIOCGIFCONF and friends:
#include <stdio.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <netinet/in.h>
#include <net/if.h>
#define FALSE 0
#define TRUE 1
#define SYS_ERROR -1
#define SYS_SUCCESS 0
#define SYS_FAILURE 1
#define IP_DEV_NAME "/dev/ip"
#define IP_MOD_NAME "ip"
#define IA(arg) \
inet_ntoa(((struct sockaddr_in *) &(arg))->sin_addr)
#define EA(arg) \
((arg) & 0xFF)
main(int argc, char *argv[])
{
int fd, i, n, buflen;
void *buf;
struct ifconf ifc;
struct ifreq *ifr;
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) == SYS_ERROR)
{
perror("socket");
exit(SYS_FAILURE);
}
if (ioctl(fd, SIOCGIFNUM, &n) == SYS_ERROR)
{
perror("ioctl SIOCGIFNUM");
exit(SYS_FAILURE);
}
printf("interfaces: %d\n", n);
buflen = n * sizeof(struct ifreq);
if (!(buf = (void *) malloc(buflen)))
{
fprintf(stderr, "memory\n");
exit(SYS_FAILURE);
}
ifc.ifc_buf = buf;
ifc.ifc_len = buflen;
if (ioctl(fd, SIOCGIFCONF, &ifc) == SYS_ERROR)
{
perror("ioctl SIOCGIFCONF");
exit(SYS_FAILURE);
}
ifr = ifc.ifc_req;
for (i = 0; i < n; i++)
{
printf("%2d:\t name: %-6s\n",
i,
ifr->ifr_name);
printf("\t addr: %-16s broadcast: %-16s\n",
IA(ifr->ifr_addr),
IA(ifr->ifr_broadaddr));
printf("\t ether: %0.2x:%0.2x:%0.2x:%0.2x:%0.2x:%0.2x:\n",
EA(ifr->ifr_enaddr[0]),
EA(ifr->ifr_enaddr[1]),
EA(ifr->ifr_enaddr[2]),
EA(ifr->ifr_enaddr[3]),
EA(ifr->ifr_enaddr[4]),
EA(ifr->ifr_enaddr[5]));
printf("\t flags: 0x%X metric: %3d\n",
ifr->ifr_flags,
ifr->ifr_metric);
ifr++;
}
devfs_find(CLASS, devfs_entry, TRUE);
close(fd);
exit(SYS_SUCCESS);
}
------------------------------------------------------------------------
Example 2: Use of devfs_find:
#include <stdio.h>
#include <fcntl.h>
#include <sys/sunddi.h>
#include <sys/ddi_impldefs.h>
#define FALSE 0
#define TRUE 1
#define SYS_ERROR -1
#define SYS_SUCCESS 0
#define SYS_FAILURE 1
#define CLASS DDI_NT_NET
static void devfs_entry(const char *devfsname,
const char *devfstype,
const dev_info_t *dip,
struct ddi_minor_data *minor,
struct ddi_minor_data *alias)
{
char *name = NULL;
printf("name: [%s] type: [%s] code: [%d]\n",
devfsname, devfstype, minor->type);
switch (minor->type)
{
case DDM_ALIAS:
printf("type: alias\n");
name = (char *) local_addr(alias->ddm_name);
break;
case DDM_MINOR:
printf("type: minor\n");
name = (char *) (local_addr(DEVI(dip)->devi_name));
break;
default:
printf("(unknown type)\n");
break;
}
}
main(int argc, char *argv[])
{
devfs_find(CLASS, devfs_entry, TRUE);
exit(SYS_SUCCESS);
}
------------------------------------------------------------------------
--
. o o . Laboratory for Computational Intelligence
. >v< . University of British Columbia
_____mm.mm_____ http://www.cs.ubc.ca/nest/lci