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