From owner-freebsd-hackers Sat Sep 16 3: 1:22 2000 Delivered-To: freebsd-hackers@freebsd.org Received: from salmon.maths.tcd.ie (salmon.maths.tcd.ie [134.226.81.11]) by hub.freebsd.org (Postfix) with SMTP id 7A60937B422; Sat, 16 Sep 2000 03:01:12 -0700 (PDT) Received: from walton.maths.tcd.ie by salmon.maths.tcd.ie with SMTP id ; 16 Sep 2000 11:01:11 +0100 (BST) To: Robert Watson Cc: Chris Ptacek , freebsd-hackers@FreeBSD.ORG Subject: Re: Getting all the IP address for a machine from code... In-reply-to: Your message of "Fri, 15 Sep 2000 11:52:31 EDT." X-Request-Do: Date: Sat, 16 Sep 2000 11:01:10 +0100 From: David Malone Message-ID: <200009161101.aa71225@salmon.maths.tcd.ie> Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG > 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 #include #include #include #include #include #include #include #include #include #include #include /* * 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<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<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