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