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