xref: /haiku/src/add-ons/kernel/network/stack/stack.cpp (revision 204dee708a999d5a71d0cb9497650ee7cef85d0a)
1 /*
2  * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  */
8 
9 
10 #include "ancillary_data.h"
11 #include "device_interfaces.h"
12 #include "domains.h"
13 #include "interfaces.h"
14 #include "link.h"
15 #include "stack_private.h"
16 #include "utility.h"
17 
18 #include <net_datalink_protocol.h>
19 #include <net_device.h>
20 #include <net_protocol.h>
21 #include <net_stack.h>
22 
23 #include <lock.h>
24 #include <util/AutoLock.h>
25 #include <util/khash.h>
26 
27 #include <KernelExport.h>
28 
29 #include <net/if_types.h>
30 #include <new>
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 
36 //#define TRACE_STACK
37 #ifdef TRACE_STACK
38 #	define TRACE(x) dprintf x
39 #else
40 #	define TRACE(x) ;
41 #endif
42 
43 #define MAX_CHAIN_MODULES 5
44 
45 struct chain;
46 typedef DoublyLinkedList<chain> ChainList;
47 
48 struct chain_key {
49 	int		family;
50 	int		type;
51 	int		protocol;
52 };
53 
54 struct family {
55 	family(int type);
56 
57 	void Acquire();
58 	void Release();
59 
60 	static int Compare(void* _family, const void* _key);
61 	static uint32 Hash(void* _family, const void* _key, uint32 range);
62 	static struct family* Lookup(int type);
63 	static struct family* Add(int type);
64 
65 	struct family*	next;
66 	int				type;
67 	int32			ref_count;
68 	ChainList		chains;
69 };
70 
71 struct chain : DoublyLinkedListLinkImpl<chain> {
72 	chain(int family, int type, int protocol);
73 	~chain();
74 
75 	status_t Acquire();
76 	void Release();
77 	void Uninitialize();
78 
79 	static int Compare(void* _chain, const void* _key);
80 	static uint32 Hash(void* _chain, const void* _key, uint32 range);
81 	static struct chain* Lookup(hash_table* chains, int family, int type,
82 		int protocol);
83 	static struct chain* Add(hash_table* chains, int family, int type,
84 		int protocol, va_list modules);
85 	static struct chain* Add(hash_table* chains, int family, int type,
86 		int protocol, ...);
87 	static void DeleteChains(hash_table* chains);
88 
89 	chain*			next;
90 	struct family*	parent;
91 
92 	int 			family;
93 	int				type;
94 	int				protocol;
95 
96 	int32			ref_count;
97 	uint32			flags;
98 	const char*		modules[MAX_CHAIN_MODULES + 1];
99 	module_info*	infos[MAX_CHAIN_MODULES + 1];
100 };
101 
102 #define CHAIN_MISSING_MODULE	0x02
103 #define CHAIN_INITIALIZED		0x01
104 
105 static mutex sChainLock;
106 static mutex sInitializeChainLock;
107 static hash_table* sProtocolChains;
108 static hash_table* sDatalinkProtocolChains;
109 static hash_table* sReceivingProtocolChains;
110 static hash_table* sFamilies;
111 static bool sInitialized;
112 
113 
114 family::family(int _type)
115 	:
116 	type(_type),
117 	ref_count(0)
118 {
119 }
120 
121 
122 void
123 family::Acquire()
124 {
125 	atomic_add(&ref_count, 1);
126 }
127 
128 
129 void
130 family::Release()
131 {
132 	if (atomic_add(&ref_count, -1) > 1)
133 		return;
134 
135 	TRACE(("family %d unused, uninit chains\n", type));
136 	MutexLocker _(sChainLock);
137 
138 	ChainList::Iterator iterator = chains.GetIterator();
139 	while (struct chain* chain = iterator.Next()) {
140 		chain->Uninitialize();
141 	}
142 }
143 
144 
145 /*static*/ int
146 family::Compare(void* _family, const void* _key)
147 {
148 	struct family* family = (struct family*)_family;
149 	int key = (addr_t)_key;
150 
151 	if (family->type == key)
152 		return 0;
153 
154 	return 1;
155 }
156 
157 
158 /*static*/ uint32
159 family::Hash(void* _family, const void* _key, uint32 range)
160 {
161 	struct family* family = (struct family*)_family;
162 	int key = (addr_t)_key;
163 
164 	if (family != NULL)
165 		return family->type % range;
166 
167 	return key % range;
168 }
169 
170 
171 /*static*/ struct family*
172 family::Lookup(int type)
173 {
174 	return (struct family*)hash_lookup(sFamilies, (void*)(addr_t)type);
175 }
176 
177 
178 /*static*/ struct family*
179 family::Add(int type)
180 {
181 	struct family* family = new (std::nothrow) ::family(type);
182 	if (family == NULL)
183 		return NULL;
184 
185 	if (hash_insert(sFamilies, family) != B_OK) {
186 		delete family;
187 		return NULL;
188 	}
189 
190 	return family;
191 }
192 
193 
194 //	#pragma mark -
195 
196 
197 chain::chain(int _family, int _type, int _protocol)
198 	:
199 	family(_family),
200 	type(_type),
201 	protocol(_protocol),
202 	ref_count(0),
203 	flags(0)
204 {
205 	parent = ::family::Lookup(family);
206 	if (parent == NULL)
207 		parent = ::family::Add(family);
208 
209 	//parent->chains.Add(this);
210 
211 	for (int32 i = 0; i < MAX_CHAIN_MODULES; i++) {
212 		modules[i] = NULL;
213 		infos[i] = NULL;
214 	}
215 }
216 
217 
218 chain::~chain()
219 {
220 	for (int32 i = 0; i < MAX_CHAIN_MODULES; i++) {
221 		free((char*)modules[i]);
222 	}
223 
224 	//parent->chains.Remove(this);
225 }
226 
227 
228 status_t
229 chain::Acquire()
230 {
231 	if (atomic_add(&ref_count, 1) > 0) {
232 		if ((flags & CHAIN_MISSING_MODULE) != 0) {
233 			atomic_add(&ref_count, -1);
234 			return EAFNOSUPPORT;
235 		}
236 
237 		while ((flags & CHAIN_INITIALIZED) == 0) {
238 			mutex_lock(&sInitializeChainLock);
239 			mutex_unlock(&sInitializeChainLock);
240 		}
241 		return B_OK;
242 	}
243 
244 	parent->Acquire();
245 
246 	if ((flags & CHAIN_INITIALIZED) != 0)
247 		return B_OK;
248 
249 	TRACE(("initializing chain %d.%d.%d\n", family, type, protocol));
250 	MutexLocker locker(&sInitializeChainLock);
251 
252 	for (int32 i = 0; modules[i] != NULL; i++) {
253 		if (get_module(modules[i], &infos[i]) < B_OK) {
254 			flags |= CHAIN_MISSING_MODULE;
255 
256 			// put already opened modules
257 			while (i-- > 0) {
258 				put_module(modules[i]);
259 			}
260 			return EAFNOSUPPORT;
261 		}
262 	}
263 
264 	flags |= CHAIN_INITIALIZED;
265 	return B_OK;
266 }
267 
268 
269 void
270 chain::Release()
271 {
272 	if (atomic_add(&ref_count, -1) > 1)
273 		return;
274 
275 	TRACE(("chain %d.%d.%d unused\n", family, type, protocol));
276 	parent->Release();
277 }
278 
279 
280 void
281 chain::Uninitialize()
282 {
283 	if ((flags & CHAIN_INITIALIZED) == 0)
284 		return;
285 
286 	TRACE(("uninit chain %d.%d.%d\n", family, type, protocol));
287 	MutexLocker _(sInitializeChainLock);
288 
289 	for (int32 i = 0; modules[i] != NULL; i++) {
290 		put_module(modules[i]);
291 	}
292 
293 	flags &= ~CHAIN_INITIALIZED;
294 }
295 
296 
297 /*static*/ int
298 chain::Compare(void* _chain, const void* _key)
299 {
300 	const chain_key* key = (const chain_key*)_key;
301 	struct chain* chain = (struct chain*)_chain;
302 
303 	if (chain->family == key->family
304 		&& chain->type == key->type
305 		&& chain->protocol == key->protocol)
306 		return 0;
307 
308 	return 1;
309 }
310 
311 
312 /*static*/ uint32
313 chain::Hash(void* _chain, const void* _key, uint32 range)
314 {
315 	const chain_key* key = (const chain_key*)_key;
316 	struct chain* chain = (struct chain*)_chain;
317 
318 // TODO: check if this makes a good hash...
319 #define HASH(o) ((uint32)(((o)->family) ^ ((o)->type) ^ ((o)->protocol)) % range)
320 #if 0
321 	TRACE(("%d.%d.%d: Hash: %lu\n", chain ? chain->family : key->family,
322 		chain ? chain->type : key->type, chain ? chain->protocol : key->protocol,
323 		chain ? HASH(chain) : HASH(key)));
324 #endif
325 
326 	if (chain != NULL)
327 		return HASH(chain);
328 
329 	return HASH(key);
330 #undef HASH
331 }
332 
333 
334 /*static*/ struct chain*
335 chain::Lookup(hash_table* chains, int family, int type, int protocol)
336 {
337 	struct chain_key key = { family, type, protocol };
338 	return (struct chain*)hash_lookup(chains, &key);
339 }
340 
341 
342 /*static*/ struct chain*
343 chain::Add(hash_table* chains, int family, int type, int protocol,
344 	va_list modules)
345 {
346 	struct chain* chain = new (std::nothrow) ::chain(family, type, protocol);
347 	if (chain == NULL)
348 		return NULL;
349 
350 	if (chain->parent == NULL || hash_insert(chains, chain) != B_OK) {
351 		delete chain;
352 		return NULL;
353 	}
354 
355 	TRACE(("Add chain %d.%d.%d:\n", family, type, protocol));
356 	const char* module;
357 	int32 count = 0;
358 
359 	while (true) {
360 		module = va_arg(modules, const char*);
361 		if (module == NULL)
362 			break;
363 
364 		TRACE(("  [%ld] %s\n", count, module));
365 		chain->modules[count] = strdup(module);
366 		if (chain->modules[count] == NULL
367 			|| ++count >= MAX_CHAIN_MODULES) {
368 			hash_remove(chains, chain);
369 			delete chain;
370 			return NULL;
371 		}
372 	}
373 
374 	if (chains == sProtocolChains && count == 0) {
375 		hash_remove(chains, chain);
376 		delete chain;
377 		return NULL;
378 	}
379 
380 	return chain;
381 }
382 
383 
384 /*static*/ struct chain*
385 chain::Add(hash_table* chains, int family, int type, int protocol, ...)
386 {
387 	va_list modules;
388 	va_start(modules, protocol);
389 
390 	struct chain* chain = Add(chains, family, type, 0, modules);
391 
392 	va_end(modules);
393 	return chain;
394 }
395 
396 
397 /*static*/ void
398 chain::DeleteChains(hash_table* chains)
399 {
400 	uint32 cookie = 0;
401 	while (true) {
402 		struct chain* chain = (struct chain*)hash_remove_first(chains, &cookie);
403 		if (chain == NULL)
404 			break;
405 
406 		chain->Uninitialize();
407 		delete chain;
408 	}
409 }
410 
411 
412 //	#pragma mark -
413 
414 
415 static void
416 uninit_domain_protocols(net_socket* socket)
417 {
418 	net_protocol* protocol = socket->first_protocol;
419 	while (protocol != NULL) {
420 		net_protocol* next = protocol->next;
421 		protocol->module->uninit_protocol(protocol);
422 
423 		protocol = next;
424 	}
425 
426 	socket->first_protocol = NULL;
427 	socket->first_info = NULL;
428 }
429 
430 
431 status_t
432 get_domain_protocols(net_socket* socket)
433 {
434 	struct chain* chain;
435 
436 	{
437 		MutexLocker _(sChainLock);
438 
439 		chain = chain::Lookup(sProtocolChains, socket->family, socket->type,
440 			socket->type == SOCK_RAW ? 0 : socket->protocol);
441 			// in SOCK_RAW mode, we ignore the protocol information
442 		if (chain == NULL) {
443 			// TODO: if we want to be POSIX compatible, we should also support
444 			//	the error codes EPROTONOSUPPORT and EPROTOTYPE.
445 			return EAFNOSUPPORT;
446 		}
447 	}
448 
449 	// create net_protocol objects for the protocols in the chain
450 
451 	status_t status = chain->Acquire();
452 	if (status != B_OK)
453 		return status;
454 
455 	net_protocol* last = NULL;
456 
457 	for (int32 i = 0; chain->infos[i] != NULL; i++) {
458 		net_protocol* protocol =
459 			((net_protocol_module_info*)chain->infos[i])->init_protocol(socket);
460 		if (protocol == NULL) {
461 			// free protocols we already initialized
462 			uninit_domain_protocols(socket);
463 			chain->Release();
464 			return B_NO_MEMORY;
465 		}
466 
467 		protocol->module = (net_protocol_module_info*)chain->infos[i];
468 		protocol->socket = socket;
469 		protocol->next = NULL;
470 
471 		if (last == NULL) {
472 			socket->first_protocol = protocol;
473 			socket->first_info = protocol->module;
474 		} else
475 			last->next = protocol;
476 
477 		last = protocol;
478 	}
479 
480 	return B_OK;
481 }
482 
483 
484 status_t
485 put_domain_protocols(net_socket* socket)
486 {
487 	struct chain* chain;
488 
489 	{
490 		MutexLocker _(sChainLock);
491 
492 		chain = chain::Lookup(sProtocolChains, socket->family, socket->type,
493 			socket->protocol);
494 		if (chain == NULL)
495 			return B_ERROR;
496 	}
497 
498 	uninit_domain_protocols(socket);
499 	chain->Release();
500 	return B_OK;
501 }
502 
503 
504 static void
505 uninit_domain_datalink_protocols(domain_datalink* datalink)
506 {
507 	TRACE(("%s(datalink %p)\n", __FUNCTION__, datalink));
508 
509 	if (datalink == NULL)
510 		return;
511 
512 	net_datalink_protocol* protocol = datalink->first_protocol;
513 	while (protocol != NULL) {
514 		net_datalink_protocol* next = protocol->next;
515 		protocol->module->uninit_protocol(protocol);
516 
517 		protocol = next;
518 	}
519 
520 	datalink->first_protocol = NULL;
521 	datalink->first_info = NULL;
522 }
523 
524 
525 status_t
526 get_domain_datalink_protocols(Interface* interface, net_domain* domain)
527 {
528 	TRACE(("%s(interface %p, domain %d)\n", __FUNCTION__, interface,
529 		domain->family));
530 
531 	struct chain* chain;
532 
533 	{
534 		MutexLocker _(sChainLock);
535 
536 		chain = chain::Lookup(sDatalinkProtocolChains, domain->family,
537 			interface->DeviceInterface()->device->type, 0);
538 		if (chain == NULL)
539 			return EAFNOSUPPORT;
540 	}
541 
542 	domain_datalink* datalink = interface->DomainDatalink(domain->family);
543 	if (datalink == NULL)
544 		return B_BAD_VALUE;
545 	if (datalink->first_protocol != NULL)
546 		return B_NAME_IN_USE;
547 
548 	// create net_protocol objects for the protocols in the chain
549 
550 	status_t status = chain->Acquire();
551 	if (status != B_OK)
552 		return status;
553 
554 	net_datalink_protocol* last = NULL;
555 
556 	for (int32 i = 0; chain->infos[i] != NULL; i++) {
557 		net_datalink_protocol* protocol;
558 		status_t status = ((net_datalink_protocol_module_info*)
559 			chain->infos[i])->init_protocol(interface, domain, &protocol);
560 		if (status != B_OK) {
561 			// free protocols we already initialized
562 			uninit_domain_datalink_protocols(datalink);
563 			chain->Release();
564 			return status;
565 		}
566 
567 		protocol->module = (net_datalink_protocol_module_info*)chain->infos[i];
568 		protocol->interface = interface;
569 		protocol->domain = domain;
570 		protocol->next = NULL;
571 
572 		if (last == NULL) {
573 			datalink->first_protocol = protocol;
574 			datalink->first_info = protocol->module;
575 		} else
576 			last->next = protocol;
577 
578 		last = protocol;
579 	}
580 
581 	return B_OK;
582 }
583 
584 
585 status_t
586 put_domain_datalink_protocols(Interface* interface, net_domain* domain)
587 {
588 	TRACE(("%s(interface %p, domain %d)\n", __FUNCTION__, interface,
589 		domain->family));
590 
591 	struct chain* chain;
592 
593 	{
594 		MutexLocker _(sChainLock);
595 
596 		chain = chain::Lookup(sDatalinkProtocolChains, domain->family,
597 			interface->DeviceInterface()->device->type, 0);
598 		if (chain == NULL)
599 			return B_ERROR;
600 	}
601 
602 	uninit_domain_datalink_protocols(interface->DomainDatalink(domain->family));
603 	chain->Release();
604 	return B_OK;
605 }
606 
607 
608 status_t
609 get_domain_receiving_protocol(net_domain* _domain, uint32 type,
610 	net_protocol_module_info** _module)
611 {
612 	struct net_domain_private* domain = (net_domain_private*)_domain;
613 	struct chain* chain;
614 
615 	TRACE(("get_domain_receiving_protocol(family %d, type %lu)\n",
616 		domain->family, type));
617 
618 	{
619 		MutexLocker _(sChainLock);
620 
621 		chain = chain::Lookup(sReceivingProtocolChains, domain->family,
622 			type, 0);
623 		if (chain == NULL)
624 			return EAFNOSUPPORT;
625 	}
626 
627 	status_t status = chain->Acquire();
628 	if (status != B_OK)
629 		return status;
630 
631 	*_module = (net_protocol_module_info*)chain->infos[0];
632 	return B_OK;
633 }
634 
635 
636 status_t
637 put_domain_receiving_protocol(net_domain* _domain, uint32 type)
638 {
639 	struct net_domain_private* domain = (net_domain_private*)_domain;
640 	struct chain* chain;
641 
642 	{
643 		MutexLocker _(sChainLock);
644 
645 		chain = chain::Lookup(sReceivingProtocolChains, domain->family,
646 			type, 0);
647 		if (chain == NULL)
648 			return B_ERROR;
649 	}
650 
651 	chain->Release();
652 	return B_OK;
653 }
654 
655 
656 status_t
657 register_domain_protocols(int family, int type, int protocol, ...)
658 {
659 	if (type == SOCK_RAW) {
660 		// in SOCK_RAW mode, we ignore the protocol information
661 		protocol = 0;
662 	}
663 
664 	MutexLocker locker(&sChainLock);
665 
666 	struct chain* chain = chain::Lookup(sProtocolChains, family, type, protocol);
667 	if (chain != NULL)
668 		return B_OK;
669 
670 	va_list modules;
671 	va_start(modules, protocol);
672 
673 	chain = chain::Add(sProtocolChains, family, type, protocol, modules);
674 
675 	va_end(modules);
676 
677 	if (chain == NULL)
678 		return B_NO_MEMORY;
679 
680 	return B_OK;
681 }
682 
683 
684 status_t
685 register_domain_datalink_protocols(int family, int type, ...)
686 {
687 	TRACE(("register_domain_datalink_protocol(%d.%d)\n", family, type));
688 	MutexLocker locker(&sChainLock);
689 
690 	struct chain* chain
691 		= chain::Lookup(sDatalinkProtocolChains, family, type, 0);
692 	if (chain != NULL)
693 		return B_OK;
694 
695 	va_list modules;
696 	va_start(modules, type);
697 
698 	chain = chain::Add(sDatalinkProtocolChains, family, type, 0, modules);
699 
700 	va_end(modules);
701 
702 	if (chain == NULL)
703 		return B_NO_MEMORY;
704 
705 	// Add datalink interface protocol as the last protocol in the chain; it's
706 	// name stays unset, so that it won't be part of the release/acquire process.
707 
708 	uint32 count = 0;
709 	while (chain->modules[count] != NULL) {
710 		count++;
711 	}
712 
713 	chain->infos[count] = (module_info*)&gDatalinkInterfaceProtocolModule;
714 	return B_OK;
715 }
716 
717 
718 static status_t
719 register_domain_receiving_protocol(int family, int type, const char* moduleName)
720 {
721 	TRACE(("register_domain_receiving_protocol(%d.%d, %s)\n", family, type,
722 		moduleName));
723 
724 	MutexLocker _(sChainLock);
725 
726 	struct chain* chain
727 		= chain::Lookup(sReceivingProtocolChains, family, type, 0);
728 	if (chain != NULL)
729 		return B_OK;
730 
731 	chain = chain::Add(sReceivingProtocolChains, family, type, 0, moduleName,
732 		NULL);
733 	if (chain == NULL)
734 		return B_NO_MEMORY;
735 
736 	return B_OK;
737 }
738 
739 
740 static void
741 scan_modules(const char* path)
742 {
743 	void* cookie = open_module_list(path);
744 	if (cookie == NULL)
745 		return;
746 
747 	while (true) {
748 		char name[B_FILE_NAME_LENGTH];
749 		size_t length = sizeof(name);
750 		if (read_next_module_name(cookie, name, &length) != B_OK)
751 			break;
752 
753 		TRACE(("scan %s\n", name));
754 
755 		module_info* module;
756 		if (get_module(name, &module) == B_OK) {
757 			// we don't need the module right now, but we give it a chance
758 			// to register itself
759 			put_module(name);
760 		}
761 	}
762 
763 	close_module_list(cookie);
764 }
765 
766 
767 status_t
768 init_stack()
769 {
770 	status_t status = init_domains();
771 	if (status != B_OK)
772 		return status;
773 
774 	status = init_interfaces();
775 	if (status != B_OK)
776 		goto err1;
777 
778 	status = init_device_interfaces();
779 	if (status != B_OK)
780 		goto err2;
781 
782 	status = init_timers();
783 	if (status != B_OK)
784 		goto err3;
785 
786 	status = init_notifications();
787 	if (status < B_OK) {
788 		// If this fails, it just means there won't be any notifications,
789 		// it's not a fatal error.
790 		dprintf("networking stack notifications could not be initialized: %s\n",
791 			strerror(status));
792 	}
793 
794 	module_info* dummy;
795 	status = get_module(NET_SOCKET_MODULE_NAME, &dummy);
796 	if (status != B_OK)
797 		goto err4;
798 
799 	mutex_init(&sChainLock, "net chains");
800 	mutex_init(&sInitializeChainLock, "net intialize chains");
801 
802 	sFamilies = hash_init(10, offsetof(struct family, next),
803 		&family::Compare, &family::Hash);
804 	if (sFamilies == NULL) {
805 		status = B_NO_MEMORY;
806 		goto err5;
807 	}
808 
809 	sProtocolChains = hash_init(10, offsetof(struct chain, next),
810 		&chain::Compare, &chain::Hash);
811 	if (sProtocolChains == NULL) {
812 		status = B_NO_MEMORY;
813 		goto err6;
814 	}
815 
816 	sDatalinkProtocolChains = hash_init(10, offsetof(struct chain, next),
817 		&chain::Compare, &chain::Hash);
818 	if (sDatalinkProtocolChains == NULL) {
819 		status = B_NO_MEMORY;
820 		goto err7;
821 	}
822 
823 	sReceivingProtocolChains = hash_init(10, offsetof(struct chain, next),
824 		&chain::Compare, &chain::Hash);
825 	if (sReceivingProtocolChains == NULL) {
826 		status = B_NO_MEMORY;
827 		goto err8;
828 	}
829 
830 	sInitialized = true;
831 
832 	link_init();
833 	scan_modules("network/protocols");
834 	scan_modules("network/datalink_protocols");
835 
836 	// TODO: for now!
837 	register_domain_datalink_protocols(AF_INET, IFT_LOOP,
838 		"network/datalink_protocols/loopback_frame/v1", NULL);
839 	register_domain_datalink_protocols(AF_INET6, IFT_LOOP,
840 		"network/datalink_protocols/loopback_frame/v1", NULL);
841 	register_domain_datalink_protocols(AF_INET, IFT_ETHER,
842 		"network/datalink_protocols/arp/v1",
843 		"network/datalink_protocols/ethernet_frame/v1",
844 		NULL);
845 	register_domain_datalink_protocols(AF_INET6, IFT_ETHER,
846 		"network/datalink_protocols/ipv6_datagram/v1",
847 		"network/datalink_protocols/ethernet_frame/v1",
848 		NULL);
849 
850 	return B_OK;
851 
852 err8:
853 	hash_uninit(sDatalinkProtocolChains);
854 err7:
855 	hash_uninit(sProtocolChains);
856 err6:
857 	hash_uninit(sFamilies);
858 err5:
859 	mutex_destroy(&sInitializeChainLock);
860 	mutex_destroy(&sChainLock);
861 err4:
862 	uninit_timers();
863 err3:
864 	uninit_device_interfaces();
865 err2:
866 	uninit_interfaces();
867 err1:
868 	uninit_domains();
869 	return status;
870 }
871 
872 
873 status_t
874 uninit_stack()
875 {
876 	TRACE(("Unloading network stack\n"));
877 
878 	put_module(NET_SOCKET_MODULE_NAME);
879 	uninit_timers();
880 	uninit_device_interfaces();
881 	uninit_interfaces();
882 	uninit_domains();
883 	uninit_notifications();
884 
885 	mutex_destroy(&sChainLock);
886 	mutex_destroy(&sInitializeChainLock);
887 
888 	// remove chains and families
889 
890 	chain::DeleteChains(sProtocolChains);
891 	chain::DeleteChains(sDatalinkProtocolChains);
892 	chain::DeleteChains(sReceivingProtocolChains);
893 
894 	uint32 cookie = 0;
895 	while (true) {
896 		struct family* family = (struct family*)hash_remove_first(sFamilies,
897 			&cookie);
898 		if (family == NULL)
899 			break;
900 
901 		delete family;
902 	}
903 
904 	hash_uninit(sProtocolChains);
905 	hash_uninit(sDatalinkProtocolChains);
906 	hash_uninit(sReceivingProtocolChains);
907 	hash_uninit(sFamilies);
908 
909 	return B_OK;
910 }
911 
912 
913 static status_t
914 stack_std_ops(int32 op, ...)
915 {
916 	switch (op) {
917 		case B_MODULE_INIT:
918 			return sInitialized ? B_OK : B_BUSY;
919 		case B_MODULE_UNINIT:
920 			return B_OK;
921 
922 		default:
923 			return B_ERROR;
924 	}
925 }
926 
927 
928 net_stack_module_info gNetStackModule = {
929 	{
930 		NET_STACK_MODULE_NAME,
931 		0,
932 		stack_std_ops
933 	},
934 
935 	register_domain,
936 	unregister_domain,
937 	get_domain,
938 
939 	register_domain_protocols,
940 	register_domain_datalink_protocols,
941 	register_domain_receiving_protocol,
942 
943 	get_domain_receiving_protocol,
944 	put_domain_receiving_protocol,
945 
946 	register_device_deframer,
947 	unregister_device_deframer,
948 	register_domain_device_handler,
949 	register_device_handler,
950 	unregister_device_handler,
951 	register_device_monitor,
952 	unregister_device_monitor,
953 	device_link_changed,
954 	device_removed,
955 	device_enqueue_buffer,
956 
957 	notify_socket,
958 
959 	checksum,
960 
961 	init_fifo,
962 	uninit_fifo,
963 	fifo_enqueue_buffer,
964 	fifo_dequeue_buffer,
965 	clear_fifo,
966 	fifo_socket_enqueue_buffer,
967 
968 	init_timer,
969 	set_timer,
970 	cancel_timer,
971 	wait_for_timer,
972 	is_timer_active,
973 	is_timer_running,
974 
975 	is_syscall,
976 	is_restarted_syscall,
977 	store_syscall_restart_timeout,
978 	restore_syscall_restart_timeout,
979 
980 	create_ancillary_data_container,
981 	delete_ancillary_data_container,
982 	add_ancillary_data,
983 	remove_ancillary_data,
984 	move_ancillary_data,
985 	next_ancillary_data
986 };
987 
988 module_info* modules[] = {
989 	(module_info*)&gNetStackModule,
990 	(module_info*)&gNetBufferModule,
991 	(module_info*)&gNetSocketModule,
992 	(module_info*)&gNetDatalinkModule,
993 	(module_info*)&gLinkModule,
994 	(module_info*)&gNetStackInterfaceModule,
995 	NULL
996 };
997