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