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