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 return B_OK; 969 } 970 971 972 status_t 973 UdpEndpoint::Free() 974 { 975 TRACE_EP("Free()"); 976 fManager->UnbindEndpoint(this); 977 return sUdpEndpointManager->FreeEndpoint(fManager); 978 } 979 980 981 // #pragma mark - outbound 982 983 984 status_t 985 UdpEndpoint::SendRoutedData(net_buffer *buffer, net_route *route) 986 { 987 TRACE_EP("SendRoutedData(%p [%lu bytes], %p)", buffer, buffer->size, route); 988 989 if (buffer->size > (0xffff - sizeof(udp_header))) 990 return EMSGSIZE; 991 992 buffer->protocol = IPPROTO_UDP; 993 994 // add and fill UDP-specific header: 995 NetBufferPrepend<udp_header> header(buffer); 996 if (header.Status() < B_OK) 997 return header.Status(); 998 999 header->source_port = AddressModule()->get_port(buffer->source); 1000 header->destination_port = AddressModule()->get_port(buffer->destination); 1001 header->udp_length = htons(buffer->size); 1002 // the udp-header is already included in the buffer-size 1003 header->udp_checksum = 0; 1004 1005 header.Sync(); 1006 1007 uint16 calculatedChecksum = Checksum::PseudoHeader(AddressModule(), 1008 gBufferModule, buffer, IPPROTO_UDP); 1009 if (calculatedChecksum == 0) 1010 calculatedChecksum = 0xffff; 1011 1012 *UDPChecksumField(buffer) = calculatedChecksum; 1013 1014 return next->module->send_routed_data(next, route, buffer); 1015 } 1016 1017 1018 status_t 1019 UdpEndpoint::SendData(net_buffer *buffer) 1020 { 1021 TRACE_EP("SendData(%p [%lu bytes])", buffer, buffer->size); 1022 1023 return gDatalinkModule->send_data(this, NULL, buffer); 1024 } 1025 1026 1027 // #pragma mark - inbound 1028 1029 1030 ssize_t 1031 UdpEndpoint::BytesAvailable() 1032 { 1033 size_t bytes = AvailableData(); 1034 TRACE_EP("BytesAvailable(): %lu", bytes); 1035 return bytes; 1036 } 1037 1038 1039 status_t 1040 UdpEndpoint::FetchData(size_t numBytes, uint32 flags, net_buffer **_buffer) 1041 { 1042 TRACE_EP("FetchData(%ld, 0x%lx)", numBytes, flags); 1043 1044 status_t status = Dequeue(flags, _buffer); 1045 TRACE_EP(" FetchData(): returned from fifo status: %s", strerror(status)); 1046 if (status != B_OK) 1047 return status; 1048 1049 TRACE_EP(" FetchData(): returns buffer with %ld bytes", (*_buffer)->size); 1050 return B_OK; 1051 } 1052 1053 1054 status_t 1055 UdpEndpoint::StoreData(net_buffer *buffer) 1056 { 1057 TRACE_EP("StoreData(%p [%ld bytes])", buffer, buffer->size); 1058 1059 return EnqueueClone(buffer); 1060 } 1061 1062 1063 status_t 1064 UdpEndpoint::DeliverData(net_buffer *_buffer) 1065 { 1066 TRACE_EP("DeliverData(%p [%ld bytes])", _buffer, _buffer->size); 1067 1068 net_buffer *buffer = gBufferModule->clone(_buffer, false); 1069 if (buffer == NULL) 1070 return B_NO_MEMORY; 1071 1072 status_t status = sUdpEndpointManager->Deframe(buffer); 1073 if (status < B_OK) { 1074 gBufferModule->free(buffer); 1075 return status; 1076 } 1077 1078 return Enqueue(buffer); 1079 } 1080 1081 1082 void 1083 UdpEndpoint::Dump() const 1084 { 1085 char local[64]; 1086 LocalAddress().AsString(local, sizeof(local), true); 1087 char peer[64]; 1088 PeerAddress().AsString(peer, sizeof(peer), true); 1089 1090 kprintf("%p %20s %20s %8lu\n", this, local, peer, fCurrentBytes); 1091 } 1092 1093 1094 // #pragma mark - protocol interface 1095 1096 1097 net_protocol * 1098 udp_init_protocol(net_socket *socket) 1099 { 1100 socket->protocol = IPPROTO_UDP; 1101 1102 UdpEndpoint *endpoint = new (std::nothrow) UdpEndpoint(socket); 1103 if (endpoint == NULL || endpoint->InitCheck() < B_OK) { 1104 delete endpoint; 1105 return NULL; 1106 } 1107 1108 return endpoint; 1109 } 1110 1111 1112 status_t 1113 udp_uninit_protocol(net_protocol *protocol) 1114 { 1115 delete (UdpEndpoint *)protocol; 1116 return B_OK; 1117 } 1118 1119 1120 status_t 1121 udp_open(net_protocol *protocol) 1122 { 1123 return ((UdpEndpoint *)protocol)->Open(); 1124 } 1125 1126 1127 status_t 1128 udp_close(net_protocol *protocol) 1129 { 1130 return ((UdpEndpoint *)protocol)->Close(); 1131 } 1132 1133 1134 status_t 1135 udp_free(net_protocol *protocol) 1136 { 1137 return ((UdpEndpoint *)protocol)->Free(); 1138 } 1139 1140 1141 status_t 1142 udp_connect(net_protocol *protocol, const struct sockaddr *address) 1143 { 1144 return ((UdpEndpoint *)protocol)->Connect(address); 1145 } 1146 1147 1148 status_t 1149 udp_accept(net_protocol *protocol, struct net_socket **_acceptedSocket) 1150 { 1151 return B_NOT_SUPPORTED; 1152 } 1153 1154 1155 status_t 1156 udp_control(net_protocol *protocol, int level, int option, void *value, 1157 size_t *_length) 1158 { 1159 return protocol->next->module->control(protocol->next, level, option, 1160 value, _length); 1161 } 1162 1163 1164 status_t 1165 udp_getsockopt(net_protocol *protocol, int level, int option, void *value, 1166 int *length) 1167 { 1168 return protocol->next->module->getsockopt(protocol->next, level, option, 1169 value, length); 1170 } 1171 1172 1173 status_t 1174 udp_setsockopt(net_protocol *protocol, int level, int option, 1175 const void *value, int length) 1176 { 1177 return protocol->next->module->setsockopt(protocol->next, level, option, 1178 value, length); 1179 } 1180 1181 1182 status_t 1183 udp_bind(net_protocol *protocol, const struct sockaddr *address) 1184 { 1185 return ((UdpEndpoint *)protocol)->Bind(address); 1186 } 1187 1188 1189 status_t 1190 udp_unbind(net_protocol *protocol, struct sockaddr *address) 1191 { 1192 return ((UdpEndpoint *)protocol)->Unbind(address); 1193 } 1194 1195 1196 status_t 1197 udp_listen(net_protocol *protocol, int count) 1198 { 1199 return B_NOT_SUPPORTED; 1200 } 1201 1202 1203 status_t 1204 udp_shutdown(net_protocol *protocol, int direction) 1205 { 1206 return B_NOT_SUPPORTED; 1207 } 1208 1209 1210 status_t 1211 udp_send_routed_data(net_protocol *protocol, struct net_route *route, 1212 net_buffer *buffer) 1213 { 1214 return ((UdpEndpoint *)protocol)->SendRoutedData(buffer, route); 1215 } 1216 1217 1218 status_t 1219 udp_send_data(net_protocol *protocol, net_buffer *buffer) 1220 { 1221 return ((UdpEndpoint *)protocol)->SendData(buffer); 1222 } 1223 1224 1225 ssize_t 1226 udp_send_avail(net_protocol *protocol) 1227 { 1228 return protocol->socket->send.buffer_size; 1229 } 1230 1231 1232 status_t 1233 udp_read_data(net_protocol *protocol, size_t numBytes, uint32 flags, 1234 net_buffer **_buffer) 1235 { 1236 return ((UdpEndpoint *)protocol)->FetchData(numBytes, flags, _buffer); 1237 } 1238 1239 1240 ssize_t 1241 udp_read_avail(net_protocol *protocol) 1242 { 1243 return ((UdpEndpoint *)protocol)->BytesAvailable(); 1244 } 1245 1246 1247 struct net_domain * 1248 udp_get_domain(net_protocol *protocol) 1249 { 1250 return protocol->next->module->get_domain(protocol->next); 1251 } 1252 1253 1254 size_t 1255 udp_get_mtu(net_protocol *protocol, const struct sockaddr *address) 1256 { 1257 return protocol->next->module->get_mtu(protocol->next, address); 1258 } 1259 1260 1261 status_t 1262 udp_receive_data(net_buffer *buffer) 1263 { 1264 return sUdpEndpointManager->ReceiveData(buffer); 1265 } 1266 1267 1268 status_t 1269 udp_deliver_data(net_protocol *protocol, net_buffer *buffer) 1270 { 1271 return ((UdpEndpoint *)protocol)->DeliverData(buffer); 1272 } 1273 1274 1275 status_t 1276 udp_error_received(net_error error, net_buffer* buffer) 1277 { 1278 status_t notifyError = B_OK; 1279 1280 switch (error) { 1281 case B_NET_ERROR_UNREACH_NET: 1282 notifyError = ENETUNREACH; 1283 break; 1284 case B_NET_ERROR_UNREACH_HOST: 1285 case B_NET_ERROR_TRANSIT_TIME_EXCEEDED: 1286 notifyError = EHOSTUNREACH; 1287 break; 1288 case B_NET_ERROR_UNREACH_PROTOCOL: 1289 case B_NET_ERROR_UNREACH_PORT: 1290 notifyError = ECONNREFUSED; 1291 break; 1292 case B_NET_ERROR_MESSAGE_SIZE: 1293 notifyError = EMSGSIZE; 1294 break; 1295 case B_NET_ERROR_PARAMETER_PROBLEM: 1296 notifyError = ENOPROTOOPT; 1297 break; 1298 1299 case B_NET_ERROR_QUENCH: 1300 default: 1301 // ignore them 1302 gBufferModule->free(buffer); 1303 return B_OK; 1304 } 1305 1306 ASSERT(notifyError != B_OK); 1307 1308 return sUdpEndpointManager->ReceiveError(notifyError, buffer); 1309 } 1310 1311 1312 status_t 1313 udp_error_reply(net_protocol *protocol, net_buffer *cause, net_error error, 1314 net_error_data *errorData) 1315 { 1316 return B_ERROR; 1317 } 1318 1319 1320 ssize_t 1321 udp_process_ancillary_data_no_container(net_protocol *protocol, 1322 net_buffer* buffer, void *data, size_t dataSize) 1323 { 1324 return protocol->next->module->process_ancillary_data_no_container( 1325 protocol, buffer, data, dataSize); 1326 } 1327 1328 1329 // #pragma mark - module interface 1330 1331 1332 static status_t 1333 init_udp() 1334 { 1335 status_t status; 1336 TRACE_EPM("init_udp()"); 1337 1338 sUdpEndpointManager = new (std::nothrow) UdpEndpointManager; 1339 if (sUdpEndpointManager == NULL) 1340 return B_NO_MEMORY; 1341 1342 status = sUdpEndpointManager->InitCheck(); 1343 if (status != B_OK) 1344 goto err1; 1345 1346 status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, 1347 IPPROTO_IP, 1348 "network/protocols/udp/v1", 1349 "network/protocols/ipv4/v1", 1350 NULL); 1351 if (status < B_OK) 1352 goto err1; 1353 status = gStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM, 1354 IPPROTO_IP, 1355 "network/protocols/udp/v1", 1356 "network/protocols/ipv6/v1", 1357 NULL); 1358 if (status < B_OK) 1359 goto err1; 1360 1361 status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, 1362 IPPROTO_UDP, 1363 "network/protocols/udp/v1", 1364 "network/protocols/ipv4/v1", 1365 NULL); 1366 if (status < B_OK) 1367 goto err1; 1368 status = gStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM, 1369 IPPROTO_UDP, 1370 "network/protocols/udp/v1", 1371 "network/protocols/ipv6/v1", 1372 NULL); 1373 if (status < B_OK) 1374 goto err1; 1375 1376 status = gStackModule->register_domain_receiving_protocol(AF_INET, 1377 IPPROTO_UDP, "network/protocols/udp/v1"); 1378 if (status < B_OK) 1379 goto err1; 1380 status = gStackModule->register_domain_receiving_protocol(AF_INET6, 1381 IPPROTO_UDP, "network/protocols/udp/v1"); 1382 if (status < B_OK) 1383 goto err1; 1384 1385 add_debugger_command("udp_endpoints", UdpEndpointManager::DumpEndpoints, 1386 "lists all open UDP endpoints"); 1387 1388 return B_OK; 1389 1390 err1: 1391 // TODO: shouldn't unregister the protocols here? 1392 delete sUdpEndpointManager; 1393 1394 TRACE_EPM("init_udp() fails with %lx (%s)", status, strerror(status)); 1395 return status; 1396 } 1397 1398 1399 static status_t 1400 uninit_udp() 1401 { 1402 TRACE_EPM("uninit_udp()"); 1403 remove_debugger_command("udp_endpoints", 1404 UdpEndpointManager::DumpEndpoints); 1405 delete sUdpEndpointManager; 1406 return B_OK; 1407 } 1408 1409 1410 static status_t 1411 udp_std_ops(int32 op, ...) 1412 { 1413 switch (op) { 1414 case B_MODULE_INIT: 1415 return init_udp(); 1416 1417 case B_MODULE_UNINIT: 1418 return uninit_udp(); 1419 1420 default: 1421 return B_ERROR; 1422 } 1423 } 1424 1425 1426 net_protocol_module_info sUDPModule = { 1427 { 1428 "network/protocols/udp/v1", 1429 0, 1430 udp_std_ops 1431 }, 1432 NET_PROTOCOL_ATOMIC_MESSAGES, 1433 1434 udp_init_protocol, 1435 udp_uninit_protocol, 1436 udp_open, 1437 udp_close, 1438 udp_free, 1439 udp_connect, 1440 udp_accept, 1441 udp_control, 1442 udp_getsockopt, 1443 udp_setsockopt, 1444 udp_bind, 1445 udp_unbind, 1446 udp_listen, 1447 udp_shutdown, 1448 udp_send_data, 1449 udp_send_routed_data, 1450 udp_send_avail, 1451 udp_read_data, 1452 udp_read_avail, 1453 udp_get_domain, 1454 udp_get_mtu, 1455 udp_receive_data, 1456 udp_deliver_data, 1457 udp_error_received, 1458 udp_error_reply, 1459 NULL, // add_ancillary_data() 1460 NULL, // process_ancillary_data() 1461 udp_process_ancillary_data_no_container, 1462 NULL, // send_data_no_buffer() 1463 NULL // read_data_no_buffer() 1464 }; 1465 1466 module_dependency module_dependencies[] = { 1467 {NET_STACK_MODULE_NAME, (module_info **)&gStackModule}, 1468 {NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule}, 1469 {NET_DATALINK_MODULE_NAME, (module_info **)&gDatalinkModule}, 1470 {NET_SOCKET_MODULE_NAME, (module_info **)&gSocketModule}, 1471 {} 1472 }; 1473 1474 module_info *modules[] = { 1475 (module_info *)&sUDPModule, 1476 NULL 1477 }; 1478