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