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