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 mtu = deviceInterface->device->mtu; 468 metric = 0; 469 470 fDeviceInterface = acquire_device_interface(deviceInterface); 471 472 recursive_lock_init(&fLock, name); 473 474 // Grab a reference to the networking stack, to make sure it won't be 475 // unloaded as long as an interface exists 476 module_info* module; 477 get_module(gNetStackInterfaceModule.info.name, &module); 478 } 479 480 481 Interface::~Interface() 482 { 483 TRACE("Interface %p: destructor\n", this); 484 485 put_device_interface(fDeviceInterface); 486 487 // Uninitialize the domain datalink protocols 488 489 DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 490 while (domain_datalink* datalink = iterator.Next()) { 491 put_domain_datalink_protocols(this, datalink->domain); 492 } 493 494 // Free domain datalink objects 495 496 domain_datalink* next = fDatalinkTable.Clear(true); 497 while (next != NULL) { 498 domain_datalink* datalink = next; 499 next = next->hash_link; 500 501 delete datalink; 502 } 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("mtu: %" B_PRIu32 "\n", mtu); 1053 kprintf("metric: %" B_PRIu32 "\n", metric); 1054 kprintf("ref count: %" B_PRId32 "\n", CountReferences()); 1055 1056 kprintf("datalink protocols:\n"); 1057 1058 DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator(); 1059 size_t i = 0; 1060 while (domain_datalink* datalink = datalinkIterator.Next()) { 1061 kprintf("%2zu. domain: %p\n", ++i, datalink->domain); 1062 kprintf(" first_protocol: %p\n", datalink->first_protocol); 1063 kprintf(" first_info: %p\n", datalink->first_info); 1064 kprintf(" direct_route: %p\n", &datalink->direct_route); 1065 } 1066 1067 kprintf("addresses:\n"); 1068 1069 AddressList::ConstIterator iterator = fAddresses.GetIterator(); 1070 i = 0; 1071 while (InterfaceAddress* address = iterator.Next()) { 1072 address->Dump(++i, true); 1073 } 1074 } 1075 1076 1077 #endif // ENABLE_DEBUGGER_COMMANDS 1078 1079 1080 status_t 1081 Interface::_SetUp() 1082 { 1083 status_t status = up_device_interface(fDeviceInterface); 1084 if (status != B_OK) 1085 return status; 1086 1087 RecursiveLocker interfacesLocker(sLock); 1088 SetBusy(true); 1089 interfacesLocker.Unlock(); 1090 1091 // Propagate flag to all datalink protocols 1092 DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 1093 while (domain_datalink* datalink = iterator.Next()) { 1094 status = datalink->first_info->interface_up(datalink->first_protocol); 1095 if (status != B_OK) { 1096 // Revert "up" status 1097 DatalinkTable::Iterator secondIterator 1098 = fDatalinkTable.GetIterator(); 1099 while (secondIterator.HasNext()) { 1100 domain_datalink* secondDatalink = secondIterator.Next(); 1101 if (secondDatalink == NULL || secondDatalink == datalink) 1102 break; 1103 1104 secondDatalink->first_info->interface_down( 1105 secondDatalink->first_protocol); 1106 } 1107 1108 down_device_interface(fDeviceInterface); 1109 SetBusy(false); 1110 return status; 1111 } 1112 } 1113 1114 // Add default routes for the existing addresses 1115 1116 AddressList::Iterator addressIterator = fAddresses.GetIterator(); 1117 while (InterfaceAddress* address = addressIterator.Next()) { 1118 address->AddDefaultRoutes(SIOCSIFADDR); 1119 } 1120 1121 flags |= IFF_UP; 1122 SetBusy(false); 1123 1124 return B_OK; 1125 } 1126 1127 1128 InterfaceAddress* 1129 Interface::_FirstForFamily(int family) 1130 { 1131 ASSERT_LOCKED_RECURSIVE(&fLock); 1132 1133 AddressList::Iterator iterator = fAddresses.GetIterator(); 1134 while (InterfaceAddress* address = iterator.Next()) { 1135 if (address->domain != NULL && address->domain->family == family) 1136 return address; 1137 } 1138 1139 return NULL; 1140 } 1141 1142 1143 status_t 1144 Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address, 1145 int32 option, const sockaddr* originalAddress, 1146 const sockaddr* requestedAddress) 1147 { 1148 // Copy old address 1149 sockaddr_storage oldAddress; 1150 if (address->domain->address_module->set_to((sockaddr*)&oldAddress, 1151 originalAddress) != B_OK) 1152 oldAddress.ss_family = AF_UNSPEC; 1153 1154 // Copy new address (this also makes sure that sockaddr::sa_len is set 1155 // correctly) 1156 sockaddr_storage newAddress; 1157 if (address->domain->address_module->set_to((sockaddr*)&newAddress, 1158 requestedAddress) != B_OK) 1159 newAddress.ss_family = AF_UNSPEC; 1160 1161 // Test if anything changed for real 1162 if (address->domain->address_module->equal_addresses( 1163 (sockaddr*)&oldAddress, (sockaddr*)&newAddress)) { 1164 // Nothing to do 1165 TRACE(" option %" B_PRId32 " addresses are equal!\n", option); 1166 return B_OK; 1167 } 1168 1169 // TODO: mark this address busy or call while holding the lock! 1170 address->AcquireReference(); 1171 locker.Unlock(); 1172 1173 domain_datalink* datalink = DomainDatalink(address->domain); 1174 status_t status = datalink->first_protocol->module->change_address( 1175 datalink->first_protocol, address, option, 1176 oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL, 1177 newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL); 1178 1179 locker.Lock(); 1180 address->ReleaseReference(); 1181 return status; 1182 } 1183 1184 1185 // #pragma mark - 1186 1187 1188 /*! Searches for a specific interface by name. 1189 You need to have the interface list's lock hold when calling this function. 1190 */ 1191 static struct Interface* 1192 find_interface(const char* name) 1193 { 1194 ASSERT_LOCKED_RECURSIVE(&sLock); 1195 1196 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1197 while (Interface* interface = iterator.Next()) { 1198 if (!strcmp(interface->name, name)) 1199 return interface; 1200 } 1201 1202 return NULL; 1203 } 1204 1205 1206 /*! Searches for a specific interface by index. 1207 You need to have the interface list's lock hold when calling this function. 1208 */ 1209 static struct Interface* 1210 find_interface(uint32 index) 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 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1428 return NULL; 1429 1430 interface->AcquireReference(); 1431 return interface; 1432 } 1433 1434 1435 Interface* 1436 get_interface(net_domain* domain, const char* name) 1437 { 1438 RecursiveLocker locker(sLock); 1439 1440 Interface* interface = find_interface(name); 1441 if (interface == NULL || interface->IsBusy()) 1442 return NULL; 1443 1444 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1445 return NULL; 1446 1447 interface->AcquireReference(); 1448 return interface; 1449 } 1450 1451 1452 Interface* 1453 get_interface_for_device(net_domain* domain, uint32 index) 1454 { 1455 RecursiveLocker locker(sLock); 1456 1457 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1458 while (Interface* interface = iterator.Next()) { 1459 if (interface->device->index == index) { 1460 if (interface->IsBusy()) 1461 return NULL; 1462 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1463 return NULL; 1464 1465 interface->AcquireReference(); 1466 return interface; 1467 } 1468 } 1469 1470 return NULL; 1471 } 1472 1473 1474 /*! Returns a reference to an Interface that matches the given \a linkAddress. 1475 The link address is checked against its hardware address, or its interface 1476 name, or finally the interface index. 1477 */ 1478 Interface* 1479 get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) 1480 { 1481 sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress; 1482 1483 RecursiveLocker locker(sLock); 1484 1485 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1486 while (Interface* interface = iterator.Next()) { 1487 if (interface->IsBusy()) 1488 continue; 1489 // Test if the hardware address matches, or if the given interface 1490 // matches, or if at least the index matches. 1491 if ((linkAddress.sdl_alen == interface->device->address.length 1492 && memcmp(LLADDR(&linkAddress), interface->device->address.data, 1493 linkAddress.sdl_alen) == 0) 1494 || (linkAddress.sdl_nlen > 0 1495 && !strcmp(interface->name, (const char*)linkAddress.sdl_data)) 1496 || (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0 1497 && linkAddress.sdl_index == interface->index)) { 1498 if (interface->IsBusy()) 1499 return NULL; 1500 if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1501 return NULL; 1502 1503 interface->AcquireReference(); 1504 return interface; 1505 } 1506 } 1507 1508 return NULL; 1509 } 1510 1511 1512 InterfaceAddress* 1513 get_interface_address(const sockaddr* local) 1514 { 1515 if (local->sa_family == AF_UNSPEC) 1516 return NULL; 1517 1518 MutexLocker locker(sHashLock); 1519 1520 InterfaceAddress* address = sAddressTable.Lookup(local); 1521 if (address == NULL) 1522 return NULL; 1523 1524 address->AcquireReference(); 1525 return address; 1526 } 1527 1528 1529 InterfaceAddress* 1530 get_interface_address_for_destination(net_domain* domain, 1531 const sockaddr* destination) 1532 { 1533 RecursiveLocker locker(sLock); 1534 1535 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1536 while (Interface* interface = iterator.Next()) { 1537 if (interface->IsBusy()) 1538 continue; 1539 1540 InterfaceAddress* address 1541 = interface->AddressForDestination(domain, destination); 1542 if (address != NULL) 1543 return address; 1544 } 1545 1546 return NULL; 1547 } 1548 1549 1550 /*! Returns a reference to an InterfaceAddress of the specified \a domain that 1551 belongs to the interface identified via \a linkAddress. Only the hardware 1552 address is matched. 1553 1554 If \a unconfiguredOnly is set, the interface address must not yet be 1555 configured, or must currently be in the process of being configured. 1556 */ 1557 InterfaceAddress* 1558 get_interface_address_for_link(net_domain* domain, const sockaddr* address, 1559 bool unconfiguredOnly) 1560 { 1561 sockaddr_dl& linkAddress = *(sockaddr_dl*)address; 1562 1563 RecursiveLocker locker(sLock); 1564 1565 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1566 while (Interface* interface = iterator.Next()) { 1567 if (interface->IsBusy()) 1568 continue; 1569 // Test if the hardware address matches, or if the given interface 1570 // matches, or if at least the index matches. 1571 if (linkAddress.sdl_alen == interface->device->address.length 1572 && memcmp(LLADDR(&linkAddress), interface->device->address.data, 1573 linkAddress.sdl_alen) == 0) { 1574 TRACE(" %s matches\n", interface->name); 1575 // link address matches 1576 if (unconfiguredOnly) 1577 return interface->FirstUnconfiguredForFamily(domain->family); 1578 1579 return interface->FirstForFamily(domain->family); 1580 } 1581 } 1582 1583 return NULL; 1584 } 1585 1586 1587 uint32 1588 count_interfaces() 1589 { 1590 RecursiveLocker locker(sLock); 1591 1592 return sInterfaces.Count(); 1593 } 1594 1595 1596 /*! Dumps a list of all interfaces into the supplied userland buffer. 1597 If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is 1598 returned. 1599 */ 1600 status_t 1601 list_interfaces(int family, void* _buffer, size_t* bufferSize) 1602 { 1603 RecursiveLocker locker(sLock); 1604 1605 UserBuffer buffer(_buffer, *bufferSize); 1606 1607 InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1608 while (Interface* interface = iterator.Next()) { 1609 // Copy name 1610 buffer.Push(interface->name, IF_NAMESIZE); 1611 1612 // Copy address 1613 InterfaceAddress* address = interface->FirstForFamily(family); 1614 size_t length = 0; 1615 1616 if (address != NULL && address->local != NULL) { 1617 // Actual address 1618 buffer.Push(address->local, length = address->local->sa_len); 1619 } else { 1620 // Empty address 1621 sockaddr empty; 1622 empty.sa_len = 2; 1623 empty.sa_family = AF_UNSPEC; 1624 buffer.Push(&empty, length = empty.sa_len); 1625 } 1626 1627 if (address != NULL) 1628 address->ReleaseReference(); 1629 1630 if (IF_NAMESIZE + length < sizeof(ifreq)) { 1631 // Make sure at least sizeof(ifreq) bytes are written for each 1632 // interface for compatibility with other platforms 1633 buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length); 1634 } 1635 1636 if (buffer.Status() != B_OK) 1637 return buffer.Status(); 1638 } 1639 1640 *bufferSize = buffer.BytesConsumed(); 1641 return B_OK; 1642 } 1643 1644 1645 // #pragma mark - 1646 1647 1648 status_t 1649 init_interfaces() 1650 { 1651 recursive_lock_init(&sLock, "net interfaces"); 1652 mutex_init(&sHashLock, "net local addresses"); 1653 1654 new (&sInterfaces) InterfaceList; 1655 new (&sAddressTable) AddressTable; 1656 // static C++ objects are not initialized in the module startup 1657 1658 #if ENABLE_DEBUGGER_COMMANDS 1659 add_debugger_command("net_interface", &dump_interface, 1660 "Dump the given network interface"); 1661 add_debugger_command("net_interfaces", &dump_interfaces, 1662 "Dump all network interfaces"); 1663 add_debugger_command("net_local", &dump_local, 1664 "Dump all local interface addresses"); 1665 add_debugger_command("net_route", &dump_route, 1666 "Dump the given network route"); 1667 #endif 1668 return B_OK; 1669 } 1670 1671 1672 status_t 1673 uninit_interfaces() 1674 { 1675 #if ENABLE_DEBUGGER_COMMANDS 1676 remove_debugger_command("net_interface", &dump_interface); 1677 remove_debugger_command("net_interfaces", &dump_interfaces); 1678 remove_debugger_command("net_local", &dump_local); 1679 remove_debugger_command("net_route", &dump_route); 1680 #endif 1681 1682 recursive_lock_destroy(&sLock); 1683 mutex_destroy(&sHashLock); 1684 return B_OK; 1685 } 1686 1687