+struct addr_info {
+ int ifindex;
+ struct odhcpd_ipaddr *addrs;
+ size_t addrs_sz;
+ int pending;
+ ssize_t ret;
+};
+
+static int cb_valid_handler(struct nl_msg *msg, void *arg)
+{
+ struct addr_info *ctxt = (struct addr_info *)arg;
+ struct nlmsghdr *hdr = nlmsg_hdr(msg);
+ struct ifaddrmsg *ifa;
+ struct nlattr *nla[__IFA_MAX];
+
+ if (hdr->nlmsg_type != RTM_NEWADDR || ctxt->ret >= (ssize_t)ctxt->addrs_sz)
+ return NL_SKIP;
+
+ ifa = NLMSG_DATA(hdr);
+ if (ifa->ifa_scope != RT_SCOPE_UNIVERSE ||
+ (ctxt->ifindex && ifa->ifa_index != (unsigned)ctxt->ifindex))
+ return NL_SKIP;
+
+ nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL);
+ if (!nla[IFA_ADDRESS])
+ return NL_SKIP;
+
+ memset(&ctxt->addrs[ctxt->ret], 0, sizeof(ctxt->addrs[ctxt->ret]));
+ ctxt->addrs[ctxt->ret].prefix = ifa->ifa_prefixlen;
+
+ nla_memcpy(&ctxt->addrs[ctxt->ret].addr, nla[IFA_ADDRESS],
+ sizeof(ctxt->addrs[ctxt->ret].addr));
+
+ if (nla[IFA_CACHEINFO]) {
+ struct ifa_cacheinfo *ifc = nla_data(nla[IFA_CACHEINFO]);
+
+ ctxt->addrs[ctxt->ret].preferred = ifc->ifa_prefered;
+ ctxt->addrs[ctxt->ret].valid = ifc->ifa_valid;
+ }
+
+ if (ifa->ifa_flags & IFA_F_DEPRECATED)
+ ctxt->addrs[ctxt->ret].preferred = 0;
+
+ ctxt->ret++;
+
+ return NL_OK;
+}
+
+static int cb_finish_handler(_unused struct nl_msg *msg, void *arg)
+{
+ struct addr_info *ctxt = (struct addr_info *)arg;
+
+ ctxt->pending = 0;
+
+ return NL_STOP;
+}
+
+static int cb_error_handler(_unused struct sockaddr_nl *nla, struct nlmsgerr *err,
+ void *arg)
+{
+ struct addr_info *ctxt = (struct addr_info *)arg;
+
+ ctxt->pending = 0;
+ ctxt->ret = err->error;
+
+ return NL_STOP;
+}