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