xref: /haiku/src/add-ons/kernel/network/stack/stack.cpp (revision 1b80286772b529a3d6de3bbeb0720c62e6a32fed)
1 /*
2  * Copyright 2006-2009, 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 "domains.h"
12 #include "interfaces.h"
13 #include "link.h"
14 #include "stack_private.h"
15 #include "utility.h"
16 
17 #include <net_datalink_protocol.h>
18 #include <net_device.h>
19 #include <net_protocol.h>
20 #include <net_stack.h>
21 
22 #include <lock.h>
23 #include <util/AutoLock.h>
24 #include <util/khash.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 chain : DoublyLinkedListLinkImpl<chain> {
71 	chain(int family, int type, int protocol);
72 	~chain();
73 
74 	status_t Acquire();
75 	void Release();
76 	void Uninitialize();
77 
78 	static int Compare(void* _chain, const void* _key);
79 	static uint32 Hash(void* _chain, const void* _key, uint32 range);
80 	static struct chain* Lookup(hash_table* chains, int family, int type,
81 		int protocol);
82 	static struct chain* Add(hash_table* chains, int family, int type,
83 		int protocol, va_list modules);
84 	static struct chain* Add(hash_table* chains, int family, int type,
85 		int protocol, ...);
86 	static void DeleteChains(hash_table* 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 #define CHAIN_MISSING_MODULE	0x02
102 #define CHAIN_INITIALIZED		0x01
103 
104 static mutex sChainLock;
105 static mutex sInitializeChainLock;
106 static hash_table* sProtocolChains;
107 static hash_table* sDatalinkProtocolChains;
108 static hash_table* sReceivingProtocolChains;
109 static hash_table* sFamilies;
110 static bool sInitialized;
111 
112 
113 family::family(int _type)
114 	:
115 	type(_type),
116 	ref_count(0)
117 {
118 }
119 
120 
121 void
122 family::Acquire()
123 {
124 	atomic_add(&ref_count, 1);
125 }
126 
127 
128 void
129 family::Release()
130 {
131 	if (atomic_add(&ref_count, -1) > 1)
132 		return;
133 
134 	TRACE(("family %d unused, uninit chains\n", type));
135 	MutexLocker _(sChainLock);
136 
137 	ChainList::Iterator iterator = chains.GetIterator();
138 	while (struct chain* chain = iterator.Next()) {
139 		chain->Uninitialize();
140 	}
141 }
142 
143 
144 /*static*/ int
145 family::Compare(void* _family, const void* _key)
146 {
147 	struct family* family = (struct family*)_family;
148 	int key = (int)_key;
149 
150 	if (family->type == key)
151 		return 0;
152 
153 	return 1;
154 }
155 
156 
157 /*static*/ uint32
158 family::Hash(void* _family, const void* _key, uint32 range)
159 {
160 	struct family* family = (struct family*)_family;
161 	int key = (int)_key;
162 
163 	if (family != NULL)
164 		return family->type % range;
165 
166 	return key % range;
167 }
168 
169 
170 /*static*/ struct family*
171 family::Lookup(int type)
172 {
173 	return (struct family*)hash_lookup(sFamilies, (void*)type);
174 }
175 
176 
177 /*static*/ struct family*
178 family::Add(int type)
179 {
180 	struct family* family = new (std::nothrow) ::family(type);
181 	if (family == NULL)
182 		return NULL;
183 
184 	if (hash_insert(sFamilies, family) != B_OK) {
185 		delete family;
186 		return NULL;
187 	}
188 
189 	return family;
190 }
191 
192 
193 //	#pragma mark -
194 
195 
196 chain::chain(int _family, int _type, int _protocol)
197 	:
198 	family(_family),
199 	type(_type),
200 	protocol(_protocol),
201 	ref_count(0),
202 	flags(0)
203 {
204 	parent = ::family::Lookup(family);
205 	if (parent == NULL)
206 		parent = ::family::Add(family);
207 
208 	//parent->chains.Add(this);
209 
210 	for (int32 i = 0; i < MAX_CHAIN_MODULES; i++) {
211 		modules[i] = NULL;
212 		infos[i] = NULL;
213 	}
214 }
215 
216 
217 chain::~chain()
218 {
219 	for (int32 i = 0; i < MAX_CHAIN_MODULES; i++) {
220 		free((char*)modules[i]);
221 	}
222 
223 	//parent->chains.Remove(this);
224 }
225 
226 
227 status_t
228 chain::Acquire()
229 {
230 	if (atomic_add(&ref_count, 1) > 0) {
231 		if ((flags & CHAIN_MISSING_MODULE) != 0) {
232 			atomic_add(&ref_count, -1);
233 			return EAFNOSUPPORT;
234 		}
235 
236 		while ((flags & CHAIN_INITIALIZED) == 0) {
237 			mutex_lock(&sInitializeChainLock);
238 			mutex_unlock(&sInitializeChainLock);
239 		}
240 		return B_OK;
241 	}
242 
243 	parent->Acquire();
244 
245 	if ((flags & CHAIN_INITIALIZED) != 0)
246 		return B_OK;
247 
248 	TRACE(("initializing chain %d.%d.%d\n", family, type, protocol));
249 	MutexLocker locker(&sInitializeChainLock);
250 
251 	for (int32 i = 0; modules[i] != NULL; i++) {
252 		if (get_module(modules[i], &infos[i]) < B_OK) {
253 			flags |= CHAIN_MISSING_MODULE;
254 
255 			// put already opened modules
256 			while (i-- > 0) {
257 				put_module(modules[i]);
258 			}
259 			return EAFNOSUPPORT;
260 		}
261 	}
262 
263 	flags |= CHAIN_INITIALIZED;
264 	return B_OK;
265 }
266 
267 
268 void
269 chain::Release()
270 {
271 	if (atomic_add(&ref_count, -1) > 1)
272 		return;
273 
274 	TRACE(("chain %d.%d.%d unused\n", family, type, protocol));
275 	parent->Release();
276 }
277 
278 
279 void
280 chain::Uninitialize()
281 {
282 	if ((flags & CHAIN_INITIALIZED) == 0)
283 		return;
284 
285 	TRACE(("uninit chain %d.%d.%d\n", family, type, protocol));
286 	MutexLocker _(sInitializeChainLock);
287 
288 	for (int32 i = 0; modules[i] != NULL; i++) {
289 		put_module(modules[i]);
290 	}
291 
292 	flags &= ~CHAIN_INITIALIZED;
293 }
294 
295 
296 /*static*/ int
297 chain::Compare(void* _chain, const void* _key)
298 {
299 	const chain_key* key = (const chain_key*)_key;
300 	struct chain* chain = (struct chain*)_chain;
301 
302 	if (chain->family == key->family
303 		&& chain->type == key->type
304 		&& chain->protocol == key->protocol)
305 		return 0;
306 
307 	return 1;
308 }
309 
310 
311 /*static*/ uint32
312 chain::Hash(void* _chain, const void* _key, uint32 range)
313 {
314 	const chain_key* key = (const chain_key*)_key;
315 	struct chain* chain = (struct chain*)_chain;
316 
317 // TODO: check if this makes a good hash...
318 #define HASH(o) ((uint32)(((o)->family) ^ ((o)->type) ^ ((o)->protocol)) % range)
319 #if 0
320 	TRACE(("%d.%d.%d: Hash: %lu\n", chain ? chain->family : key->family,
321 		chain ? chain->type : key->type, chain ? chain->protocol : key->protocol,
322 		chain ? HASH(chain) : HASH(key)));
323 #endif
324 
325 	if (chain != NULL)
326 		return HASH(chain);
327 
328 	return HASH(key);
329 #undef HASH
330 }
331 
332 
333 /*static*/ struct chain*
334 chain::Lookup(hash_table* chains, int family, int type, int protocol)
335 {
336 	struct chain_key key = { family, type, protocol };
337 	return (struct chain*)hash_lookup(chains, &key);
338 }
339 
340 
341 /*static*/ struct chain*
342 chain::Add(hash_table* 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 || hash_insert(chains, 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 			hash_remove(chains, chain);
368 			delete chain;
369 			return NULL;
370 		}
371 	}
372 
373 	if (chains == sProtocolChains && count == 0) {
374 		hash_remove(chains, chain);
375 		delete chain;
376 		return NULL;
377 	}
378 
379 	return chain;
380 }
381 
382 
383 /*static*/ struct chain*
384 chain::Add(hash_table* 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(hash_table* chains)
398 {
399 	uint32 cookie = 0;
400 	while (true) {
401 		struct chain* chain = (struct chain*)hash_remove_first(chains, &cookie);
402 		if (chain == NULL)
403 			break;
404 
405 		chain->Uninitialize();
406 		delete chain;
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(net_interface* interface)
505 {
506 	net_datalink_protocol* protocol = interface->first_protocol;
507 	while (protocol != NULL) {
508 		net_datalink_protocol* next = protocol->next;
509 		protocol->module->uninit_protocol(protocol);
510 
511 		protocol = next;
512 	}
513 
514 	interface->first_protocol = NULL;
515 	interface->first_info = NULL;
516 }
517 
518 
519 status_t
520 get_domain_datalink_protocols(net_interface* _interface)
521 {
522 	struct net_interface_private* interface = (net_interface_private*)_interface;
523 	struct chain* chain;
524 
525 	{
526 		MutexLocker _(sChainLock);
527 
528 		chain = chain::Lookup(sDatalinkProtocolChains, interface->domain->family,
529 			interface->device_interface->device->type, 0);
530 		if (chain == NULL)
531 			return EAFNOSUPPORT;
532 	}
533 
534 	// create net_protocol objects for the protocols in the chain
535 
536 	status_t status = chain->Acquire();
537 	if (status < B_OK)
538 		return status;
539 
540 	net_datalink_protocol* last = NULL;
541 
542 	for (int32 i = 0; chain->infos[i] != NULL; i++) {
543 		net_datalink_protocol* protocol;
544 		status_t status = ((net_datalink_protocol_module_info*)
545 			chain->infos[i])->init_protocol(interface, &protocol);
546 		if (status < B_OK) {
547 			// free protocols we already initialized
548 			uninit_domain_datalink_protocols(interface);
549 			chain->Release();
550 			return status;
551 		}
552 
553 		protocol->module = (net_datalink_protocol_module_info*)chain->infos[i];
554 		protocol->interface = interface;
555 		protocol->next = NULL;
556 
557 		if (last == NULL) {
558 			interface->first_protocol = protocol;
559 			interface->first_info = protocol->module;
560 		} else
561 			last->next = protocol;
562 
563 		last = protocol;
564 	}
565 
566 	return B_OK;
567 }
568 
569 
570 status_t
571 put_domain_datalink_protocols(net_interface* _interface)
572 {
573 	struct net_interface_private* interface = (net_interface_private*)_interface;
574 	struct chain* chain;
575 
576 	{
577 		MutexLocker _(sChainLock);
578 
579 		chain = chain::Lookup(sDatalinkProtocolChains, interface->domain->family,
580 			interface->device_interface->device->type, 0);
581 		if (chain == NULL)
582 			return B_ERROR;
583 	}
584 
585 	uninit_domain_datalink_protocols(interface);
586 	chain->Release();
587 	return B_OK;
588 }
589 
590 
591 status_t
592 get_domain_receiving_protocol(net_domain* _domain, uint32 type,
593 	net_protocol_module_info** _module)
594 {
595 	struct net_domain_private* domain = (net_domain_private*)_domain;
596 	struct chain* chain;
597 
598 	TRACE(("get_domain_receiving_protocol(family %d, type %lu)\n",
599 		domain->family, type));
600 
601 	{
602 		MutexLocker _(sChainLock);
603 
604 		chain = chain::Lookup(sReceivingProtocolChains, domain->family,
605 			type, 0);
606 		if (chain == NULL)
607 			return EAFNOSUPPORT;
608 	}
609 
610 	status_t status = chain->Acquire();
611 	if (status != B_OK)
612 		return status;
613 
614 	*_module = (net_protocol_module_info*)chain->infos[0];
615 	return B_OK;
616 }
617 
618 
619 status_t
620 put_domain_receiving_protocol(net_domain* _domain, uint32 type)
621 {
622 	struct net_domain_private* domain = (net_domain_private*)_domain;
623 	struct chain* chain;
624 
625 	{
626 		MutexLocker _(sChainLock);
627 
628 		chain = chain::Lookup(sReceivingProtocolChains, domain->family,
629 			type, 0);
630 		if (chain == NULL)
631 			return B_ERROR;
632 	}
633 
634 	chain->Release();
635 	return B_OK;
636 }
637 
638 
639 status_t
640 register_domain_protocols(int family, int type, int protocol, ...)
641 {
642 	if (type == SOCK_RAW) {
643 		// in SOCK_RAW mode, we ignore the protocol information
644 		protocol = 0;
645 	}
646 
647 	MutexLocker locker(&sChainLock);
648 
649 	struct chain* chain = chain::Lookup(sProtocolChains, family, type, protocol);
650 	if (chain != NULL)
651 		return B_OK;
652 
653 	va_list modules;
654 	va_start(modules, protocol);
655 
656 	chain = chain::Add(sProtocolChains, family, type, protocol, modules);
657 
658 	va_end(modules);
659 
660 	if (chain == NULL)
661 		return B_NO_MEMORY;
662 
663 	return B_OK;
664 }
665 
666 
667 status_t
668 register_domain_datalink_protocols(int family, int type, ...)
669 {
670 	TRACE(("register_domain_datalink_protocol(%d.%d)\n", family, type));
671 	MutexLocker locker(&sChainLock);
672 
673 	struct chain* chain
674 		= chain::Lookup(sDatalinkProtocolChains, family, type, 0);
675 	if (chain != NULL)
676 		return B_OK;
677 
678 	va_list modules;
679 	va_start(modules, type);
680 
681 	chain = chain::Add(sDatalinkProtocolChains, family, type, 0, modules);
682 
683 	va_end(modules);
684 
685 	if (chain == NULL)
686 		return B_NO_MEMORY;
687 
688 	// Add datalink interface protocol as the last protocol in the chain; it's
689 	// name stays unset, so that it won't be part of the release/acquire process.
690 
691 	uint32 count = 0;
692 	while (chain->modules[count] != NULL) {
693 		count++;
694 	}
695 
696 	chain->infos[count] = (module_info*)&gDatalinkInterfaceProtocolModule;
697 	return B_OK;
698 }
699 
700 
701 static status_t
702 register_domain_receiving_protocol(int family, int type, const char* moduleName)
703 {
704 	TRACE(("register_domain_receiving_protocol(%d.%d, %s)\n", family, type,
705 		moduleName));
706 
707 	MutexLocker _(sChainLock);
708 
709 	struct chain* chain
710 		= chain::Lookup(sReceivingProtocolChains, family, type, 0);
711 	if (chain != NULL)
712 		return B_OK;
713 
714 	chain = chain::Add(sReceivingProtocolChains, family, type, 0, moduleName,
715 		NULL);
716 	if (chain == NULL)
717 		return B_NO_MEMORY;
718 
719 	return B_OK;
720 }
721 
722 
723 static void
724 scan_modules(const char* path)
725 {
726 	void* cookie = open_module_list(path);
727 	if (cookie == NULL)
728 		return;
729 
730 	while (true) {
731 		char name[B_FILE_NAME_LENGTH];
732 		size_t length = sizeof(name);
733 		if (read_next_module_name(cookie, name, &length) != B_OK)
734 			break;
735 
736 		TRACE(("scan %s\n", name));
737 
738 		module_info* module;
739 		if (get_module(name, &module) == B_OK) {
740 			// we don't need the module right now, but we give it a chance
741 			// to register itself
742 			put_module(name);
743 		}
744 	}
745 }
746 
747 
748 status_t
749 init_stack()
750 {
751 	status_t status = init_domains();
752 	if (status != B_OK)
753 		return status;
754 
755 	status = init_interfaces();
756 	if (status != B_OK)
757 		goto err1;
758 
759 	status = init_timers();
760 	if (status != B_OK)
761 		goto err2;
762 
763 	status = init_notifications();
764 	if (status < B_OK) {
765 		// If this fails, it just means there won't be any notifications,
766 		// it's not a fatal error.
767 		dprintf("networking stack notifications could not be initialized: %s\n",
768 			strerror(status));
769 	}
770 
771 	module_info* dummy;
772 	status = get_module(NET_SOCKET_MODULE_NAME, &dummy);
773 	if (status != B_OK)
774 		goto err3;
775 
776 	mutex_init(&sChainLock, "net chains");
777 	mutex_init(&sInitializeChainLock, "net intialize chains");
778 
779 	sFamilies = hash_init(10, offsetof(struct family, next),
780 		&family::Compare, &family::Hash);
781 	if (sFamilies == NULL) {
782 		status = B_NO_MEMORY;
783 		goto err5;
784 	}
785 
786 	sProtocolChains = hash_init(10, offsetof(struct chain, next),
787 		&chain::Compare, &chain::Hash);
788 	if (sProtocolChains == NULL) {
789 		status = B_NO_MEMORY;
790 		goto err6;
791 	}
792 
793 	sDatalinkProtocolChains = hash_init(10, offsetof(struct chain, next),
794 		&chain::Compare, &chain::Hash);
795 	if (sDatalinkProtocolChains == NULL) {
796 		status = B_NO_MEMORY;
797 		goto err7;
798 	}
799 
800 	sReceivingProtocolChains = hash_init(10, offsetof(struct chain, next),
801 		&chain::Compare, &chain::Hash);
802 	if (sReceivingProtocolChains == NULL) {
803 		status = B_NO_MEMORY;
804 		goto err8;
805 	}
806 
807 	sInitialized = true;
808 
809 	link_init();
810 	scan_modules("network/protocols");
811 	scan_modules("network/datalink_protocols");
812 
813 	// TODO: for now!
814 	register_domain_datalink_protocols(AF_INET, IFT_LOOP,
815 		"network/datalink_protocols/loopback_frame/v1", NULL);
816 	register_domain_datalink_protocols(AF_INET, IFT_ETHER,
817 		"network/datalink_protocols/ipv4_datagram/v1",
818 		"network/datalink_protocols/arp/v1",
819 		"network/datalink_protocols/ethernet_frame/v1",
820 		NULL);
821 
822 	return B_OK;
823 
824 err8:
825 	hash_uninit(sDatalinkProtocolChains);
826 err7:
827 	hash_uninit(sProtocolChains);
828 err6:
829 	hash_uninit(sFamilies);
830 err5:
831 	mutex_destroy(&sInitializeChainLock);
832 	mutex_destroy(&sChainLock);
833 err3:
834 	uninit_timers();
835 err2:
836 	uninit_interfaces();
837 err1:
838 	uninit_domains();
839 	return status;
840 }
841 
842 
843 status_t
844 uninit_stack()
845 {
846 	TRACE(("Unloading network stack\n"));
847 
848 	put_module(NET_SOCKET_MODULE_NAME);
849 	uninit_timers();
850 	uninit_interfaces();
851 	uninit_domains();
852 	uninit_notifications();
853 
854 	mutex_destroy(&sChainLock);
855 	mutex_destroy(&sInitializeChainLock);
856 
857 	// remove chains and families
858 
859 	chain::DeleteChains(sProtocolChains);
860 	chain::DeleteChains(sDatalinkProtocolChains);
861 	chain::DeleteChains(sReceivingProtocolChains);
862 
863 	uint32 cookie = 0;
864 	while (true) {
865 		struct family* family = (struct family*)hash_remove_first(sFamilies,
866 			&cookie);
867 		if (family == NULL)
868 			break;
869 
870 		delete family;
871 	}
872 
873 	hash_uninit(sProtocolChains);
874 	hash_uninit(sDatalinkProtocolChains);
875 	hash_uninit(sReceivingProtocolChains);
876 	hash_uninit(sFamilies);
877 
878 	return B_OK;
879 }
880 
881 
882 static status_t
883 stack_std_ops(int32 op, ...)
884 {
885 	switch (op) {
886 		case B_MODULE_INIT:
887 			return sInitialized ? B_OK : B_BUSY;
888 		case B_MODULE_UNINIT:
889 			return B_OK;
890 
891 		default:
892 			return B_ERROR;
893 	}
894 }
895 
896 
897 net_stack_module_info gNetStackModule = {
898 	{
899 		NET_STACK_MODULE_NAME,
900 		0,
901 		stack_std_ops
902 	},
903 
904 	register_domain,
905 	unregister_domain,
906 	get_domain,
907 
908 	register_domain_protocols,
909 	register_domain_datalink_protocols,
910 	register_domain_receiving_protocol,
911 
912 	get_domain_receiving_protocol,
913 	put_domain_receiving_protocol,
914 
915 	register_device_deframer,
916 	unregister_device_deframer,
917 	register_domain_device_handler,
918 	register_device_handler,
919 	unregister_device_handler,
920 	register_device_monitor,
921 	unregister_device_monitor,
922 	device_link_changed,
923 	device_removed,
924 	device_enqueue_buffer,
925 
926 	notify_socket,
927 
928 	checksum,
929 
930 	init_fifo,
931 	uninit_fifo,
932 	fifo_enqueue_buffer,
933 	fifo_dequeue_buffer,
934 	clear_fifo,
935 	fifo_socket_enqueue_buffer,
936 
937 	init_timer,
938 	set_timer,
939 	cancel_timer,
940 	wait_for_timer,
941 	is_timer_active,
942 	is_timer_running,
943 
944 	is_syscall,
945 	is_restarted_syscall,
946 	store_syscall_restart_timeout,
947 	restore_syscall_restart_timeout,
948 
949 	create_ancillary_data_container,
950 	delete_ancillary_data_container,
951 	add_ancillary_data,
952 	remove_ancillary_data,
953 	move_ancillary_data,
954 	next_ancillary_data
955 };
956 
957 module_info* modules[] = {
958 	(module_info*)&gNetStackModule,
959 	(module_info*)&gNetBufferModule,
960 	(module_info*)&gNetSocketModule,
961 	(module_info*)&gNetDatalinkModule,
962 	(module_info*)&gLinkModule,
963 	(module_info*)&gNetStackInterfaceModule,
964 	NULL
965 };
966