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