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