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