-static int read_response(int fd, unsigned requests_max) {
- union {
- struct sockaddr sa;
- struct sockaddr_nl nl;
- } sa;
- union {
- struct nlmsghdr header;
- uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct nlmsgerr))];
- } response;
-
- ssize_t l;
- socklen_t sa_len = sizeof(sa);
- struct nlmsgerr *nlmsgerr;
-
- l = recvfrom_loop(fd, &response, sizeof(response), 0, &sa.sa, &sa_len);
- if (l < 0)
- return -errno;
-
- if (sa_len != sizeof(sa.nl) ||
- sa.nl.nl_family != AF_NETLINK)
- return -EIO;
-
- if (sa.nl.nl_pid != 0)
- return 0;
-
- if ((size_t) l < sizeof(struct nlmsghdr))
- return -EIO;
-
- if (response.header.nlmsg_type != NLMSG_ERROR ||
- (pid_t) response.header.nlmsg_pid != getpid() ||
- response.header.nlmsg_seq >= requests_max)
- return 0;
-
- if ((size_t) l < NLMSG_LENGTH(sizeof(struct nlmsgerr)) ||
- response.header.nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
- return -EIO;
-
- nlmsgerr = NLMSG_DATA(&response.header);
-
- if (nlmsgerr->error < 0 && nlmsgerr->error != -EEXIST)
- return nlmsgerr->error;
-
- return response.header.nlmsg_seq;
-}
-