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