Date: Thu, 11 Nov 1999 08:05:40 +0000 From: David Malone <dwmalone@maths.tcd.ie> To: "Santhosh Kumar M [CEC-S]" <santoshm@wipinfo.soft.net> Cc: freebsd-hackers@FreeBSD.ORG Subject: Re: A Question Message-ID: <19991111080540.A58543@walton.maths.tcd.ie> In-Reply-To: <Pine.SV4.3.93.991111112533.8773A-100000@tagore> References: <Pine.SV4.3.93.991111112533.8773A-100000@tagore>
next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, Nov 11, 1999 at 11:29:57AM +0530, Santhosh Kumar M [CEC-S] wrote: > Can anyone give me the library call or system calls by which i can > get all the IP address configured on a local system (Note: the system can > be multihomed adapters). Here is a program I wrote to try to see how to find the addresses of all the interfaces. It's based on rwhod and reading how the kernel does it. I think I'm doing it the correct way, but it isn't pretty. 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 majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19991111080540.A58543>