/* Gets IPv6 interface information from the /proc filesystem in linux*/ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) { struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr; FILE *fp; char addr[8][5]; int flags, myflags, index, plen, scope; char ifname[9], lastname[IFNAMSIZ]; char addr6[32+7+1]; /* don't forget the seven ':' */ struct addrinfo hints, *res0; struct sockaddr_in6 *sin6; struct in6_addr *addrptr; int err; int sockfd = -1; struct ifreq ifr; res0=NULL; ifihead = NULL; ifipnext = &ifihead; lastname[0] = 0; if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) { sockfd = socket(AF_INET6, SOCK_DGRAM, 0); if (sockfd < 0) { goto gotError; } while (fscanf(fp, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n", addr[0],addr[1],addr[2],addr[3], addr[4],addr[5],addr[6],addr[7], &index, &plen, &scope, &flags, ifname) != EOF) { myflags = 0; if (strncmp(lastname, ifname, IFNAMSIZ) == 0) { if (doaliases == 0) continue; /* already processed this interface */ myflags = IFI_ALIAS; } memcpy(lastname, ifname, IFNAMSIZ); ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info)); if (ifi == NULL) { goto gotError; } ifipold = *ifipnext; /* need this later */ ifiptr = ifipnext; *ifipnext = ifi; /* prev points to this new one */ ifipnext = &ifi->ifi_next; /* pointer to next one goes here */ sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", addr[0],addr[1],addr[2],addr[3], addr[4],addr[5],addr[6],addr[7]); /* Add address of the interface */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_flags = AI_NUMERICHOST; err = getaddrinfo(addr6, NULL, &hints, &res0); if (err) { goto gotError; } ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6)); if (ifi->ifi_addr == NULL) { goto gotError; } memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6)); /* Add netmask of the interface */ char ipv6addr[INET6_ADDRSTRLEN]; plen_to_mask(plen, ipv6addr); ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6)); if (ifi->ifi_addr == NULL) { goto gotError; } sin6=calloc(1, sizeof(struct sockaddr_in6)); addrptr=calloc(1, sizeof(struct in6_addr)); inet_pton(family, ipv6addr, addrptr); sin6->sin6_family=family; sin6->sin6_addr=*addrptr; sin6->sin6_scope_id=scope; memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6)); free(sin6); /* Add interface name */ memcpy(ifi->ifi_name, ifname, IFI_NAME); /* Add interface index */ ifi->ifi_index = index; /* Add interface flags*/ memcpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { if (errno == EADDRNOTAVAIL) { /* * If the main interface is configured with no IP address but * an alias interface exists with an IP address, you get * EADDRNOTAVAIL for the main interface */ free(ifi->ifi_addr); free(ifi); ifipnext = ifiptr; *ifipnext = ifipold; continue; } else { goto gotError; } } ifi->ifi_flags = ifr.ifr_flags; freeaddrinfo(res0); res0=NULL; } } goto done; gotError: if (ifihead != NULL) { free_ifi_info(ifihead); ifihead = NULL; } if (res0 != NULL) { freeaddrinfo(res0); res0=NULL; } done: if (sockfd != -1) { assert(close(sockfd) == 0); } return(ifihead); /* pointer to first structure in linked list */ }
/* Gets IPv6 interface information from the /proc filesystem in linux*/ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) { struct ifi_info *ifi, *ifihead, **ifipnext; FILE *fp; char addr[8][5]; int flags, myflags, index, plen, scope; char ifname[9], lastname[IFNAMSIZ]; char addr6[32+7+1]; /* don't forget the seven ':' */ struct addrinfo hints, *res0; struct sockaddr_in6 *sin6; struct in6_addr *addrptr; int err; res0=NULL; ifihead = NULL; ifipnext = &ifihead; lastname[0] = 0; if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) { while (fscanf(fp, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n", addr[0],addr[1],addr[2],addr[3], addr[4],addr[5],addr[6],addr[7], &index, &plen, &scope, &flags, ifname) != EOF) { myflags = 0; if (strncmp(lastname, ifname, IFNAMSIZ) == 0) { if (doaliases == 0) continue; /* already processed this interface */ myflags = IFI_ALIAS; } memcpy(lastname, ifname, IFNAMSIZ); ifi = (struct ifi_info*)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 */ sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", addr[0],addr[1],addr[2],addr[3], addr[4],addr[5],addr[6],addr[7]); /* Add address of the interface */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_flags = AI_NUMERICHOST; err = getaddrinfo(addr6, NULL, &hints, &res0); if (err) { goto gotError; } ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6)); if (ifi->ifi_addr == NULL) { goto gotError; } memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6)); /* Add netmask of the interface */ char ipv6addr[INET6_ADDRSTRLEN]; plen_to_mask(plen, ipv6addr); ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6)); if (ifi->ifi_addr == NULL) { goto gotError; } sin6=calloc(1, sizeof(struct sockaddr_in6)); addrptr=calloc(1, sizeof(struct in6_addr)); inet_pton(family, ipv6addr, addrptr); sin6->sin6_family=family; sin6->sin6_addr=*addrptr; sin6->sin6_scope_id=scope; memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6)); free(sin6); /* Add interface name */ memcpy(ifi->ifi_name, ifname, IFI_NAME); /* Add interface index */ ifi->ifi_index = index; /* If interface is in /proc then it is up*/ ifi->ifi_flags = IFF_UP; freeaddrinfo(res0); res0=NULL; } } goto done; gotError: if (ifihead != NULL) { free_ifi_info(ifihead); ifihead = NULL; } if (res0 != NULL) { freeaddrinfo(res0); res0=NULL; } done: return(ifihead); /* pointer to first structure in linked list */ }