1 /* 2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Oliver Tappe, zooey@hirschkaefer.de 7 * Hugo Santos, hugosantos@gmail.com 8 */ 9 10 11 #include <net_buffer.h> 12 #include <net_datalink.h> 13 #include <net_protocol.h> 14 #include <net_stack.h> 15 16 #include <lock.h> 17 #include <util/AutoLock.h> 18 #include <util/DoublyLinkedList.h> 19 #include <util/OpenHashTable.h> 20 21 #include <KernelExport.h> 22 23 #include <NetBufferUtilities.h> 24 #include <NetUtilities.h> 25 #include <ProtocolUtilities.h> 26 27 #include <algorithm> 28 #include <netinet/in.h> 29 #include <netinet/ip.h> 30 #include <new> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <utility> 34 35 36 // NOTE the locking protocol dictates that we must hold UdpDomainSupport's 37 // lock before holding a child UdpEndpoint's lock. This restriction 38 // is dictated by the receive path as blind access to the endpoint 39 // hash is required when holding the DomainSupport's lock. 40 41 42 //#define TRACE_UDP 43 #ifdef TRACE_UDP 44 # define TRACE_BLOCK(x) dump_block x 45 // do not remove the space before ', ##args' if you want this 46 // to compile with gcc 2.95 47 # define TRACE_EP(format, args...) dprintf("UDP [%llu] %p " format "\n", \ 48 system_time(), this , ##args) 49 # define TRACE_EPM(format, args...) dprintf("UDP [%llu] " format "\n", \ 50 system_time() , ##args) 51 # define TRACE_DOMAIN(format, args...) dprintf("UDP [%llu] (%d) " format \ 52 "\n", system_time(), Domain()->family , ##args) 53 #else 54 # define TRACE_BLOCK(x) 55 # define TRACE_EP(args...) do { } while (0) 56 # define TRACE_EPM(args...) do { } while (0) 57 # define TRACE_DOMAIN(args...) do { } while (0) 58 #endif 59 60 61 struct udp_header { 62 uint16 source_port; 63 uint16 destination_port; 64 uint16 udp_length; 65 uint16 udp_checksum; 66 } _PACKED; 67 68 69 typedef NetBufferField<uint16, offsetof(udp_header, udp_checksum)> 70 UDPChecksumField; 71 72 class UdpDomainSupport; 73 74 class UdpEndpoint : public net_protocol, public DatagramSocket<> { 75 public: 76 UdpEndpoint(net_socket* socket); 77 78 status_t Bind(const sockaddr* newAddr); 79 status_t Unbind(sockaddr* newAddr); 80 status_t Connect(const sockaddr* newAddr); 81 82 status_t Open(); 83 status_t Close(); 84 status_t Free(); 85 86 status_t SendRoutedData(net_buffer* buffer, 87 net_route* route); 88 status_t SendData(net_buffer* buffer); 89 90 ssize_t BytesAvailable(); 91 status_t FetchData(size_t numBytes, uint32 flags, 92 net_buffer** _buffer); 93 94 status_t StoreData(net_buffer* buffer); 95 status_t DeliverData(net_buffer* buffer); 96 97 // only the domain support will change/check the Active flag so 98 // we don't really need to protect it with the socket lock. 99 bool IsActive() const { return fActive; } 100 void SetActive(bool newValue) { fActive = newValue; } 101 102 UdpEndpoint*& HashTableLink() { return fLink; } 103 104 void Dump() const; 105 106 private: 107 UdpDomainSupport* fManager; 108 bool fActive; 109 // an active UdpEndpoint is part of the 110 // endpoint hash (and it is bound and 111 // optionally connected) 112 113 UdpEndpoint* fLink; 114 }; 115 116 117 class UdpDomainSupport; 118 119 struct UdpHashDefinition { 120 typedef net_address_module_info ParentType; 121 typedef std::pair<const sockaddr *, const sockaddr *> KeyType; 122 typedef UdpEndpoint ValueType; 123 124 UdpHashDefinition(net_address_module_info *_module) 125 : module(_module) {} 126 UdpHashDefinition(const UdpHashDefinition& definition) 127 : module(definition.module) {} 128 129 size_t HashKey(const KeyType &key) const 130 { 131 return _Mix(module->hash_address_pair(key.first, key.second)); 132 } 133 134 size_t Hash(UdpEndpoint *endpoint) const 135 { 136 return _Mix(endpoint->LocalAddress().HashPair( 137 *endpoint->PeerAddress())); 138 } 139 140 static size_t _Mix(size_t hash) 141 { 142 // move the bits into the relevant range (as defined by kNumHashBuckets) 143 return (hash & 0x000007FF) ^ (hash & 0x003FF800) >> 11 144 ^ (hash & 0xFFC00000UL) >> 22; 145 } 146 147 bool Compare(const KeyType &key, UdpEndpoint *endpoint) const 148 { 149 return endpoint->LocalAddress().EqualTo(key.first, true) 150 && endpoint->PeerAddress().EqualTo(key.second, true); 151 } 152 153 UdpEndpoint *&GetLink(UdpEndpoint *endpoint) const 154 { 155 return endpoint->HashTableLink(); 156 } 157 158 net_address_module_info *module; 159 }; 160 161 162 class UdpDomainSupport : public DoublyLinkedListLinkImpl<UdpDomainSupport> { 163 public: 164 UdpDomainSupport(net_domain *domain); 165 ~UdpDomainSupport(); 166 167 status_t Init(); 168 169 net_domain *Domain() const { return fDomain; } 170 171 void Ref() { fEndpointCount++; } 172 bool Put() { fEndpointCount--; return fEndpointCount == 0; } 173 174 status_t DemuxIncomingBuffer(net_buffer* buffer); 175 status_t DeliverError(status_t error, net_buffer* buffer); 176 177 status_t BindEndpoint(UdpEndpoint *endpoint, const sockaddr *address); 178 status_t ConnectEndpoint(UdpEndpoint *endpoint, const sockaddr *address); 179 status_t UnbindEndpoint(UdpEndpoint *endpoint); 180 181 void DumpEndpoints() const; 182 183 private: 184 status_t _BindEndpoint(UdpEndpoint *endpoint, const sockaddr *address); 185 status_t _Bind(UdpEndpoint *endpoint, const sockaddr *address); 186 status_t _BindToEphemeral(UdpEndpoint *endpoint, const sockaddr *address); 187 status_t _FinishBind(UdpEndpoint *endpoint, const sockaddr *address); 188 189 UdpEndpoint *_FindActiveEndpoint(const sockaddr *ourAddress, 190 const sockaddr *peerAddress, uint32 index = 0); 191 status_t _DemuxBroadcast(net_buffer *buffer); 192 status_t _DemuxUnicast(net_buffer *buffer); 193 194 uint16 _GetNextEphemeral(); 195 UdpEndpoint *_EndpointWithPort(uint16 port) const; 196 197 net_address_module_info *AddressModule() const 198 { return fDomain->address_module; } 199 200 typedef BOpenHashTable<UdpHashDefinition, false> EndpointTable; 201 202 mutex fLock; 203 net_domain *fDomain; 204 uint16 fLastUsedEphemeral; 205 EndpointTable fActiveEndpoints; 206 uint32 fEndpointCount; 207 208 static const uint16 kFirst = 49152; 209 static const uint16 kLast = 65535; 210 static const uint32 kNumHashBuckets = 0x800; 211 // if you change this, adjust the shifting in 212 // Hash() accordingly! 213 }; 214 215 216 typedef DoublyLinkedList<UdpDomainSupport> UdpDomainList; 217 218 219 class UdpEndpointManager { 220 public: 221 UdpEndpointManager(); 222 ~UdpEndpointManager(); 223 224 status_t InitCheck() const; 225 226 status_t ReceiveData(net_buffer* buffer); 227 status_t ReceiveError(status_t error, 228 net_buffer* buffer); 229 status_t Deframe(net_buffer* buffer); 230 231 UdpDomainSupport* OpenEndpoint(UdpEndpoint* endpoint); 232 status_t FreeEndpoint(UdpDomainSupport* domain); 233 234 static int DumpEndpoints(int argc, char *argv[]); 235 236 private: 237 inline net_domain* _GetDomain(net_buffer* buffer); 238 UdpDomainSupport* _GetDomainSupport(net_domain* domain, 239 bool create); 240 UdpDomainSupport* _GetDomainSupport(net_buffer* buffer); 241 242 mutex fLock; 243 status_t fStatus; 244 UdpDomainList fDomains; 245 }; 246 247 248 static UdpEndpointManager *sUdpEndpointManager; 249 250 net_buffer_module_info *gBufferModule; 251 net_datalink_module_info *gDatalinkModule; 252 net_stack_module_info *gStackModule; 253 net_socket_module_info *gSocketModule; 254 255 256 // #pragma mark - 257 258 259 UdpDomainSupport::UdpDomainSupport(net_domain *domain) 260 : 261 fDomain(domain), 262 fActiveEndpoints(domain->address_module), 263 fEndpointCount(0) 264 { 265 mutex_init(&fLock, "udp domain"); 266 267 fLastUsedEphemeral = kFirst + rand() % (kLast - kFirst); 268 } 269 270 271 UdpDomainSupport::~UdpDomainSupport() 272 { 273 mutex_destroy(&fLock); 274 } 275 276 277 status_t 278 UdpDomainSupport::Init() 279 { 280 return fActiveEndpoints.Init(kNumHashBuckets); 281 } 282 283 284 status_t 285 UdpDomainSupport::DemuxIncomingBuffer(net_buffer *buffer) 286 { 287 // NOTE: multicast is delivered directly to the endpoint 288 MutexLocker _(fLock); 289 290 if ((buffer->flags & MSG_BCAST) != 0) 291 return _DemuxBroadcast(buffer); 292 if ((buffer->flags & MSG_MCAST) != 0) 293 return B_ERROR; 294 295 return _DemuxUnicast(buffer); 296 } 297 298 299 status_t 300 UdpDomainSupport::DeliverError(status_t error, net_buffer* buffer) 301 { 302 if ((buffer->flags & (MSG_BCAST | MSG_MCAST)) != 0) 303 return B_ERROR; 304 305 MutexLocker _(fLock); 306 307 // Forward the error to the socket 308 UdpEndpoint* endpoint = _FindActiveEndpoint(buffer->source, 309 buffer->destination); 310 if (endpoint != NULL) { 311 gSocketModule->notify(endpoint->Socket(), B_SELECT_ERROR, error); 312 endpoint->NotifyOne(); 313 } 314 315 gBufferModule->free(buffer); 316 return B_OK; 317 } 318 319 320 status_t 321 UdpDomainSupport::BindEndpoint(UdpEndpoint *endpoint, 322 const sockaddr *address) 323 { 324 if (!AddressModule()->is_same_family(address)) 325 return EAFNOSUPPORT; 326 327 MutexLocker _(fLock); 328 329 if (endpoint->IsActive()) 330 return EINVAL; 331 332 return _BindEndpoint(endpoint, address); 333 } 334 335 336 status_t 337 UdpDomainSupport::ConnectEndpoint(UdpEndpoint *endpoint, 338 const sockaddr *address) 339 { 340 MutexLocker _(fLock); 341 342 if (endpoint->IsActive()) { 343 fActiveEndpoints.Remove(endpoint); 344 endpoint->SetActive(false); 345 } 346 347 if (address->sa_family == AF_UNSPEC) { 348 // [Stevens-UNP1, p226]: specifying AF_UNSPEC requests a "disconnect", 349 // so we reset the peer address: 350 endpoint->PeerAddress().SetToEmpty(); 351 } else { 352 if (!AddressModule()->is_same_family(address)) 353 return EAFNOSUPPORT; 354 355 // consider destination address INADDR_ANY as INADDR_LOOPBACK 356 sockaddr_storage _address; 357 if (AddressModule()->is_empty_address(address, false)) { 358 AddressModule()->get_loopback_address((sockaddr *)&_address); 359 // for IPv4 and IPv6 the port is at the same offset 360 ((sockaddr_in&)_address).sin_port 361 = ((sockaddr_in *)address)->sin_port; 362 address = (sockaddr *)&_address; 363 } 364 365 status_t status = endpoint->PeerAddress().SetTo(address); 366 if (status < B_OK) 367 return status; 368 struct net_route *routeToDestination 369 = gDatalinkModule->get_route(fDomain, address); 370 if (routeToDestination) { 371 // stay bound to current local port, if any. 372 uint16 port = endpoint->LocalAddress().Port(); 373 status = endpoint->LocalAddress().SetTo( 374 routeToDestination->interface_address->local); 375 endpoint->LocalAddress().SetPort(port); 376 gDatalinkModule->put_route(fDomain, routeToDestination); 377 if (status < B_OK) 378 return status; 379 } 380 } 381 382 // we need to activate no matter whether or not we have just disconnected, 383 // as calling connect() always triggers an implicit bind(): 384 return _BindEndpoint(endpoint, *endpoint->LocalAddress()); 385 } 386 387 388 status_t 389 UdpDomainSupport::UnbindEndpoint(UdpEndpoint *endpoint) 390 { 391 MutexLocker _(fLock); 392 393 if (endpoint->IsActive()) 394 fActiveEndpoints.Remove(endpoint); 395 396 endpoint->SetActive(false); 397 398 return B_OK; 399 } 400 401 402 void 403 UdpDomainSupport::DumpEndpoints() const 404 { 405 kprintf("-------- UDP Domain %p ---------\n", this); 406 kprintf("%10s %20s %20s %8s\n", "address", "local", "peer", "recv-q"); 407 408 EndpointTable::Iterator it = fActiveEndpoints.GetIterator(); 409 410 while (UdpEndpoint* endpoint = it.Next()) { 411 endpoint->Dump(); 412 } 413 } 414 415 416 status_t 417 UdpDomainSupport::_BindEndpoint(UdpEndpoint *endpoint, 418 const sockaddr *address) 419 { 420 if (AddressModule()->get_port(address) == 0) 421 return _BindToEphemeral(endpoint, address); 422 423 return _Bind(endpoint, address); 424 } 425 426 427 status_t 428 UdpDomainSupport::_Bind(UdpEndpoint *endpoint, const sockaddr *address) 429 { 430 int socketOptions = endpoint->Socket()->options; 431 432 EndpointTable::Iterator it = fActiveEndpoints.GetIterator(); 433 434 // Iterate over all active UDP-endpoints and check if the requested bind 435 // is allowed (see figure 22.24 in [Stevens - TCP2, p735]): 436 TRACE_DOMAIN("CheckBindRequest() for %s...", AddressString(fDomain, 437 address, true).Data()); 438 439 while (it.HasNext()) { 440 UdpEndpoint *otherEndpoint = it.Next(); 441 442 TRACE_DOMAIN(" ...checking endpoint %p (port=%u)...", otherEndpoint, 443 ntohs(otherEndpoint->LocalAddress().Port())); 444 445 if (otherEndpoint->LocalAddress().EqualPorts(address)) { 446 // port is already bound, SO_REUSEADDR or SO_REUSEPORT is required: 447 if ((otherEndpoint->Socket()->options 448 & (SO_REUSEADDR | SO_REUSEPORT)) == 0 449 || (socketOptions & (SO_REUSEADDR | SO_REUSEPORT)) == 0) 450 return EADDRINUSE; 451 452 // if both addresses are the same, SO_REUSEPORT is required: 453 if (otherEndpoint->LocalAddress().EqualTo(address, false) 454 && ((otherEndpoint->Socket()->options & SO_REUSEPORT) == 0 455 || (socketOptions & SO_REUSEPORT) == 0)) 456 return EADDRINUSE; 457 } 458 } 459 460 return _FinishBind(endpoint, address); 461 } 462 463 464 status_t 465 UdpDomainSupport::_BindToEphemeral(UdpEndpoint *endpoint, 466 const sockaddr *address) 467 { 468 SocketAddressStorage newAddress(AddressModule()); 469 status_t status = newAddress.SetTo(address); 470 if (status < B_OK) 471 return status; 472 473 uint16 allocedPort = _GetNextEphemeral(); 474 if (allocedPort == 0) 475 return ENOBUFS; 476 477 newAddress.SetPort(htons(allocedPort)); 478 479 return _FinishBind(endpoint, *newAddress); 480 } 481 482 483 status_t 484 UdpDomainSupport::_FinishBind(UdpEndpoint *endpoint, const sockaddr *address) 485 { 486 status_t status = endpoint->next->module->bind(endpoint->next, address); 487 if (status < B_OK) 488 return status; 489 490 fActiveEndpoints.Insert(endpoint); 491 endpoint->SetActive(true); 492 493 return B_OK; 494 } 495 496 497 UdpEndpoint * 498 UdpDomainSupport::_FindActiveEndpoint(const sockaddr *ourAddress, 499 const sockaddr *peerAddress, uint32 index) 500 { 501 ASSERT_LOCKED_MUTEX(&fLock); 502 503 TRACE_DOMAIN("finding Endpoint for %s <- %s", 504 AddressString(fDomain, ourAddress, true).Data(), 505 AddressString(fDomain, peerAddress, true).Data()); 506 507 UdpEndpoint* endpoint = fActiveEndpoints.Lookup( 508 std::make_pair(ourAddress, peerAddress)); 509 510 // Make sure the bound_to_device constraint is fulfilled 511 while (endpoint != NULL && endpoint->socket->bound_to_device != 0 512 && index != 0 && endpoint->socket->bound_to_device != index) { 513 endpoint = endpoint->HashTableLink(); 514 if (endpoint != NULL 515 && (!endpoint->LocalAddress().EqualTo(ourAddress, true) 516 || !endpoint->PeerAddress().EqualTo(peerAddress, true))) 517 return NULL; 518 } 519 520 return endpoint; 521 } 522 523 524 status_t 525 UdpDomainSupport::_DemuxBroadcast(net_buffer* buffer) 526 { 527 sockaddr* peerAddr = buffer->source; 528 sockaddr* broadcastAddr = buffer->destination; 529 uint16 incomingPort = AddressModule()->get_port(broadcastAddr); 530 531 sockaddr* mask = NULL; 532 if (buffer->interface_address != NULL) 533 mask = (sockaddr*)buffer->interface_address->mask; 534 535 TRACE_DOMAIN("_DemuxBroadcast(%p): mask %p\n", buffer, mask); 536 537 EndpointTable::Iterator iterator = fActiveEndpoints.GetIterator(); 538 539 while (UdpEndpoint* endpoint = iterator.Next()) { 540 TRACE_DOMAIN(" _DemuxBroadcast(): checking endpoint %s...", 541 AddressString(fDomain, *endpoint->LocalAddress(), true).Data()); 542 543 if (endpoint->socket->bound_to_device != 0 544 && buffer->index != endpoint->socket->bound_to_device) 545 continue; 546 547 if (endpoint->LocalAddress().Port() != incomingPort) { 548 // ports don't match, so we do not dispatch to this endpoint... 549 continue; 550 } 551 552 if (!endpoint->PeerAddress().IsEmpty(true)) { 553 // endpoint is connected to a specific destination, we check if 554 // this datagram is from there: 555 if (!endpoint->PeerAddress().EqualTo(peerAddr, true)) { 556 // no, datagram is from another peer, so we do not dispatch to 557 // this endpoint... 558 continue; 559 } 560 } 561 562 if (endpoint->LocalAddress().MatchMasked(broadcastAddr, mask) 563 || mask == NULL || endpoint->LocalAddress().IsEmpty(false)) { 564 // address matches, dispatch to this endpoint: 565 endpoint->StoreData(buffer); 566 } 567 } 568 569 return B_OK; 570 } 571 572 573 status_t 574 UdpDomainSupport::_DemuxUnicast(net_buffer* buffer) 575 { 576 TRACE_DOMAIN("_DemuxUnicast(%p)", buffer); 577 578 const sockaddr* localAddress = buffer->destination; 579 const sockaddr* peerAddress = buffer->source; 580 581 // look for full (most special) match: 582 UdpEndpoint* endpoint = _FindActiveEndpoint(localAddress, peerAddress, 583 buffer->index); 584 if (endpoint == NULL) { 585 // look for endpoint matching local address & port: 586 endpoint = _FindActiveEndpoint(localAddress, NULL, buffer->index); 587 if (endpoint == NULL) { 588 // look for endpoint matching peer address & port and local port: 589 SocketAddressStorage local(AddressModule()); 590 local.SetToEmpty(); 591 local.SetPort(AddressModule()->get_port(localAddress)); 592 endpoint = _FindActiveEndpoint(*local, peerAddress, buffer->index); 593 if (endpoint == NULL) { 594 // last chance: look for endpoint matching local port only: 595 endpoint = _FindActiveEndpoint(*local, NULL, buffer->index); 596 } 597 } 598 } 599 600 if (endpoint == NULL) { 601 TRACE_DOMAIN("_DemuxUnicast(%p) - no matching endpoint found!", buffer); 602 return B_NAME_NOT_FOUND; 603 } 604 605 endpoint->StoreData(buffer); 606 return B_OK; 607 } 608 609 610 uint16 611 UdpDomainSupport::_GetNextEphemeral() 612 { 613 uint16 stop, curr; 614 if (fLastUsedEphemeral < kLast) { 615 stop = fLastUsedEphemeral; 616 curr = fLastUsedEphemeral + 1; 617 } else { 618 stop = kLast; 619 curr = kFirst; 620 } 621 622 TRACE_DOMAIN("_GetNextEphemeral(), last %hu, curr %hu, stop %hu", 623 fLastUsedEphemeral, curr, stop); 624 625 // TODO: a free list could be used to avoid the impact of these two 626 // nested loops most of the time... let's see how bad this really is 627 for (; curr != stop; curr = (curr < kLast) ? (curr + 1) : kFirst) { 628 TRACE_DOMAIN(" _GetNextEphemeral(): trying port %hu...", curr); 629 630 if (_EndpointWithPort(htons(curr)) == NULL) { 631 TRACE_DOMAIN(" _GetNextEphemeral(): ...using port %hu", curr); 632 fLastUsedEphemeral = curr; 633 return curr; 634 } 635 } 636 637 return 0; 638 } 639 640 641 UdpEndpoint * 642 UdpDomainSupport::_EndpointWithPort(uint16 port) const 643 { 644 EndpointTable::Iterator it = fActiveEndpoints.GetIterator(); 645 646 while (it.HasNext()) { 647 UdpEndpoint *endpoint = it.Next(); 648 if (endpoint->LocalAddress().Port() == port) 649 return endpoint; 650 } 651 652 return NULL; 653 } 654 655 656 // #pragma mark - 657 658 659 UdpEndpointManager::UdpEndpointManager() 660 { 661 mutex_init(&fLock, "UDP endpoints"); 662 fStatus = B_OK; 663 } 664 665 666 UdpEndpointManager::~UdpEndpointManager() 667 { 668 mutex_destroy(&fLock); 669 } 670 671 672 status_t 673 UdpEndpointManager::InitCheck() const 674 { 675 return fStatus; 676 } 677 678 679 int 680 UdpEndpointManager::DumpEndpoints(int argc, char *argv[]) 681 { 682 UdpDomainList::Iterator it = sUdpEndpointManager->fDomains.GetIterator(); 683 684 while (it.HasNext()) 685 it.Next()->DumpEndpoints(); 686 687 return 0; 688 } 689 690 691 // #pragma mark - inbound 692 693 694 status_t 695 UdpEndpointManager::ReceiveData(net_buffer *buffer) 696 { 697 TRACE_EPM("ReceiveData(%p [%" B_PRIu32 " bytes])", buffer, buffer->size); 698 699 UdpDomainSupport* domainSupport = _GetDomainSupport(buffer); 700 if (domainSupport == NULL) { 701 // we don't instantiate domain supports in the receiving path, as 702 // we are only interested in delivering data to existing sockets. 703 return B_ERROR; 704 } 705 706 status_t status = Deframe(buffer); 707 if (status != B_OK) 708 return status; 709 710 status = domainSupport->DemuxIncomingBuffer(buffer); 711 if (status != B_OK) { 712 TRACE_EPM(" ReceiveData(): no endpoint."); 713 // Send port unreachable error 714 domainSupport->Domain()->module->error_reply(NULL, buffer, 715 B_NET_ERROR_UNREACH_PORT, NULL); 716 return B_ERROR; 717 } 718 719 gBufferModule->free(buffer); 720 return B_OK; 721 } 722 723 724 status_t 725 UdpEndpointManager::ReceiveError(status_t error, net_buffer* buffer) 726 { 727 TRACE_EPM("ReceiveError(code %" B_PRId32 " %p [%" B_PRIu32 " bytes])", 728 error, buffer, buffer->size); 729 730 // We only really need the port information 731 if (buffer->size < 4) 732 return B_BAD_VALUE; 733 734 UdpDomainSupport* domainSupport = _GetDomainSupport(buffer); 735 if (domainSupport == NULL) { 736 // we don't instantiate domain supports in the receiving path, as 737 // we are only interested in delivering data to existing sockets. 738 return B_ERROR; 739 } 740 741 // Deframe the buffer manually, as we usually only get 8 bytes from the 742 // original packet 743 udp_header header; 744 if (gBufferModule->read(buffer, 0, &header, 745 std::min((size_t)buffer->size, sizeof(udp_header))) != B_OK) 746 return B_BAD_VALUE; 747 748 net_domain* domain = buffer->interface_address->domain; 749 net_address_module_info* addressModule = domain->address_module; 750 751 SocketAddress source(addressModule, buffer->source); 752 SocketAddress destination(addressModule, buffer->destination); 753 754 source.SetPort(header.source_port); 755 destination.SetPort(header.destination_port); 756 757 return domainSupport->DeliverError(error, buffer); 758 } 759 760 761 status_t 762 UdpEndpointManager::Deframe(net_buffer* buffer) 763 { 764 TRACE_EPM("Deframe(%p [%ld bytes])", buffer, buffer->size); 765 766 NetBufferHeaderReader<udp_header> bufferHeader(buffer); 767 if (bufferHeader.Status() != B_OK) 768 return bufferHeader.Status(); 769 770 udp_header& header = bufferHeader.Data(); 771 772 net_domain* domain = _GetDomain(buffer); 773 if (domain == NULL) { 774 TRACE_EPM(" Deframe(): UDP packed dropped as there was no domain " 775 "specified (interface address %p).", buffer->interface_address); 776 return B_BAD_VALUE; 777 } 778 net_address_module_info* addressModule = domain->address_module; 779 780 SocketAddress source(addressModule, buffer->source); 781 SocketAddress destination(addressModule, buffer->destination); 782 783 source.SetPort(header.source_port); 784 destination.SetPort(header.destination_port); 785 786 TRACE_EPM(" Deframe(): data from %s to %s", source.AsString(true).Data(), 787 destination.AsString(true).Data()); 788 789 uint16 udpLength = ntohs(header.udp_length); 790 if (udpLength > buffer->size) { 791 TRACE_EPM(" Deframe(): buffer is too short, expected %hu.", 792 udpLength); 793 return B_MISMATCHED_VALUES; 794 } 795 796 if (buffer->size > udpLength) 797 gBufferModule->trim(buffer, udpLength); 798 799 if (header.udp_checksum != 0) { 800 // check UDP-checksum (simulating a so-called "pseudo-header"): 801 uint16 sum = Checksum::PseudoHeader(addressModule, gBufferModule, 802 buffer, IPPROTO_UDP); 803 if (sum != 0) { 804 TRACE_EPM(" Deframe(): bad checksum 0x%hx.", sum); 805 return B_BAD_VALUE; 806 } 807 } 808 809 bufferHeader.Remove(); 810 // remove UDP-header from buffer before passing it on 811 812 return B_OK; 813 } 814 815 816 UdpDomainSupport * 817 UdpEndpointManager::OpenEndpoint(UdpEndpoint *endpoint) 818 { 819 MutexLocker _(fLock); 820 821 UdpDomainSupport* domain = _GetDomainSupport(endpoint->Domain(), true); 822 if (domain) 823 domain->Ref(); 824 return domain; 825 } 826 827 828 status_t 829 UdpEndpointManager::FreeEndpoint(UdpDomainSupport *domain) 830 { 831 MutexLocker _(fLock); 832 833 if (domain->Put()) { 834 fDomains.Remove(domain); 835 delete domain; 836 } 837 838 return B_OK; 839 } 840 841 842 // #pragma mark - 843 844 845 inline net_domain* 846 UdpEndpointManager::_GetDomain(net_buffer* buffer) 847 { 848 if (buffer->interface_address != NULL) 849 return buffer->interface_address->domain; 850 851 return gStackModule->get_domain(buffer->destination->sa_family); 852 } 853 854 855 UdpDomainSupport* 856 UdpEndpointManager::_GetDomainSupport(net_domain* domain, bool create) 857 { 858 ASSERT_LOCKED_MUTEX(&fLock); 859 860 if (domain == NULL) 861 return NULL; 862 863 // TODO convert this into a Hashtable or install per-domain 864 // receiver handlers that forward the requests to the 865 // appropriate DemuxIncomingBuffer(). For instance, while 866 // being constructed UdpDomainSupport could call 867 // register_domain_receiving_protocol() with the right 868 // family. 869 UdpDomainList::Iterator iterator = fDomains.GetIterator(); 870 while (UdpDomainSupport* domainSupport = iterator.Next()) { 871 if (domainSupport->Domain() == domain) 872 return domainSupport; 873 } 874 875 if (!create) 876 return NULL; 877 878 UdpDomainSupport* domainSupport 879 = new (std::nothrow) UdpDomainSupport(domain); 880 if (domainSupport == NULL || domainSupport->Init() < B_OK) { 881 delete domainSupport; 882 return NULL; 883 } 884 885 fDomains.Add(domainSupport); 886 return domainSupport; 887 } 888 889 890 /*! Retrieves the UdpDomainSupport object responsible for this buffer, if the 891 domain can be determined. This is only successful if the domain support is 892 already existing, ie. there must already be an endpoint for the domain. 893 */ 894 UdpDomainSupport* 895 UdpEndpointManager::_GetDomainSupport(net_buffer* buffer) 896 { 897 MutexLocker _(fLock); 898 899 return _GetDomainSupport(_GetDomain(buffer), false); 900 // TODO: we don't want to hold to the manager's lock during the 901 // whole RX path, we may not hold an endpoint's lock with the 902 // manager lock held. 903 // But we should increase the domain's refcount here. 904 } 905 906 907 // #pragma mark - 908 909 910 UdpEndpoint::UdpEndpoint(net_socket *socket) 911 : 912 DatagramSocket<>("udp endpoint", socket), 913 fActive(false) 914 { 915 } 916 917 918 // #pragma mark - activation 919 920 921 status_t 922 UdpEndpoint::Bind(const sockaddr *address) 923 { 924 TRACE_EP("Bind(%s)", AddressString(Domain(), address, true).Data()); 925 return fManager->BindEndpoint(this, address); 926 } 927 928 929 status_t 930 UdpEndpoint::Unbind(sockaddr *address) 931 { 932 TRACE_EP("Unbind()"); 933 return fManager->UnbindEndpoint(this); 934 } 935 936 937 status_t 938 UdpEndpoint::Connect(const sockaddr *address) 939 { 940 TRACE_EP("Connect(%s)", AddressString(Domain(), address, true).Data()); 941 return fManager->ConnectEndpoint(this, address); 942 } 943 944 945 status_t 946 UdpEndpoint::Open() 947 { 948 TRACE_EP("Open()"); 949 950 AutoLocker _(fLock); 951 952 status_t status = ProtocolSocket::Open(); 953 if (status < B_OK) 954 return status; 955 956 fManager = sUdpEndpointManager->OpenEndpoint(this); 957 if (fManager == NULL) 958 return EAFNOSUPPORT; 959 960 return B_OK; 961 } 962 963 964 status_t 965 UdpEndpoint::Close() 966 { 967 TRACE_EP("Close()"); 968 fSocket->error = EBADF; 969 WakeAll(); 970 return B_OK; 971 } 972 973 974 status_t 975 UdpEndpoint::Free() 976 { 977 TRACE_EP("Free()"); 978 fManager->UnbindEndpoint(this); 979 return sUdpEndpointManager->FreeEndpoint(fManager); 980 } 981 982 983 // #pragma mark - outbound 984 985 986 status_t 987 UdpEndpoint::SendRoutedData(net_buffer *buffer, net_route *route) 988 { 989 TRACE_EP("SendRoutedData(%p [%lu bytes], %p)", buffer, buffer->size, route); 990 991 if (buffer->size > (0xffff - sizeof(udp_header))) 992 return EMSGSIZE; 993 994 buffer->protocol = IPPROTO_UDP; 995 996 // add and fill UDP-specific header: 997 NetBufferPrepend<udp_header> header(buffer); 998 if (header.Status() < B_OK) 999 return header.Status(); 1000 1001 header->source_port = AddressModule()->get_port(buffer->source); 1002 header->destination_port = AddressModule()->get_port(buffer->destination); 1003 header->udp_length = htons(buffer->size); 1004 // the udp-header is already included in the buffer-size 1005 header->udp_checksum = 0; 1006 1007 header.Sync(); 1008 1009 uint16 calculatedChecksum = Checksum::PseudoHeader(AddressModule(), 1010 gBufferModule, buffer, IPPROTO_UDP); 1011 if (calculatedChecksum == 0) 1012 calculatedChecksum = 0xffff; 1013 1014 *UDPChecksumField(buffer) = calculatedChecksum; 1015 1016 return next->module->send_routed_data(next, route, buffer); 1017 } 1018 1019 1020 status_t 1021 UdpEndpoint::SendData(net_buffer *buffer) 1022 { 1023 TRACE_EP("SendData(%p [%lu bytes])", buffer, buffer->size); 1024 1025 return gDatalinkModule->send_data(this, NULL, buffer); 1026 } 1027 1028 1029 // #pragma mark - inbound 1030 1031 1032 ssize_t 1033 UdpEndpoint::BytesAvailable() 1034 { 1035 size_t bytes = AvailableData(); 1036 TRACE_EP("BytesAvailable(): %lu", bytes); 1037 return bytes; 1038 } 1039 1040 1041 status_t 1042 UdpEndpoint::FetchData(size_t numBytes, uint32 flags, net_buffer **_buffer) 1043 { 1044 TRACE_EP("FetchData(%ld, 0x%lx)", numBytes, flags); 1045 1046 status_t status = Dequeue(flags, _buffer); 1047 TRACE_EP(" FetchData(): returned from fifo status: %s", strerror(status)); 1048 if (status != B_OK) 1049 return status; 1050 1051 TRACE_EP(" FetchData(): returns buffer with %ld bytes", (*_buffer)->size); 1052 return B_OK; 1053 } 1054 1055 1056 status_t 1057 UdpEndpoint::StoreData(net_buffer *buffer) 1058 { 1059 TRACE_EP("StoreData(%p [%ld bytes])", buffer, buffer->size); 1060 1061 return EnqueueClone(buffer); 1062 } 1063 1064 1065 status_t 1066 UdpEndpoint::DeliverData(net_buffer *_buffer) 1067 { 1068 TRACE_EP("DeliverData(%p [%ld bytes])", _buffer, _buffer->size); 1069 1070 net_buffer *buffer = gBufferModule->clone(_buffer, false); 1071 if (buffer == NULL) 1072 return B_NO_MEMORY; 1073 1074 status_t status = sUdpEndpointManager->Deframe(buffer); 1075 if (status < B_OK) { 1076 gBufferModule->free(buffer); 1077 return status; 1078 } 1079 1080 return Enqueue(buffer); 1081 } 1082 1083 1084 void 1085 UdpEndpoint::Dump() const 1086 { 1087 char local[64]; 1088 LocalAddress().AsString(local, sizeof(local), true); 1089 char peer[64]; 1090 PeerAddress().AsString(peer, sizeof(peer), true); 1091 1092 kprintf("%p %20s %20s %8lu\n", this, local, peer, fCurrentBytes); 1093 } 1094 1095 1096 // #pragma mark - protocol interface 1097 1098 1099 net_protocol * 1100 udp_init_protocol(net_socket *socket) 1101 { 1102 socket->protocol = IPPROTO_UDP; 1103 1104 UdpEndpoint *endpoint = new (std::nothrow) UdpEndpoint(socket); 1105 if (endpoint == NULL || endpoint->InitCheck() < B_OK) { 1106 delete endpoint; 1107 return NULL; 1108 } 1109 1110 return endpoint; 1111 } 1112 1113 1114 status_t 1115 udp_uninit_protocol(net_protocol *protocol) 1116 { 1117 delete (UdpEndpoint *)protocol; 1118 return B_OK; 1119 } 1120 1121 1122 status_t 1123 udp_open(net_protocol *protocol) 1124 { 1125 return ((UdpEndpoint *)protocol)->Open(); 1126 } 1127 1128 1129 status_t 1130 udp_close(net_protocol *protocol) 1131 { 1132 return ((UdpEndpoint *)protocol)->Close(); 1133 } 1134 1135 1136 status_t 1137 udp_free(net_protocol *protocol) 1138 { 1139 return ((UdpEndpoint *)protocol)->Free(); 1140 } 1141 1142 1143 status_t 1144 udp_connect(net_protocol *protocol, const struct sockaddr *address) 1145 { 1146 return ((UdpEndpoint *)protocol)->Connect(address); 1147 } 1148 1149 1150 status_t 1151 udp_accept(net_protocol *protocol, struct net_socket **_acceptedSocket) 1152 { 1153 return B_NOT_SUPPORTED; 1154 } 1155 1156 1157 status_t 1158 udp_control(net_protocol *protocol, int level, int option, void *value, 1159 size_t *_length) 1160 { 1161 return protocol->next->module->control(protocol->next, level, option, 1162 value, _length); 1163 } 1164 1165 1166 status_t 1167 udp_getsockopt(net_protocol *protocol, int level, int option, void *value, 1168 int *length) 1169 { 1170 return protocol->next->module->getsockopt(protocol->next, level, option, 1171 value, length); 1172 } 1173 1174 1175 status_t 1176 udp_setsockopt(net_protocol *protocol, int level, int option, 1177 const void *value, int length) 1178 { 1179 return protocol->next->module->setsockopt(protocol->next, level, option, 1180 value, length); 1181 } 1182 1183 1184 status_t 1185 udp_bind(net_protocol *protocol, const struct sockaddr *address) 1186 { 1187 return ((UdpEndpoint *)protocol)->Bind(address); 1188 } 1189 1190 1191 status_t 1192 udp_unbind(net_protocol *protocol, struct sockaddr *address) 1193 { 1194 return ((UdpEndpoint *)protocol)->Unbind(address); 1195 } 1196 1197 1198 status_t 1199 udp_listen(net_protocol *protocol, int count) 1200 { 1201 return B_NOT_SUPPORTED; 1202 } 1203 1204 1205 status_t 1206 udp_shutdown(net_protocol *protocol, int direction) 1207 { 1208 return B_NOT_SUPPORTED; 1209 } 1210 1211 1212 status_t 1213 udp_send_routed_data(net_protocol *protocol, struct net_route *route, 1214 net_buffer *buffer) 1215 { 1216 return ((UdpEndpoint *)protocol)->SendRoutedData(buffer, route); 1217 } 1218 1219 1220 status_t 1221 udp_send_data(net_protocol *protocol, net_buffer *buffer) 1222 { 1223 return ((UdpEndpoint *)protocol)->SendData(buffer); 1224 } 1225 1226 1227 ssize_t 1228 udp_send_avail(net_protocol *protocol) 1229 { 1230 return protocol->socket->send.buffer_size; 1231 } 1232 1233 1234 status_t 1235 udp_read_data(net_protocol *protocol, size_t numBytes, uint32 flags, 1236 net_buffer **_buffer) 1237 { 1238 return ((UdpEndpoint *)protocol)->FetchData(numBytes, flags, _buffer); 1239 } 1240 1241 1242 ssize_t 1243 udp_read_avail(net_protocol *protocol) 1244 { 1245 return ((UdpEndpoint *)protocol)->BytesAvailable(); 1246 } 1247 1248 1249 struct net_domain * 1250 udp_get_domain(net_protocol *protocol) 1251 { 1252 return protocol->next->module->get_domain(protocol->next); 1253 } 1254 1255 1256 size_t 1257 udp_get_mtu(net_protocol *protocol, const struct sockaddr *address) 1258 { 1259 return protocol->next->module->get_mtu(protocol->next, address); 1260 } 1261 1262 1263 status_t 1264 udp_receive_data(net_buffer *buffer) 1265 { 1266 return sUdpEndpointManager->ReceiveData(buffer); 1267 } 1268 1269 1270 status_t 1271 udp_deliver_data(net_protocol *protocol, net_buffer *buffer) 1272 { 1273 return ((UdpEndpoint *)protocol)->DeliverData(buffer); 1274 } 1275 1276 1277 status_t 1278 udp_error_received(net_error error, net_buffer* buffer) 1279 { 1280 status_t notifyError = B_OK; 1281 1282 switch (error) { 1283 case B_NET_ERROR_UNREACH_NET: 1284 notifyError = ENETUNREACH; 1285 break; 1286 case B_NET_ERROR_UNREACH_HOST: 1287 case B_NET_ERROR_TRANSIT_TIME_EXCEEDED: 1288 notifyError = EHOSTUNREACH; 1289 break; 1290 case B_NET_ERROR_UNREACH_PROTOCOL: 1291 case B_NET_ERROR_UNREACH_PORT: 1292 notifyError = ECONNREFUSED; 1293 break; 1294 case B_NET_ERROR_MESSAGE_SIZE: 1295 notifyError = EMSGSIZE; 1296 break; 1297 case B_NET_ERROR_PARAMETER_PROBLEM: 1298 notifyError = ENOPROTOOPT; 1299 break; 1300 1301 case B_NET_ERROR_QUENCH: 1302 default: 1303 // ignore them 1304 gBufferModule->free(buffer); 1305 return B_OK; 1306 } 1307 1308 ASSERT(notifyError != B_OK); 1309 1310 return sUdpEndpointManager->ReceiveError(notifyError, buffer); 1311 } 1312 1313 1314 status_t 1315 udp_error_reply(net_protocol *protocol, net_buffer *cause, net_error error, 1316 net_error_data *errorData) 1317 { 1318 return B_ERROR; 1319 } 1320 1321 1322 ssize_t 1323 udp_process_ancillary_data_no_container(net_protocol *protocol, 1324 net_buffer* buffer, void *data, size_t dataSize) 1325 { 1326 return protocol->next->module->process_ancillary_data_no_container( 1327 protocol, buffer, data, dataSize); 1328 } 1329 1330 1331 // #pragma mark - module interface 1332 1333 1334 static status_t 1335 init_udp() 1336 { 1337 status_t status; 1338 TRACE_EPM("init_udp()"); 1339 1340 sUdpEndpointManager = new (std::nothrow) UdpEndpointManager; 1341 if (sUdpEndpointManager == NULL) 1342 return B_NO_MEMORY; 1343 1344 status = sUdpEndpointManager->InitCheck(); 1345 if (status != B_OK) 1346 goto err1; 1347 1348 status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, 1349 IPPROTO_IP, 1350 "network/protocols/udp/v1", 1351 "network/protocols/ipv4/v1", 1352 NULL); 1353 if (status < B_OK) 1354 goto err1; 1355 status = gStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM, 1356 IPPROTO_IP, 1357 "network/protocols/udp/v1", 1358 "network/protocols/ipv6/v1", 1359 NULL); 1360 if (status < B_OK) 1361 goto err1; 1362 1363 status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, 1364 IPPROTO_UDP, 1365 "network/protocols/udp/v1", 1366 "network/protocols/ipv4/v1", 1367 NULL); 1368 if (status < B_OK) 1369 goto err1; 1370 status = gStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM, 1371 IPPROTO_UDP, 1372 "network/protocols/udp/v1", 1373 "network/protocols/ipv6/v1", 1374 NULL); 1375 if (status < B_OK) 1376 goto err1; 1377 1378 status = gStackModule->register_domain_receiving_protocol(AF_INET, 1379 IPPROTO_UDP, "network/protocols/udp/v1"); 1380 if (status < B_OK) 1381 goto err1; 1382 status = gStackModule->register_domain_receiving_protocol(AF_INET6, 1383 IPPROTO_UDP, "network/protocols/udp/v1"); 1384 if (status < B_OK) 1385 goto err1; 1386 1387 add_debugger_command("udp_endpoints", UdpEndpointManager::DumpEndpoints, 1388 "lists all open UDP endpoints"); 1389 1390 return B_OK; 1391 1392 err1: 1393 // TODO: shouldn't unregister the protocols here? 1394 delete sUdpEndpointManager; 1395 1396 TRACE_EPM("init_udp() fails with %lx (%s)", status, strerror(status)); 1397 return status; 1398 } 1399 1400 1401 static status_t 1402 uninit_udp() 1403 { 1404 TRACE_EPM("uninit_udp()"); 1405 remove_debugger_command("udp_endpoints", 1406 UdpEndpointManager::DumpEndpoints); 1407 delete sUdpEndpointManager; 1408 return B_OK; 1409 } 1410 1411 1412 static status_t 1413 udp_std_ops(int32 op, ...) 1414 { 1415 switch (op) { 1416 case B_MODULE_INIT: 1417 return init_udp(); 1418 1419 case B_MODULE_UNINIT: 1420 return uninit_udp(); 1421 1422 default: 1423 return B_ERROR; 1424 } 1425 } 1426 1427 1428 net_protocol_module_info sUDPModule = { 1429 { 1430 "network/protocols/udp/v1", 1431 0, 1432 udp_std_ops 1433 }, 1434 NET_PROTOCOL_ATOMIC_MESSAGES, 1435 1436 udp_init_protocol, 1437 udp_uninit_protocol, 1438 udp_open, 1439 udp_close, 1440 udp_free, 1441 udp_connect, 1442 udp_accept, 1443 udp_control, 1444 udp_getsockopt, 1445 udp_setsockopt, 1446 udp_bind, 1447 udp_unbind, 1448 udp_listen, 1449 udp_shutdown, 1450 udp_send_data, 1451 udp_send_routed_data, 1452 udp_send_avail, 1453 udp_read_data, 1454 udp_read_avail, 1455 udp_get_domain, 1456 udp_get_mtu, 1457 udp_receive_data, 1458 udp_deliver_data, 1459 udp_error_received, 1460 udp_error_reply, 1461 NULL, // add_ancillary_data() 1462 NULL, // process_ancillary_data() 1463 udp_process_ancillary_data_no_container, 1464 NULL, // send_data_no_buffer() 1465 NULL // read_data_no_buffer() 1466 }; 1467 1468 module_dependency module_dependencies[] = { 1469 {NET_STACK_MODULE_NAME, (module_info **)&gStackModule}, 1470 {NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule}, 1471 {NET_DATALINK_MODULE_NAME, (module_info **)&gDatalinkModule}, 1472 {NET_SOCKET_MODULE_NAME, (module_info **)&gSocketModule}, 1473 {} 1474 }; 1475 1476 module_info *modules[] = { 1477 (module_info *)&sUDPModule, 1478 NULL 1479 }; 1480