-
-struct ifi_info *get_ifi_info(int family, int doaliases)
-{
- int junk;
- struct ifi_info *ifi, *ifihead, **ifipnext;
- int sockfd, len, lastlen, flags, myflags;
- char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
- struct ifconf ifc;
- struct ifreq *ifr, ifrcopy;
- struct sockaddr_in *sinptr;
-
-#if defined(AF_INET6) && defined(HAVE_IPV6)
- struct sockaddr_in6 *sinptr6;
-#endif
-
- sockfd = -1;
- buf = NULL;
- ifihead = NULL;
-
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sockfd < 0) {
- goto gotError;
- }
-
- lastlen = 0;
- len = 100 * sizeof(struct ifreq); /* initial buffer size guess */
- for ( ; ; ) {
- buf = malloc(len);
- if (buf == NULL) {
- goto gotError;
- }
- ifc.ifc_len = len;
- ifc.ifc_buf = buf;
- if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
- if (errno != EINVAL || lastlen != 0) {
- goto gotError;
- }
- } else {
- if (ifc.ifc_len == lastlen)
- break; /* success, len has not changed */
- lastlen = ifc.ifc_len;
- }
- len += 10 * sizeof(struct ifreq); /* increment */
- free(buf);
- }
- ifihead = NULL;
- ifipnext = &ifihead;
- lastname[0] = 0;
-/* end get_ifi_info1 */
-
-/* include get_ifi_info2 */
- for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
- ifr = (struct ifreq *) ptr;
-
- len = GET_SA_LEN(ifr->ifr_addr);
- ptr += sizeof(ifr->ifr_name) + len; /* for next one in buffer */
-
-// fprintf(stderr, "intf %d name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
-
- if (ifr->ifr_addr.sa_family != family)
- continue; /* ignore if not desired address family */
-
- myflags = 0;
- if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL)
- *cptr = 0; /* replace colon will null */
- if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
- if (doaliases == 0)
- continue; /* already processed this interface */
- myflags = IFI_ALIAS;
- }
- memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
-
- ifrcopy = *ifr;
- if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) {
- goto gotError;
- }
-
- flags = ifrcopy.ifr_flags;
- if ((flags & IFF_UP) == 0)
- continue; /* ignore if interface not up */
-
- ifi = calloc(1, sizeof(struct ifi_info));
- if (ifi == NULL) {
- goto gotError;
- }
- *ifipnext = ifi; /* prev points to this new one */
- ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
-
- ifi->ifi_flags = flags; /* IFF_xxx values */
- ifi->ifi_myflags = myflags; /* IFI_xxx values */
- ifi->ifi_index = if_nametoindex(ifr->ifr_name);
- memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
- ifi->ifi_name[IFI_NAME-1] = '\0';
-/* end get_ifi_info2 */
-/* include get_ifi_info3 */
- switch (ifr->ifr_addr.sa_family) {
- case AF_INET:
- sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
- if (ifi->ifi_addr == NULL) {
- ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in));
- if (ifi->ifi_addr == NULL) {
- goto gotError;
- }
- memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
-
-#ifdef SIOCGIFBRDADDR
- if (flags & IFF_BROADCAST) {
- if (ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
- goto gotError;
- }
- sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
- ifi->ifi_brdaddr = calloc(1, sizeof(struct sockaddr_in));
- if (ifi->ifi_brdaddr == NULL) {
- goto gotError;
- }
- memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
- }
-#endif
-
-#ifdef SIOCGIFDSTADDR
- if (flags & IFF_POINTOPOINT) {
- if (ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy) < 0) {
- goto gotError;
- }
- sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
- ifi->ifi_dstaddr = calloc(1, sizeof(struct sockaddr_in));
- if (ifi->ifi_dstaddr == NULL) {
- goto gotError;
- }
- memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
- }
-#endif
- }
- break;
-
-#if defined(AF_INET6) && defined(HAVE_IPV6)
- case AF_INET6:
- sinptr6 = (struct sockaddr_in6 *) &ifr->ifr_addr;
- if (ifi->ifi_addr == NULL) {
- ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
- if (ifi->ifi_addr == NULL) {
- goto gotError;
- }
-
- /* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
- /* We need to strip that out */
- if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr))
- sinptr6->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
- memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
- }
- break;
-#endif
-
- default:
- break;
- }
- }
- goto done;
-
-gotError:
- if (ifihead != NULL) {
- free_ifi_info(ifihead);
- ifihead = NULL;
- }
-
-done:
- if (buf != NULL) {
- free(buf);
- }
- if (sockfd != -1) {
- junk = close(sockfd);
- assert(junk == 0);
- }
- return(ifihead); /* pointer to first structure in linked list */
-}
-/* end get_ifi_info3 */
-
-/* include free_ifi_info */
-void
-free_ifi_info(struct ifi_info *ifihead)
-{
- struct ifi_info *ifi, *ifinext;
-
- for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
- if (ifi->ifi_addr != NULL)
- free(ifi->ifi_addr);
- if (ifi->ifi_brdaddr != NULL)
- free(ifi->ifi_brdaddr);
- if (ifi->ifi_dstaddr != NULL)
- free(ifi->ifi_dstaddr);
- ifinext = ifi->ifi_next; /* can't fetch ifi_next after free() */
- free(ifi); /* the ifi_info{} itself */
- }
-}
-/* end free_ifi_info */
-
-ssize_t