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