xref: /haiku/src/add-ons/kernel/network/protocols/udp/udp.cpp (revision d86f48f3f5a6ca5039ee8f2190c97906d976f2d1)
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