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