> It is possible to get interface lists on earlier versions (and I hope
> still current versions) using the ioctl interfaces described in Stevens.
> See also ifconfig.c source from various versions of FreeBSD :-).
I think Garret suggested that the ioctl method was deprecated?
I wrote some code just to figure out how the sysctl stuff is packed
'cos it's not that obvoius - I've included it below incase it might
be of use to someone.
David.
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <stdlib.h>
#include <err.h>
#include <stdio.h>
#include <string.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/*
* This is an example of how to find info about the currently configured
* interfaces.
*
* The code in rwhod and ifconfig if pretty hard to understand as it
* doesn't really exploit the structure of what you're returned. We use
* a sysctl to get the interface list, which returns a buffer with a
* list of things each starting with:
*
* msglen
* version
* type
*
* The generic type used to with this start in the kernel seems to be
* "struct rt_msghdr". For this sysctl we call it returns a message of
* type RTM_IFINFO followed by a list of RTM_NEWADDR for each interface.
* This corrisponds to the interface and each of the configurations you
* "put" on it with ifconfig.
*
* The RTM_IFINFO message contains a struct if_msghdr followed by a
* list of struct sockaddr. The RTM_NEWADDR contains a struct ifa_msghdr
* followed by a list of struct sockaddr.
*
* The struct sockaddr's sizes have been truncated to the nearest
* power of two into which the data will fit. The struct sockaddr's
* included depend on what is apropriate to this message. You can tell
* which of RTAX_* sockaddr's have been included by looking at the set
* bits of ifm_addrs or ifam_addrs, so you have to expand them out into
* an array of struct sockaddr's of size RTAX_MAX.
*/
void unpack_addrs(struct sockaddr *packed,struct sockaddr *unpacked,int rti_addrs);
void print_addrs(struct sockaddr *unpacked,int rti_addrs);
int
main(int argc, char **argv)
{
char *buf, *lim, *next; /* For sysctl */
size_t needed;
int mib[6];
struct rt_msghdr *rtm; /* For decoding messages */
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
struct sockaddr *packed_addr; /* For decoding addresses */
struct sockaddr unpacked_addr[RTAX_MAX];
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
errx(1, "route-sysctl-estimate");
if ((buf = malloc(needed)) == NULL)
errx(1, "malloc");
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
errx(1, "actual retrieval of interface table");
lim = buf + needed;
for( next = buf; next < lim; next += rtm->rtm_msglen ) {
rtm = (struct rt_msghdr *)next;
switch( rtm->rtm_type ) {
case RTM_IFINFO:
ifm = (struct if_msghdr *)next;
packed_addr = (struct sockaddr *)(next + sizeof(struct
if_msghdr));
printf("Found an interface.\n");
if( ifm->ifm_flags & IFF_UP )
printf("It is currently up.\n");
if( ifm->ifm_addrs != 0 ) {
printf("These addresses were available:\n");
unpack_addrs(packed_addr,unpacked_addr,
ifm->ifm_addrs);
print_addrs(unpacked_addr,ifm->ifm_addrs);
} else
printf("No addresses were available.\n");
break;
case RTM_NEWADDR:
ifam = (struct ifa_msghdr *)next;
packed_addr = (struct sockaddr *)(next + sizeof(struct
ifa_msghdr));
printf("Found extra addresses associated with interface.\n");
unpack_addrs(packed_addr,unpacked_addr,
ifam->ifam_addrs);
print_addrs(unpacked_addr,ifam->ifam_addrs);
break;
default:
errx(1, "unexpected rtm type");
}
}
exit(0);
}
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
void
unpack_addrs(struct sockaddr *packed,struct sockaddr *unpacked,int rti_addrs)
{
int i;
for( i = 0; i < RTAX_MAX; i++ ) {
bzero(&unpacked[i],sizeof(unpacked[i]));
if( rti_addrs & (1<<i) ) {
memcpy(&(unpacked[i]), packed, packed->sa_len);
packed = (struct sockaddr *)(((char *)packed) +
ROUNDUP(packed->sa_len));
}
}
}
void
print_addrs(struct sockaddr *unpacked,int rti_addrs)
{
int i;
for( i = 0; i < RTAX_MAX; i++ ) {
if( (rti_addrs & (1<<i)) == 0 )
continue;
switch(i) {
case RTAX_DST:
printf("Destination address");
break;
case RTAX_GATEWAY:
printf("Gateway address");
break;
case RTAX_NETMASK:
printf("Netmask");
break;
case RTAX_GENMASK:
printf("Cloning mask");
break;
case RTAX_IFP:
printf("Interface name");
break;
case RTAX_IFA:
printf("Interface address");
break;
case RTAX_AUTHOR:
printf("Author of redirect");
break;
case RTAX_BRD:
printf("Broadcast address");
break;
default:
printf("Unknown type of address %d",i);
break;
}
printf(": ");
switch( unpacked[i].sa_family ) {
case AF_INET:
printf(inet_ntoa(((struct sockaddr_in
*)&(unpacked[i]))->sin_addr));
break;
default:
printf("address in family %d", unpacked[i].sa_family);
break;
}
printf(".\n");
}
}
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message