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