xref: /haiku/src/add-ons/kernel/network/stack/stack.cpp (revision 25160e50935c4647beb1f0f07839698c389fdf79)
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 	TRACE(("%d.%d.%d: Hash: %lu\n", chain ? chain->family : key->family,
318 		chain ? chain->type : key->type, chain ? chain->protocol : key->protocol,
319 		chain ? HASH(chain) : HASH(key)));
320 
321 	if (chain != NULL)
322 		return HASH(chain);
323 
324 	return HASH(key);
325 #undef HASH
326 }
327 
328 
329 /*static */ struct chain *
330 chain::Lookup(hash_table *chains, int family, int type, int protocol)
331 {
332 	struct chain_key key = { family, type, protocol };
333 	return (struct chain *)hash_lookup(chains, &key);
334 }
335 
336 
337 /*static*/ struct chain *
338 chain::Add(hash_table *chains, int family, int type, int protocol, va_list modules)
339 {
340 	struct chain *chain = new (std::nothrow) ::chain(family, type, protocol);
341 	if (chain == NULL)
342 		return NULL;
343 
344 	if (chain->parent == NULL || hash_insert(chains, chain) != B_OK) {
345 		delete chain;
346 		return NULL;
347 	}
348 
349 	TRACE(("Add chain %d.%d.%d:\n", family, type, protocol));
350 	const char *module;
351 	int32 count = 0;
352 
353 	while (true) {
354 		module = va_arg(modules, const char *);
355 		if (module == NULL)
356 			break;
357 
358 		TRACE(("  [%ld] %s\n", count, module));
359 		chain->modules[count] = strdup(module);
360 		if (chain->modules[count] == NULL
361 			|| ++count >= MAX_CHAIN_MODULES) {
362 			hash_remove(chains, chain);
363 			delete chain;
364 			return NULL;
365 		}
366 	}
367 
368 	if (chains == sProtocolChains && count == 0) {
369 		hash_remove(chains, chain);
370 		delete chain;
371 		return NULL;
372 	}
373 
374 	return chain;
375 }
376 
377 
378 /*static*/ struct chain *
379 chain::Add(hash_table *chains, int family, int type, int protocol, ...)
380 {
381 	va_list modules;
382 	va_start(modules, protocol);
383 
384 	struct chain *chain = Add(chains, family, type, 0, modules);
385 
386 	va_end(modules);
387 	return chain;
388 }
389 
390 
391 /*static*/ void
392 chain::DeleteChains(hash_table *chains)
393 {
394 	uint32 cookie = 0;
395 	while (true) {
396 		struct chain *chain = (struct chain *)hash_remove_first(chains, &cookie);
397 		if (chain == NULL)
398 			break;
399 
400 		chain->Uninitialize();
401 		delete chain;
402 	}
403 }
404 
405 
406 //	#pragma mark -
407 
408 
409 static void
410 uninit_domain_protocols(net_socket *socket)
411 {
412 	net_protocol *protocol = socket->first_protocol;
413 	while (protocol != NULL) {
414 		net_protocol *next = protocol->next;
415 		protocol->module->uninit_protocol(protocol);
416 
417 		protocol = next;
418 	}
419 
420 	socket->first_protocol = NULL;
421 	socket->first_info = NULL;
422 }
423 
424 
425 status_t
426 get_domain_protocols(net_socket *socket)
427 {
428 	struct chain *chain;
429 
430 	{
431 		BenaphoreLocker locker(&sChainLock);
432 
433 		chain = chain::Lookup(sProtocolChains, socket->family, socket->type,
434 			socket->type == SOCK_RAW ? 0 : socket->protocol);
435 			// in SOCK_RAW mode, we ignore the protocol information
436 		if (chain == NULL) {
437 			// TODO: if we want to be POSIX compatible, we should also support
438 			//	the error codes EPROTONOSUPPORT and EPROTOTYPE.
439 			return EAFNOSUPPORT;
440 		}
441 	}
442 
443 	// create net_protocol objects for the protocols in the chain
444 
445 	status_t status = chain->Acquire();
446 	if (status < B_OK)
447 		return status;
448 
449 	net_protocol *last = NULL;
450 
451 	for (int32 i = 0; chain->infos[i] != NULL; i++) {
452 		net_protocol *protocol =
453 			((net_protocol_module_info *)chain->infos[i])->init_protocol(socket);
454 		if (protocol == NULL) {
455 			// free protocols we already initialized
456 			uninit_domain_protocols(socket);
457 			chain->Release();
458 			return B_NO_MEMORY;
459 		}
460 
461 		protocol->module = (net_protocol_module_info *)chain->infos[i];
462 		protocol->socket = socket;
463 		protocol->next = NULL;
464 
465 		if (last == NULL) {
466 			socket->first_protocol = protocol;
467 			socket->first_info = protocol->module;
468 		} else
469 			last->next = protocol;
470 
471 		last = protocol;
472 	}
473 
474 	return B_OK;
475 }
476 
477 
478 status_t
479 put_domain_protocols(net_socket *socket)
480 {
481 	struct chain *chain;
482 
483 	{
484 		BenaphoreLocker locker(&sChainLock);
485 
486 		chain = chain::Lookup(sProtocolChains, socket->family, socket->type,
487 			socket->protocol);
488 		if (chain == NULL)
489 			return B_ERROR;
490 	}
491 
492 	uninit_domain_protocols(socket);
493 	chain->Release();
494 	return B_OK;
495 }
496 
497 
498 static void
499 uninit_domain_datalink_protocols(net_interface *interface)
500 {
501 	net_datalink_protocol *protocol = interface->first_protocol;
502 	while (protocol != NULL) {
503 		net_datalink_protocol *next = protocol->next;
504 		protocol->module->uninit_protocol(protocol);
505 
506 		protocol = next;
507 	}
508 
509 	interface->first_protocol = NULL;
510 	interface->first_info = NULL;
511 }
512 
513 
514 status_t
515 get_domain_datalink_protocols(net_interface *_interface)
516 {
517 	struct net_interface_private *interface = (net_interface_private *)_interface;
518 	struct chain *chain;
519 
520 	{
521 		BenaphoreLocker locker(&sChainLock);
522 
523 		chain = chain::Lookup(sDatalinkProtocolChains, interface->domain->family,
524 			interface->device_interface->device->type, 0);
525 		if (chain == NULL)
526 			return EAFNOSUPPORT;
527 	}
528 
529 	// create net_protocol objects for the protocols in the chain
530 
531 	status_t status = chain->Acquire();
532 	if (status < B_OK)
533 		return status;
534 
535 	net_datalink_protocol *last = NULL;
536 
537 	for (int32 i = 0; chain->infos[i] != NULL; i++) {
538 		net_datalink_protocol *protocol;
539 		status_t status = ((net_datalink_protocol_module_info *)chain->infos[i])->init_protocol(
540 			interface, &protocol);
541 		if (status < B_OK) {
542 			// free protocols we already initialized
543 			uninit_domain_datalink_protocols(interface);
544 			chain->Release();
545 			return status;
546 		}
547 
548 		protocol->module = (net_datalink_protocol_module_info *)chain->infos[i];
549 		protocol->interface = interface;
550 		protocol->next = NULL;
551 
552 		if (last == NULL) {
553 			interface->first_protocol = protocol;
554 			interface->first_info = protocol->module;
555 		} else
556 			last->next = protocol;
557 
558 		last = protocol;
559 	}
560 
561 	return B_OK;
562 }
563 
564 
565 status_t
566 put_domain_datalink_protocols(net_interface *_interface)
567 {
568 	struct net_interface_private *interface = (net_interface_private *)_interface;
569 	struct chain *chain;
570 
571 	{
572 		BenaphoreLocker locker(&sChainLock);
573 
574 		chain = chain::Lookup(sDatalinkProtocolChains, interface->domain->family,
575 			interface->device_interface->device->type, 0);
576 		if (chain == NULL)
577 			return B_ERROR;
578 	}
579 
580 	uninit_domain_datalink_protocols(interface);
581 	chain->Release();
582 	return B_OK;
583 }
584 
585 
586 status_t
587 get_domain_receiving_protocol(net_domain *_domain, uint32 type,
588 	net_protocol_module_info **_module)
589 {
590 	struct net_domain_private *domain = (net_domain_private *)_domain;
591 	struct chain *chain;
592 
593 	TRACE(("get_domain_receiving_protocol(family %d, type %lu)\n", domain->family, type));
594 	{
595 		BenaphoreLocker locker(&sChainLock);
596 
597 		chain = chain::Lookup(sReceivingProtocolChains, domain->family,
598 			type, 0);
599 		if (chain == NULL)
600 			return EAFNOSUPPORT;
601 	}
602 
603 	status_t status = chain->Acquire();
604 	if (status < B_OK)
605 		return status;
606 
607 	*_module = (net_protocol_module_info *)chain->infos[0];
608 	return B_OK;
609 }
610 
611 
612 status_t
613 put_domain_receiving_protocol(net_domain *_domain, uint32 type)
614 {
615 	struct net_domain_private *domain = (net_domain_private *)_domain;
616 	struct chain *chain;
617 
618 	{
619 		BenaphoreLocker locker(&sChainLock);
620 
621 		chain = chain::Lookup(sReceivingProtocolChains, domain->family,
622 			type, 0);
623 		if (chain == NULL)
624 			return B_ERROR;
625 	}
626 
627 	chain->Release();
628 	return B_OK;
629 }
630 
631 
632 status_t
633 register_domain_protocols(int family, int type, int protocol, ...)
634 {
635 	if (type == SOCK_RAW) {
636 		// in SOCK_RAW mode, we ignore the protocol information
637 		protocol = 0;
638 	}
639 
640 	BenaphoreLocker locker(&sChainLock);
641 
642 	struct chain *chain = chain::Lookup(sProtocolChains, family, type, protocol);
643 	if (chain != NULL)
644 		return B_OK;
645 
646 	va_list modules;
647 	va_start(modules, protocol);
648 
649 	chain = chain::Add(sProtocolChains, family, type, protocol, modules);
650 
651 	va_end(modules);
652 
653 	if (chain == NULL)
654 		return B_NO_MEMORY;
655 
656 	return B_OK;
657 }
658 
659 
660 status_t
661 register_domain_datalink_protocols(int family, int type, ...)
662 {
663 	TRACE(("register_domain_datalink_protocol(%d.%d)\n", family, type));
664 	BenaphoreLocker locker(&sChainLock);
665 
666 	struct chain *chain = chain::Lookup(sDatalinkProtocolChains, family, type, 0);
667 	if (chain != NULL)
668 		return B_OK;
669 
670 	va_list modules;
671 	va_start(modules, type);
672 
673 	chain = chain::Add(sDatalinkProtocolChains, family, type, 0, modules);
674 
675 	va_end(modules);
676 
677 	if (chain == NULL)
678 		return B_NO_MEMORY;
679 
680 	// Add datalink interface protocol as the last protocol in the chain; it's name
681 	// stays unset, so that it won't be part of the release/acquire process.
682 
683 	uint32 count = 0;
684 	while (chain->modules[count] != NULL) {
685 		count++;
686 	}
687 
688 	chain->infos[count] = (module_info *)&gDatalinkInterfaceProtocolModule;
689 	return B_OK;
690 }
691 
692 
693 static status_t
694 register_domain_receiving_protocol(int family, int type, const char *moduleName)
695 {
696 	TRACE(("register_domain_receiving_protocol(%d.%d, %s)\n", family, type,
697 		moduleName));
698 
699 	BenaphoreLocker locker(&sChainLock);
700 
701 	struct chain *chain = chain::Lookup(sReceivingProtocolChains, family, type, 0);
702 	if (chain != NULL)
703 		return B_OK;
704 
705 	chain = chain::Add(sReceivingProtocolChains, family, type, 0, moduleName, NULL);
706 	if (chain == NULL)
707 		return B_NO_MEMORY;
708 
709 	return B_OK;
710 }
711 
712 
713 static void
714 scan_modules(const char *path)
715 {
716 	void *cookie = open_module_list(path);
717 	if (cookie == NULL)
718 		return;
719 
720 	while (true) {
721 		char name[B_FILE_NAME_LENGTH];
722 		size_t length = sizeof(name);
723 		if (read_next_module_name(cookie, name, &length) != B_OK)
724 			break;
725 
726 		TRACE(("scan %s\n", name));
727 
728 		module_info *module;
729 		if (get_module(name, &module) == B_OK) {
730 			// we don't need the module right now, but we give it a chance
731 			// to register itself
732 			put_module(name);
733 		}
734 	}
735 }
736 
737 
738 static status_t
739 init_stack()
740 {
741 	status_t status = init_domains();
742 	if (status < B_OK)
743 		return status;
744 
745 	status = init_interfaces();
746 	if (status < B_OK)
747 		goto err1;
748 
749 	status = init_timers();
750 	if (status < B_OK)
751 		goto err2;
752 
753 	if (benaphore_init(&sChainLock, "net chains") < B_OK)
754 		goto err3;
755 	if (benaphore_init(&sInitializeChainLock, "net intialize chains") < B_OK)
756 		goto err4;
757 
758 	sFamilies = hash_init(10, offsetof(struct family, next),
759 		&family::Compare, &family::Hash);
760 	if (sFamilies == NULL) {
761 		status = B_NO_MEMORY;
762 		goto err5;
763 	}
764 
765 	sProtocolChains = hash_init(10, offsetof(struct chain, next),
766 		&chain::Compare, &chain::Hash);
767 	if (sProtocolChains == NULL) {
768 		status = B_NO_MEMORY;
769 		goto err6;
770 	}
771 
772 	sDatalinkProtocolChains = hash_init(10, offsetof(struct chain, next),
773 		&chain::Compare, &chain::Hash);
774 	if (sDatalinkProtocolChains == NULL) {
775 		status = B_NO_MEMORY;
776 		goto err7;
777 	}
778 
779 	sReceivingProtocolChains = hash_init(10, offsetof(struct chain, next),
780 		&chain::Compare, &chain::Hash);
781 	if (sReceivingProtocolChains == NULL) {
782 		status = B_NO_MEMORY;
783 		goto err8;
784 	}
785 
786 	sInitialized = true;
787 
788 	link_init();
789 	scan_modules("network/protocols");
790 	scan_modules("network/datalink_protocols");
791 
792 	// TODO: for now!
793 	register_domain_datalink_protocols(AF_INET, IFT_LOOP, NULL);
794 	register_domain_datalink_protocols(AF_INET, IFT_ETHER,
795 		"network/datalink_protocols/arp/v1",
796 		"network/datalink_protocols/ethernet_frame/v1",
797 		NULL);
798 
799 	return B_OK;
800 
801 err8:
802 	hash_uninit(sDatalinkProtocolChains);
803 err7:
804 	hash_uninit(sProtocolChains);
805 err6:
806 	hash_uninit(sFamilies);
807 err5:
808 	benaphore_destroy(&sInitializeChainLock);
809 err4:
810 	benaphore_destroy(&sChainLock);
811 err3:
812 	uninit_timers();
813 err2:
814 	uninit_interfaces();
815 err1:
816 	uninit_domains();
817 	return status;
818 }
819 
820 
821 status_t
822 uninit_stack()
823 {
824 	TRACE(("Unloading network stack\n"));
825 
826 	uninit_timers();
827 	uninit_interfaces();
828 	uninit_domains();
829 
830 	benaphore_destroy(&sChainLock);
831 	benaphore_destroy(&sInitializeChainLock);
832 
833 	// remove chains and families
834 
835 	chain::DeleteChains(sProtocolChains);
836 	chain::DeleteChains(sDatalinkProtocolChains);
837 	chain::DeleteChains(sReceivingProtocolChains);
838 
839 	uint32 cookie = 0;
840 	while (true) {
841 		struct family *family = (struct family *)hash_remove_first(sFamilies, &cookie);
842 		if (family == NULL)
843 			break;
844 
845 		delete family;
846 	}
847 
848 	hash_uninit(sProtocolChains);
849 	hash_uninit(sDatalinkProtocolChains);
850 	hash_uninit(sReceivingProtocolChains);
851 	hash_uninit(sFamilies);
852 
853 	return B_OK;
854 }
855 
856 
857 static status_t
858 starter_std_ops(int32 op, ...)
859 {
860 	switch (op) {
861 		case B_MODULE_INIT:
862 			return init_stack();
863 		case B_MODULE_UNINIT:
864 			return uninit_stack();
865 
866 		default:
867 			return B_ERROR;
868 	}
869 }
870 
871 
872 static status_t
873 stack_std_ops(int32 op, ...)
874 {
875 	switch (op) {
876 		case B_MODULE_INIT:
877 			return sInitialized ? B_OK : B_BUSY;
878 		case B_MODULE_UNINIT:
879 			return B_OK;
880 
881 		default:
882 			return B_ERROR;
883 	}
884 }
885 
886 
887 static net_stack_module_info sNetStackModule = {
888 	{
889 		NET_STACK_MODULE_NAME,
890 		0,
891 		stack_std_ops
892 	},
893 	register_domain,
894 	unregister_domain,
895 	get_domain,
896 
897 	register_domain_protocols,
898 	register_domain_datalink_protocols,
899 	register_domain_receiving_protocol,
900 
901 	get_domain_receiving_protocol,
902 	put_domain_receiving_protocol,
903 
904 	register_device_deframer,
905 	unregister_device_deframer,
906 	register_domain_device_handler,
907 	register_device_handler,
908 	unregister_device_handler,
909 	register_device_monitor,
910 	unregister_device_monitor,
911 	device_removed,
912 
913 	checksum,
914 
915 	init_fifo,
916 	uninit_fifo,
917 	fifo_enqueue_buffer,
918 	fifo_dequeue_buffer,
919 	clear_fifo,
920 
921 	init_timer,
922 	set_timer,
923 };
924 
925 static module_info sNetStarterModule = {
926 	NET_STARTER_MODULE_NAME,
927 	0,
928 	starter_std_ops
929 };
930 
931 module_info *modules[] = {
932 	(module_info *)&sNetStackModule,
933 	(module_info *)&sNetStarterModule,
934 	(module_info *)&gNetBufferModule,
935 	(module_info *)&gNetSocketModule,
936 	(module_info *)&gNetDatalinkModule,
937 	(module_info *)&gLinkModule,
938 	NULL
939 };
940