- uint8_t buf[8192];
- ssize_t len = 0, ret = 0;
-
- for (struct nlmsghdr *nhm = NULL; ; nhm = NLMSG_NEXT(nhm, len)) {
- while (len < 0 || !NLMSG_OK(nhm, (size_t)len)) {
- len = recv(rtnl_socket, buf, sizeof(buf), 0);
- nhm = (struct nlmsghdr*)buf;
- if (len < 0 || !NLMSG_OK(nhm, (size_t)len)) {
- if (errno == EINTR)
- continue;
- else
- return ret;
- }
- }
-
- if (nhm->nlmsg_type != RTM_NEWADDR)
- break;
-
- // Skip address but keep clearing socket buffer
- if (ret >= (ssize_t)cnt)
- continue;
-
- struct ifaddrmsg *ifa = NLMSG_DATA(nhm);
- if (ifa->ifa_scope != RT_SCOPE_UNIVERSE ||
- (ifindex && ifa->ifa_index != (unsigned)ifindex))
- continue;
-
- struct rtattr *rta = (struct rtattr*)&ifa[1];
- size_t alen = NLMSG_PAYLOAD(nhm, sizeof(*ifa));
- memset(&addrs[ret], 0, sizeof(addrs[ret]));
- addrs[ret].prefix = ifa->ifa_prefixlen;
-
- while (RTA_OK(rta, alen)) {
- if (rta->rta_type == IFA_ADDRESS) {
- memcpy(&addrs[ret].addr, RTA_DATA(rta),
- sizeof(struct in6_addr));
- } else if (rta->rta_type == IFA_CACHEINFO) {
- struct ifa_cacheinfo *ifc = RTA_DATA(rta);
- addrs[ret].preferred = ifc->ifa_prefered;
- addrs[ret].valid = ifc->ifa_valid;
- }
-
- rta = RTA_NEXT(rta, alen);
- }