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