return 0;
}
-int sd_rtnl_message_route_get_dst_len(sd_rtnl_message *m, unsigned char *dst_len) {
+int sd_rtnl_message_route_get_dst_prefixlen(sd_rtnl_message *m, unsigned char *dst_len) {
struct rtmsg *rtm;
assert_return(m, -EINVAL);
return 0;
}
-int sd_rtnl_message_route_get_src_len(sd_rtnl_message *m, unsigned char *src_len) {
+int sd_rtnl_message_route_get_src_prefixlen(sd_rtnl_message *m, unsigned char *src_len) {
struct rtmsg *rtm;
assert_return(m, -EINVAL);
return 0;
}
+int sd_rtnl_message_neigh_set_flags(sd_rtnl_message *m, uint8_t flags) {
+ struct ndmsg *ndm;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
+
+ ndm = NLMSG_DATA(m->hdr);
+ ndm->ndm_flags |= flags;
+
+ return 0;
+}
+
+int sd_rtnl_message_neigh_set_state(sd_rtnl_message *m, uint16_t state) {
+ struct ndmsg *ndm;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
+
+ ndm = NLMSG_DATA(m->hdr);
+ ndm->ndm_state |= state;
+
+ return 0;
+}
+
+int sd_rtnl_message_neigh_get_flags(sd_rtnl_message *m, uint8_t *flags) {
+ struct ndmsg *ndm;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
+
+ ndm = NLMSG_DATA(m->hdr);
+ *flags = ndm->ndm_flags;
+
+ return 0;
+}
+
+int sd_rtnl_message_neigh_get_state(sd_rtnl_message *m, uint16_t *state) {
+ struct ndmsg *ndm;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
+
+ ndm = NLMSG_DATA(m->hdr);
+ *state = ndm->ndm_state;
+
+ return 0;
+}
+
int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
struct ndmsg *ndm;
int r;
assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
- assert_return(ndm_family == AF_INET || ndm_family == AF_INET6, -EINVAL);
+ assert_return(ndm_family == AF_INET ||
+ ndm_family == AF_INET6 ||
+ ndm_family == PF_BRIDGE, -EINVAL);
assert_return(ret, -EINVAL);
r = message_new(rtnl, ret, nlmsg_type);
size = (size_t)r;
if (size) {
- length = strnlen(data, size);
- if (length >= size)
+ length = strnlen(data, size+1);
+ if (length > size)
return -EINVAL;
} else
length = strlen(data);
return m->hdr->nlmsg_seq;
}
+int sd_rtnl_message_is_error(sd_rtnl_message *m) {
+ assert_return(m, 0);
+ assert_return(m->hdr, 0);
+
+ return m->hdr->nlmsg_type == NLMSG_ERROR;
+}
+
int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
struct nlmsgerr *err;
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
- if (m->hdr->nlmsg_type != NLMSG_ERROR)
+ if (!sd_rtnl_message_is_error(m))
return 0;
err = NLMSG_DATA(m->hdr);
/* no data */
if (errno == ENOBUFS)
log_debug("rtnl: kernel receive buffer overrun");
+ else if (errno == EAGAIN)
+ log_debug("rtnl: no data in socket");
- return (errno == EAGAIN) ? 0 : -errno;
+ return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
} else if (r == 0)
/* connection was closed by the kernel */
return -ECONNRESET;
/* from the kernel */
if (ucred->uid == 0 && ucred->pid == 0)
auth = true;
+ else
+ log_debug("rtnl: ignoring message from uid %u pid %u", ucred->uid, ucred->pid);
} else if (cmsg->cmsg_level == SOL_NETLINK &&
cmsg->cmsg_type == NETLINK_PKTINFO &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
}
}
- for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
+ for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
const NLType *nl_type;
if (new_msg->nlmsg_type == NLMSG_DONE) {
/* finished reading multi-part message */
done = true;
- break;
+
+ continue;
}
/* check that we support this message type */