]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libudev/libudev-monitor.c
journal: fix monotonic seeking
[thirdparty/systemd.git] / src / libudev / libudev-monitor.c
CommitLineData
ba6929f6
KS
1/*
2 * libudev - interface to udev device information
3 *
28460195 4 * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org>
ba6929f6 5 *
4061ab9f
KS
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
ba6929f6
KS
10 */
11
ba6929f6
KS
12#include <stdio.h>
13#include <stdlib.h>
14#include <stddef.h>
15#include <unistd.h>
16#include <errno.h>
17#include <string.h>
18#include <dirent.h>
e14bdd88 19#include <sys/poll.h>
ba6929f6
KS
20#include <sys/stat.h>
21#include <sys/socket.h>
22#include <sys/un.h>
e14bdd88 23#include <arpa/inet.h>
1c7047ea 24#include <linux/netlink.h>
e14bdd88 25#include <linux/filter.h>
ba6929f6
KS
26
27#include "libudev.h"
28#include "libudev-private.h"
b49d9b50 29#include "socket-util.h"
ba6929f6 30
ce1d6d7f
KS
31/**
32 * SECTION:libudev-monitor
33 * @short_description: device event source
34 *
35 * Connects to a device event source.
36 */
37
ce1d6d7f
KS
38/**
39 * udev_monitor:
40 *
50579295 41 * Opaque object handling an event source.
ce1d6d7f 42 */
ba6929f6 43struct udev_monitor {
912541b0
KS
44 struct udev *udev;
45 int refcount;
46 int sock;
b49d9b50
KS
47 union sockaddr_union snl;
48 union sockaddr_union snl_trusted_sender;
49 union sockaddr_union snl_destination;
912541b0
KS
50 socklen_t addrlen;
51 struct udev_list filter_subsystem_list;
52 struct udev_list filter_tag_list;
53 bool bound;
ba6929f6
KS
54};
55
f2b93744 56enum udev_monitor_netlink_group {
912541b0
KS
57 UDEV_MONITOR_NONE,
58 UDEV_MONITOR_KERNEL,
59 UDEV_MONITOR_UDEV,
f2b93744
KS
60};
61
912541b0 62#define UDEV_MONITOR_MAGIC 0xfeedcafe
e14bdd88 63struct udev_monitor_netlink_header {
912541b0
KS
64 /* "libudev" prefix to distinguish libudev and kernel messages */
65 char prefix[8];
66 /*
67 * magic to protect against daemon <-> library message format mismatch
68 * used in the kernel from socket filter rules; needs to be stored in network order
69 */
70 unsigned int magic;
71 /* total length of header structure known to the sender */
72 unsigned int header_size;
73 /* properties string buffer */
74 unsigned int properties_off;
75 unsigned int properties_len;
76 /*
77 * hashes of primary device properties strings, to let libudev subscribers
78 * use in-kernel socket filters; values need to be stored in network order
79 */
80 unsigned int filter_subsystem_hash;
81 unsigned int filter_devtype_hash;
82 unsigned int filter_tag_bloom_hi;
83 unsigned int filter_tag_bloom_lo;
e14bdd88
KS
84};
85
86static struct udev_monitor *udev_monitor_new(struct udev *udev)
87{
912541b0
KS
88 struct udev_monitor *udev_monitor;
89
90 udev_monitor = calloc(1, sizeof(struct udev_monitor));
91 if (udev_monitor == NULL)
92 return NULL;
93 udev_monitor->refcount = 1;
94 udev_monitor->udev = udev;
95 udev_list_init(udev, &udev_monitor->filter_subsystem_list, false);
96 udev_list_init(udev, &udev_monitor->filter_tag_list, true);
97 return udev_monitor;
e14bdd88
KS
98}
99
7459bcdc 100struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd)
1c7047ea 101{
912541b0
KS
102 struct udev_monitor *udev_monitor;
103 unsigned int group;
104
105 if (udev == NULL)
106 return NULL;
107
108 if (name == NULL)
109 group = UDEV_MONITOR_NONE;
110 else if (strcmp(name, "udev") == 0)
111 group = UDEV_MONITOR_UDEV;
112 else if (strcmp(name, "kernel") == 0)
113 group = UDEV_MONITOR_KERNEL;
114 else
115 return NULL;
116
117 udev_monitor = udev_monitor_new(udev);
118 if (udev_monitor == NULL)
119 return NULL;
120
121 if (fd < 0) {
122 udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT);
123 if (udev_monitor->sock == -1) {
c8f8394a 124 udev_err(udev, "error getting socket: %m\n");
912541b0
KS
125 free(udev_monitor);
126 return NULL;
127 }
128 } else {
129 udev_monitor->bound = true;
130 udev_monitor->sock = fd;
131 }
132
b49d9b50
KS
133 udev_monitor->snl.nl.nl_family = AF_NETLINK;
134 udev_monitor->snl.nl.nl_groups = group;
912541b0
KS
135
136 /* default destination for sending */
b49d9b50
KS
137 udev_monitor->snl_destination.nl.nl_family = AF_NETLINK;
138 udev_monitor->snl_destination.nl.nl_groups = UDEV_MONITOR_UDEV;
912541b0 139
912541b0 140 return udev_monitor;
1c7047ea
KS
141}
142
7459bcdc
KS
143/**
144 * udev_monitor_new_from_netlink:
145 * @udev: udev library context
146 * @name: name of event source
147 *
148 * Create new udev monitor and connect to a specified event
149 * source. Valid sources identifiers are "udev" and "kernel".
150 *
151 * Applications should usually not connect directly to the
152 * "kernel" events, because the devices might not be useable
153 * at that time, before udev has configured them, and created
50579295
KS
154 * device nodes. Accessing devices at the same time as udev,
155 * might result in unpredictable behavior. The "udev" events
156 * are sent out after udev has finished its event processing,
157 * all rules have been processed, and needed device nodes are
158 * created.
7459bcdc
KS
159 *
160 * The initial refcount is 1, and needs to be decremented to
161 * release the resources of the udev monitor.
162 *
163 * Returns: a new udev monitor, or #NULL, in case of an error
164 **/
54cf0b7f 165_public_ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name)
7459bcdc 166{
912541b0 167 return udev_monitor_new_from_netlink_fd(udev, name, -1);
7459bcdc
KS
168}
169
e14bdd88 170static inline void bpf_stmt(struct sock_filter *inss, unsigned int *i,
912541b0 171 unsigned short code, unsigned int data)
e14bdd88 172{
912541b0 173 struct sock_filter *ins = &inss[*i];
e14bdd88 174
912541b0
KS
175 ins->code = code;
176 ins->k = data;
177 (*i)++;
e14bdd88
KS
178}
179
180static inline void bpf_jmp(struct sock_filter *inss, unsigned int *i,
912541b0
KS
181 unsigned short code, unsigned int data,
182 unsigned short jt, unsigned short jf)
e14bdd88 183{
912541b0 184 struct sock_filter *ins = &inss[*i];
e14bdd88 185
912541b0
KS
186 ins->code = code;
187 ins->jt = jt;
188 ins->jf = jf;
189 ins->k = data;
190 (*i)++;
e14bdd88
KS
191}
192
ce1d6d7f
KS
193/**
194 * udev_monitor_filter_update:
195 * @udev_monitor: monitor
196 *
50579295
KS
197 * Update the installed socket filter. This is only needed,
198 * if the filter was removed or changed.
ce1d6d7f
KS
199 *
200 * Returns: 0 on success, otherwise a negative error value.
201 */
54cf0b7f 202_public_ int udev_monitor_filter_update(struct udev_monitor *udev_monitor)
e14bdd88 203{
912541b0
KS
204 struct sock_filter ins[512];
205 struct sock_fprog filter;
206 unsigned int i;
207 struct udev_list_entry *list_entry;
208 int err;
209
210 if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) == NULL &&
211 udev_list_get_entry(&udev_monitor->filter_tag_list) == NULL)
212 return 0;
213
214 memset(ins, 0x00, sizeof(ins));
215 i = 0;
216
217 /* load magic in A */
218 bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, magic));
219 /* jump if magic matches */
220 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, UDEV_MONITOR_MAGIC, 1, 0);
221 /* wrong magic, pass packet */
222 bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);
223
224 if (udev_list_get_entry(&udev_monitor->filter_tag_list) != NULL) {
225 int tag_matches;
226
227 /* count tag matches, to calculate end of tag match block */
228 tag_matches = 0;
229 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list))
230 tag_matches++;
231
232 /* add all tags matches */
233 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list)) {
234 uint64_t tag_bloom_bits = util_string_bloom64(udev_list_entry_get_name(list_entry));
235 uint32_t tag_bloom_hi = tag_bloom_bits >> 32;
236 uint32_t tag_bloom_lo = tag_bloom_bits & 0xffffffff;
237
238 /* load device bloom bits in A */
239 bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_tag_bloom_hi));
240 /* clear bits (tag bits & bloom bits) */
241 bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_hi);
242 /* jump to next tag if it does not match */
243 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_hi, 0, 3);
244
245 /* load device bloom bits in A */
246 bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_tag_bloom_lo));
247 /* clear bits (tag bits & bloom bits) */
248 bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_lo);
249 /* jump behind end of tag match block if tag matches */
250 tag_matches--;
251 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_lo, 1 + (tag_matches * 6), 0);
252 }
253
254 /* nothing matched, drop packet */
255 bpf_stmt(ins, &i, BPF_RET|BPF_K, 0);
256 }
257
258 /* add all subsystem matches */
259 if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) != NULL) {
260 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_subsystem_list)) {
261 unsigned int hash = util_string_hash32(udev_list_entry_get_name(list_entry));
262
263 /* load device subsystem value in A */
264 bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_subsystem_hash));
265 if (udev_list_entry_get_value(list_entry) == NULL) {
266 /* jump if subsystem does not match */
267 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1);
268 } else {
269 /* jump if subsystem does not match */
270 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 3);
271
272 /* load device devtype value in A */
273 bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_devtype_hash));
274 /* jump if value does not match */
275 hash = util_string_hash32(udev_list_entry_get_value(list_entry));
276 bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1);
277 }
278
279 /* matched, pass packet */
280 bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);
281
8fef0ff2 282 if (i+1 >= ELEMENTSOF(ins))
912541b0
KS
283 return -1;
284 }
285
286 /* nothing matched, drop packet */
287 bpf_stmt(ins, &i, BPF_RET|BPF_K, 0);
288 }
289
290 /* matched, pass packet */
291 bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);
292
293 /* install filter */
294 memset(&filter, 0x00, sizeof(filter));
295 filter.len = i;
296 filter.filter = ins;
297 err = setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter));
298 return err;
e14bdd88
KS
299}
300
1e03b754
KS
301int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender)
302{
b49d9b50 303 udev_monitor->snl_trusted_sender.nl.nl_pid = sender->snl.nl.nl_pid;
912541b0 304 return 0;
1e03b754 305}
ce1d6d7f
KS
306/**
307 * udev_monitor_enable_receiving:
308 * @udev_monitor: the monitor which should receive events
309 *
310 * Binds the @udev_monitor socket to the event source.
311 *
312 * Returns: 0 on success, otherwise a negative error value.
313 */
54cf0b7f 314_public_ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
d59f11e1 315{
912541b0
KS
316 int err = 0;
317 const int on = 1;
318
b49d9b50 319 if (udev_monitor->snl.nl.nl_family == 0)
912541b0 320 return -EINVAL;
2d13da88
KS
321
322 udev_monitor_filter_update(udev_monitor);
323
324 if (!udev_monitor->bound) {
325 err = bind(udev_monitor->sock,
b49d9b50 326 &udev_monitor->snl.sa, sizeof(struct sockaddr_nl));
2d13da88
KS
327 if (err == 0)
328 udev_monitor->bound = true;
912541b0
KS
329 }
330
2d13da88 331 if (err >= 0) {
b49d9b50 332 union sockaddr_union snl;
2d13da88
KS
333 socklen_t addrlen;
334
335 /*
336 * get the address the kernel has assigned us
337 * it is usually, but not necessarily the pid
338 */
339 addrlen = sizeof(struct sockaddr_nl);
b49d9b50 340 err = getsockname(udev_monitor->sock, &snl.sa, &addrlen);
2d13da88 341 if (err == 0)
b49d9b50 342 udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid;
2d13da88 343 } else {
c8f8394a 344 udev_err(udev_monitor->udev, "bind failed: %m\n");
912541b0
KS
345 return err;
346 }
347
348 /* enable receiving of sender credentials */
349 setsockopt(udev_monitor->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
350 return 0;
ba6929f6
KS
351}
352
f712894d
KS
353/**
354 * udev_monitor_set_receive_buffer_size:
355 * @udev_monitor: the monitor which should receive events
356 * @size: the size in bytes
357 *
358 * Set the size of the kernel socket buffer. This call needs the
359 * appropriate privileges to succeed.
360 *
361 * Returns: 0 on success, otherwise -1 on error.
362 */
54cf0b7f 363_public_ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size)
cb25a958 364{
912541b0
KS
365 if (udev_monitor == NULL)
366 return -1;
367 return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size));
cb25a958
KS
368}
369
1e03b754
KS
370int udev_monitor_disconnect(struct udev_monitor *udev_monitor)
371{
912541b0 372 int err;
1e03b754 373
912541b0
KS
374 err = close(udev_monitor->sock);
375 udev_monitor->sock = -1;
376 return err;
1e03b754
KS
377}
378
7d8787b3
KS
379/**
380 * udev_monitor_ref:
381 * @udev_monitor: udev monitor
382 *
383 * Take a reference of a udev monitor.
384 *
385 * Returns: the passed udev monitor
386 **/
54cf0b7f 387_public_ struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor)
ba6929f6 388{
912541b0
KS
389 if (udev_monitor == NULL)
390 return NULL;
391 udev_monitor->refcount++;
392 return udev_monitor;
ba6929f6
KS
393}
394
7d8787b3
KS
395/**
396 * udev_monitor_unref:
397 * @udev_monitor: udev monitor
398 *
ff109b8d 399 * Drop a reference of a udev monitor. If the refcount reaches zero,
be7de409 400 * the bound socket will be closed, and the resources of the monitor
7d8787b3
KS
401 * will be released.
402 *
c1959569 403 * Returns: the passed udev monitor if it has still an active reference, or #NULL otherwise.
7d8787b3 404 **/
20bbd54f 405_public_ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor)
ba6929f6 406{
912541b0 407 if (udev_monitor == NULL)
20bbd54f 408 return NULL;
912541b0
KS
409 udev_monitor->refcount--;
410 if (udev_monitor->refcount > 0)
20bbd54f 411 return udev_monitor;
912541b0
KS
412 if (udev_monitor->sock >= 0)
413 close(udev_monitor->sock);
414 udev_list_cleanup(&udev_monitor->filter_subsystem_list);
415 udev_list_cleanup(&udev_monitor->filter_tag_list);
912541b0 416 free(udev_monitor);
20bbd54f 417 return NULL;
ba6929f6
KS
418}
419
7d8787b3
KS
420/**
421 * udev_monitor_get_udev:
422 * @udev_monitor: udev monitor
423 *
b98fd840 424 * Retrieve the udev library context the monitor was created with.
7d8787b3
KS
425 *
426 * Returns: the udev library context
427 **/
54cf0b7f 428_public_ struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor)
ba6929f6 429{
912541b0
KS
430 if (udev_monitor == NULL)
431 return NULL;
432 return udev_monitor->udev;
ba6929f6
KS
433}
434
7d8787b3
KS
435/**
436 * udev_monitor_get_fd:
437 * @udev_monitor: udev monitor
438 *
439 * Retrieve the socket file descriptor associated with the monitor.
440 *
441 * Returns: the socket file descriptor
442 **/
54cf0b7f 443_public_ int udev_monitor_get_fd(struct udev_monitor *udev_monitor)
ba6929f6 444{
912541b0
KS
445 if (udev_monitor == NULL)
446 return -1;
447 return udev_monitor->sock;
ba6929f6
KS
448}
449
e14bdd88
KS
450static int passes_filter(struct udev_monitor *udev_monitor, struct udev_device *udev_device)
451{
912541b0
KS
452 struct udev_list_entry *list_entry;
453
454 if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) == NULL)
455 goto tag;
456 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_subsystem_list)) {
457 const char *subsys = udev_list_entry_get_name(list_entry);
458 const char *dsubsys = udev_device_get_subsystem(udev_device);
459 const char *devtype;
460 const char *ddevtype;
461
462 if (strcmp(dsubsys, subsys) != 0)
463 continue;
464
465 devtype = udev_list_entry_get_value(list_entry);
466 if (devtype == NULL)
467 goto tag;
468 ddevtype = udev_device_get_devtype(udev_device);
469 if (ddevtype == NULL)
470 continue;
471 if (strcmp(ddevtype, devtype) == 0)
472 goto tag;
473 }
474 return 0;
28460195
KS
475
476tag:
912541b0
KS
477 if (udev_list_get_entry(&udev_monitor->filter_tag_list) == NULL)
478 return 1;
479 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list)) {
480 const char *tag = udev_list_entry_get_name(list_entry);
481
482 if (udev_device_has_tag(udev_device, tag))
483 return 1;
484 }
485 return 0;
e14bdd88
KS
486}
487
7d8787b3 488/**
d59f11e1 489 * udev_monitor_receive_device:
7d8787b3
KS
490 * @udev_monitor: udev monitor
491 *
d59f11e1 492 * Receive data from the udev monitor socket, allocate a new udev
b98fd840 493 * device, fill in the received data, and return the device.
7d8787b3 494 *
50579295 495 * Only socket connections with uid=0 are accepted.
7d8787b3
KS
496 *
497 * The initial refcount is 1, and needs to be decremented to
be7de409 498 * release the resources of the udev device.
7d8787b3
KS
499 *
500 * Returns: a new udev device, or #NULL, in case of an error
501 **/
54cf0b7f 502_public_ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor)
ba6929f6 503{
912541b0
KS
504 struct udev_device *udev_device;
505 struct msghdr smsg;
506 struct iovec iov;
507 char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
508 struct cmsghdr *cmsg;
b49d9b50 509 union sockaddr_union snl;
912541b0
KS
510 struct ucred *cred;
511 char buf[8192];
512 ssize_t buflen;
513 ssize_t bufpos;
514 struct udev_monitor_netlink_header *nlh;
ba6929f6 515
e14bdd88 516retry:
912541b0
KS
517 if (udev_monitor == NULL)
518 return NULL;
912541b0
KS
519 iov.iov_base = &buf;
520 iov.iov_len = sizeof(buf);
521 memset (&smsg, 0x00, sizeof(struct msghdr));
522 smsg.msg_iov = &iov;
523 smsg.msg_iovlen = 1;
524 smsg.msg_control = cred_msg;
525 smsg.msg_controllen = sizeof(cred_msg);
526
b49d9b50 527 if (udev_monitor->snl.nl.nl_family != 0) {
912541b0
KS
528 smsg.msg_name = &snl;
529 smsg.msg_namelen = sizeof(snl);
530 }
531
532 buflen = recvmsg(udev_monitor->sock, &smsg, 0);
533 if (buflen < 0) {
534 if (errno != EINTR)
c8f8394a 535 udev_dbg(udev_monitor->udev, "unable to receive message\n");
912541b0
KS
536 return NULL;
537 }
538
539 if (buflen < 32 || (size_t)buflen >= sizeof(buf)) {
c8f8394a 540 udev_dbg(udev_monitor->udev, "invalid message length\n");
912541b0
KS
541 return NULL;
542 }
543
b49d9b50
KS
544 if (udev_monitor->snl.nl.nl_family != 0) {
545 if (snl.nl.nl_groups == 0) {
912541b0 546 /* unicast message, check if we trust the sender */
b49d9b50
KS
547 if (udev_monitor->snl_trusted_sender.nl.nl_pid == 0 ||
548 snl.nl.nl_pid != udev_monitor->snl_trusted_sender.nl.nl_pid) {
c8f8394a 549 udev_dbg(udev_monitor->udev, "unicast netlink message ignored\n");
912541b0
KS
550 return NULL;
551 }
b49d9b50
KS
552 } else if (snl.nl.nl_groups == UDEV_MONITOR_KERNEL) {
553 if (snl.nl.nl_pid > 0) {
c8f8394a 554 udev_dbg(udev_monitor->udev, "multicast kernel netlink message from pid %d ignored\n",
b49d9b50 555 snl.nl.nl_pid);
912541b0
KS
556 return NULL;
557 }
558 }
559 }
560
561 cmsg = CMSG_FIRSTHDR(&smsg);
562 if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
c8f8394a 563 udev_dbg(udev_monitor->udev, "no sender credentials received, message ignored\n");
912541b0
KS
564 return NULL;
565 }
566
567 cred = (struct ucred *)CMSG_DATA(cmsg);
568 if (cred->uid != 0) {
c8f8394a 569 udev_dbg(udev_monitor->udev, "sender uid=%d, message ignored\n", cred->uid);
912541b0
KS
570 return NULL;
571 }
572
573 if (memcmp(buf, "libudev", 8) == 0) {
574 /* udev message needs proper version magic */
575 nlh = (struct udev_monitor_netlink_header *) buf;
576 if (nlh->magic != htonl(UDEV_MONITOR_MAGIC)) {
c8f8394a 577 udev_err(udev_monitor->udev, "unrecognized message signature (%x != %x)\n",
912541b0
KS
578 nlh->magic, htonl(UDEV_MONITOR_MAGIC));
579 return NULL;
580 }
ee56538f 581 if (nlh->properties_off+32 > (size_t)buflen)
912541b0
KS
582 return NULL;
583 bufpos = nlh->properties_off;
584 } else {
585 /* kernel message with header */
586 bufpos = strlen(buf) + 1;
587 if ((size_t)bufpos < sizeof("a@/d") || bufpos >= buflen) {
c8f8394a 588 udev_dbg(udev_monitor->udev, "invalid message length\n");
912541b0
KS
589 return NULL;
590 }
591
592 /* check message header */
593 if (strstr(buf, "@/") == NULL) {
c8f8394a 594 udev_dbg(udev_monitor->udev, "unrecognized message header\n");
912541b0
KS
595 return NULL;
596 }
597 }
598
599 udev_device = udev_device_new(udev_monitor->udev);
600 if (udev_device == NULL)
601 return NULL;
602 udev_device_set_info_loaded(udev_device);
603
604 while (bufpos < buflen) {
605 char *key;
606 size_t keylen;
607
608 key = &buf[bufpos];
609 keylen = strlen(key);
610 if (keylen == 0)
611 break;
612 bufpos += keylen + 1;
613 udev_device_add_property_from_string_parse(udev_device, key);
614 }
615
616 if (udev_device_add_property_from_string_parse_finish(udev_device) < 0) {
c8f8394a 617 udev_dbg(udev_monitor->udev, "missing values, invalid device\n");
912541b0
KS
618 udev_device_unref(udev_device);
619 return NULL;
620 }
621
622 /* skip device, if it does not pass the current filter */
623 if (!passes_filter(udev_monitor, udev_device)) {
624 struct pollfd pfd[1];
625 int rc;
626
627 udev_device_unref(udev_device);
628
629 /* if something is queued, get next device */
630 pfd[0].fd = udev_monitor->sock;
631 pfd[0].events = POLLIN;
632 rc = poll(pfd, 1, 0);
633 if (rc > 0)
634 goto retry;
635 return NULL;
636 }
637
638 return udev_device;
ba6929f6 639}
9925ab04 640
1e03b754 641int udev_monitor_send_device(struct udev_monitor *udev_monitor,
912541b0 642 struct udev_monitor *destination, struct udev_device *udev_device)
9925ab04 643{
912541b0
KS
644 const char *buf;
645 ssize_t blen;
646 ssize_t count;
2d13da88
KS
647 struct msghdr smsg;
648 struct iovec iov[2];
649 const char *val;
650 struct udev_monitor_netlink_header nlh;
651 struct udev_list_entry *list_entry;
652 uint64_t tag_bloom_bits;
653
b49d9b50 654 if (udev_monitor->snl.nl.nl_family == 0)
2d13da88 655 return -EINVAL;
912541b0
KS
656
657 blen = udev_device_get_properties_monitor_buf(udev_device, &buf);
658 if (blen < 32)
659 return -EINVAL;
660
2d13da88
KS
661 /* add versioned header */
662 memset(&nlh, 0x00, sizeof(struct udev_monitor_netlink_header));
663 memcpy(nlh.prefix, "libudev", 8);
664 nlh.magic = htonl(UDEV_MONITOR_MAGIC);
665 nlh.header_size = sizeof(struct udev_monitor_netlink_header);
666 val = udev_device_get_subsystem(udev_device);
667 nlh.filter_subsystem_hash = htonl(util_string_hash32(val));
668 val = udev_device_get_devtype(udev_device);
669 if (val != NULL)
670 nlh.filter_devtype_hash = htonl(util_string_hash32(val));
671 iov[0].iov_base = &nlh;
672 iov[0].iov_len = sizeof(struct udev_monitor_netlink_header);
673
674 /* add tag bloom filter */
675 tag_bloom_bits = 0;
676 udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
677 tag_bloom_bits |= util_string_bloom64(udev_list_entry_get_name(list_entry));
678 if (tag_bloom_bits > 0) {
679 nlh.filter_tag_bloom_hi = htonl(tag_bloom_bits >> 32);
680 nlh.filter_tag_bloom_lo = htonl(tag_bloom_bits & 0xffffffff);
912541b0
KS
681 }
682
2d13da88
KS
683 /* add properties list */
684 nlh.properties_off = iov[0].iov_len;
685 nlh.properties_len = blen;
686 iov[1].iov_base = (char *)buf;
687 iov[1].iov_len = blen;
912541b0 688
2d13da88
KS
689 memset(&smsg, 0x00, sizeof(struct msghdr));
690 smsg.msg_iov = iov;
691 smsg.msg_iovlen = 2;
692 /*
693 * Use custom address for target, or the default one.
694 *
695 * If we send to a multicast group, we will get
696 * ECONNREFUSED, which is expected.
697 */
698 if (destination != NULL)
699 smsg.msg_name = &destination->snl;
700 else
701 smsg.msg_name = &udev_monitor->snl_destination;
702 smsg.msg_namelen = sizeof(struct sockaddr_nl);
703 count = sendmsg(udev_monitor->sock, &smsg, 0);
c8f8394a 704 udev_dbg(udev_monitor->udev, "passed %zi bytes to netlink monitor %p\n", count, udev_monitor);
2d13da88 705 return count;
9925ab04 706}
e14bdd88 707
ce1d6d7f
KS
708/**
709 * udev_monitor_filter_add_match_subsystem_devtype:
710 * @udev_monitor: the monitor
711 * @subsystem: the subsystem value to match the incoming devices against
214a6c79 712 * @devtype: the devtype value to match the incoming devices against
ce1d6d7f 713 *
50579295 714 * This filter is efficiently executed inside the kernel, and libudev subscribers
28460195
KS
715 * will usually not be woken up for devices which do not match.
716 *
ce1d6d7f
KS
717 * The filter must be installed before the monitor is switched to listening mode.
718 *
719 * Returns: 0 on success, otherwise a negative error value.
720 */
54cf0b7f 721_public_ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype)
e14bdd88 722{
912541b0
KS
723 if (udev_monitor == NULL)
724 return -EINVAL;
725 if (subsystem == NULL)
726 return -EINVAL;
727 if (udev_list_entry_add(&udev_monitor->filter_subsystem_list, subsystem, devtype) == NULL)
728 return -ENOMEM;
729 return 0;
e14bdd88 730}
08a7a795 731
28460195
KS
732/**
733 * udev_monitor_filter_add_match_tag:
734 * @udev_monitor: the monitor
735 * @tag: the name of a tag
736 *
50579295 737 * This filter is efficiently executed inside the kernel, and libudev subscribers
28460195
KS
738 * will usually not be woken up for devices which do not match.
739 *
740 * The filter must be installed before the monitor is switched to listening mode.
741 *
742 * Returns: 0 on success, otherwise a negative error value.
743 */
54cf0b7f 744_public_ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag)
28460195 745{
912541b0
KS
746 if (udev_monitor == NULL)
747 return -EINVAL;
748 if (tag == NULL)
749 return -EINVAL;
750 if (udev_list_entry_add(&udev_monitor->filter_tag_list, tag, NULL) == NULL)
751 return -ENOMEM;
752 return 0;
28460195
KS
753}
754
ce1d6d7f
KS
755/**
756 * udev_monitor_filter_remove:
757 * @udev_monitor: monitor
758 *
759 * Remove all filters from monitor.
760 *
761 * Returns: 0 on success, otherwise a negative error value.
762 */
54cf0b7f 763_public_ int udev_monitor_filter_remove(struct udev_monitor *udev_monitor)
08a7a795 764{
912541b0 765 static struct sock_fprog filter = { 0, NULL };
08a7a795 766
912541b0
KS
767 udev_list_cleanup(&udev_monitor->filter_subsystem_list);
768 return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter));
08a7a795 769}