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