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