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