ng_base.c revision 70784
11556Srgrimes/*
21556Srgrimes * ng_base.c
31556Srgrimes *
41556Srgrimes * Copyright (c) 1996-1999 Whistle Communications, Inc.
51556Srgrimes * All rights reserved.
61556Srgrimes *
71556Srgrimes * Subject to the following obligations and disclaimer of warranty, use and
81556Srgrimes * redistribution of this software, in source or object code forms, with or
91556Srgrimes * without modifications are expressly permitted by Whistle Communications;
101556Srgrimes * provided, however, that:
111556Srgrimes * 1. Any and all reproductions of the source or object code must include the
121556Srgrimes *    copyright notice above and the following disclaimer of warranties; and
131556Srgrimes * 2. No rights are granted, in any manner or form, to use Whistle
141556Srgrimes *    Communications, Inc. trademarks, including the mark "WHISTLE
151556Srgrimes *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
161556Srgrimes *    such appears in the above copyright notice or in the software.
171556Srgrimes *
181556Srgrimes * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
191556Srgrimes * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
201556Srgrimes * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
211556Srgrimes * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
221556Srgrimes * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
231556Srgrimes * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
241556Srgrimes * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
251556Srgrimes * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
261556Srgrimes * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
271556Srgrimes * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
281556Srgrimes * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
291556Srgrimes * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
301556Srgrimes * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
311556Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3217987Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3350471Speter * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
341556Srgrimes * OF SUCH DAMAGE.
351556Srgrimes *
361556Srgrimes * Authors: Julian Elischer <julian@freebsd.org>
371556Srgrimes *          Archie Cobbs <archie@freebsd.org>
381556Srgrimes *
391556Srgrimes * $FreeBSD: head/sys/netgraph/ng_base.c 70784 2001-01-08 05:34:06Z julian $
4046684Skris * $Whistle: ng_base.c,v 1.39 1999/01/28 23:54:53 julian Exp $
411556Srgrimes */
421556Srgrimes
431556Srgrimes/*
441556Srgrimes * This file implements the base netgraph code.
451556Srgrimes */
461556Srgrimes
4738521Scracauer#include <sys/param.h>
481556Srgrimes#include <sys/systm.h>
491556Srgrimes#include <sys/errno.h>
501556Srgrimes#include <sys/kernel.h>
511556Srgrimes#include <sys/malloc.h>
521556Srgrimes#include <sys/syslog.h>
531556Srgrimes#include <sys/sysctl.h>
5438530Scracauer#include <sys/linker.h>
551556Srgrimes#include <sys/queue.h>
561556Srgrimes#include <sys/mbuf.h>
571556Srgrimes#include <sys/ctype.h>
581556Srgrimes#include <machine/limits.h>
59218306Sjilles
60220978Sjilles#include <net/netisr.h>
611556Srgrimes
621556Srgrimes#include <netgraph/ng_message.h>
631556Srgrimes#include <netgraph/netgraph.h>
641556Srgrimes#include <netgraph/ng_parse.h>
651556Srgrimes
661556SrgrimesMODULE_VERSION(netgraph, 1);
671556Srgrimes
681556Srgrimes/* List of all active nodes */
691556Srgrimesstatic LIST_HEAD(, ng_node) ng_nodelist;
7038521Scracauerstatic struct mtx	ng_nodelist_mtx;
7138521Scracauer
721556Srgrimes#ifdef	NETGRAPH_DEBUG
731556Srgrimes
7417987Speterstatic SLIST_HEAD(, ng_node) ng_allnodes;
75199660Sjillesstatic LIST_HEAD(, ng_node) ng_freenodes; /* in debug, we never free() them */
76199660Sjillesstatic SLIST_HEAD(, ng_hook) ng_allhooks;
771556Srgrimesstatic LIST_HEAD(, ng_hook) ng_freehooks; /* in debug, we never free() them */
781556Srgrimes
791556Srgrimesstatic void ng_dumpitems(void);
801556Srgrimesstatic void ng_dumpnodes(void);
81200967Sjillesstatic void ng_dumphooks(void);
8290111Simp
83216622Sjilles#endif	/* NETGRAPH_DEBUG */
84200967Sjilles
85200967Sjilles/* List nodes with unallocated work */
861556Srgrimesstatic TAILQ_HEAD(, ng_node) ng_worklist = TAILQ_HEAD_INITIALIZER(ng_worklist);
871556Srgrimesstatic struct mtx	ng_worklist_mtx;
881556Srgrimes
891556Srgrimes/* List of installed types */
901556Srgrimesstatic LIST_HEAD(, ng_type) ng_typelist;
911556Srgrimesstatic struct mtx	ng_typelist_mtx;
921556Srgrimes
931556Srgrimes/* Hash related definitions */
941556Srgrimes/* Don't nead to initialise them because it's a LIST */
95#define ID_HASH_SIZE 32 /* most systems wont need even this many */
96static LIST_HEAD(, ng_node) ng_ID_hash[ID_HASH_SIZE];
97static struct mtx	ng_idhash_mtx;
98
99/* Mutex that protects the free queue item list */
100static volatile item_p		ngqfree;	/* free ones */
101static struct mtx	ngq_mtx;
102
103/* Internal functions */
104static int	ng_add_hook(node_p node, const char *name, hook_p * hookp);
105static int	ng_connect(hook_p hook1, hook_p hook2);
106static void	ng_disconnect_hook(hook_p hook);
107static int	ng_generic_msg(node_p here, item_p item, hook_p lasthook);
108static ng_ID_t	ng_decodeidname(const char *name);
109static int	ngb_mod_event(module_t mod, int event, void *data);
110static void	ng_worklist_remove(node_p node);
111static void	ngintr(void);
112static int	ng_apply_item(node_p node, item_p item);
113static void	ng_flush_input_queue(struct ng_queue * ngq);
114static void	ng_setisr(node_p node);
115static node_p	ng_ID2noderef(ng_ID_t ID);
116
117/* imported , these used to be externally visible, some may go back */
118int	ng_bypass(hook_p hook1, hook_p hook2);
119void	ng_cutlinks(node_p node);
120int	ng_con_nodes(node_p node, const char *name, node_p node2,
121	const char *name2);
122void	ng_destroy_hook(hook_p hook);
123node_p	ng_name2noderef(node_p node, const char *name);
124int	ng_path2noderef(node_p here, const char *path,
125	node_p *dest, hook_p *lasthook);
126struct	ng_type *ng_findtype(const char *type);
127int	ng_make_node(const char *type, node_p *nodepp);
128int	ng_mkpeer(node_p node, const char *name, const char *name2, char *type);
129int	ng_path_parse(char *addr, char **node, char **path, char **hook);
130void	ng_rmnode(node_p node);
131void	ng_unname(node_p node);
132
133
134/* Our own netgraph malloc type */
135MALLOC_DEFINE(M_NETGRAPH, "netgraph", "netgraph structures and ctrl messages");
136MALLOC_DEFINE(M_NETGRAPH_HOOK, "netgraph_hook", "netgraph hook structures");
137MALLOC_DEFINE(M_NETGRAPH_NODE, "netgraph_node", "netgraph node structures");
138MALLOC_DEFINE(M_NETGRAPH_ITEM, "netgraph_item", "netgraph item structures");
139MALLOC_DEFINE(M_NETGRAPH_META, "netgraph_meta", "netgraph name storage");
140MALLOC_DEFINE(M_NETGRAPH_MSG, "netgraph_msg", "netgraph name storage");
141
142/* Should not be visible outside this file */
143
144#define _NG_ALLOC_HOOK(hook) \
145	MALLOC(hook, hook_p, sizeof(*hook), M_NETGRAPH_HOOK, M_NOWAIT | M_ZERO)
146#define _NG_ALLOC_NODE(node) \
147	MALLOC(node, node_p, sizeof(*node), M_NETGRAPH_NODE, M_NOWAIT | M_ZERO)
148
149#ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
150/*
151 * In debug mode:
152 * In an attempt to help track reference count screwups
153 * we do not free objects back to the malloc system, but keep them
154 * in a local cache where we can examine them and keep information safely
155 * after they have been freed.
156 * We use this scheme for nodes and hooks, and to some extent for items.
157 */
158static __inline hook_p
159ng_alloc_hook(void)
160{
161	hook_p hook;
162	SLIST_ENTRY(ng_hook) temp;
163	mtx_enter(&ng_nodelist_mtx, MTX_DEF);
164	hook = LIST_FIRST(&ng_freehooks);
165	if (hook) {
166		LIST_REMOVE(hook, hk_hooks);
167		bcopy(&hook->hk_all, &temp, sizeof(temp));
168		bzero(hook, sizeof(struct ng_hook));
169		bcopy(&temp, &hook->hk_all, sizeof(temp));
170		mtx_exit(&ng_nodelist_mtx, MTX_DEF);
171		hook->hk_magic = HK_MAGIC;
172	} else {
173		mtx_exit(&ng_nodelist_mtx, MTX_DEF);
174		_NG_ALLOC_HOOK(hook);
175		if (hook) {
176			hook->hk_magic = HK_MAGIC;
177			mtx_enter(&ng_nodelist_mtx, MTX_DEF);
178			SLIST_INSERT_HEAD(&ng_allhooks, hook, hk_all);
179			mtx_exit(&ng_nodelist_mtx, MTX_DEF);
180		}
181	}
182	return (hook);
183}
184
185static __inline node_p
186ng_alloc_node(void)
187{
188	node_p node;
189	SLIST_ENTRY(ng_node) temp;
190	mtx_enter(&ng_nodelist_mtx, MTX_DEF);
191	node = LIST_FIRST(&ng_freenodes);
192	if (node) {
193		LIST_REMOVE(node, nd_nodes);
194		bcopy(&node->nd_all, &temp, sizeof(temp));
195		bzero(node, sizeof(struct ng_node));
196		bcopy(&temp, &node->nd_all, sizeof(temp));
197		mtx_exit(&ng_nodelist_mtx, MTX_DEF);
198		node->nd_magic = ND_MAGIC;
199	} else {
200		mtx_exit(&ng_nodelist_mtx, MTX_DEF);
201		_NG_ALLOC_NODE(node);
202		if (node) {
203			node->nd_magic = ND_MAGIC;
204			mtx_enter(&ng_nodelist_mtx, MTX_DEF);
205			SLIST_INSERT_HEAD(&ng_allnodes, node, nd_all);
206			mtx_exit(&ng_nodelist_mtx, MTX_DEF);
207		}
208	}
209	return (node);
210}
211
212#define NG_ALLOC_HOOK(hook) do { (hook) = ng_alloc_hook(); } while (0)
213#define NG_ALLOC_NODE(node) do { (node) = ng_alloc_node(); } while (0)
214
215
216#define NG_FREE_HOOK(hook)						\
217	do {								\
218		mtx_enter(&ng_nodelist_mtx, MTX_DEF);			\
219		LIST_INSERT_HEAD(&ng_freehooks, hook, hk_hooks);	\
220		hook->hk_magic = 0;					\
221		mtx_exit(&ng_nodelist_mtx, MTX_DEF);			\
222	} while (0)
223
224#define NG_FREE_NODE(node)						\
225	do {								\
226		mtx_enter(&ng_nodelist_mtx, MTX_DEF);			\
227		LIST_INSERT_HEAD(&ng_freenodes, node, nd_nodes);	\
228		node->nd_magic = 0;					\
229		mtx_exit(&ng_nodelist_mtx, MTX_DEF);			\
230	} while (0)
231
232#else /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
233
234#define NG_ALLOC_HOOK(hook) _NG_ALLOC_HOOK(hook)
235#define NG_ALLOC_NODE(node) _NG_ALLOC_NODE(node)
236
237#define NG_FREE_HOOK(hook) do { FREE((hook), M_NETGRAPH_HOOK); } while (0)
238#define NG_FREE_NODE(node) do { FREE((node), M_NETGRAPH_NODE); } while (0)
239
240#endif /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
241
242/* Warning: Generally use NG_FREE_ITEM() instead */
243#define NG_FREE_ITEM_REAL(item) do { FREE((item), M_NETGRAPH_ITEM); } while (0)
244
245
246/* Set this to Debugger("X") to catch all errors as they occur */
247#ifndef TRAP_ERROR
248#define TRAP_ERROR
249#endif
250
251static	ng_ID_t nextID = 1;
252
253#ifdef INVARIANTS
254#define CHECK_DATA_MBUF(m)	do {					\
255		struct mbuf *n;						\
256		int total;						\
257									\
258		if (((m)->m_flags & M_PKTHDR) == 0)			\
259			panic("%s: !PKTHDR", __FUNCTION__);		\
260		for (total = 0, n = (m); n != NULL; n = n->m_next)	\
261			total += n->m_len;				\
262		if ((m)->m_pkthdr.len != total) {			\
263			panic("%s: %d != %d",				\
264			    __FUNCTION__, (m)->m_pkthdr.len, total);	\
265		}							\
266	} while (0)
267#else
268#define CHECK_DATA_MBUF(m)
269#endif
270
271
272/************************************************************************
273	Parse type definitions for generic messages
274************************************************************************/
275
276/* Handy structure parse type defining macro */
277#define DEFINE_PARSE_STRUCT_TYPE(lo, up, args)				\
278static const struct ng_parse_struct_info				\
279	ng_ ## lo ## _type_info = NG_GENERIC_ ## up ## _INFO args;	\
280static const struct ng_parse_type ng_generic_ ## lo ## _type = {	\
281	&ng_parse_struct_type,						\
282	&ng_ ## lo ## _type_info					\
283}
284
285DEFINE_PARSE_STRUCT_TYPE(mkpeer, MKPEER, ());
286DEFINE_PARSE_STRUCT_TYPE(connect, CONNECT, ());
287DEFINE_PARSE_STRUCT_TYPE(name, NAME, ());
288DEFINE_PARSE_STRUCT_TYPE(rmhook, RMHOOK, ());
289DEFINE_PARSE_STRUCT_TYPE(nodeinfo, NODEINFO, ());
290DEFINE_PARSE_STRUCT_TYPE(typeinfo, TYPEINFO, ());
291DEFINE_PARSE_STRUCT_TYPE(linkinfo, LINKINFO, (&ng_generic_nodeinfo_type));
292
293/* Get length of an array when the length is stored as a 32 bit
294   value immediately preceeding the array -- as with struct namelist
295   and struct typelist. */
296static int
297ng_generic_list_getLength(const struct ng_parse_type *type,
298	const u_char *start, const u_char *buf)
299{
300	return *((const u_int32_t *)(buf - 4));
301}
302
303/* Get length of the array of struct linkinfo inside a struct hooklist */
304static int
305ng_generic_linkinfo_getLength(const struct ng_parse_type *type,
306	const u_char *start, const u_char *buf)
307{
308	const struct hooklist *hl = (const struct hooklist *)start;
309
310	return hl->nodeinfo.hooks;
311}
312
313/* Array type for a variable length array of struct namelist */
314static const struct ng_parse_array_info ng_nodeinfoarray_type_info = {
315	&ng_generic_nodeinfo_type,
316	&ng_generic_list_getLength
317};
318static const struct ng_parse_type ng_generic_nodeinfoarray_type = {
319	&ng_parse_array_type,
320	&ng_nodeinfoarray_type_info
321};
322
323/* Array type for a variable length array of struct typelist */
324static const struct ng_parse_array_info ng_typeinfoarray_type_info = {
325	&ng_generic_typeinfo_type,
326	&ng_generic_list_getLength
327};
328static const struct ng_parse_type ng_generic_typeinfoarray_type = {
329	&ng_parse_array_type,
330	&ng_typeinfoarray_type_info
331};
332
333/* Array type for array of struct linkinfo in struct hooklist */
334static const struct ng_parse_array_info ng_generic_linkinfo_array_type_info = {
335	&ng_generic_linkinfo_type,
336	&ng_generic_linkinfo_getLength
337};
338static const struct ng_parse_type ng_generic_linkinfo_array_type = {
339	&ng_parse_array_type,
340	&ng_generic_linkinfo_array_type_info
341};
342
343DEFINE_PARSE_STRUCT_TYPE(typelist, TYPELIST, (&ng_generic_nodeinfoarray_type));
344DEFINE_PARSE_STRUCT_TYPE(hooklist, HOOKLIST,
345	(&ng_generic_nodeinfo_type, &ng_generic_linkinfo_array_type));
346DEFINE_PARSE_STRUCT_TYPE(listnodes, LISTNODES,
347	(&ng_generic_nodeinfoarray_type));
348
349/* List of commands and how to convert arguments to/from ASCII */
350static const struct ng_cmdlist ng_generic_cmds[] = {
351	{
352	  NGM_GENERIC_COOKIE,
353	  NGM_SHUTDOWN,
354	  "shutdown",
355	  NULL,
356	  NULL
357	},
358	{
359	  NGM_GENERIC_COOKIE,
360	  NGM_MKPEER,
361	  "mkpeer",
362	  &ng_generic_mkpeer_type,
363	  NULL
364	},
365	{
366	  NGM_GENERIC_COOKIE,
367	  NGM_CONNECT,
368	  "connect",
369	  &ng_generic_connect_type,
370	  NULL
371	},
372	{
373	  NGM_GENERIC_COOKIE,
374	  NGM_NAME,
375	  "name",
376	  &ng_generic_name_type,
377	  NULL
378	},
379	{
380	  NGM_GENERIC_COOKIE,
381	  NGM_RMHOOK,
382	  "rmhook",
383	  &ng_generic_rmhook_type,
384	  NULL
385	},
386	{
387	  NGM_GENERIC_COOKIE,
388	  NGM_NODEINFO,
389	  "nodeinfo",
390	  NULL,
391	  &ng_generic_nodeinfo_type
392	},
393	{
394	  NGM_GENERIC_COOKIE,
395	  NGM_LISTHOOKS,
396	  "listhooks",
397	  NULL,
398	  &ng_generic_hooklist_type
399	},
400	{
401	  NGM_GENERIC_COOKIE,
402	  NGM_LISTNAMES,
403	  "listnames",
404	  NULL,
405	  &ng_generic_listnodes_type	/* same as NGM_LISTNODES */
406	},
407	{
408	  NGM_GENERIC_COOKIE,
409	  NGM_LISTNODES,
410	  "listnodes",
411	  NULL,
412	  &ng_generic_listnodes_type
413	},
414	{
415	  NGM_GENERIC_COOKIE,
416	  NGM_LISTTYPES,
417	  "listtypes",
418	  NULL,
419	  &ng_generic_typeinfo_type
420	},
421	{
422	  NGM_GENERIC_COOKIE,
423	  NGM_TEXT_CONFIG,
424	  "textconfig",
425	  NULL,
426	  &ng_parse_string_type
427	},
428	{
429	  NGM_GENERIC_COOKIE,
430	  NGM_TEXT_STATUS,
431	  "textstatus",
432	  NULL,
433	  &ng_parse_string_type
434	},
435	{
436	  NGM_GENERIC_COOKIE,
437	  NGM_ASCII2BINARY,
438	  "ascii2binary",
439	  &ng_parse_ng_mesg_type,
440	  &ng_parse_ng_mesg_type
441	},
442	{
443	  NGM_GENERIC_COOKIE,
444	  NGM_BINARY2ASCII,
445	  "binary2ascii",
446	  &ng_parse_ng_mesg_type,
447	  &ng_parse_ng_mesg_type
448	},
449	{ 0 }
450};
451
452/************************************************************************
453			Node routines
454************************************************************************/
455
456/*
457 * Instantiate a node of the requested type
458 */
459int
460ng_make_node(const char *typename, node_p *nodepp)
461{
462	struct ng_type *type;
463	int	error;
464
465	/* Check that the type makes sense */
466	if (typename == NULL) {
467		TRAP_ERROR;
468		return (EINVAL);
469	}
470
471	/* Locate the node type */
472	if ((type = ng_findtype(typename)) == NULL) {
473		char filename[NG_TYPELEN + 4];
474		linker_file_t lf;
475		int error;
476
477		/* Not found, try to load it as a loadable module */
478		snprintf(filename, sizeof(filename), "ng_%s", typename);
479		error = linker_load_file(filename, &lf);
480		if (error != 0)
481			return (error);
482		lf->userrefs++;		/* pretend loaded by the syscall */
483
484		/* Try again, as now the type should have linked itself in */
485		if ((type = ng_findtype(typename)) == NULL)
486			return (ENXIO);
487	}
488
489	/*
490	 * If we have a constructor, then make the node and
491	 * call the constructor to do type specific initialisation.
492	 */
493	if (type->constructor != NULL) {
494		if ((error = ng_make_node_common(type, nodepp)) == 0) {
495			if ((error = ((*type->constructor)(*nodepp)) != 0)) {
496				NG_NODE_UNREF(*nodepp);
497			}
498		}
499	} else {
500		/*
501		 * Node has no constructor. We cannot ask for one
502		 * to be made. It must be brought into existance by
503		 * some external agency. The external acency should
504		 * call ng_make_node_common() directly to get the
505		 * netgraph part initialised.
506		 */
507		TRAP_ERROR
508		error = EINVAL;
509	}
510	return (error);
511}
512
513/*
514 * Generic node creation. Called by node initialisation for externally
515 * instantiated nodes (e.g. hardware, sockets, etc ).
516 * The returned node has a reference count of 1.
517 */
518int
519ng_make_node_common(struct ng_type *type, node_p *nodepp)
520{
521	node_p node;
522
523	/* Require the node type to have been already installed */
524	if (ng_findtype(type->name) == NULL) {
525		TRAP_ERROR;
526		return (EINVAL);
527	}
528
529	/* Make a node and try attach it to the type */
530	NG_ALLOC_NODE(node);
531	if (node == NULL) {
532		TRAP_ERROR;
533		return (ENOMEM);
534	}
535	node->nd_type = type;
536	NG_NODE_REF(node);				/* note reference */
537	type->refs++;
538
539	mtx_init(&node->nd_input_queue.q_mtx, "netgraph node mutex", 0);
540	node->nd_input_queue.queue = NULL;
541	node->nd_input_queue.last = &node->nd_input_queue.queue;
542	node->nd_input_queue.q_flags = 0;
543	node->nd_input_queue.q_node = node;
544
545	/* Initialize hook list for new node */
546	LIST_INIT(&node->nd_hooks);
547
548	/* Link us into the node linked list */
549	mtx_enter(&ng_nodelist_mtx, MTX_DEF);
550	LIST_INSERT_HEAD(&ng_nodelist, node, nd_nodes);
551	mtx_exit(&ng_nodelist_mtx, MTX_DEF);
552
553
554	/* get an ID and put us in the hash chain */
555	mtx_enter(&ng_idhash_mtx, MTX_DEF);
556	for (;;) { /* wrap protection, even if silly */
557		node_p node2 = NULL;
558		node->nd_ID = nextID++; /* 137/second for 1 year before wrap */
559		/* Is there a problem with the new number? */
560		if ((node->nd_ID == 0)
561		|| (node2 = ng_ID2noderef(node->nd_ID))) {
562			if (node2) {
563				NG_NODE_UNREF(node2);
564				node2 = NULL;
565			}
566		} else {
567			break;
568		}
569	}
570	LIST_INSERT_HEAD(&ng_ID_hash[node->nd_ID % ID_HASH_SIZE],
571							node, nd_idnodes);
572	mtx_exit(&ng_idhash_mtx, MTX_DEF);
573
574	/* Done */
575	*nodepp = node;
576	return (0);
577}
578
579/*
580 * Forceably start the shutdown process on a node. Either call
581 * it's shutdown method, or do the default shutdown if there is
582 * no type-specific method.
583 *
584 * We can only be called form a shutdown message, so we know we have
585 * a writer lock, and therefore exclusive access.
586 *
587 * Persistent node types must have a type-specific method which
588 * Allocates a new node. This one is irretrievably going away.
589 */
590void
591ng_rmnode(node_p node)
592{
593	/* Check if it's already shutting down */
594	if ((node->nd_flags & NG_CLOSING) != 0)
595		return;
596
597	/* Add an extra reference so it doesn't go away during this */
598	NG_NODE_REF(node);
599
600	/*
601	 * Mark it invalid so any newcomers know not to try use it
602	 * Also add our own mark so we can't recurse
603	 * note that NG_INVALID does not do this as it's also set during
604	 * creation
605	 */
606	node->nd_flags |= NG_INVALID|NG_CLOSING;
607
608	ng_cutlinks(node);
609
610	/*
611	 * Drain the input queue forceably.
612	 * it has no hooks so what's it going to do, bleed on someone?
613	 * Theoretically we came here from a queue entry that was added
614	 * Just before the queue was closed, so it should be empty anyway.
615	 */
616	ng_flush_input_queue(&node->nd_input_queue);
617
618	/*
619	 * Take us off the work queue if we are there.
620	 * We definatly have no work to be done.
621	 */
622	ng_worklist_remove(node);
623
624	/* Ask the type if it has anything to do in this case */
625	if (node->nd_type && node->nd_type->shutdown) {
626		(*node->nd_type->shutdown)(node);
627	} else {				/* do the default thing */
628		NG_NODE_UNREF(node);
629	}
630	if (NG_NODE_IS_VALID(node)) {
631		/*
632		 * Well, blow me down if the node code hasn't declared
633		 * that it doesn't want to die.
634		 * Presumably it is a persistant node.
635		 * XXX we need a way to tell the node
636		 * "No, really.. the hardware's going away.. REALLY die"
637		 * We need a way
638		 */
639		return;
640	}
641
642	ng_unname(node); /* basically a NOP these days */
643
644	/*
645	 * Remove extra reference, possibly the last
646	 * Possible other holders of references may include
647	 * timeout callouts, but theoretically the node's supposed to
648	 * have cancelled them. Possibly hardware dependencies may
649	 * force a driver to 'linger' with a reference.
650	 */
651	NG_NODE_UNREF(node);
652}
653
654/*
655 * Called by the destructor to remove any STANDARD external references
656 * May one day have it's own message to call it..
657 */
658void
659ng_cutlinks(node_p node)
660{
661	hook_p  hook;
662
663	/* Make sure that this is set to stop infinite loops */
664	node->nd_flags |= NG_INVALID;
665
666	/*
667	 * Drain the input queue forceably.
668	 * We also do this in ng_rmnode
669	 * to make sure we get all code paths.
670	 */
671	ng_flush_input_queue(&node->nd_input_queue);
672
673	/* Notify all remaining connected nodes to disconnect */
674	while ((hook = LIST_FIRST(&node->nd_hooks)) != NULL)
675		ng_destroy_hook(hook);
676}
677
678/*
679 * Remove a reference to the node, possibly the last
680 */
681void
682ng_unref_node(node_p node)
683{
684	int     v;
685	do {
686		v = node->nd_refs;
687	} while (! atomic_cmpset_int(&node->nd_refs, v, v - 1));
688
689	if (v == 1) { /* we were the last */
690
691		mtx_enter(&ng_nodelist_mtx, MTX_DEF);
692		node->nd_type->refs--; /* XXX maybe should get types lock? */
693		LIST_REMOVE(node, nd_nodes);
694		mtx_exit(&ng_nodelist_mtx, MTX_DEF);
695
696		mtx_enter(&ng_idhash_mtx, MTX_DEF);
697		LIST_REMOVE(node, nd_idnodes);
698		mtx_exit(&ng_idhash_mtx, MTX_DEF);
699
700		NG_FREE_NODE(node);
701	}
702}
703
704/************************************************************************
705			Node ID handling
706************************************************************************/
707static node_p
708ng_ID2noderef(ng_ID_t ID)
709{
710	node_p node;
711	mtx_enter(&ng_idhash_mtx, MTX_DEF);
712	LIST_FOREACH(node, &ng_ID_hash[ID % ID_HASH_SIZE], nd_idnodes) {
713		if (node->nd_ID == ID)
714			break;
715	}
716	if(node)
717		NG_NODE_REF(node);
718	mtx_exit(&ng_idhash_mtx, MTX_DEF);
719	return(node);
720}
721
722ng_ID_t
723ng_node2ID(node_p node)
724{
725	return (node?node->nd_ID:0);
726}
727
728/************************************************************************
729			Node name handling
730************************************************************************/
731
732/*
733 * Assign a node a name. Once assigned, the name cannot be changed.
734 */
735int
736ng_name_node(node_p node, const char *name)
737{
738	int i;
739	node_p node2;
740
741	/* Check the name is valid */
742	for (i = 0; i < NG_NODELEN + 1; i++) {
743		if (name[i] == '\0' || name[i] == '.' || name[i] == ':')
744			break;
745	}
746	if (i == 0 || name[i] != '\0') {
747		TRAP_ERROR;
748		return (EINVAL);
749	}
750	if (ng_decodeidname(name) != 0) { /* valid IDs not allowed here */
751		TRAP_ERROR;
752		return (EINVAL);
753	}
754
755	/* Check the name isn't already being used */
756	if ((node2 = ng_name2noderef(node, name)) != NULL) {
757		NG_NODE_UNREF(node2);
758		TRAP_ERROR;
759		return (EADDRINUSE);
760	}
761
762	/* copy it */
763	strncpy(NG_NODE_NAME(node), name, NG_NODELEN);
764
765	return (0);
766}
767
768/*
769 * Find a node by absolute name. The name should NOT end with ':'
770 * The name "." means "this node" and "[xxx]" means "the node
771 * with ID (ie, at address) xxx".
772 *
773 * Returns the node if found, else NULL.
774 * Eventually should add something faster than a sequential search.
775 * Note it aquires a reference on the node so you can be sure it's still there.
776 */
777node_p
778ng_name2noderef(node_p here, const char *name)
779{
780	node_p node;
781	ng_ID_t temp;
782
783	/* "." means "this node" */
784	if (strcmp(name, ".") == 0) {
785		NG_NODE_REF(here);
786		return(here);
787	}
788
789	/* Check for name-by-ID */
790	if ((temp = ng_decodeidname(name)) != 0) {
791		return (ng_ID2noderef(temp));
792	}
793
794	/* Find node by name */
795	mtx_enter(&ng_nodelist_mtx, MTX_DEF);
796	LIST_FOREACH(node, &ng_nodelist, nd_nodes) {
797		if (NG_NODE_HAS_NAME(node)
798		&& (strcmp(NG_NODE_NAME(node), name) == 0))
799			break;
800	}
801	if (node)
802		NG_NODE_REF(node);
803	mtx_exit(&ng_nodelist_mtx, MTX_DEF);
804	return (node);
805}
806
807/*
808 * Decode a ID name, eg. "[f03034de]". Returns 0 if the
809 * string is not valid, otherwise returns the value.
810 */
811static ng_ID_t
812ng_decodeidname(const char *name)
813{
814	const int len = strlen(name);
815	char *eptr;
816	u_long val;
817
818	/* Check for proper length, brackets, no leading junk */
819	if (len < 3 || name[0] != '[' || name[len - 1] != ']'
820	    || !isxdigit(name[1]))
821		return (0);
822
823	/* Decode number */
824	val = strtoul(name + 1, &eptr, 16);
825	if (eptr - name != len - 1 || val == ULONG_MAX || val == 0)
826		return ((ng_ID_t)0);
827	return (ng_ID_t)val;
828}
829
830/*
831 * Remove a name from a node. This should only be called
832 * when shutting down and removing the node.
833 */
834void
835ng_unname(node_p node)
836{
837	bzero(NG_NODE_NAME(node), NG_NODELEN);
838}
839
840/************************************************************************
841			Hook routines
842 Names are not optional. Hooks are always connected, except for a
843 brief moment within these routines.
844************************************************************************/
845
846/*
847 * Remove a hook reference
848 */
849void
850ng_unref_hook(hook_p hook)
851{
852	int     v;
853	do {
854		v = hook->hk_refs;
855	} while (! atomic_cmpset_int(&hook->hk_refs, v, v - 1));
856
857	if (v == 1) { /* we were the last */
858		if (NG_HOOK_NODE(hook)) {
859			NG_NODE_UNREF((NG_HOOK_NODE(hook)));
860			hook->hk_node = NULL;
861		}
862		NG_FREE_HOOK(hook);
863	}
864}
865
866/*
867 * Add an unconnected hook to a node. Only used internally.
868 */
869static int
870ng_add_hook(node_p node, const char *name, hook_p *hookp)
871{
872	hook_p hook;
873	int error = 0;
874
875	/* Check that the given name is good */
876	if (name == NULL) {
877		TRAP_ERROR;
878		return (EINVAL);
879	}
880	if (ng_findhook(node, name) != NULL) {
881		TRAP_ERROR;
882		return (EEXIST);
883	}
884
885	/* Allocate the hook and link it up */
886	NG_ALLOC_HOOK(hook);
887	if (hook == NULL) {
888		TRAP_ERROR;
889		return (ENOMEM);
890	}
891	hook->hk_refs = 1;
892	hook->hk_flags = HK_INVALID;
893	hook->hk_node = node;
894	NG_NODE_REF(node);		/* each hook counts as a reference */
895
896	/* Check if the node type code has something to say about it */
897	if (node->nd_type->newhook != NULL)
898		if ((error = (*node->nd_type->newhook)(node, hook, name)) != 0) {
899			NG_HOOK_UNREF(hook);	/* this frees the hook */
900			return (error);
901		}
902
903	/*
904	 * The 'type' agrees so far, so go ahead and link it in.
905	 * We'll ask again later when we actually connect the hooks.
906	 * The reference we have is for this linkage.
907	 */
908	LIST_INSERT_HEAD(&node->nd_hooks, hook, hk_hooks);
909	node->nd_numhooks++;
910
911	/* Set hook name */
912	strncpy(NG_HOOK_NAME(hook), name, NG_HOOKLEN);
913	if (hookp)
914		*hookp = hook;
915	return (error);
916}
917
918/*
919 * Connect a pair of hooks. Only used internally.
920 */
921static int
922ng_connect(hook_p hook1, hook_p hook2)
923{
924	int     error;
925
926	hook1->hk_peer = hook2;
927	hook2->hk_peer = hook1;
928
929	/* Give each node the opportunity to veto the impending connection */
930	if (hook1->hk_node->nd_type->connect) {
931		if ((error = (*hook1->hk_node->nd_type->connect) (hook1))) {
932			ng_destroy_hook(hook1);	/* also zaps hook2 */
933			return (error);
934		}
935	}
936	if (hook2->hk_node->nd_type->connect) {
937		if ((error = (*hook2->hk_node->nd_type->connect) (hook2))) {
938			ng_destroy_hook(hook2);	/* also zaps hook1 */
939			return (error);
940		}
941	}
942	hook1->hk_flags &= ~HK_INVALID;
943	hook2->hk_flags &= ~HK_INVALID;
944	return (0);
945}
946
947/*
948 * Find a hook
949 *
950 * Node types may supply their own optimized routines for finding
951 * hooks.  If none is supplied, we just do a linear search.
952 */
953hook_p
954ng_findhook(node_p node, const char *name)
955{
956	hook_p hook;
957
958	if (node->nd_type->findhook != NULL)
959		return (*node->nd_type->findhook)(node, name);
960	LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
961		if (strcmp(NG_HOOK_NAME(hook), name) == 0)
962			return (hook);
963	}
964	return (NULL);
965}
966
967/*
968 * Destroy a hook
969 *
970 * As hooks are always attached, this really destroys two hooks.
971 * The one given, and the one attached to it. Disconnect the hooks
972 * from each other first.
973 */
974void
975ng_destroy_hook(hook_p hook)
976{
977	hook_p peer = NG_HOOK_PEER(hook);
978
979	hook->hk_flags |= HK_INVALID;		/* as soon as possible */
980	if (peer) {
981		peer->hk_flags |= HK_INVALID;	/* as soon as possible */
982		hook->hk_peer = NULL;
983		peer->hk_peer = NULL;
984		ng_disconnect_hook(peer);
985	}
986	ng_disconnect_hook(hook);
987}
988
989/*
990 * Notify the node of the hook's demise. This may result in more actions
991 * (e.g. shutdown) but we don't do that ourselves and don't know what
992 * happens there. If there is no appropriate handler, then just remove it
993 * (and decrement the reference count of it's node which in turn might
994 * make something happen).
995 */
996static void
997ng_disconnect_hook(hook_p hook)
998{
999	node_p node = NG_HOOK_NODE(hook);
1000
1001	/*
1002	 * Remove the hook from the node's list to avoid possible recursion
1003	 * in case the disconnection results in node shutdown.
1004	 */
1005	LIST_REMOVE(hook, hk_hooks);
1006	node->nd_numhooks--;
1007	if (node->nd_type->disconnect) {
1008		/*
1009		 * The type handler may elect to destroy the peer so don't
1010		 * trust its existance after this point.
1011		 */
1012		(*node->nd_type->disconnect) (hook);
1013	}
1014	NG_HOOK_UNREF(hook);
1015}
1016
1017/*
1018 * Take two hooks on a node and merge the connection so that the given node
1019 * is effectively bypassed.
1020 */
1021int
1022ng_bypass(hook_p hook1, hook_p hook2)
1023{
1024	if (hook1->hk_node != hook2->hk_node) {
1025		TRAP_ERROR
1026		return (EINVAL);
1027	}
1028	hook1->hk_peer->hk_peer = hook2->hk_peer;
1029	hook2->hk_peer->hk_peer = hook1->hk_peer;
1030
1031	/* XXX If we ever cache methods on hooks update them as well */
1032	hook1->hk_peer = NULL;
1033	hook2->hk_peer = NULL;
1034	ng_destroy_hook(hook1);
1035	ng_destroy_hook(hook2);
1036	return (0);
1037}
1038
1039/*
1040 * Install a new netgraph type
1041 */
1042int
1043ng_newtype(struct ng_type *tp)
1044{
1045	const size_t namelen = strlen(tp->name);
1046
1047	/* Check version and type name fields */
1048	if ((tp->version != NG_ABI_VERSION)
1049	|| (namelen == 0)
1050	|| (namelen > NG_TYPELEN)) {
1051		TRAP_ERROR;
1052		return (EINVAL);
1053	}
1054
1055	/* Check for name collision */
1056	if (ng_findtype(tp->name) != NULL) {
1057		TRAP_ERROR;
1058		return (EEXIST);
1059	}
1060
1061	tp->refs = 0;
1062
1063	/* Link in new type */
1064	mtx_enter(&ng_typelist_mtx, MTX_DEF);
1065	LIST_INSERT_HEAD(&ng_typelist, tp, types);
1066	mtx_exit(&ng_typelist_mtx, MTX_DEF);
1067	return (0);
1068}
1069
1070/*
1071 * Look for a type of the name given
1072 */
1073struct ng_type *
1074ng_findtype(const char *typename)
1075{
1076	struct ng_type *type;
1077
1078	mtx_enter(&ng_typelist_mtx, MTX_DEF);
1079	LIST_FOREACH(type, &ng_typelist, types) {
1080		if (strcmp(type->name, typename) == 0)
1081			break;
1082	}
1083	mtx_exit(&ng_typelist_mtx, MTX_DEF);
1084	return (type);
1085}
1086
1087/************************************************************************
1088			Composite routines
1089************************************************************************/
1090
1091/*
1092 * Make a peer and connect. The order is arranged to minimise
1093 * the work needed to back out in case of error.
1094 */
1095int
1096ng_mkpeer(node_p node, const char *name, const char *name2, char *type)
1097{
1098	node_p  node2;
1099	hook_p  hook;
1100	hook_p  hook2;
1101	int     error;
1102
1103	if ((error = ng_add_hook(node, name, &hook)))
1104		return (error);
1105	if ((error = ng_make_node(type, &node2))) {
1106		ng_destroy_hook(hook);
1107		return (error);
1108	}
1109	if ((error = ng_add_hook(node2, name2, &hook2))) {
1110		ng_rmnode(node2);
1111		ng_destroy_hook(hook);
1112		return (error);
1113	}
1114
1115	/*
1116	 * Actually link the two hooks together.. on failure they are
1117	 * destroyed so we don't have to do that here.
1118	 */
1119	if ((error = ng_connect(hook, hook2)))
1120		ng_rmnode(node2);
1121	return (error);
1122}
1123
1124/*
1125 * Connect two nodes using the specified hooks
1126 */
1127int
1128ng_con_nodes(node_p node, const char *name, node_p node2, const char *name2)
1129{
1130	int     error;
1131	hook_p  hook;
1132	hook_p  hook2;
1133
1134	if ((error = ng_add_hook(node, name, &hook)))
1135		return (error);
1136	if ((error = ng_add_hook(node2, name2, &hook2))) {
1137		ng_destroy_hook(hook);
1138		return (error);
1139	}
1140	return (ng_connect(hook, hook2));
1141}
1142/************************************************************************
1143		Utility routines to send self messages
1144************************************************************************/
1145/*
1146 * Static version of shutdown message. we don't want to need resources
1147 * to shut down (we may be doing it to release resources because we ran out.
1148 */
1149static struct	ng_mesg  ng_msg_shutdown = {
1150	{NG_VERSION,		/* u_char */
1151	0,			/* u_char spare */
1152	0,			/* u_int16_t arglen */
1153	NGF_STATIC,		/* u_int32_t flags */
1154	0,			/* u_int32_t token */
1155	NGM_GENERIC_COOKIE,	/* u_int32_t */
1156	NGM_SHUTDOWN,		/* u_int32_t */
1157	"shutdown"}		/* u_char[16] */
1158};
1159
1160int
1161ng_rmnode_self(node_p here)
1162{
1163	item_p	item;
1164	struct	ng_mesg	*msg;
1165
1166	/*
1167	 * Use the static version to avoid needing
1168	 * memory allocation to succeed.
1169	 * The message is never written to and always the same.
1170	 */
1171	msg = &ng_msg_shutdown;
1172
1173	/*
1174	 * Try get a queue item to send it with.
1175	 * Hopefully since it has a reserve, we can get one.
1176	 * If we can't we are screwed anyhow.
1177	 * Increase the chances by flushing our queue first.
1178	 * We may free an item, (if we were the hog).
1179	 * Work in progress is allowed to complete.
1180	 * We also pretty much ensure that we come straight
1181	 * back in to do the shutdown. It may be a good idea
1182	 * to hold a reference actually to stop it from all
1183	 * going up in smoke.
1184	 */
1185/*	ng_flush_input_queue(&here->nd_input_queue); will mask problem  */
1186	item = ng_package_msg_self(here, NULL, msg);
1187	if (item == NULL) { /* it would have freed the msg except static */
1188		/* try again after flushing our queue */
1189		ng_flush_input_queue(&here->nd_input_queue);
1190		item = ng_package_msg_self(here, NULL, msg);
1191		if (item == NULL) {
1192			printf("failed to free node 0x%x\n", ng_node2ID(here));
1193			return (ENOMEM);
1194		}
1195	}
1196	return (ng_snd_item(item, 0));
1197}
1198
1199/***********************************************************************
1200 * Parse and verify a string of the form:  <NODE:><PATH>
1201 *
1202 * Such a string can refer to a specific node or a specific hook
1203 * on a specific node, depending on how you look at it. In the
1204 * latter case, the PATH component must not end in a dot.
1205 *
1206 * Both <NODE:> and <PATH> are optional. The <PATH> is a string
1207 * of hook names separated by dots. This breaks out the original
1208 * string, setting *nodep to "NODE" (or NULL if none) and *pathp
1209 * to "PATH" (or NULL if degenerate). Also, *hookp will point to
1210 * the final hook component of <PATH>, if any, otherwise NULL.
1211 *
1212 * This returns -1 if the path is malformed. The char ** are optional.
1213 ***********************************************************************/
1214int
1215ng_path_parse(char *addr, char **nodep, char **pathp, char **hookp)
1216{
1217	char   *node, *path, *hook;
1218	int     k;
1219
1220	/*
1221	 * Extract absolute NODE, if any
1222	 */
1223	for (path = addr; *path && *path != ':'; path++);
1224	if (*path) {
1225		node = addr;	/* Here's the NODE */
1226		*path++ = '\0';	/* Here's the PATH */
1227
1228		/* Node name must not be empty */
1229		if (!*node)
1230			return -1;
1231
1232		/* A name of "." is OK; otherwise '.' not allowed */
1233		if (strcmp(node, ".") != 0) {
1234			for (k = 0; node[k]; k++)
1235				if (node[k] == '.')
1236					return -1;
1237		}
1238	} else {
1239		node = NULL;	/* No absolute NODE */
1240		path = addr;	/* Here's the PATH */
1241	}
1242
1243	/* Snoop for illegal characters in PATH */
1244	for (k = 0; path[k]; k++)
1245		if (path[k] == ':')
1246			return -1;
1247
1248	/* Check for no repeated dots in PATH */
1249	for (k = 0; path[k]; k++)
1250		if (path[k] == '.' && path[k + 1] == '.')
1251			return -1;
1252
1253	/* Remove extra (degenerate) dots from beginning or end of PATH */
1254	if (path[0] == '.')
1255		path++;
1256	if (*path && path[strlen(path) - 1] == '.')
1257		path[strlen(path) - 1] = 0;
1258
1259	/* If PATH has a dot, then we're not talking about a hook */
1260	if (*path) {
1261		for (hook = path, k = 0; path[k]; k++)
1262			if (path[k] == '.') {
1263				hook = NULL;
1264				break;
1265			}
1266	} else
1267		path = hook = NULL;
1268
1269	/* Done */
1270	if (nodep)
1271		*nodep = node;
1272	if (pathp)
1273		*pathp = path;
1274	if (hookp)
1275		*hookp = hook;
1276	return (0);
1277}
1278
1279/*
1280 * Given a path, which may be absolute or relative, and a starting node,
1281 * return the destination node.
1282 */
1283int
1284ng_path2noderef(node_p here, const char *address,
1285				node_p *destp, hook_p *lasthook)
1286{
1287	char    fullpath[NG_PATHLEN + 1];
1288	char   *nodename, *path, pbuf[2];
1289	node_p  node, oldnode;
1290	char   *cp;
1291	hook_p hook = NULL;
1292
1293	/* Initialize */
1294	if (destp == NULL) {
1295		TRAP_ERROR
1296		return EINVAL;
1297	}
1298	*destp = NULL;
1299
1300	/* Make a writable copy of address for ng_path_parse() */
1301	strncpy(fullpath, address, sizeof(fullpath) - 1);
1302	fullpath[sizeof(fullpath) - 1] = '\0';
1303
1304	/* Parse out node and sequence of hooks */
1305	if (ng_path_parse(fullpath, &nodename, &path, NULL) < 0) {
1306		TRAP_ERROR;
1307		return EINVAL;
1308	}
1309	if (path == NULL) {
1310		pbuf[0] = '.';	/* Needs to be writable */
1311		pbuf[1] = '\0';
1312		path = pbuf;
1313	}
1314
1315	/*
1316	 * For an absolute address, jump to the starting node.
1317	 * Note that this holds a reference on the node for us.
1318	 * Don't forget to drop the reference if we don't need it.
1319	 */
1320	if (nodename) {
1321		node = ng_name2noderef(here, nodename);
1322		if (node == NULL) {
1323			TRAP_ERROR
1324			return (ENOENT);
1325		}
1326	} else {
1327		if (here == NULL) {
1328			TRAP_ERROR
1329			return (EINVAL);
1330		}
1331		node = here;
1332		NG_NODE_REF(node);
1333	}
1334
1335	/*
1336	 * Now follow the sequence of hooks
1337	 * XXX
1338	 * We actually cannot guarantee that the sequence
1339	 * is not being demolished as we crawl along it
1340	 * without extra-ordinary locking etc.
1341	 * So this is a bit dodgy to say the least.
1342	 * We can probably hold up some things by holding
1343	 * the nodelist mutex for the time of this
1344	 * crawl if we wanted.. At least that way we wouldn't have to
1345	 * worry about the nodes dissappearing, but the hooks would still
1346	 * be a problem.
1347	 */
1348	for (cp = path; node != NULL && *cp != '\0'; ) {
1349		char *segment;
1350
1351		/*
1352		 * Break out the next path segment. Replace the dot we just
1353		 * found with a NUL; "cp" points to the next segment (or the
1354		 * NUL at the end).
1355		 */
1356		for (segment = cp; *cp != '\0'; cp++) {
1357			if (*cp == '.') {
1358				*cp++ = '\0';
1359				break;
1360			}
1361		}
1362
1363		/* Empty segment */
1364		if (*segment == '\0')
1365			continue;
1366
1367		/* We have a segment, so look for a hook by that name */
1368		hook = ng_findhook(node, segment);
1369
1370		/* Can't get there from here... */
1371		if (hook == NULL
1372		    || NG_HOOK_PEER(hook) == NULL
1373		    || NG_HOOK_NOT_VALID(hook)
1374		    || NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook))) {
1375			TRAP_ERROR;
1376			NG_NODE_UNREF(node);
1377#if 0
1378			printf("hooknotvalid %s %s %d %d %d %d ",
1379					path,
1380					segment,
1381					hook == NULL,
1382		     			NG_HOOK_PEER(hook) == NULL,
1383		     			NG_HOOK_NOT_VALID(hook),
1384		     			NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook)));
1385#endif
1386			return (ENOENT);
1387		}
1388
1389		/*
1390		 * Hop on over to the next node
1391		 * XXX
1392		 * Big race conditions here as hooks and nodes go away
1393		 * *** Idea.. store an ng_ID_t in each hook and use that
1394		 * instead of the direct hook in this crawl?
1395		 */
1396		oldnode = node;
1397		if ((node = NG_PEER_NODE(hook)))
1398			NG_NODE_REF(node);	/* XXX RACE */
1399		NG_NODE_UNREF(oldnode);	/* XXX another race */
1400		if (NG_NODE_NOT_VALID(node)) {
1401			NG_NODE_UNREF(node);	/* XXX more races */
1402			node = NULL;
1403		}
1404	}
1405
1406	/* If node somehow missing, fail here (probably this is not needed) */
1407	if (node == NULL) {
1408		TRAP_ERROR;
1409		return (ENXIO);
1410	}
1411
1412	/* Done */
1413	*destp = node;
1414	if (lasthook != NULL)
1415		*lasthook = (hook ? NG_HOOK_PEER(hook) : NULL);
1416	return (0);
1417}
1418
1419/***************************************************************\
1420* Input queue handling.
1421* All activities are submitted to the node via the input queue
1422* which implements a multiple-reader/single-writer gate.
1423* Items which cannot be handled immeditly are queued.
1424*
1425* read-write queue locking inline functions			*
1426\***************************************************************/
1427
1428static __inline item_p ng_dequeue(struct ng_queue * ngq);
1429static __inline item_p ng_acquire_read(struct ng_queue * ngq,
1430					item_p  item);
1431static __inline item_p ng_acquire_write(struct ng_queue * ngq,
1432					item_p  item);
1433static __inline void	ng_leave_read(struct ng_queue * ngq);
1434static __inline void	ng_leave_write(struct ng_queue * ngq);
1435static __inline void	ng_queue_rw(struct ng_queue * ngq,
1436					item_p  item, int rw);
1437
1438/*
1439 * Definition of the bits fields in the ng_queue flag word.
1440 * Defined here rather than in netgraph.h because no-one should fiddle
1441 * with them.
1442 *
1443 * The ordering here is important! don't shuffle these. If you add
1444 * READ_PENDING to the word when it has READ_PENDING already set, you
1445 * generate a carry into the reader count, this you atomically add a reader,
1446 * and remove the pending reader count! Similarly for the pending writer
1447 * flag, adding WRITE_PENDING generates a carry and sets the WRITER_ACTIVE
1448 * flag, while clearing WRITE_PENDING. When 'SINGLE_THREAD_ONLY' is set, then
1449 * it is only permitted to do WRITER operations. Reader operations will
1450 * result in errors.
1451 * But that "hack" is unnecessary: "cpp" can do the math for us!
1452 */
1453/*-
1454 Safety Barrier--------+ (adjustable to suit taste) (not used yet)
1455                       |
1456                       V
1457+-------+-------+-------+-------+-------+-------+-------+-------+
1458| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
1459|A|c|t|i|v|e| |R|e|a|d|e|r| |C|o|u|n|t| | | | | | | | | |R|A|W|S|
1460| | | | | | | | | | | | | | | | | | | | | | | | | | | | |P|W|P|T|
1461+-------+-------+-------+-------+-------+-------+-------+-------+
1462\_________________________ ____________________________/ | | | |
1463                          V                              | | | |
1464                [active reader count]                    | | | |
1465                                                         | | | |
1466        Read Pending ------------------------------------+ | | |
1467                                                           | | |
1468        Active Writer -------------------------------------+ | |
1469                                                             | |
1470        Write Pending ---------------------------------------+ |
1471                                                               |
1472        Single Threading Only ---------------------------------+
1473*/
1474#define	SINGLE_THREAD_ONLY 0x00000001	/* if set, even reads single thread */
1475#define WRITE_PENDING	0x00000002
1476#define	WRITER_ACTIVE	0x00000004
1477#define READ_PENDING	0x00000008
1478#define	READER_INCREMENT 0x00000010
1479#define	READER_MASK	0xfffffff0	/* Not valid if WRITER_ACTIVE is set */
1480#define SAFETY_BARRIER	0x00100000	/* 64K items queued should be enough */
1481/*
1482 * Taking into account the current state of the queue and node, possibly take
1483 * the next entry off the queue and return it. Return NULL if there was
1484 * nothing we could return, either because there really was nothing there, or
1485 * because the node was in a state where it cannot yet process the next item
1486 * on the queue.
1487 *
1488 * This MUST MUST MUST be called with the mutex held.
1489 */
1490static __inline item_p
1491ng_dequeue(struct ng_queue *ngq)
1492{
1493	item_p item;
1494	u_int		add_arg;
1495	/*
1496	 * If there is a writer, then the answer is "no". Everything else
1497	 * stops when there is a WRITER.
1498	 */
1499	if (ngq->q_flags & WRITER_ACTIVE) {
1500		return (NULL);
1501	}
1502	/* Now take a look at what's on the queue and what's running */
1503	if ((ngq->q_flags & ~(READER_MASK | SINGLE_THREAD_ONLY)) == READ_PENDING) {
1504		/*
1505		 * It was a reader and we have no write active. We don't care
1506		 * how many readers are already active. Adjust the count for
1507		 * the item we are about to dequeue. Adding READ_PENDING to
1508		 * the exisiting READ_PENDING clears it and generates a carry
1509		 * into the reader count.
1510		 */
1511		add_arg = READ_PENDING;
1512	} else if ((ngq->q_flags & ~SINGLE_THREAD_ONLY) == WRITE_PENDING) {
1513		/*
1514		 * There is a pending write, no readers and no active writer.
1515		 * This means we can go ahead with the pending writer. Note
1516		 * the fact that we now have a writer, ready for when we take
1517		 * it off the queue.
1518		 *
1519		 * We don't need to worry about a possible collision with the
1520		 * fasttrack reader.
1521		 *
1522		 * The fasttrack thread may take a long time to discover that we
1523		 * are running so we would have an inconsistent state in the
1524		 * flags for a while. Since we ignore the reader count
1525		 * entirely when the WRITER_ACTIVE flag is set, this should
1526		 * not matter (in fact it is defined that way). If it tests
1527		 * the flag before this operation, the WRITE_PENDING flag
1528		 * will make it fail, and if it tests it later, the
1529		 * ACTIVE_WRITER flag will do the same. If it is SO slow that
1530		 * we have actually completed the operation, and neither flag
1531		 * is set (nor the READ_PENDING) by the time that it tests
1532		 * the flags, then it is actually ok for it to continue. If
1533		 * it completes and we've finished and the read pending is
1534		 * set it still fails.
1535		 *
1536		 * So we can just ignore it,  as long as we can ensure that the
1537		 * transition from WRITE_PENDING state to the WRITER_ACTIVE
1538		 * state is atomic.
1539		 *
1540		 * After failing, first it will be held back by the mutex, then
1541		 * when it can proceed, it will queue its request, then it
1542		 * would arrive at this function. Usually it will have to
1543		 * leave empty handed because the ACTIVE WRITER bit wil be
1544		 * set.
1545		 */
1546		/*
1547		 * Adjust the flags for the item we are about to dequeue.
1548		 * Adding WRITE_PENDING to the exisiting WRITE_PENDING clears
1549		 * it and generates a carry into the WRITER_ACTIVE flag, all
1550		 * atomically.
1551		 */
1552		add_arg = WRITE_PENDING;
1553		/*
1554		 * We want to write "active writer, no readers " Now go make
1555		 * it true. In fact there may be a number in the readers
1556		 * count but we know it is not true and will be fixed soon.
1557		 * We will fix the flags for the next pending entry in a
1558		 * moment.
1559		 */
1560	} else {
1561		/*
1562		 * We can't dequeue anything.. return and say so. Probably we
1563		 * have a write pending and the readers count is non zero. If
1564		 * we got here because a reader hit us just at the wrong
1565		 * moment with the fasttrack code, and put us in a strange
1566		 * state, then it will be through in just a moment, (as soon
1567		 * as we release the mutex) and keep things moving.
1568		 */
1569		return (0);
1570	}
1571
1572	/*
1573	 * Now we dequeue the request (whatever it may be) and correct the
1574	 * pending flags and the next and last pointers.
1575	 */
1576	item = ngq->queue;
1577	ngq->queue = item->el_next;
1578	if (ngq->last == &(item->el_next)) {
1579		/*
1580		 * that was the last entry in the queue so set the 'last
1581		 * pointer up correctly and make sure the pending flags are
1582		 * clear.
1583		 */
1584		ngq->last = &(ngq->queue);
1585		/*
1586		 * Whatever flag was set is cleared and the carry sets the
1587		 * correct new active state/count. So we don't need to change
1588		 * add_arg.
1589		 */
1590	} else {
1591		if ((ngq->queue->el_flags & NGQF_TYPE) == NGQF_READER) {
1592			/*
1593			 * If we had a READ_PENDING and have another one, we
1594			 * just want to add READ_PENDING twice (the same as
1595			 * adding READER_INCREMENT). If we had WRITE_PENDING,
1596			 * we want to add READ_PENDING + WRITE_PENDING to
1597			 * clear the old WRITE_PENDING, set ACTIVE_WRITER,
1598			 * and set READ_PENDING. Either way we just add
1599			 * READ_PENDING to whatever we already had.
1600			 */
1601			add_arg += READ_PENDING;
1602		} else {
1603			/*
1604			 * If we had a WRITE_PENDING and have another one, we
1605			 * just want to add WRITE_PENDING twice (the same as
1606			 * adding ACTIVE_WRITER). If we had READ_PENDING, we
1607			 * want to add READ_PENDING + WRITE_PENDING to clear
1608			 * the old READ_PENDING, increment the readers, and
1609			 * set WRITE_PENDING. Either way we just add
1610			 * WRITE_PENDING to whatever we already had.
1611			 */
1612			add_arg += WRITE_PENDING;
1613		}
1614	}
1615	atomic_add_long(&ngq->q_flags, add_arg);
1616	/*
1617	 * We have successfully cleared the old pending flag, set the new one
1618	 * if it is needed, and incremented the appropriate active field.
1619	 * (all in one atomic addition.. wow)
1620	 */
1621	return (item);
1622}
1623
1624/*
1625 * Queue a packet to be picked up by someone else.
1626 * We really don't care who, but we can't or don't want to hang around
1627 * to process it ourselves. We are probably an interrupt routine..
1628 * 1 = writer, 0 = reader
1629 * We should set something to indicate NETISR requested
1630 * If it's the first item queued.
1631 */
1632#define NGQRW_R 0
1633#define NGQRW_W 1
1634static __inline void
1635ng_queue_rw(struct ng_queue * ngq, item_p  item, int rw)
1636{
1637	item->el_next = NULL;	/* maybe not needed */
1638	*ngq->last = item;
1639	/*
1640	 * If it was the first item in the queue then we need to
1641	 * set the last pointer and the type flags.
1642	 */
1643	if (ngq->last == &(ngq->queue)) {
1644		/*
1645		 * When called with constants for rw, the optimiser will
1646		 * remove the unneeded branch below.
1647		 */
1648		if (rw == NGQRW_W) {
1649			atomic_add_long(&ngq->q_flags, WRITE_PENDING);
1650		} else {
1651			atomic_add_long(&ngq->q_flags, READ_PENDING);
1652		}
1653	}
1654	ngq->last = &(item->el_next);
1655}
1656
1657
1658/*
1659 * This function 'cheats' in that it first tries to 'grab' the use of the
1660 * node, without going through the mutex. We can do this becasue of the
1661 * semantics of the lock. The semantics include a clause that says that the
1662 * value of the readers count is invalid if the WRITER_ACTIVE flag is set. It
1663 * also says that the WRITER_ACTIVE flag cannot be set if the readers count
1664 * is not zero. Note that this talks about what is valid to SET the
1665 * WRITER_ACTIVE flag, because from the moment it is set, the value if the
1666 * reader count is immaterial, and not valid. The two 'pending' flags have a
1667 * similar effect, in that If they are orthogonal to the two active fields in
1668 * how they are set, but if either is set, the attempted 'grab' need to be
1669 * backed out because there is earlier work, and we maintain ordering in the
1670 * queue. The result of this is that the reader request can try obtain use of
1671 * the node with only a single atomic addition, and without any of the mutex
1672 * overhead. If this fails the operation degenerates to the same as for other
1673 * cases.
1674 *
1675 */
1676static __inline item_p
1677ng_acquire_read(struct ng_queue *ngq, item_p item)
1678{
1679
1680	/* ######### Hack alert ######### */
1681	atomic_add_long(&ngq->q_flags, READER_INCREMENT);
1682	if ((ngq->q_flags & (~READER_MASK)) == 0) {
1683		/* Successfully grabbed node */
1684		return (item);
1685	}
1686	/* undo the damage if we didn't succeed */
1687	atomic_subtract_long(&ngq->q_flags, READER_INCREMENT);
1688
1689	/* ######### End Hack alert ######### */
1690	mtx_enter((&ngq->q_mtx), MTX_SPIN);
1691	/*
1692	 * Try again. Another processor (or interrupt for that matter) may
1693	 * have removed the last queued item that was stopping us from
1694	 * running, between the previous test, and the moment that we took
1695	 * the mutex. (Or maybe a writer completed.)
1696	 */
1697	if ((ngq->q_flags & (~READER_MASK)) == 0) {
1698		atomic_add_long(&ngq->q_flags, READER_INCREMENT);
1699		mtx_exit((&ngq->q_mtx), MTX_SPIN);
1700		return (item);
1701	}
1702
1703	/*
1704	 * Quick check that we are doing things right.
1705	 */
1706	if (ngq->q_flags & SINGLE_THREAD_ONLY) {
1707		panic("Calling single treaded queue incorrectly");
1708	}
1709
1710	/*
1711	 * and queue the request for later.
1712	 */
1713	item->el_flags |= NGQF_TYPE;
1714	ng_queue_rw(ngq, item, NGQRW_R);
1715
1716	/*
1717	 * Ok, so that's the item successfully queued for later. So now we
1718	 * see if we can dequeue something to run instead.
1719	 */
1720	item = ng_dequeue(ngq);
1721	mtx_exit(&(ngq->q_mtx), MTX_SPIN);
1722	return (item);
1723}
1724
1725static __inline item_p
1726ng_acquire_write(struct ng_queue *ngq, item_p item)
1727{
1728restart:
1729	mtx_enter(&(ngq->q_mtx), MTX_SPIN);
1730	/*
1731	 * If there are no readers, no writer, and no pending packets, then
1732	 * we can just go ahead. In all other situations we need to queue the
1733	 * request
1734	 */
1735	if ((ngq->q_flags & (~SINGLE_THREAD_ONLY)) == 0) {
1736		atomic_add_long(&ngq->q_flags, WRITER_ACTIVE);
1737		mtx_exit((&ngq->q_mtx), MTX_SPIN);
1738		if (ngq->q_flags & READER_MASK) {
1739			/* Collision with fast-track reader */
1740			atomic_add_long(&ngq->q_flags, -WRITER_ACTIVE);
1741			goto restart;
1742		}
1743
1744		return (item);
1745	}
1746
1747	/*
1748	 * and queue the request for later.
1749	 */
1750	item->el_flags &= ~NGQF_TYPE;
1751	ng_queue_rw(ngq, item, NGQRW_W);
1752
1753	/*
1754	 * Ok, so that's the item successfully queued for later. So now we
1755	 * see if we can dequeue something to run instead.
1756	 */
1757	item = ng_dequeue(ngq);
1758	mtx_exit(&(ngq->q_mtx), MTX_SPIN);
1759	return (item);
1760}
1761
1762static __inline void
1763ng_leave_read(struct ng_queue *ngq)
1764{
1765	atomic_subtract_long(&ngq->q_flags, READER_INCREMENT);
1766}
1767
1768static __inline void
1769ng_leave_write(struct ng_queue *ngq)
1770{
1771	atomic_subtract_long(&ngq->q_flags, WRITER_ACTIVE);
1772}
1773
1774static void
1775ng_flush_input_queue(struct ng_queue * ngq)
1776{
1777	item_p item;
1778	u_int		add_arg;
1779	mtx_enter(&ngq->q_mtx, MTX_SPIN);
1780	for (;;) {
1781		/* Now take a look at what's on the queue */
1782		if (ngq->q_flags & READ_PENDING) {
1783			add_arg = -READ_PENDING;
1784		} else if (ngq->q_flags & WRITE_PENDING) {
1785			add_arg = -WRITE_PENDING;
1786		} else {
1787			break;
1788		}
1789
1790		item = ngq->queue;
1791		ngq->queue = item->el_next;
1792		if (ngq->last == &(item->el_next)) {
1793			ngq->last = &(ngq->queue);
1794		} else {
1795			if ((ngq->queue->el_flags & NGQF_TYPE) == NGQF_READER) {
1796				add_arg += READ_PENDING;
1797			} else {
1798				add_arg += WRITE_PENDING;
1799			}
1800		}
1801		atomic_add_long(&ngq->q_flags, add_arg);
1802
1803		mtx_exit(&ngq->q_mtx, MTX_SPIN);
1804		NG_FREE_ITEM(item);
1805		mtx_enter(&ngq->q_mtx, MTX_SPIN);
1806	}
1807	mtx_exit(&ngq->q_mtx, MTX_SPIN);
1808}
1809
1810/***********************************************************************
1811* Externally visible method for sending or queueing messages or data.
1812***********************************************************************/
1813
1814/*
1815 * MACRO WILL DO THE JOB OF CALLING ng_package_msg IN CALLER
1816 * before we are called. The user code should have filled out the item
1817 * correctly by this stage:
1818 * Common:
1819 *    reference to destination node.
1820 *    Reference to destination rcv hook if relevant.
1821 * Data:
1822 *    pointer to mbuf
1823 *    pointer to metadata
1824 * Control_Message:
1825 *    pointer to msg.
1826 *    ID of original sender node. (return address)
1827 *
1828 * The nodes have several routines and macros to help with this task:
1829 * ng_package_msg()
1830 * ng_package_data() do much of the work.
1831 * ng_retarget_msg
1832 * ng_retarget_data
1833 */
1834
1835int
1836ng_snd_item(item_p item, int queue)
1837{
1838	hook_p hook = item->el_hook;
1839	node_p dest = item->el_dest;
1840	int rw;
1841	int error = 0, ierror;
1842	item_p	oitem;
1843	struct ng_queue * ngq = &dest->nd_input_queue;
1844
1845#ifdef	NETGRAPH_DEBUG
1846        _ngi_check(item, __FILE__, __LINE__);
1847#endif
1848
1849	if (item == NULL) {
1850		TRAP_ERROR;
1851		return (EINVAL);	/* failed to get queue element */
1852	}
1853	if (dest == NULL) {
1854		NG_FREE_ITEM(item);
1855		TRAP_ERROR;
1856		return (EINVAL);	/* No address */
1857	}
1858	if ((item->el_flags & NGQF_D_M) == NGQF_DATA) {
1859		/*
1860		 * DATA MESSAGE
1861		 * Delivered to a node via a non-optional hook.
1862		 * Both should be present in the item even though
1863		 * the node is derivable from the hook.
1864		 * References are held on both by the item.
1865		 */
1866#ifdef	NETGRAPH_DEBUG
1867        _ngi_check(item, __FILE__, __LINE__);
1868#endif
1869		CHECK_DATA_MBUF(NGI_M(item));
1870		if (hook == NULL) {
1871			NG_FREE_ITEM(item);
1872			TRAP_ERROR;
1873			return(EINVAL);
1874		}
1875		if ((NG_HOOK_NOT_VALID(hook))
1876		|| (NG_NODE_NOT_VALID(NG_HOOK_NODE(hook)))) {
1877			NG_FREE_ITEM(item);
1878			return (ENOTCONN);
1879		}
1880		if ((hook->hk_flags & HK_QUEUE)) {
1881			queue = 1;
1882		}
1883		/* By default data is a reader in the locking scheme */
1884		item->el_flags |= NGQF_READER;
1885		rw = NGQRW_R;
1886	} else {
1887		/*
1888		 * CONTROL MESSAGE
1889		 * Delivered to a node.
1890		 * Hook is optional.
1891		 * References are held by the item on the node and
1892		 * the hook if it is present.
1893		 */
1894		if (hook && (hook->hk_flags & HK_QUEUE)) {
1895			queue = 1;
1896		}
1897		/* Data messages count as writers unles explicitly exempted */
1898		if (NGI_MSG(item)->header.cmd & NGM_READONLY) {
1899			item->el_flags |= NGQF_READER;
1900			rw = NGQRW_R;
1901		} else {
1902			item->el_flags &= ~NGQF_TYPE;
1903			rw = NGQRW_W;
1904		}
1905	}
1906	/*
1907	 * If the node specifies single threading, force writer semantics
1908	 * Similarly the node may say one hook always produces writers.
1909	 * These are over-rides.
1910	 */
1911	if ((ngq->q_flags & SINGLE_THREAD_ONLY)
1912	|| (dest->nd_flags & NG_FORCE_WRITER)
1913	|| (hook && (hook->hk_flags & HK_FORCE_WRITER))) {
1914			rw = NGQRW_W;
1915			item->el_flags &= ~NGQF_TYPE;
1916	}
1917	if (queue) {
1918		/* Put it on the queue for that node*/
1919#ifdef	NETGRAPH_DEBUG
1920        _ngi_check(item, __FILE__, __LINE__);
1921#endif
1922		mtx_enter(&(ngq->q_mtx), MTX_SPIN);
1923		ng_queue_rw(ngq, item, rw);
1924		mtx_exit(&(ngq->q_mtx), MTX_SPIN);
1925		/*
1926		 * If there are active elements then we can rely on
1927		 * them. if not we should not rely on another packet
1928		 * coming here by another path,
1929		 * so it is best to put us in the netisr list.
1930		 */
1931		if ((ngq->q_flags & (READER_MASK|WRITER_ACTIVE)) == 0) {
1932			ng_setisr(ngq->q_node);
1933		}
1934		return (0);
1935	}
1936	/*
1937	 * Take a queue item and a node and see if we can apply the item to
1938	 * the node. We may end up getting a different item to apply instead.
1939	 * Will allow for a piggyback reply only in the case where
1940	 * there is no queueing.
1941	 */
1942
1943	oitem = item;
1944	/*
1945	 * We already decided how we will be queueud or treated.
1946	 * Try get the appropriate operating permission.
1947	 */
1948 	if (rw == NGQRW_R) {
1949		item = ng_acquire_read(ngq, item);
1950	} else {
1951		item = ng_acquire_write(ngq, item);
1952	}
1953
1954	/*
1955	 * May have come back with a different item.
1956	 * or maybe none at all. The one we started with will
1957	 * have been queued in thises cases.
1958	 */
1959	if (item == NULL) {
1960		return (0);
1961	}
1962
1963#ifdef	NETGRAPH_DEBUG
1964        _ngi_check(item, __FILE__, __LINE__);
1965#endif
1966	ierror = ng_apply_item(dest, item); /* drops r/w lock when done */
1967
1968	/* only return an error if it was our initial item.. (compat hack) */
1969	if (oitem == item) {
1970		error = ierror;
1971	}
1972
1973	/*
1974	 * Now we've handled the packet we brought, (or a friend of it) let's
1975	 * look for any other packets that may have been queued up. We hold
1976	 * no locks, so if someone puts something in the queue after
1977	 * we check that it is empty, it is their problem
1978	 * to ensure it is processed. If we have the netisr thread cme in here
1979	 * while we still say we have stuff to do, we may get a boost
1980	 * in SMP systems. :-)
1981	 */
1982	for (;;) {
1983		/* quick hack to save all that mutex stuff */
1984		if ((ngq->q_flags & (WRITE_PENDING | READ_PENDING)) == 0) {
1985			if (dest->nd_flags & NG_WORKQ)
1986				ng_worklist_remove(dest);
1987			return (0);
1988		}
1989		/*
1990		 * dequeue acquires and adjusts the input_queue as it dequeues
1991		 * packets. It acquires the rw lock as needed.
1992		 */
1993		mtx_enter(&ngq->q_mtx, MTX_SPIN);
1994		item = ng_dequeue(ngq);
1995		mtx_exit(&ngq->q_mtx, MTX_SPIN);
1996		if (!item) {
1997			/*
1998			 * If we have no work to do
1999			 * then we certainly don't need to be
2000			 * on the worklist.
2001			 */
2002			if (dest->nd_flags & NG_WORKQ)
2003				ng_worklist_remove(dest);
2004			return (0);
2005		}
2006#ifdef	NETGRAPH_DEBUG
2007        _ngi_check(item, __FILE__, __LINE__);
2008#endif
2009
2010		/*
2011		 * We have the appropriate lock, so run the item.
2012		 * When finished it will drop the lock accordingly
2013		 */
2014
2015		ierror = ng_apply_item(dest, item);
2016		/*
2017		 * only return an error if it was our initial
2018		 * item.. (compat hack)
2019		 */
2020		if (oitem == item) {
2021			error = ierror;
2022		}
2023	}
2024	return (0);
2025}
2026
2027/*
2028 * We have an item that was possibly queued somewhere.
2029 * It should contain all the information needed
2030 * to run it on the appropriate node/hook.
2031 */
2032static int
2033ng_apply_item(node_p node, item_p item)
2034{
2035	hook_p  hook;
2036	int was_reader = ((item->el_flags & NGQF_TYPE));
2037	int error = 0;
2038	ng_rcvdata_t *rcvdata;
2039
2040	hook = item->el_hook;
2041	item->el_hook = NULL;	/* so NG_FREE_ITEM doesn't NG_HOOK_UNREF() */
2042	/* We already have the node.. assume responsibility */
2043	/* And the reference */
2044	/* node = item->el_dest; */
2045	item->el_dest = NULL;	/* same as for the hook above */
2046#ifdef	NETGRAPH_DEBUG
2047        _ngi_check(item, __FILE__, __LINE__);
2048#endif
2049
2050	switch (item->el_flags & NGQF_D_M) {
2051	case NGQF_DATA:
2052		/*
2053		 * Check things are still ok as when we were queued.
2054		 */
2055
2056		if ((hook == NULL)
2057		|| NG_HOOK_NOT_VALID(hook)
2058		|| NG_NODE_NOT_VALID(NG_HOOK_NODE(hook))
2059		|| ((rcvdata = NG_HOOK_NODE(hook)->nd_type->rcvdata) == NULL)) {
2060			error = EIO;
2061			NG_FREE_ITEM(item);
2062		} else {
2063			error = (*rcvdata)(hook, item);
2064		}
2065		break;
2066	case NGQF_MESG:
2067
2068		if (hook) {
2069			item->el_hook = NULL;
2070			if (NG_HOOK_NOT_VALID(hook)) {
2071			/*
2072			 * If the hook has been zapped then we can't use it.
2073			 * Immediatly drop its reference.
2074			 * The message may not need it.
2075			 */
2076				NG_HOOK_UNREF(hook);
2077				hook = NULL;
2078			}
2079		}
2080		/*
2081		 * Similarly, if the node is a zombie there is
2082		 * nothing we can do with it, drop everything.
2083		 */
2084		if (NG_NODE_NOT_VALID(node)) {
2085			TRAP_ERROR;
2086			error = EINVAL;
2087			NG_FREE_ITEM(item);
2088		} else {
2089			/*
2090			 * Call the appropriate message handler for the object.
2091			 * It is up to the message handler to free the message.
2092			 * If it's a generic message, handle it generically,
2093			 * otherwise call the type's message handler
2094			 * (if it exists)
2095			 * XXX (race). Remember that a queued message may
2096			 * reference a node or hook that has just been
2097			 * invalidated. It will exist as the queue code
2098			 * is holding a reference, but..
2099			 */
2100
2101			struct ng_mesg *msg = NGI_MSG(item);
2102
2103			if ((msg->header.typecookie == NGM_GENERIC_COOKIE)
2104			&& ((msg->header.flags & NGF_RESP) == 0)) {
2105				error = ng_generic_msg(node, item, hook);
2106			} else {
2107				if ((node)->nd_type->rcvmsg != NULL) {
2108					error = (*(node)->nd_type->rcvmsg)((node),
2109						(item), (hook));
2110				} else {
2111					TRAP_ERROR;
2112					error = EINVAL; /* XXX */
2113					NG_FREE_ITEM(item);
2114				}
2115			}
2116			/* item is now invalid */
2117		}
2118		break;
2119	}
2120	/*
2121	 * We held references on some of the resources
2122	 * that we took from the item. Now that we have
2123	 * finished doing everything, drop those references.
2124	 */
2125	if (hook) {
2126		NG_HOOK_UNREF(hook);
2127	}
2128
2129	if (was_reader) {
2130		ng_leave_read(&node->nd_input_queue);
2131	} else {
2132		ng_leave_write(&node->nd_input_queue);
2133	}
2134	NG_NODE_UNREF(node);
2135	return (error);
2136}
2137
2138/***********************************************************************
2139 * Implement the 'generic' control messages
2140 ***********************************************************************/
2141static int
2142ng_generic_msg(node_p here, item_p item, hook_p lasthook)
2143{
2144	int error = 0;
2145	struct ng_mesg *msg;
2146	struct ng_mesg *resp = NULL;
2147
2148	NGI_GET_MSG(item, msg);
2149	if (msg->header.typecookie != NGM_GENERIC_COOKIE) {
2150		TRAP_ERROR
2151		error = EINVAL;
2152		goto out;
2153	}
2154	switch (msg->header.cmd) {
2155	case NGM_SHUTDOWN:
2156		ng_rmnode(here);
2157		break;
2158	case NGM_MKPEER:
2159	    {
2160		struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data;
2161
2162		if (msg->header.arglen != sizeof(*mkp)) {
2163			TRAP_ERROR
2164			error = EINVAL;
2165			break;
2166		}
2167		mkp->type[sizeof(mkp->type) - 1] = '\0';
2168		mkp->ourhook[sizeof(mkp->ourhook) - 1] = '\0';
2169		mkp->peerhook[sizeof(mkp->peerhook) - 1] = '\0';
2170		error = ng_mkpeer(here, mkp->ourhook, mkp->peerhook, mkp->type);
2171		break;
2172	    }
2173	case NGM_CONNECT:
2174	    {
2175		struct ngm_connect *const con =
2176			(struct ngm_connect *) msg->data;
2177		node_p node2;
2178
2179		if (msg->header.arglen != sizeof(*con)) {
2180			TRAP_ERROR
2181			error = EINVAL;
2182			break;
2183		}
2184		con->path[sizeof(con->path) - 1] = '\0';
2185		con->ourhook[sizeof(con->ourhook) - 1] = '\0';
2186		con->peerhook[sizeof(con->peerhook) - 1] = '\0';
2187		/* Don't forget we get a reference.. */
2188		error = ng_path2noderef(here, con->path, &node2, NULL);
2189		if (error)
2190			break;
2191		error = ng_con_nodes(here, con->ourhook, node2, con->peerhook);
2192		NG_NODE_UNREF(node2);
2193		break;
2194	    }
2195	case NGM_NAME:
2196	    {
2197		struct ngm_name *const nam = (struct ngm_name *) msg->data;
2198
2199		if (msg->header.arglen != sizeof(*nam)) {
2200			TRAP_ERROR
2201			error = EINVAL;
2202			break;
2203		}
2204		nam->name[sizeof(nam->name) - 1] = '\0';
2205		error = ng_name_node(here, nam->name);
2206		break;
2207	    }
2208	case NGM_RMHOOK:
2209	    {
2210		struct ngm_rmhook *const rmh = (struct ngm_rmhook *) msg->data;
2211		hook_p hook;
2212
2213		if (msg->header.arglen != sizeof(*rmh)) {
2214			TRAP_ERROR
2215			error = EINVAL;
2216			break;
2217		}
2218		rmh->ourhook[sizeof(rmh->ourhook) - 1] = '\0';
2219		if ((hook = ng_findhook(here, rmh->ourhook)) != NULL)
2220			ng_destroy_hook(hook);
2221		break;
2222	    }
2223	case NGM_NODEINFO:
2224	    {
2225		struct nodeinfo *ni;
2226
2227		NG_MKRESPONSE(resp, msg, sizeof(*ni), M_NOWAIT);
2228		if (resp == NULL) {
2229			error = ENOMEM;
2230			break;
2231		}
2232
2233		/* Fill in node info */
2234		ni = (struct nodeinfo *) resp->data;
2235		if (NG_NODE_HAS_NAME(here))
2236			strncpy(ni->name, NG_NODE_NAME(here), NG_NODELEN);
2237		strncpy(ni->type, here->nd_type->name, NG_TYPELEN);
2238		ni->id = ng_node2ID(here);
2239		ni->hooks = here->nd_numhooks;
2240		break;
2241	    }
2242	case NGM_LISTHOOKS:
2243	    {
2244		const int nhooks = here->nd_numhooks;
2245		struct hooklist *hl;
2246		struct nodeinfo *ni;
2247		hook_p hook;
2248
2249		/* Get response struct */
2250		NG_MKRESPONSE(resp, msg, sizeof(*hl)
2251		    + (nhooks * sizeof(struct linkinfo)), M_NOWAIT);
2252		if (resp == NULL) {
2253			error = ENOMEM;
2254			break;
2255		}
2256		hl = (struct hooklist *) resp->data;
2257		ni = &hl->nodeinfo;
2258
2259		/* Fill in node info */
2260		if (NG_NODE_HAS_NAME(here))
2261			strncpy(ni->name, NG_NODE_NAME(here), NG_NODELEN);
2262		strncpy(ni->type, here->nd_type->name, NG_TYPELEN);
2263		ni->id = ng_node2ID(here);
2264
2265		/* Cycle through the linked list of hooks */
2266		ni->hooks = 0;
2267		LIST_FOREACH(hook, &here->nd_hooks, hk_hooks) {
2268			struct linkinfo *const link = &hl->link[ni->hooks];
2269
2270			if (ni->hooks >= nhooks) {
2271				log(LOG_ERR, "%s: number of %s changed\n",
2272				    __FUNCTION__, "hooks");
2273				break;
2274			}
2275			if (NG_HOOK_NOT_VALID(hook))
2276				continue;
2277			strncpy(link->ourhook, NG_HOOK_NAME(hook), NG_HOOKLEN);
2278			strncpy(link->peerhook,
2279				NG_PEER_HOOK_NAME(hook), NG_HOOKLEN);
2280			if (NG_PEER_NODE_NAME(hook)[0] != '\0')
2281				strncpy(link->nodeinfo.name,
2282				    NG_PEER_NODE_NAME(hook), NG_NODELEN);
2283			strncpy(link->nodeinfo.type,
2284			   NG_PEER_NODE(hook)->nd_type->name, NG_TYPELEN);
2285			link->nodeinfo.id = ng_node2ID(NG_PEER_NODE(hook));
2286			link->nodeinfo.hooks = NG_PEER_NODE(hook)->nd_numhooks;
2287			ni->hooks++;
2288		}
2289		break;
2290	    }
2291
2292	case NGM_LISTNAMES:
2293	case NGM_LISTNODES:
2294	    {
2295		const int unnamed = (msg->header.cmd == NGM_LISTNODES);
2296		struct namelist *nl;
2297		node_p node;
2298		int num = 0;
2299
2300		mtx_enter(&ng_nodelist_mtx, MTX_DEF);
2301		/* Count number of nodes */
2302		LIST_FOREACH(node, &ng_nodelist, nd_nodes) {
2303			if (unnamed || NG_NODE_HAS_NAME(node))
2304				num++;
2305		}
2306		mtx_exit(&ng_nodelist_mtx, MTX_DEF);
2307
2308		/* Get response struct */
2309		NG_MKRESPONSE(resp, msg, sizeof(*nl)
2310		    + (num * sizeof(struct nodeinfo)), M_NOWAIT);
2311		if (resp == NULL) {
2312			error = ENOMEM;
2313			break;
2314		}
2315		nl = (struct namelist *) resp->data;
2316
2317		/* Cycle through the linked list of nodes */
2318		nl->numnames = 0;
2319		mtx_enter(&ng_nodelist_mtx, MTX_DEF);
2320		LIST_FOREACH(node, &ng_nodelist, nd_nodes) {
2321			struct nodeinfo *const np = &nl->nodeinfo[nl->numnames];
2322
2323			if (nl->numnames >= num) {
2324				log(LOG_ERR, "%s: number of %s changed\n",
2325				    __FUNCTION__, "nodes");
2326				break;
2327			}
2328			if (NG_NODE_NOT_VALID(node))
2329				continue;
2330			if (!unnamed && (! NG_NODE_HAS_NAME(node)))
2331				continue;
2332			if (NG_NODE_HAS_NAME(node))
2333				strncpy(np->name, NG_NODE_NAME(node), NG_NODELEN);
2334			strncpy(np->type, node->nd_type->name, NG_TYPELEN);
2335			np->id = ng_node2ID(node);
2336			np->hooks = node->nd_numhooks;
2337			nl->numnames++;
2338		}
2339		mtx_exit(&ng_nodelist_mtx, MTX_DEF);
2340		break;
2341	    }
2342
2343	case NGM_LISTTYPES:
2344	    {
2345		struct typelist *tl;
2346		struct ng_type *type;
2347		int num = 0;
2348
2349		mtx_enter(&ng_typelist_mtx, MTX_DEF);
2350		/* Count number of types */
2351		LIST_FOREACH(type, &ng_typelist, types)
2352			num++;
2353		mtx_exit(&ng_typelist_mtx, MTX_DEF);
2354
2355		/* Get response struct */
2356		NG_MKRESPONSE(resp, msg, sizeof(*tl)
2357		    + (num * sizeof(struct typeinfo)), M_NOWAIT);
2358		if (resp == NULL) {
2359			error = ENOMEM;
2360			break;
2361		}
2362		tl = (struct typelist *) resp->data;
2363
2364		/* Cycle through the linked list of types */
2365		tl->numtypes = 0;
2366		mtx_enter(&ng_typelist_mtx, MTX_DEF);
2367		LIST_FOREACH(type, &ng_typelist, types) {
2368			struct typeinfo *const tp = &tl->typeinfo[tl->numtypes];
2369
2370			if (tl->numtypes >= num) {
2371				log(LOG_ERR, "%s: number of %s changed\n",
2372				    __FUNCTION__, "types");
2373				break;
2374			}
2375			strncpy(tp->type_name, type->name, NG_TYPELEN);
2376			tp->numnodes = type->refs;
2377			tl->numtypes++;
2378		}
2379		mtx_exit(&ng_typelist_mtx, MTX_DEF);
2380		break;
2381	    }
2382
2383	case NGM_BINARY2ASCII:
2384	    {
2385		int bufSize = 20 * 1024;	/* XXX hard coded constant */
2386		const struct ng_parse_type *argstype;
2387		const struct ng_cmdlist *c;
2388		struct ng_mesg *binary, *ascii;
2389
2390		/* Data area must contain a valid netgraph message */
2391		binary = (struct ng_mesg *)msg->data;
2392		if (msg->header.arglen < sizeof(struct ng_mesg)
2393		    || msg->header.arglen - sizeof(struct ng_mesg)
2394		      < binary->header.arglen) {
2395			TRAP_ERROR
2396			error = EINVAL;
2397			break;
2398		}
2399
2400		/* Get a response message with lots of room */
2401		NG_MKRESPONSE(resp, msg, sizeof(*ascii) + bufSize, M_NOWAIT);
2402		if (resp == NULL) {
2403			error = ENOMEM;
2404			break;
2405		}
2406		ascii = (struct ng_mesg *)resp->data;
2407
2408		/* Copy binary message header to response message payload */
2409		bcopy(binary, ascii, sizeof(*binary));
2410
2411		/* Find command by matching typecookie and command number */
2412		for (c = here->nd_type->cmdlist;
2413		    c != NULL && c->name != NULL; c++) {
2414			if (binary->header.typecookie == c->cookie
2415			    && binary->header.cmd == c->cmd)
2416				break;
2417		}
2418		if (c == NULL || c->name == NULL) {
2419			for (c = ng_generic_cmds; c->name != NULL; c++) {
2420				if (binary->header.typecookie == c->cookie
2421				    && binary->header.cmd == c->cmd)
2422					break;
2423			}
2424			if (c->name == NULL) {
2425				NG_FREE_MSG(resp);
2426				error = ENOSYS;
2427				break;
2428			}
2429		}
2430
2431		/* Convert command name to ASCII */
2432		snprintf(ascii->header.cmdstr, sizeof(ascii->header.cmdstr),
2433		    "%s", c->name);
2434
2435		/* Convert command arguments to ASCII */
2436		argstype = (binary->header.flags & NGF_RESP) ?
2437		    c->respType : c->mesgType;
2438		if (argstype == NULL)
2439			*ascii->data = '\0';
2440		else {
2441			if ((error = ng_unparse(argstype,
2442			    (u_char *)binary->data,
2443			    ascii->data, bufSize)) != 0) {
2444				NG_FREE_MSG(resp);
2445				break;
2446			}
2447		}
2448
2449		/* Return the result as struct ng_mesg plus ASCII string */
2450		bufSize = strlen(ascii->data) + 1;
2451		ascii->header.arglen = bufSize;
2452		resp->header.arglen = sizeof(*ascii) + bufSize;
2453		break;
2454	    }
2455
2456	case NGM_ASCII2BINARY:
2457	    {
2458		int bufSize = 2000;	/* XXX hard coded constant */
2459		const struct ng_cmdlist *c;
2460		const struct ng_parse_type *argstype;
2461		struct ng_mesg *ascii, *binary;
2462		int off = 0;
2463
2464		/* Data area must contain at least a struct ng_mesg + '\0' */
2465		ascii = (struct ng_mesg *)msg->data;
2466		if (msg->header.arglen < sizeof(*ascii) + 1
2467		    || ascii->header.arglen < 1
2468		    || msg->header.arglen
2469		      < sizeof(*ascii) + ascii->header.arglen) {
2470			TRAP_ERROR
2471			error = EINVAL;
2472			break;
2473		}
2474		ascii->data[ascii->header.arglen - 1] = '\0';
2475
2476		/* Get a response message with lots of room */
2477		NG_MKRESPONSE(resp, msg, sizeof(*binary) + bufSize, M_NOWAIT);
2478		if (resp == NULL) {
2479			error = ENOMEM;
2480			break;
2481		}
2482		binary = (struct ng_mesg *)resp->data;
2483
2484		/* Copy ASCII message header to response message payload */
2485		bcopy(ascii, binary, sizeof(*ascii));
2486
2487		/* Find command by matching ASCII command string */
2488		for (c = here->nd_type->cmdlist;
2489		    c != NULL && c->name != NULL; c++) {
2490			if (strcmp(ascii->header.cmdstr, c->name) == 0)
2491				break;
2492		}
2493		if (c == NULL || c->name == NULL) {
2494			for (c = ng_generic_cmds; c->name != NULL; c++) {
2495				if (strcmp(ascii->header.cmdstr, c->name) == 0)
2496					break;
2497			}
2498			if (c->name == NULL) {
2499				NG_FREE_MSG(resp);
2500				error = ENOSYS;
2501				break;
2502			}
2503		}
2504
2505		/* Convert command name to binary */
2506		binary->header.cmd = c->cmd;
2507		binary->header.typecookie = c->cookie;
2508
2509		/* Convert command arguments to binary */
2510		argstype = (binary->header.flags & NGF_RESP) ?
2511		    c->respType : c->mesgType;
2512		if (argstype == NULL)
2513			bufSize = 0;
2514		else {
2515			if ((error = ng_parse(argstype, ascii->data,
2516			    &off, (u_char *)binary->data, &bufSize)) != 0) {
2517				NG_FREE_MSG(resp);
2518				break;
2519			}
2520		}
2521
2522		/* Return the result */
2523		binary->header.arglen = bufSize;
2524		resp->header.arglen = sizeof(*binary) + bufSize;
2525		break;
2526	    }
2527
2528	case NGM_TEXT_CONFIG:
2529	case NGM_TEXT_STATUS:
2530		/*
2531		 * This one is tricky as it passes the command down to the
2532		 * actual node, even though it is a generic type command.
2533		 * This means we must assume that the item/msg is already freed
2534		 * when control passes back to us.
2535		 */
2536		if (here->nd_type->rcvmsg != NULL) {
2537			NGI_MSG(item) = msg; /* put it back as we found it */
2538			return((*here->nd_type->rcvmsg)(here, item, lasthook));
2539		}
2540		/* Fall through if rcvmsg not supported */
2541	default:
2542		TRAP_ERROR;
2543		error = EINVAL;
2544	}
2545	/*
2546	 * Sometimes a generic message may be statically allocated
2547	 * to avoid problems with allocating when in tight memeory situations.
2548	 * Don't free it if it is so.
2549	 * I break them appart here, because erros may cause a free if the item
2550	 * in which case we'd be doing it twice.
2551	 * they are kept together above, to simplify freeing.
2552	 */
2553out:
2554	NG_RESPOND_MSG(error, here, item, resp);
2555	if ( msg && ((msg->header.flags & NGF_STATIC) == 0))
2556		NG_FREE_MSG(msg);
2557	return (error);
2558}
2559
2560/*
2561 * Copy a 'meta'.
2562 *
2563 * Returns new meta, or NULL if original meta is NULL or ENOMEM.
2564 */
2565meta_p
2566ng_copy_meta(meta_p meta)
2567{
2568	meta_p meta2;
2569
2570	if (meta == NULL)
2571		return (NULL);
2572	MALLOC(meta2, meta_p, meta->used_len, M_NETGRAPH_META, M_NOWAIT);
2573	if (meta2 == NULL)
2574		return (NULL);
2575	meta2->allocated_len = meta->used_len;
2576	bcopy(meta, meta2, meta->used_len);
2577	return (meta2);
2578}
2579
2580/************************************************************************
2581			Module routines
2582************************************************************************/
2583
2584/*
2585 * Handle the loading/unloading of a netgraph node type module
2586 */
2587int
2588ng_mod_event(module_t mod, int event, void *data)
2589{
2590	struct ng_type *const type = data;
2591	int s, error = 0;
2592
2593	switch (event) {
2594	case MOD_LOAD:
2595
2596		/* Register new netgraph node type */
2597		s = splnet();
2598		if ((error = ng_newtype(type)) != 0) {
2599			splx(s);
2600			break;
2601		}
2602
2603		/* Call type specific code */
2604		if (type->mod_event != NULL)
2605			if ((error = (*type->mod_event)(mod, event, data))) {
2606				mtx_enter(&ng_typelist_mtx, MTX_DEF);
2607				LIST_REMOVE(type, types);
2608				mtx_exit(&ng_typelist_mtx, MTX_DEF);
2609			}
2610		splx(s);
2611		break;
2612
2613	case MOD_UNLOAD:
2614		s = splnet();
2615		if (type->refs != 0)		/* make sure no nodes exist! */
2616			error = EBUSY;
2617		else {
2618			if (type->mod_event != NULL) {	/* check with type */
2619				error = (*type->mod_event)(mod, event, data);
2620				if (error != 0) {	/* type refuses.. */
2621					splx(s);
2622					break;
2623				}
2624			}
2625			mtx_enter(&ng_typelist_mtx, MTX_DEF);
2626			LIST_REMOVE(type, types);
2627			mtx_exit(&ng_typelist_mtx, MTX_DEF);
2628		}
2629		splx(s);
2630		break;
2631
2632	default:
2633		if (type->mod_event != NULL)
2634			error = (*type->mod_event)(mod, event, data);
2635		else
2636			error = 0;		/* XXX ? */
2637		break;
2638	}
2639	return (error);
2640}
2641
2642/*
2643 * Handle loading and unloading for this code.
2644 * The only thing we need to link into is the NETISR strucure.
2645 */
2646static int
2647ngb_mod_event(module_t mod, int event, void *data)
2648{
2649	int s, error = 0;
2650
2651	switch (event) {
2652	case MOD_LOAD:
2653		/* Register line discipline */
2654		mtx_init(&ng_worklist_mtx, "netgraph worklist mutex", 0);
2655		mtx_init(&ng_typelist_mtx, "netgraph types mutex", 0);
2656		mtx_init(&ng_nodelist_mtx, "netgraph nodelist mutex", 0);
2657		mtx_init(&ng_idhash_mtx, "netgraph idhash mutex", 0);
2658		mtx_init(&ngq_mtx, "netgraph netisr mutex", 0);
2659		s = splimp();
2660		error = register_netisr(NETISR_NETGRAPH, ngintr);
2661		splx(s);
2662		break;
2663	case MOD_UNLOAD:
2664		/* You cant unload it because an interface may be using it.  */
2665		error = EBUSY;
2666		break;
2667	default:
2668		error = EOPNOTSUPP;
2669		break;
2670	}
2671	return (error);
2672}
2673
2674static moduledata_t netgraph_mod = {
2675	"netgraph",
2676	ngb_mod_event,
2677	(NULL)
2678};
2679DECLARE_MODULE(netgraph, netgraph_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
2680
2681/************************************************************************
2682			Queue element get/free routines
2683************************************************************************/
2684
2685
2686static int			allocated;	/* number of items malloc'd */
2687static int			maxalloc = 128;	/* limit the damage of a leak */
2688static const int		ngqfreemax = 64;/* cache at most this many */
2689static const int		ngqfreelow = 4; /* try malloc if free < this */
2690static volatile int		ngqfreesize;	/* number of cached entries */
2691#ifdef	NETGRAPH_DEBUG
2692static TAILQ_HEAD(, ng_item) ng_itemlist = TAILQ_HEAD_INITIALIZER(ng_itemlist);
2693#endif
2694/*
2695 * Get a queue entry
2696 * This is usually called when a packet first enters netgraph.
2697 * By definition, this is usually from an interrupt, or from a user.
2698 * Users are not so important, but try be quick for the times that it's
2699 * an interrupt. Use atomic operations to cope with collisions
2700 * with interrupts and other processors. Assumes MALLOC is SMP safe.
2701 * XXX If reserve is low, we should try to get 2 from malloc as this
2702 * would indicate it often fails.
2703 */
2704static item_p
2705ng_getqblk(void)
2706{
2707	item_p item = NULL;
2708
2709	/*
2710	 * Try get a cached queue block, or else allocate a new one
2711	 * If we are less than our reserve, try malloc. If malloc
2712	 * fails, then that's what the reserve is for...
2713	 * Don't completely trust ngqfreesize, as it is subject
2714	 * to races.. (it'll eventually catch up but may be out by one or two
2715	 * for brief moments(under SMP or interrupts).
2716	 * ngqfree is the final arbiter. We have our little reserve
2717	 * because we use M_NOWAIT for malloc. This just helps us
2718	 * avoid dropping packets while not increasing the time
2719	 * we take to service the interrupt (on average) (we hope).
2720	 */
2721	for (;;) {
2722		if ((ngqfreesize < ngqfreelow) || (ngqfree == NULL)) {
2723			if (allocated < maxalloc) {  /* don't leak forever */
2724				MALLOC(item, item_p ,
2725				    sizeof(*item), M_NETGRAPH_ITEM,
2726				    (M_NOWAIT | M_ZERO));
2727				if (item) {
2728#ifdef	NETGRAPH_DEBUG
2729					TAILQ_INSERT_TAIL(&ng_itemlist,
2730								item, all);
2731#endif	/* NETGRAPH_DEBUG */
2732					atomic_add_int(&allocated, 1);
2733					break;
2734				}
2735			}
2736		}
2737
2738		/*
2739		 * We didn't or couldn't malloc.
2740		 * try get one from our cache.
2741		 * item must be NULL to get here.
2742		 */
2743		if ((item = ngqfree) != NULL) {
2744			/*
2745			 * Atomically try grab the first item
2746			 * and put it's successor in its place.
2747			 * If we fail, just try again.. someone else
2748			 * beat us to this one or freed one.
2749			 * Don't worry about races with ngqfreesize.
2750			 * Close enough is good enough..
2751			 */
2752			if (atomic_cmpset_ptr(&ngqfree, item, item->el_next)) {
2753				atomic_subtract_int(&ngqfreesize, 1);
2754				break;
2755			}
2756			item = NULL;
2757		} else {
2758			/* We really ran out */
2759			break;
2760		}
2761	}
2762	item->el_flags &= ~NGQF_FREE;
2763	return (item);
2764}
2765
2766/*
2767 * Release a queue entry
2768 */
2769void
2770ng_free_item(item_p item)
2771{
2772
2773	/*
2774	 * The item may hold resources on it's own. We need to free
2775	 * these before we can free the item. What they are depends upon
2776	 * what kind of item it is. it is important that nodes zero
2777	 * out pointers to resources that they remove from the item
2778	 * or we release them again here.
2779	 */
2780	if (item->el_flags & NGQF_FREE) {
2781		panic(" Freeing free queue item");
2782	}
2783	switch (item->el_flags & NGQF_D_M) {
2784	case NGQF_DATA:
2785		/* If we have an mbuf and metadata still attached.. */
2786		NG_FREE_M(_NGI_M(item));
2787		NG_FREE_META(_NGI_META(item));
2788		break;
2789	case NGQF_MESG:
2790		_NGI_RETADDR(item) = NULL;
2791		NG_FREE_MSG(_NGI_MSG(item));
2792		break;
2793	}
2794		/* If we still have a node or hook referenced... */
2795	if (item->el_dest) {
2796		NG_NODE_UNREF(item->el_dest);
2797		item->el_dest = NULL;
2798	}
2799	if (item->el_hook) {
2800		NG_HOOK_UNREF(item->el_hook);
2801		item->el_hook = NULL;
2802	}
2803	item->el_flags |= NGQF_FREE;
2804
2805	/*
2806	 * We have freed any resources held by the item.
2807	 * now we can free the item itself.
2808	 */
2809	if (ngqfreesize < ngqfreemax) { /* don't worry about races */
2810		for (;;) {
2811			item->el_next = ngqfree;
2812			if (atomic_cmpset_ptr(&ngqfree, item->el_next, item)) {
2813				break;
2814			}
2815		}
2816		atomic_add_int(&ngqfreesize, 1);
2817	} else {
2818		/* This is the only place that should use this Macro */
2819#ifdef	NETGRAPH_DEBUG
2820		TAILQ_REMOVE(&ng_itemlist, item, all);
2821#endif	/* NETGRAPH_DEBUG */
2822		NG_FREE_ITEM_REAL(item);
2823		atomic_subtract_int(&allocated, 1);
2824	}
2825}
2826
2827#ifdef	NETGRAPH_DEBUG
2828void
2829dumphook (hook_p hook, char *file, int line)
2830{
2831	printf("hook: name %s, %d refs, Last touched:\n",
2832		_NG_HOOK_NAME(hook), hook->hk_refs);
2833	printf("	Last active @ %s, line %d\n",
2834		hook->lastfile, hook->lastline);
2835	if (line) {
2836		printf(" problem discovered at file %s, line %d\n", file, line);
2837	}
2838}
2839
2840void
2841dumpnode(node_p node, char *file, int line)
2842{
2843	printf("node: ID [%x]: type '%s', %d hooks, flags 0x%x, %d refs, %s:\n",
2844		ng_node2ID(node), node->nd_type->name,
2845		node->nd_numhooks, node->nd_flags,
2846		node->nd_refs, node->nd_name);
2847	printf("	Last active @ %s, line %d\n",
2848		node->lastfile, node->lastline);
2849	if (line) {
2850		printf(" problem discovered at file %s, line %d\n", file, line);
2851	}
2852}
2853
2854void
2855dumpitem(item_p item, char *file, int line)
2856{
2857	if (item->el_flags & NGQF_FREE) {
2858		printf(" Free item, freed at %s, line %d\n",
2859			item->lastfile, item->lastline);
2860	} else {
2861		printf(" ACTIVE item, last used at %s, line %d",
2862			item->lastfile, item->lastline);
2863		if ((item->el_flags & NGQF_D_M) == NGQF_MESG) {
2864			printf(" - retaddr[%d]:\n", _NGI_RETADDR(item));
2865		} else {
2866			printf(" - [data]\n");
2867		}
2868	}
2869	if (line) {
2870		printf(" problem discovered at file %s, line %d\n", file, line);
2871		if (item->el_dest) {
2872			printf("node %p ([%x])\n",
2873				item->el_dest, ng_node2ID(item->el_dest));
2874		}
2875	}
2876}
2877
2878static void
2879ng_dumpitems(void)
2880{
2881	item_p item;
2882	int i = 1;
2883	TAILQ_FOREACH(item, &ng_itemlist, all) {
2884		printf("[%d] ", i++);
2885		dumpitem(item, NULL, 0);
2886	}
2887}
2888
2889static void
2890ng_dumpnodes(void)
2891{
2892	node_p node;
2893	int i = 1;
2894	SLIST_FOREACH(node, &ng_allnodes, nd_all) {
2895		printf("[%d] ", i++);
2896		dumpnode(node, NULL, 0);
2897	}
2898}
2899
2900static void
2901ng_dumphooks(void)
2902{
2903	hook_p hook;
2904	int i = 1;
2905	SLIST_FOREACH(hook, &ng_allhooks, hk_all) {
2906		printf("[%d] ", i++);
2907		dumphook(hook, NULL, 0);
2908	}
2909}
2910
2911static int
2912sysctl_debug_ng_dump_items(SYSCTL_HANDLER_ARGS)
2913{
2914	static int count;
2915	int error;
2916	int val;
2917	int i;
2918
2919	val = allocated;
2920	i = 1;
2921	error = sysctl_handle_int(oidp, &val, sizeof(int), req);
2922	if(count++  & 1) { /* for some reason sysctl calls it twice */
2923		ng_dumpitems();
2924		ng_dumpnodes();
2925		ng_dumphooks();
2926	}
2927	return error;
2928}
2929
2930SYSCTL_PROC(_debug, OID_AUTO, ng_dump_items, CTLTYPE_INT | CTLFLAG_RD,
2931    0, 0, sysctl_debug_ng_dump_items, "I", "Number of allocated items");
2932#endif	/* NETGRAPH_DEBUG */
2933
2934
2935/***********************************************************************
2936* Worklist routines
2937**********************************************************************/
2938/* NETISR thread enters here */
2939/*
2940 * Pick a node off the list of nodes with work,
2941 * try get an item to process off it.
2942 * If there are no more, remove the node from the list.
2943 */
2944static void
2945ngintr(void)
2946{
2947	item_p item;
2948	node_p  node = NULL;
2949
2950	for (;;) {
2951		mtx_enter(&ng_worklist_mtx, MTX_SPIN);
2952		node = TAILQ_FIRST(&ng_worklist);
2953		if (!node) {
2954			mtx_exit(&ng_worklist_mtx, MTX_SPIN);
2955			break;
2956		}
2957		TAILQ_REMOVE(&ng_worklist, node, nd_work);
2958		mtx_exit(&ng_worklist_mtx, MTX_SPIN);
2959		/*
2960		 * We have the node. We also take over the reference
2961		 * that the list had on it.
2962		 * Now process as much as you can, until it won't
2963		 * let you have another item off the queue.
2964		 * All this time, keep the reference
2965		 * that lets us be sure that the node still exists.
2966		 * Let the reference go at the last minute.
2967		 */
2968		for (;;) {
2969			mtx_enter(&node->nd_input_queue.q_mtx, MTX_SPIN);
2970			item = ng_dequeue(&node->nd_input_queue);
2971			if (item == NULL) {
2972				/*
2973				 * Say we are on the queue as long as
2974				 * we are processing it here.
2975				 * it probably wouldn't come here while we
2976				 * are processing anyhow.
2977				 */
2978				node->nd_flags &= ~NG_WORKQ;
2979				mtx_exit(&node->nd_input_queue.q_mtx, MTX_SPIN);
2980				NG_NODE_UNREF(node);
2981				break; /* go look for another node */
2982			} else {
2983				mtx_exit(&node->nd_input_queue.q_mtx, MTX_SPIN);
2984#ifdef	NETGRAPH_DEBUG
2985        _ngi_check(item, __FILE__, __LINE__);
2986#endif
2987				ng_apply_item(node, item);
2988			}
2989		}
2990	}
2991}
2992
2993static void
2994ng_worklist_remove(node_p node)
2995{
2996	mtx_enter(&ng_worklist_mtx, MTX_SPIN);
2997	if (node->nd_flags & NG_WORKQ) {
2998		TAILQ_REMOVE(&ng_worklist, node, nd_work);
2999		NG_NODE_UNREF(node);
3000	}
3001	node->nd_flags &= ~NG_WORKQ;
3002	mtx_exit(&ng_worklist_mtx, MTX_SPIN);
3003}
3004
3005static void
3006ng_setisr(node_p node)
3007{
3008	mtx_enter(&ng_worklist_mtx, MTX_SPIN);
3009	if ((node->nd_flags & NG_WORKQ) == 0) {
3010		/*
3011		 * If we are not already on the work queue,
3012		 * then put us on.
3013		 */
3014		node->nd_flags |= NG_WORKQ;
3015		TAILQ_INSERT_TAIL(&ng_worklist, node, nd_work);
3016		NG_NODE_REF(node);
3017	}
3018	mtx_exit(&ng_worklist_mtx, MTX_SPIN);
3019	schednetisr(NETISR_NETGRAPH);
3020}
3021
3022
3023/***********************************************************************
3024* Externally useable functions to set up a queue item ready for sending
3025***********************************************************************/
3026
3027#ifdef	NETGRAPH_DEBUG
3028#define	ITEM_DEBUG_CHECKS						\
3029	do {								\
3030		if (item->el_dest ) {					\
3031			printf("item already has node");		\
3032			Debugger("has node");				\
3033			NG_NODE_UNREF(item->el_dest);			\
3034			item->el_dest = NULL;				\
3035		}							\
3036		if (item->el_hook ) {					\
3037			printf("item already has hook");		\
3038			Debugger("has hook");				\
3039			NG_HOOK_UNREF(item->el_hook);			\
3040			item->el_hook = NULL;				\
3041		}							\
3042	} while (0)
3043#else
3044#define ITEM_DEBUG_CHECKS
3045#endif
3046
3047/*
3048 * Put elements into the item.
3049 * Hook and node references will be removed when the item is dequeued.
3050 * (or equivalent)
3051 * (XXX) Unsafe because no reference held by peer on remote node.
3052 * remote node might go away in this timescale.
3053 * We know the hooks can't go away because that would require getting
3054 * a writer item on both nodes and we must have at least a  reader
3055 * here to eb able to do this.
3056 * Note that the hook loaded is the REMOTE hook.
3057 *
3058 * This is possibly in the critical path for new data.
3059 */
3060item_p
3061ng_package_data(struct mbuf *m, meta_p meta)
3062{
3063	item_p item;
3064
3065	if ((item = ng_getqblk()) == NULL) {
3066		NG_FREE_M(m);
3067		NG_FREE_META(meta);
3068		return (NULL);
3069	}
3070	ITEM_DEBUG_CHECKS;
3071	item->el_flags = NGQF_DATA;
3072	item->el_next = NULL;
3073	NGI_M(item) = m;
3074	NGI_META(item) = meta;
3075	return (item);
3076}
3077
3078/*
3079 * Allocate a queue item and put items into it..
3080 * Evaluate the address as this will be needed to queue it and
3081 * to work out what some of the fields should be.
3082 * Hook and node references will be removed when the item is dequeued.
3083 * (or equivalent)
3084 */
3085item_p
3086ng_package_msg(struct ng_mesg *msg)
3087{
3088	item_p item;
3089
3090	if ((item = ng_getqblk()) == NULL) {
3091		if ((msg->header.flags & NGF_STATIC) == 0) {
3092			NG_FREE_MSG(msg);
3093		}
3094		return (NULL);
3095	}
3096	ITEM_DEBUG_CHECKS;
3097	item->el_flags = NGQF_MESG;
3098	item->el_next = NULL;
3099	/*
3100	 * Set the current lasthook into the queue item
3101	 */
3102	NGI_MSG(item) = msg;
3103	NGI_RETADDR(item) = NULL;
3104	return (item);
3105}
3106
3107
3108
3109#define SET_RETADDR							\
3110	do {	/* Data items don't have retaddrs */			\
3111		if ((item->el_flags & NGQF_D_M) == NGQF_MESG) {		\
3112			if (retaddr) {					\
3113				NGI_RETADDR(item) = retaddr;		\
3114			} else {					\
3115				/*					\
3116				 * The old return address should be ok.	\
3117				 * If there isn't one, use the address	\
3118				 * here.				\
3119				 */					\
3120				if (NGI_RETADDR(item) == 0) {		\
3121					NGI_RETADDR(item)		\
3122						= ng_node2ID(here);	\
3123				}					\
3124			}						\
3125		}							\
3126	} while (0)
3127
3128int
3129ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr)
3130{
3131	ITEM_DEBUG_CHECKS;
3132	/*
3133	 * Quick sanity check..
3134	 * Since a hook holds a reference on it's node, once we know
3135	 * that the peer is still connected (even if invalid,) we know
3136	 * that the peer node is present, though maybe invalid.
3137	 */
3138	if ((hook == NULL)
3139	|| NG_HOOK_NOT_VALID(hook)
3140	|| (NG_HOOK_PEER(hook) == NULL)
3141	|| NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook))
3142	|| NG_NODE_NOT_VALID(NG_PEER_NODE(hook))) {
3143		NG_FREE_ITEM(item);
3144		TRAP_ERROR
3145		return (EINVAL);
3146	}
3147
3148	/*
3149	 * Transfer our interest to the other (peer) end.
3150	 */
3151	item->el_hook = NG_HOOK_PEER(hook);
3152	NG_HOOK_REF(item->el_hook); /* Don't let it go while on the queue */
3153	item->el_dest = NG_PEER_NODE(hook);
3154	NG_NODE_REF(item->el_dest); /* Nor this */
3155	SET_RETADDR;
3156	return (0);
3157}
3158
3159int
3160ng_address_path(node_p here, item_p item, char *address, ng_ID_t retaddr)
3161{
3162	node_p  dest = NULL;
3163	hook_p	hook = NULL;
3164	int     error;
3165
3166	ITEM_DEBUG_CHECKS;
3167	/*
3168	 * Note that ng_path2noderef increments the reference count
3169	 * on the node for us if it finds one. So we don't have to.
3170	 */
3171	error = ng_path2noderef(here, address, &dest, &hook);
3172	if (error) {
3173		NG_FREE_ITEM(item);
3174		return (error);
3175	}
3176	item->el_dest = dest;
3177	if (( item->el_hook = hook))
3178		NG_HOOK_REF(hook);	/* don't let it go while on the queue */
3179	SET_RETADDR;
3180	return (0);
3181}
3182
3183int
3184ng_address_ID(node_p here, item_p item, ng_ID_t ID, ng_ID_t retaddr)
3185{
3186	node_p dest;
3187
3188	ITEM_DEBUG_CHECKS;
3189	/*
3190	 * Find the target node.
3191	 */
3192	dest = ng_ID2noderef(ID); /* GETS REFERENCE! */
3193	if (dest == NULL) {
3194		NG_FREE_ITEM(item);
3195		TRAP_ERROR
3196		return(EINVAL);
3197	}
3198	/* Fill out the contents */
3199	item->el_flags = NGQF_MESG;
3200	item->el_next = NULL;
3201	item->el_dest = dest;
3202	item->el_hook = NULL;
3203	SET_RETADDR;
3204	return (0);
3205}
3206
3207/*
3208 * special case to send a message to self (e.g. destroy node)
3209 * Possibly indicate an arrival hook too.
3210 * Useful for removing that hook :-)
3211 */
3212item_p
3213ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg)
3214{
3215	item_p item;
3216
3217	/*
3218	 * Find the target node.
3219	 * If there is a HOOK argument, then use that in preference
3220	 * to the address.
3221	 */
3222	if ((item = ng_getqblk()) == NULL) {
3223		if ((msg->header.flags & NGF_STATIC) == 0) {
3224			NG_FREE_MSG(msg);
3225		}
3226		return (NULL);
3227	}
3228
3229	/* Fill out the contents */
3230	item->el_flags = NGQF_MESG;
3231	item->el_next = NULL;
3232	item->el_dest = here;
3233	NG_NODE_REF(here);
3234	item->el_hook = hook;
3235	if (hook)
3236		NG_HOOK_REF(hook);
3237	NGI_MSG(item) = msg;
3238	NGI_RETADDR(item) = ng_node2ID(here);
3239	return (item);
3240}
3241
3242/*
3243 * Set the address, if none given, give the node here.
3244 */
3245void
3246ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr)
3247{
3248	if (retaddr) {
3249		NGI_RETADDR(item) = retaddr;
3250	} else {
3251		/*
3252		 * The old return address should be ok.
3253		 * If there isn't one, use the address here.
3254		 */
3255		NGI_RETADDR(item) = ng_node2ID(here);
3256	}
3257}
3258
3259#define TESTING
3260#ifdef TESTING
3261/* just test all the macros */
3262void
3263ng_macro_test(item_p item);
3264void
3265ng_macro_test(item_p item)
3266{
3267	node_p node = NULL;
3268	hook_p hook = NULL;
3269	struct mbuf *m;
3270	meta_p meta;
3271	struct ng_mesg *msg;
3272	ng_ID_t retaddr;
3273	int	error;
3274
3275	NGI_GET_M(item, m);
3276	NGI_GET_META(item, meta);
3277	NGI_GET_MSG(item, msg);
3278	retaddr = NGI_RETADDR(item);
3279	NG_SEND_DATA(error, hook, m, meta);
3280	NG_SEND_DATA_ONLY(error, hook, m);
3281	NG_FWD_NEW_DATA(error, item, hook, m);
3282	NG_FWD_ITEM_HOOK(error, item, hook);
3283	NG_SEND_MSG_HOOK(error, node, msg, hook, retaddr);
3284	NG_SEND_MSG_ID(error, node, msg, retaddr, retaddr);
3285	NG_SEND_MSG_PATH(error, node, msg, ".:", retaddr);
3286	NG_QUEUE_MSG(error, node, msg, ".:", retaddr);
3287	NG_FWD_MSG_HOOK(error, node, item, hook, retaddr);
3288}
3289#endif /* TESTING */
3290
3291