]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-device/device-monitor.c
sd-device: introduce sd_device_monitor
[thirdparty/systemd.git] / src / libsystemd / sd-device / device-monitor.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <linux/filter.h>
5 #include <linux/netlink.h>
6 #include <sys/socket.h>
7
8 #include "sd-device.h"
9 #include "sd-event.h"
10
11 #include "MurmurHash2.h"
12 #include "alloc-util.h"
13 #include "device-monitor-private.h"
14 #include "device-private.h"
15 #include "device-util.h"
16 #include "fd-util.h"
17 #include "format-util.h"
18 #include "hashmap.h"
19 #include "missing.h"
20 #include "mount-util.h"
21 #include "set.h"
22 #include "socket-util.h"
23 #include "string-util.h"
24 #include "strv.h"
25
26 struct sd_device_monitor {
27 unsigned n_ref;
28
29 int sock;
30 union sockaddr_union snl;
31 union sockaddr_union snl_trusted_sender;
32 bool bound;
33
34 Hashmap *subsystem_filter;
35 Set *tag_filter;
36 bool filter_uptodate;
37
38 sd_event *event;
39 sd_event_source *event_source;
40 int64_t event_priority;
41 sd_device_monitor_handler_t callback;
42 void *userdata;
43 };
44
45 #define UDEV_MONITOR_MAGIC 0xfeedcafe
46
47 typedef struct monitor_netlink_header {
48 /* "libudev" prefix to distinguish libudev and kernel messages */
49 char prefix[8];
50 /* Magic to protect against daemon <-> Library message format mismatch
51 * Used in the kernel from socket filter rules; needs to be stored in network order */
52 unsigned magic;
53 /* Total length of header structure known to the sender */
54 unsigned header_size;
55 /* Properties string buffer */
56 unsigned properties_off;
57 unsigned properties_len;
58 /* Hashes of primary device properties strings, to let libudev subscribers
59 * use in-kernel socket filters; values need to be stored in network order */
60 unsigned filter_subsystem_hash;
61 unsigned filter_devtype_hash;
62 unsigned filter_tag_bloom_hi;
63 unsigned filter_tag_bloom_lo;
64 } monitor_netlink_header;
65
66 static int monitor_set_nl_address(sd_device_monitor *m) {
67 union sockaddr_union snl;
68 socklen_t addrlen;
69
70 assert(m);
71
72 /* Get the address the kernel has assigned us.
73 * It is usually, but not necessarily the pid. */
74 addrlen = sizeof(struct sockaddr_nl);
75 if (getsockname(m->sock, &snl.sa, &addrlen) < 0)
76 return -errno;
77
78 m->snl.nl.nl_pid = snl.nl.nl_pid;
79 return 0;
80 }
81
82 int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor *sender) {
83 assert_return(m, -EINVAL);
84 assert_return(sender, -EINVAL);
85
86 m->snl_trusted_sender.nl.nl_pid = sender->snl.nl.nl_pid;
87 return 0;
88 }
89
90 _public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size) {
91 int n = (int) size;
92
93 assert_return(m, -EINVAL);
94 assert_return((size_t) n != size, -EINVAL);
95
96 if (setsockopt(m->sock, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) < 0 &&
97 setsockopt(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, &n, sizeof(n)) < 0)
98 return -errno;
99
100 return 0;
101 }
102
103 int device_monitor_disconnect(sd_device_monitor *m) {
104 assert(m);
105
106 m->sock = safe_close(m->sock);
107 return 0;
108 }
109
110 int device_monitor_get_fd(sd_device_monitor *m) {
111 assert_return(m, -EINVAL);
112
113 return m->sock;
114 }
115
116 int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group, int fd) {
117 _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL;
118 _cleanup_close_ int sock = -1;
119 int r;
120
121 assert_return(ret, -EINVAL);
122 assert_return(group >= 0 && group < _MONITOR_NETLINK_GROUP_MAX, -EINVAL);
123
124 if (group == MONITOR_GROUP_UDEV &&
125 access("/run/udev/control", F_OK) < 0 &&
126 dev_is_devtmpfs() <= 0) {
127
128 /*
129 * We do not support subscribing to uevents if no instance of
130 * udev is running. Uevents would otherwise broadcast the
131 * processing data of the host into containers, which is not
132 * desired.
133 *
134 * Containers will currently not get any udev uevents, until
135 * a supporting infrastructure is available.
136 *
137 * We do not set a netlink multicast group here, so the socket
138 * will not receive any messages.
139 */
140
141 log_debug("The udev service seems not to be active, disabling the monitor");
142 group = MONITOR_GROUP_NONE;
143 }
144
145 if (fd < 0) {
146 sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT);
147 if (sock < 0)
148 return log_debug_errno(errno, "Failed to create socket: %m");
149 }
150
151 m = new(sd_device_monitor, 1);
152 if (!m)
153 return -ENOMEM;
154
155 *m = (sd_device_monitor) {
156 .n_ref = 1,
157 .sock = fd >= 0 ? fd : TAKE_FD(sock),
158 .bound = fd >= 0,
159 .snl.nl.nl_family = AF_NETLINK,
160 .snl.nl.nl_groups = group,
161 };
162
163 if (fd >= 0) {
164 r = monitor_set_nl_address(m);
165 if (r < 0)
166 return log_debug_errno(r, "Failed to set netlink address: %m");
167 }
168
169 *ret = TAKE_PTR(m);
170 return 0;
171 }
172
173 _public_ int sd_device_monitor_new(sd_device_monitor **ret) {
174 return device_monitor_new_full(ret, MONITOR_GROUP_UDEV, -1);
175 }
176
177 _public_ int sd_device_monitor_stop(sd_device_monitor *m) {
178 assert_return(m, -EINVAL);
179
180 m->event_source = sd_event_source_unref(m->event_source);
181 (void) device_monitor_disconnect(m);
182
183 return 0;
184 }
185
186 static int device_monitor_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
187 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
188 sd_device_monitor *m = userdata;
189
190 assert(m);
191
192 if (device_monitor_receive_device(m, &device) <= 0)
193 return 0;
194
195 if (m->callback)
196 return m->callback(m, device, m->userdata);
197
198 return 0;
199 }
200
201 _public_ int sd_device_monitor_start(sd_device_monitor *m, sd_device_monitor_handler_t callback, void *userdata, const char *description) {
202 _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
203 int r;
204
205 assert_return(m, -EINVAL);
206
207 if (!m->event) {
208 r = sd_device_monitor_attach_event(m, NULL, 0);
209 if (r < 0)
210 return r;
211 }
212
213 r = device_monitor_enable_receiving(m);
214 if (r < 0)
215 return r;
216
217 m->callback = callback;
218 m->userdata = userdata;
219
220 r = sd_event_add_io(m->event, &s, m->sock, EPOLLIN, device_monitor_event_handler, m);
221 if (r < 0)
222 return r;
223
224 r = sd_event_source_set_priority(s, m->event_priority);
225 if (r < 0)
226 return r;
227
228 if (description) {
229 r = sd_event_source_set_description(s, description);
230 if (r < 0)
231 return r;
232 }
233
234 m->event_source = TAKE_PTR(s);
235
236 return 0;
237 }
238
239 _public_ int sd_device_monitor_detach_event(sd_device_monitor *m) {
240 assert_return(m, -EINVAL);
241
242 (void) sd_device_monitor_stop(m);
243 m->event = sd_event_unref(m->event);
244
245 return 0;
246 }
247
248 _public_ int sd_device_monitor_attach_event(sd_device_monitor *m, sd_event *event, int64_t priority) {
249 int r;
250
251 assert_return(m, -EINVAL);
252 assert_return(!m->event, -EBUSY);
253
254 if (event)
255 m->event = sd_event_ref(event);
256 else {
257 r = sd_event_default(&m->event);
258 if (r < 0)
259 return 0;
260 }
261
262 m->event_priority = priority;
263
264 return 0;
265 }
266
267 _public_ sd_event *sd_device_monitor_get_event(sd_device_monitor *m) {
268 assert_return(m, NULL);
269
270 return m->event;
271 }
272
273 int device_monitor_enable_receiving(sd_device_monitor *m) {
274 int r;
275
276 assert_return(m, -EINVAL);
277
278 if (!m->filter_uptodate) {
279 r = sd_device_monitor_filter_update(m);
280 if (r < 0)
281 return log_debug_errno(r, "Failed to update filter: %m");
282 }
283
284 if (!m->bound) {
285 if (bind(m->sock, &m->snl.sa, sizeof(struct sockaddr_nl)) < 0)
286 return log_debug_errno(errno, "Failed to bind monitoring socket to event source: %m");
287
288 m->bound = true;
289 }
290
291 r = monitor_set_nl_address(m);
292 if (r < 0)
293 return log_debug_errno(r, "Failed to set address: %m");
294
295 /* enable receiving of sender credentials */
296 if (setsockopt(m->sock, SOL_SOCKET, SO_PASSCRED, &const_int_one, sizeof(const_int_one)) < 0)
297 return log_debug_errno(errno, "Failed to set socket option SO_PASSCRED: %m");
298
299 return 0;
300 }
301
302 static sd_device_monitor *device_monitor_free(sd_device_monitor *m) {
303 assert(m);
304
305 (void) sd_device_monitor_detach_event(m);
306
307 hashmap_free_free_free(m->subsystem_filter);
308 set_free_free(m->tag_filter);
309
310 return mfree(m);
311 }
312
313 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_monitor, sd_device_monitor, device_monitor_free);
314
315 static int passes_filter(sd_device_monitor *m, sd_device *device) {
316 const char *tag, *subsystem, *devtype, *s, *d = NULL;
317 Iterator i;
318 int r;
319
320 assert_return(m, -EINVAL);
321 assert_return(device, -EINVAL);
322
323 if (hashmap_isempty(m->subsystem_filter))
324 goto tag;
325
326 r = sd_device_get_subsystem(device, &s);
327 if (r < 0)
328 return r;
329
330 r = sd_device_get_devtype(device, &d);
331 if (r < 0 && r != -ENOENT)
332 return r;
333
334 HASHMAP_FOREACH_KEY(devtype, subsystem, m->subsystem_filter, i) {
335 if (!streq(s, subsystem))
336 continue;
337
338 if (!devtype)
339 goto tag;
340
341 if (!d)
342 continue;
343
344 if (streq(d, devtype))
345 goto tag;
346 }
347
348 return 0;
349
350 tag:
351 if (set_isempty(m->tag_filter))
352 return 1;
353
354 SET_FOREACH(tag, m->tag_filter, i)
355 if (sd_device_has_tag(device, tag) > 0)
356 return 1;
357
358 return 0;
359 }
360
361 int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
362 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
363 union {
364 monitor_netlink_header nlh;
365 char raw[8192];
366 } buf;
367 struct iovec iov = {
368 .iov_base = &buf,
369 .iov_len = sizeof(buf)
370 };
371 char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
372 union sockaddr_union snl;
373 struct msghdr smsg = {
374 .msg_iov = &iov,
375 .msg_iovlen = 1,
376 .msg_control = cred_msg,
377 .msg_controllen = sizeof(cred_msg),
378 .msg_name = &snl,
379 .msg_namelen = sizeof(snl),
380 };
381 struct cmsghdr *cmsg;
382 struct ucred *cred;
383 ssize_t buflen, bufpos;
384 bool is_initialized = false;
385 int r;
386
387 assert(ret);
388
389 buflen = recvmsg(m->sock, &smsg, 0);
390 if (buflen < 0) {
391 if (errno != EINTR)
392 log_debug_errno(errno, "Failed to receive message: %m");
393 return -errno;
394 }
395
396 if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC))
397 return log_debug_errno(EINVAL, "Invalid message length.");
398
399 if (snl.nl.nl_groups == MONITOR_GROUP_NONE) {
400 /* unicast message, check if we trust the sender */
401 if (m->snl_trusted_sender.nl.nl_pid == 0 ||
402 snl.nl.nl_pid != m->snl_trusted_sender.nl.nl_pid)
403 return log_debug_errno(EAGAIN, "Unicast netlink message ignored.");
404
405 } else if (snl.nl.nl_groups == MONITOR_GROUP_KERNEL) {
406 if (snl.nl.nl_pid > 0)
407 return log_debug_errno(EAGAIN, "Multicast kernel netlink message from PID %"PRIu32" ignored.", snl.nl.nl_pid);
408 }
409
410 cmsg = CMSG_FIRSTHDR(&smsg);
411 if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS)
412 return log_debug_errno(EAGAIN, "No sender credentials received, message ignored.");
413
414 cred = (struct ucred*) CMSG_DATA(cmsg);
415 if (cred->uid != 0)
416 return log_debug_errno(EAGAIN, "Sender uid="UID_FMT", message ignored.", cred->uid);
417
418 if (streq(buf.raw, "libudev")) {
419 /* udev message needs proper version magic */
420 if (buf.nlh.magic != htobe32(UDEV_MONITOR_MAGIC))
421 return log_debug_errno(EAGAIN, "Invalid message signature (%x != %x)",
422 buf.nlh.magic, htobe32(UDEV_MONITOR_MAGIC));
423
424 if (buf.nlh.properties_off+32 > (size_t) buflen)
425 return log_debug_errno(EAGAIN, "Invalid message length (%u > %zd)",
426 buf.nlh.properties_off+32, buflen);
427
428 bufpos = buf.nlh.properties_off;
429
430 /* devices received from udev are always initialized */
431 is_initialized = true;
432
433 } else {
434 /* kernel message with header */
435 bufpos = strlen(buf.raw) + 1;
436 if ((size_t) bufpos < sizeof("a@/d") || bufpos >= buflen)
437 return log_debug_errno(EAGAIN, "Invalid message length");
438
439 /* check message header */
440 if (!strstr(buf.raw, "@/"))
441 return log_debug_errno(EAGAIN, "Invalid message header");
442 }
443
444 r = device_new_from_nulstr(&device, (uint8_t*) &buf.raw[bufpos], buflen - bufpos);
445 if (r < 0)
446 return log_debug_errno(r, "Failed to create device: %m");
447
448 if (is_initialized)
449 device_set_is_initialized(device);
450
451 /* Skip device, if it does not pass the current filter */
452 r = passes_filter(m, device);
453 if (r < 0)
454 return log_debug_errno(r, "Failed to check received device passing filter: %m");
455
456 if (r == 0)
457 log_debug("Received device does not pass filter, ignoring");
458 else
459 *ret = TAKE_PTR(device);
460
461 return r;
462 }
463
464 static uint32_t string_hash32(const char *str) {
465 return MurmurHash2(str, strlen(str), 0);
466 }
467
468 /* Get a bunch of bit numbers out of the hash, and set the bits in our bit field */
469 static uint64_t string_bloom64(const char *str) {
470 uint64_t bits = 0;
471 uint32_t hash = string_hash32(str);
472
473 bits |= 1LLU << (hash & 63);
474 bits |= 1LLU << ((hash >> 6) & 63);
475 bits |= 1LLU << ((hash >> 12) & 63);
476 bits |= 1LLU << ((hash >> 18) & 63);
477 return bits;
478 }
479
480 int device_monitor_send_device(
481 sd_device_monitor *m,
482 sd_device_monitor *destination,
483 sd_device *device) {
484
485 monitor_netlink_header nlh = {
486 .prefix = "libudev",
487 .magic = htobe32(UDEV_MONITOR_MAGIC),
488 .header_size = sizeof nlh,
489 };
490 struct iovec iov[2] = {
491 { .iov_base = &nlh, .iov_len = sizeof nlh },
492 };
493 struct msghdr smsg = {
494 .msg_iov = iov,
495 .msg_iovlen = 2,
496 };
497 /* default destination for sending */
498 union sockaddr_union default_destination = {
499 .nl.nl_family = AF_NETLINK,
500 .nl.nl_groups = MONITOR_GROUP_UDEV,
501 };
502 uint64_t tag_bloom_bits;
503 const char *buf, *val;
504 ssize_t count;
505 size_t blen;
506 int r;
507
508 assert(m);
509 assert(device);
510
511 r = device_get_properties_nulstr(device, (const uint8_t **) &buf, &blen);
512 if (r < 0)
513 return log_debug_errno(r, "Failed to get device properties: %m");
514 if (blen < 32) {
515 log_debug("Device buffer is too small to contain a valid device");
516 return -EINVAL;
517 }
518
519 /* fill in versioned header */
520 r = sd_device_get_subsystem(device, &val);
521 if (r < 0)
522 return log_debug_errno(r, "Failed to get device subsystem: %m");
523 nlh.filter_subsystem_hash = htobe32(string_hash32(val));
524
525 if (sd_device_get_devtype(device, &val) >= 0 && val)
526 nlh.filter_devtype_hash = htobe32(string_hash32(val));
527
528 /* add tag bloom filter */
529 tag_bloom_bits = 0;
530 FOREACH_DEVICE_TAG(device, val)
531 tag_bloom_bits |= string_bloom64(val);
532
533 if (tag_bloom_bits > 0) {
534 nlh.filter_tag_bloom_hi = htobe32(tag_bloom_bits >> 32);
535 nlh.filter_tag_bloom_lo = htobe32(tag_bloom_bits & 0xffffffff);
536 }
537
538 /* add properties list */
539 nlh.properties_off = iov[0].iov_len;
540 nlh.properties_len = blen;
541 iov[1] = (struct iovec) {
542 .iov_base = (char*) buf,
543 .iov_len = blen,
544 };
545
546 /*
547 * Use custom address for target, or the default one.
548 *
549 * If we send to a multicast group, we will get
550 * ECONNREFUSED, which is expected.
551 */
552 smsg.msg_name = destination ? &destination->snl : &default_destination;
553 smsg.msg_namelen = sizeof(struct sockaddr_nl);
554 count = sendmsg(m->sock, &smsg, 0);
555 if (count < 0) {
556 if (!destination && errno == ECONNREFUSED) {
557 log_debug("Passed device to netlink monitor");
558 return 0;
559 } else
560 return log_debug_errno(errno, "Failed to send device to netlink monitor");
561 }
562
563 log_debug("Passed %zi byte device to netlink monitor", count);
564 return count;
565 }
566
567 static void bpf_stmt(struct sock_filter *ins, unsigned *i,
568 unsigned short code, unsigned data) {
569 ins[(*i)++] = (struct sock_filter) {
570 .code = code,
571 .k = data,
572 };
573 }
574
575 static void bpf_jmp(struct sock_filter *ins, unsigned *i,
576 unsigned short code, unsigned data,
577 unsigned short jt, unsigned short jf) {
578 ins[(*i)++] = (struct sock_filter) {
579 .code = code,
580 .jt = jt,
581 .jf = jf,
582 .k = data,
583 };
584 }
585
586 _public_ int sd_device_monitor_filter_update(sd_device_monitor *m) {
587 struct sock_filter ins[512] = {};
588 struct sock_fprog filter;
589 const char *subsystem, *devtype, *tag;
590 unsigned i = 0;
591 Iterator it;
592
593 assert_return(m, -EINVAL);
594
595 if (hashmap_isempty(m->subsystem_filter) &&
596 set_isempty(m->tag_filter)) {
597 m->filter_uptodate = true;
598 return 0;
599 }
600
601 /* load magic in A */
602 bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, magic));
603 /* jump if magic matches */
604 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, UDEV_MONITOR_MAGIC, 1, 0);
605 /* wrong magic, pass packet */
606 bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);
607
608 if (!set_isempty(m->tag_filter)) {
609 int tag_matches = set_size(m->tag_filter);
610
611 /* add all tags matches */
612 SET_FOREACH(tag, m->tag_filter, it) {
613 uint64_t tag_bloom_bits = string_bloom64(tag);
614 uint32_t tag_bloom_hi = tag_bloom_bits >> 32;
615 uint32_t tag_bloom_lo = tag_bloom_bits & 0xffffffff;
616
617 /* load device bloom bits in A */
618 bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, filter_tag_bloom_hi));
619 /* clear bits (tag bits & bloom bits) */
620 bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_hi);
621 /* jump to next tag if it does not match */
622 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_hi, 0, 3);
623
624 /* load device bloom bits in A */
625 bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, filter_tag_bloom_lo));
626 /* clear bits (tag bits & bloom bits) */
627 bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_lo);
628 /* jump behind end of tag match block if tag matches */
629 tag_matches--;
630 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_lo, 1 + (tag_matches * 6), 0);
631 }
632
633 /* nothing matched, drop packet */
634 bpf_stmt(ins, &i, BPF_RET|BPF_K, 0);
635 }
636
637 /* add all subsystem matches */
638 if (!hashmap_isempty(m->subsystem_filter)) {
639 HASHMAP_FOREACH_KEY(devtype, subsystem, m->subsystem_filter, it) {
640 uint32_t hash = string_hash32(subsystem);
641
642 /* load device subsystem value in A */
643 bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, filter_subsystem_hash));
644 if (!devtype) {
645 /* jump if subsystem does not match */
646 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1);
647 } else {
648 hash = string_hash32(devtype);
649
650 /* jump if subsystem does not match */
651 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 3);
652 /* load device devtype value in A */
653 bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, filter_devtype_hash));
654 /* jump if value does not match */
655 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1);
656 }
657
658 /* matched, pass packet */
659 bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);
660
661 if (i+1 >= ELEMENTSOF(ins))
662 return -E2BIG;
663 }
664
665 /* nothing matched, drop packet */
666 bpf_stmt(ins, &i, BPF_RET|BPF_K, 0);
667 }
668
669 /* matched, pass packet */
670 bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);
671
672 /* install filter */
673 filter = (struct sock_fprog) {
674 .len = i,
675 .filter = ins,
676 };
677 if (setsockopt(m->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) < 0)
678 return -errno;
679
680 m->filter_uptodate = true;
681 return 0;
682 }
683
684 _public_ int sd_device_monitor_filter_add_match_subsystem_devtype(sd_device_monitor *m, const char *subsystem, const char *devtype) {
685 _cleanup_free_ char *s = NULL, *d = NULL;
686 int r;
687
688 assert_return(m, -EINVAL);
689 assert_return(subsystem, -EINVAL);
690
691 s = strdup(subsystem);
692 if (!s)
693 return -ENOMEM;
694
695 if (devtype) {
696 d = strdup(devtype);
697 if (!d)
698 return -ENOMEM;
699 }
700
701 r = hashmap_ensure_allocated(&m->subsystem_filter, NULL);
702 if (r < 0)
703 return r;
704
705 r = hashmap_put(m->subsystem_filter, s, d);
706 if (r < 0)
707 return r;
708
709 s = d = NULL;
710 m->filter_uptodate = false;
711
712 return 0;
713 }
714
715 _public_ int sd_device_monitor_filter_add_match_tag(sd_device_monitor *m, const char *tag) {
716 _cleanup_free_ char *t = NULL;
717 int r;
718
719 assert_return(m, -EINVAL);
720 assert_return(tag, -EINVAL);
721
722 t = strdup(tag);
723 if (!t)
724 return -ENOMEM;
725
726 r = set_ensure_allocated(&m->tag_filter, &string_hash_ops);
727 if (r < 0)
728 return r;
729
730 r = set_put(m->tag_filter, t);
731 if (r == -EEXIST)
732 return 0;
733 if (r < 0)
734 return r;
735
736 TAKE_PTR(t);
737 m->filter_uptodate = false;
738
739 return 0;
740 }
741
742 _public_ int sd_device_monitor_filter_remove(sd_device_monitor *m) {
743 static const struct sock_fprog filter = { 0, NULL };
744
745 assert_return(m, -EINVAL);
746
747 m->subsystem_filter = hashmap_free_free_free(m->subsystem_filter);
748 m->tag_filter = set_free_free(m->tag_filter);
749
750 if (setsockopt(m->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) < 0)
751 return -errno;
752
753 m->filter_uptodate = true;
754 return 0;
755 }