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