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