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