1 /* 2 * Copyright 2006, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Oliver Tappe, zooey@hirschkaefer.de 7 */ 8 9 10 #include <net_buffer.h> 11 #include <net_datalink.h> 12 #include <net_protocol.h> 13 #include <net_stack.h> 14 15 #include <lock.h> 16 #include <util/AutoLock.h> 17 #include <util/khash.h> 18 19 #include <KernelExport.h> 20 21 #include <NetBufferUtilities.h> 22 #include <NetUtilities.h> 23 24 #include <netinet/in.h> 25 #include <new> 26 #include <stdlib.h> 27 #include <string.h> 28 29 30 //#define TRACE_UDP 31 #ifdef TRACE_UDP 32 # define TRACE(x) dprintf x 33 # define TRACE_BLOCK(x) dump_block x 34 #else 35 # define TRACE(x) 36 # define TRACE_BLOCK(x) 37 #endif 38 39 40 struct udp_header { 41 uint16 source_port; 42 uint16 destination_port; 43 uint16 udp_length; 44 uint16 udp_checksum; 45 } _PACKED; 46 47 48 class UdpEndpoint : public net_protocol { 49 public: 50 UdpEndpoint(net_socket *socket); 51 ~UdpEndpoint(); 52 53 status_t Bind(sockaddr *newAddr); 54 status_t Unbind(sockaddr *newAddr); 55 status_t Connect(const sockaddr *newAddr); 56 57 status_t Open(); 58 status_t Close(); 59 status_t Free(); 60 61 status_t SendData(net_buffer *buffer, net_route *route); 62 63 ssize_t BytesAvailable(); 64 status_t FetchData(size_t numBytes, uint32 flags, 65 net_buffer **_buffer); 66 67 status_t StoreData(net_buffer *buffer); 68 69 UdpEndpoint *hash_link; 70 // link required by hash_table (see khash.h) 71 private: 72 status_t _Activate(); 73 status_t _Deactivate(); 74 75 bool fActive; 76 // an active UdpEndpoint is part of the endpoint 77 // hash (and it is bound and optionally connected) 78 net_fifo fFifo; 79 // storage space for incoming data 80 }; 81 82 83 class UdpEndpointManager { 84 85 struct hash_key { 86 hash_key(sockaddr *ourAddress, sockaddr *peerAddress); 87 88 sockaddr ourAddress; 89 sockaddr peerAddress; 90 }; 91 92 class Ephemerals { 93 public: 94 Ephemerals(); 95 ~Ephemerals(); 96 97 uint16 GetNext(hash_table *activeEndpoints); 98 static const uint16 kFirst = 49152; 99 static const uint16 kLast = 65535; 100 private: 101 uint16 fLastUsed; 102 }; 103 104 public: 105 UdpEndpointManager(); 106 ~UdpEndpointManager(); 107 108 status_t DemuxBroadcast(net_buffer *buffer); 109 status_t DemuxMulticast(net_buffer *buffer); 110 status_t DemuxUnicast(net_buffer *buffer); 111 status_t DemuxIncomingBuffer(net_buffer *buffer); 112 status_t ReceiveData(net_buffer *buffer); 113 114 static int Compare(void *udpEndpoint, const void *_key); 115 static uint32 ComputeHash(sockaddr *ourAddress, sockaddr *peerAddress); 116 static uint32 Hash(void *udpEndpoint, const void *key, uint32 range); 117 118 UdpEndpoint *FindActiveEndpoint(sockaddr *ourAddress, 119 sockaddr *peerAddress); 120 status_t CheckBindRequest(sockaddr *address, int socketOptions); 121 122 status_t ActivateEndpoint(UdpEndpoint *endpoint); 123 status_t DeactivateEndpoint(UdpEndpoint *endpoint); 124 125 status_t OpenEndpoint(UdpEndpoint *endpoint); 126 status_t CloseEndpoint(UdpEndpoint *endpoint); 127 status_t FreeEndpoint(UdpEndpoint *endpoint); 128 129 uint16 GetEphemeralPort(); 130 131 benaphore *Locker(); 132 status_t InitCheck() const; 133 private: 134 benaphore fLock; 135 hash_table *fActiveEndpoints; 136 static const uint32 kNumHashBuckets = 0x800; 137 // if you change this, adjust the shifting in 138 // Hash() accordingly! 139 Ephemerals fEphemerals; 140 status_t fStatus; 141 uint32 fEndpointCount; 142 }; 143 144 145 static UdpEndpointManager *sUdpEndpointManager; 146 147 static net_domain *sDomain; 148 149 static net_address_module_info *sAddressModule; 150 net_buffer_module_info *gBufferModule; 151 static net_datalink_module_info *sDatalinkModule; 152 static net_stack_module_info *sStackModule; 153 154 155 // #pragma mark - 156 157 158 UdpEndpointManager::hash_key::hash_key(sockaddr *_ourAddress, sockaddr *_peerAddress) 159 { 160 memcpy(&ourAddress, _ourAddress, sizeof(sockaddr)); 161 memcpy(&peerAddress, _peerAddress, sizeof(sockaddr)); 162 } 163 164 165 // #pragma mark - 166 167 168 UdpEndpointManager::Ephemerals::Ephemerals() 169 : 170 fLastUsed(kLast) 171 { 172 } 173 174 175 UdpEndpointManager::Ephemerals::~Ephemerals() 176 { 177 } 178 179 180 uint16 181 UdpEndpointManager::Ephemerals::GetNext(hash_table *activeEndpoints) 182 { 183 uint16 stop, curr, ncurr; 184 if (fLastUsed < kLast) { 185 stop = fLastUsed; 186 curr = fLastUsed + 1; 187 } else { 188 stop = kLast; 189 curr = kFirst; 190 } 191 192 TRACE(("UdpEndpointManager::Ephemerals::GetNext()...\n")); 193 // TODO: a free list could be used to avoid the impact of these 194 // two nested loops most of the time... let's see how bad this really is 195 UdpEndpoint *endpoint; 196 struct hash_iterator endpointIterator; 197 hash_open(activeEndpoints, &endpointIterator); 198 bool found = false; 199 uint16 endpointPort; 200 while(!found && curr != stop) { 201 TRACE(("...trying port %u...\n", curr)); 202 ncurr = htons(curr); 203 for(hash_rewind(activeEndpoints, &endpointIterator); !found; ) { 204 endpoint = (UdpEndpoint *)hash_next(activeEndpoints, &endpointIterator); 205 if (!endpoint) { 206 found = true; 207 break; 208 } 209 endpointPort = sAddressModule->get_port( 210 (sockaddr *)&endpoint->socket->address); 211 TRACE(("...checking endpoint %p (port=%u)...\n", endpoint, 212 ntohs(endpointPort))); 213 if (endpointPort == ncurr) 214 break; 215 } 216 if (!found) { 217 if (curr < kLast) 218 curr++; 219 else 220 curr = kFirst; 221 } 222 } 223 hash_close(activeEndpoints, &endpointIterator, false); 224 if (!found) 225 return 0; 226 TRACE(("...using port %u\n", curr)); 227 fLastUsed = curr; 228 return curr; 229 } 230 231 232 // #pragma mark - 233 234 235 UdpEndpointManager::UdpEndpointManager() 236 : 237 fStatus(B_NO_INIT), 238 fEndpointCount(0) 239 { 240 fActiveEndpoints = hash_init(kNumHashBuckets, offsetof(UdpEndpoint, hash_link), 241 &Compare, &Hash); 242 if (fActiveEndpoints == NULL) { 243 fStatus = B_NO_MEMORY; 244 return; 245 } 246 247 fStatus = benaphore_init(&fLock, "UDP endpoints"); 248 if (fStatus < B_OK) 249 hash_uninit(fActiveEndpoints); 250 } 251 252 253 UdpEndpointManager::~UdpEndpointManager() 254 { 255 benaphore_destroy(&fLock); 256 hash_uninit(fActiveEndpoints); 257 } 258 259 260 inline benaphore * 261 UdpEndpointManager::Locker() 262 { 263 return &fLock; 264 } 265 266 267 inline status_t 268 UdpEndpointManager::InitCheck() const 269 { 270 return fStatus; 271 } 272 273 274 // #pragma mark - hashing 275 276 277 /*static*/ int 278 UdpEndpointManager::Compare(void *_udpEndpoint, const void *_key) 279 { 280 struct UdpEndpoint *udpEndpoint = (UdpEndpoint*)_udpEndpoint; 281 hash_key *key = (hash_key *)_key; 282 283 sockaddr *ourAddr = (sockaddr *)&udpEndpoint->socket->address; 284 sockaddr *peerAddr = (sockaddr *)&udpEndpoint->socket->peer; 285 286 if (sAddressModule->equal_addresses_and_ports(ourAddr, &key->ourAddress) 287 && sAddressModule->equal_addresses_and_ports(peerAddr, &key->peerAddress)) 288 return 0; 289 290 return 1; 291 } 292 293 294 /*static*/ inline uint32 295 UdpEndpointManager::ComputeHash(sockaddr *ourAddress, sockaddr *peerAddress) 296 { 297 return sAddressModule->hash_address_pair(ourAddress, peerAddress); 298 } 299 300 301 /*static*/ uint32 302 UdpEndpointManager::Hash(void *_udpEndpoint, const void *_key, uint32 range) 303 { 304 uint32 hash; 305 306 if (_udpEndpoint) { 307 struct UdpEndpoint *udpEndpoint = (UdpEndpoint*)_udpEndpoint; 308 sockaddr *ourAddr = (sockaddr*)&udpEndpoint->socket->address; 309 sockaddr *peerAddr = (sockaddr*)&udpEndpoint->socket->peer; 310 hash = ComputeHash(ourAddr, peerAddr); 311 } else { 312 hash_key *key = (hash_key *)_key; 313 hash = ComputeHash(&key->ourAddress, &key->peerAddress); 314 } 315 316 // move the bits into the relevant range (as defined by kNumHashBuckets): 317 hash = (hash & 0x000007FF) ^ (hash & 0x003FF800) >> 11 318 ^ (hash & 0xFFC00000UL) >> 22; 319 320 TRACE(("UDP-endpoint hash is %lx\n", hash % range)); 321 return hash % range; 322 } 323 324 325 // #pragma mark - inbound 326 327 328 UdpEndpoint * 329 UdpEndpointManager::FindActiveEndpoint(sockaddr *ourAddress, 330 sockaddr *peerAddress) 331 { 332 TRACE(("trying to find UDP-endpoint for (l:%s p:%s)\n", 333 AddressString(sDomain, ourAddress, true).Data(), 334 AddressString(sDomain, peerAddress, true).Data())); 335 hash_key key(ourAddress, peerAddress); 336 UdpEndpoint *endpoint = (UdpEndpoint *)hash_lookup(fActiveEndpoints, &key); 337 return endpoint; 338 } 339 340 341 status_t 342 UdpEndpointManager::DemuxBroadcast(net_buffer *buffer) 343 { 344 sockaddr *peerAddr = (sockaddr *)&buffer->source; 345 sockaddr *broadcastAddr = (sockaddr *)&buffer->destination; 346 sockaddr *mask = NULL; 347 if (buffer->interface) 348 mask = (sockaddr *)buffer->interface->mask; 349 350 TRACE(("demuxing buffer %p as broadcast...\n", buffer)); 351 352 sockaddr anyAddr; 353 sAddressModule->set_to_empty_address(&anyAddr); 354 355 uint16 incomingPort = sAddressModule->get_port(broadcastAddr); 356 357 UdpEndpoint *endpoint; 358 sockaddr *addr, *connectAddr; 359 struct hash_iterator endpointIterator; 360 for(hash_open(fActiveEndpoints, &endpointIterator); ; ) { 361 endpoint = (UdpEndpoint *)hash_next(fActiveEndpoints, &endpointIterator); 362 if (!endpoint) 363 break; 364 365 addr = (sockaddr *)&endpoint->socket->address; 366 TRACE(("UDP-DemuxBroadcast() is checking endpoint %s...\n", 367 AddressString(sDomain, addr, true).Data())); 368 369 if (incomingPort != sAddressModule->get_port(addr)) { 370 // ports don't match, so we do not dispatch to this endpoint... 371 continue; 372 } 373 374 connectAddr = (sockaddr *)&endpoint->socket->peer; 375 if (!sAddressModule->is_empty_address(connectAddr, true)) { 376 // endpoint is connected to a specific destination, we check if 377 // this datagram is from there: 378 if (!sAddressModule->equal_addresses_and_ports(connectAddr, peerAddr)) { 379 // no, datagram is from another peer, so we do not dispatch to 380 // this endpoint... 381 continue; 382 } 383 } 384 385 if (sAddressModule->equal_masked_addresses(addr, broadcastAddr, mask) 386 || sAddressModule->equal_addresses(addr, &anyAddr)) { 387 // address matches, dispatch to this endpoint: 388 endpoint->StoreData(buffer); 389 } 390 } 391 hash_close(fActiveEndpoints, &endpointIterator, false); 392 return B_OK; 393 } 394 395 396 status_t 397 UdpEndpointManager::DemuxMulticast(net_buffer *buffer) 398 { // TODO: implement! 399 return B_ERROR; 400 } 401 402 403 status_t 404 UdpEndpointManager::DemuxUnicast(net_buffer *buffer) 405 { 406 struct sockaddr *peerAddr = (struct sockaddr *)&buffer->source; 407 struct sockaddr *localAddr = (struct sockaddr *)&buffer->destination; 408 409 TRACE(("demuxing buffer %p as unicast...\n", buffer)); 410 411 struct sockaddr anyAddr; 412 sAddressModule->set_to_empty_address(&anyAddr); 413 414 UdpEndpoint *endpoint; 415 // look for full (most special) match: 416 endpoint = FindActiveEndpoint(localAddr, peerAddr); 417 if (!endpoint) { 418 // look for endpoint matching local address & port: 419 endpoint = FindActiveEndpoint(localAddr, &anyAddr); 420 if (!endpoint) { 421 // look for endpoint matching peer address & port and local port: 422 sockaddr localPortAddr; 423 sAddressModule->set_to_empty_address(&localPortAddr); 424 uint16 localPort = sAddressModule->get_port(localAddr); 425 sAddressModule->set_port(&localPortAddr, localPort); 426 endpoint = FindActiveEndpoint(&localPortAddr, peerAddr); 427 if (!endpoint) { 428 // last chance: look for endpoint matching local port only: 429 endpoint = FindActiveEndpoint(&localPortAddr, &anyAddr); 430 } 431 } 432 } 433 if (!endpoint) 434 return B_NAME_NOT_FOUND; 435 436 endpoint->StoreData(buffer); 437 return B_OK; 438 } 439 440 441 status_t 442 UdpEndpointManager::DemuxIncomingBuffer(net_buffer *buffer) 443 { 444 status_t status; 445 446 if (buffer->flags & MSG_BCAST) 447 status = DemuxBroadcast(buffer); 448 else if (buffer->flags & MSG_MCAST) 449 status = DemuxMulticast(buffer); 450 else 451 status = DemuxUnicast(buffer); 452 453 return status; 454 } 455 456 457 status_t 458 UdpEndpointManager::ReceiveData(net_buffer *buffer) 459 { 460 NetBufferHeader<udp_header> bufferHeader(buffer); 461 if (bufferHeader.Status() < B_OK) 462 return bufferHeader.Status(); 463 464 udp_header &header = bufferHeader.Data(); 465 466 struct sockaddr *source = (struct sockaddr *)&buffer->source; 467 struct sockaddr *destination = (struct sockaddr *)&buffer->destination; 468 469 BenaphoreLocker locker(sUdpEndpointManager->Locker()); 470 if (!sDomain) { 471 // domain and address module are not known yet, we copy them from 472 // the buffer's interface (if any): 473 if (buffer->interface == NULL || buffer->interface->domain == NULL) 474 sDomain = sStackModule->get_domain(AF_INET); 475 else 476 sDomain = buffer->interface->domain; 477 if (sDomain == NULL) { 478 // this shouldn't occur, of course, but who knows... 479 return B_BAD_VALUE; 480 } 481 sAddressModule = sDomain->address_module; 482 } 483 sAddressModule->set_port(source, header.source_port); 484 sAddressModule->set_port(destination, header.destination_port); 485 TRACE(("UDP received data from source %s for destination %s\n", 486 AddressString(sDomain, source, true).Data(), 487 AddressString(sDomain, destination, true).Data())); 488 489 uint16 udpLength = ntohs(header.udp_length); 490 if (udpLength > buffer->size) { 491 TRACE(("buffer %p is too short (%lu instead of %u), we drop it!\n", 492 buffer, buffer->size, udpLength)); 493 return B_MISMATCHED_VALUES; 494 } 495 if (buffer->size > udpLength) { 496 TRACE(("buffer %p is too long (%lu instead of %u), trimming it.\n", 497 buffer, buffer->size, udpLength)); 498 gBufferModule->trim(buffer, udpLength); 499 } 500 501 if (header.udp_checksum != 0) { 502 // check UDP-checksum (simulating a so-called "pseudo-header"): 503 Checksum udpChecksum; 504 sAddressModule->checksum_address(&udpChecksum, source); 505 sAddressModule->checksum_address(&udpChecksum, destination); 506 udpChecksum 507 << (uint16)htons(IPPROTO_UDP) 508 << header.udp_length 509 // peculiar but correct: UDP-len is used twice for checksum 510 // (as it is already contained in udp_header) 511 << Checksum::BufferHelper(buffer, gBufferModule); 512 uint16 sum = udpChecksum; 513 if (sum != 0) { 514 TRACE(("buffer %p has bad checksum (%u), we drop it!\n", buffer, sum)); 515 return B_BAD_VALUE; 516 } 517 } 518 519 bufferHeader.Remove(); 520 // remove UDP-header from buffer before passing it on 521 522 status_t status = DemuxIncomingBuffer(buffer); 523 if (status < B_OK) { 524 TRACE(("no matching endpoint found for buffer %p, we drop it!", buffer)); 525 // TODO: send ICMP-error 526 return B_ERROR; 527 } 528 529 return B_ERROR; 530 } 531 532 533 // #pragma mark - activation 534 535 536 status_t 537 UdpEndpointManager::CheckBindRequest(sockaddr *address, int socketOptions) 538 { // sUdpEndpointManager->Locker() must be locked! 539 status_t status = B_OK; 540 UdpEndpoint *otherEndpoint; 541 sockaddr *otherAddr; 542 struct hash_iterator endpointIterator; 543 544 // Iterate over all active UDP-endpoints and check if the requested bind 545 // is allowed (see figure 22.24 in [Stevens - TCP2, p735]): 546 hash_open(fActiveEndpoints, &endpointIterator); 547 TRACE(("UdpEndpointManager::CheckBindRequest() for %s...\n", 548 AddressString(sDomain, address, true).Data())); 549 while(1) { 550 otherEndpoint = (UdpEndpoint *)hash_next(fActiveEndpoints, &endpointIterator); 551 if (!otherEndpoint) 552 break; 553 otherAddr = (sockaddr *)&otherEndpoint->socket->address; 554 TRACE(("...checking endpoint %p (port=%u)...\n", otherEndpoint, 555 ntohs(sAddressModule->get_port(otherAddr)))); 556 if (sAddressModule->equal_ports(otherAddr, address)) { 557 // port is already bound, SO_REUSEADDR or SO_REUSEPORT is required: 558 if (otherEndpoint->socket->options & (SO_REUSEADDR | SO_REUSEPORT) == 0 559 || socketOptions & (SO_REUSEADDR | SO_REUSEPORT) == 0) { 560 status = EADDRINUSE; 561 break; 562 } 563 // if both addresses are the same, SO_REUSEPORT is required: 564 if (sAddressModule->equal_addresses(otherAddr, address) 565 && (otherEndpoint->socket->options & SO_REUSEPORT == 0 566 || socketOptions & SO_REUSEPORT == 0)) { 567 status = EADDRINUSE; 568 break; 569 } 570 } 571 } 572 hash_close(fActiveEndpoints, &endpointIterator, false); 573 574 TRACE(("UdpEndpointManager::CheckBindRequest done (status=%lx)\n", status)); 575 return status; 576 } 577 578 579 status_t 580 UdpEndpointManager::ActivateEndpoint(UdpEndpoint *endpoint) 581 { // sUdpEndpointManager->Locker() must be locked! 582 TRACE(("UDP-endpoint(%s) is activated\n", 583 AddressString(sDomain, (sockaddr *)&endpoint->socket->address, true).Data())); 584 return hash_insert(fActiveEndpoints, endpoint); 585 } 586 587 588 status_t 589 UdpEndpointManager::DeactivateEndpoint(UdpEndpoint *endpoint) 590 { // sUdpEndpointManager->Locker() must be locked! 591 TRACE(("UDP-endpoint(%s) is deactivated\n", 592 AddressString(sDomain, (sockaddr *)&endpoint->socket->address, true).Data())); 593 return hash_remove(fActiveEndpoints, endpoint); 594 } 595 596 597 status_t 598 UdpEndpointManager::OpenEndpoint(UdpEndpoint *endpoint) 599 { // sUdpEndpointManager->Locker() must be locked! 600 if (fEndpointCount++ == 0) { 601 sDomain = sStackModule->get_domain(AF_INET); 602 sAddressModule = sDomain->address_module; 603 TRACE(("udp: setting domain-pointer to %p.\n", sDomain)); 604 } 605 return B_OK; 606 } 607 608 609 status_t 610 UdpEndpointManager::CloseEndpoint(UdpEndpoint *endpoint) 611 { // sUdpEndpointManager->Locker() must be locked! 612 return B_OK; 613 } 614 615 616 status_t 617 UdpEndpointManager::FreeEndpoint(UdpEndpoint *endpoint) 618 { // sUdpEndpointManager->Locker() must be locked! 619 if (--fEndpointCount == 0) { 620 TRACE(("udp: clearing domain-pointer and address-module.\n")); 621 sDomain = NULL; 622 sAddressModule = NULL; 623 } 624 return B_OK; 625 } 626 627 628 uint16 629 UdpEndpointManager::GetEphemeralPort() 630 { 631 return fEphemerals.GetNext(fActiveEndpoints); 632 } 633 634 635 // #pragma mark - 636 637 638 UdpEndpoint::UdpEndpoint(net_socket *socket) 639 : 640 fActive(false) 641 { 642 status_t status = sStackModule->init_fifo(&fFifo, "UDP endpoint fifo", 643 socket->receive.buffer_size); 644 if (status < B_OK) 645 fFifo.notify = status; 646 } 647 648 649 UdpEndpoint::~UdpEndpoint() 650 { 651 if (fFifo.notify >= B_OK) 652 sStackModule->uninit_fifo(&fFifo); 653 } 654 655 656 // #pragma mark - activation 657 658 659 status_t 660 UdpEndpoint::Bind(sockaddr *address) 661 { 662 if (address->sa_family != AF_INET) 663 return EAFNOSUPPORT; 664 665 // let IP check whether there is an interface that supports the given address: 666 status_t status = next->module->bind(next, address); 667 if (status < B_OK) 668 return status; 669 670 BenaphoreLocker locker(sUdpEndpointManager->Locker()); 671 672 if (fActive) { 673 // socket module should have called unbind() before! 674 return EINVAL; 675 } 676 677 if (sAddressModule->get_port(address) == 0) { 678 uint16 port = htons(sUdpEndpointManager->GetEphemeralPort()); 679 if (port == 0) 680 return ENOBUFS; 681 // whoa, no more ephemeral port available!?! 682 sAddressModule->set_port((sockaddr *)&socket->address, port); 683 } else { 684 status = sUdpEndpointManager->CheckBindRequest((sockaddr *)&socket->address, 685 socket->options); 686 if (status < B_OK) 687 return status; 688 } 689 690 return _Activate(); 691 } 692 693 694 status_t 695 UdpEndpoint::Unbind(sockaddr *address) 696 { 697 if (address->sa_family != AF_INET) 698 return EAFNOSUPPORT; 699 700 BenaphoreLocker locker(sUdpEndpointManager->Locker()); 701 702 return _Deactivate(); 703 } 704 705 706 status_t 707 UdpEndpoint::Connect(const sockaddr *address) 708 { 709 if (address->sa_family != AF_INET && address->sa_family != AF_UNSPEC) 710 return EAFNOSUPPORT; 711 712 BenaphoreLocker locker(sUdpEndpointManager->Locker()); 713 714 if (fActive) 715 _Deactivate(); 716 717 if (address->sa_family == AF_UNSPEC) { 718 // [Stevens-UNP1, p226]: specifying AF_UNSPEC requests a "disconnect", 719 // so we reset the peer address: 720 sAddressModule->set_to_empty_address((sockaddr *)&socket->peer); 721 } else 722 sAddressModule->set_to((sockaddr *)&socket->peer, address); 723 724 // we need to activate no matter whether or not we have just disconnected, 725 // as calling connect() always triggers an implicit bind(): 726 return _Activate(); 727 } 728 729 730 status_t 731 UdpEndpoint::Open() 732 { 733 BenaphoreLocker locker(sUdpEndpointManager->Locker()); 734 return sUdpEndpointManager->OpenEndpoint(this); 735 } 736 737 738 status_t 739 UdpEndpoint::Close() 740 { 741 BenaphoreLocker locker(sUdpEndpointManager->Locker()); 742 if (fActive) 743 _Deactivate(); 744 return sUdpEndpointManager->CloseEndpoint(this); 745 } 746 747 748 status_t 749 UdpEndpoint::Free() 750 { 751 BenaphoreLocker locker(sUdpEndpointManager->Locker()); 752 return sUdpEndpointManager->FreeEndpoint(this); 753 } 754 755 756 status_t 757 UdpEndpoint::_Activate() 758 { 759 if (fActive) 760 return B_ERROR; 761 status_t status = sUdpEndpointManager->ActivateEndpoint(this); 762 fActive = (status == B_OK); 763 return status; 764 } 765 766 767 status_t 768 UdpEndpoint::_Deactivate() 769 { 770 if (!fActive) 771 return B_ERROR; 772 status_t status = sUdpEndpointManager->DeactivateEndpoint(this); 773 fActive = false; 774 return status; 775 } 776 777 778 // #pragma mark - outbound 779 780 781 status_t 782 UdpEndpoint::SendData(net_buffer *buffer, net_route *route) 783 { 784 if (buffer->size > socket->send.buffer_size) 785 return EMSGSIZE; 786 787 buffer->protocol = IPPROTO_UDP; 788 789 { // scope for lifetime of bufferHeader 790 791 // add and fill UDP-specific header: 792 NetBufferPrepend<udp_header> bufferHeader(buffer); 793 if (bufferHeader.Status() < B_OK) 794 return bufferHeader.Status(); 795 796 udp_header &header = bufferHeader.Data(); 797 798 header.source_port = sAddressModule->get_port((sockaddr *)&buffer->source); 799 header.destination_port = sAddressModule->get_port( 800 (sockaddr *)&buffer->destination); 801 header.udp_length = htons(buffer->size); 802 // the udp-header is already included in the buffer-size 803 header.udp_checksum = 0; 804 805 // generate UDP-checksum (simulating a so-called "pseudo-header"): 806 Checksum udpChecksum; 807 sAddressModule->checksum_address(&udpChecksum, 808 (sockaddr *)route->interface->address); 809 sAddressModule->checksum_address(&udpChecksum, 810 (sockaddr *)&buffer->destination); 811 udpChecksum 812 << (uint16)htons(IPPROTO_UDP) 813 << (uint16)htons(buffer->size) 814 // peculiar but correct: UDP-len is used twice for checksum 815 // (as it is already contained in udp_header) 816 << Checksum::BufferHelper(buffer, gBufferModule); 817 header.udp_checksum = udpChecksum; 818 if (header.udp_checksum == 0) 819 header.udp_checksum = 0xFFFF; 820 821 TRACE_BLOCK(((char*)&header, sizeof(udp_header), "udp-hdr: ")); 822 } 823 return next->module->send_routed_data(next, route, buffer); 824 } 825 826 827 // #pragma mark - inbound 828 829 830 ssize_t 831 UdpEndpoint::BytesAvailable() 832 { 833 return fFifo.current_bytes; 834 } 835 836 837 status_t 838 UdpEndpoint::FetchData(size_t numBytes, uint32 flags, net_buffer **_buffer) 839 { 840 net_buffer *buffer; 841 AddressString addressString(sDomain, (sockaddr *)&socket->address, true); 842 TRACE(("FetchData() with size=%ld called for endpoint with (%s)\n", 843 numBytes, addressString.Data())); 844 845 status_t status = sStackModule->fifo_dequeue_buffer(&fFifo, flags, 846 socket->receive.timeout, &buffer); 847 TRACE(("Endpoint with (%s) returned from fifo status=%lx\n", 848 addressString.Data(), status)); 849 if (status < B_OK) 850 return status; 851 852 if (numBytes < buffer->size) { 853 // discard any data behind the amount requested 854 gBufferModule->trim(buffer, numBytes); 855 // TODO: we should indicate MSG_TRUNC to application! 856 } 857 858 TRACE(("FetchData() returns buffer with %ld data bytes\n", buffer->size)); 859 *_buffer = buffer; 860 return B_OK; 861 } 862 863 864 status_t 865 UdpEndpoint::StoreData(net_buffer *_buffer) 866 { 867 TRACE(("buffer %p passed to endpoint with (%s)\n", _buffer, 868 AddressString(sDomain, (sockaddr *)&socket->address, true).Data())); 869 net_buffer *buffer = gBufferModule->clone(_buffer, false); 870 if (buffer == NULL) 871 return B_NO_MEMORY; 872 873 status_t status = sStackModule->fifo_enqueue_buffer(&fFifo, buffer); 874 if (status >= B_OK) 875 sStackModule->notify_socket(socket, B_SELECT_READ, BytesAvailable()); 876 else 877 gBufferModule->free(buffer); 878 879 return status; 880 } 881 882 883 // #pragma mark - protocol interface 884 885 886 net_protocol * 887 udp_init_protocol(net_socket *socket) 888 { 889 socket->protocol = IPPROTO_UDP; 890 socket->send.buffer_size = 65535 - 20 - 8; 891 // subtract lengths of IP and UDP headers (NOTE: IP headers could be 892 // larger if IP options are used, but we do not currently care for that) 893 894 UdpEndpoint *endpoint = new (std::nothrow) UdpEndpoint(socket); 895 TRACE(("udp_init_protocol(%p) created endpoint %p\n", socket, endpoint)); 896 return endpoint; 897 } 898 899 900 status_t 901 udp_uninit_protocol(net_protocol *protocol) 902 { 903 TRACE(("udp_uninit_protocol(%p)\n", protocol)); 904 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 905 delete udpEndpoint; 906 return B_OK; 907 } 908 909 910 status_t 911 udp_open(net_protocol *protocol) 912 { 913 TRACE(("udp_open(%p)\n", protocol)); 914 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 915 return udpEndpoint->Open(); 916 } 917 918 919 status_t 920 udp_close(net_protocol *protocol) 921 { 922 TRACE(("udp_close(%p)\n", protocol)); 923 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 924 return udpEndpoint->Close(); 925 } 926 927 928 status_t 929 udp_free(net_protocol *protocol) 930 { 931 TRACE(("udp_free(%p)\n", protocol)); 932 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 933 return udpEndpoint->Free(); 934 } 935 936 937 status_t 938 udp_connect(net_protocol *protocol, const struct sockaddr *address) 939 { 940 TRACE(("udp_connect(%p) on address %s\n", protocol, 941 AddressString(sDomain, address, true).Data())); 942 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 943 return udpEndpoint->Connect(address); 944 } 945 946 947 status_t 948 udp_accept(net_protocol *protocol, struct net_socket **_acceptedSocket) 949 { 950 return EOPNOTSUPP; 951 } 952 953 954 status_t 955 udp_control(net_protocol *protocol, int level, int option, void *value, 956 size_t *_length) 957 { 958 TRACE(("udp_control(%p)\n", protocol)); 959 return protocol->next->module->control(protocol->next, level, option, 960 value, _length); 961 } 962 963 964 status_t 965 udp_bind(net_protocol *protocol, struct sockaddr *address) 966 { 967 TRACE(("udp_bind(%p) on address %s\n", protocol, 968 AddressString(sDomain, address, true).Data())); 969 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 970 return udpEndpoint->Bind(address); 971 } 972 973 974 status_t 975 udp_unbind(net_protocol *protocol, struct sockaddr *address) 976 { 977 TRACE(("udp_unbind(%p) on address %s\n", protocol, 978 AddressString(sDomain, address, true).Data())); 979 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 980 return udpEndpoint->Unbind(address); 981 } 982 983 984 status_t 985 udp_listen(net_protocol *protocol, int count) 986 { 987 return EOPNOTSUPP; 988 } 989 990 991 status_t 992 udp_shutdown(net_protocol *protocol, int direction) 993 { 994 return EOPNOTSUPP; 995 } 996 997 998 status_t 999 udp_send_routed_data(net_protocol *protocol, struct net_route *route, 1000 net_buffer *buffer) 1001 { 1002 TRACE(("udp_send_routed_data(%p) size=%lu\n", protocol, buffer->size)); 1003 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 1004 return udpEndpoint->SendData(buffer, route); 1005 } 1006 1007 1008 status_t 1009 udp_send_data(net_protocol *protocol, net_buffer *buffer) 1010 { 1011 TRACE(("udp_send_data(%p) size=%lu\n", protocol, buffer->size)); 1012 1013 struct net_route *route = sDatalinkModule->get_route(sDomain, 1014 (sockaddr *)&buffer->destination); 1015 if (route == NULL) 1016 return ENETUNREACH; 1017 1018 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 1019 status_t status = udpEndpoint->SendData(buffer, route); 1020 sDatalinkModule->put_route(sDomain, route); 1021 return status; 1022 } 1023 1024 1025 ssize_t 1026 udp_send_avail(net_protocol *protocol) 1027 { 1028 ssize_t avail = protocol->socket->send.buffer_size; 1029 TRACE(("udp_send_avail(%p) result=%lu\n", protocol, avail)); 1030 return avail; 1031 } 1032 1033 1034 status_t 1035 udp_read_data(net_protocol *protocol, size_t numBytes, uint32 flags, 1036 net_buffer **_buffer) 1037 { 1038 TRACE(("udp_read_data(%p) size=%lu flags=%lx\n", protocol, numBytes, flags)); 1039 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 1040 return udpEndpoint->FetchData(numBytes, flags, _buffer); 1041 } 1042 1043 1044 ssize_t 1045 udp_read_avail(net_protocol *protocol) 1046 { 1047 UdpEndpoint *udpEndpoint = (UdpEndpoint *)protocol; 1048 return udpEndpoint->BytesAvailable(); 1049 } 1050 1051 1052 struct net_domain * 1053 udp_get_domain(net_protocol *protocol) 1054 { 1055 return protocol->next->module->get_domain(protocol->next); 1056 } 1057 1058 1059 size_t 1060 udp_get_mtu(net_protocol *protocol, const struct sockaddr *address) 1061 { 1062 return protocol->next->module->get_mtu(protocol->next, address); 1063 } 1064 1065 1066 status_t 1067 udp_receive_data(net_buffer *buffer) 1068 { 1069 TRACE(("udp_receive_data() size=%lu\n", buffer->size)); 1070 return sUdpEndpointManager->ReceiveData(buffer); 1071 } 1072 1073 1074 status_t 1075 udp_error(uint32 code, net_buffer *data) 1076 { 1077 return B_ERROR; 1078 } 1079 1080 1081 status_t 1082 udp_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code, 1083 void *errorData) 1084 { 1085 return B_ERROR; 1086 } 1087 1088 1089 // #pragma mark - module interface 1090 1091 1092 static status_t 1093 init_udp() 1094 { 1095 status_t status; 1096 TRACE(("init_udp()\n")); 1097 1098 status = get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule); 1099 if (status < B_OK) 1100 return status; 1101 status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule); 1102 if (status < B_OK) 1103 goto err1; 1104 status = get_module(NET_DATALINK_MODULE_NAME, (module_info **)&sDatalinkModule); 1105 if (status < B_OK) 1106 goto err2; 1107 1108 sUdpEndpointManager = new (std::nothrow) UdpEndpointManager; 1109 if (sUdpEndpointManager == NULL) { 1110 status = ENOBUFS; 1111 goto err3; 1112 } 1113 status = sUdpEndpointManager->InitCheck(); 1114 if (status != B_OK) 1115 goto err3; 1116 1117 status = sStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_IP, 1118 "network/protocols/udp/v1", 1119 "network/protocols/ipv4/v1", 1120 NULL); 1121 if (status < B_OK) 1122 goto err4; 1123 status = sStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 1124 "network/protocols/udp/v1", 1125 "network/protocols/ipv4/v1", 1126 NULL); 1127 if (status < B_OK) 1128 goto err4; 1129 1130 status = sStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_UDP, 1131 "network/protocols/udp/v1"); 1132 if (status < B_OK) 1133 goto err4; 1134 1135 return B_OK; 1136 1137 err4: 1138 delete sUdpEndpointManager; 1139 err3: 1140 put_module(NET_DATALINK_MODULE_NAME); 1141 err2: 1142 put_module(NET_BUFFER_MODULE_NAME); 1143 err1: 1144 put_module(NET_STACK_MODULE_NAME); 1145 1146 TRACE(("init_udp() fails with %lx (%s)\n", status, strerror(status))); 1147 return status; 1148 } 1149 1150 1151 static status_t 1152 uninit_udp() 1153 { 1154 TRACE(("uninit_udp()\n")); 1155 delete sUdpEndpointManager; 1156 put_module(NET_DATALINK_MODULE_NAME); 1157 put_module(NET_BUFFER_MODULE_NAME); 1158 put_module(NET_STACK_MODULE_NAME); 1159 return B_OK; 1160 } 1161 1162 1163 static status_t 1164 udp_std_ops(int32 op, ...) 1165 { 1166 switch (op) { 1167 case B_MODULE_INIT: 1168 return init_udp(); 1169 1170 case B_MODULE_UNINIT: 1171 return uninit_udp(); 1172 1173 default: 1174 return B_ERROR; 1175 } 1176 } 1177 1178 1179 net_protocol_module_info sUDPModule = { 1180 { 1181 "network/protocols/udp/v1", 1182 0, 1183 udp_std_ops 1184 }, 1185 udp_init_protocol, 1186 udp_uninit_protocol, 1187 udp_open, 1188 udp_close, 1189 udp_free, 1190 udp_connect, 1191 udp_accept, 1192 udp_control, 1193 udp_bind, 1194 udp_unbind, 1195 udp_listen, 1196 udp_shutdown, 1197 udp_send_data, 1198 udp_send_routed_data, 1199 udp_send_avail, 1200 udp_read_data, 1201 udp_read_avail, 1202 udp_get_domain, 1203 udp_get_mtu, 1204 udp_receive_data, 1205 udp_error, 1206 udp_error_reply, 1207 }; 1208 1209 module_info *modules[] = { 1210 (module_info *)&sUDPModule, 1211 NULL 1212 }; 1213