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