xref: /dragonfly/sys/kern/kern_udev.c (revision 13dd34d8)
1 /*
2  * Copyright (c) 2010,2018 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Alex Hornung <ahornung@gmail.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/uio.h>
37 #include <sys/kernel.h>
38 #include <sys/proc.h>
39 #include <sys/buf.h>
40 #include <sys/conf.h>
41 #include <sys/event.h>
42 #include <sys/vnode.h>
43 #include <sys/malloc.h>
44 #include <sys/objcache.h>
45 #include <sys/ctype.h>
46 #include <sys/syslog.h>
47 #include <sys/udev.h>
48 #include <sys/devfs.h>
49 #include <libprop/proplib.h>
50 
51 MALLOC_DEFINE(M_UDEV, "udev", "udev allocs");
52 static struct objcache *udev_event_kernel_cache;
53 
54 /* XXX: use UUIDs for identification; would need help from devfs */
55 
56 static cdev_t		udev_dev;
57 static d_open_t		udev_dev_open;
58 static d_close_t	udev_dev_close;
59 static d_read_t		udev_dev_read;
60 static d_kqfilter_t	udev_dev_kqfilter;
61 static d_ioctl_t	udev_dev_ioctl;
62 static d_clone_t	udev_dev_clone;
63 
64 struct udev_prop_ctx {
65 	prop_array_t cdevs;
66 	int error;
67 };
68 
69 struct udev_event_kernel {
70 	struct udev_event ev;
71 	TAILQ_ENTRY(udev_event_kernel)	link;
72 };
73 
74 struct udev_softc {
75 	TAILQ_ENTRY(udev_softc) entry;
76 	int opened;
77 	int initiated;
78 	int unit;
79 	cdev_t dev;
80 
81 	struct udev_event_kernel marker;	/* udev_evq marker */
82 };
83 
84 struct cmd_function {
85 	const char *cmd;
86 	int  (*fn)(struct udev_softc *, struct plistref *,
87 		   u_long, prop_dictionary_t);
88 };
89 
90 static int _udev_dict_set_cstr(prop_dictionary_t, const char *, char *);
91 static int _udev_dict_set_int(prop_dictionary_t, const char *, int64_t);
92 static int _udev_dict_set_uint(prop_dictionary_t, const char *, uint64_t);
93 static int _udev_dict_delete_key(prop_dictionary_t, const char *);
94 static prop_dictionary_t udev_init_dict_event(cdev_t, const char *);
95 static int udev_init_dict(cdev_t);
96 static int udev_destroy_dict(cdev_t);
97 static void udev_event_insert(int, prop_dictionary_t);
98 static void udev_clean_events_locked(void);
99 static char *udev_event_externalize(struct udev_event_kernel *);
100 static void udev_getdevs_scan_callback(char *, cdev_t, bool, void *);
101 static int udev_getdevs_ioctl(struct udev_softc *, struct plistref *,
102 					u_long, prop_dictionary_t);
103 static void udev_dev_filter_detach(struct knote *);
104 static int udev_dev_filter_read(struct knote *, long);
105 
106 static struct dev_ops udev_dev_ops = {
107 	{ "udev", 0, 0 },
108 	.d_open = udev_dev_open,
109 	.d_close = udev_dev_close,
110 	.d_read = udev_dev_read,
111 	.d_kqfilter = udev_dev_kqfilter,
112 	.d_ioctl = udev_dev_ioctl
113 };
114 
115 static struct cmd_function cmd_fn[] = {
116 		{ .cmd = "getdevs", .fn = udev_getdevs_ioctl},
117 		{NULL, NULL}
118 };
119 
120 DEVFS_DEFINE_CLONE_BITMAP(udev);
121 
122 static TAILQ_HEAD(, udev_softc) udevq;
123 static TAILQ_HEAD(, udev_event_kernel) udev_evq;
124 static struct kqinfo udev_kq;
125 static struct lock udev_lk;
126 static int udev_evqlen;
127 static int udev_initiated_count;
128 static int udev_open_count;
129 static int udev_seqwait;
130 static int udev_seq;
131 static struct lock udev_dict_lk = LOCK_INITIALIZER("dict", 0, 0);
132 
133 /*
134  * Acquire the device's si_dict and lock the device's si_dict field.
135  * If the device does not have an attached dictionary, NULL is returned.
136  *
137  * This function must be matched by a udev_put_dict() call regardless of
138  * the return value.  The device field is STILL LOCKED even when NULL is
139  * returned.
140  *
141  * Currently a single global lock is implemented.
142  */
143 static prop_dictionary_t
udev_get_dict(cdev_t dev)144 udev_get_dict(cdev_t dev)
145 {
146 	prop_dictionary_t udict;
147 
148 	lockmgr(&udev_dict_lk, LK_EXCLUSIVE|LK_CANRECURSE);
149 	udict = dev->si_dict;
150 	if (udict)
151 		prop_object_retain(udict);
152 	return udict;
153 }
154 
155 /*
156  * Release the dictionary previously returned by udev_get_dict() and unlock
157  * the device's si_dict field.  udict may be NULL.
158  */
159 static void
udev_put_dict(cdev_t dev,prop_dictionary_t udict)160 udev_put_dict(cdev_t dev, prop_dictionary_t udict)
161 {
162 	if (udict)
163 		prop_object_release(udict);
164 	lockmgr(&udev_dict_lk, LK_RELEASE);
165 }
166 
167 static int
_udev_dict_set_cstr(prop_dictionary_t dict,const char * key,char * str)168 _udev_dict_set_cstr(prop_dictionary_t dict, const char *key, char *str)
169 {
170 	prop_string_t	ps;
171 
172 	KKASSERT(dict != NULL);
173 
174 	ps = prop_string_create_cstring(str);
175 	if (ps == NULL) {
176 		return ENOMEM;
177 	}
178 
179 	if (prop_dictionary_set(dict, key, ps) == false) {
180 		prop_object_release(ps);
181 		return ENOMEM;
182 	}
183 
184 	prop_object_release(ps);
185 	return 0;
186 }
187 
188 static int
_udev_dict_set_int(prop_dictionary_t dict,const char * key,int64_t val)189 _udev_dict_set_int(prop_dictionary_t dict, const char *key, int64_t val)
190 {
191 	prop_number_t	pn;
192 
193 	KKASSERT(dict != NULL);
194 
195 	pn = prop_number_create_integer(val);
196 	if (pn == NULL)
197 		return ENOMEM;
198 
199 	if (prop_dictionary_set(dict, key, pn) == false) {
200 		prop_object_release(pn);
201 		return ENOMEM;
202 	}
203 
204 	prop_object_release(pn);
205 	return 0;
206 }
207 
208 static int
_udev_dict_set_uint(prop_dictionary_t dict,const char * key,uint64_t val)209 _udev_dict_set_uint(prop_dictionary_t dict, const char *key, uint64_t val)
210 {
211 	prop_number_t	pn;
212 
213 	KKASSERT(dict != NULL);
214 
215 	pn = prop_number_create_unsigned_integer(val);
216 	if (pn == NULL)
217 		return ENOMEM;
218 
219 	if (prop_dictionary_set(dict, key, pn) == false) {
220 		prop_object_release(pn);
221 		return ENOMEM;
222 	}
223 
224 	prop_object_release(pn);
225 	return 0;
226 }
227 
228 static int
_udev_dict_delete_key(prop_dictionary_t dict,const char * key)229 _udev_dict_delete_key(prop_dictionary_t dict, const char *key)
230 {
231 	KKASSERT(dict != NULL);
232 
233 	prop_dictionary_remove(dict, key);
234 
235 	return 0;
236 }
237 
238 /*
239  * Initialize an event dictionary, which contains three parameters to
240  * identify the device referred to (name, devnum, kptr) and the affected key.
241  */
242 static prop_dictionary_t
udev_init_dict_event(cdev_t dev,const char * key)243 udev_init_dict_event(cdev_t dev, const char *key)
244 {
245 	prop_dictionary_t	dict;
246 	uint64_t	kptr;
247 	int error;
248 
249 	kptr = (uint64_t)(uintptr_t)dev;
250 	KKASSERT(dev != NULL);
251 
252 	dict = prop_dictionary_create();
253 	if (dict == NULL) {
254 		log(LOG_DEBUG, "udev_init_dict_event: prop_dictionary_create() failed\n");
255 		return NULL;
256 	}
257 
258 	if ((error = _udev_dict_set_cstr(dict, "name", dev->si_name)))
259 		goto error_out;
260 	if ((error = _udev_dict_set_uint(dict, "devnum", dev->si_inode)))
261 		goto error_out;
262 	if ((error = _udev_dict_set_uint(dict, "devtype", (dev_dflags(dev) & D_TYPEMASK))))
263 		goto error_out;
264 	if ((error = _udev_dict_set_uint(dict, "kptr", kptr)))
265 		goto error_out;
266 	if ((error = _udev_dict_set_cstr(dict, "key", __DECONST(char *, key))))
267 		goto error_out;
268 
269 	return dict;
270 
271 error_out:
272 	prop_object_release(dict);
273 	return NULL;
274 }
275 
276 int
udev_dict_set_cstr(cdev_t dev,const char * key,char * str)277 udev_dict_set_cstr(cdev_t dev, const char *key, char *str)
278 {
279 	prop_dictionary_t dict;
280 	prop_dictionary_t udict;
281 	int error;
282 
283 	KKASSERT(dev != NULL);
284 
285 	while ((udict = udev_get_dict(dev)) == NULL) {
286 		error = udev_init_dict(dev);
287 		udev_put_dict(dev, udict);
288 		if (error)
289 			return -1;
290 	}
291 
292 	/* Queue a key update event */
293 	dict = udev_init_dict_event(dev, key);
294 	if (dict == NULL) {
295 		error = ENOMEM;
296 		goto errout;
297 	}
298 
299 	if ((error = _udev_dict_set_cstr(dict, "value", str))) {
300 		prop_object_release(dict);
301 		goto errout;
302 	}
303 	udev_event_insert(UDEV_EV_KEY_UPDATE, dict);
304 	prop_object_release(dict);
305 	error = _udev_dict_set_cstr(udict, key, str);
306 
307 errout:
308 	udev_put_dict(dev, udict);
309 
310 	return error;
311 }
312 
313 int
udev_dict_set_int(cdev_t dev,const char * key,int64_t val)314 udev_dict_set_int(cdev_t dev, const char *key, int64_t val)
315 {
316 	prop_dictionary_t dict;
317 	prop_dictionary_t udict;
318 	int error;
319 
320 	KKASSERT(dev != NULL);
321 
322 	while ((udict = udev_get_dict(dev)) == NULL) {
323 		error = udev_init_dict(dev);
324 		udev_put_dict(dev, udict);
325 		if (error)
326 			return -1;
327 	}
328 
329 	/* Queue a key update event */
330 	dict = udev_init_dict_event(dev, key);
331 	if (dict == NULL) {
332 		error = ENOMEM;
333 		goto errout;
334 	}
335 	if ((error = _udev_dict_set_int(dict, "value", val))) {
336 		prop_object_release(dict);
337 		goto errout;
338 	}
339 	udev_event_insert(UDEV_EV_KEY_UPDATE, dict);
340 	prop_object_release(dict);
341 	error = _udev_dict_set_int(udict, key, val);
342 errout:
343 	udev_put_dict(dev, udict);
344 
345 	return error;
346 }
347 
348 int
udev_dict_set_uint(cdev_t dev,const char * key,uint64_t val)349 udev_dict_set_uint(cdev_t dev, const char *key, uint64_t val)
350 {
351 	prop_dictionary_t dict;
352 	prop_dictionary_t udict;
353 	int error;
354 
355 	KKASSERT(dev != NULL);
356 
357 	while ((udict = udev_get_dict(dev)) == NULL) {
358 		error = udev_init_dict(dev);
359 		udev_put_dict(dev, udict);
360 		if (error)
361 			return -1;
362 	}
363 
364 	/* Queue a key update event */
365 	dict = udev_init_dict_event(dev, key);
366 	if (dict == NULL) {
367 		error = ENOMEM;
368 		goto errout;
369 	}
370 	if ((error = _udev_dict_set_uint(dict, "value", val))) {
371 		prop_object_release(dict);
372 		goto errout;
373 	}
374 	udev_event_insert(UDEV_EV_KEY_UPDATE, dict);
375 	prop_object_release(dict);
376 	error = _udev_dict_set_uint(udict, key, val);
377 errout:
378 	udev_put_dict(dev, udict);
379 
380 	return error;
381 }
382 
383 int
udev_dict_delete_key(cdev_t dev,const char * key)384 udev_dict_delete_key(cdev_t dev, const char *key)
385 {
386 	prop_dictionary_t dict;
387 	prop_dictionary_t udict;
388 	int error;
389 
390 	KKASSERT(dev != NULL);
391 	udict = udev_get_dict(dev);
392 	if (udict == NULL) {
393 		error = ENOMEM;
394 		goto errout;
395 	}
396 
397 	/* Queue a key removal event */
398 	dict = udev_init_dict_event(dev, key);
399 	if (dict == NULL) {
400 		error = ENOMEM;
401 		goto errout;
402 	}
403 	udev_event_insert(UDEV_EV_KEY_REMOVE, dict);
404 	prop_object_release(dict);
405 	error = _udev_dict_delete_key(udict, key);
406 errout:
407 	udev_put_dict(dev, udict);
408 
409 	return error;
410 }
411 
412 /*
413  * device dictionary access already locked
414  */
415 static int
udev_init_dict(cdev_t dev)416 udev_init_dict(cdev_t dev)
417 {
418 	prop_dictionary_t dict;
419 	uint64_t	kptr;
420 	int error;
421 
422 	kptr = (uint64_t)(uintptr_t)dev;
423 
424 	KKASSERT(dev != NULL);
425 
426 	if (dev->si_dict != NULL) {
427 		log(LOG_DEBUG,
428 		    "udev_init_dict: new dict for %s, but has "
429 		    "dict already (%p)!\n",
430 		    dev->si_name, dev->si_dict);
431 		return 0;
432 	}
433 
434 	dict = prop_dictionary_create();
435 	if (dict == NULL) {
436 		log(LOG_DEBUG,
437 		    "udev_init_dict: prop_dictionary_create() failed\n");
438 		return ENOMEM;
439 	}
440 
441 	if ((error = _udev_dict_set_cstr(dict, "name", dev->si_name)))
442 		goto error_out;
443 	if ((error = _udev_dict_set_uint(dict, "devnum", dev->si_inode)))
444 		goto error_out;
445 	if ((error = _udev_dict_set_uint(dict, "kptr", kptr)))
446 		goto error_out;
447 	if ((error = _udev_dict_set_uint(dict, "devtype",
448 					 (dev_dflags(dev) & D_TYPEMASK)))) {
449 		goto error_out;
450 	}
451 
452 	/* XXX: The next 3 are marginallly useful, if at all */
453 	if ((error = _udev_dict_set_uint(dict, "uid", dev->si_uid)))
454 		goto error_out;
455 	if ((error = _udev_dict_set_uint(dict, "gid", dev->si_gid)))
456 		goto error_out;
457 	if ((error = _udev_dict_set_int(dict, "mode", dev->si_perms)))
458 		goto error_out;
459 
460 	if ((error = _udev_dict_set_int(dict, "major", dev->si_umajor)))
461 		goto error_out;
462 	if ((error = _udev_dict_set_int(dict, "minor", dev->si_uminor)))
463 		goto error_out;
464 	if (dev->si_ops->head.name != NULL) {
465 		if ((error = _udev_dict_set_cstr(dict, "driver",
466 		    __DECONST(char *, dev->si_ops->head.name))))
467 			goto error_out;
468 	}
469 
470 	dev->si_dict = dict;
471 	return 0;
472 
473 error_out:
474 	dev->si_dict = NULL;
475 	prop_object_release(dict);
476 	return error;
477 }
478 
479 /*
480  * device dictionary access already locked
481  */
482 static int
udev_destroy_dict(cdev_t dev)483 udev_destroy_dict(cdev_t dev)
484 {
485 	prop_dictionary_t udict;
486 
487 	KKASSERT(dev != NULL);
488 	udict = udev_get_dict(dev);
489 
490 	/* field is now locked, use directly to handle races */
491 	if (dev->si_dict) {
492 		prop_object_release(dev->si_dict);
493 		dev->si_dict = NULL;
494 	}
495 	udev_put_dict(dev, udict);
496 
497 	return 0;
498 }
499 
500 static void
udev_event_insert(int ev_type,prop_dictionary_t dict)501 udev_event_insert(int ev_type, prop_dictionary_t dict)
502 {
503 	struct udev_event_kernel *ev;
504 	prop_dictionary_t dict_copy;
505 
506 	/* Only start queing events after client has initiated properly */
507 	if (udev_initiated_count) {
508 		dict_copy = prop_dictionary_copy(dict);
509 		if (dict_copy == NULL)
510 			return;
511 		ev = objcache_get(udev_event_kernel_cache, M_WAITOK);
512 		ev->ev.ev_dict = dict_copy;
513 		ev->ev.ev_type = ev_type;
514 
515 		lockmgr(&udev_lk, LK_EXCLUSIVE);
516 		TAILQ_INSERT_TAIL(&udev_evq, ev, link);
517 		++udev_evqlen;
518 		++udev_seq;
519 		if (udev_seqwait)
520 			wakeup(&udev_seqwait);
521 		lockmgr(&udev_lk, LK_RELEASE);
522 		wakeup(&udev_evq);
523 		KNOTE(&udev_kq.ki_note, 0);
524 	} else if (udev_open_count) {
525 		lockmgr(&udev_lk, LK_EXCLUSIVE);
526 		++udev_seq;
527 		if (udev_seqwait)
528 			wakeup(&udev_seqwait);
529 		lockmgr(&udev_lk, LK_RELEASE);
530 		KNOTE(&udev_kq.ki_note, 0);
531 	}
532 }
533 
534 static void
udev_clean_events_locked(void)535 udev_clean_events_locked(void)
536 {
537 	struct udev_event_kernel *ev;
538 
539 	while ((ev = TAILQ_FIRST(&udev_evq)) &&
540 	       ev->ev.ev_dict != NULL) {
541 		TAILQ_REMOVE(&udev_evq, ev, link);
542 		objcache_put(udev_event_kernel_cache, ev);
543 		--udev_evqlen;
544 	}
545 }
546 
547 static char *
udev_event_externalize(struct udev_event_kernel * ev)548 udev_event_externalize(struct udev_event_kernel *ev)
549 {
550 	prop_dictionary_t	dict;
551 	char *xml;
552 	int error;
553 
554 	dict = prop_dictionary_create();
555 	if (dict == NULL) {
556 		log(LOG_DEBUG,
557 		    "udev_event_externalize: prop_dictionary_create() failed\n");
558 		return NULL;
559 	}
560 
561 	if ((error = _udev_dict_set_int(dict, "evtype", ev->ev.ev_type))) {
562 		prop_object_release(dict);
563 		return NULL;
564 	}
565 
566 	if (prop_dictionary_set(dict, "evdict", ev->ev.ev_dict) == false) {
567 		prop_object_release(dict);
568 		return NULL;
569 	}
570 
571 	prop_object_release(ev->ev.ev_dict);
572 
573 	xml = prop_dictionary_externalize(dict);
574 
575 	prop_object_release(dict);
576 
577 	return xml;
578 }
579 
580 int
udev_event_attach(cdev_t dev,char * name,int alias)581 udev_event_attach(cdev_t dev, char *name, int alias)
582 {
583 	prop_dictionary_t dict;
584 	prop_dictionary_t udict;
585 	int error;
586 
587 	KKASSERT(dev != NULL);
588 
589 	error = ENOMEM;
590 
591 	udict = udev_get_dict(dev);
592 	if (alias) {
593 		if (udict == NULL)
594 			goto error_out;
595 		dict = prop_dictionary_copy(udict);
596 		if (dict == NULL)
597 			goto error_out;
598 
599 		if ((error = _udev_dict_set_cstr(dict, "name", name))) {
600 			prop_object_release(dict);
601 			goto error_out;
602 		}
603 
604 		_udev_dict_set_int(dict, "alias", 1);
605 
606 		udev_event_insert(UDEV_EVENT_ATTACH, dict);
607 		prop_object_release(dict);
608 	} else {
609 		while (udict == NULL) {
610 			error = udev_init_dict(dev);
611 			if (error)
612 				goto error_out;
613 			udev_put_dict(dev, udict);
614 			udict = udev_get_dict(dev);
615 		}
616 		_udev_dict_set_int(udict, "alias", 0);
617 		udev_event_insert(UDEV_EVENT_ATTACH, udict);
618 	}
619 error_out:
620 	udev_put_dict(dev, udict);
621 
622 	return error;
623 }
624 
625 int
udev_event_detach(cdev_t dev,char * name,int alias)626 udev_event_detach(cdev_t dev, char *name, int alias)
627 {
628 	prop_dictionary_t dict;
629 	prop_dictionary_t udict;
630 
631 	KKASSERT(dev != NULL);
632 
633 	udict = udev_get_dict(dev);
634 	if (alias) {
635 		dict = prop_dictionary_copy(udict);
636 		if (dict == NULL)
637 			goto error_out;
638 
639 		if (_udev_dict_set_cstr(dict, "name", name)) {
640 			prop_object_release(dict);
641 			goto error_out;
642 		}
643 
644 		_udev_dict_set_int(dict, "alias", 1);
645 
646 		udev_event_insert(UDEV_EVENT_DETACH, dict);
647 		prop_object_release(dict);
648 	} else {
649 		if (udict)
650 			udev_event_insert(UDEV_EVENT_DETACH, udict);
651 	}
652 
653 error_out:
654 	udev_destroy_dict(dev);
655 	udev_put_dict(dev, udict);
656 
657 	return 0;
658 }
659 
660 /*
661  * Allow multiple opens.  Each opener gets a different device.
662  * Messages are replicated to all devices using a marker system.
663  */
664 static int
udev_dev_clone(struct dev_clone_args * ap)665 udev_dev_clone(struct dev_clone_args *ap)
666 {
667 	struct udev_softc *softc;
668 	int unit;
669 
670 	unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(udev), 1000);
671 	if (unit < 0) {
672 		ap->a_dev = NULL;
673 		return 1;
674 	}
675 
676 	softc = kmalloc(sizeof(*softc), M_UDEV, M_WAITOK | M_ZERO);
677 	softc->unit = unit;
678 	lockmgr(&udev_lk, LK_EXCLUSIVE);
679 	TAILQ_INSERT_TAIL(&udevq, softc, entry);
680 	lockmgr(&udev_lk, LK_RELEASE);
681 
682 	softc->dev = make_only_dev(&udev_dev_ops, unit, ap->a_cred->cr_ruid,
683 				   0, 0600, "udevs/%d", unit);
684 	softc->dev->si_drv1 = softc;
685 	ap->a_dev = softc->dev;
686 	return 0;
687 }
688 
689 /*
690  * dev stuff
691  */
692 static int
udev_dev_open(struct dev_open_args * ap)693 udev_dev_open(struct dev_open_args *ap)
694 {
695 	struct udev_softc *softc = ap->a_head.a_dev->si_drv1;
696 
697 	lockmgr(&udev_lk, LK_EXCLUSIVE);
698 	if (softc == NULL || softc->opened) {
699 		lockmgr(&udev_lk, LK_RELEASE);
700 		return EBUSY;
701 	}
702 	softc->opened = 1;
703 	++udev_open_count;
704 	lockmgr(&udev_lk, LK_RELEASE);
705 
706 	return 0;
707 }
708 
709 static int
udev_dev_close(struct dev_close_args * ap)710 udev_dev_close(struct dev_close_args *ap)
711 {
712 	struct udev_softc *softc = ap->a_head.a_dev->si_drv1;
713 
714 	KKASSERT(softc->dev == ap->a_head.a_dev);
715 	KKASSERT(softc->opened == 1);
716 
717 	destroy_dev(ap->a_head.a_dev);
718 	lockmgr(&udev_lk, LK_EXCLUSIVE);
719 	TAILQ_REMOVE(&udevq, softc, entry);
720 
721 	if (softc->initiated) {
722 		TAILQ_REMOVE(&udev_evq, &softc->marker, link);
723 		softc->initiated = 0;
724 		--udev_initiated_count;
725 		udev_clean_events_locked();
726 	}
727 	softc->opened = 0;
728 	softc->dev = NULL;
729 	ap->a_head.a_dev->si_drv1 = NULL;
730 	--udev_open_count;
731 	lockmgr(&udev_lk, LK_RELEASE);
732 
733 	/*
734 	 * WARNING! devfs_clone_bitmap_put() interacts with the devfs
735 	 *	    thread, avoid deadlocks by ensuring we are unlocked
736 	 *	    before calling.
737 	 */
738 	devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(udev), softc->unit);
739 	wakeup(&udev_evq);
740 
741 	kfree(softc, M_UDEV);
742 
743 	return 0;
744 }
745 
746 static struct filterops udev_dev_read_filtops =
747 	{ FILTEROP_ISFD | FILTEROP_MPSAFE, NULL,
748 	  udev_dev_filter_detach, udev_dev_filter_read };
749 
750 static int
udev_dev_kqfilter(struct dev_kqfilter_args * ap)751 udev_dev_kqfilter(struct dev_kqfilter_args *ap)
752 {
753 	struct udev_softc *softc = ap->a_head.a_dev->si_drv1;
754 	struct knote *kn = ap->a_kn;
755 	struct klist *klist;
756 
757 	ap->a_result = 0;
758 	lockmgr(&udev_lk, LK_EXCLUSIVE);
759 
760 	switch (kn->kn_filter) {
761 	case EVFILT_READ:
762 		kn->kn_fop = &udev_dev_read_filtops;
763 		kn->kn_hook = (caddr_t)softc;
764 		break;
765 	default:
766 		ap->a_result = EOPNOTSUPP;
767 	        lockmgr(&udev_lk, LK_RELEASE);
768 		return (0);
769 	}
770 
771 	klist = &udev_kq.ki_note;
772 	knote_insert(klist, kn);
773 
774         lockmgr(&udev_lk, LK_RELEASE);
775 
776 	return (0);
777 }
778 
779 static void
udev_dev_filter_detach(struct knote * kn)780 udev_dev_filter_detach(struct knote *kn)
781 {
782 	struct klist *klist;
783 
784 	lockmgr(&udev_lk, LK_EXCLUSIVE);
785 	klist = &udev_kq.ki_note;
786 	knote_remove(klist, kn);
787 	lockmgr(&udev_lk, LK_RELEASE);
788 }
789 
790 static int
udev_dev_filter_read(struct knote * kn,long hint)791 udev_dev_filter_read(struct knote *kn, long hint)
792 {
793 	struct udev_softc *softc = (void *)kn->kn_hook;
794 	struct udev_event_kernel *ev;
795 	int ready = 0;
796 
797 	lockmgr(&udev_lk, LK_EXCLUSIVE);
798 	if (softc->initiated) {
799 		ev = TAILQ_NEXT(&softc->marker, link);
800 		while (ev && ev->ev.ev_dict == NULL)
801 			ev = TAILQ_NEXT(ev, link);
802 		if (ev)
803 			ready = 1;
804 	}
805 	lockmgr(&udev_lk, LK_RELEASE);
806 
807 	return (ready);
808 }
809 
810 static int
udev_dev_read(struct dev_read_args * ap)811 udev_dev_read(struct dev_read_args *ap)
812 {
813 	struct udev_softc *softc = ap->a_head.a_dev->si_drv1;
814 	struct udev_event_kernel *ev;
815 	struct uio *uio = ap->a_uio;
816 	char	*xml;
817 	size_t	len;
818 	int	error;
819 
820 	lockmgr(&udev_lk, LK_EXCLUSIVE);
821 
822 	/*
823 	 * Automatically enable message collection if it has not already
824 	 * been enabled.
825 	 */
826 	if (softc->initiated == 0) {
827 		softc->initiated = 1;
828 		++udev_initiated_count;
829 		TAILQ_INSERT_HEAD(&udev_evq, &softc->marker, link);
830 	}
831 
832 	/*
833 	 * Loop, sleep interruptably until we get an event or signal.
834 	 */
835 	error = 0;
836 	for (;;) {
837 		if (softc->initiated) {
838 			ev = TAILQ_NEXT(&softc->marker, link);
839 			while (ev && ev->ev.ev_dict == NULL)
840 				ev = TAILQ_NEXT(ev, link);
841 			if (ev) {
842 				if ((xml = udev_event_externalize(ev)) == NULL) {
843 					error = ENOMEM;
844 					break;
845 				}
846 				len = strlen(xml) + 1; /* include terminator */
847 				if (uio->uio_resid < len)
848 					error = ENOMEM;
849 				else
850 					error = uiomove((caddr_t)xml, len, uio);
851 				kfree(xml, M_TEMP);
852 
853 				/*
854 				 * Move the marker
855 				 */
856 				TAILQ_REMOVE(&udev_evq, &softc->marker, link);
857 				TAILQ_INSERT_AFTER(&udev_evq,
858 						   ev, &softc->marker, link);
859 				udev_clean_events_locked();
860 				break;
861 			}
862 		}
863 		if (ap->a_ioflag & IO_NDELAY) {
864 			error = EWOULDBLOCK;
865 			break;
866 		}
867 		if ((error = lksleep(&udev_evq, &udev_lk, PCATCH, "udevq", 0)))
868 			break;
869 	}
870 
871 	lockmgr(&udev_lk, LK_RELEASE);
872 	return error;
873 }
874 
875 static int
udev_dev_ioctl(struct dev_ioctl_args * ap)876 udev_dev_ioctl(struct dev_ioctl_args *ap)
877 {
878 	struct udev_softc *softc = ap->a_head.a_dev->si_drv1;
879 	prop_dictionary_t dict;
880 	prop_object_t	po;
881 	prop_string_t	ps;
882 	struct plistref *pref;
883 	int i, error;
884 	int seq;
885 
886 	error = 0;
887 
888 	switch(ap->a_cmd) {
889 	case UDEVPROP:
890 		/* Use proplib(3) for userspace/kernel communication */
891 		pref = (struct plistref *)ap->a_data;
892 		error = prop_dictionary_copyin_ioctl(pref, ap->a_cmd, &dict);
893 		if (error)
894 			return error;
895 
896 		po = prop_dictionary_get(dict, "command");
897 		if (po == NULL || prop_object_type(po) != PROP_TYPE_STRING) {
898 			log(LOG_DEBUG, "udev: prop_dictionary_get() failed\n");
899 			prop_object_release(dict);
900 			return EINVAL;
901 		}
902 
903 		ps = po;
904 		/* Handle cmd */
905 		for(i = 0; cmd_fn[i].cmd != NULL; i++) {
906 			if (prop_string_equals_cstring(ps, cmd_fn[i].cmd))
907 				break;
908 		}
909 
910 		if (cmd_fn[i].cmd != NULL) {
911 			error = cmd_fn[i].fn(softc, pref, ap->a_cmd, dict);
912 		} else {
913 			error = EINVAL;
914 		}
915 
916 		//prop_object_release(po);
917 		prop_object_release(dict);
918 		break;
919 	case UDEVWAIT:
920 		/*
921 		 * Wait for events based on sequence number.  Updates
922 		 * sequence number for loop.
923 		 */
924 		lockmgr(&udev_lk, LK_EXCLUSIVE);
925 		seq = *(int *)ap->a_data;
926 		++udev_seqwait;
927 		while (seq == udev_seq) {
928 			error = lksleep(&udev_seqwait, &udev_lk,
929 					PCATCH, "udevw", 0);
930 			if (error)
931 				break;
932 		}
933 		--udev_seqwait;
934 		*(int *)ap->a_data = udev_seq;
935 		lockmgr(&udev_lk, LK_RELEASE);
936 		break;
937 	default:
938 		error = ENOTTY; /* Inappropriate ioctl for device */
939 		break;
940 	}
941 
942 	return(error);
943 }
944 
945 static void
udev_getdevs_scan_callback(char * name,cdev_t cdev,bool is_alias,void * arg)946 udev_getdevs_scan_callback(char *name, cdev_t cdev, bool is_alias, void *arg)
947 {
948 	struct udev_prop_ctx *ctx = arg;
949 
950 	KKASSERT(arg != NULL);
951 
952 	if (cdev->si_dict == NULL)
953 		return;
954 
955 	if (prop_array_add(ctx->cdevs, cdev->si_dict) == false) {
956 		ctx->error = EINVAL;
957 		return;
958 	}
959 }
960 
961 static int
udev_getdevs_ioctl(struct udev_softc * softc,struct plistref * pref,u_long cmd,prop_dictionary_t dict)962 udev_getdevs_ioctl(struct udev_softc *softc, struct plistref *pref,
963 		   u_long cmd, prop_dictionary_t dict)
964 {
965 	prop_dictionary_t odict;
966 	struct udev_prop_ctx ctx;
967 	int error;
968 
969 	/*
970 	 * Ensure event notification is enabled before doing the devfs
971 	 * scan so nothing gets missed.
972 	 */
973 	lockmgr(&udev_lk, LK_EXCLUSIVE);
974 	if (softc->initiated == 0) {
975 		softc->initiated = 1;
976 		++udev_initiated_count;
977 		TAILQ_INSERT_HEAD(&udev_evq, &softc->marker, link);
978 	}
979 	lockmgr(&udev_lk, LK_RELEASE);
980 
981 	/*
982 	 * Devfs scan to build full dictionary.
983 	 */
984 	ctx.error = 0;
985 	ctx.cdevs = prop_array_create();
986 	if (ctx.cdevs == NULL) {
987 		log(LOG_DEBUG,
988 		    "udev_getdevs_ioctl: prop_array_create() failed\n");
989 		return EINVAL;
990 	}
991 
992 	devfs_scan_callback(udev_getdevs_scan_callback, &ctx);
993 
994 	if (ctx.error != 0) {
995 		prop_object_release(ctx.cdevs);
996 		return (ctx.error);
997 	}
998 
999 	odict = prop_dictionary_create();
1000 	if (odict == NULL) {
1001 		return ENOMEM;
1002 	}
1003 
1004 	if ((prop_dictionary_set(odict, "array", ctx.cdevs)) == 0) {
1005 		log(LOG_DEBUG,
1006 		    "udev_getdevs_ioctl: prop_dictionary_set failed\n");
1007 		prop_object_release(odict);
1008 		return ENOMEM;
1009 	}
1010 
1011 	error = prop_dictionary_copyout_ioctl(pref, cmd, odict);
1012 
1013 	prop_object_release(odict);
1014 	return error;
1015 }
1016 
1017 
1018 /*
1019  * SYSINIT stuff
1020  */
1021 static void
udev_init(void)1022 udev_init(void)
1023 {
1024 	lockinit(&udev_lk, "udevlk", 0, LK_CANRECURSE);
1025 	TAILQ_INIT(&udevq);
1026 	TAILQ_INIT(&udev_evq);
1027 	udev_event_kernel_cache = objcache_create_simple(M_UDEV, sizeof(struct udev_event_kernel));
1028 }
1029 
1030 static void
udev_uninit(void)1031 udev_uninit(void)
1032 {
1033 	objcache_destroy(udev_event_kernel_cache);
1034 }
1035 
1036 static void
udev_dev_init(void)1037 udev_dev_init(void)
1038 {
1039 	udev_dev = make_autoclone_dev(&udev_dev_ops, &DEVFS_CLONE_BITMAP(udev),
1040 				      udev_dev_clone,
1041 				      UID_ROOT, GID_WHEEL, 0600, "udev");
1042 }
1043 
1044 static void
udev_dev_uninit(void)1045 udev_dev_uninit(void)
1046 {
1047 	destroy_dev(udev_dev);
1048 }
1049 
1050 SYSINIT(subr_udev_register, SI_SUB_CREATE_INIT, SI_ORDER_ANY,
1051 	udev_init, NULL);
1052 SYSUNINIT(subr_udev_register, SI_SUB_CREATE_INIT, SI_ORDER_ANY,
1053 	udev_uninit, NULL);
1054 SYSINIT(subr_udev_dev_register, SI_SUB_DRIVERS, SI_ORDER_ANY,
1055 	udev_dev_init, NULL);
1056 SYSUNINIT(subr_udev_dev_register, SI_SUB_DRIVERS, SI_ORDER_ANY,
1057 	udev_dev_uninit, NULL);
1058