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