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