xref: /haiku/src/add-ons/kernel/network/protocols/udp/udp.cpp (revision 0041b382147b19ee82ba05e36f007951892c2223)
1 /*
2  * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Oliver Tappe, zooey@hirschkaefer.de
7  *		Hugo Santos, hugosantos@gmail.com
8  */
9 
10 
11 #include <net_buffer.h>
12 #include <net_datalink.h>
13 #include <net_protocol.h>
14 #include <net_stack.h>
15 
16 #include <icmp.h>
17 
18 #include <lock.h>
19 #include <util/AutoLock.h>
20 #include <util/DoublyLinkedList.h>
21 #include <util/OpenHashTable.h>
22 
23 #include <KernelExport.h>
24 
25 #include <NetBufferUtilities.h>
26 #include <NetUtilities.h>
27 #include <ProtocolUtilities.h>
28 
29 #include <algorithm>
30 #include <netinet/in.h>
31 #include <netinet/ip.h>
32 #include <new>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <utility>
36 
37 
38 // NOTE the locking protocol dictates that we must hold UdpDomainSupport's
39 //      lock before holding a child UdpEndpoint's lock. This restriction
40 //      is dictated by the receive path as blind access to the endpoint
41 //      hash is required when holding the DomainSupport's lock.
42 
43 
44 //#define TRACE_UDP
45 #ifdef TRACE_UDP
46 #	define TRACE_BLOCK(x) dump_block x
47 // do not remove the space before ', ##args' if you want this
48 // to compile with gcc 2.95
49 #	define TRACE_EP(format, args...)	dprintf("UDP [%llu] %p " format "\n", \
50 		system_time(), this , ##args)
51 #	define TRACE_EPM(format, args...)	dprintf("UDP [%llu] " format "\n", \
52 		system_time() , ##args)
53 #	define TRACE_DOMAIN(format, args...)	dprintf("UDP [%llu] (%d) " format \
54 		"\n", system_time(), Domain()->family , ##args)
55 #else
56 #	define TRACE_BLOCK(x)
57 #	define TRACE_EP(args...)	do { } while (0)
58 #	define TRACE_EPM(args...)	do { } while (0)
59 #	define TRACE_DOMAIN(args...)	do { } while (0)
60 #endif
61 
62 
63 struct udp_header {
64 	uint16 source_port;
65 	uint16 destination_port;
66 	uint16 udp_length;
67 	uint16 udp_checksum;
68 } _PACKED;
69 
70 
71 typedef NetBufferField<uint16, offsetof(udp_header, udp_checksum)>
72 	UDPChecksumField;
73 
74 class UdpDomainSupport;
75 
76 class UdpEndpoint : public net_protocol, public DatagramSocket<> {
77 public:
78 	UdpEndpoint(net_socket *socket);
79 
80 	status_t				Bind(const sockaddr *newAddr);
81 	status_t				Unbind(sockaddr *newAddr);
82 	status_t				Connect(const sockaddr *newAddr);
83 
84 	status_t				Open();
85 	status_t				Close();
86 	status_t				Free();
87 
88 	status_t				SendRoutedData(net_buffer *buffer,
89 								net_route *route);
90 	status_t				SendData(net_buffer *buffer);
91 
92 	ssize_t					BytesAvailable();
93 	status_t				FetchData(size_t numBytes, uint32 flags,
94 								net_buffer **_buffer);
95 
96 	status_t				StoreData(net_buffer *buffer);
97 	status_t				DeliverData(net_buffer *buffer);
98 
99 	// only the domain support will change/check the Active flag so
100 	// we don't really need to protect it with the socket lock.
101 	bool					IsActive() const { return fActive; }
102 	void					SetActive(bool newValue) { fActive = newValue; }
103 
104 	UdpEndpoint				*&HashTableLink() { return fLink; }
105 
106 private:
107 	UdpDomainSupport		*fManager;
108 	bool					fActive;
109 								// an active UdpEndpoint is part of the
110 								// endpoint hash (and it is bound and optionally
111 								// connected)
112 
113 	UdpEndpoint				*fLink;
114 };
115 
116 
117 class UdpDomainSupport;
118 
119 struct UdpHashDefinition {
120 	typedef net_address_module_info ParentType;
121 	typedef std::pair<const sockaddr *, const sockaddr *> KeyType;
122 	typedef UdpEndpoint ValueType;
123 
124 	UdpHashDefinition(net_address_module_info *_module)
125 		: module(_module) {}
126 	UdpHashDefinition(const UdpHashDefinition& definition)
127 		: module(definition.module) {}
128 
129 	size_t HashKey(const KeyType &key) const
130 	{
131 		return _Mix(module->hash_address_pair(key.first, key.second));
132 	}
133 
134 	size_t Hash(UdpEndpoint *endpoint) const
135 	{
136 		return _Mix(endpoint->LocalAddress().HashPair(
137 			*endpoint->PeerAddress()));
138 	}
139 
140 	static size_t _Mix(size_t hash)
141 	{
142 		// move the bits into the relevant range (as defined by kNumHashBuckets)
143 		return (hash & 0x000007FF) ^ (hash & 0x003FF800) >> 11
144 			^ (hash & 0xFFC00000UL) >> 22;
145 	}
146 
147 	bool Compare(const KeyType &key, UdpEndpoint *endpoint) const
148 	{
149 		return endpoint->LocalAddress().EqualTo(key.first, true)
150 			&& endpoint->PeerAddress().EqualTo(key.second, true);
151 	}
152 
153 	UdpEndpoint *&GetLink(UdpEndpoint *endpoint) const
154 	{
155 		return endpoint->HashTableLink();
156 	}
157 
158 	net_address_module_info *module;
159 };
160 
161 
162 class UdpDomainSupport : public DoublyLinkedListLinkImpl<UdpDomainSupport> {
163 public:
164 	UdpDomainSupport(net_domain *domain);
165 	~UdpDomainSupport();
166 
167 	status_t Init();
168 
169 	net_domain *Domain() const { return fDomain; }
170 
171 	void Ref() { fEndpointCount++; }
172 	bool Put() { fEndpointCount--; return fEndpointCount == 0; }
173 
174 	status_t DemuxIncomingBuffer(net_buffer* buffer);
175 	status_t DeliverError(status_t error, net_buffer* buffer);
176 
177 	status_t BindEndpoint(UdpEndpoint *endpoint, const sockaddr *address);
178 	status_t ConnectEndpoint(UdpEndpoint *endpoint, const sockaddr *address);
179 	status_t UnbindEndpoint(UdpEndpoint *endpoint);
180 
181 	void DumpEndpoints() const;
182 
183 private:
184 	status_t _BindEndpoint(UdpEndpoint *endpoint, const sockaddr *address);
185 	status_t _Bind(UdpEndpoint *endpoint, const sockaddr *address);
186 	status_t _BindToEphemeral(UdpEndpoint *endpoint, const sockaddr *address);
187 	status_t _FinishBind(UdpEndpoint *endpoint, const sockaddr *address);
188 
189 	UdpEndpoint *_FindActiveEndpoint(const sockaddr *ourAddress,
190 		const sockaddr *peerAddress);
191 	UdpEndpoint* _EndpointFor(net_buffer* buffer);
192 	status_t _DemuxBroadcast(net_buffer *buffer);
193 	status_t _DemuxUnicast(net_buffer *buffer);
194 
195 	uint16 _GetNextEphemeral();
196 	UdpEndpoint *_EndpointWithPort(uint16 port) const;
197 
198 	net_address_module_info *AddressModule() const
199 		{ return fDomain->address_module; }
200 
201 	typedef BOpenHashTable<UdpHashDefinition, false> EndpointTable;
202 
203 	mutex			fLock;
204 	net_domain		*fDomain;
205 	uint16			fLastUsedEphemeral;
206 	EndpointTable	fActiveEndpoints;
207 	uint32			fEndpointCount;
208 
209 	static const uint16		kFirst = 49152;
210 	static const uint16		kLast = 65535;
211 	static const uint32		kNumHashBuckets = 0x800;
212 							// if you change this, adjust the shifting in
213 							// Hash() accordingly!
214 };
215 
216 
217 typedef DoublyLinkedList<UdpDomainSupport> UdpDomainList;
218 
219 
220 class UdpEndpointManager {
221 public:
222 								UdpEndpointManager();
223 								~UdpEndpointManager();
224 
225 			status_t			InitCheck() const;
226 
227 			status_t			ReceiveData(net_buffer* buffer);
228 			status_t			ReceiveError(status_t error,
229 									net_buffer* buffer);
230 			status_t			Deframe(net_buffer* buffer);
231 
232 			UdpDomainSupport*	OpenEndpoint(UdpEndpoint* endpoint);
233 			status_t			FreeEndpoint(UdpDomainSupport* domain);
234 
235 	static	int					DumpEndpoints(int argc, char *argv[]);
236 
237 private:
238 			UdpDomainSupport*	_GetDomain(net_domain *domain, bool create);
239 			UdpDomainSupport*	_GetDomain(net_buffer* buffer);
240 
241 			mutex				fLock;
242 			status_t			fStatus;
243 			UdpDomainList		fDomains;
244 };
245 
246 
247 static UdpEndpointManager *sUdpEndpointManager;
248 
249 net_buffer_module_info *gBufferModule;
250 net_datalink_module_info *gDatalinkModule;
251 net_stack_module_info *gStackModule;
252 net_socket_module_info *gSocketModule;
253 
254 
255 // #pragma mark -
256 
257 
258 UdpDomainSupport::UdpDomainSupport(net_domain *domain)
259 	:
260 	fDomain(domain),
261 	fActiveEndpoints(domain->address_module),
262 	fEndpointCount(0)
263 {
264 	mutex_init(&fLock, "udp domain");
265 
266 	fLastUsedEphemeral = kFirst + rand() % (kLast - kFirst);
267 }
268 
269 
270 UdpDomainSupport::~UdpDomainSupport()
271 {
272 	mutex_destroy(&fLock);
273 }
274 
275 
276 status_t
277 UdpDomainSupport::Init()
278 {
279 	return fActiveEndpoints.Init(kNumHashBuckets);
280 }
281 
282 
283 status_t
284 UdpDomainSupport::DemuxIncomingBuffer(net_buffer *buffer)
285 {
286 	// NOTE: multicast is delivered directly to the endpoint
287 	MutexLocker _(fLock);
288 
289 	if ((buffer->flags & MSG_BCAST) != 0)
290 		return _DemuxBroadcast(buffer);
291 	if ((buffer->flags & MSG_MCAST) != 0)
292 		return B_ERROR;
293 
294 	return _DemuxUnicast(buffer);
295 }
296 
297 
298 status_t
299 UdpDomainSupport::DeliverError(status_t error, net_buffer* buffer)
300 {
301 	if ((buffer->flags & (MSG_BCAST | MSG_MCAST)) != 0)
302 		return B_ERROR;
303 
304 	MutexLocker _(fLock);
305 
306 	// RFC 1122 4.1.3.3:
307 	// TODO: Pass to the application layer all ICMP error messages
308 
309 	UdpEndpoint* endpoint = _EndpointFor(buffer);
310 	if (endpoint != NULL)
311 		gSocketModule->notify(endpoint->Socket(), B_SELECT_ERROR, error);
312 
313 	gBufferModule->free(buffer);
314 	return B_OK;
315 }
316 
317 
318 status_t
319 UdpDomainSupport::BindEndpoint(UdpEndpoint *endpoint,
320 	const sockaddr *address)
321 {
322 	if (!AddressModule()->is_same_family(address))
323 		return EAFNOSUPPORT;
324 
325 	MutexLocker _(fLock);
326 
327 	if (endpoint->IsActive())
328 		return EINVAL;
329 
330 	return _BindEndpoint(endpoint, address);
331 }
332 
333 
334 status_t
335 UdpDomainSupport::ConnectEndpoint(UdpEndpoint *endpoint,
336 	const sockaddr *address)
337 {
338 	MutexLocker _(fLock);
339 
340 	if (endpoint->IsActive()) {
341 		fActiveEndpoints.Remove(endpoint);
342 		endpoint->SetActive(false);
343 	}
344 
345 	if (address->sa_family == AF_UNSPEC) {
346 		// [Stevens-UNP1, p226]: specifying AF_UNSPEC requests a "disconnect",
347 		// so we reset the peer address:
348 		endpoint->PeerAddress().SetToEmpty();
349 	} else {
350 		if (!AddressModule()->is_same_family(address))
351 			return EAFNOSUPPORT;
352 
353 		// consider destination address INADDR_ANY as INADDR_LOOPBACK
354 		sockaddr_storage _address;
355 		if (AddressModule()->is_empty_address(address, false)) {
356 			AddressModule()->get_loopback_address((sockaddr *)&_address);
357 			// for IPv4 and IPv6 the port is at the same offset
358 			((sockaddr_in&)_address).sin_port
359 				= ((sockaddr_in *)address)->sin_port;
360 			address = (sockaddr *)&_address;
361 		}
362 
363 		status_t status = endpoint->PeerAddress().SetTo(address);
364 		if (status < B_OK)
365 			return status;
366 		struct net_route *routeToDestination
367 			= gDatalinkModule->get_route(fDomain, address);
368 		if (routeToDestination) {
369 			status = endpoint->LocalAddress().SetTo(
370 				routeToDestination->interface->address);
371 			gDatalinkModule->put_route(fDomain, routeToDestination);
372 			if (status < B_OK)
373 				return status;
374 		}
375 	}
376 
377 	// we need to activate no matter whether or not we have just disconnected,
378 	// as calling connect() always triggers an implicit bind():
379 	return _BindEndpoint(endpoint, *endpoint->LocalAddress());
380 }
381 
382 
383 status_t
384 UdpDomainSupport::UnbindEndpoint(UdpEndpoint *endpoint)
385 {
386 	MutexLocker _(fLock);
387 
388 	if (endpoint->IsActive())
389 		fActiveEndpoints.Remove(endpoint);
390 
391 	endpoint->SetActive(false);
392 
393 	return B_OK;
394 }
395 
396 
397 void
398 UdpDomainSupport::DumpEndpoints() const
399 {
400 	kprintf("-------- UDP Domain %p ---------\n", this);
401 	kprintf("%10s %20s %20s %8s\n", "address", "local", "peer", "recv-q");
402 
403 	EndpointTable::Iterator it = fActiveEndpoints.GetIterator();
404 
405 	while (it.HasNext()) {
406 		UdpEndpoint *endpoint = it.Next();
407 
408 		char localBuf[64], peerBuf[64];
409 		endpoint->LocalAddress().AsString(localBuf, sizeof(localBuf), true);
410 		endpoint->PeerAddress().AsString(peerBuf, sizeof(peerBuf), true);
411 
412 		kprintf("%p %20s %20s %8lu\n", endpoint, localBuf, peerBuf,
413 			endpoint->AvailableData());
414 	}
415 }
416 
417 
418 status_t
419 UdpDomainSupport::_BindEndpoint(UdpEndpoint *endpoint,
420 	const sockaddr *address)
421 {
422 	if (AddressModule()->get_port(address) == 0)
423 		return _BindToEphemeral(endpoint, address);
424 
425 	return _Bind(endpoint, address);
426 }
427 
428 
429 status_t
430 UdpDomainSupport::_Bind(UdpEndpoint *endpoint, const sockaddr *address)
431 {
432 	int socketOptions = endpoint->Socket()->options;
433 
434 	EndpointTable::Iterator it = fActiveEndpoints.GetIterator();
435 
436 	// Iterate over all active UDP-endpoints and check if the requested bind
437 	// is allowed (see figure 22.24 in [Stevens - TCP2, p735]):
438 	TRACE_DOMAIN("CheckBindRequest() for %s...", AddressString(fDomain,
439 		address, true).Data());
440 
441 	while (it.HasNext()) {
442 		UdpEndpoint *otherEndpoint = it.Next();
443 
444 		TRACE_DOMAIN("  ...checking endpoint %p (port=%u)...", otherEndpoint,
445 			ntohs(otherEndpoint->LocalAddress().Port()));
446 
447 		if (otherEndpoint->LocalAddress().EqualPorts(address)) {
448 			// port is already bound, SO_REUSEADDR or SO_REUSEPORT is required:
449 			if ((otherEndpoint->Socket()->options
450 					& (SO_REUSEADDR | SO_REUSEPORT)) == 0
451 				|| (socketOptions & (SO_REUSEADDR | SO_REUSEPORT)) == 0)
452 				return EADDRINUSE;
453 
454 			// if both addresses are the same, SO_REUSEPORT is required:
455 			if (otherEndpoint->LocalAddress().EqualTo(address, false)
456 				&& ((otherEndpoint->Socket()->options & SO_REUSEPORT) == 0
457 					|| (socketOptions & SO_REUSEPORT) == 0))
458 				return EADDRINUSE;
459 		}
460 	}
461 
462 	return _FinishBind(endpoint, address);
463 }
464 
465 
466 status_t
467 UdpDomainSupport::_BindToEphemeral(UdpEndpoint *endpoint,
468 	const sockaddr *address)
469 {
470 	SocketAddressStorage newAddress(AddressModule());
471 	status_t status = newAddress.SetTo(address);
472 	if (status < B_OK)
473 		return status;
474 
475 	uint16 allocedPort = _GetNextEphemeral();
476 	if (allocedPort == 0)
477 		return ENOBUFS;
478 
479 	newAddress.SetPort(htons(allocedPort));
480 
481 	return _FinishBind(endpoint, *newAddress);
482 }
483 
484 
485 status_t
486 UdpDomainSupport::_FinishBind(UdpEndpoint *endpoint, const sockaddr *address)
487 {
488 	status_t status = endpoint->next->module->bind(endpoint->next, address);
489 	if (status < B_OK)
490 		return status;
491 
492 	fActiveEndpoints.Insert(endpoint);
493 	endpoint->SetActive(true);
494 
495 	return B_OK;
496 }
497 
498 
499 UdpEndpoint *
500 UdpDomainSupport::_FindActiveEndpoint(const sockaddr *ourAddress,
501 	const sockaddr *peerAddress)
502 {
503 	TRACE_DOMAIN("finding Endpoint for %s <- %s",
504 		AddressString(fDomain, ourAddress, true).Data(),
505 		AddressString(fDomain, peerAddress, true).Data());
506 
507 	return fActiveEndpoints.Lookup(std::make_pair(ourAddress, peerAddress));
508 }
509 
510 
511 UdpEndpoint*
512 UdpDomainSupport::_EndpointFor(net_buffer* buffer)
513 {
514 	ASSERT_LOCKED_MUTEX(&fLock);
515 
516 	struct sockaddr *peerAddr = buffer->source;
517 	struct sockaddr *localAddr = buffer->destination;
518 
519 	// look for full (most special) match:
520 	UdpEndpoint* endpoint = _FindActiveEndpoint(localAddr, peerAddr);
521 	if (endpoint != NULL)
522 		return endpoint;
523 
524 	// look for endpoint matching local address & port:
525 	endpoint = _FindActiveEndpoint(localAddr, NULL);
526 	if (endpoint != NULL)
527 		return endpoint;
528 
529 	// look for endpoint matching peer address & port and local port:
530 	SocketAddressStorage local(AddressModule());
531 	local.SetToEmpty();
532 	local.SetPort(AddressModule()->get_port(localAddr));
533 	endpoint = _FindActiveEndpoint(*local, peerAddr);
534 	if (endpoint != NULL)
535 		return endpoint;
536 
537 	// last chance: look for endpoint matching local port only:
538 	return _FindActiveEndpoint(*local, NULL);
539 }
540 
541 
542 status_t
543 UdpDomainSupport::_DemuxBroadcast(net_buffer *buffer)
544 {
545 	sockaddr *peerAddr = buffer->source;
546 	sockaddr *broadcastAddr = buffer->destination;
547 	sockaddr *mask = NULL;
548 	if (buffer->interface)
549 		mask = (sockaddr *)buffer->interface->mask;
550 
551 	TRACE_DOMAIN("_DemuxBroadcast(%p)", buffer);
552 
553 	uint16 incomingPort = AddressModule()->get_port(broadcastAddr);
554 
555 	EndpointTable::Iterator it = fActiveEndpoints.GetIterator();
556 
557 	while (it.HasNext()) {
558 		UdpEndpoint *endpoint = it.Next();
559 
560 		TRACE_DOMAIN("  _DemuxBroadcast(): checking endpoint %s...",
561 			AddressString(fDomain, *endpoint->LocalAddress(), true).Data());
562 
563 		if (endpoint->LocalAddress().Port() != incomingPort) {
564 			// ports don't match, so we do not dispatch to this endpoint...
565 			continue;
566 		}
567 
568 		if (!endpoint->PeerAddress().IsEmpty(true)) {
569 			// endpoint is connected to a specific destination, we check if
570 			// this datagram is from there:
571 			if (!endpoint->PeerAddress().EqualTo(peerAddr, true)) {
572 				// no, datagram is from another peer, so we do not dispatch to
573 				// this endpoint...
574 				continue;
575 			}
576 		}
577 
578 		if (endpoint->LocalAddress().MatchMasked(broadcastAddr, mask)
579 			|| endpoint->LocalAddress().IsEmpty(false)) {
580 			// address matches, dispatch to this endpoint:
581 			endpoint->StoreData(buffer);
582 		}
583 	}
584 
585 	return B_OK;
586 }
587 
588 
589 status_t
590 UdpDomainSupport::_DemuxUnicast(net_buffer *buffer)
591 {
592 	TRACE_DOMAIN("_DemuxUnicast(%p)", buffer);
593 
594 	UdpEndpoint* endpoint = _EndpointFor(buffer);
595 	if (endpoint == NULL) {
596 		TRACE_DOMAIN("_DemuxUnicast(%p) - no matching endpoint found!", buffer);
597 		return B_NAME_NOT_FOUND;
598 	}
599 
600 	endpoint->StoreData(buffer);
601 	return B_OK;
602 }
603 
604 
605 uint16
606 UdpDomainSupport::_GetNextEphemeral()
607 {
608 	uint16 stop, curr;
609 	if (fLastUsedEphemeral < kLast) {
610 		stop = fLastUsedEphemeral;
611 		curr = fLastUsedEphemeral + 1;
612 	} else {
613 		stop = kLast;
614 		curr = kFirst;
615 	}
616 
617 	TRACE_DOMAIN("_GetNextEphemeral(), last %hu, curr %hu, stop %hu",
618 		fLastUsedEphemeral, curr, stop);
619 
620 	// TODO: a free list could be used to avoid the impact of these two
621 	//        nested loops most of the time... let's see how bad this really is
622 	for (; curr != stop; curr = (curr < kLast) ? (curr + 1) : kFirst) {
623 		TRACE_DOMAIN("  _GetNextEphemeral(): trying port %hu...", curr);
624 
625 		if (_EndpointWithPort(htons(curr)) == NULL) {
626 			TRACE_DOMAIN("  _GetNextEphemeral(): ...using port %hu", curr);
627 			fLastUsedEphemeral = curr;
628 			return curr;
629 		}
630 	}
631 
632 	return 0;
633 }
634 
635 
636 UdpEndpoint *
637 UdpDomainSupport::_EndpointWithPort(uint16 port) const
638 {
639 	EndpointTable::Iterator it = fActiveEndpoints.GetIterator();
640 
641 	while (it.HasNext()) {
642 		UdpEndpoint *endpoint = it.Next();
643 		if (endpoint->LocalAddress().Port() == port)
644 			return endpoint;
645 	}
646 
647 	return NULL;
648 }
649 
650 
651 // #pragma mark -
652 
653 
654 UdpEndpointManager::UdpEndpointManager()
655 {
656 	mutex_init(&fLock, "UDP endpoints");
657 	fStatus = B_OK;
658 }
659 
660 
661 UdpEndpointManager::~UdpEndpointManager()
662 {
663 	mutex_destroy(&fLock);
664 }
665 
666 
667 status_t
668 UdpEndpointManager::InitCheck() const
669 {
670 	return fStatus;
671 }
672 
673 
674 int
675 UdpEndpointManager::DumpEndpoints(int argc, char *argv[])
676 {
677 	UdpDomainList::Iterator it = sUdpEndpointManager->fDomains.GetIterator();
678 
679 	while (it.HasNext())
680 		it.Next()->DumpEndpoints();
681 
682 	return 0;
683 }
684 
685 
686 // #pragma mark - inbound
687 
688 
689 status_t
690 UdpEndpointManager::ReceiveData(net_buffer *buffer)
691 {
692 	TRACE_EPM("ReceiveData(%p [%" B_PRIu32 " bytes])", buffer, buffer->size);
693 
694 	UdpDomainSupport* domainSupport = _GetDomain(buffer);
695 	if (domainSupport == NULL) {
696 		// we don't instantiate domain supports in the receiving path, as
697 		// we are only interested in delivering data to existing sockets.
698 		return B_ERROR;
699 	}
700 
701 	status_t status = Deframe(buffer);
702 	if (status != B_OK)
703 		return status;
704 
705 	status = domainSupport->DemuxIncomingBuffer(buffer);
706 	if (status != B_OK) {
707 		TRACE_EPM("  ReceiveData(): no endpoint.");
708 		// Send port unreachable error
709 		domainSupport->Domain()->module->error_reply(NULL, buffer,
710 			icmp_encode(ICMP_TYPE_UNREACH, ICMP_CODE_PORT_UNREACH), NULL);
711 		return B_ERROR;
712 	}
713 
714 	gBufferModule->free(buffer);
715 	return B_OK;
716 }
717 
718 
719 status_t
720 UdpEndpointManager::ReceiveError(status_t error, net_buffer* buffer)
721 {
722 	TRACE_EPM("ReceiveError(code %" B_PRId32 " %p [%" B_PRIu32 " bytes])",
723 		error, buffer, buffer->size);
724 
725 	// We only really need the port information
726 	if (buffer->size < 4)
727 		return B_BAD_VALUE;
728 
729 	UdpDomainSupport* domainSupport = _GetDomain(buffer);
730 	if (domainSupport == NULL) {
731 		// we don't instantiate domain supports in the receiving path, as
732 		// we are only interested in delivering data to existing sockets.
733 		return B_ERROR;
734 	}
735 
736 	// Deframe the buffer manually, as we usually only get 8 bytes from the
737 	// original packet
738 	udp_header header;
739 	if (gBufferModule->read(buffer, 0, &header,
740 			std::min(buffer->size, sizeof(udp_header))) != B_OK)
741 		return B_BAD_VALUE;
742 
743 	net_domain* domain = buffer->interface->domain;
744 	net_address_module_info* addressModule = domain->address_module;
745 
746 	SocketAddress source(addressModule, buffer->source);
747 	SocketAddress destination(addressModule, buffer->destination);
748 
749 	source.SetPort(header.source_port);
750 	destination.SetPort(header.destination_port);
751 
752 	status_t status = domainSupport->DeliverError(error, buffer);
753 	if (status != B_OK)
754 		return status;
755 
756 	gBufferModule->free(buffer);
757 	return B_OK;
758 }
759 
760 
761 status_t
762 UdpEndpointManager::Deframe(net_buffer *buffer)
763 {
764 	TRACE_EPM("Deframe(%p [%ld bytes])", buffer, buffer->size);
765 
766 	NetBufferHeaderReader<udp_header> bufferHeader(buffer);
767 	if (bufferHeader.Status() < B_OK)
768 		return bufferHeader.Status();
769 
770 	udp_header &header = bufferHeader.Data();
771 
772 	if (buffer->interface == NULL || buffer->interface->domain == NULL) {
773 		TRACE_EPM("  Deframe(): UDP packed dropped as there was no domain "
774 			"specified (interface %p).", buffer->interface);
775 		return B_BAD_VALUE;
776 	}
777 
778 	net_domain *domain = buffer->interface->domain;
779 	net_address_module_info *addressModule = domain->address_module;
780 
781 	SocketAddress source(addressModule, buffer->source);
782 	SocketAddress destination(addressModule, buffer->destination);
783 
784 	source.SetPort(header.source_port);
785 	destination.SetPort(header.destination_port);
786 
787 	TRACE_EPM("  Deframe(): data from %s to %s", source.AsString(true).Data(),
788 		destination.AsString(true).Data());
789 
790 	uint16 udpLength = ntohs(header.udp_length);
791 	if (udpLength > buffer->size) {
792 		TRACE_EPM("  Deframe(): buffer is too short, expected %hu.",
793 			udpLength);
794 		return B_MISMATCHED_VALUES;
795 	}
796 
797 	if (buffer->size > udpLength)
798 		gBufferModule->trim(buffer, udpLength);
799 
800 	if (header.udp_checksum != 0) {
801 		// check UDP-checksum (simulating a so-called "pseudo-header"):
802 		uint16 sum = Checksum::PseudoHeader(addressModule, gBufferModule,
803 			buffer, IPPROTO_UDP);
804 		if (sum != 0) {
805 			TRACE_EPM("  Deframe(): bad checksum 0x%hx.", sum);
806 			return B_BAD_VALUE;
807 		}
808 	}
809 
810 	bufferHeader.Remove();
811 		// remove UDP-header from buffer before passing it on
812 
813 	return B_OK;
814 }
815 
816 
817 UdpDomainSupport *
818 UdpEndpointManager::OpenEndpoint(UdpEndpoint *endpoint)
819 {
820 	MutexLocker _(fLock);
821 
822 	UdpDomainSupport *domain = _GetDomain(endpoint->Domain(), true);
823 	if (domain)
824 		domain->Ref();
825 	return domain;
826 }
827 
828 
829 status_t
830 UdpEndpointManager::FreeEndpoint(UdpDomainSupport *domain)
831 {
832 	MutexLocker _(fLock);
833 
834 	if (domain->Put()) {
835 		fDomains.Remove(domain);
836 		delete domain;
837 	}
838 
839 	return B_OK;
840 }
841 
842 
843 // #pragma mark -
844 
845 
846 UdpDomainSupport *
847 UdpEndpointManager::_GetDomain(net_domain *domain, bool create)
848 {
849 	UdpDomainList::Iterator it = fDomains.GetIterator();
850 
851 	// TODO convert this into a Hashtable or install per-domain
852 	//      receiver handlers that forward the requests to the
853 	//      appropriate DemuxIncomingBuffer(). For instance, while
854 	//      being constructed UdpDomainSupport could call
855 	//      register_domain_receiving_protocol() with the right
856 	//      family.
857 	while (it.HasNext()) {
858 		UdpDomainSupport *domainSupport = it.Next();
859 		if (domainSupport->Domain() == domain)
860 			return domainSupport;
861 	}
862 
863 	if (!create)
864 		return NULL;
865 
866 	UdpDomainSupport *domainSupport =
867 		new (std::nothrow) UdpDomainSupport(domain);
868 	if (domainSupport == NULL || domainSupport->Init() < B_OK) {
869 		delete domainSupport;
870 		return NULL;
871 	}
872 
873 	fDomains.Add(domainSupport);
874 	return domainSupport;
875 }
876 
877 
878 UdpDomainSupport*
879 UdpEndpointManager::_GetDomain(net_buffer* buffer)
880 {
881 	if (buffer->interface == NULL)
882 		return NULL;
883 
884 	MutexLocker _(fLock);
885 	return _GetDomain(buffer->interface->domain, false);
886 		// TODO: we don't want to hold to the manager's lock during the
887 		// whole RX path, we may not hold an endpoint's lock with the
888 		// manager lock held.
889 		// But we should increase the domain's refcount here.
890 }
891 
892 
893 // #pragma mark -
894 
895 
896 UdpEndpoint::UdpEndpoint(net_socket *socket)
897 	: DatagramSocket<>("udp endpoint", socket), fActive(false) {}
898 
899 
900 // #pragma mark - activation
901 
902 
903 status_t
904 UdpEndpoint::Bind(const sockaddr *address)
905 {
906 	TRACE_EP("Bind(%s)", AddressString(Domain(), address, true).Data());
907 	return fManager->BindEndpoint(this, address);
908 }
909 
910 
911 status_t
912 UdpEndpoint::Unbind(sockaddr *address)
913 {
914 	TRACE_EP("Unbind()");
915 	return fManager->UnbindEndpoint(this);
916 }
917 
918 
919 status_t
920 UdpEndpoint::Connect(const sockaddr *address)
921 {
922 	TRACE_EP("Connect(%s)", AddressString(Domain(), address, true).Data());
923 	return fManager->ConnectEndpoint(this, address);
924 }
925 
926 
927 status_t
928 UdpEndpoint::Open()
929 {
930 	TRACE_EP("Open()");
931 
932 	AutoLocker _(fLock);
933 
934 	status_t status = ProtocolSocket::Open();
935 	if (status < B_OK)
936 		return status;
937 
938 	fManager = sUdpEndpointManager->OpenEndpoint(this);
939 	if (fManager == NULL)
940 		return EAFNOSUPPORT;
941 
942 	return B_OK;
943 }
944 
945 
946 status_t
947 UdpEndpoint::Close()
948 {
949 	TRACE_EP("Close()");
950 	return B_OK;
951 }
952 
953 
954 status_t
955 UdpEndpoint::Free()
956 {
957 	TRACE_EP("Free()");
958 	fManager->UnbindEndpoint(this);
959 	return sUdpEndpointManager->FreeEndpoint(fManager);
960 }
961 
962 
963 // #pragma mark - outbound
964 
965 
966 status_t
967 UdpEndpoint::SendRoutedData(net_buffer *buffer, net_route *route)
968 {
969 	TRACE_EP("SendRoutedData(%p [%lu bytes], %p)", buffer, buffer->size, route);
970 
971 	if (buffer->size > (0xffff - sizeof(udp_header)))
972 		return EMSGSIZE;
973 
974 	buffer->protocol = IPPROTO_UDP;
975 
976 	// add and fill UDP-specific header:
977 	NetBufferPrepend<udp_header> header(buffer);
978 	if (header.Status() < B_OK)
979 		return header.Status();
980 
981 	header->source_port = AddressModule()->get_port(buffer->source);
982 	header->destination_port = AddressModule()->get_port(buffer->destination);
983 	header->udp_length = htons(buffer->size);
984 		// the udp-header is already included in the buffer-size
985 	header->udp_checksum = 0;
986 
987 	header.Sync();
988 
989 	uint16 calculatedChecksum = Checksum::PseudoHeader(AddressModule(),
990 		gBufferModule, buffer, IPPROTO_UDP);
991 	if (calculatedChecksum == 0)
992 		calculatedChecksum = 0xffff;
993 
994 	*UDPChecksumField(buffer) = calculatedChecksum;
995 
996 	return next->module->send_routed_data(next, route, buffer);
997 }
998 
999 
1000 status_t
1001 UdpEndpoint::SendData(net_buffer *buffer)
1002 {
1003 	TRACE_EP("SendData(%p [%lu bytes])", buffer, buffer->size);
1004 
1005 	return gDatalinkModule->send_datagram(this, NULL, buffer);
1006 }
1007 
1008 
1009 // #pragma mark - inbound
1010 
1011 
1012 ssize_t
1013 UdpEndpoint::BytesAvailable()
1014 {
1015 	size_t bytes = AvailableData();
1016 	TRACE_EP("BytesAvailable(): %lu", bytes);
1017 	return bytes;
1018 }
1019 
1020 
1021 status_t
1022 UdpEndpoint::FetchData(size_t numBytes, uint32 flags, net_buffer **_buffer)
1023 {
1024 	TRACE_EP("FetchData(%ld, 0x%lx)", numBytes, flags);
1025 
1026 	status_t status = SocketDequeue(flags, _buffer);
1027 	TRACE_EP("  FetchData(): returned from fifo status=0x%lx", status);
1028 	if (status < B_OK)
1029 		return status;
1030 
1031 	TRACE_EP("  FetchData(): returns buffer with %ld bytes", (*_buffer)->size);
1032 	return B_OK;
1033 }
1034 
1035 
1036 status_t
1037 UdpEndpoint::StoreData(net_buffer *buffer)
1038 {
1039 	TRACE_EP("StoreData(%p [%ld bytes])", buffer, buffer->size);
1040 
1041 	return SocketEnqueue(buffer);
1042 }
1043 
1044 
1045 status_t
1046 UdpEndpoint::DeliverData(net_buffer *_buffer)
1047 {
1048 	TRACE_EP("DeliverData(%p [%ld bytes])", _buffer, _buffer->size);
1049 
1050 	net_buffer *buffer = gBufferModule->clone(_buffer, false);
1051 	if (buffer == NULL)
1052 		return B_NO_MEMORY;
1053 
1054 	status_t status = sUdpEndpointManager->Deframe(buffer);
1055 	if (status < B_OK) {
1056 		gBufferModule->free(buffer);
1057 		return status;
1058 	}
1059 
1060 	// we call Enqueue() instead of SocketEnqueue() as there is
1061 	// no need to clone the buffer again.
1062 	return Enqueue(buffer);
1063 }
1064 
1065 
1066 // #pragma mark - protocol interface
1067 
1068 
1069 net_protocol *
1070 udp_init_protocol(net_socket *socket)
1071 {
1072 	socket->protocol = IPPROTO_UDP;
1073 
1074 	UdpEndpoint *endpoint = new (std::nothrow) UdpEndpoint(socket);
1075 	if (endpoint == NULL || endpoint->InitCheck() < B_OK) {
1076 		delete endpoint;
1077 		return NULL;
1078 	}
1079 
1080 	return endpoint;
1081 }
1082 
1083 
1084 status_t
1085 udp_uninit_protocol(net_protocol *protocol)
1086 {
1087 	delete (UdpEndpoint *)protocol;
1088 	return B_OK;
1089 }
1090 
1091 
1092 status_t
1093 udp_open(net_protocol *protocol)
1094 {
1095 	return ((UdpEndpoint *)protocol)->Open();
1096 }
1097 
1098 
1099 status_t
1100 udp_close(net_protocol *protocol)
1101 {
1102 	return ((UdpEndpoint *)protocol)->Close();
1103 }
1104 
1105 
1106 status_t
1107 udp_free(net_protocol *protocol)
1108 {
1109 	return ((UdpEndpoint *)protocol)->Free();
1110 }
1111 
1112 
1113 status_t
1114 udp_connect(net_protocol *protocol, const struct sockaddr *address)
1115 {
1116 	return ((UdpEndpoint *)protocol)->Connect(address);
1117 }
1118 
1119 
1120 status_t
1121 udp_accept(net_protocol *protocol, struct net_socket **_acceptedSocket)
1122 {
1123 	return EOPNOTSUPP;
1124 }
1125 
1126 
1127 status_t
1128 udp_control(net_protocol *protocol, int level, int option, void *value,
1129 	size_t *_length)
1130 {
1131 	return protocol->next->module->control(protocol->next, level, option,
1132 		value, _length);
1133 }
1134 
1135 
1136 status_t
1137 udp_getsockopt(net_protocol *protocol, int level, int option, void *value,
1138 	int *length)
1139 {
1140 	return protocol->next->module->getsockopt(protocol->next, level, option,
1141 		value, length);
1142 }
1143 
1144 
1145 status_t
1146 udp_setsockopt(net_protocol *protocol, int level, int option,
1147 	const void *value, int length)
1148 {
1149 	return protocol->next->module->setsockopt(protocol->next, level, option,
1150 		value, length);
1151 }
1152 
1153 
1154 status_t
1155 udp_bind(net_protocol *protocol, const struct sockaddr *address)
1156 {
1157 	return ((UdpEndpoint *)protocol)->Bind(address);
1158 }
1159 
1160 
1161 status_t
1162 udp_unbind(net_protocol *protocol, struct sockaddr *address)
1163 {
1164 	return ((UdpEndpoint *)protocol)->Unbind(address);
1165 }
1166 
1167 
1168 status_t
1169 udp_listen(net_protocol *protocol, int count)
1170 {
1171 	return EOPNOTSUPP;
1172 }
1173 
1174 
1175 status_t
1176 udp_shutdown(net_protocol *protocol, int direction)
1177 {
1178 	return EOPNOTSUPP;
1179 }
1180 
1181 
1182 status_t
1183 udp_send_routed_data(net_protocol *protocol, struct net_route *route,
1184 	net_buffer *buffer)
1185 {
1186 	return ((UdpEndpoint *)protocol)->SendRoutedData(buffer, route);
1187 }
1188 
1189 
1190 status_t
1191 udp_send_data(net_protocol *protocol, net_buffer *buffer)
1192 {
1193 	return ((UdpEndpoint *)protocol)->SendData(buffer);
1194 }
1195 
1196 
1197 ssize_t
1198 udp_send_avail(net_protocol *protocol)
1199 {
1200 	return protocol->socket->send.buffer_size;
1201 }
1202 
1203 
1204 status_t
1205 udp_read_data(net_protocol *protocol, size_t numBytes, uint32 flags,
1206 	net_buffer **_buffer)
1207 {
1208 	return ((UdpEndpoint *)protocol)->FetchData(numBytes, flags, _buffer);
1209 }
1210 
1211 
1212 ssize_t
1213 udp_read_avail(net_protocol *protocol)
1214 {
1215 	return ((UdpEndpoint *)protocol)->BytesAvailable();
1216 }
1217 
1218 
1219 struct net_domain *
1220 udp_get_domain(net_protocol *protocol)
1221 {
1222 	return protocol->next->module->get_domain(protocol->next);
1223 }
1224 
1225 
1226 size_t
1227 udp_get_mtu(net_protocol *protocol, const struct sockaddr *address)
1228 {
1229 	return protocol->next->module->get_mtu(protocol->next, address);
1230 }
1231 
1232 
1233 status_t
1234 udp_receive_data(net_buffer *buffer)
1235 {
1236 	return sUdpEndpointManager->ReceiveData(buffer);
1237 }
1238 
1239 
1240 status_t
1241 udp_deliver_data(net_protocol *protocol, net_buffer *buffer)
1242 {
1243 	return ((UdpEndpoint *)protocol)->DeliverData(buffer);
1244 }
1245 
1246 
1247 status_t
1248 udp_error_received(uint32 code, net_buffer* buffer)
1249 {
1250 	uint8 icmpType, icmpCode;
1251 	icmp_decode(code, icmpType, icmpCode);
1252 
1253 	status_t error = B_OK;
1254 	switch (icmpType) {
1255 		case ICMP_TYPE_UNREACH:
1256 			if (icmpCode == ICMP_CODE_NET_UNREACH)
1257 				error = ENETUNREACH;
1258 			else if (icmpCode == ICMP_CODE_HOST_UNREACH)
1259 				error = EHOSTUNREACH;
1260 			else if (icmpCode == ICMP_CODE_SOURCE_ROUTE_FAIL)
1261 				error = EOPNOTSUPP;
1262 			else if (icmpCode == ICMP_CODE_PROTO_UNREACH)
1263 				error = ENOPROTOOPT;
1264 			else if (icmpCode == ICMP_CODE_PORT_UNREACH)
1265 				error = ECONNREFUSED;
1266 			else if (icmpCode == ICMP_CODE_FRAG_NEEDED)
1267 				error = EMSGSIZE;
1268 			else
1269 				error = EOPNOTSUPP;
1270 			break;
1271 		case ICMP_TYPE_TIME_EXCEEDED:
1272 			error = EHOSTUNREACH;
1273 			break;
1274 		case ICMP_TYPE_PARAM_PROBLEM:
1275 			error = EPROTO;
1276 			break;
1277 		case ICMP_TYPE_SOURCE_QUENCH:
1278 		default:
1279 			// ignore them
1280 			break;
1281 	}
1282 
1283 	if (error != B_OK)
1284 		sUdpEndpointManager->ReceiveError(error, buffer);
1285 
1286 	gBufferModule->free(buffer);
1287 	return B_OK;
1288 }
1289 
1290 
1291 status_t
1292 udp_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
1293 	void *errorData)
1294 {
1295 	return B_ERROR;
1296 }
1297 
1298 
1299 ssize_t
1300 udp_process_ancillary_data_no_container(net_protocol *protocol,
1301 	net_buffer* buffer, void *data, size_t dataSize)
1302 {
1303 	return protocol->next->module->process_ancillary_data_no_container(
1304 		protocol, buffer, data, dataSize);
1305 }
1306 
1307 
1308 //	#pragma mark - module interface
1309 
1310 
1311 static status_t
1312 init_udp()
1313 {
1314 	status_t status;
1315 	TRACE_EPM("init_udp()");
1316 
1317 	sUdpEndpointManager = new (std::nothrow) UdpEndpointManager;
1318 	if (sUdpEndpointManager == NULL)
1319 		return B_NO_MEMORY;
1320 
1321 	status = sUdpEndpointManager->InitCheck();
1322 	if (status != B_OK)
1323 		goto err1;
1324 
1325 	status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_IP,
1326 		"network/protocols/udp/v1",
1327 		"network/protocols/ipv4/v1",
1328 		NULL);
1329 	if (status < B_OK)
1330 		goto err1;
1331 	status = gStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM, IPPROTO_IP,
1332 		"network/protocols/udp/v1",
1333 		"network/protocols/ipv6/v1",
1334 		NULL);
1335 	if (status < B_OK)
1336 		goto err1;
1337 
1338 	status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
1339 		"network/protocols/udp/v1",
1340 		"network/protocols/ipv4/v1",
1341 		NULL);
1342 	if (status < B_OK)
1343 		goto err1;
1344 	status = gStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
1345 		"network/protocols/udp/v1",
1346 		"network/protocols/ipv6/v1",
1347 		NULL);
1348 	if (status < B_OK)
1349 		goto err1;
1350 
1351 	status = gStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_UDP,
1352 		"network/protocols/udp/v1");
1353 	if (status < B_OK)
1354 		goto err1;
1355 	status = gStackModule->register_domain_receiving_protocol(AF_INET6, IPPROTO_UDP,
1356 		"network/protocols/udp/v1");
1357 	if (status < B_OK)
1358 		goto err1;
1359 
1360 	add_debugger_command("udp_endpoints", UdpEndpointManager::DumpEndpoints,
1361 		"lists all open UDP endpoints");
1362 
1363 	return B_OK;
1364 
1365 err1:
1366 	// TODO: shouldn't unregister the protocols here?
1367 	delete sUdpEndpointManager;
1368 
1369 	TRACE_EPM("init_udp() fails with %lx (%s)", status, strerror(status));
1370 	return status;
1371 }
1372 
1373 
1374 static status_t
1375 uninit_udp()
1376 {
1377 	TRACE_EPM("uninit_udp()");
1378 	remove_debugger_command("udp_endpoints",
1379 		UdpEndpointManager::DumpEndpoints);
1380 	delete sUdpEndpointManager;
1381 	return B_OK;
1382 }
1383 
1384 
1385 static status_t
1386 udp_std_ops(int32 op, ...)
1387 {
1388 	switch (op) {
1389 		case B_MODULE_INIT:
1390 			return init_udp();
1391 
1392 		case B_MODULE_UNINIT:
1393 			return uninit_udp();
1394 
1395 		default:
1396 			return B_ERROR;
1397 	}
1398 }
1399 
1400 
1401 net_protocol_module_info sUDPModule = {
1402 	{
1403 		"network/protocols/udp/v1",
1404 		0,
1405 		udp_std_ops
1406 	},
1407 	NET_PROTOCOL_ATOMIC_MESSAGES,
1408 
1409 	udp_init_protocol,
1410 	udp_uninit_protocol,
1411 	udp_open,
1412 	udp_close,
1413 	udp_free,
1414 	udp_connect,
1415 	udp_accept,
1416 	udp_control,
1417 	udp_getsockopt,
1418 	udp_setsockopt,
1419 	udp_bind,
1420 	udp_unbind,
1421 	udp_listen,
1422 	udp_shutdown,
1423 	udp_send_data,
1424 	udp_send_routed_data,
1425 	udp_send_avail,
1426 	udp_read_data,
1427 	udp_read_avail,
1428 	udp_get_domain,
1429 	udp_get_mtu,
1430 	udp_receive_data,
1431 	udp_deliver_data,
1432 	udp_error_received,
1433 	udp_error_reply,
1434 	NULL,		// add_ancillary_data()
1435 	NULL,		// process_ancillary_data()
1436 	udp_process_ancillary_data_no_container,
1437 	NULL,		// send_data_no_buffer()
1438 	NULL		// read_data_no_buffer()
1439 };
1440 
1441 module_dependency module_dependencies[] = {
1442 	{NET_STACK_MODULE_NAME, (module_info **)&gStackModule},
1443 	{NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule},
1444 	{NET_DATALINK_MODULE_NAME, (module_info **)&gDatalinkModule},
1445 	{NET_SOCKET_MODULE_NAME, (module_info **)&gSocketModule},
1446 	{}
1447 };
1448 
1449 module_info *modules[] = {
1450 	(module_info *)&sUDPModule,
1451 	NULL
1452 };
1453