- 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;
+ }
+ if (ifs->ifa.ifa_name) {
+ unsigned int bucket = ifs->index % IFADDRS_HASH_SIZE;
+ ifs->hash_next = ctx->hash[bucket];
+ ctx->hash[bucket] = ifs;
+ }
+ } else {
+ ifs->ifa.ifa_name = ifs0->ifa.ifa_name;
+ ifs->ifa.ifa_flags = ifs0->ifa.ifa_flags;
+ for (rta = NLMSG_RTA(h, sizeof(*ifa)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) {
+ switch (rta->rta_type) {
+ case IFA_ADDRESS:
+ /* If ifa_addr is already set we, received an IFA_LOCAL before
+ * so treat this as destination address */
+ if (ifs->ifa.ifa_addr)
+ copy_addr(&ifs->ifa.ifa_dstaddr, ifa->ifa_family, &ifs->ifu, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
+ else
+ copy_addr(&ifs->ifa.ifa_addr, ifa->ifa_family, &ifs->addr, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
+ break;
+ case IFA_BROADCAST:
+ copy_addr(&ifs->ifa.ifa_broadaddr, ifa->ifa_family, &ifs->ifu, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
+ break;
+ case IFA_LOCAL:
+ /* If ifa_addr is set and we get IFA_LOCAL, assume we have
+ * a point-to-point network. Move address to correct field. */
+ if (ifs->ifa.ifa_addr) {
+ ifs->ifu = ifs->addr;
+ ifs->ifa.ifa_dstaddr = &ifs->ifu.sa;
+ memset(&ifs->addr, 0, sizeof(ifs->addr));