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