return RTA_PAYLOAD(rta);
}
-int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
+int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
int r;
void *attr_data;
else if (strnlen(attr_data, r) >= (size_t) r)
return -EIO;
- *data = (char *) attr_data;
+ *data = (const char *) attr_data;
return 0;
}
return r;
} else if (nl_type->type == NLA_UNION) {
const NLTypeSystemUnion *type_system_union;
- char *key;
+ const char *key;
r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
&type_system_union,
return k;
}
-static int socket_recv_message(int fd, struct iovec *iov, bool peek) {
- uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
+static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
+ uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
+ CMSG_SPACE(sizeof(struct nl_pktinfo))];
struct msghdr msg = {
.msg_iov = iov,
.msg_iovlen = 1,
.msg_controllen = sizeof(cred_buffer),
};
struct cmsghdr *cmsg;
+ uint32_t group = 0;
bool auth = false;
int r;
struct ucred *ucred = (void *)CMSG_DATA(cmsg);
/* from the kernel */
- if (ucred->uid == 0 && ucred->pid == 0) {
+ if (ucred->uid == 0 && ucred->pid == 0)
auth = true;
- break;
- }
+ } else if (cmsg->cmsg_level == SOL_NETLINK &&
+ cmsg->cmsg_type == NETLINK_PKTINFO &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
+ struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
+
+ /* multi-cast group */
+ group = pktinfo->group;
}
}
/* not from the kernel, ignore */
return 0;
+ if (group)
+ *_group = group;
+
return r;
}
int socket_read_message(sd_rtnl *rtnl) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
struct iovec iov = {};
+ uint32_t group = 0;
bool multi_part = false, done = false;
struct nlmsghdr *new_msg;
size_t len;
assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
/* read nothing, just get the pending message size */
- r = socket_recv_message(rtnl->fd, &iov, true);
+ r = socket_recv_message(rtnl->fd, &iov, &group, true);
if (r <= 0)
return r;
else
iov.iov_len = rtnl->rbuffer_allocated;
/* read the pending message */
- r = socket_recv_message(rtnl->fd, &iov, false);
+ r = socket_recv_message(rtnl->fd, &iov, &group, false);
if (r <= 0)
return r;
else
_cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
const NLType *nl_type;
- if (new_msg->nlmsg_pid && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
+ if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
/* not broadcast and not for us */
continue;