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