1 /* 2 * Copyright 2006-2011, 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 "interfaces.h" 11 12 #include <net/if_dl.h> 13 #include <new> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <sys/sockio.h> 18 19 #include <KernelExport.h> 20 21 #include <net_device.h> 22 #include <NetUtilities.h> 23 24 #include "device_interfaces.h" 25 #include "domains.h" 26 #include "stack_private.h" 27 #include "utility.h" 28 29 30 //#define TRACE_INTERFACES 31 #ifdef TRACE_INTERFACES 32 # define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x) 33 #else 34 # define TRACE(x...) ; 35 #endif 36 37 38 struct AddressHashDefinition { 39 typedef const sockaddr* KeyType; 40 typedef InterfaceAddress ValueType; 41 42 AddressHashDefinition() 43 { 44 } 45 46 size_t HashKey(const KeyType& key) const 47 { 48 net_domain* domain = get_domain(key->sa_family); 49 if (domain == NULL) 50 return 0; 51 52 return domain->address_module->hash_address(key, false); 53 } 54 55 size_t Hash(InterfaceAddress* address) const 56 { 57 return address->domain->address_module->hash_address(address->local, 58 false); 59 } 60 61 bool Compare(const KeyType& key, InterfaceAddress* address) const 62 { 63 if (address->local == NULL) 64 return key->sa_family == AF_UNSPEC; 65 66 if (address->local->sa_family != key->sa_family) 67 return false; 68 69 return address->domain->address_module->equal_addresses(key, 70 address->local); 71 } 72 73 InterfaceAddress*& GetLink(InterfaceAddress* address) const 74 { 75 return address->HashTableLink(); 76 } 77 }; 78 79 typedef BOpenHashTable<AddressHashDefinition, true, false> AddressTable; 80 81 82 static recursive_lock sLock; 83 static InterfaceList sInterfaces; 84 static mutex sHashLock; 85 static AddressTable sAddressTable; 86 static uint32 sInterfaceIndex; 87 88 89 #if 0 90 //! For debugging purposes only 91 void 92 dump_interface_refs(void) 93 { 94 RecursiveLocker locker(sLock); 95 96 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 97 while (Interface* interface = iterator.Next()) { 98 dprintf("%p: %s, %ld\n", interface, interface->name, 99 interface->CountReferences()); 100 } 101 } 102 #endif 103 104 105 #if ENABLE_DEBUGGER_COMMANDS 106 107 108 static int 109 dump_interface(int argc, char** argv) 110 { 111 if (argc != 2) { 112 kprintf("usage: %s [name|address]\n", argv[0]); 113 return 0; 114 } 115 116 Interface* interface = NULL; 117 118 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 119 while ((interface = iterator.Next()) != NULL) { 120 if (!strcmp(argv[1], interface->name)) 121 break; 122 } 123 124 if (interface == NULL) 125 interface = (Interface*)parse_expression(argv[1]); 126 127 interface->Dump(); 128 129 return 0; 130 } 131 132 133 static int 134 dump_interfaces(int argc, char** argv) 135 { 136 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 137 while (Interface* interface = iterator.Next()) { 138 kprintf("%p %s\n", interface, interface->name); 139 } 140 return 0; 141 } 142 143 144 static int 145 dump_local(int argc, char** argv) 146 { 147 AddressTable::Iterator iterator = sAddressTable.GetIterator(); 148 size_t i = 0; 149 while (InterfaceAddress* address = iterator.Next()) { 150 address->Dump(++i); 151 dprintf(" hash: %" B_PRIu32 "\n", 152 address->domain->address_module->hash_address(address->local, 153 false)); 154 } 155 return 0; 156 } 157 158 159 static int 160 dump_route(int argc, char** argv) 161 { 162 if (argc != 2) { 163 kprintf("usage: %s [address]\n", argv[0]); 164 return 0; 165 } 166 167 net_route* route = (net_route*)parse_expression(argv[1]); 168 kprintf("destination: %p\n", route->destination); 169 kprintf("mask: %p\n", route->mask); 170 kprintf("gateway: %p\n", route->gateway); 171 kprintf("flags: %" B_PRIx32 "\n", route->flags); 172 kprintf("mtu: %" B_PRIu32 "\n", route->mtu); 173 kprintf("interface address: %p\n", route->interface_address); 174 175 if (route->interface_address != NULL) { 176 ((InterfaceAddress*)route->interface_address)->Dump(); 177 } 178 179 return 0; 180 } 181 182 183 #endif // ENABLE_DEBUGGER_COMMANDS 184 185 186 InterfaceAddress::InterfaceAddress() 187 { 188 _Init(NULL, NULL); 189 } 190 191 192 InterfaceAddress::InterfaceAddress(net_interface* netInterface, 193 net_domain* netDomain) 194 { 195 _Init(netInterface, netDomain); 196 } 197 198 199 InterfaceAddress::~InterfaceAddress() 200 { 201 TRACE("InterfaceAddress %p: destructor\n", this); 202 203 if (interface != NULL && (flags & IFAF_DIRECT_ADDRESS) == 0) 204 ((Interface*)interface)->ReleaseReference(); 205 } 206 207 208 status_t 209 InterfaceAddress::SetTo(const ifaliasreq& request) 210 { 211 status_t status = SetLocal((const sockaddr*)&request.ifra_addr); 212 if (status == B_OK) 213 status = SetDestination((const sockaddr*)&request.ifra_broadaddr); 214 if (status == B_OK) 215 status = SetMask((const sockaddr*)&request.ifra_mask); 216 217 return status; 218 } 219 220 221 status_t 222 InterfaceAddress::SetLocal(const sockaddr* to) 223 { 224 return Set(&local, to); 225 } 226 227 228 status_t 229 InterfaceAddress::SetDestination(const sockaddr* to) 230 { 231 return Set(&destination, to); 232 } 233 234 235 status_t 236 InterfaceAddress::SetMask(const sockaddr* to) 237 { 238 return Set(&mask, to); 239 } 240 241 242 sockaddr** 243 InterfaceAddress::AddressFor(int32 option) 244 { 245 switch (option) { 246 case SIOCSIFADDR: 247 case SIOCGIFADDR: 248 case SIOCDIFADDR: 249 return &local; 250 251 case SIOCSIFNETMASK: 252 case SIOCGIFNETMASK: 253 return &mask; 254 255 case SIOCSIFBRDADDR: 256 case SIOCSIFDSTADDR: 257 case SIOCGIFBRDADDR: 258 case SIOCGIFDSTADDR: 259 return &destination; 260 261 default: 262 return NULL; 263 } 264 } 265 266 267 /*! Adds the default routes that every interface address needs, ie. the local 268 host route, and one for the subnet (if set). 269 */ 270 void 271 InterfaceAddress::AddDefaultRoutes(int32 option) 272 { 273 net_route route; 274 route.destination = local; 275 route.gateway = NULL; 276 route.interface_address = this; 277 278 if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) { 279 route.mask = mask; 280 route.flags = 0; 281 add_route(domain, &route); 282 } 283 284 if (option == SIOCSIFADDR) { 285 route.mask = NULL; 286 route.flags = RTF_LOCAL | RTF_HOST; 287 add_route(domain, &route); 288 } 289 } 290 291 292 /*! Removes the default routes as set by AddDefaultRoutes() again. */ 293 void 294 InterfaceAddress::RemoveDefaultRoutes(int32 option) 295 { 296 net_route route; 297 route.destination = local; 298 route.gateway = NULL; 299 route.interface_address = this; 300 301 if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) { 302 route.mask = mask; 303 route.flags = 0; 304 remove_route(domain, &route); 305 } 306 307 if (option == SIOCSIFADDR) { 308 route.mask = NULL; 309 route.flags = RTF_LOCAL | RTF_HOST; 310 remove_route(domain, &route); 311 } 312 } 313 314 315 bool 316 InterfaceAddress::LocalIsDefined() const 317 { 318 return local != NULL && local->sa_family != AF_UNSPEC; 319 } 320 321 322 #if ENABLE_DEBUGGER_COMMANDS 323 324 325 void 326 InterfaceAddress::Dump(size_t index, bool hideInterface) 327 { 328 if (index) 329 kprintf("%2zu. ", index); 330 else 331 kprintf(" "); 332 333 if (!hideInterface) { 334 kprintf("interface: %p (%s)\n ", interface, 335 interface != NULL ? interface->name : "-"); 336 } 337 338 kprintf("domain: %p (family %u)\n", domain, 339 domain != NULL ? domain->family : AF_UNSPEC); 340 341 char buffer[64]; 342 if (local != NULL && domain != NULL) { 343 domain->address_module->print_address_buffer(local, buffer, 344 sizeof(buffer), false); 345 } else 346 strcpy(buffer, "-"); 347 kprintf(" local: %s\n", buffer); 348 349 if (mask != NULL && domain != NULL) { 350 domain->address_module->print_address_buffer(mask, buffer, 351 sizeof(buffer), false); 352 } else 353 strcpy(buffer, "-"); 354 kprintf(" mask: %s\n", buffer); 355 356 if (destination != NULL && domain != NULL) { 357 domain->address_module->print_address_buffer(destination, buffer, 358 sizeof(buffer), false); 359 } else 360 strcpy(buffer, "-"); 361 kprintf(" destination: %s\n", buffer); 362 363 kprintf(" ref count: %" B_PRId32 "\n", CountReferences()); 364 } 365 366 367 #endif // ENABLE_DEBUGGER_COMMANDS 368 369 370 /*static*/ status_t 371 InterfaceAddress::Set(sockaddr** _address, const sockaddr* to) 372 { 373 sockaddr* address = *_address; 374 375 if (to == NULL || to->sa_family == AF_UNSPEC) { 376 // Clear address 377 free(address); 378 *_address = NULL; 379 return B_OK; 380 } 381 382 // Set address 383 384 size_t size = max_c(to->sa_len, sizeof(sockaddr)); 385 if (size > sizeof(sockaddr_storage)) 386 size = sizeof(sockaddr_storage); 387 388 address = Prepare(_address, size); 389 if (address == NULL) 390 return B_NO_MEMORY; 391 392 memcpy(address, to, size); 393 address->sa_len = size; 394 395 return B_OK; 396 } 397 398 399 /*! Makes sure that the sockaddr object pointed to by \a _address is large 400 enough to hold \a size bytes. 401 \a _address may point to NULL when calling this method. 402 */ 403 /*static*/ sockaddr* 404 InterfaceAddress::Prepare(sockaddr** _address, size_t size) 405 { 406 size = max_c(size, sizeof(sockaddr)); 407 if (size > sizeof(sockaddr_storage)) 408 size = sizeof(sockaddr_storage); 409 410 sockaddr* address = *_address; 411 412 if (address == NULL || size > address->sa_len) { 413 address = (sockaddr*)realloc(address, size); 414 if (address == NULL) 415 return NULL; 416 } 417 418 address->sa_len = size; 419 420 *_address = address; 421 return address; 422 } 423 424 425 void 426 InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain) 427 { 428 TRACE("InterfaceAddress %p: init interface %p, domain %p\n", this, 429 netInterface, netDomain); 430 431 interface = netInterface; 432 domain = netDomain; 433 local = NULL; 434 destination = NULL; 435 mask = NULL; 436 flags = 0; 437 438 if (interface != NULL) 439 ((Interface*)interface)->AcquireReference(); 440 } 441 442 443 // #pragma mark - 444 445 446 Interface::Interface(const char* interfaceName, 447 net_device_interface* deviceInterface) 448 { 449 TRACE("Interface %p: new \"%s\", device interface %p\n", this, 450 interfaceName, deviceInterface); 451 452 int written = strlcpy(name, interfaceName, IF_NAMESIZE); 453 memset(name + written, 0, IF_NAMESIZE - written); 454 // Clear remaining space 455 456 device = deviceInterface->device; 457 458 index = ++sInterfaceIndex; 459 flags = 0; 460 type = 0; 461 mtu = deviceInterface->device->mtu; 462 metric = 0; 463 464 fDeviceInterface = acquire_device_interface(deviceInterface); 465 466 recursive_lock_init(&fLock, name); 467 468 // Grab a reference to the networking stack, to make sure it won't be 469 // unloaded as long as an interface exists 470 module_info* module; 471 get_module(gNetStackInterfaceModule.info.name, &module); 472 } 473 474 475 Interface::~Interface() 476 { 477 TRACE("Interface %p: destructor\n", this); 478 479 put_device_interface(fDeviceInterface); 480 481 // Uninitialize the domain datalink protocols 482 483 DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 484 while (domain_datalink* datalink = iterator.Next()) { 485 put_domain_datalink_protocols(this, datalink->domain); 486 } 487 488 // Free domain datalink objects 489 490 domain_datalink* next = fDatalinkTable.Clear(true); 491 while (next != NULL) { 492 domain_datalink* datalink = next; 493 next = next->hash_link; 494 495 delete datalink; 496 } 497 498 recursive_lock_destroy(&fLock); 499 500 // Release reference of the stack - at this point, our stack may be unloaded 501 // if no other interfaces or sockets are left 502 put_module(gNetStackInterfaceModule.info.name); 503 } 504 505 506 /*! Returns a reference to the first InterfaceAddress that is from the same 507 as the specified \a family. 508 */ 509 InterfaceAddress* 510 Interface::FirstForFamily(int family) 511 { 512 RecursiveLocker locker(fLock); 513 514 InterfaceAddress* address = _FirstForFamily(family); 515 if (address != NULL) { 516 address->AcquireReference(); 517 return address; 518 } 519 520 return NULL; 521 } 522 523 524 /*! Returns a reference to the first unconfigured address of this interface 525 for the specified \a family. 526 */ 527 InterfaceAddress* 528 Interface::FirstUnconfiguredForFamily(int family) 529 { 530 RecursiveLocker locker(fLock); 531 532 AddressList::Iterator iterator = fAddresses.GetIterator(); 533 while (InterfaceAddress* address = iterator.Next()) { 534 if (address->domain->family == family 535 && (address->local == NULL 536 // TODO: this has to be solved differently!! 537 || (flags & IFF_CONFIGURING) != 0)) { 538 address->AcquireReference(); 539 return address; 540 } 541 } 542 543 return NULL; 544 } 545 546 547 /*! Returns a reference to the InterfaceAddress that has the specified 548 \a destination address. 549 */ 550 InterfaceAddress* 551 Interface::AddressForDestination(net_domain* domain, 552 const sockaddr* destination) 553 { 554 RecursiveLocker locker(fLock); 555 556 if ((device->flags & IFF_BROADCAST) == 0) { 557 // The device does not support broadcasting 558 return NULL; 559 } 560 561 AddressList::Iterator iterator = fAddresses.GetIterator(); 562 while (InterfaceAddress* address = iterator.Next()) { 563 if (address->domain == domain 564 && address->destination != NULL 565 && domain->address_module->equal_addresses(address->destination, 566 destination)) { 567 address->AcquireReference(); 568 return address; 569 } 570 } 571 572 return NULL; 573 } 574 575 576 /*! Returns a reference to the InterfaceAddress that has the specified 577 \a local address. 578 */ 579 InterfaceAddress* 580 Interface::AddressForLocal(net_domain* domain, const sockaddr* local) 581 { 582 RecursiveLocker locker(fLock); 583 584 AddressList::Iterator iterator = fAddresses.GetIterator(); 585 while (InterfaceAddress* address = iterator.Next()) { 586 if (address->domain == domain 587 && address->local != NULL 588 && domain->address_module->equal_addresses(address->local, local)) { 589 address->AcquireReference(); 590 return address; 591 } 592 } 593 594 return NULL; 595 } 596 597 598 status_t 599 Interface::AddAddress(InterfaceAddress* address) 600 { 601 net_domain* domain = address->domain; 602 if (domain == NULL) 603 return B_BAD_VALUE; 604 605 RecursiveLocker locker(fLock); 606 fAddresses.Add(address); 607 locker.Unlock(); 608 609 if (address->LocalIsDefined()) { 610 MutexLocker hashLocker(sHashLock); 611 sAddressTable.Insert(address); 612 } 613 return B_OK; 614 } 615 616 617 void 618 Interface::RemoveAddress(InterfaceAddress* address) 619 { 620 net_domain* domain = address->domain; 621 if (domain == NULL) 622 return; 623 624 RecursiveLocker locker(fLock); 625 626 fAddresses.Remove(address); 627 address->GetDoublyLinkedListLink()->next = NULL; 628 629 locker.Unlock(); 630 631 if (address->LocalIsDefined()) { 632 MutexLocker hashLocker(sHashLock); 633 sAddressTable.Remove(address); 634 } 635 } 636 637 638 bool 639 Interface::GetNextAddress(InterfaceAddress** _address) 640 { 641 RecursiveLocker locker(fLock); 642 643 InterfaceAddress* address = *_address; 644 if (address == NULL) { 645 // get first address 646 address = fAddresses.First(); 647 } else { 648 // get next, if possible 649 InterfaceAddress* next = fAddresses.GetNext(address); 650 address->ReleaseReference(); 651 address = next; 652 } 653 654 *_address = address; 655 656 if (address == NULL) 657 return false; 658 659 address->AcquireReference(); 660 return true; 661 } 662 663 664 InterfaceAddress* 665 Interface::AddressAt(size_t index) 666 { 667 RecursiveLocker locker(fLock); 668 669 AddressList::Iterator iterator = fAddresses.GetIterator(); 670 size_t i = 0; 671 672 while (InterfaceAddress* address = iterator.Next()) { 673 if (i++ == index) { 674 address->AcquireReference(); 675 return address; 676 } 677 } 678 679 return NULL; 680 } 681 682 683 int32 684 Interface::IndexOfAddress(InterfaceAddress* address) 685 { 686 if (address == NULL) 687 return -1; 688 689 RecursiveLocker locker(fLock); 690 691 AddressList::Iterator iterator = fAddresses.GetIterator(); 692 int32 index = 0; 693 694 while (iterator.HasNext()) { 695 if (address == iterator.Next()) 696 return index; 697 698 index++; 699 } 700 701 return -1; 702 } 703 704 705 size_t 706 Interface::CountAddresses() 707 { 708 RecursiveLocker locker(fLock); 709 return fAddresses.Count(); 710 } 711 712 713 void 714 Interface::RemoveAddresses() 715 { 716 RecursiveLocker locker(fLock); 717 718 while (InterfaceAddress* address = fAddresses.RemoveHead()) { 719 locker.Unlock(); 720 721 if (address->LocalIsDefined()) { 722 MutexLocker hashLocker(sHashLock); 723 sAddressTable.Remove(address); 724 } 725 address->ReleaseReference(); 726 727 locker.Lock(); 728 } 729 } 730 731 732 /*! This is called in order to call the correct methods of the datalink 733 protocols, ie. it will translate address changes to 734 net_datalink_protocol::change_address(), and IFF_UP changes to 735 net_datalink_protocol::interface_up(), and interface_down(). 736 737 Everything else is passed unchanged to net_datalink_protocol::control(). 738 */ 739 status_t 740 Interface::Control(net_domain* domain, int32 option, ifreq& request, 741 ifreq* userRequest, size_t length) 742 { 743 switch (option) { 744 case SIOCSIFFLAGS: 745 { 746 if (length != sizeof(ifreq)) 747 return B_BAD_VALUE; 748 749 uint32 requestFlags = request.ifr_flags; 750 uint32 oldFlags = flags; 751 status_t status = B_OK; 752 753 request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST); 754 755 if ((requestFlags & IFF_UP) != (flags & IFF_UP)) { 756 if ((requestFlags & IFF_UP) != 0) 757 status = _SetUp(); 758 else 759 SetDown(); 760 } 761 762 if (status == B_OK) { 763 // TODO: maybe allow deleting IFF_BROADCAST on the interface 764 // level? 765 flags &= IFF_UP | IFF_LINK | IFF_BROADCAST; 766 flags |= request.ifr_flags; 767 } 768 769 if (oldFlags != flags) { 770 TRACE("Interface %p: flags changed from %" B_PRIx32 " to %" 771 B_PRIx32 "\n", this, oldFlags, flags); 772 notify_interface_changed(this, oldFlags, flags); 773 } 774 775 return status; 776 } 777 778 case B_SOCKET_SET_ALIAS: 779 { 780 if (length != sizeof(ifaliasreq)) 781 return B_BAD_VALUE; 782 783 RecursiveLocker locker(fLock); 784 785 ifaliasreq aliasRequest; 786 if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq)) 787 != B_OK) 788 return B_BAD_ADDRESS; 789 790 InterfaceAddress* address = NULL; 791 if (aliasRequest.ifra_index < 0) { 792 if (!domain->address_module->is_empty_address( 793 (const sockaddr*)&aliasRequest.ifra_addr, false)) { 794 // Find first address that matches the local address 795 address = AddressForLocal(domain, 796 (const sockaddr*)&aliasRequest.ifra_addr); 797 } 798 if (address == NULL) { 799 // Find first address for family 800 address = FirstForFamily(domain->family); 801 } 802 if (address == NULL) { 803 // Create new on the fly 804 address = new(std::nothrow) InterfaceAddress(this, domain); 805 if (address == NULL) 806 return B_NO_MEMORY; 807 808 status_t status = AddAddress(address); 809 if (status != B_OK) { 810 delete address; 811 return status; 812 } 813 814 // Note, even if setting the address failed, the empty 815 // address added here will still be added to the interface. 816 address->AcquireReference(); 817 } 818 } else 819 address = AddressAt(aliasRequest.ifra_index); 820 821 if (address == NULL) 822 return B_BAD_VALUE; 823 824 status_t status = B_OK; 825 826 if (!domain->address_module->equal_addresses( 827 (sockaddr*)&aliasRequest.ifra_addr, address->local)) { 828 status = _ChangeAddress(locker, address, SIOCSIFADDR, 829 address->local, (sockaddr*)&aliasRequest.ifra_addr); 830 } 831 832 if (status == B_OK && !domain->address_module->equal_addresses( 833 (sockaddr*)&aliasRequest.ifra_mask, address->mask) 834 && !domain->address_module->is_empty_address( 835 (sockaddr*)&aliasRequest.ifra_mask, false)) { 836 status = _ChangeAddress(locker, address, SIOCSIFNETMASK, 837 address->mask, (sockaddr*)&aliasRequest.ifra_mask); 838 } 839 840 if (status == B_OK && !domain->address_module->equal_addresses( 841 (sockaddr*)&aliasRequest.ifra_destination, 842 address->destination) 843 && !domain->address_module->is_empty_address( 844 (sockaddr*)&aliasRequest.ifra_destination, false)) { 845 status = _ChangeAddress(locker, address, 846 (domain->address_module->flags 847 & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0 848 ? SIOCSIFBRDADDR : SIOCSIFDSTADDR, 849 address->destination, 850 (sockaddr*)&aliasRequest.ifra_destination); 851 } 852 853 address->ReleaseReference(); 854 return status; 855 } 856 857 case SIOCSIFADDR: 858 case SIOCSIFNETMASK: 859 case SIOCSIFBRDADDR: 860 case SIOCSIFDSTADDR: 861 case SIOCDIFADDR: 862 { 863 if (length != sizeof(ifreq)) 864 return B_BAD_VALUE; 865 866 RecursiveLocker locker(fLock); 867 868 InterfaceAddress* address = NULL; 869 sockaddr_storage newAddress; 870 871 size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr)); 872 if (size > sizeof(sockaddr_storage)) 873 size = sizeof(sockaddr_storage); 874 875 if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK) 876 return B_BAD_ADDRESS; 877 878 if (option == SIOCDIFADDR) { 879 // Find referring address - we can't use the hash, as another 880 // interface might use the same address. 881 AddressList::Iterator iterator = fAddresses.GetIterator(); 882 while ((address = iterator.Next()) != NULL) { 883 if (address->domain == domain 884 && domain->address_module->equal_addresses( 885 address->local, (sockaddr*)&newAddress)) 886 break; 887 } 888 889 if (address == NULL) 890 return B_BAD_VALUE; 891 } else { 892 // Just use the first address for this family 893 address = _FirstForFamily(domain->family); 894 if (address == NULL) { 895 // Create new on the fly 896 address = new(std::nothrow) InterfaceAddress(this, domain); 897 if (address == NULL) 898 return B_NO_MEMORY; 899 900 status_t status = AddAddress(address); 901 if (status != B_OK) { 902 delete address; 903 return status; 904 } 905 906 // Note, even if setting the address failed, the empty 907 // address added here will still be added to the interface. 908 } 909 } 910 911 return _ChangeAddress(locker, address, option, 912 *address->AddressFor(option), 913 option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL); 914 } 915 916 default: 917 // pass the request into the datalink protocol stack 918 domain_datalink* datalink = DomainDatalink(domain->family); 919 if (datalink->first_info != NULL) { 920 return datalink->first_info->control( 921 datalink->first_protocol, option, userRequest, length); 922 } 923 break; 924 } 925 926 return B_BAD_VALUE; 927 } 928 929 930 void 931 Interface::SetDown() 932 { 933 if ((flags & IFF_UP) == 0) 934 return; 935 936 // TODO: We acquire also the net_interfaces lock here 937 // to avoid a lock inversion in the ipv6 protocol implementation 938 // (see ticket #9377). 939 // A better solution would be to avoid locking the interface lock (fLock) 940 // when calling the lower layers. 941 RecursiveLocker interfacesLocker(sLock); 942 RecursiveLocker locker(fLock); 943 944 DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 945 while (domain_datalink* datalink = iterator.Next()) { 946 datalink->first_info->interface_down(datalink->first_protocol); 947 } 948 949 flags &= ~IFF_UP; 950 } 951 952 953 /*! Called when a device lost its IFF_UP status. We will invalidate all 954 interface routes here. 955 */ 956 void 957 Interface::WentDown() 958 { 959 TRACE("Interface %p: went down\n", this); 960 961 RecursiveLocker locker(fLock); 962 963 AddressList::Iterator iterator = fAddresses.GetIterator(); 964 while (InterfaceAddress* address = iterator.Next()) { 965 if (address->domain != NULL) 966 invalidate_routes(address->domain, this); 967 } 968 } 969 970 971 status_t 972 Interface::CreateDomainDatalinkIfNeeded(net_domain* domain) 973 { 974 RecursiveLocker locker(fLock); 975 976 if (fDatalinkTable.Lookup(domain->family) != NULL) 977 return B_OK; 978 979 TRACE("Interface %p: create domain datalink for domain %p\n", this, domain); 980 981 domain_datalink* datalink = new(std::nothrow) domain_datalink; 982 if (datalink == NULL) 983 return B_NO_MEMORY; 984 985 datalink->first_protocol = NULL; 986 datalink->first_info = NULL; 987 datalink->domain = domain; 988 989 // setup direct route for bound devices 990 datalink->direct_route.destination = NULL; 991 datalink->direct_route.mask = NULL; 992 datalink->direct_route.gateway = NULL; 993 datalink->direct_route.flags = 0; 994 datalink->direct_route.mtu = 0; 995 datalink->direct_route.interface_address = &datalink->direct_address; 996 datalink->direct_route.ref_count = 1; 997 // make sure this doesn't get deleted accidently 998 999 // provide its link back to the interface 1000 datalink->direct_address.local = NULL; 1001 datalink->direct_address.destination = NULL; 1002 datalink->direct_address.mask = NULL; 1003 datalink->direct_address.domain = domain; 1004 datalink->direct_address.interface = this; 1005 datalink->direct_address.flags = IFAF_DIRECT_ADDRESS; 1006 1007 fDatalinkTable.Insert(datalink); 1008 1009 status_t status = get_domain_datalink_protocols(this, domain); 1010 if (status == B_OK) 1011 return B_OK; 1012 1013 fDatalinkTable.Remove(datalink); 1014 delete datalink; 1015 1016 return status; 1017 } 1018 1019 1020 domain_datalink* 1021 Interface::DomainDatalink(uint8 family) 1022 { 1023 // Note: domain datalinks cannot be removed while the interface is alive, 1024 // since this would require us either to hold the lock while calling this 1025 // function, or introduce reference counting for the domain_datalink 1026 // structure. 1027 RecursiveLocker locker(fLock); 1028 return fDatalinkTable.Lookup(family); 1029 } 1030 1031 1032 #if ENABLE_DEBUGGER_COMMANDS 1033 1034 1035 void 1036 Interface::Dump() const 1037 { 1038 kprintf("name: %s\n", name); 1039 kprintf("device: %p\n", device); 1040 kprintf("device_interface: %p\n", fDeviceInterface); 1041 kprintf("index: %" B_PRIu32 "\n", index); 1042 kprintf("flags: %#" B_PRIx32 "\n", flags); 1043 kprintf("type: %u\n", type); 1044 kprintf("mtu: %" B_PRIu32 "\n", mtu); 1045 kprintf("metric: %" B_PRIu32 "\n", metric); 1046 kprintf("ref count: %" B_PRId32 "\n", CountReferences()); 1047 1048 kprintf("datalink protocols:\n"); 1049 1050 DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator(); 1051 size_t i = 0; 1052 while (domain_datalink* datalink = datalinkIterator.Next()) { 1053 kprintf("%2zu. domain: %p\n", ++i, datalink->domain); 1054 kprintf(" first_protocol: %p\n", datalink->first_protocol); 1055 kprintf(" first_info: %p\n", datalink->first_info); 1056 kprintf(" direct_route: %p\n", &datalink->direct_route); 1057 } 1058 1059 kprintf("addresses:\n"); 1060 1061 AddressList::ConstIterator iterator = fAddresses.GetIterator(); 1062 i = 0; 1063 while (InterfaceAddress* address = iterator.Next()) { 1064 address->Dump(++i, true); 1065 } 1066 } 1067 1068 1069 #endif // ENABLE_DEBUGGER_COMMANDS 1070 1071 1072 status_t 1073 Interface::_SetUp() 1074 { 1075 status_t status = up_device_interface(fDeviceInterface); 1076 if (status != B_OK) 1077 return status; 1078 1079 // Propagate flag to all datalink protocols 1080 1081 RecursiveLocker locker(fLock); 1082 1083 DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 1084 while (domain_datalink* datalink = iterator.Next()) { 1085 status = datalink->first_info->interface_up(datalink->first_protocol); 1086 if (status != B_OK) { 1087 // Revert "up" status 1088 DatalinkTable::Iterator secondIterator 1089 = fDatalinkTable.GetIterator(); 1090 while (secondIterator.HasNext()) { 1091 domain_datalink* secondDatalink = secondIterator.Next(); 1092 if (secondDatalink == NULL || secondDatalink == datalink) 1093 break; 1094 1095 secondDatalink->first_info->interface_down( 1096 secondDatalink->first_protocol); 1097 } 1098 1099 down_device_interface(fDeviceInterface); 1100 return status; 1101 } 1102 } 1103 1104 // Add default routes for the existing addresses 1105 1106 AddressList::Iterator addressIterator = fAddresses.GetIterator(); 1107 while (InterfaceAddress* address = addressIterator.Next()) { 1108 address->AddDefaultRoutes(SIOCSIFADDR); 1109 } 1110 1111 flags |= IFF_UP; 1112 return B_OK; 1113 } 1114 1115 1116 InterfaceAddress* 1117 Interface::_FirstForFamily(int family) 1118 { 1119 ASSERT_LOCKED_RECURSIVE(&fLock); 1120 1121 AddressList::Iterator iterator = fAddresses.GetIterator(); 1122 while (InterfaceAddress* address = iterator.Next()) { 1123 if (address->domain != NULL && address->domain->family == family) 1124 return address; 1125 } 1126 1127 return NULL; 1128 } 1129 1130 1131 status_t 1132 Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address, 1133 int32 option, const sockaddr* originalAddress, 1134 const sockaddr* requestedAddress) 1135 { 1136 // Copy old address 1137 sockaddr_storage oldAddress; 1138 if (address->domain->address_module->set_to((sockaddr*)&oldAddress, 1139 originalAddress) != B_OK) 1140 oldAddress.ss_family = AF_UNSPEC; 1141 1142 // Copy new address (this also makes sure that sockaddr::sa_len is set 1143 // correctly) 1144 sockaddr_storage newAddress; 1145 if (address->domain->address_module->set_to((sockaddr*)&newAddress, 1146 requestedAddress) != B_OK) 1147 newAddress.ss_family = AF_UNSPEC; 1148 1149 // Test if anything changed for real 1150 if (address->domain->address_module->equal_addresses( 1151 (sockaddr*)&oldAddress, (sockaddr*)&newAddress)) { 1152 // Nothing to do 1153 TRACE(" option %" B_PRId32 " addresses are equal!\n", option); 1154 return B_OK; 1155 } 1156 1157 // TODO: mark this address busy or call while holding the lock! 1158 address->AcquireReference(); 1159 locker.Unlock(); 1160 1161 domain_datalink* datalink = DomainDatalink(address->domain); 1162 status_t status = datalink->first_protocol->module->change_address( 1163 datalink->first_protocol, address, option, 1164 oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL, 1165 newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL); 1166 1167 locker.Lock(); 1168 address->ReleaseReference(); 1169 return status; 1170 } 1171 1172 1173 // #pragma mark - 1174 1175 1176 /*! Searches for a specific interface by name. 1177 You need to have the interface list's lock hold when calling this function. 1178 */ 1179 static struct Interface* 1180 find_interface(const char* name) 1181 { 1182 ASSERT_LOCKED_RECURSIVE(&sLock); 1183 1184 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1185 while (Interface* interface = iterator.Next()) { 1186 if (!strcmp(interface->name, name)) 1187 return interface; 1188 } 1189 1190 return NULL; 1191 } 1192 1193 1194 /*! Searches for a specific interface by index. 1195 You need to have the interface list's lock hold when calling this function. 1196 */ 1197 static struct Interface* 1198 find_interface(uint32 index) 1199 { 1200 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1201 while (Interface* interface = iterator.Next()) { 1202 if (interface->index == index) 1203 return interface; 1204 } 1205 1206 return NULL; 1207 } 1208 1209 1210 // #pragma mark - 1211 1212 1213 status_t 1214 add_interface(const char* name, net_domain_private* domain, 1215 const ifaliasreq& request, net_device_interface* deviceInterface) 1216 { 1217 RecursiveLocker locker(sLock); 1218 1219 if (find_interface(name) != NULL) 1220 return B_NAME_IN_USE; 1221 1222 Interface* interface 1223 = new(std::nothrow) Interface(name, deviceInterface); 1224 if (interface == NULL) 1225 return B_NO_MEMORY; 1226 1227 sInterfaces.Add(interface); 1228 interface->AcquireReference(); 1229 // We need another reference to be able to use the interface without 1230 // holding sLock. 1231 1232 locker.Unlock(); 1233 1234 status_t status = add_interface_address(interface, domain, request); 1235 if (status == B_OK) 1236 notify_interface_added(interface); 1237 else { 1238 locker.Lock(); 1239 sInterfaces.Remove(interface); 1240 locker.Unlock(); 1241 interface->ReleaseReference(); 1242 } 1243 1244 interface->ReleaseReference(); 1245 1246 return status; 1247 } 1248 1249 1250 /*! Removes the interface from the list, and puts the stack's reference to it. 1251 */ 1252 void 1253 remove_interface(Interface* interface) 1254 { 1255 interface->SetDown(); 1256 interface->RemoveAddresses(); 1257 1258 RecursiveLocker locker(sLock); 1259 sInterfaces.Remove(interface); 1260 locker.Unlock(); 1261 1262 notify_interface_removed(interface); 1263 1264 interface->ReleaseReference(); 1265 } 1266 1267 1268 /*! This is called whenever a device interface is being removed. We will get 1269 the corresponding Interface, and remove it. 1270 */ 1271 void 1272 interface_removed_device_interface(net_device_interface* deviceInterface) 1273 { 1274 RecursiveLocker locker(sLock); 1275 1276 Interface* interface = find_interface(deviceInterface->device->name); 1277 if (interface != NULL) 1278 remove_interface(interface); 1279 } 1280 1281 1282 status_t 1283 add_interface_address(Interface* interface, net_domain_private* domain, 1284 const ifaliasreq& request) 1285 { 1286 // Make sure the family of the provided addresses is valid 1287 if ((request.ifra_addr.ss_family != domain->family 1288 && request.ifra_addr.ss_family != AF_UNSPEC) 1289 || (request.ifra_mask.ss_family != domain->family 1290 && request.ifra_mask.ss_family != AF_UNSPEC) 1291 || (request.ifra_broadaddr.ss_family != domain->family 1292 && request.ifra_broadaddr.ss_family != AF_UNSPEC)) 1293 return B_BAD_VALUE; 1294 1295 RecursiveLocker locker(interface->Lock()); 1296 1297 InterfaceAddress* address 1298 = new(std::nothrow) InterfaceAddress(interface, domain); 1299 if (address == NULL) 1300 return B_NO_MEMORY; 1301 1302 status_t status = address->SetTo(request); 1303 if (status == B_OK) 1304 status = interface->CreateDomainDatalinkIfNeeded(domain); 1305 if (status == B_OK) 1306 status = interface->AddAddress(address); 1307 1308 if (status == B_OK && address->local != NULL) { 1309 // update the datalink protocols 1310 domain_datalink* datalink = interface->DomainDatalink(domain->family); 1311 1312 status = datalink->first_protocol->module->change_address( 1313 datalink->first_protocol, address, SIOCAIFADDR, NULL, 1314 address->local); 1315 if (status != B_OK) 1316 interface->RemoveAddress(address); 1317 } 1318 if (status == B_OK) 1319 notify_interface_changed(interface); 1320 else 1321 delete address; 1322 1323 return status; 1324 } 1325 1326 1327 status_t 1328 update_interface_address(InterfaceAddress* interfaceAddress, int32 option, 1329 const sockaddr* oldAddress, const sockaddr* newAddress) 1330 { 1331 TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress " 1332 "%s)\n", __FUNCTION__, interfaceAddress, option, 1333 AddressString(interfaceAddress->domain, oldAddress).Data(), 1334 AddressString(interfaceAddress->domain, newAddress).Data()); 1335 1336 MutexLocker locker(sHashLock); 1337 1338 // set logical interface address 1339 sockaddr** _address = interfaceAddress->AddressFor(option); 1340 if (_address == NULL) 1341 return B_BAD_VALUE; 1342 1343 Interface* interface = (Interface*)interfaceAddress->interface; 1344 1345 interfaceAddress->RemoveDefaultRoutes(option); 1346 1347 if (option == SIOCDIFADDR) { 1348 // Remove address, and release its reference (causing our caller to 1349 // delete it) 1350 locker.Unlock(); 1351 1352 invalidate_routes(interfaceAddress); 1353 1354 interface->RemoveAddress(interfaceAddress); 1355 interfaceAddress->ReleaseReference(); 1356 return B_OK; 1357 } 1358 1359 if (interfaceAddress->LocalIsDefined()) 1360 sAddressTable.Remove(interfaceAddress); 1361 1362 // Copy new address over 1363 status_t status = InterfaceAddress::Set(_address, newAddress); 1364 if (status == B_OK) { 1365 sockaddr* address = *_address; 1366 1367 if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) { 1368 // Reset netmask and broadcast addresses to defaults 1369 net_domain* domain = interfaceAddress->domain; 1370 sockaddr* defaultNetmask = NULL; 1371 const sockaddr* netmask = NULL; 1372 if (option == SIOCSIFADDR) { 1373 defaultNetmask = InterfaceAddress::Prepare( 1374 &interfaceAddress->mask, address->sa_len); 1375 } else 1376 netmask = newAddress; 1377 1378 // Reset the broadcast address if the address family has 1379 // such 1380 sockaddr* defaultBroadcast = NULL; 1381 if ((domain->address_module->flags 1382 & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) { 1383 defaultBroadcast = InterfaceAddress::Prepare( 1384 &interfaceAddress->destination, address->sa_len); 1385 } else 1386 InterfaceAddress::Set(&interfaceAddress->destination, NULL); 1387 1388 domain->address_module->set_to_defaults(defaultNetmask, 1389 defaultBroadcast, interfaceAddress->local, netmask); 1390 } 1391 1392 interfaceAddress->AddDefaultRoutes(option); 1393 notify_interface_changed(interface); 1394 } 1395 1396 if (interfaceAddress->LocalIsDefined()) 1397 sAddressTable.Insert(interfaceAddress); 1398 return status; 1399 } 1400 1401 1402 Interface* 1403 get_interface(net_domain* domain, uint32 index) 1404 { 1405 RecursiveLocker locker(sLock); 1406 1407 Interface* interface; 1408 if (index == 0) 1409 interface = sInterfaces.First(); 1410 else 1411 interface = find_interface(index); 1412 if (interface == NULL) 1413 return NULL; 1414 1415 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1416 return NULL; 1417 1418 interface->AcquireReference(); 1419 return interface; 1420 } 1421 1422 1423 Interface* 1424 get_interface(net_domain* domain, const char* name) 1425 { 1426 RecursiveLocker locker(sLock); 1427 1428 Interface* interface = find_interface(name); 1429 if (interface == NULL) 1430 return NULL; 1431 1432 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1433 return NULL; 1434 1435 interface->AcquireReference(); 1436 return interface; 1437 } 1438 1439 1440 Interface* 1441 get_interface_for_device(net_domain* domain, uint32 index) 1442 { 1443 RecursiveLocker locker(sLock); 1444 1445 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1446 while (Interface* interface = iterator.Next()) { 1447 if (interface->device->index == index) { 1448 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1449 return NULL; 1450 1451 interface->AcquireReference(); 1452 return interface; 1453 } 1454 } 1455 1456 return NULL; 1457 } 1458 1459 1460 /*! Returns a reference to an Interface that matches the given \a linkAddress. 1461 The link address is checked against its hardware address, or its interface 1462 name, or finally the interface index. 1463 */ 1464 Interface* 1465 get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) 1466 { 1467 sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress; 1468 1469 RecursiveLocker locker(sLock); 1470 1471 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1472 while (Interface* interface = iterator.Next()) { 1473 // Test if the hardware address matches, or if the given interface 1474 // matches, or if at least the index matches. 1475 if ((linkAddress.sdl_alen == interface->device->address.length 1476 && memcmp(LLADDR(&linkAddress), interface->device->address.data, 1477 linkAddress.sdl_alen) == 0) 1478 || (linkAddress.sdl_nlen > 0 1479 && !strcmp(interface->name, (const char*)linkAddress.sdl_data)) 1480 || (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0 1481 && linkAddress.sdl_index == interface->index)) { 1482 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1483 return NULL; 1484 1485 interface->AcquireReference(); 1486 return interface; 1487 } 1488 } 1489 1490 return NULL; 1491 } 1492 1493 1494 InterfaceAddress* 1495 get_interface_address(const sockaddr* local) 1496 { 1497 if (local->sa_family == AF_UNSPEC) 1498 return NULL; 1499 1500 MutexLocker locker(sHashLock); 1501 1502 InterfaceAddress* address = sAddressTable.Lookup(local); 1503 if (address == NULL) 1504 return NULL; 1505 1506 address->AcquireReference(); 1507 return address; 1508 } 1509 1510 1511 InterfaceAddress* 1512 get_interface_address_for_destination(net_domain* domain, 1513 const sockaddr* destination) 1514 { 1515 RecursiveLocker locker(sLock); 1516 1517 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1518 while (Interface* interface = iterator.Next()) { 1519 InterfaceAddress* address 1520 = interface->AddressForDestination(domain, destination); 1521 if (address != NULL) 1522 return address; 1523 } 1524 1525 return NULL; 1526 } 1527 1528 1529 /*! Returns a reference to an InterfaceAddress of the specified \a domain that 1530 belongs to the interface identified via \a linkAddress. Only the hardware 1531 address is matched. 1532 1533 If \a unconfiguredOnly is set, the interface address must not yet be 1534 configured, or must currently be in the process of being configured. 1535 */ 1536 InterfaceAddress* 1537 get_interface_address_for_link(net_domain* domain, const sockaddr* address, 1538 bool unconfiguredOnly) 1539 { 1540 sockaddr_dl& linkAddress = *(sockaddr_dl*)address; 1541 1542 RecursiveLocker locker(sLock); 1543 1544 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1545 while (Interface* interface = iterator.Next()) { 1546 // Test if the hardware address matches, or if the given interface 1547 // matches, or if at least the index matches. 1548 if (linkAddress.sdl_alen == interface->device->address.length 1549 && memcmp(LLADDR(&linkAddress), interface->device->address.data, 1550 linkAddress.sdl_alen) == 0) { 1551 TRACE(" %s matches\n", interface->name); 1552 // link address matches 1553 if (unconfiguredOnly) 1554 return interface->FirstUnconfiguredForFamily(domain->family); 1555 1556 return interface->FirstForFamily(domain->family); 1557 } 1558 } 1559 1560 return NULL; 1561 } 1562 1563 1564 uint32 1565 count_interfaces() 1566 { 1567 RecursiveLocker locker(sLock); 1568 1569 return sInterfaces.Count(); 1570 } 1571 1572 1573 /*! Dumps a list of all interfaces into the supplied userland buffer. 1574 If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is 1575 returned. 1576 */ 1577 status_t 1578 list_interfaces(int family, void* _buffer, size_t* bufferSize) 1579 { 1580 RecursiveLocker locker(sLock); 1581 1582 UserBuffer buffer(_buffer, *bufferSize); 1583 1584 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1585 while (Interface* interface = iterator.Next()) { 1586 // Copy name 1587 buffer.Push(interface->name, IF_NAMESIZE); 1588 1589 // Copy address 1590 InterfaceAddress* address = interface->FirstForFamily(family); 1591 size_t length = 0; 1592 1593 if (address != NULL && address->local != NULL) { 1594 // Actual address 1595 buffer.Push(address->local, length = address->local->sa_len); 1596 } else { 1597 // Empty address 1598 sockaddr empty; 1599 empty.sa_len = 2; 1600 empty.sa_family = AF_UNSPEC; 1601 buffer.Push(&empty, length = empty.sa_len); 1602 } 1603 1604 if (address != NULL) 1605 address->ReleaseReference(); 1606 1607 if (IF_NAMESIZE + length < sizeof(ifreq)) { 1608 // Make sure at least sizeof(ifreq) bytes are written for each 1609 // interface for compatibility with other platforms 1610 buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length); 1611 } 1612 1613 if (buffer.Status() != B_OK) 1614 return buffer.Status(); 1615 } 1616 1617 *bufferSize = buffer.BytesConsumed(); 1618 return B_OK; 1619 } 1620 1621 1622 // #pragma mark - 1623 1624 1625 status_t 1626 init_interfaces() 1627 { 1628 recursive_lock_init(&sLock, "net interfaces"); 1629 mutex_init(&sHashLock, "net local addresses"); 1630 1631 new (&sInterfaces) InterfaceList; 1632 new (&sAddressTable) AddressTable; 1633 // static C++ objects are not initialized in the module startup 1634 1635 #if ENABLE_DEBUGGER_COMMANDS 1636 add_debugger_command("net_interface", &dump_interface, 1637 "Dump the given network interface"); 1638 add_debugger_command("net_interfaces", &dump_interfaces, 1639 "Dump all network interfaces"); 1640 add_debugger_command("net_local", &dump_local, 1641 "Dump all local interface addresses"); 1642 add_debugger_command("net_route", &dump_route, 1643 "Dump the given network route"); 1644 #endif 1645 return B_OK; 1646 } 1647 1648 1649 status_t 1650 uninit_interfaces() 1651 { 1652 #if ENABLE_DEBUGGER_COMMANDS 1653 remove_debugger_command("net_interface", &dump_interface); 1654 remove_debugger_command("net_interfaces", &dump_interfaces); 1655 remove_debugger_command("net_local", &dump_local); 1656 remove_debugger_command("net_route", &dump_route); 1657 #endif 1658 1659 recursive_lock_destroy(&sLock); 1660 mutex_destroy(&sHashLock); 1661 return B_OK; 1662 } 1663 1664