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