X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fnetwork%2Fgetifaddrs.c;h=a4c317821d2a3aaea8b7ecb9ecec27b1aab5d53f;hb=8813c956e506d57065b7089a98c8fcef1ef58c47;hp=50eaee804f344bb48bcd3b71859024f34392f69e;hpb=c82f53f67cb256e0096c8649235028b6613b9a22;p=musl diff --git a/src/network/getifaddrs.c b/src/network/getifaddrs.c index 50eaee80..a4c31782 100644 --- a/src/network/getifaddrs.c +++ b/src/network/getifaddrs.c @@ -36,7 +36,6 @@ static stor* list_add(stor** list, stor** head, char* ifname) *head = curr; if(!*list) *list = curr; } - out: return curr; } @@ -52,8 +51,17 @@ void freeifaddrs(struct ifaddrs *ifp) static void ipv6netmask(unsigned prefix_length, struct sockaddr_in6 *sa) { - // FIXME: left for bit-wizard rich - memset(&sa->sin6_addr, -1, sizeof(sa->sin6_addr)); + unsigned char* hb = sa->sin6_addr.s6_addr; + unsigned onebytes = prefix_length / 8; + unsigned bits = prefix_length % 8; + unsigned nullbytes = 16 - onebytes; + memset(hb, -1, onebytes); + memset(hb+onebytes, 0, nullbytes); + if(bits) { + unsigned char x = -1; + x <<= 8 - bits; + hb[onebytes] = x; + } } static void dealwithipv6(stor **list, stor** head) @@ -106,70 +114,54 @@ static void dealwithipv6(stor **list, stor** head) int getifaddrs(struct ifaddrs **ifap) { - FILE* f = fopen("/proc/net/dev", "r"); - if(!f) return -1; - - /* the alternative to parsing /proc.. seems to be iterating - through the interfaces using an index number in ifreq.ifr_ifindex - until we get some error code back. the kernel will fill ifr_name field - for valid ifindices (SIOCGIFINDEX) */ stor *list = 0, *head = 0; - - char* line; char linebuf[512]; - while((line = fgets(linebuf, sizeof linebuf, f))) { - while(isspace(*line) && *line) line++; - char* start = line; - while(*line && isalnum(*line)) line++; - if(line > start && *line == ':') { - // found interface - *line = 0; - stor* curr = list_add(&list, &head, start); - if(!curr) { - fclose(f); - goto err2; - } + struct if_nameindex* ii = if_nameindex(); + if(!ii) return -1; + size_t i; + for(i = 0; ii[i].if_index || ii[i].if_name; i++) { + stor* curr = list_add(&list, &head, ii[i].if_name); + if(!curr) { + if_freenameindex(ii); + goto err2; } } - fclose(f); + if_freenameindex(ii); int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if(sock == -1) goto err2; struct ifreq reqs[32]; /* arbitrary chosen boundary */ struct ifconf conf = {.ifc_len = sizeof reqs, .ifc_req = reqs}; if(-1 == ioctl(sock, SIOCGIFCONF, &conf)) goto err; - else { - size_t reqitems = conf.ifc_len / sizeof(struct ifreq); - for(head = list; head; head = (stor*)head->next) { - size_t i; - for(i = 0; i < reqitems; i++) { - // get SIOCGIFADDR of active interfaces. - if(!strcmp(reqs[i].ifr_name, head->name)) { - head->addr.v4 = *(struct sockaddr_in*)&reqs[i].ifr_addr; - head->ifa.ifa_addr = (struct sockaddr*) &head->addr; - break; - } + size_t reqitems = conf.ifc_len / sizeof(struct ifreq); + for(head = list; head; head = (stor*)head->next) { + for(i = 0; i < reqitems; i++) { + // get SIOCGIFADDR of active interfaces. + if(!strcmp(reqs[i].ifr_name, head->name)) { + head->addr.v4 = *(struct sockaddr_in*)&reqs[i].ifr_addr; + head->ifa.ifa_addr = (struct sockaddr*) &head->addr; + break; } - struct ifreq req; - snprintf(req.ifr_name, sizeof req.ifr_name, "%s", head->name); - if(-1 == ioctl(sock, SIOCGIFFLAGS, &req)) goto err; + } + struct ifreq req; + snprintf(req.ifr_name, sizeof req.ifr_name, "%s", head->name); + if(-1 == ioctl(sock, SIOCGIFFLAGS, &req)) goto err; - head->ifa.ifa_flags = req.ifr_flags; - if(head->ifa.ifa_addr) { - /* or'ing flags with IFF_LOWER_UP on active interfaces to mimic glibc */ - head->ifa.ifa_flags |= IFF_LOWER_UP; - if(-1 == ioctl(sock, SIOCGIFNETMASK, &req)) goto err; - head->netmask.v4 = *(struct sockaddr_in*)&req.ifr_netmask; - head->ifa.ifa_netmask = (struct sockaddr*) &head->netmask; - - if(head->ifa.ifa_flags & IFF_POINTOPOINT) { - if(-1 == ioctl(sock, SIOCGIFDSTADDR, &req)) goto err; - head->dst.v4 = *(struct sockaddr_in*)&req.ifr_dstaddr; - } else { - if(-1 == ioctl(sock, SIOCGIFBRDADDR, &req)) goto err; - head->dst.v4 = *(struct sockaddr_in*)&req.ifr_broadaddr; - } - head->ifa.ifa_ifu.ifu_dstaddr = (struct sockaddr*) &head->dst; + head->ifa.ifa_flags = req.ifr_flags; + if(head->ifa.ifa_addr) { + /* or'ing flags with IFF_LOWER_UP on active interfaces to mimic glibc */ + head->ifa.ifa_flags |= IFF_LOWER_UP; + if(-1 == ioctl(sock, SIOCGIFNETMASK, &req)) goto err; + head->netmask.v4 = *(struct sockaddr_in*)&req.ifr_netmask; + head->ifa.ifa_netmask = (struct sockaddr*) &head->netmask; + + if(head->ifa.ifa_flags & IFF_POINTOPOINT) { + if(-1 == ioctl(sock, SIOCGIFDSTADDR, &req)) goto err; + head->dst.v4 = *(struct sockaddr_in*)&req.ifr_dstaddr; + } else { + if(-1 == ioctl(sock, SIOCGIFBRDADDR, &req)) goto err; + head->dst.v4 = *(struct sockaddr_in*)&req.ifr_broadaddr; } + head->ifa.ifa_ifu.ifu_dstaddr = (struct sockaddr*) &head->dst; } } close(sock);