#include <errno.h>
#include <linux/filter.h>
#include <linux/netlink.h>
-#include <sys/socket.h>
+#include <unistd.h>
#include "sd-device.h"
#include "sd-event.h"
#include "fd-util.h"
#include "format-util.h"
#include "hashmap.h"
-#include "missing.h"
-#include "mount-util.h"
+#include "io-util.h"
+#include "mountpoint-util.h"
#include "set.h"
#include "socket-util.h"
#include "string-util.h"
assert_return(m, -EINVAL);
assert_return((size_t) n == size, -EINVAL);
- if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n) < 0) {
- r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n);
+ if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n) < 0) {
+ r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n);
if (r < 0)
return r;
}
else {
r = sd_event_default(&m->event);
if (r < 0)
- return 0;
+ return r;
}
return 0;
assert_return(m, -EINVAL);
- if (!m->filter_uptodate) {
- r = sd_device_monitor_filter_update(m);
- if (r < 0)
- return log_debug_errno(r, "sd-device-monitor: Failed to update filter: %m");
- }
+ r = sd_device_monitor_filter_update(m);
+ if (r < 0)
+ return log_debug_errno(r, "sd-device-monitor: Failed to update filter: %m");
if (!m->bound) {
+ /* enable receiving of sender credentials */
+ r = setsockopt_int(m->sock, SOL_SOCKET, SO_PASSCRED, true);
+ if (r < 0)
+ return log_debug_errno(r, "sd-device-monitor: Failed to set socket option SO_PASSCRED: %m");
+
if (bind(m->sock, &m->snl.sa, sizeof(struct sockaddr_nl)) < 0)
- return log_debug_errno(errno, "sd-device-monitor: Failed to bind monitoring socket to event source: %m");
+ return log_debug_errno(errno, "sd-device-monitor: Failed to bind monitoring socket: %m");
m->bound = true;
- }
- r = monitor_set_nl_address(m);
- if (r < 0)
- return log_debug_errno(r, "sd-device-monitor: Failed to set address: %m");
-
- /* enable receiving of sender credentials */
- r = setsockopt_int(m->sock, SOL_SOCKET, SO_PASSCRED, true);
- if (r < 0)
- return log_debug_errno(r, "sd-device-monitor: Failed to set socket option SO_PASSCRED: %m");
+ r = monitor_set_nl_address(m);
+ if (r < 0)
+ return log_debug_errno(r, "sd-device-monitor: Failed to set address: %m");
+ }
return 0;
}
.iov_base = &buf,
.iov_len = sizeof(buf)
};
- char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
+ CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
union sockaddr_union snl;
struct msghdr smsg = {
.msg_iov = &iov,
.msg_iovlen = 1,
- .msg_control = cred_msg,
- .msg_controllen = sizeof(cred_msg),
+ .msg_control = &control,
+ .msg_controllen = sizeof(control),
.msg_name = &snl,
.msg_namelen = sizeof(snl),
};
}
if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC))
- return log_debug_errno(EINVAL, "sd-device-monitor: Invalid message length.");
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "sd-device-monitor: Invalid message length.");
if (snl.nl.nl_groups == MONITOR_GROUP_NONE) {
/* unicast message, check if we trust the sender */
if (m->snl_trusted_sender.nl.nl_pid == 0 ||
snl.nl.nl_pid != m->snl_trusted_sender.nl.nl_pid)
- return log_debug_errno(EAGAIN, "sd-device-monitor: Unicast netlink message ignored.");
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "sd-device-monitor: Unicast netlink message ignored.");
} else if (snl.nl.nl_groups == MONITOR_GROUP_KERNEL) {
if (snl.nl.nl_pid > 0)
- return log_debug_errno(EAGAIN, "sd-device-monitor: Multicast kernel netlink message from PID %"PRIu32" ignored.", snl.nl.nl_pid);
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "sd-device-monitor: Multicast kernel netlink message from PID %"PRIu32" ignored.", snl.nl.nl_pid);
}
cmsg = CMSG_FIRSTHDR(&smsg);
if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS)
- return log_debug_errno(EAGAIN, "sd-device-monitor: No sender credentials received, message ignored.");
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "sd-device-monitor: No sender credentials received, message ignored.");
cred = (struct ucred*) CMSG_DATA(cmsg);
if (cred->uid != 0)
- return log_debug_errno(EAGAIN, "sd-device-monitor: Sender uid="UID_FMT", message ignored.", cred->uid);
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "sd-device-monitor: Sender uid="UID_FMT", message ignored.", cred->uid);
if (streq(buf.raw, "libudev")) {
/* udev message needs proper version magic */
if (buf.nlh.magic != htobe32(UDEV_MONITOR_MAGIC))
- return log_debug_errno(EAGAIN, "sd-device-monitor: Invalid message signature (%x != %x)",
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "sd-device-monitor: Invalid message signature (%x != %x)",
buf.nlh.magic, htobe32(UDEV_MONITOR_MAGIC));
if (buf.nlh.properties_off+32 > (size_t) buflen)
- return log_debug_errno(EAGAIN, "sd-device-monitor: Invalid message length (%u > %zd)",
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "sd-device-monitor: Invalid message length (%u > %zd)",
buf.nlh.properties_off+32, buflen);
bufpos = buf.nlh.properties_off;
/* kernel message with header */
bufpos = strlen(buf.raw) + 1;
if ((size_t) bufpos < sizeof("a@/d") || bufpos >= buflen)
- return log_debug_errno(EAGAIN, "sd-device-monitor: Invalid message length");
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "sd-device-monitor: Invalid message length");
/* check message header */
if (!strstr(buf.raw, "@/"))
- return log_debug_errno(EAGAIN, "sd-device-monitor: Invalid message header");
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "sd-device-monitor: Invalid message header");
}
r = device_new_from_nulstr(&device, (uint8_t*) &buf.raw[bufpos], buflen - bufpos);
/* add properties list */
nlh.properties_off = iov[0].iov_len;
nlh.properties_len = blen;
- iov[1] = (struct iovec) {
- .iov_base = (char*) buf,
- .iov_len = blen,
- };
+ iov[1] = IOVEC_MAKE((char*) buf, blen);
/*
* Use custom address for target, or the default one.
assert_return(m, -EINVAL);
+ if (m->filter_uptodate)
+ return 0;
+
if (hashmap_isempty(m->subsystem_filter) &&
set_isempty(m->tag_filter)) {
m->filter_uptodate = true;
/* jump if subsystem does not match */
bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1);
} else {
- hash = string_hash32(devtype);
-
/* jump if subsystem does not match */
bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 3);
/* load device devtype value in A */
bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, filter_devtype_hash));
/* jump if value does not match */
+ hash = string_hash32(devtype);
bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1);
}
m->subsystem_filter = hashmap_free_free_free(m->subsystem_filter);
m->tag_filter = set_free_free(m->tag_filter);
- if (setsockopt(m->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) < 0)
+ if (setsockopt(m->sock, SOL_SOCKET, SO_DETACH_FILTER, &filter, sizeof(filter)) < 0)
return -errno;
m->filter_uptodate = true;