1 /* 2 * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "domains.h" 11 #include "interfaces.h" 12 #include "stack_private.h" 13 #include "utility.h" 14 15 #include <net_device.h> 16 17 #include <lock.h> 18 #include <util/AutoLock.h> 19 20 #include <KernelExport.h> 21 22 #include <net/if_dl.h> 23 #include <new> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 28 29 #define TRACE_INTERFACES 30 #ifdef TRACE_INTERFACES 31 # define TRACE(x) dprintf x 32 #else 33 # define TRACE(x) ; 34 #endif 35 36 #define ENABLE_DEBUGGER_COMMANDS 1 37 38 39 static mutex sInterfaceLock; 40 static DeviceInterfaceList sInterfaces; 41 static uint32 sInterfaceIndex; 42 static uint32 sDeviceIndex; 43 44 45 static status_t 46 device_consumer_thread(void* _interface) 47 { 48 net_device_interface* interface = (net_device_interface*)_interface; 49 net_device* device = interface->device; 50 net_buffer* buffer; 51 52 while (true) { 53 ssize_t status = fifo_dequeue_buffer(&interface->receive_queue, 0, 54 B_INFINITE_TIMEOUT, &buffer); 55 if (status == B_INTERRUPTED) 56 continue; 57 else if (status < B_OK) 58 break; 59 60 if (buffer->interface != NULL) { 61 // if the interface is already specified, this buffer was 62 // delivered locally. 63 if (buffer->interface->domain->module->receive_data(buffer) == B_OK) 64 buffer = NULL; 65 } else { 66 // find handler for this packet 67 DeviceHandlerList::Iterator iterator = 68 interface->receive_funcs.GetIterator(); 69 while (buffer && iterator.HasNext()) { 70 net_device_handler* handler = iterator.Next(); 71 72 // if the handler returns B_OK, it consumed the buffer 73 if (handler->type == buffer->type 74 && handler->func(handler->cookie, device, buffer) == B_OK) 75 buffer = NULL; 76 } 77 } 78 79 if (buffer != NULL) 80 gNetBufferModule.free(buffer); 81 } 82 83 return B_OK; 84 } 85 86 87 static net_device_interface* 88 find_device_interface(const char* name) 89 { 90 DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator(); 91 92 while (net_device_interface* interface = iterator.Next()) { 93 if (!strcmp(interface->device->name, name)) 94 return interface; 95 } 96 97 return NULL; 98 } 99 100 101 /*! The domain's device receive handler - this will inject the net_buffers into 102 the protocol layer (the domain's registered receive handler). 103 */ 104 static status_t 105 domain_receive_adapter(void* cookie, net_device* device, net_buffer* buffer) 106 { 107 net_domain_private* domain = (net_domain_private*)cookie; 108 109 buffer->interface = find_interface(domain, device->index); 110 return domain->module->receive_data(buffer); 111 } 112 113 114 static net_device_interface* 115 allocate_device_interface(net_device* device, net_device_module_info* module) 116 { 117 net_device_interface* interface = new(std::nothrow) net_device_interface; 118 if (interface == NULL) 119 return NULL; 120 121 recursive_lock_init(&interface->receive_lock, "interface receive lock"); 122 123 char name[128]; 124 snprintf(name, sizeof(name), "%s receive queue", device->name); 125 126 if (init_fifo(&interface->receive_queue, name, 16 * 1024 * 1024) < B_OK) 127 goto error1; 128 129 interface->device = device; 130 interface->up_count = 0; 131 interface->ref_count = 1; 132 interface->deframe_func = NULL; 133 interface->deframe_ref_count = 0; 134 135 snprintf(name, sizeof(name), "%s consumer", device->name); 136 137 interface->reader_thread = -1; 138 interface->consumer_thread = spawn_kernel_thread(device_consumer_thread, 139 name, B_DISPLAY_PRIORITY, interface); 140 if (interface->consumer_thread < B_OK) 141 goto error2; 142 resume_thread(interface->consumer_thread); 143 144 // TODO: proper interface index allocation 145 device->index = ++sDeviceIndex; 146 device->module = module; 147 148 sInterfaces.Add(interface); 149 return interface; 150 151 error2: 152 uninit_fifo(&interface->receive_queue); 153 error1: 154 recursive_lock_destroy(&interface->receive_lock); 155 delete interface; 156 157 return NULL; 158 } 159 160 161 static net_device_interface* 162 acquire_device_interface(net_device_interface* interface) 163 { 164 if (interface == NULL || atomic_add(&interface->ref_count, 1) == 0) 165 return NULL; 166 167 return interface; 168 } 169 170 171 static void 172 notify_device_monitors(net_device_interface* interface, int32 event) 173 { 174 RecursiveLocker _(interface->receive_lock); 175 176 DeviceMonitorList::Iterator iterator 177 = interface->monitor_funcs.GetIterator(); 178 while (net_device_monitor* monitor = iterator.Next()) { 179 // it's safe for the "current" item to remove itself. 180 monitor->event(monitor, event); 181 } 182 } 183 184 185 #if ENABLE_DEBUGGER_COMMANDS 186 187 188 static int 189 dump_interface(int argc, char** argv) 190 { 191 if (argc != 2) { 192 kprintf("usage: %s [address]\n", argv[0]); 193 return 0; 194 } 195 196 net_interface_private* interface 197 = (net_interface_private*)parse_expression(argv[1]); 198 199 kprintf("name: %s\n", interface->name); 200 kprintf("base_name: %s\n", interface->name); 201 kprintf("domain: %p\n", interface->domain); 202 kprintf("device: %p\n", interface->device); 203 kprintf("device_interface: %p\n", interface->device_interface); 204 kprintf("direct_route: %p\n", &interface->direct_route); 205 kprintf("first_protocol: %p\n", interface->first_protocol); 206 kprintf("first_info: %p\n", interface->first_info); 207 kprintf("address: %p\n", interface->address); 208 kprintf("destination: %p\n", interface->destination); 209 kprintf("mask: %p\n", interface->mask); 210 kprintf("index: %" B_PRIu32 "\n", interface->index); 211 kprintf("flags: %#" B_PRIx32 "\n", interface->flags); 212 kprintf("type: %u\n", interface->type); 213 kprintf("mtu: %" B_PRIu32 "\n", interface->mtu); 214 kprintf("metric: %" B_PRIu32 "\n", interface->metric); 215 216 return 0; 217 } 218 219 220 static int 221 dump_device_interface(int argc, char** argv) 222 { 223 if (argc != 2) { 224 kprintf("usage: %s [address]\n", argv[0]); 225 return 0; 226 } 227 228 net_device_interface* interface 229 = (net_device_interface*)parse_expression(argv[1]); 230 231 kprintf("device: %p\n", interface->device); 232 kprintf("reader_thread: %ld\n", interface->reader_thread); 233 kprintf("up_count: %" B_PRIu32 "\n", interface->up_count); 234 kprintf("ref_count: %" B_PRId32 "\n", interface->ref_count); 235 kprintf("deframe_func: %p\n", interface->deframe_func); 236 kprintf("deframe_ref_count: %" B_PRId32 "\n", interface->ref_count); 237 kprintf("monitor_funcs:\n"); 238 kprintf("receive_funcs:\n"); 239 kprintf("consumer_thread: %ld\n", interface->consumer_thread); 240 kprintf("receive_lock: %p\n", &interface->receive_lock); 241 kprintf("receive_queue: %p\n", &interface->receive_queue); 242 243 DeviceMonitorList::Iterator monitorIterator 244 = interface->monitor_funcs.GetIterator(); 245 while (monitorIterator.HasNext()) 246 kprintf(" %p\n", monitorIterator.Next()); 247 248 DeviceHandlerList::Iterator handlerIterator 249 = interface->receive_funcs.GetIterator(); 250 while (handlerIterator.HasNext()) 251 kprintf(" %p\n", handlerIterator.Next()); 252 253 return 0; 254 } 255 256 257 static int 258 dump_device_interfaces(int argc, char** argv) 259 { 260 DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator(); 261 while (net_device_interface* interface = iterator.Next()) { 262 kprintf(" %p\n", interface); 263 } 264 265 return 0; 266 } 267 268 269 #endif // ENABLE_DEBUGGER_COMMANDS 270 271 272 // #pragma mark - interfaces 273 274 275 /*! Searches for a specific interface in a domain by name. 276 You need to have the domain's lock hold when calling this function. 277 */ 278 struct net_interface_private* 279 find_interface(struct net_domain* domain, const char* name) 280 { 281 net_interface_private* interface = NULL; 282 283 while (true) { 284 interface = (net_interface_private*)list_get_next_item( 285 &domain->interfaces, interface); 286 if (interface == NULL) 287 break; 288 289 if (!strcmp(interface->name, name)) 290 return interface; 291 } 292 293 return NULL; 294 } 295 296 297 /*! Searches for a specific interface in a domain by index. 298 You need to have the domain's lock hold when calling this function. 299 */ 300 struct net_interface_private* 301 find_interface(struct net_domain* domain, uint32 index) 302 { 303 net_interface_private* interface = NULL; 304 305 while (true) { 306 interface = (net_interface_private*)list_get_next_item( 307 &domain->interfaces, interface); 308 if (interface == NULL) 309 break; 310 311 if (interface->index == index) 312 return interface; 313 } 314 315 return NULL; 316 } 317 318 319 status_t 320 create_interface(net_domain* domain, const char* name, const char* baseName, 321 net_device_interface* deviceInterface, net_interface_private** _interface) 322 { 323 net_interface_private* interface = new(std::nothrow) net_interface_private; 324 if (interface == NULL) 325 return B_NO_MEMORY; 326 327 strlcpy(interface->name, name, IF_NAMESIZE); 328 strlcpy(interface->base_name, baseName, IF_NAMESIZE); 329 interface->domain = domain; 330 interface->device = deviceInterface->device; 331 332 interface->address = NULL; 333 interface->destination = NULL; 334 interface->mask = NULL; 335 336 interface->index = ++sInterfaceIndex; 337 interface->flags = 0; 338 interface->type = 0; 339 interface->mtu = deviceInterface->device->mtu; 340 interface->metric = 0; 341 interface->device_interface = acquire_device_interface(deviceInterface); 342 343 // setup direct route for bound devices 344 interface->direct_route.destination = NULL; 345 interface->direct_route.mask = NULL; 346 interface->direct_route.gateway = NULL; 347 interface->direct_route.flags = 0; 348 interface->direct_route.mtu = 0; 349 interface->direct_route.interface = interface; 350 interface->direct_route.ref_count = 1; 351 // make sure this doesn't get deleted accidently 352 353 status_t status = get_domain_datalink_protocols(interface); 354 if (status < B_OK) { 355 delete interface; 356 return status; 357 } 358 359 // Grab a reference to the networking stack, to make sure it won't be 360 // unloaded as long as an interface exists 361 module_info* module; 362 get_module(gNetStackInterfaceModule.info.name, &module); 363 364 *_interface = interface; 365 return B_OK; 366 } 367 368 369 void 370 interface_set_down(net_interface* interface) 371 { 372 if ((interface->flags & IFF_UP) == 0) 373 return; 374 375 interface->flags &= ~IFF_UP; 376 interface->first_info->interface_down(interface->first_protocol); 377 } 378 379 380 void 381 delete_interface(net_interface_private* interface) 382 { 383 // deleting an interface is fairly complex as we need 384 // to clear all references to it throughout the stack 385 386 // this will possibly call (if IFF_UP): 387 // interface_protocol_down() 388 // domain_interface_went_down() 389 // invalidate_routes() 390 // remove_route() 391 // update_route_infos() 392 // get_route_internal() 393 // down_device_interface() -- if upcount reaches 0 394 interface_set_down(interface); 395 396 // This call requires the RX Lock to be a recursive 397 // lock since each uninit_protocol() call may call 398 // again into the stack to unregister a reader for 399 // instance, which tries to obtain the RX lock again. 400 put_domain_datalink_protocols(interface); 401 402 put_device_interface(interface->device_interface); 403 404 free(interface->address); 405 free(interface->destination); 406 free(interface->mask); 407 408 delete interface; 409 410 // Release reference of the stack - at this point, our stack may be unloaded 411 // if no other interfaces or sockets are left 412 put_module(gNetStackInterfaceModule.info.name); 413 } 414 415 416 void 417 put_interface(struct net_interface_private* interface) 418 { 419 // TODO: reference counting 420 // TODO: better locking scheme 421 recursive_lock_unlock(&((net_domain_private*)interface->domain)->lock); 422 } 423 424 425 struct net_interface_private* 426 get_interface(net_domain* _domain, const char* name) 427 { 428 net_domain_private* domain = (net_domain_private*)_domain; 429 recursive_lock_lock(&domain->lock); 430 431 net_interface_private* interface = NULL; 432 while (true) { 433 interface = (net_interface_private*)list_get_next_item( 434 &domain->interfaces, interface); 435 if (interface == NULL) 436 break; 437 438 // TODO: We keep the domain locked for now 439 if (!strcmp(interface->name, name)) 440 return interface; 441 } 442 443 recursive_lock_unlock(&domain->lock); 444 return NULL; 445 } 446 447 448 // #pragma mark - device interfaces 449 450 451 void 452 get_device_interface_address(net_device_interface* interface, sockaddr* _address) 453 { 454 sockaddr_dl &address = *(sockaddr_dl*)_address; 455 456 address.sdl_family = AF_LINK; 457 address.sdl_index = interface->device->index; 458 address.sdl_type = interface->device->type; 459 address.sdl_nlen = strlen(interface->device->name); 460 address.sdl_slen = 0; 461 memcpy(address.sdl_data, interface->device->name, address.sdl_nlen); 462 463 address.sdl_alen = interface->device->address.length; 464 memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen); 465 466 address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data) 467 + address.sdl_nlen + address.sdl_alen; 468 } 469 470 471 uint32 472 count_device_interfaces() 473 { 474 MutexLocker locker(sInterfaceLock); 475 476 DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator(); 477 uint32 count = 0; 478 479 while (iterator.HasNext()) { 480 iterator.Next(); 481 count++; 482 } 483 484 return count; 485 } 486 487 488 /*! Dumps a list of all interfaces into the supplied userland buffer. 489 If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is 490 returned. 491 */ 492 status_t 493 list_device_interfaces(void* _buffer, size_t* bufferSize) 494 { 495 MutexLocker locker(sInterfaceLock); 496 497 DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator(); 498 UserBuffer buffer(_buffer, *bufferSize); 499 500 while (net_device_interface* interface = iterator.Next()) { 501 ifreq request; 502 strlcpy(request.ifr_name, interface->device->name, IF_NAMESIZE); 503 get_device_interface_address(interface, &request.ifr_addr); 504 505 if (buffer.Copy(&request, IF_NAMESIZE + request.ifr_addr.sa_len) == NULL) 506 return buffer.Status(); 507 } 508 509 *bufferSize = buffer.ConsumedAmount(); 510 return B_OK; 511 } 512 513 514 /*! Releases the reference for the interface. When all references are 515 released, the interface is removed. 516 */ 517 void 518 put_device_interface(struct net_device_interface* interface) 519 { 520 if (atomic_add(&interface->ref_count, -1) != 1) 521 return; 522 523 { 524 MutexLocker locker(sInterfaceLock); 525 sInterfaces.Remove(interface); 526 } 527 528 uninit_fifo(&interface->receive_queue); 529 status_t status; 530 wait_for_thread(interface->consumer_thread, &status); 531 532 net_device* device = interface->device; 533 const char* moduleName = device->module->info.name; 534 535 device->module->uninit_device(device); 536 put_module(moduleName); 537 538 recursive_lock_destroy(&interface->receive_lock); 539 delete interface; 540 } 541 542 543 /*! Finds an interface by the specified index and acquires a reference to it. 544 */ 545 struct net_device_interface* 546 get_device_interface(uint32 index) 547 { 548 MutexLocker locker(sInterfaceLock); 549 550 // TODO: maintain an array of all device interfaces instead 551 DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator(); 552 while (net_device_interface* interface = iterator.Next()) { 553 if (interface->device->index == index) { 554 if (atomic_add(&interface->ref_count, 1) != 0) 555 return interface; 556 } 557 } 558 559 return NULL; 560 } 561 562 563 /*! Finds an interface by the specified name and grabs a reference to it. 564 If the interface does not yet exist, a new one is created. 565 */ 566 struct net_device_interface* 567 get_device_interface(const char* name, bool create) 568 { 569 MutexLocker locker(sInterfaceLock); 570 571 net_device_interface* interface = find_device_interface(name); 572 if (interface != NULL) { 573 if (atomic_add(&interface->ref_count, 1) != 0) 574 return interface; 575 576 // try to recreate interface - it just got removed 577 } 578 579 if (!create) 580 return NULL; 581 582 void* cookie = open_module_list("network/devices"); 583 if (cookie == NULL) 584 return NULL; 585 586 while (true) { 587 char moduleName[B_FILE_NAME_LENGTH]; 588 size_t length = sizeof(moduleName); 589 if (read_next_module_name(cookie, moduleName, &length) != B_OK) 590 break; 591 592 TRACE(("get_device_interface: ask \"%s\" for %s\n", moduleName, name)); 593 594 net_device_module_info* module; 595 if (get_module(moduleName, (module_info**)&module) == B_OK) { 596 net_device* device; 597 status_t status = module->init_device(name, &device); 598 if (status == B_OK) { 599 interface = allocate_device_interface(device, module); 600 if (interface != NULL) 601 return interface; 602 603 module->uninit_device(device); 604 } 605 put_module(moduleName); 606 } 607 } 608 609 return NULL; 610 } 611 612 613 void 614 down_device_interface(net_device_interface* interface) 615 { 616 // Receive lock must be held when calling down_device_interface. 617 // Known callers are `interface_protocol_down' which gets 618 // here via one of the following paths: 619 // 620 // - domain_interface_control() [rx lock held, domain lock held] 621 // interface_set_down() 622 // interface_protocol_down() 623 // 624 // - domain_interface_control() [rx lock held, domain lock held] 625 // remove_interface_from_domain() 626 // delete_interface() 627 // interface_set_down() 628 629 net_device* device = interface->device; 630 631 device->flags &= ~IFF_UP; 632 device->module->down(device); 633 634 notify_device_monitors(interface, B_DEVICE_GOING_DOWN); 635 636 if (device->module->receive_data != NULL) { 637 thread_id readerThread = interface->reader_thread; 638 639 // make sure the reader thread is gone before shutting down the interface 640 status_t status; 641 wait_for_thread(readerThread, &status); 642 } 643 } 644 645 646 // #pragma mark - devices stack API 647 648 649 /*! Unregisters a previously registered deframer function. */ 650 status_t 651 unregister_device_deframer(net_device* device) 652 { 653 MutexLocker locker(sInterfaceLock); 654 655 // find device interface for this device 656 net_device_interface* interface = find_device_interface(device->name); 657 if (interface == NULL) 658 return ENODEV; 659 660 RecursiveLocker _(interface->receive_lock); 661 662 if (--interface->deframe_ref_count == 0) 663 interface->deframe_func = NULL; 664 665 return B_OK; 666 } 667 668 669 /*! Registers the deframer function for the specified \a device. 670 Note, however, that right now, you can only register one single 671 deframer function per device. 672 673 If the need arises, we might want to lift that limitation at a 674 later time (which would require a slight API change, though). 675 */ 676 status_t 677 register_device_deframer(net_device* device, net_deframe_func deframeFunc) 678 { 679 MutexLocker locker(sInterfaceLock); 680 681 // find device interface for this device 682 net_device_interface* interface = find_device_interface(device->name); 683 if (interface == NULL) 684 return ENODEV; 685 686 RecursiveLocker _(interface->receive_lock); 687 688 if (interface->deframe_func != NULL 689 && interface->deframe_func != deframeFunc) 690 return B_ERROR; 691 692 interface->deframe_func = deframeFunc; 693 interface->deframe_ref_count++; 694 return B_OK; 695 } 696 697 698 /*! Registers a domain to receive net_buffers from the specified \a device. */ 699 status_t 700 register_domain_device_handler(struct net_device* device, int32 type, 701 struct net_domain* _domain) 702 { 703 net_domain_private* domain = (net_domain_private*)_domain; 704 if (domain->module == NULL || domain->module->receive_data == NULL) 705 return B_BAD_VALUE; 706 707 return register_device_handler(device, type, &domain_receive_adapter, 708 domain); 709 } 710 711 712 /*! Registers a receiving function callback for the specified \a device. */ 713 status_t 714 register_device_handler(struct net_device* device, int32 type, 715 net_receive_func receiveFunc, void* cookie) 716 { 717 MutexLocker locker(sInterfaceLock); 718 719 // find device interface for this device 720 net_device_interface* interface = find_device_interface(device->name); 721 if (interface == NULL) 722 return ENODEV; 723 724 RecursiveLocker _(interface->receive_lock); 725 726 // see if such a handler already for this device 727 728 DeviceHandlerList::Iterator iterator 729 = interface->receive_funcs.GetIterator(); 730 while (net_device_handler* handler = iterator.Next()) { 731 if (handler->type == type) 732 return B_ERROR; 733 } 734 735 // Add new handler 736 737 net_device_handler* handler = new(std::nothrow) net_device_handler; 738 if (handler == NULL) 739 return B_NO_MEMORY; 740 741 handler->func = receiveFunc; 742 handler->type = type; 743 handler->cookie = cookie; 744 interface->receive_funcs.Add(handler); 745 return B_OK; 746 } 747 748 749 /*! Unregisters a previously registered device handler. */ 750 status_t 751 unregister_device_handler(struct net_device* device, int32 type) 752 { 753 MutexLocker locker(sInterfaceLock); 754 755 // find device interface for this device 756 net_device_interface* interface = find_device_interface(device->name); 757 if (interface == NULL) 758 return ENODEV; 759 760 RecursiveLocker _(interface->receive_lock); 761 762 // search for the handler 763 764 DeviceHandlerList::Iterator iterator 765 = interface->receive_funcs.GetIterator(); 766 while (net_device_handler* handler = iterator.Next()) { 767 if (handler->type == type) { 768 // found it 769 iterator.Remove(); 770 delete handler; 771 return B_OK; 772 } 773 } 774 775 return B_BAD_VALUE; 776 } 777 778 779 /*! Registers a device monitor for the specified device. */ 780 status_t 781 register_device_monitor(net_device* device, net_device_monitor* monitor) 782 { 783 if (monitor->receive == NULL || monitor->event == NULL) 784 return B_BAD_VALUE; 785 786 MutexLocker locker(sInterfaceLock); 787 788 // find device interface for this device 789 net_device_interface* interface = find_device_interface(device->name); 790 if (interface == NULL) 791 return ENODEV; 792 793 RecursiveLocker _(interface->receive_lock); 794 interface->monitor_funcs.Add(monitor); 795 return B_OK; 796 } 797 798 799 /*! Unregisters a previously registered device monitor. */ 800 status_t 801 unregister_device_monitor(net_device* device, net_device_monitor* monitor) 802 { 803 MutexLocker locker(sInterfaceLock); 804 805 // find device interface for this device 806 net_device_interface* interface = find_device_interface(device->name); 807 if (interface == NULL) 808 return ENODEV; 809 810 RecursiveLocker _(interface->receive_lock); 811 812 // search for the monitor 813 814 DeviceMonitorList::Iterator iterator = interface->monitor_funcs.GetIterator(); 815 while (iterator.HasNext()) { 816 if (iterator.Next() == monitor) { 817 iterator.Remove(); 818 return B_OK; 819 } 820 } 821 822 return B_BAD_VALUE; 823 } 824 825 826 /*! This function is called by device modules in case their link 827 state changed, ie. if an ethernet cable was plugged in or 828 removed. 829 */ 830 status_t 831 device_link_changed(net_device* device) 832 { 833 notify_link_changed(device); 834 return B_OK; 835 } 836 837 838 /*! This function is called by device modules once their device got 839 physically removed, ie. a USB networking card is unplugged. 840 */ 841 status_t 842 device_removed(net_device* device) 843 { 844 MutexLocker locker(sInterfaceLock); 845 846 // hold a reference to the device interface being removed 847 // so our put_() will (eventually) do the final cleanup 848 net_device_interface* interface = get_device_interface(device->name, false); 849 if (interface == NULL) 850 return ENODEV; 851 852 // Propagate the loss of the device throughout the stack. 853 // This is very complex, refer to delete_interface() for 854 // further details. 855 856 domain_removed_device_interface(interface); 857 858 notify_device_monitors(interface, B_DEVICE_BEING_REMOVED); 859 860 // By now all of the monitors must have removed themselves. If they 861 // didn't, they'll probably wait forever to be callback'ed again. 862 interface->monitor_funcs.RemoveAll(); 863 864 // All of the readers should be gone as well since we are out of 865 // interfaces and put_domain_datalink_protocols() is called for 866 // each delete_interface(). 867 868 put_device_interface(interface); 869 870 return B_OK; 871 } 872 873 874 status_t 875 device_enqueue_buffer(net_device* device, net_buffer* buffer) 876 { 877 net_device_interface* interface = get_device_interface(device->index); 878 if (interface == NULL) 879 return ENODEV; 880 881 status_t status = fifo_enqueue_buffer(&interface->receive_queue, buffer); 882 883 put_device_interface(interface); 884 return status; 885 } 886 887 888 // #pragma mark - 889 890 891 status_t 892 init_interfaces() 893 { 894 mutex_init(&sInterfaceLock, "net interfaces"); 895 896 new (&sInterfaces) DeviceInterfaceList; 897 // static C++ objects are not initialized in the module startup 898 899 #if ENABLE_DEBUGGER_COMMANDS 900 add_debugger_command("net_interface", &dump_interface, 901 "Dump the given network interface"); 902 add_debugger_command("net_device_interface", &dump_device_interface, 903 "Dump the given network device interface"); 904 add_debugger_command("net_device_interfaces", &dump_device_interfaces, 905 "Dump network device interfaces"); 906 #endif 907 return B_OK; 908 } 909 910 911 status_t 912 uninit_interfaces() 913 { 914 #if ENABLE_DEBUGGER_COMMANDS 915 remove_debugger_command("net_interface", &dump_interface); 916 remove_debugger_command("net_device_interface", &dump_device_interface); 917 remove_debugger_command("net_device_interfaces", &dump_device_interfaces); 918 #endif 919 920 mutex_destroy(&sInterfaceLock); 921 return B_OK; 922 } 923 924