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 fBusy(false) 450 { 451 TRACE("Interface %p: new \"%s\", device interface %p\n", this, 452 interfaceName, deviceInterface); 453 454 int written = strlcpy(name, interfaceName, IF_NAMESIZE); 455 memset(name + written, 0, IF_NAMESIZE - written); 456 // Clear remaining space 457 458 device = deviceInterface->device; 459 460 index = ++sInterfaceIndex; 461 flags = 0; 462 type = 0; 463 mtu = deviceInterface->device->mtu; 464 metric = 0; 465 466 fDeviceInterface = acquire_device_interface(deviceInterface); 467 468 recursive_lock_init(&fLock, name); 469 470 // Grab a reference to the networking stack, to make sure it won't be 471 // unloaded as long as an interface exists 472 module_info* module; 473 get_module(gNetStackInterfaceModule.info.name, &module); 474 } 475 476 477 Interface::~Interface() 478 { 479 TRACE("Interface %p: destructor\n", this); 480 481 put_device_interface(fDeviceInterface); 482 483 // Uninitialize the domain datalink protocols 484 485 DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 486 while (domain_datalink* datalink = iterator.Next()) { 487 put_domain_datalink_protocols(this, datalink->domain); 488 } 489 490 // Free domain datalink objects 491 492 domain_datalink* next = fDatalinkTable.Clear(true); 493 while (next != NULL) { 494 domain_datalink* datalink = next; 495 next = next->hash_link; 496 497 delete datalink; 498 } 499 500 recursive_lock_destroy(&fLock); 501 502 // Release reference of the stack - at this point, our stack may be unloaded 503 // if no other interfaces or sockets are left 504 put_module(gNetStackInterfaceModule.info.name); 505 } 506 507 508 /*! Returns a reference to the first InterfaceAddress that is from the same 509 as the specified \a family. 510 */ 511 InterfaceAddress* 512 Interface::FirstForFamily(int family) 513 { 514 RecursiveLocker locker(fLock); 515 516 InterfaceAddress* address = _FirstForFamily(family); 517 if (address != NULL) { 518 address->AcquireReference(); 519 return address; 520 } 521 522 return NULL; 523 } 524 525 526 /*! Returns a reference to the first unconfigured address of this interface 527 for the specified \a family. 528 */ 529 InterfaceAddress* 530 Interface::FirstUnconfiguredForFamily(int family) 531 { 532 RecursiveLocker locker(fLock); 533 534 AddressList::Iterator iterator = fAddresses.GetIterator(); 535 while (InterfaceAddress* address = iterator.Next()) { 536 if (address->domain->family == family 537 && (address->local == NULL 538 // TODO: this has to be solved differently!! 539 || (flags & IFF_CONFIGURING) != 0)) { 540 address->AcquireReference(); 541 return address; 542 } 543 } 544 545 return NULL; 546 } 547 548 549 /*! Returns a reference to the InterfaceAddress that has the specified 550 \a destination address. 551 */ 552 InterfaceAddress* 553 Interface::AddressForDestination(net_domain* domain, 554 const sockaddr* destination) 555 { 556 RecursiveLocker locker(fLock); 557 558 if ((device->flags & IFF_BROADCAST) == 0) { 559 // The device does not support broadcasting 560 return NULL; 561 } 562 563 AddressList::Iterator iterator = fAddresses.GetIterator(); 564 while (InterfaceAddress* address = iterator.Next()) { 565 if (address->domain == domain 566 && address->destination != NULL 567 && domain->address_module->equal_addresses(address->destination, 568 destination)) { 569 address->AcquireReference(); 570 return address; 571 } 572 } 573 574 return NULL; 575 } 576 577 578 /*! Returns a reference to the InterfaceAddress that has the specified 579 \a local address. 580 */ 581 InterfaceAddress* 582 Interface::AddressForLocal(net_domain* domain, const sockaddr* local) 583 { 584 RecursiveLocker locker(fLock); 585 586 AddressList::Iterator iterator = fAddresses.GetIterator(); 587 while (InterfaceAddress* address = iterator.Next()) { 588 if (address->domain == domain 589 && address->local != NULL 590 && domain->address_module->equal_addresses(address->local, local)) { 591 address->AcquireReference(); 592 return address; 593 } 594 } 595 596 return NULL; 597 } 598 599 600 status_t 601 Interface::AddAddress(InterfaceAddress* address) 602 { 603 net_domain* domain = address->domain; 604 if (domain == NULL) 605 return B_BAD_VALUE; 606 607 RecursiveLocker locker(fLock); 608 fAddresses.Add(address); 609 locker.Unlock(); 610 611 if (address->LocalIsDefined()) { 612 MutexLocker hashLocker(sHashLock); 613 sAddressTable.Insert(address); 614 } 615 return B_OK; 616 } 617 618 619 void 620 Interface::RemoveAddress(InterfaceAddress* address) 621 { 622 net_domain* domain = address->domain; 623 if (domain == NULL) 624 return; 625 626 RecursiveLocker locker(fLock); 627 628 fAddresses.Remove(address); 629 address->GetDoublyLinkedListLink()->next = NULL; 630 631 locker.Unlock(); 632 633 if (address->LocalIsDefined()) { 634 MutexLocker hashLocker(sHashLock); 635 sAddressTable.Remove(address); 636 } 637 } 638 639 640 bool 641 Interface::GetNextAddress(InterfaceAddress** _address) 642 { 643 RecursiveLocker locker(fLock); 644 645 InterfaceAddress* address = *_address; 646 if (address == NULL) { 647 // get first address 648 address = fAddresses.First(); 649 } else { 650 // get next, if possible 651 InterfaceAddress* next = fAddresses.GetNext(address); 652 address->ReleaseReference(); 653 address = next; 654 } 655 656 *_address = address; 657 658 if (address == NULL) 659 return false; 660 661 address->AcquireReference(); 662 return true; 663 } 664 665 666 InterfaceAddress* 667 Interface::AddressAt(size_t index) 668 { 669 RecursiveLocker locker(fLock); 670 671 AddressList::Iterator iterator = fAddresses.GetIterator(); 672 size_t i = 0; 673 674 while (InterfaceAddress* address = iterator.Next()) { 675 if (i++ == index) { 676 address->AcquireReference(); 677 return address; 678 } 679 } 680 681 return NULL; 682 } 683 684 685 int32 686 Interface::IndexOfAddress(InterfaceAddress* address) 687 { 688 if (address == NULL) 689 return -1; 690 691 RecursiveLocker locker(fLock); 692 693 AddressList::Iterator iterator = fAddresses.GetIterator(); 694 int32 index = 0; 695 696 while (iterator.HasNext()) { 697 if (address == iterator.Next()) 698 return index; 699 700 index++; 701 } 702 703 return -1; 704 } 705 706 707 size_t 708 Interface::CountAddresses() 709 { 710 RecursiveLocker locker(fLock); 711 return fAddresses.Count(); 712 } 713 714 715 void 716 Interface::RemoveAddresses() 717 { 718 RecursiveLocker locker(fLock); 719 720 while (InterfaceAddress* address = fAddresses.RemoveHead()) { 721 locker.Unlock(); 722 723 if (address->LocalIsDefined()) { 724 MutexLocker hashLocker(sHashLock); 725 sAddressTable.Remove(address); 726 } 727 address->ReleaseReference(); 728 729 locker.Lock(); 730 } 731 } 732 733 734 /*! This is called in order to call the correct methods of the datalink 735 protocols, ie. it will translate address changes to 736 net_datalink_protocol::change_address(), and IFF_UP changes to 737 net_datalink_protocol::interface_up(), and interface_down(). 738 739 Everything else is passed unchanged to net_datalink_protocol::control(). 740 */ 741 status_t 742 Interface::Control(net_domain* domain, int32 option, ifreq& request, 743 ifreq* userRequest, size_t length) 744 { 745 switch (option) { 746 case SIOCSIFFLAGS: 747 { 748 if (length != sizeof(ifreq)) 749 return B_BAD_VALUE; 750 751 uint32 requestFlags = request.ifr_flags; 752 uint32 oldFlags = flags; 753 status_t status = B_OK; 754 755 request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST); 756 757 if ((requestFlags & IFF_UP) != (flags & IFF_UP)) { 758 if ((requestFlags & IFF_UP) != 0) 759 status = _SetUp(); 760 else 761 SetDown(); 762 } 763 764 if (status == B_OK) { 765 // TODO: maybe allow deleting IFF_BROADCAST on the interface 766 // level? 767 flags &= IFF_UP | IFF_LINK | IFF_BROADCAST; 768 flags |= request.ifr_flags; 769 } 770 771 if (oldFlags != flags) { 772 TRACE("Interface %p: flags changed from %" B_PRIx32 " to %" 773 B_PRIx32 "\n", this, oldFlags, flags); 774 notify_interface_changed(this, oldFlags, flags); 775 } 776 777 return status; 778 } 779 780 case B_SOCKET_SET_ALIAS: 781 { 782 if (length != sizeof(ifaliasreq)) 783 return B_BAD_VALUE; 784 785 RecursiveLocker locker(fLock); 786 787 ifaliasreq aliasRequest; 788 if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq)) 789 != B_OK) 790 return B_BAD_ADDRESS; 791 792 InterfaceAddress* address = NULL; 793 if (aliasRequest.ifra_index < 0) { 794 if (!domain->address_module->is_empty_address( 795 (const sockaddr*)&aliasRequest.ifra_addr, false)) { 796 // Find first address that matches the local address 797 address = AddressForLocal(domain, 798 (const sockaddr*)&aliasRequest.ifra_addr); 799 } 800 if (address == NULL) { 801 // Find first address for family 802 address = FirstForFamily(domain->family); 803 } 804 if (address == NULL) { 805 // Create new on the fly 806 address = new(std::nothrow) InterfaceAddress(this, domain); 807 if (address == NULL) 808 return B_NO_MEMORY; 809 810 status_t status = AddAddress(address); 811 if (status != B_OK) { 812 delete address; 813 return status; 814 } 815 816 // Note, even if setting the address failed, the empty 817 // address added here will still be added to the interface. 818 address->AcquireReference(); 819 } 820 } else 821 address = AddressAt(aliasRequest.ifra_index); 822 823 if (address == NULL) 824 return B_BAD_VALUE; 825 826 status_t status = B_OK; 827 828 if (!domain->address_module->equal_addresses( 829 (sockaddr*)&aliasRequest.ifra_addr, address->local)) { 830 status = _ChangeAddress(locker, address, SIOCSIFADDR, 831 address->local, (sockaddr*)&aliasRequest.ifra_addr); 832 } 833 834 if (status == B_OK && !domain->address_module->equal_addresses( 835 (sockaddr*)&aliasRequest.ifra_mask, address->mask) 836 && !domain->address_module->is_empty_address( 837 (sockaddr*)&aliasRequest.ifra_mask, false)) { 838 status = _ChangeAddress(locker, address, SIOCSIFNETMASK, 839 address->mask, (sockaddr*)&aliasRequest.ifra_mask); 840 } 841 842 if (status == B_OK && !domain->address_module->equal_addresses( 843 (sockaddr*)&aliasRequest.ifra_destination, 844 address->destination) 845 && !domain->address_module->is_empty_address( 846 (sockaddr*)&aliasRequest.ifra_destination, false)) { 847 status = _ChangeAddress(locker, address, 848 (domain->address_module->flags 849 & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0 850 ? SIOCSIFBRDADDR : SIOCSIFDSTADDR, 851 address->destination, 852 (sockaddr*)&aliasRequest.ifra_destination); 853 } 854 855 address->ReleaseReference(); 856 return status; 857 } 858 859 case SIOCSIFADDR: 860 case SIOCSIFNETMASK: 861 case SIOCSIFBRDADDR: 862 case SIOCSIFDSTADDR: 863 case SIOCDIFADDR: 864 { 865 if (length != sizeof(ifreq)) 866 return B_BAD_VALUE; 867 868 RecursiveLocker locker(fLock); 869 870 InterfaceAddress* address = NULL; 871 sockaddr_storage newAddress; 872 873 size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr)); 874 if (size > sizeof(sockaddr_storage)) 875 size = sizeof(sockaddr_storage); 876 877 if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK) 878 return B_BAD_ADDRESS; 879 880 if (option == SIOCDIFADDR) { 881 // Find referring address - we can't use the hash, as another 882 // interface might use the same address. 883 AddressList::Iterator iterator = fAddresses.GetIterator(); 884 while ((address = iterator.Next()) != NULL) { 885 if (address->domain == domain 886 && domain->address_module->equal_addresses( 887 address->local, (sockaddr*)&newAddress)) 888 break; 889 } 890 891 if (address == NULL) 892 return B_BAD_VALUE; 893 } else { 894 // Just use the first address for this family 895 address = _FirstForFamily(domain->family); 896 if (address == NULL) { 897 // Create new on the fly 898 address = new(std::nothrow) InterfaceAddress(this, domain); 899 if (address == NULL) 900 return B_NO_MEMORY; 901 902 status_t status = AddAddress(address); 903 if (status != B_OK) { 904 delete address; 905 return status; 906 } 907 908 // Note, even if setting the address failed, the empty 909 // address added here will still be added to the interface. 910 } 911 } 912 913 return _ChangeAddress(locker, address, option, 914 *address->AddressFor(option), 915 option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL); 916 } 917 918 default: 919 // pass the request into the datalink protocol stack 920 domain_datalink* datalink = DomainDatalink(domain->family); 921 if (datalink->first_info != NULL) { 922 return datalink->first_info->control( 923 datalink->first_protocol, option, userRequest, length); 924 } 925 break; 926 } 927 928 return B_BAD_VALUE; 929 } 930 931 932 void 933 Interface::SetDown() 934 { 935 if ((flags & IFF_UP) == 0) 936 return; 937 938 RecursiveLocker interfacesLocker(sLock); 939 940 if (IsBusy()) 941 return; 942 943 SetBusy(true); 944 interfacesLocker.Unlock(); 945 946 DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 947 while (domain_datalink* datalink = iterator.Next()) { 948 datalink->first_info->interface_down(datalink->first_protocol); 949 } 950 951 flags &= ~IFF_UP; 952 953 SetBusy(false); 954 } 955 956 957 /*! Called when a device lost its IFF_UP status. We will invalidate all 958 interface routes here. 959 */ 960 void 961 Interface::WentDown() 962 { 963 TRACE("Interface %p: went down\n", this); 964 965 RecursiveLocker locker(fLock); 966 967 AddressList::Iterator iterator = fAddresses.GetIterator(); 968 while (InterfaceAddress* address = iterator.Next()) { 969 if (address->domain != NULL) 970 invalidate_routes(address->domain, this); 971 } 972 } 973 974 975 status_t 976 Interface::CreateDomainDatalinkIfNeeded(net_domain* domain) 977 { 978 RecursiveLocker locker(fLock); 979 980 if (fDatalinkTable.Lookup(domain->family) != NULL) 981 return B_OK; 982 983 TRACE("Interface %p: create domain datalink for domain %p\n", this, domain); 984 985 domain_datalink* datalink = new(std::nothrow) domain_datalink; 986 if (datalink == NULL) 987 return B_NO_MEMORY; 988 989 datalink->first_protocol = NULL; 990 datalink->first_info = NULL; 991 datalink->domain = domain; 992 993 // setup direct route for bound devices 994 datalink->direct_route.destination = NULL; 995 datalink->direct_route.mask = NULL; 996 datalink->direct_route.gateway = NULL; 997 datalink->direct_route.flags = 0; 998 datalink->direct_route.mtu = 0; 999 datalink->direct_route.interface_address = &datalink->direct_address; 1000 datalink->direct_route.ref_count = 1; 1001 // make sure this doesn't get deleted accidently 1002 1003 // provide its link back to the interface 1004 datalink->direct_address.local = NULL; 1005 datalink->direct_address.destination = NULL; 1006 datalink->direct_address.mask = NULL; 1007 datalink->direct_address.domain = domain; 1008 datalink->direct_address.interface = this; 1009 datalink->direct_address.flags = IFAF_DIRECT_ADDRESS; 1010 1011 fDatalinkTable.Insert(datalink); 1012 1013 status_t status = get_domain_datalink_protocols(this, domain); 1014 if (status == B_OK) 1015 return B_OK; 1016 1017 fDatalinkTable.Remove(datalink); 1018 delete datalink; 1019 1020 return status; 1021 } 1022 1023 1024 domain_datalink* 1025 Interface::DomainDatalink(uint8 family) 1026 { 1027 // Note: domain datalinks cannot be removed while the interface is alive, 1028 // since this would require us either to hold the lock while calling this 1029 // function, or introduce reference counting for the domain_datalink 1030 // structure. 1031 RecursiveLocker locker(fLock); 1032 return fDatalinkTable.Lookup(family); 1033 } 1034 1035 1036 #if ENABLE_DEBUGGER_COMMANDS 1037 1038 1039 void 1040 Interface::Dump() const 1041 { 1042 kprintf("name: %s\n", name); 1043 kprintf("device: %p\n", device); 1044 kprintf("device_interface: %p\n", fDeviceInterface); 1045 kprintf("index: %" B_PRIu32 "\n", index); 1046 kprintf("flags: %#" B_PRIx32 "\n", flags); 1047 kprintf("type: %u\n", type); 1048 kprintf("mtu: %" B_PRIu32 "\n", mtu); 1049 kprintf("metric: %" B_PRIu32 "\n", metric); 1050 kprintf("ref count: %" B_PRId32 "\n", CountReferences()); 1051 1052 kprintf("datalink protocols:\n"); 1053 1054 DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator(); 1055 size_t i = 0; 1056 while (domain_datalink* datalink = datalinkIterator.Next()) { 1057 kprintf("%2zu. domain: %p\n", ++i, datalink->domain); 1058 kprintf(" first_protocol: %p\n", datalink->first_protocol); 1059 kprintf(" first_info: %p\n", datalink->first_info); 1060 kprintf(" direct_route: %p\n", &datalink->direct_route); 1061 } 1062 1063 kprintf("addresses:\n"); 1064 1065 AddressList::ConstIterator iterator = fAddresses.GetIterator(); 1066 i = 0; 1067 while (InterfaceAddress* address = iterator.Next()) { 1068 address->Dump(++i, true); 1069 } 1070 } 1071 1072 1073 #endif // ENABLE_DEBUGGER_COMMANDS 1074 1075 1076 status_t 1077 Interface::_SetUp() 1078 { 1079 status_t status = up_device_interface(fDeviceInterface); 1080 if (status != B_OK) 1081 return status; 1082 1083 RecursiveLocker interfacesLocker(sLock); 1084 SetBusy(true); 1085 interfacesLocker.Unlock(); 1086 1087 // Propagate flag to all datalink protocols 1088 DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 1089 while (domain_datalink* datalink = iterator.Next()) { 1090 status = datalink->first_info->interface_up(datalink->first_protocol); 1091 if (status != B_OK) { 1092 // Revert "up" status 1093 DatalinkTable::Iterator secondIterator 1094 = fDatalinkTable.GetIterator(); 1095 while (secondIterator.HasNext()) { 1096 domain_datalink* secondDatalink = secondIterator.Next(); 1097 if (secondDatalink == NULL || secondDatalink == datalink) 1098 break; 1099 1100 secondDatalink->first_info->interface_down( 1101 secondDatalink->first_protocol); 1102 } 1103 1104 down_device_interface(fDeviceInterface); 1105 SetBusy(false); 1106 return status; 1107 } 1108 } 1109 1110 // Add default routes for the existing addresses 1111 1112 AddressList::Iterator addressIterator = fAddresses.GetIterator(); 1113 while (InterfaceAddress* address = addressIterator.Next()) { 1114 address->AddDefaultRoutes(SIOCSIFADDR); 1115 } 1116 1117 flags |= IFF_UP; 1118 SetBusy(false); 1119 1120 return B_OK; 1121 } 1122 1123 1124 InterfaceAddress* 1125 Interface::_FirstForFamily(int family) 1126 { 1127 ASSERT_LOCKED_RECURSIVE(&fLock); 1128 1129 AddressList::Iterator iterator = fAddresses.GetIterator(); 1130 while (InterfaceAddress* address = iterator.Next()) { 1131 if (address->domain != NULL && address->domain->family == family) 1132 return address; 1133 } 1134 1135 return NULL; 1136 } 1137 1138 1139 status_t 1140 Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address, 1141 int32 option, const sockaddr* originalAddress, 1142 const sockaddr* requestedAddress) 1143 { 1144 // Copy old address 1145 sockaddr_storage oldAddress; 1146 if (address->domain->address_module->set_to((sockaddr*)&oldAddress, 1147 originalAddress) != B_OK) 1148 oldAddress.ss_family = AF_UNSPEC; 1149 1150 // Copy new address (this also makes sure that sockaddr::sa_len is set 1151 // correctly) 1152 sockaddr_storage newAddress; 1153 if (address->domain->address_module->set_to((sockaddr*)&newAddress, 1154 requestedAddress) != B_OK) 1155 newAddress.ss_family = AF_UNSPEC; 1156 1157 // Test if anything changed for real 1158 if (address->domain->address_module->equal_addresses( 1159 (sockaddr*)&oldAddress, (sockaddr*)&newAddress)) { 1160 // Nothing to do 1161 TRACE(" option %" B_PRId32 " addresses are equal!\n", option); 1162 return B_OK; 1163 } 1164 1165 // TODO: mark this address busy or call while holding the lock! 1166 address->AcquireReference(); 1167 locker.Unlock(); 1168 1169 domain_datalink* datalink = DomainDatalink(address->domain); 1170 status_t status = datalink->first_protocol->module->change_address( 1171 datalink->first_protocol, address, option, 1172 oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL, 1173 newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL); 1174 1175 locker.Lock(); 1176 address->ReleaseReference(); 1177 return status; 1178 } 1179 1180 1181 // #pragma mark - 1182 1183 1184 /*! Searches for a specific interface by name. 1185 You need to have the interface list's lock hold when calling this function. 1186 */ 1187 static struct Interface* 1188 find_interface(const char* name) 1189 { 1190 ASSERT_LOCKED_RECURSIVE(&sLock); 1191 1192 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1193 while (Interface* interface = iterator.Next()) { 1194 if (!strcmp(interface->name, name)) 1195 return interface; 1196 } 1197 1198 return NULL; 1199 } 1200 1201 1202 /*! Searches for a specific interface by index. 1203 You need to have the interface list's lock hold when calling this function. 1204 */ 1205 static struct Interface* 1206 find_interface(uint32 index) 1207 { 1208 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1209 while (Interface* interface = iterator.Next()) { 1210 if (interface->index == index) 1211 return interface; 1212 } 1213 1214 return NULL; 1215 } 1216 1217 1218 // #pragma mark - 1219 1220 1221 status_t 1222 add_interface(const char* name, net_domain_private* domain, 1223 const ifaliasreq& request, net_device_interface* deviceInterface) 1224 { 1225 RecursiveLocker locker(sLock); 1226 1227 if (find_interface(name) != NULL) 1228 return B_NAME_IN_USE; 1229 1230 Interface* interface 1231 = new(std::nothrow) Interface(name, deviceInterface); 1232 if (interface == NULL) 1233 return B_NO_MEMORY; 1234 1235 sInterfaces.Add(interface); 1236 interface->AcquireReference(); 1237 // We need another reference to be able to use the interface without 1238 // holding sLock. 1239 1240 locker.Unlock(); 1241 1242 status_t status = add_interface_address(interface, domain, request); 1243 if (status == B_OK) 1244 notify_interface_added(interface); 1245 else { 1246 locker.Lock(); 1247 sInterfaces.Remove(interface); 1248 locker.Unlock(); 1249 interface->ReleaseReference(); 1250 } 1251 1252 interface->ReleaseReference(); 1253 1254 return status; 1255 } 1256 1257 1258 /*! Removes the interface from the list, and puts the stack's reference to it. 1259 */ 1260 void 1261 remove_interface(Interface* interface) 1262 { 1263 interface->SetDown(); 1264 interface->RemoveAddresses(); 1265 1266 RecursiveLocker locker(sLock); 1267 sInterfaces.Remove(interface); 1268 locker.Unlock(); 1269 1270 notify_interface_removed(interface); 1271 1272 interface->ReleaseReference(); 1273 } 1274 1275 1276 /*! This is called whenever a device interface is being removed. We will get 1277 the corresponding Interface, and remove it. 1278 */ 1279 void 1280 interface_removed_device_interface(net_device_interface* deviceInterface) 1281 { 1282 RecursiveLocker locker(sLock); 1283 1284 Interface* interface = find_interface(deviceInterface->device->name); 1285 if (interface != NULL) 1286 remove_interface(interface); 1287 } 1288 1289 1290 status_t 1291 add_interface_address(Interface* interface, net_domain_private* domain, 1292 const ifaliasreq& request) 1293 { 1294 // Make sure the family of the provided addresses is valid 1295 if ((request.ifra_addr.ss_family != domain->family 1296 && request.ifra_addr.ss_family != AF_UNSPEC) 1297 || (request.ifra_mask.ss_family != domain->family 1298 && request.ifra_mask.ss_family != AF_UNSPEC) 1299 || (request.ifra_broadaddr.ss_family != domain->family 1300 && request.ifra_broadaddr.ss_family != AF_UNSPEC)) 1301 return B_BAD_VALUE; 1302 1303 RecursiveLocker locker(interface->Lock()); 1304 1305 InterfaceAddress* address 1306 = new(std::nothrow) InterfaceAddress(interface, domain); 1307 if (address == NULL) 1308 return B_NO_MEMORY; 1309 1310 status_t status = address->SetTo(request); 1311 if (status == B_OK) 1312 status = interface->CreateDomainDatalinkIfNeeded(domain); 1313 if (status == B_OK) 1314 status = interface->AddAddress(address); 1315 1316 if (status == B_OK && address->local != NULL) { 1317 // update the datalink protocols 1318 domain_datalink* datalink = interface->DomainDatalink(domain->family); 1319 1320 status = datalink->first_protocol->module->change_address( 1321 datalink->first_protocol, address, SIOCAIFADDR, NULL, 1322 address->local); 1323 if (status != B_OK) 1324 interface->RemoveAddress(address); 1325 } 1326 if (status == B_OK) 1327 notify_interface_changed(interface); 1328 else 1329 delete address; 1330 1331 return status; 1332 } 1333 1334 1335 status_t 1336 update_interface_address(InterfaceAddress* interfaceAddress, int32 option, 1337 const sockaddr* oldAddress, const sockaddr* newAddress) 1338 { 1339 TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress " 1340 "%s)\n", __FUNCTION__, interfaceAddress, option, 1341 AddressString(interfaceAddress->domain, oldAddress).Data(), 1342 AddressString(interfaceAddress->domain, newAddress).Data()); 1343 1344 MutexLocker locker(sHashLock); 1345 1346 // set logical interface address 1347 sockaddr** _address = interfaceAddress->AddressFor(option); 1348 if (_address == NULL) 1349 return B_BAD_VALUE; 1350 1351 Interface* interface = (Interface*)interfaceAddress->interface; 1352 1353 interfaceAddress->RemoveDefaultRoutes(option); 1354 1355 if (option == SIOCDIFADDR) { 1356 // Remove address, and release its reference (causing our caller to 1357 // delete it) 1358 locker.Unlock(); 1359 1360 invalidate_routes(interfaceAddress); 1361 1362 interface->RemoveAddress(interfaceAddress); 1363 interfaceAddress->ReleaseReference(); 1364 return B_OK; 1365 } 1366 1367 if (interfaceAddress->LocalIsDefined()) 1368 sAddressTable.Remove(interfaceAddress); 1369 1370 // Copy new address over 1371 status_t status = InterfaceAddress::Set(_address, newAddress); 1372 if (status == B_OK) { 1373 sockaddr* address = *_address; 1374 1375 if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) { 1376 // Reset netmask and broadcast addresses to defaults 1377 net_domain* domain = interfaceAddress->domain; 1378 sockaddr* defaultNetmask = NULL; 1379 const sockaddr* netmask = NULL; 1380 if (option == SIOCSIFADDR) { 1381 defaultNetmask = InterfaceAddress::Prepare( 1382 &interfaceAddress->mask, address->sa_len); 1383 } else 1384 netmask = newAddress; 1385 1386 // Reset the broadcast address if the address family has 1387 // such 1388 sockaddr* defaultBroadcast = NULL; 1389 if ((domain->address_module->flags 1390 & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) { 1391 defaultBroadcast = InterfaceAddress::Prepare( 1392 &interfaceAddress->destination, address->sa_len); 1393 } else 1394 InterfaceAddress::Set(&interfaceAddress->destination, NULL); 1395 1396 domain->address_module->set_to_defaults(defaultNetmask, 1397 defaultBroadcast, interfaceAddress->local, netmask); 1398 } 1399 1400 interfaceAddress->AddDefaultRoutes(option); 1401 notify_interface_changed(interface); 1402 } 1403 1404 if (interfaceAddress->LocalIsDefined()) 1405 sAddressTable.Insert(interfaceAddress); 1406 return status; 1407 } 1408 1409 1410 Interface* 1411 get_interface(net_domain* domain, uint32 index) 1412 { 1413 RecursiveLocker locker(sLock); 1414 1415 Interface* interface; 1416 if (index == 0) 1417 interface = sInterfaces.First(); 1418 else 1419 interface = find_interface(index); 1420 if (interface == NULL || interface->IsBusy()) 1421 return NULL; 1422 1423 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1424 return NULL; 1425 1426 interface->AcquireReference(); 1427 return interface; 1428 } 1429 1430 1431 Interface* 1432 get_interface(net_domain* domain, const char* name) 1433 { 1434 RecursiveLocker locker(sLock); 1435 1436 Interface* interface = find_interface(name); 1437 if (interface == NULL || interface->IsBusy()) 1438 return NULL; 1439 1440 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1441 return NULL; 1442 1443 interface->AcquireReference(); 1444 return interface; 1445 } 1446 1447 1448 Interface* 1449 get_interface_for_device(net_domain* domain, uint32 index) 1450 { 1451 RecursiveLocker locker(sLock); 1452 1453 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1454 while (Interface* interface = iterator.Next()) { 1455 if (interface->device->index == index) { 1456 if (interface->IsBusy()) 1457 return NULL; 1458 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1459 return NULL; 1460 1461 interface->AcquireReference(); 1462 return interface; 1463 } 1464 } 1465 1466 return NULL; 1467 } 1468 1469 1470 /*! Returns a reference to an Interface that matches the given \a linkAddress. 1471 The link address is checked against its hardware address, or its interface 1472 name, or finally the interface index. 1473 */ 1474 Interface* 1475 get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) 1476 { 1477 sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress; 1478 1479 RecursiveLocker locker(sLock); 1480 1481 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1482 while (Interface* interface = iterator.Next()) { 1483 if (interface->IsBusy()) 1484 continue; 1485 // Test if the hardware address matches, or if the given interface 1486 // matches, or if at least the index matches. 1487 if ((linkAddress.sdl_alen == interface->device->address.length 1488 && memcmp(LLADDR(&linkAddress), interface->device->address.data, 1489 linkAddress.sdl_alen) == 0) 1490 || (linkAddress.sdl_nlen > 0 1491 && !strcmp(interface->name, (const char*)linkAddress.sdl_data)) 1492 || (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0 1493 && linkAddress.sdl_index == interface->index)) { 1494 if (interface->IsBusy()) 1495 return NULL; 1496 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1497 return NULL; 1498 1499 interface->AcquireReference(); 1500 return interface; 1501 } 1502 } 1503 1504 return NULL; 1505 } 1506 1507 1508 InterfaceAddress* 1509 get_interface_address(const sockaddr* local) 1510 { 1511 if (local->sa_family == AF_UNSPEC) 1512 return NULL; 1513 1514 MutexLocker locker(sHashLock); 1515 1516 InterfaceAddress* address = sAddressTable.Lookup(local); 1517 if (address == NULL) 1518 return NULL; 1519 1520 address->AcquireReference(); 1521 return address; 1522 } 1523 1524 1525 InterfaceAddress* 1526 get_interface_address_for_destination(net_domain* domain, 1527 const sockaddr* destination) 1528 { 1529 RecursiveLocker locker(sLock); 1530 1531 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1532 while (Interface* interface = iterator.Next()) { 1533 if (interface->IsBusy()) 1534 continue; 1535 1536 InterfaceAddress* address 1537 = interface->AddressForDestination(domain, destination); 1538 if (address != NULL) 1539 return address; 1540 } 1541 1542 return NULL; 1543 } 1544 1545 1546 /*! Returns a reference to an InterfaceAddress of the specified \a domain that 1547 belongs to the interface identified via \a linkAddress. Only the hardware 1548 address is matched. 1549 1550 If \a unconfiguredOnly is set, the interface address must not yet be 1551 configured, or must currently be in the process of being configured. 1552 */ 1553 InterfaceAddress* 1554 get_interface_address_for_link(net_domain* domain, const sockaddr* address, 1555 bool unconfiguredOnly) 1556 { 1557 sockaddr_dl& linkAddress = *(sockaddr_dl*)address; 1558 1559 RecursiveLocker locker(sLock); 1560 1561 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1562 while (Interface* interface = iterator.Next()) { 1563 if (interface->IsBusy()) 1564 continue; 1565 // Test if the hardware address matches, or if the given interface 1566 // matches, or if at least the index matches. 1567 if (linkAddress.sdl_alen == interface->device->address.length 1568 && memcmp(LLADDR(&linkAddress), interface->device->address.data, 1569 linkAddress.sdl_alen) == 0) { 1570 TRACE(" %s matches\n", interface->name); 1571 // link address matches 1572 if (unconfiguredOnly) 1573 return interface->FirstUnconfiguredForFamily(domain->family); 1574 1575 return interface->FirstForFamily(domain->family); 1576 } 1577 } 1578 1579 return NULL; 1580 } 1581 1582 1583 uint32 1584 count_interfaces() 1585 { 1586 RecursiveLocker locker(sLock); 1587 1588 return sInterfaces.Count(); 1589 } 1590 1591 1592 /*! Dumps a list of all interfaces into the supplied userland buffer. 1593 If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is 1594 returned. 1595 */ 1596 status_t 1597 list_interfaces(int family, void* _buffer, size_t* bufferSize) 1598 { 1599 RecursiveLocker locker(sLock); 1600 1601 UserBuffer buffer(_buffer, *bufferSize); 1602 1603 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1604 while (Interface* interface = iterator.Next()) { 1605 // Copy name 1606 buffer.Push(interface->name, IF_NAMESIZE); 1607 1608 // Copy address 1609 InterfaceAddress* address = interface->FirstForFamily(family); 1610 size_t length = 0; 1611 1612 if (address != NULL && address->local != NULL) { 1613 // Actual address 1614 buffer.Push(address->local, length = address->local->sa_len); 1615 } else { 1616 // Empty address 1617 sockaddr empty; 1618 empty.sa_len = 2; 1619 empty.sa_family = AF_UNSPEC; 1620 buffer.Push(&empty, length = empty.sa_len); 1621 } 1622 1623 if (address != NULL) 1624 address->ReleaseReference(); 1625 1626 if (IF_NAMESIZE + length < sizeof(ifreq)) { 1627 // Make sure at least sizeof(ifreq) bytes are written for each 1628 // interface for compatibility with other platforms 1629 buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length); 1630 } 1631 1632 if (buffer.Status() != B_OK) 1633 return buffer.Status(); 1634 } 1635 1636 *bufferSize = buffer.BytesConsumed(); 1637 return B_OK; 1638 } 1639 1640 1641 // #pragma mark - 1642 1643 1644 status_t 1645 init_interfaces() 1646 { 1647 recursive_lock_init(&sLock, "net interfaces"); 1648 mutex_init(&sHashLock, "net local addresses"); 1649 1650 new (&sInterfaces) InterfaceList; 1651 new (&sAddressTable) AddressTable; 1652 // static C++ objects are not initialized in the module startup 1653 1654 #if ENABLE_DEBUGGER_COMMANDS 1655 add_debugger_command("net_interface", &dump_interface, 1656 "Dump the given network interface"); 1657 add_debugger_command("net_interfaces", &dump_interfaces, 1658 "Dump all network interfaces"); 1659 add_debugger_command("net_local", &dump_local, 1660 "Dump all local interface addresses"); 1661 add_debugger_command("net_route", &dump_route, 1662 "Dump the given network route"); 1663 #endif 1664 return B_OK; 1665 } 1666 1667 1668 status_t 1669 uninit_interfaces() 1670 { 1671 #if ENABLE_DEBUGGER_COMMANDS 1672 remove_debugger_command("net_interface", &dump_interface); 1673 remove_debugger_command("net_interfaces", &dump_interfaces); 1674 remove_debugger_command("net_local", &dump_local); 1675 remove_debugger_command("net_route", &dump_route); 1676 #endif 1677 1678 recursive_lock_destroy(&sLock); 1679 mutex_destroy(&sHashLock); 1680 return B_OK; 1681 } 1682 1683