summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-rtnl
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2014-05-10 20:15:52 +0200
committerTom Gundersen <teg@jklm.no>2014-05-10 20:56:37 +0200
commit66269b05cf31ef5d8f83a7150c314bf35ee8a35e (patch)
tree05d730cd2b874f9b1ba0a5f0a1200410711e1513 /src/libsystemd/sd-rtnl
parent26349add97c8e9bfd26f2f16d61dd80a324f504e (diff)
rtnl: message - read group membership of incoming messages
Diffstat (limited to 'src/libsystemd/sd-rtnl')
-rw-r--r--src/libsystemd/sd-rtnl/rtnl-message.c25
-rw-r--r--src/libsystemd/sd-rtnl/sd-rtnl.c8
2 files changed, 25 insertions, 8 deletions
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index 9558e112af..84b46afb6b 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -1098,8 +1098,9 @@ int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
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,
@@ -1107,6 +1108,7 @@ static int socket_recv_message(int fd, struct iovec *iov, bool peek) {
.msg_controllen = sizeof(cred_buffer),
};
struct cmsghdr *cmsg;
+ uint32_t group = 0;
bool auth = false;
int r;
@@ -1128,10 +1130,15 @@ static int socket_recv_message(int fd, struct iovec *iov, bool peek) {
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;
}
}
@@ -1139,6 +1146,9 @@ static int socket_recv_message(int fd, struct iovec *iov, bool peek) {
/* not from the kernel, ignore */
return 0;
+ if (group)
+ *_group = group;
+
return r;
}
@@ -1150,6 +1160,7 @@ static int socket_recv_message(int fd, struct iovec *iov, bool peek) {
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;
@@ -1161,7 +1172,7 @@ int socket_read_message(sd_rtnl *rtnl) {
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
@@ -1177,7 +1188,7 @@ int socket_read_message(sd_rtnl *rtnl) {
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
diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c
index 4ee360c0a8..b91d08012a 100644
--- a/src/libsystemd/sd-rtnl/sd-rtnl.c
+++ b/src/libsystemd/sd-rtnl/sd-rtnl.c
@@ -22,6 +22,7 @@
#include <sys/socket.h>
#include <poll.h>
+#include "missing.h"
#include "macro.h"
#include "util.h"
#include "hashmap.h"
@@ -109,7 +110,12 @@ int sd_rtnl_open(sd_rtnl **ret, unsigned n_groups, ...) {
if (rtnl->fd < 0)
return -errno;
- if (setsockopt(rtnl->fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0)
+ r = setsockopt(rtnl->fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
+ if (r < 0)
+ return -errno;
+
+ r = setsockopt(rtnl->fd, SOL_NETLINK, NETLINK_PKTINFO, &one, sizeof(one));
+ if (r < 0)
return -errno;
va_start(ap, n_groups);