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