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