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