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