+ DBG("netlink receive error %s (%d)", error_buf, errno);
+ return -1;
+ }
+ if (status == 0) {
+ DBG("EOF on netlink");
+ return -1;
+ }
+ if (msg.msg_namelen != sizeof(nladdr)) {
+ DBG("sender address length == %d", msg.msg_namelen);
+ return -1;
+ }
+ for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
+ int len = h->nlmsg_len;
+ int l = len - sizeof(*h);
+
+ if (l < 0 || len > status) {
+ if (msg.msg_flags & MSG_TRUNC) {
+ DBG("truncated message");
+ return -1;
+ }
+ DBG("malformed message: len=%d", len);
+ return -1;
+ }
+
+ if (nladdr.nl_pid != peer ||
+ h->nlmsg_pid != rtnl->local.nl_pid ||
+ h->nlmsg_seq != seq) {
+ /** Don't forget to skip that message. */
+ status -= NLMSG_ALIGN(len);
+ h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
+ continue;
+ }
+
+ if (h->nlmsg_type == NLMSG_ERROR) {
+ struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
+ if (l < sizeof(struct nlmsgerr)) {
+ DBG("Error truncated message");
+ } else {
+ if (!err->error) {
+ if (answer)
+ memcpy(answer, h, h->nlmsg_len);
+ return 0;
+ }
+
+ errno = -err->error;
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ DBG("RTNETLINK answers: %s", error_buf);
+ }
+ return -1;
+ }
+ if (answer) {
+ memcpy(answer, h, h->nlmsg_len);
+ return 0;
+ }
+
+ DBG("Unexpected reply");
+
+ status -= NLMSG_ALIGN(len);
+ h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
+ }
+ if (msg.msg_flags & MSG_TRUNC) {
+ DBG("Message truncated");
+ continue;
+ }
+ if (status) {
+ DBG("Remnant of size %d", status);
+ return -1;
+ }
+ }
+}
+
+static int __netconfig_get_prefix(netconfig_inet_prefix_s *dst, char *arg, int family)
+{
+ if (family != AF_UNSPEC && family != AF_INET6) {
+ DBG("Error: invalid address family.");
+ return -1;
+ }
+
+ memset(dst, 0, sizeof(*dst));
+
+ if (strchr(arg, ':')) {
+ dst->family = AF_INET6;
+ if (inet_pton(AF_INET6, arg, dst->data) <= 0) {
+ DBG("Error: invalid ipv6 address.");