ng_base.c revision 231764
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 231764 2012-02-15 14:56:18Z 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	if (NG_HOOK_NOT_VALID(hook1) || NG_HOOK_NOT_VALID(hook2)) {
1165		mtx_unlock(&ng_topo_mtx);
1166		return (EINVAL);
1167	}
1168	hook1->hk_peer->hk_peer = hook2->hk_peer;
1169	hook2->hk_peer->hk_peer = hook1->hk_peer;
1170
1171	hook1->hk_peer = &ng_deadhook;
1172	hook2->hk_peer = &ng_deadhook;
1173	mtx_unlock(&ng_topo_mtx);
1174
1175	NG_HOOK_UNREF(hook1);
1176	NG_HOOK_UNREF(hook2);
1177
1178	/* XXX If we ever cache methods on hooks update them as well */
1179	ng_destroy_hook(hook1);
1180	ng_destroy_hook(hook2);
1181	return (0);
1182}
1183
1184/*
1185 * Install a new netgraph type
1186 */
1187int
1188ng_newtype(struct ng_type *tp)
1189{
1190	const size_t namelen = strlen(tp->name);
1191
1192	/* Check version and type name fields */
1193	if ((tp->version != NG_ABI_VERSION) || (namelen == 0) ||
1194	    (namelen >= NG_TYPESIZ)) {
1195		TRAP_ERROR();
1196		if (tp->version != NG_ABI_VERSION) {
1197			printf("Netgraph: Node type rejected. ABI mismatch. "
1198			    "Suggest recompile\n");
1199		}
1200		return (EINVAL);
1201	}
1202
1203	/* Check for name collision */
1204	if (ng_findtype(tp->name) != NULL) {
1205		TRAP_ERROR();
1206		return (EEXIST);
1207	}
1208
1209
1210	/* Link in new type */
1211	TYPELIST_WLOCK();
1212	LIST_INSERT_HEAD(&ng_typelist, tp, types);
1213	tp->refs = 1;	/* first ref is linked list */
1214	TYPELIST_WUNLOCK();
1215	return (0);
1216}
1217
1218/*
1219 * unlink a netgraph type
1220 * If no examples exist
1221 */
1222int
1223ng_rmtype(struct ng_type *tp)
1224{
1225	/* Check for name collision */
1226	if (tp->refs != 1) {
1227		TRAP_ERROR();
1228		return (EBUSY);
1229	}
1230
1231	/* Unlink type */
1232	TYPELIST_WLOCK();
1233	LIST_REMOVE(tp, types);
1234	TYPELIST_WUNLOCK();
1235	return (0);
1236}
1237
1238/*
1239 * Look for a type of the name given
1240 */
1241struct ng_type *
1242ng_findtype(const char *typename)
1243{
1244	struct ng_type *type;
1245
1246	TYPELIST_RLOCK();
1247	LIST_FOREACH(type, &ng_typelist, types) {
1248		if (strcmp(type->name, typename) == 0)
1249			break;
1250	}
1251	TYPELIST_RUNLOCK();
1252	return (type);
1253}
1254
1255/************************************************************************
1256			Composite routines
1257************************************************************************/
1258/*
1259 * Connect two nodes using the specified hooks, using queued functions.
1260 */
1261static int
1262ng_con_part3(node_p node, item_p item, hook_p hook)
1263{
1264	int	error = 0;
1265
1266	/*
1267	 * When we run, we know that the node 'node' is locked for us.
1268	 * Our caller has a reference on the hook.
1269	 * Our caller has a reference on the node.
1270	 * (In this case our caller is ng_apply_item() ).
1271	 * The peer hook has a reference on the hook.
1272	 * We are all set up except for the final call to the node, and
1273	 * the clearing of the INVALID flag.
1274	 */
1275	if (NG_HOOK_NODE(hook) == &ng_deadnode) {
1276		/*
1277		 * The node must have been freed again since we last visited
1278		 * here. ng_destry_hook() has this effect but nothing else does.
1279		 * We should just release our references and
1280		 * free anything we can think of.
1281		 * Since we know it's been destroyed, and it's our caller
1282		 * that holds the references, just return.
1283		 */
1284		ERROUT(ENOENT);
1285	}
1286	if (hook->hk_node->nd_type->connect) {
1287		if ((error = (*hook->hk_node->nd_type->connect) (hook))) {
1288			ng_destroy_hook(hook);	/* also zaps peer */
1289			printf("failed in ng_con_part3()\n");
1290			ERROUT(error);
1291		}
1292	}
1293	/*
1294	 *  XXX this is wrong for SMP. Possibly we need
1295	 * to separate out 'create' and 'invalid' flags.
1296	 * should only set flags on hooks we have locked under our node.
1297	 */
1298	hook->hk_flags &= ~HK_INVALID;
1299done:
1300	NG_FREE_ITEM(item);
1301	return (error);
1302}
1303
1304static int
1305ng_con_part2(node_p node, item_p item, hook_p hook)
1306{
1307	hook_p	peer;
1308	int	error = 0;
1309
1310	/*
1311	 * When we run, we know that the node 'node' is locked for us.
1312	 * Our caller has a reference on the hook.
1313	 * Our caller has a reference on the node.
1314	 * (In this case our caller is ng_apply_item() ).
1315	 * The peer hook has a reference on the hook.
1316	 * our node pointer points to the 'dead' node.
1317	 * First check the hook name is unique.
1318	 * Should not happen because we checked before queueing this.
1319	 */
1320	if (ng_findhook(node, NG_HOOK_NAME(hook)) != NULL) {
1321		TRAP_ERROR();
1322		ng_destroy_hook(hook); /* should destroy peer too */
1323		printf("failed in ng_con_part2()\n");
1324		ERROUT(EEXIST);
1325	}
1326	/*
1327	 * Check if the node type code has something to say about it
1328	 * If it fails, the unref of the hook will also unref the attached node,
1329	 * however since that node is 'ng_deadnode' this will do nothing.
1330	 * The peer hook will also be destroyed.
1331	 */
1332	if (node->nd_type->newhook != NULL) {
1333		if ((error = (*node->nd_type->newhook)(node, hook,
1334		    hook->hk_name))) {
1335			ng_destroy_hook(hook); /* should destroy peer too */
1336			printf("failed in ng_con_part2()\n");
1337			ERROUT(error);
1338		}
1339	}
1340
1341	/*
1342	 * The 'type' agrees so far, so go ahead and link it in.
1343	 * We'll ask again later when we actually connect the hooks.
1344	 */
1345	hook->hk_node = node;		/* just overwrite ng_deadnode */
1346	NG_NODE_REF(node);		/* each hook counts as a reference */
1347	LIST_INSERT_HEAD(&node->nd_hooks, hook, hk_hooks);
1348	node->nd_numhooks++;
1349	NG_HOOK_REF(hook);	/* one for the node */
1350
1351	/*
1352	 * We now have a symmetrical situation, where both hooks have been
1353	 * linked to their nodes, the newhook methods have been called
1354	 * And the references are all correct. The hooks are still marked
1355	 * as invalid, as we have not called the 'connect' methods
1356	 * yet.
1357	 * We can call the local one immediately as we have the
1358	 * node locked, but we need to queue the remote one.
1359	 */
1360	if (hook->hk_node->nd_type->connect) {
1361		if ((error = (*hook->hk_node->nd_type->connect) (hook))) {
1362			ng_destroy_hook(hook);	/* also zaps peer */
1363			printf("failed in ng_con_part2(A)\n");
1364			ERROUT(error);
1365		}
1366	}
1367
1368	/*
1369	 * Acquire topo mutex to avoid race with ng_destroy_hook().
1370	 */
1371	mtx_lock(&ng_topo_mtx);
1372	peer = hook->hk_peer;
1373	if (peer == &ng_deadhook) {
1374		mtx_unlock(&ng_topo_mtx);
1375		printf("failed in ng_con_part2(B)\n");
1376		ng_destroy_hook(hook);
1377		ERROUT(ENOENT);
1378	}
1379	mtx_unlock(&ng_topo_mtx);
1380
1381	if ((error = ng_send_fn2(peer->hk_node, peer, item, &ng_con_part3,
1382	    NULL, 0, NG_REUSE_ITEM))) {
1383		printf("failed in ng_con_part2(C)\n");
1384		ng_destroy_hook(hook);	/* also zaps peer */
1385		return (error);		/* item was consumed. */
1386	}
1387	hook->hk_flags &= ~HK_INVALID; /* need both to be able to work */
1388	return (0);			/* item was consumed. */
1389done:
1390	NG_FREE_ITEM(item);
1391	return (error);
1392}
1393
1394/*
1395 * Connect this node with another node. We assume that this node is
1396 * currently locked, as we are only called from an NGM_CONNECT message.
1397 */
1398static int
1399ng_con_nodes(item_p item, node_p node, const char *name,
1400    node_p node2, const char *name2)
1401{
1402	int	error;
1403	hook_p	hook;
1404	hook_p	hook2;
1405
1406	if (ng_findhook(node2, name2) != NULL) {
1407		return(EEXIST);
1408	}
1409	if ((error = ng_add_hook(node, name, &hook)))  /* gives us a ref */
1410		return (error);
1411	/* Allocate the other hook and link it up */
1412	NG_ALLOC_HOOK(hook2);
1413	if (hook2 == NULL) {
1414		TRAP_ERROR();
1415		ng_destroy_hook(hook);	/* XXX check ref counts so far */
1416		NG_HOOK_UNREF(hook);	/* including our ref */
1417		return (ENOMEM);
1418	}
1419	hook2->hk_refs = 1;		/* start with a reference for us. */
1420	hook2->hk_flags = HK_INVALID;
1421	hook2->hk_peer = hook;		/* Link the two together */
1422	hook->hk_peer = hook2;
1423	NG_HOOK_REF(hook);		/* Add a ref for the peer to each*/
1424	NG_HOOK_REF(hook2);
1425	hook2->hk_node = &ng_deadnode;
1426	strlcpy(NG_HOOK_NAME(hook2), name2, NG_HOOKSIZ);
1427
1428	/*
1429	 * Queue the function above.
1430	 * Procesing continues in that function in the lock context of
1431	 * the other node.
1432	 */
1433	if ((error = ng_send_fn2(node2, hook2, item, &ng_con_part2, NULL, 0,
1434	    NG_NOFLAGS))) {
1435		printf("failed in ng_con_nodes(): %d\n", error);
1436		ng_destroy_hook(hook);	/* also zaps peer */
1437	}
1438
1439	NG_HOOK_UNREF(hook);		/* Let each hook go if it wants to */
1440	NG_HOOK_UNREF(hook2);
1441	return (error);
1442}
1443
1444/*
1445 * Make a peer and connect.
1446 * We assume that the local node is locked.
1447 * The new node probably doesn't need a lock until
1448 * it has a hook, because it cannot really have any work until then,
1449 * but we should think about it a bit more.
1450 *
1451 * The problem may come if the other node also fires up
1452 * some hardware or a timer or some other source of activation,
1453 * also it may already get a command msg via it's ID.
1454 *
1455 * We could use the same method as ng_con_nodes() but we'd have
1456 * to add ability to remove the node when failing. (Not hard, just
1457 * make arg1 point to the node to remove).
1458 * Unless of course we just ignore failure to connect and leave
1459 * an unconnected node?
1460 */
1461static int
1462ng_mkpeer(node_p node, const char *name, const char *name2, char *type)
1463{
1464	node_p	node2;
1465	hook_p	hook1, hook2;
1466	int	error;
1467
1468	if ((error = ng_make_node(type, &node2))) {
1469		return (error);
1470	}
1471
1472	if ((error = ng_add_hook(node, name, &hook1))) { /* gives us a ref */
1473		ng_rmnode(node2, NULL, NULL, 0);
1474		return (error);
1475	}
1476
1477	if ((error = ng_add_hook(node2, name2, &hook2))) {
1478		ng_rmnode(node2, NULL, NULL, 0);
1479		ng_destroy_hook(hook1);
1480		NG_HOOK_UNREF(hook1);
1481		return (error);
1482	}
1483
1484	/*
1485	 * Actually link the two hooks together.
1486	 */
1487	hook1->hk_peer = hook2;
1488	hook2->hk_peer = hook1;
1489
1490	/* Each hook is referenced by the other */
1491	NG_HOOK_REF(hook1);
1492	NG_HOOK_REF(hook2);
1493
1494	/* Give each node the opportunity to veto the pending connection */
1495	if (hook1->hk_node->nd_type->connect) {
1496		error = (*hook1->hk_node->nd_type->connect) (hook1);
1497	}
1498
1499	if ((error == 0) && hook2->hk_node->nd_type->connect) {
1500		error = (*hook2->hk_node->nd_type->connect) (hook2);
1501
1502	}
1503
1504	/*
1505	 * drop the references we were holding on the two hooks.
1506	 */
1507	if (error) {
1508		ng_destroy_hook(hook2);	/* also zaps hook1 */
1509		ng_rmnode(node2, NULL, NULL, 0);
1510	} else {
1511		/* As a last act, allow the hooks to be used */
1512		hook1->hk_flags &= ~HK_INVALID;
1513		hook2->hk_flags &= ~HK_INVALID;
1514	}
1515	NG_HOOK_UNREF(hook1);
1516	NG_HOOK_UNREF(hook2);
1517	return (error);
1518}
1519
1520/************************************************************************
1521		Utility routines to send self messages
1522************************************************************************/
1523
1524/* Shut this node down as soon as everyone is clear of it */
1525/* Should add arg "immediately" to jump the queue */
1526int
1527ng_rmnode_self(node_p node)
1528{
1529	int		error;
1530
1531	if (node == &ng_deadnode)
1532		return (0);
1533	node->nd_flags |= NGF_INVALID;
1534	if (node->nd_flags & NGF_CLOSING)
1535		return (0);
1536
1537	error = ng_send_fn(node, NULL, &ng_rmnode, NULL, 0);
1538	return (error);
1539}
1540
1541static void
1542ng_rmhook_part2(node_p node, hook_p hook, void *arg1, int arg2)
1543{
1544	ng_destroy_hook(hook);
1545	return ;
1546}
1547
1548int
1549ng_rmhook_self(hook_p hook)
1550{
1551	int		error;
1552	node_p node = NG_HOOK_NODE(hook);
1553
1554	if (node == &ng_deadnode)
1555		return (0);
1556
1557	error = ng_send_fn(node, hook, &ng_rmhook_part2, NULL, 0);
1558	return (error);
1559}
1560
1561/***********************************************************************
1562 * Parse and verify a string of the form:  <NODE:><PATH>
1563 *
1564 * Such a string can refer to a specific node or a specific hook
1565 * on a specific node, depending on how you look at it. In the
1566 * latter case, the PATH component must not end in a dot.
1567 *
1568 * Both <NODE:> and <PATH> are optional. The <PATH> is a string
1569 * of hook names separated by dots. This breaks out the original
1570 * string, setting *nodep to "NODE" (or NULL if none) and *pathp
1571 * to "PATH" (or NULL if degenerate). Also, *hookp will point to
1572 * the final hook component of <PATH>, if any, otherwise NULL.
1573 *
1574 * This returns -1 if the path is malformed. The char ** are optional.
1575 ***********************************************************************/
1576int
1577ng_path_parse(char *addr, char **nodep, char **pathp, char **hookp)
1578{
1579	char	*node, *path, *hook;
1580	int	k;
1581
1582	/*
1583	 * Extract absolute NODE, if any
1584	 */
1585	for (path = addr; *path && *path != ':'; path++);
1586	if (*path) {
1587		node = addr;	/* Here's the NODE */
1588		*path++ = '\0';	/* Here's the PATH */
1589
1590		/* Node name must not be empty */
1591		if (!*node)
1592			return -1;
1593
1594		/* A name of "." is OK; otherwise '.' not allowed */
1595		if (strcmp(node, ".") != 0) {
1596			for (k = 0; node[k]; k++)
1597				if (node[k] == '.')
1598					return -1;
1599		}
1600	} else {
1601		node = NULL;	/* No absolute NODE */
1602		path = addr;	/* Here's the PATH */
1603	}
1604
1605	/* Snoop for illegal characters in PATH */
1606	for (k = 0; path[k]; k++)
1607		if (path[k] == ':')
1608			return -1;
1609
1610	/* Check for no repeated dots in PATH */
1611	for (k = 0; path[k]; k++)
1612		if (path[k] == '.' && path[k + 1] == '.')
1613			return -1;
1614
1615	/* Remove extra (degenerate) dots from beginning or end of PATH */
1616	if (path[0] == '.')
1617		path++;
1618	if (*path && path[strlen(path) - 1] == '.')
1619		path[strlen(path) - 1] = 0;
1620
1621	/* If PATH has a dot, then we're not talking about a hook */
1622	if (*path) {
1623		for (hook = path, k = 0; path[k]; k++)
1624			if (path[k] == '.') {
1625				hook = NULL;
1626				break;
1627			}
1628	} else
1629		path = hook = NULL;
1630
1631	/* Done */
1632	if (nodep)
1633		*nodep = node;
1634	if (pathp)
1635		*pathp = path;
1636	if (hookp)
1637		*hookp = hook;
1638	return (0);
1639}
1640
1641/*
1642 * Given a path, which may be absolute or relative, and a starting node,
1643 * return the destination node.
1644 */
1645int
1646ng_path2noderef(node_p here, const char *address, node_p *destp,
1647    hook_p *lasthook)
1648{
1649	char    fullpath[NG_PATHSIZ];
1650	char   *nodename, *path;
1651	node_p  node, oldnode;
1652
1653	/* Initialize */
1654	if (destp == NULL) {
1655		TRAP_ERROR();
1656		return EINVAL;
1657	}
1658	*destp = NULL;
1659
1660	/* Make a writable copy of address for ng_path_parse() */
1661	strncpy(fullpath, address, sizeof(fullpath) - 1);
1662	fullpath[sizeof(fullpath) - 1] = '\0';
1663
1664	/* Parse out node and sequence of hooks */
1665	if (ng_path_parse(fullpath, &nodename, &path, NULL) < 0) {
1666		TRAP_ERROR();
1667		return EINVAL;
1668	}
1669
1670	/*
1671	 * For an absolute address, jump to the starting node.
1672	 * Note that this holds a reference on the node for us.
1673	 * Don't forget to drop the reference if we don't need it.
1674	 */
1675	if (nodename) {
1676		node = ng_name2noderef(here, nodename);
1677		if (node == NULL) {
1678			TRAP_ERROR();
1679			return (ENOENT);
1680		}
1681	} else {
1682		if (here == NULL) {
1683			TRAP_ERROR();
1684			return (EINVAL);
1685		}
1686		node = here;
1687		NG_NODE_REF(node);
1688	}
1689
1690	if (path == NULL) {
1691		if (lasthook != NULL)
1692			*lasthook = NULL;
1693		*destp = node;
1694		return (0);
1695	}
1696
1697	/*
1698	 * Now follow the sequence of hooks
1699	 *
1700	 * XXXGL: The path may demolish as we go the sequence, but if
1701	 * we hold the topology mutex at critical places, then, I hope,
1702	 * we would always have valid pointers in hand, although the
1703	 * path behind us may no longer exist.
1704	 */
1705	for (;;) {
1706		hook_p hook;
1707		char *segment;
1708
1709		/*
1710		 * Break out the next path segment. Replace the dot we just
1711		 * found with a NUL; "path" points to the next segment (or the
1712		 * NUL at the end).
1713		 */
1714		for (segment = path; *path != '\0'; path++) {
1715			if (*path == '.') {
1716				*path++ = '\0';
1717				break;
1718			}
1719		}
1720
1721		/* We have a segment, so look for a hook by that name */
1722		hook = ng_findhook(node, segment);
1723
1724		mtx_lock(&ng_topo_mtx);
1725		/* Can't get there from here... */
1726		if (hook == NULL || NG_HOOK_PEER(hook) == NULL ||
1727		    NG_HOOK_NOT_VALID(hook) ||
1728		    NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook))) {
1729			TRAP_ERROR();
1730			NG_NODE_UNREF(node);
1731			mtx_unlock(&ng_topo_mtx);
1732			return (ENOENT);
1733		}
1734
1735		/*
1736		 * Hop on over to the next node
1737		 * XXX
1738		 * Big race conditions here as hooks and nodes go away
1739		 * *** Idea.. store an ng_ID_t in each hook and use that
1740		 * instead of the direct hook in this crawl?
1741		 */
1742		oldnode = node;
1743		if ((node = NG_PEER_NODE(hook)))
1744			NG_NODE_REF(node);	/* XXX RACE */
1745		NG_NODE_UNREF(oldnode);	/* XXX another race */
1746		if (NG_NODE_NOT_VALID(node)) {
1747			NG_NODE_UNREF(node);	/* XXX more races */
1748			mtx_unlock(&ng_topo_mtx);
1749			TRAP_ERROR();
1750			return (ENXIO);
1751		}
1752
1753		if (*path == '\0') {
1754			if (lasthook != NULL) {
1755				if (hook != NULL) {
1756					*lasthook = NG_HOOK_PEER(hook);
1757					NG_HOOK_REF(*lasthook);
1758				} else
1759					*lasthook = NULL;
1760			}
1761			mtx_unlock(&ng_topo_mtx);
1762			*destp = node;
1763			return (0);
1764		}
1765		mtx_unlock(&ng_topo_mtx);
1766	}
1767}
1768
1769/***************************************************************\
1770* Input queue handling.
1771* All activities are submitted to the node via the input queue
1772* which implements a multiple-reader/single-writer gate.
1773* Items which cannot be handled immediately are queued.
1774*
1775* read-write queue locking inline functions			*
1776\***************************************************************/
1777
1778static __inline void	ng_queue_rw(node_p node, item_p  item, int rw);
1779static __inline item_p	ng_dequeue(node_p node, int *rw);
1780static __inline item_p	ng_acquire_read(node_p node, item_p  item);
1781static __inline item_p	ng_acquire_write(node_p node, item_p  item);
1782static __inline void	ng_leave_read(node_p node);
1783static __inline void	ng_leave_write(node_p node);
1784
1785/*
1786 * Definition of the bits fields in the ng_queue flag word.
1787 * Defined here rather than in netgraph.h because no-one should fiddle
1788 * with them.
1789 *
1790 * The ordering here may be important! don't shuffle these.
1791 */
1792/*-
1793 Safety Barrier--------+ (adjustable to suit taste) (not used yet)
1794                       |
1795                       V
1796+-------+-------+-------+-------+-------+-------+-------+-------+
1797  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
1798  | |A|c|t|i|v|e| |R|e|a|d|e|r| |C|o|u|n|t| | | | | | | | | |P|A|
1799  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |O|W|
1800+-------+-------+-------+-------+-------+-------+-------+-------+
1801  \___________________________ ____________________________/ | |
1802                            V                                | |
1803                  [active reader count]                      | |
1804                                                             | |
1805            Operation Pending -------------------------------+ |
1806                                                               |
1807          Active Writer ---------------------------------------+
1808
1809Node queue has such semantics:
1810- All flags modifications are atomic.
1811- Reader count can be incremented only if there is no writer or pending flags.
1812  As soon as this can't be done with single operation, it is implemented with
1813  spin loop and atomic_cmpset().
1814- Writer flag can be set only if there is no any bits set.
1815  It is implemented with atomic_cmpset().
1816- Pending flag can be set any time, but to avoid collision on queue processing
1817  all queue fields are protected by the mutex.
1818- Queue processing thread reads queue holding the mutex, but releases it while
1819  processing. When queue is empty pending flag is removed.
1820*/
1821
1822#define WRITER_ACTIVE	0x00000001
1823#define OP_PENDING	0x00000002
1824#define READER_INCREMENT 0x00000004
1825#define READER_MASK	0xfffffffc	/* Not valid if WRITER_ACTIVE is set */
1826#define SAFETY_BARRIER	0x00100000	/* 128K items queued should be enough */
1827
1828/* Defines of more elaborate states on the queue */
1829/* Mask of bits a new read cares about */
1830#define NGQ_RMASK	(WRITER_ACTIVE|OP_PENDING)
1831
1832/* Mask of bits a new write cares about */
1833#define NGQ_WMASK	(NGQ_RMASK|READER_MASK)
1834
1835/* Test to decide if there is something on the queue. */
1836#define QUEUE_ACTIVE(QP) ((QP)->q_flags & OP_PENDING)
1837
1838/* How to decide what the next queued item is. */
1839#define HEAD_IS_READER(QP)  NGI_QUEUED_READER(STAILQ_FIRST(&(QP)->queue))
1840#define HEAD_IS_WRITER(QP)  NGI_QUEUED_WRITER(STAILQ_FIRST(&(QP)->queue)) /* notused */
1841
1842/* Read the status to decide if the next item on the queue can now run. */
1843#define QUEUED_READER_CAN_PROCEED(QP)			\
1844		(((QP)->q_flags & (NGQ_RMASK & ~OP_PENDING)) == 0)
1845#define QUEUED_WRITER_CAN_PROCEED(QP)			\
1846		(((QP)->q_flags & (NGQ_WMASK & ~OP_PENDING)) == 0)
1847
1848/* Is there a chance of getting ANY work off the queue? */
1849#define NEXT_QUEUED_ITEM_CAN_PROCEED(QP)				\
1850	((HEAD_IS_READER(QP)) ? QUEUED_READER_CAN_PROCEED(QP) :		\
1851				QUEUED_WRITER_CAN_PROCEED(QP))
1852
1853#define NGQRW_R 0
1854#define NGQRW_W 1
1855
1856#define NGQ2_WORKQ	0x00000001
1857
1858/*
1859 * Taking into account the current state of the queue and node, possibly take
1860 * the next entry off the queue and return it. Return NULL if there was
1861 * nothing we could return, either because there really was nothing there, or
1862 * because the node was in a state where it cannot yet process the next item
1863 * on the queue.
1864 */
1865static __inline item_p
1866ng_dequeue(node_p node, int *rw)
1867{
1868	item_p item;
1869	struct ng_queue *ngq = &node->nd_input_queue;
1870
1871	/* This MUST be called with the mutex held. */
1872	mtx_assert(&ngq->q_mtx, MA_OWNED);
1873
1874	/* If there is nothing queued, then just return. */
1875	if (!QUEUE_ACTIVE(ngq)) {
1876		CTR4(KTR_NET, "%20s: node [%x] (%p) queue empty; "
1877		    "queue flags 0x%lx", __func__,
1878		    node->nd_ID, node, ngq->q_flags);
1879		return (NULL);
1880	}
1881
1882	/*
1883	 * From here, we can assume there is a head item.
1884	 * We need to find out what it is and if it can be dequeued, given
1885	 * the current state of the node.
1886	 */
1887	if (HEAD_IS_READER(ngq)) {
1888		while (1) {
1889			long t = ngq->q_flags;
1890			if (t & WRITER_ACTIVE) {
1891				/* There is writer, reader can't proceed. */
1892				CTR4(KTR_NET, "%20s: node [%x] (%p) queued "
1893				    "reader can't proceed; queue flags 0x%lx",
1894				    __func__, node->nd_ID, node, t);
1895				return (NULL);
1896			}
1897			if (atomic_cmpset_acq_int(&ngq->q_flags, t,
1898			    t + READER_INCREMENT))
1899				break;
1900			cpu_spinwait();
1901		}
1902		/* We have got reader lock for the node. */
1903		*rw = NGQRW_R;
1904	} else if (atomic_cmpset_acq_int(&ngq->q_flags, OP_PENDING,
1905	    OP_PENDING + WRITER_ACTIVE)) {
1906		/* We have got writer lock for the node. */
1907		*rw = NGQRW_W;
1908	} else {
1909		/* There is somebody other, writer can't proceed. */
1910		CTR4(KTR_NET, "%20s: node [%x] (%p) queued writer can't "
1911		    "proceed; queue flags 0x%lx", __func__, node->nd_ID, node,
1912		    ngq->q_flags);
1913		return (NULL);
1914	}
1915
1916	/*
1917	 * Now we dequeue the request (whatever it may be) and correct the
1918	 * pending flags and the next and last pointers.
1919	 */
1920	item = STAILQ_FIRST(&ngq->queue);
1921	STAILQ_REMOVE_HEAD(&ngq->queue, el_next);
1922	if (STAILQ_EMPTY(&ngq->queue))
1923		atomic_clear_int(&ngq->q_flags, OP_PENDING);
1924	CTR6(KTR_NET, "%20s: node [%x] (%p) returning item %p as %s; queue "
1925	    "flags 0x%lx", __func__, node->nd_ID, node, item, *rw ? "WRITER" :
1926	    "READER", ngq->q_flags);
1927	return (item);
1928}
1929
1930/*
1931 * Queue a packet to be picked up later by someone else.
1932 * If the queue could be run now, add node to the queue handler's worklist.
1933 */
1934static __inline void
1935ng_queue_rw(node_p node, item_p  item, int rw)
1936{
1937	struct ng_queue *ngq = &node->nd_input_queue;
1938	if (rw == NGQRW_W)
1939		NGI_SET_WRITER(item);
1940	else
1941		NGI_SET_READER(item);
1942
1943	NG_QUEUE_LOCK(ngq);
1944	/* Set OP_PENDING flag and enqueue the item. */
1945	atomic_set_int(&ngq->q_flags, OP_PENDING);
1946	STAILQ_INSERT_TAIL(&ngq->queue, item, el_next);
1947
1948	CTR5(KTR_NET, "%20s: node [%x] (%p) queued item %p as %s", __func__,
1949	    node->nd_ID, node, item, rw ? "WRITER" : "READER" );
1950
1951	/*
1952	 * We can take the worklist lock with the node locked
1953	 * BUT NOT THE REVERSE!
1954	 */
1955	if (NEXT_QUEUED_ITEM_CAN_PROCEED(ngq))
1956		ng_worklist_add(node);
1957	NG_QUEUE_UNLOCK(ngq);
1958}
1959
1960/* Acquire reader lock on node. If node is busy, queue the packet. */
1961static __inline item_p
1962ng_acquire_read(node_p node, item_p item)
1963{
1964	KASSERT(node != &ng_deadnode,
1965	    ("%s: working on deadnode", __func__));
1966
1967	/* Reader needs node without writer and pending items. */
1968	for (;;) {
1969		long t = node->nd_input_queue.q_flags;
1970		if (t & NGQ_RMASK)
1971			break; /* Node is not ready for reader. */
1972		if (atomic_cmpset_acq_int(&node->nd_input_queue.q_flags, t,
1973		    t + READER_INCREMENT)) {
1974	    		/* Successfully grabbed node */
1975			CTR4(KTR_NET, "%20s: node [%x] (%p) acquired item %p",
1976			    __func__, node->nd_ID, node, item);
1977			return (item);
1978		}
1979		cpu_spinwait();
1980	};
1981
1982	/* Queue the request for later. */
1983	ng_queue_rw(node, item, NGQRW_R);
1984
1985	return (NULL);
1986}
1987
1988/* Acquire writer lock on node. If node is busy, queue the packet. */
1989static __inline item_p
1990ng_acquire_write(node_p node, item_p item)
1991{
1992	KASSERT(node != &ng_deadnode,
1993	    ("%s: working on deadnode", __func__));
1994
1995	/* Writer needs completely idle node. */
1996	if (atomic_cmpset_acq_int(&node->nd_input_queue.q_flags, 0,
1997	    WRITER_ACTIVE)) {
1998	    	/* Successfully grabbed node */
1999		CTR4(KTR_NET, "%20s: node [%x] (%p) acquired item %p",
2000		    __func__, node->nd_ID, node, item);
2001		return (item);
2002	}
2003
2004	/* Queue the request for later. */
2005	ng_queue_rw(node, item, NGQRW_W);
2006
2007	return (NULL);
2008}
2009
2010#if 0
2011static __inline item_p
2012ng_upgrade_write(node_p node, item_p item)
2013{
2014	struct ng_queue *ngq = &node->nd_input_queue;
2015	KASSERT(node != &ng_deadnode,
2016	    ("%s: working on deadnode", __func__));
2017
2018	NGI_SET_WRITER(item);
2019
2020	NG_QUEUE_LOCK(ngq);
2021
2022	/*
2023	 * There will never be no readers as we are there ourselves.
2024	 * Set the WRITER_ACTIVE flags ASAP to block out fast track readers.
2025	 * The caller we are running from will call ng_leave_read()
2026	 * soon, so we must account for that. We must leave again with the
2027	 * READER lock. If we find other readers, then
2028	 * queue the request for later. However "later" may be rignt now
2029	 * if there are no readers. We don't really care if there are queued
2030	 * items as we will bypass them anyhow.
2031	 */
2032	atomic_add_int(&ngq->q_flags, WRITER_ACTIVE - READER_INCREMENT);
2033	if ((ngq->q_flags & (NGQ_WMASK & ~OP_PENDING)) == WRITER_ACTIVE) {
2034		NG_QUEUE_UNLOCK(ngq);
2035
2036		/* It's just us, act on the item. */
2037		/* will NOT drop writer lock when done */
2038		ng_apply_item(node, item, 0);
2039
2040		/*
2041		 * Having acted on the item, atomically
2042		 * downgrade back to READER and finish up.
2043	 	 */
2044		atomic_add_int(&ngq->q_flags, READER_INCREMENT - WRITER_ACTIVE);
2045
2046		/* Our caller will call ng_leave_read() */
2047		return;
2048	}
2049	/*
2050	 * It's not just us active, so queue us AT THE HEAD.
2051	 * "Why?" I hear you ask.
2052	 * Put us at the head of the queue as we've already been
2053	 * through it once. If there is nothing else waiting,
2054	 * set the correct flags.
2055	 */
2056	if (STAILQ_EMPTY(&ngq->queue)) {
2057		/* We've gone from, 0 to 1 item in the queue */
2058		atomic_set_int(&ngq->q_flags, OP_PENDING);
2059
2060		CTR3(KTR_NET, "%20s: node [%x] (%p) set OP_PENDING", __func__,
2061		    node->nd_ID, node);
2062	};
2063	STAILQ_INSERT_HEAD(&ngq->queue, item, el_next);
2064	CTR4(KTR_NET, "%20s: node [%x] (%p) requeued item %p as WRITER",
2065	    __func__, node->nd_ID, node, item );
2066
2067	/* Reverse what we did above. That downgrades us back to reader */
2068	atomic_add_int(&ngq->q_flags, READER_INCREMENT - WRITER_ACTIVE);
2069	if (QUEUE_ACTIVE(ngq) && NEXT_QUEUED_ITEM_CAN_PROCEED(ngq))
2070		ng_worklist_add(node);
2071	NG_QUEUE_UNLOCK(ngq);
2072
2073	return;
2074}
2075#endif
2076
2077/* Release reader lock. */
2078static __inline void
2079ng_leave_read(node_p node)
2080{
2081	atomic_subtract_rel_int(&node->nd_input_queue.q_flags, READER_INCREMENT);
2082}
2083
2084/* Release writer lock. */
2085static __inline void
2086ng_leave_write(node_p node)
2087{
2088	atomic_clear_rel_int(&node->nd_input_queue.q_flags, WRITER_ACTIVE);
2089}
2090
2091/* Purge node queue. Called on node shutdown. */
2092static void
2093ng_flush_input_queue(node_p node)
2094{
2095	struct ng_queue *ngq = &node->nd_input_queue;
2096	item_p item;
2097
2098	NG_QUEUE_LOCK(ngq);
2099	while ((item = STAILQ_FIRST(&ngq->queue)) != NULL) {
2100		STAILQ_REMOVE_HEAD(&ngq->queue, el_next);
2101		if (STAILQ_EMPTY(&ngq->queue))
2102			atomic_clear_int(&ngq->q_flags, OP_PENDING);
2103		NG_QUEUE_UNLOCK(ngq);
2104
2105		/* If the item is supplying a callback, call it with an error */
2106		if (item->apply != NULL) {
2107			if (item->depth == 1)
2108				item->apply->error = ENOENT;
2109			if (refcount_release(&item->apply->refs)) {
2110				(*item->apply->apply)(item->apply->context,
2111				    item->apply->error);
2112			}
2113		}
2114		NG_FREE_ITEM(item);
2115		NG_QUEUE_LOCK(ngq);
2116	}
2117	NG_QUEUE_UNLOCK(ngq);
2118}
2119
2120/***********************************************************************
2121* Externally visible method for sending or queueing messages or data.
2122***********************************************************************/
2123
2124/*
2125 * The module code should have filled out the item correctly by this stage:
2126 * Common:
2127 *    reference to destination node.
2128 *    Reference to destination rcv hook if relevant.
2129 *    apply pointer must be or NULL or reference valid struct ng_apply_info.
2130 * Data:
2131 *    pointer to mbuf
2132 * Control_Message:
2133 *    pointer to msg.
2134 *    ID of original sender node. (return address)
2135 * Function:
2136 *    Function pointer
2137 *    void * argument
2138 *    integer argument
2139 *
2140 * The nodes have several routines and macros to help with this task:
2141 */
2142
2143int
2144ng_snd_item(item_p item, int flags)
2145{
2146	hook_p hook;
2147	node_p node;
2148	int queue, rw;
2149	struct ng_queue *ngq;
2150	int error = 0;
2151
2152	/* We are sending item, so it must be present! */
2153	KASSERT(item != NULL, ("ng_snd_item: item is NULL"));
2154
2155#ifdef	NETGRAPH_DEBUG
2156	_ngi_check(item, __FILE__, __LINE__);
2157#endif
2158
2159	/* Item was sent once more, postpone apply() call. */
2160	if (item->apply)
2161		refcount_acquire(&item->apply->refs);
2162
2163	node = NGI_NODE(item);
2164	/* Node is never optional. */
2165	KASSERT(node != NULL, ("ng_snd_item: node is NULL"));
2166
2167	hook = NGI_HOOK(item);
2168	/* Valid hook and mbuf are mandatory for data. */
2169	if ((item->el_flags & NGQF_TYPE) == NGQF_DATA) {
2170		KASSERT(hook != NULL, ("ng_snd_item: hook for data is NULL"));
2171		if (NGI_M(item) == NULL)
2172			ERROUT(EINVAL);
2173		CHECK_DATA_MBUF(NGI_M(item));
2174	}
2175
2176	/*
2177	 * If the item or the node specifies single threading, force
2178	 * writer semantics. Similarly, the node may say one hook always
2179	 * produces writers. These are overrides.
2180	 */
2181	if (((item->el_flags & NGQF_RW) == NGQF_WRITER) ||
2182	    (node->nd_flags & NGF_FORCE_WRITER) ||
2183	    (hook && (hook->hk_flags & HK_FORCE_WRITER))) {
2184		rw = NGQRW_W;
2185	} else {
2186		rw = NGQRW_R;
2187	}
2188
2189	/*
2190	 * If sender or receiver requests queued delivery, or call graph
2191	 * loops back from outbound to inbound path, or stack usage
2192	 * level is dangerous - enqueue message.
2193	 */
2194	if ((flags & NG_QUEUE) || (hook && (hook->hk_flags & HK_QUEUE))) {
2195		queue = 1;
2196	} else if (hook && (hook->hk_flags & HK_TO_INBOUND) &&
2197	    curthread->td_ng_outbound) {
2198		queue = 1;
2199	} else {
2200		queue = 0;
2201#ifdef GET_STACK_USAGE
2202		/*
2203		 * Most of netgraph nodes have small stack consumption and
2204		 * for them 25% of free stack space is more than enough.
2205		 * Nodes/hooks with higher stack usage should be marked as
2206		 * HI_STACK. For them 50% of stack will be guaranteed then.
2207		 * XXX: Values 25% and 50% are completely empirical.
2208		 */
2209		size_t	st, su, sl;
2210		GET_STACK_USAGE(st, su);
2211		sl = st - su;
2212		if ((sl * 4 < st) || ((sl * 2 < st) &&
2213		    ((node->nd_flags & NGF_HI_STACK) || (hook &&
2214		    (hook->hk_flags & HK_HI_STACK)))))
2215			queue = 1;
2216#endif
2217	}
2218
2219	if (queue) {
2220		item->depth = 1;
2221		/* Put it on the queue for that node*/
2222		ng_queue_rw(node, item, rw);
2223		return ((flags & NG_PROGRESS) ? EINPROGRESS : 0);
2224	}
2225
2226	/*
2227	 * We already decided how we will be queueud or treated.
2228	 * Try get the appropriate operating permission.
2229	 */
2230 	if (rw == NGQRW_R)
2231		item = ng_acquire_read(node, item);
2232	else
2233		item = ng_acquire_write(node, item);
2234
2235	/* Item was queued while trying to get permission. */
2236	if (item == NULL)
2237		return ((flags & NG_PROGRESS) ? EINPROGRESS : 0);
2238
2239	NGI_GET_NODE(item, node); /* zaps stored node */
2240
2241	item->depth++;
2242	error = ng_apply_item(node, item, rw); /* drops r/w lock when done */
2243
2244	/* If something is waiting on queue and ready, schedule it. */
2245	ngq = &node->nd_input_queue;
2246	if (QUEUE_ACTIVE(ngq)) {
2247		NG_QUEUE_LOCK(ngq);
2248		if (QUEUE_ACTIVE(ngq) && NEXT_QUEUED_ITEM_CAN_PROCEED(ngq))
2249			ng_worklist_add(node);
2250		NG_QUEUE_UNLOCK(ngq);
2251	}
2252
2253	/*
2254	 * Node may go away as soon as we remove the reference.
2255	 * Whatever we do, DO NOT access the node again!
2256	 */
2257	NG_NODE_UNREF(node);
2258
2259	return (error);
2260
2261done:
2262	/* If was not sent, apply callback here. */
2263	if (item->apply != NULL) {
2264		if (item->depth == 0 && error != 0)
2265			item->apply->error = error;
2266		if (refcount_release(&item->apply->refs)) {
2267			(*item->apply->apply)(item->apply->context,
2268			    item->apply->error);
2269		}
2270	}
2271
2272	NG_FREE_ITEM(item);
2273	return (error);
2274}
2275
2276/*
2277 * We have an item that was possibly queued somewhere.
2278 * It should contain all the information needed
2279 * to run it on the appropriate node/hook.
2280 * If there is apply pointer and we own the last reference, call apply().
2281 */
2282static int
2283ng_apply_item(node_p node, item_p item, int rw)
2284{
2285	hook_p  hook;
2286	ng_rcvdata_t *rcvdata;
2287	ng_rcvmsg_t *rcvmsg;
2288	struct ng_apply_info *apply;
2289	int	error = 0, depth;
2290
2291	/* Node and item are never optional. */
2292	KASSERT(node != NULL, ("ng_apply_item: node is NULL"));
2293	KASSERT(item != NULL, ("ng_apply_item: item is NULL"));
2294
2295	NGI_GET_HOOK(item, hook); /* clears stored hook */
2296#ifdef	NETGRAPH_DEBUG
2297	_ngi_check(item, __FILE__, __LINE__);
2298#endif
2299
2300	apply = item->apply;
2301	depth = item->depth;
2302
2303	switch (item->el_flags & NGQF_TYPE) {
2304	case NGQF_DATA:
2305		/*
2306		 * Check things are still ok as when we were queued.
2307		 */
2308		KASSERT(hook != NULL, ("ng_apply_item: hook for data is NULL"));
2309		if (NG_HOOK_NOT_VALID(hook) ||
2310		    NG_NODE_NOT_VALID(node)) {
2311			error = EIO;
2312			NG_FREE_ITEM(item);
2313			break;
2314		}
2315		/*
2316		 * If no receive method, just silently drop it.
2317		 * Give preference to the hook over-ride method.
2318		 */
2319		if ((!(rcvdata = hook->hk_rcvdata)) &&
2320		    (!(rcvdata = NG_HOOK_NODE(hook)->nd_type->rcvdata))) {
2321			error = 0;
2322			NG_FREE_ITEM(item);
2323			break;
2324		}
2325		error = (*rcvdata)(hook, item);
2326		break;
2327	case NGQF_MESG:
2328		if (hook && NG_HOOK_NOT_VALID(hook)) {
2329			/*
2330			 * The hook has been zapped then we can't use it.
2331			 * Immediately drop its reference.
2332			 * The message may not need it.
2333			 */
2334			NG_HOOK_UNREF(hook);
2335			hook = NULL;
2336		}
2337		/*
2338		 * Similarly, if the node is a zombie there is
2339		 * nothing we can do with it, drop everything.
2340		 */
2341		if (NG_NODE_NOT_VALID(node)) {
2342			TRAP_ERROR();
2343			error = EINVAL;
2344			NG_FREE_ITEM(item);
2345			break;
2346		}
2347		/*
2348		 * Call the appropriate message handler for the object.
2349		 * It is up to the message handler to free the message.
2350		 * If it's a generic message, handle it generically,
2351		 * otherwise call the type's message handler (if it exists).
2352		 * XXX (race). Remember that a queued message may
2353		 * reference a node or hook that has just been
2354		 * invalidated. It will exist as the queue code
2355		 * is holding a reference, but..
2356		 */
2357		if ((NGI_MSG(item)->header.typecookie == NGM_GENERIC_COOKIE) &&
2358		    ((NGI_MSG(item)->header.flags & NGF_RESP) == 0)) {
2359			error = ng_generic_msg(node, item, hook);
2360			break;
2361		}
2362		if (((!hook) || (!(rcvmsg = hook->hk_rcvmsg))) &&
2363		    (!(rcvmsg = node->nd_type->rcvmsg))) {
2364			TRAP_ERROR();
2365			error = 0;
2366			NG_FREE_ITEM(item);
2367			break;
2368		}
2369		error = (*rcvmsg)(node, item, hook);
2370		break;
2371	case NGQF_FN:
2372	case NGQF_FN2:
2373		/*
2374		 * In the case of the shutdown message we allow it to hit
2375		 * even if the node is invalid.
2376		 */
2377		if (NG_NODE_NOT_VALID(node) &&
2378		    NGI_FN(item) != &ng_rmnode) {
2379			TRAP_ERROR();
2380			error = EINVAL;
2381			NG_FREE_ITEM(item);
2382			break;
2383		}
2384		/* Same is about some internal functions and invalid hook. */
2385		if (hook && NG_HOOK_NOT_VALID(hook) &&
2386		    NGI_FN2(item) != &ng_con_part2 &&
2387		    NGI_FN2(item) != &ng_con_part3 &&
2388		    NGI_FN(item) != &ng_rmhook_part2) {
2389			TRAP_ERROR();
2390			error = EINVAL;
2391			NG_FREE_ITEM(item);
2392			break;
2393		}
2394
2395		if ((item->el_flags & NGQF_TYPE) == NGQF_FN) {
2396			(*NGI_FN(item))(node, hook, NGI_ARG1(item),
2397			    NGI_ARG2(item));
2398			NG_FREE_ITEM(item);
2399		} else	/* it is NGQF_FN2 */
2400			error = (*NGI_FN2(item))(node, item, hook);
2401		break;
2402	}
2403	/*
2404	 * We held references on some of the resources
2405	 * that we took from the item. Now that we have
2406	 * finished doing everything, drop those references.
2407	 */
2408	if (hook)
2409		NG_HOOK_UNREF(hook);
2410
2411 	if (rw == NGQRW_R)
2412		ng_leave_read(node);
2413	else
2414		ng_leave_write(node);
2415
2416	/* Apply callback. */
2417	if (apply != NULL) {
2418		if (depth == 1 && error != 0)
2419			apply->error = error;
2420		if (refcount_release(&apply->refs))
2421			(*apply->apply)(apply->context, apply->error);
2422	}
2423
2424	return (error);
2425}
2426
2427/***********************************************************************
2428 * Implement the 'generic' control messages
2429 ***********************************************************************/
2430static int
2431ng_generic_msg(node_p here, item_p item, hook_p lasthook)
2432{
2433	int error = 0;
2434	struct ng_mesg *msg;
2435	struct ng_mesg *resp = NULL;
2436
2437	NGI_GET_MSG(item, msg);
2438	if (msg->header.typecookie != NGM_GENERIC_COOKIE) {
2439		TRAP_ERROR();
2440		error = EINVAL;
2441		goto out;
2442	}
2443	switch (msg->header.cmd) {
2444	case NGM_SHUTDOWN:
2445		ng_rmnode(here, NULL, NULL, 0);
2446		break;
2447	case NGM_MKPEER:
2448	    {
2449		struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data;
2450
2451		if (msg->header.arglen != sizeof(*mkp)) {
2452			TRAP_ERROR();
2453			error = EINVAL;
2454			break;
2455		}
2456		mkp->type[sizeof(mkp->type) - 1] = '\0';
2457		mkp->ourhook[sizeof(mkp->ourhook) - 1] = '\0';
2458		mkp->peerhook[sizeof(mkp->peerhook) - 1] = '\0';
2459		error = ng_mkpeer(here, mkp->ourhook, mkp->peerhook, mkp->type);
2460		break;
2461	    }
2462	case NGM_CONNECT:
2463	    {
2464		struct ngm_connect *const con =
2465			(struct ngm_connect *) msg->data;
2466		node_p node2;
2467
2468		if (msg->header.arglen != sizeof(*con)) {
2469			TRAP_ERROR();
2470			error = EINVAL;
2471			break;
2472		}
2473		con->path[sizeof(con->path) - 1] = '\0';
2474		con->ourhook[sizeof(con->ourhook) - 1] = '\0';
2475		con->peerhook[sizeof(con->peerhook) - 1] = '\0';
2476		/* Don't forget we get a reference.. */
2477		error = ng_path2noderef(here, con->path, &node2, NULL);
2478		if (error)
2479			break;
2480		error = ng_con_nodes(item, here, con->ourhook,
2481		    node2, con->peerhook);
2482		NG_NODE_UNREF(node2);
2483		break;
2484	    }
2485	case NGM_NAME:
2486	    {
2487		struct ngm_name *const nam = (struct ngm_name *) msg->data;
2488
2489		if (msg->header.arglen != sizeof(*nam)) {
2490			TRAP_ERROR();
2491			error = EINVAL;
2492			break;
2493		}
2494		nam->name[sizeof(nam->name) - 1] = '\0';
2495		error = ng_name_node(here, nam->name);
2496		break;
2497	    }
2498	case NGM_RMHOOK:
2499	    {
2500		struct ngm_rmhook *const rmh = (struct ngm_rmhook *) msg->data;
2501		hook_p hook;
2502
2503		if (msg->header.arglen != sizeof(*rmh)) {
2504			TRAP_ERROR();
2505			error = EINVAL;
2506			break;
2507		}
2508		rmh->ourhook[sizeof(rmh->ourhook) - 1] = '\0';
2509		if ((hook = ng_findhook(here, rmh->ourhook)) != NULL)
2510			ng_destroy_hook(hook);
2511		break;
2512	    }
2513	case NGM_NODEINFO:
2514	    {
2515		struct nodeinfo *ni;
2516
2517		NG_MKRESPONSE(resp, msg, sizeof(*ni), M_NOWAIT);
2518		if (resp == NULL) {
2519			error = ENOMEM;
2520			break;
2521		}
2522
2523		/* Fill in node info */
2524		ni = (struct nodeinfo *) resp->data;
2525		if (NG_NODE_HAS_NAME(here))
2526			strcpy(ni->name, NG_NODE_NAME(here));
2527		strcpy(ni->type, here->nd_type->name);
2528		ni->id = ng_node2ID(here);
2529		ni->hooks = here->nd_numhooks;
2530		break;
2531	    }
2532	case NGM_LISTHOOKS:
2533	    {
2534		const int nhooks = here->nd_numhooks;
2535		struct hooklist *hl;
2536		struct nodeinfo *ni;
2537		hook_p hook;
2538
2539		/* Get response struct */
2540		NG_MKRESPONSE(resp, msg, sizeof(*hl) +
2541		    (nhooks * sizeof(struct linkinfo)), M_NOWAIT);
2542		if (resp == NULL) {
2543			error = ENOMEM;
2544			break;
2545		}
2546		hl = (struct hooklist *) resp->data;
2547		ni = &hl->nodeinfo;
2548
2549		/* Fill in node info */
2550		if (NG_NODE_HAS_NAME(here))
2551			strcpy(ni->name, NG_NODE_NAME(here));
2552		strcpy(ni->type, here->nd_type->name);
2553		ni->id = ng_node2ID(here);
2554
2555		/* Cycle through the linked list of hooks */
2556		ni->hooks = 0;
2557		LIST_FOREACH(hook, &here->nd_hooks, hk_hooks) {
2558			struct linkinfo *const link = &hl->link[ni->hooks];
2559
2560			if (ni->hooks >= nhooks) {
2561				log(LOG_ERR, "%s: number of %s changed\n",
2562				    __func__, "hooks");
2563				break;
2564			}
2565			if (NG_HOOK_NOT_VALID(hook))
2566				continue;
2567			strcpy(link->ourhook, NG_HOOK_NAME(hook));
2568			strcpy(link->peerhook, NG_PEER_HOOK_NAME(hook));
2569			if (NG_PEER_NODE_NAME(hook)[0] != '\0')
2570				strcpy(link->nodeinfo.name,
2571				    NG_PEER_NODE_NAME(hook));
2572			strcpy(link->nodeinfo.type,
2573			   NG_PEER_NODE(hook)->nd_type->name);
2574			link->nodeinfo.id = ng_node2ID(NG_PEER_NODE(hook));
2575			link->nodeinfo.hooks = NG_PEER_NODE(hook)->nd_numhooks;
2576			ni->hooks++;
2577		}
2578		break;
2579	    }
2580
2581	case NGM_LISTNAMES:
2582	case NGM_LISTNODES:
2583	    {
2584		const int unnamed = (msg->header.cmd == NGM_LISTNODES);
2585		struct namelist *nl;
2586		node_p node;
2587		int num = 0, i;
2588
2589		NAMEHASH_RLOCK();
2590		/* Count number of nodes */
2591		for (i = 0; i < NG_NAME_HASH_SIZE; i++) {
2592			LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) {
2593				if (NG_NODE_IS_VALID(node) &&
2594				    (unnamed || NG_NODE_HAS_NAME(node))) {
2595					num++;
2596				}
2597			}
2598		}
2599
2600		/* Get response struct */
2601		NG_MKRESPONSE(resp, msg, sizeof(*nl) +
2602		    (num * sizeof(struct nodeinfo)), M_NOWAIT);
2603		if (resp == NULL) {
2604			NAMEHASH_RUNLOCK();
2605			error = ENOMEM;
2606			break;
2607		}
2608		nl = (struct namelist *) resp->data;
2609
2610		/* Cycle through the linked list of nodes */
2611		nl->numnames = 0;
2612		for (i = 0; i < NG_NAME_HASH_SIZE; i++) {
2613			LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) {
2614				struct nodeinfo *const np =
2615				    &nl->nodeinfo[nl->numnames];
2616
2617				if (NG_NODE_NOT_VALID(node))
2618					continue;
2619				if (!unnamed && (! NG_NODE_HAS_NAME(node)))
2620					continue;
2621				if (NG_NODE_HAS_NAME(node))
2622					strcpy(np->name, NG_NODE_NAME(node));
2623				strcpy(np->type, node->nd_type->name);
2624				np->id = ng_node2ID(node);
2625				np->hooks = node->nd_numhooks;
2626				KASSERT(nl->numnames < num, ("%s: no space",
2627				    __func__));
2628				nl->numnames++;
2629			}
2630		}
2631		NAMEHASH_RUNLOCK();
2632		break;
2633	    }
2634
2635	case NGM_LISTTYPES:
2636	    {
2637		struct typelist *tl;
2638		struct ng_type *type;
2639		int num = 0;
2640
2641		TYPELIST_RLOCK();
2642		/* Count number of types */
2643		LIST_FOREACH(type, &ng_typelist, types)
2644			num++;
2645
2646		/* Get response struct */
2647		NG_MKRESPONSE(resp, msg, sizeof(*tl) +
2648		    (num * sizeof(struct typeinfo)), M_NOWAIT);
2649		if (resp == NULL) {
2650			TYPELIST_RUNLOCK();
2651			error = ENOMEM;
2652			break;
2653		}
2654		tl = (struct typelist *) resp->data;
2655
2656		/* Cycle through the linked list of types */
2657		tl->numtypes = 0;
2658		LIST_FOREACH(type, &ng_typelist, types) {
2659			struct typeinfo *const tp = &tl->typeinfo[tl->numtypes];
2660
2661			strcpy(tp->type_name, type->name);
2662			tp->numnodes = type->refs - 1; /* don't count list */
2663			KASSERT(tl->numtypes < num, ("%s: no space", __func__));
2664			tl->numtypes++;
2665		}
2666		TYPELIST_RUNLOCK();
2667		break;
2668	    }
2669
2670	case NGM_BINARY2ASCII:
2671	    {
2672		int bufSize = 20 * 1024;	/* XXX hard coded constant */
2673		const struct ng_parse_type *argstype;
2674		const struct ng_cmdlist *c;
2675		struct ng_mesg *binary, *ascii;
2676
2677		/* Data area must contain a valid netgraph message */
2678		binary = (struct ng_mesg *)msg->data;
2679		if (msg->header.arglen < sizeof(struct ng_mesg) ||
2680		    (msg->header.arglen - sizeof(struct ng_mesg) <
2681		    binary->header.arglen)) {
2682			TRAP_ERROR();
2683			error = EINVAL;
2684			break;
2685		}
2686
2687		/* Get a response message with lots of room */
2688		NG_MKRESPONSE(resp, msg, sizeof(*ascii) + bufSize, M_NOWAIT);
2689		if (resp == NULL) {
2690			error = ENOMEM;
2691			break;
2692		}
2693		ascii = (struct ng_mesg *)resp->data;
2694
2695		/* Copy binary message header to response message payload */
2696		bcopy(binary, ascii, sizeof(*binary));
2697
2698		/* Find command by matching typecookie and command number */
2699		for (c = here->nd_type->cmdlist; c != NULL && c->name != NULL;
2700		    c++) {
2701			if (binary->header.typecookie == c->cookie &&
2702			    binary->header.cmd == c->cmd)
2703				break;
2704		}
2705		if (c == NULL || c->name == NULL) {
2706			for (c = ng_generic_cmds; c->name != NULL; c++) {
2707				if (binary->header.typecookie == c->cookie &&
2708				    binary->header.cmd == c->cmd)
2709					break;
2710			}
2711			if (c->name == NULL) {
2712				NG_FREE_MSG(resp);
2713				error = ENOSYS;
2714				break;
2715			}
2716		}
2717
2718		/* Convert command name to ASCII */
2719		snprintf(ascii->header.cmdstr, sizeof(ascii->header.cmdstr),
2720		    "%s", c->name);
2721
2722		/* Convert command arguments to ASCII */
2723		argstype = (binary->header.flags & NGF_RESP) ?
2724		    c->respType : c->mesgType;
2725		if (argstype == NULL) {
2726			*ascii->data = '\0';
2727		} else {
2728			if ((error = ng_unparse(argstype,
2729			    (u_char *)binary->data,
2730			    ascii->data, bufSize)) != 0) {
2731				NG_FREE_MSG(resp);
2732				break;
2733			}
2734		}
2735
2736		/* Return the result as struct ng_mesg plus ASCII string */
2737		bufSize = strlen(ascii->data) + 1;
2738		ascii->header.arglen = bufSize;
2739		resp->header.arglen = sizeof(*ascii) + bufSize;
2740		break;
2741	    }
2742
2743	case NGM_ASCII2BINARY:
2744	    {
2745		int bufSize = 20 * 1024;	/* XXX hard coded constant */
2746		const struct ng_cmdlist *c;
2747		const struct ng_parse_type *argstype;
2748		struct ng_mesg *ascii, *binary;
2749		int off = 0;
2750
2751		/* Data area must contain at least a struct ng_mesg + '\0' */
2752		ascii = (struct ng_mesg *)msg->data;
2753		if ((msg->header.arglen < sizeof(*ascii) + 1) ||
2754		    (ascii->header.arglen < 1) ||
2755		    (msg->header.arglen < sizeof(*ascii) +
2756		    ascii->header.arglen)) {
2757			TRAP_ERROR();
2758			error = EINVAL;
2759			break;
2760		}
2761		ascii->data[ascii->header.arglen - 1] = '\0';
2762
2763		/* Get a response message with lots of room */
2764		NG_MKRESPONSE(resp, msg, sizeof(*binary) + bufSize, M_NOWAIT);
2765		if (resp == NULL) {
2766			error = ENOMEM;
2767			break;
2768		}
2769		binary = (struct ng_mesg *)resp->data;
2770
2771		/* Copy ASCII message header to response message payload */
2772		bcopy(ascii, binary, sizeof(*ascii));
2773
2774		/* Find command by matching ASCII command string */
2775		for (c = here->nd_type->cmdlist;
2776		    c != NULL && c->name != NULL; c++) {
2777			if (strcmp(ascii->header.cmdstr, c->name) == 0)
2778				break;
2779		}
2780		if (c == NULL || c->name == NULL) {
2781			for (c = ng_generic_cmds; c->name != NULL; c++) {
2782				if (strcmp(ascii->header.cmdstr, c->name) == 0)
2783					break;
2784			}
2785			if (c->name == NULL) {
2786				NG_FREE_MSG(resp);
2787				error = ENOSYS;
2788				break;
2789			}
2790		}
2791
2792		/* Convert command name to binary */
2793		binary->header.cmd = c->cmd;
2794		binary->header.typecookie = c->cookie;
2795
2796		/* Convert command arguments to binary */
2797		argstype = (binary->header.flags & NGF_RESP) ?
2798		    c->respType : c->mesgType;
2799		if (argstype == NULL) {
2800			bufSize = 0;
2801		} else {
2802			if ((error = ng_parse(argstype, ascii->data, &off,
2803			    (u_char *)binary->data, &bufSize)) != 0) {
2804				NG_FREE_MSG(resp);
2805				break;
2806			}
2807		}
2808
2809		/* Return the result */
2810		binary->header.arglen = bufSize;
2811		resp->header.arglen = sizeof(*binary) + bufSize;
2812		break;
2813	    }
2814
2815	case NGM_TEXT_CONFIG:
2816	case NGM_TEXT_STATUS:
2817		/*
2818		 * This one is tricky as it passes the command down to the
2819		 * actual node, even though it is a generic type command.
2820		 * This means we must assume that the item/msg is already freed
2821		 * when control passes back to us.
2822		 */
2823		if (here->nd_type->rcvmsg != NULL) {
2824			NGI_MSG(item) = msg; /* put it back as we found it */
2825			return((*here->nd_type->rcvmsg)(here, item, lasthook));
2826		}
2827		/* Fall through if rcvmsg not supported */
2828	default:
2829		TRAP_ERROR();
2830		error = EINVAL;
2831	}
2832	/*
2833	 * Sometimes a generic message may be statically allocated
2834	 * to avoid problems with allocating when in tight memory situations.
2835	 * Don't free it if it is so.
2836	 * I break them appart here, because erros may cause a free if the item
2837	 * in which case we'd be doing it twice.
2838	 * they are kept together above, to simplify freeing.
2839	 */
2840out:
2841	NG_RESPOND_MSG(error, here, item, resp);
2842	NG_FREE_MSG(msg);
2843	return (error);
2844}
2845
2846/************************************************************************
2847			Queue element get/free routines
2848************************************************************************/
2849
2850uma_zone_t			ng_qzone;
2851uma_zone_t			ng_qdzone;
2852static int			numthreads = 0; /* number of queue threads */
2853static int			maxalloc = 4096;/* limit the damage of a leak */
2854static int			maxdata = 512;	/* limit the damage of a DoS */
2855
2856TUNABLE_INT("net.graph.threads", &numthreads);
2857SYSCTL_INT(_net_graph, OID_AUTO, threads, CTLFLAG_RDTUN, &numthreads,
2858    0, "Number of queue processing threads");
2859TUNABLE_INT("net.graph.maxalloc", &maxalloc);
2860SYSCTL_INT(_net_graph, OID_AUTO, maxalloc, CTLFLAG_RDTUN, &maxalloc,
2861    0, "Maximum number of non-data queue items to allocate");
2862TUNABLE_INT("net.graph.maxdata", &maxdata);
2863SYSCTL_INT(_net_graph, OID_AUTO, maxdata, CTLFLAG_RDTUN, &maxdata,
2864    0, "Maximum number of data queue items to allocate");
2865
2866#ifdef	NETGRAPH_DEBUG
2867static TAILQ_HEAD(, ng_item) ng_itemlist = TAILQ_HEAD_INITIALIZER(ng_itemlist);
2868static int allocated;	/* number of items malloc'd */
2869#endif
2870
2871/*
2872 * Get a queue entry.
2873 * This is usually called when a packet first enters netgraph.
2874 * By definition, this is usually from an interrupt, or from a user.
2875 * Users are not so important, but try be quick for the times that it's
2876 * an interrupt.
2877 */
2878static __inline item_p
2879ng_alloc_item(int type, int flags)
2880{
2881	item_p item;
2882
2883	KASSERT(((type & ~NGQF_TYPE) == 0),
2884	    ("%s: incorrect item type: %d", __func__, type));
2885
2886	item = uma_zalloc((type == NGQF_DATA) ? ng_qdzone : ng_qzone,
2887	    ((flags & NG_WAITOK) ? M_WAITOK : M_NOWAIT) | M_ZERO);
2888
2889	if (item) {
2890		item->el_flags = type;
2891#ifdef	NETGRAPH_DEBUG
2892		mtx_lock(&ngq_mtx);
2893		TAILQ_INSERT_TAIL(&ng_itemlist, item, all);
2894		allocated++;
2895		mtx_unlock(&ngq_mtx);
2896#endif
2897	}
2898
2899	return (item);
2900}
2901
2902/*
2903 * Release a queue entry
2904 */
2905void
2906ng_free_item(item_p item)
2907{
2908	/*
2909	 * The item may hold resources on it's own. We need to free
2910	 * these before we can free the item. What they are depends upon
2911	 * what kind of item it is. it is important that nodes zero
2912	 * out pointers to resources that they remove from the item
2913	 * or we release them again here.
2914	 */
2915	switch (item->el_flags & NGQF_TYPE) {
2916	case NGQF_DATA:
2917		/* If we have an mbuf still attached.. */
2918		NG_FREE_M(_NGI_M(item));
2919		break;
2920	case NGQF_MESG:
2921		_NGI_RETADDR(item) = 0;
2922		NG_FREE_MSG(_NGI_MSG(item));
2923		break;
2924	case NGQF_FN:
2925	case NGQF_FN2:
2926		/* nothing to free really, */
2927		_NGI_FN(item) = NULL;
2928		_NGI_ARG1(item) = NULL;
2929		_NGI_ARG2(item) = 0;
2930		break;
2931	}
2932	/* If we still have a node or hook referenced... */
2933	_NGI_CLR_NODE(item);
2934	_NGI_CLR_HOOK(item);
2935
2936#ifdef	NETGRAPH_DEBUG
2937	mtx_lock(&ngq_mtx);
2938	TAILQ_REMOVE(&ng_itemlist, item, all);
2939	allocated--;
2940	mtx_unlock(&ngq_mtx);
2941#endif
2942	uma_zfree(((item->el_flags & NGQF_TYPE) == NGQF_DATA) ?
2943	    ng_qdzone : ng_qzone, item);
2944}
2945
2946/*
2947 * Change type of the queue entry.
2948 * Possibly reallocates it from another UMA zone.
2949 */
2950static __inline item_p
2951ng_realloc_item(item_p pitem, int type, int flags)
2952{
2953	item_p item;
2954	int from, to;
2955
2956	KASSERT((pitem != NULL), ("%s: can't reallocate NULL", __func__));
2957	KASSERT(((type & ~NGQF_TYPE) == 0),
2958	    ("%s: incorrect item type: %d", __func__, type));
2959
2960	from = ((pitem->el_flags & NGQF_TYPE) == NGQF_DATA);
2961	to = (type == NGQF_DATA);
2962	if (from != to) {
2963		/* If reallocation is required do it and copy item. */
2964		if ((item = ng_alloc_item(type, flags)) == NULL) {
2965			ng_free_item(pitem);
2966			return (NULL);
2967		}
2968		*item = *pitem;
2969		ng_free_item(pitem);
2970	} else
2971		item = pitem;
2972	item->el_flags = (item->el_flags & ~NGQF_TYPE) | type;
2973
2974	return (item);
2975}
2976
2977/************************************************************************
2978			Module routines
2979************************************************************************/
2980
2981/*
2982 * Handle the loading/unloading of a netgraph node type module
2983 */
2984int
2985ng_mod_event(module_t mod, int event, void *data)
2986{
2987	struct ng_type *const type = data;
2988	int error = 0;
2989
2990	switch (event) {
2991	case MOD_LOAD:
2992
2993		/* Register new netgraph node type */
2994		if ((error = ng_newtype(type)) != 0)
2995			break;
2996
2997		/* Call type specific code */
2998		if (type->mod_event != NULL)
2999			if ((error = (*type->mod_event)(mod, event, data))) {
3000				TYPELIST_WLOCK();
3001				type->refs--;	/* undo it */
3002				LIST_REMOVE(type, types);
3003				TYPELIST_WUNLOCK();
3004			}
3005		break;
3006
3007	case MOD_UNLOAD:
3008		if (type->refs > 1) {		/* make sure no nodes exist! */
3009			error = EBUSY;
3010		} else {
3011			if (type->refs == 0) /* failed load, nothing to undo */
3012				break;
3013			if (type->mod_event != NULL) {	/* check with type */
3014				error = (*type->mod_event)(mod, event, data);
3015				if (error != 0)	/* type refuses.. */
3016					break;
3017			}
3018			TYPELIST_WLOCK();
3019			LIST_REMOVE(type, types);
3020			TYPELIST_WUNLOCK();
3021		}
3022		break;
3023
3024	default:
3025		if (type->mod_event != NULL)
3026			error = (*type->mod_event)(mod, event, data);
3027		else
3028			error = EOPNOTSUPP;		/* XXX ? */
3029		break;
3030	}
3031	return (error);
3032}
3033
3034#ifdef VIMAGE
3035static void
3036vnet_netgraph_uninit(const void *unused __unused)
3037{
3038	node_p node = NULL, last_killed = NULL;
3039	int i;
3040
3041	do {
3042		/* Find a node to kill */
3043		NAMEHASH_RLOCK();
3044		for (i = 0; i < NG_NAME_HASH_SIZE; i++) {
3045			LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) {
3046				if (node != &ng_deadnode) {
3047					NG_NODE_REF(node);
3048					break;
3049				}
3050			}
3051			if (node != NULL)
3052				break;
3053		}
3054		NAMEHASH_RUNLOCK();
3055
3056		/* Attempt to kill it only if it is a regular node */
3057		if (node != NULL) {
3058			if (node == last_killed) {
3059				/* This should never happen */
3060				printf("ng node %s needs NGF_REALLY_DIE\n",
3061				    node->nd_name);
3062				if (node->nd_flags & NGF_REALLY_DIE)
3063					panic("ng node %s won't die",
3064					    node->nd_name);
3065				node->nd_flags |= NGF_REALLY_DIE;
3066			}
3067			ng_rmnode(node, NULL, NULL, 0);
3068			NG_NODE_UNREF(node);
3069			last_killed = node;
3070		}
3071	} while (node != NULL);
3072}
3073VNET_SYSUNINIT(vnet_netgraph_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
3074    vnet_netgraph_uninit, NULL);
3075#endif /* VIMAGE */
3076
3077/*
3078 * Handle loading and unloading for this code.
3079 * The only thing we need to link into is the NETISR strucure.
3080 */
3081static int
3082ngb_mod_event(module_t mod, int event, void *data)
3083{
3084	struct proc *p;
3085	struct thread *td;
3086	int i, error = 0;
3087
3088	switch (event) {
3089	case MOD_LOAD:
3090		/* Initialize everything. */
3091		NG_WORKLIST_LOCK_INIT();
3092		rw_init(&ng_typelist_lock, "netgraph types");
3093		rw_init(&ng_idhash_lock, "netgraph idhash");
3094		rw_init(&ng_namehash_lock, "netgraph namehash");
3095		mtx_init(&ng_topo_mtx, "netgraph topology mutex", NULL,
3096		    MTX_DEF);
3097#ifdef	NETGRAPH_DEBUG
3098		mtx_init(&ng_nodelist_mtx, "netgraph nodelist mutex", NULL,
3099		    MTX_DEF);
3100		mtx_init(&ngq_mtx, "netgraph item list mutex", NULL,
3101		    MTX_DEF);
3102#endif
3103		ng_qzone = uma_zcreate("NetGraph items", sizeof(struct ng_item),
3104		    NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
3105		uma_zone_set_max(ng_qzone, maxalloc);
3106		ng_qdzone = uma_zcreate("NetGraph data items",
3107		    sizeof(struct ng_item), NULL, NULL, NULL, NULL,
3108		    UMA_ALIGN_CACHE, 0);
3109		uma_zone_set_max(ng_qdzone, maxdata);
3110		/* Autoconfigure number of threads. */
3111		if (numthreads <= 0)
3112			numthreads = mp_ncpus;
3113		/* Create threads. */
3114    		p = NULL; /* start with no process */
3115		for (i = 0; i < numthreads; i++) {
3116			if (kproc_kthread_add(ngthread, NULL, &p, &td,
3117			    RFHIGHPID, 0, "ng_queue", "ng_queue%d", i)) {
3118				numthreads = i;
3119				break;
3120			}
3121		}
3122		break;
3123	case MOD_UNLOAD:
3124		/* You can't unload it because an interface may be using it. */
3125		error = EBUSY;
3126		break;
3127	default:
3128		error = EOPNOTSUPP;
3129		break;
3130	}
3131	return (error);
3132}
3133
3134static moduledata_t netgraph_mod = {
3135	"netgraph",
3136	ngb_mod_event,
3137	(NULL)
3138};
3139DECLARE_MODULE(netgraph, netgraph_mod, SI_SUB_NETGRAPH, SI_ORDER_MIDDLE);
3140SYSCTL_NODE(_net, OID_AUTO, graph, CTLFLAG_RW, 0, "netgraph Family");
3141SYSCTL_INT(_net_graph, OID_AUTO, abi_version, CTLFLAG_RD, 0, NG_ABI_VERSION,"");
3142SYSCTL_INT(_net_graph, OID_AUTO, msg_version, CTLFLAG_RD, 0, NG_VERSION, "");
3143
3144#ifdef	NETGRAPH_DEBUG
3145void
3146dumphook (hook_p hook, char *file, int line)
3147{
3148	printf("hook: name %s, %d refs, Last touched:\n",
3149		_NG_HOOK_NAME(hook), hook->hk_refs);
3150	printf("	Last active @ %s, line %d\n",
3151		hook->lastfile, hook->lastline);
3152	if (line) {
3153		printf(" problem discovered at file %s, line %d\n", file, line);
3154#ifdef KDB
3155		kdb_backtrace();
3156#endif
3157	}
3158}
3159
3160void
3161dumpnode(node_p node, char *file, int line)
3162{
3163	printf("node: ID [%x]: type '%s', %d hooks, flags 0x%x, %d refs, %s:\n",
3164		_NG_NODE_ID(node), node->nd_type->name,
3165		node->nd_numhooks, node->nd_flags,
3166		node->nd_refs, node->nd_name);
3167	printf("	Last active @ %s, line %d\n",
3168		node->lastfile, node->lastline);
3169	if (line) {
3170		printf(" problem discovered at file %s, line %d\n", file, line);
3171#ifdef KDB
3172		kdb_backtrace();
3173#endif
3174	}
3175}
3176
3177void
3178dumpitem(item_p item, char *file, int line)
3179{
3180	printf(" ACTIVE item, last used at %s, line %d",
3181		item->lastfile, item->lastline);
3182	switch(item->el_flags & NGQF_TYPE) {
3183	case NGQF_DATA:
3184		printf(" - [data]\n");
3185		break;
3186	case NGQF_MESG:
3187		printf(" - retaddr[%d]:\n", _NGI_RETADDR(item));
3188		break;
3189	case NGQF_FN:
3190		printf(" - fn@%p (%p, %p, %p, %d (%x))\n",
3191			_NGI_FN(item),
3192			_NGI_NODE(item),
3193			_NGI_HOOK(item),
3194			item->body.fn.fn_arg1,
3195			item->body.fn.fn_arg2,
3196			item->body.fn.fn_arg2);
3197		break;
3198	case NGQF_FN2:
3199		printf(" - fn2@%p (%p, %p, %p, %d (%x))\n",
3200			_NGI_FN2(item),
3201			_NGI_NODE(item),
3202			_NGI_HOOK(item),
3203			item->body.fn.fn_arg1,
3204			item->body.fn.fn_arg2,
3205			item->body.fn.fn_arg2);
3206		break;
3207	}
3208	if (line) {
3209		printf(" problem discovered at file %s, line %d\n", file, line);
3210		if (_NGI_NODE(item)) {
3211			printf("node %p ([%x])\n",
3212				_NGI_NODE(item), ng_node2ID(_NGI_NODE(item)));
3213		}
3214	}
3215}
3216
3217static void
3218ng_dumpitems(void)
3219{
3220	item_p item;
3221	int i = 1;
3222	TAILQ_FOREACH(item, &ng_itemlist, all) {
3223		printf("[%d] ", i++);
3224		dumpitem(item, NULL, 0);
3225	}
3226}
3227
3228static void
3229ng_dumpnodes(void)
3230{
3231	node_p node;
3232	int i = 1;
3233	mtx_lock(&ng_nodelist_mtx);
3234	SLIST_FOREACH(node, &ng_allnodes, nd_all) {
3235		printf("[%d] ", i++);
3236		dumpnode(node, NULL, 0);
3237	}
3238	mtx_unlock(&ng_nodelist_mtx);
3239}
3240
3241static void
3242ng_dumphooks(void)
3243{
3244	hook_p hook;
3245	int i = 1;
3246	mtx_lock(&ng_nodelist_mtx);
3247	SLIST_FOREACH(hook, &ng_allhooks, hk_all) {
3248		printf("[%d] ", i++);
3249		dumphook(hook, NULL, 0);
3250	}
3251	mtx_unlock(&ng_nodelist_mtx);
3252}
3253
3254static int
3255sysctl_debug_ng_dump_items(SYSCTL_HANDLER_ARGS)
3256{
3257	int error;
3258	int val;
3259	int i;
3260
3261	val = allocated;
3262	i = 1;
3263	error = sysctl_handle_int(oidp, &val, 0, req);
3264	if (error != 0 || req->newptr == NULL)
3265		return (error);
3266	if (val == 42) {
3267		ng_dumpitems();
3268		ng_dumpnodes();
3269		ng_dumphooks();
3270	}
3271	return (0);
3272}
3273
3274SYSCTL_PROC(_debug, OID_AUTO, ng_dump_items, CTLTYPE_INT | CTLFLAG_RW,
3275    0, sizeof(int), sysctl_debug_ng_dump_items, "I", "Number of allocated items");
3276#endif	/* NETGRAPH_DEBUG */
3277
3278
3279/***********************************************************************
3280* Worklist routines
3281**********************************************************************/
3282/*
3283 * Pick a node off the list of nodes with work,
3284 * try get an item to process off it. Remove the node from the list.
3285 */
3286static void
3287ngthread(void *arg)
3288{
3289	for (;;) {
3290		node_p  node;
3291
3292		/* Get node from the worklist. */
3293		NG_WORKLIST_LOCK();
3294		while ((node = STAILQ_FIRST(&ng_worklist)) == NULL)
3295			NG_WORKLIST_SLEEP();
3296		STAILQ_REMOVE_HEAD(&ng_worklist, nd_input_queue.q_work);
3297		NG_WORKLIST_UNLOCK();
3298		CURVNET_SET(node->nd_vnet);
3299		CTR3(KTR_NET, "%20s: node [%x] (%p) taken off worklist",
3300		    __func__, node->nd_ID, node);
3301		/*
3302		 * We have the node. We also take over the reference
3303		 * that the list had on it.
3304		 * Now process as much as you can, until it won't
3305		 * let you have another item off the queue.
3306		 * All this time, keep the reference
3307		 * that lets us be sure that the node still exists.
3308		 * Let the reference go at the last minute.
3309		 */
3310		for (;;) {
3311			item_p item;
3312			int rw;
3313
3314			NG_QUEUE_LOCK(&node->nd_input_queue);
3315			item = ng_dequeue(node, &rw);
3316			if (item == NULL) {
3317				node->nd_input_queue.q_flags2 &= ~NGQ2_WORKQ;
3318				NG_QUEUE_UNLOCK(&node->nd_input_queue);
3319				break; /* go look for another node */
3320			} else {
3321				NG_QUEUE_UNLOCK(&node->nd_input_queue);
3322				NGI_GET_NODE(item, node); /* zaps stored node */
3323				ng_apply_item(node, item, rw);
3324				NG_NODE_UNREF(node);
3325			}
3326		}
3327		NG_NODE_UNREF(node);
3328		CURVNET_RESTORE();
3329	}
3330}
3331
3332/*
3333 * XXX
3334 * It's posible that a debugging NG_NODE_REF may need
3335 * to be outside the mutex zone
3336 */
3337static void
3338ng_worklist_add(node_p node)
3339{
3340
3341	mtx_assert(&node->nd_input_queue.q_mtx, MA_OWNED);
3342
3343	if ((node->nd_input_queue.q_flags2 & NGQ2_WORKQ) == 0) {
3344		/*
3345		 * If we are not already on the work queue,
3346		 * then put us on.
3347		 */
3348		node->nd_input_queue.q_flags2 |= NGQ2_WORKQ;
3349		NG_NODE_REF(node); /* XXX safe in mutex? */
3350		NG_WORKLIST_LOCK();
3351		STAILQ_INSERT_TAIL(&ng_worklist, node, nd_input_queue.q_work);
3352		NG_WORKLIST_UNLOCK();
3353		CTR3(KTR_NET, "%20s: node [%x] (%p) put on worklist", __func__,
3354		    node->nd_ID, node);
3355		NG_WORKLIST_WAKEUP();
3356	} else {
3357		CTR3(KTR_NET, "%20s: node [%x] (%p) already on worklist",
3358		    __func__, node->nd_ID, node);
3359	}
3360}
3361
3362
3363/***********************************************************************
3364* Externally useable functions to set up a queue item ready for sending
3365***********************************************************************/
3366
3367#ifdef	NETGRAPH_DEBUG
3368#define	ITEM_DEBUG_CHECKS						\
3369	do {								\
3370		if (NGI_NODE(item) ) {					\
3371			printf("item already has node");		\
3372			kdb_enter(KDB_WHY_NETGRAPH, "has node");	\
3373			NGI_CLR_NODE(item);				\
3374		}							\
3375		if (NGI_HOOK(item) ) {					\
3376			printf("item already has hook");		\
3377			kdb_enter(KDB_WHY_NETGRAPH, "has hook");	\
3378			NGI_CLR_HOOK(item);				\
3379		}							\
3380	} while (0)
3381#else
3382#define ITEM_DEBUG_CHECKS
3383#endif
3384
3385/*
3386 * Put mbuf into the item.
3387 * Hook and node references will be removed when the item is dequeued.
3388 * (or equivalent)
3389 * (XXX) Unsafe because no reference held by peer on remote node.
3390 * remote node might go away in this timescale.
3391 * We know the hooks can't go away because that would require getting
3392 * a writer item on both nodes and we must have at least a  reader
3393 * here to be able to do this.
3394 * Note that the hook loaded is the REMOTE hook.
3395 *
3396 * This is possibly in the critical path for new data.
3397 */
3398item_p
3399ng_package_data(struct mbuf *m, int flags)
3400{
3401	item_p item;
3402
3403	if ((item = ng_alloc_item(NGQF_DATA, flags)) == NULL) {
3404		NG_FREE_M(m);
3405		return (NULL);
3406	}
3407	ITEM_DEBUG_CHECKS;
3408	item->el_flags |= NGQF_READER;
3409	NGI_M(item) = m;
3410	return (item);
3411}
3412
3413/*
3414 * Allocate a queue item and put items into it..
3415 * Evaluate the address as this will be needed to queue it and
3416 * to work out what some of the fields should be.
3417 * Hook and node references will be removed when the item is dequeued.
3418 * (or equivalent)
3419 */
3420item_p
3421ng_package_msg(struct ng_mesg *msg, int flags)
3422{
3423	item_p item;
3424
3425	if ((item = ng_alloc_item(NGQF_MESG, flags)) == NULL) {
3426		NG_FREE_MSG(msg);
3427		return (NULL);
3428	}
3429	ITEM_DEBUG_CHECKS;
3430	/* Messages items count as writers unless explicitly exempted. */
3431	if (msg->header.cmd & NGM_READONLY)
3432		item->el_flags |= NGQF_READER;
3433	else
3434		item->el_flags |= NGQF_WRITER;
3435	/*
3436	 * Set the current lasthook into the queue item
3437	 */
3438	NGI_MSG(item) = msg;
3439	NGI_RETADDR(item) = 0;
3440	return (item);
3441}
3442
3443
3444
3445#define SET_RETADDR(item, here, retaddr)				\
3446	do {	/* Data or fn items don't have retaddrs */		\
3447		if ((item->el_flags & NGQF_TYPE) == NGQF_MESG) {	\
3448			if (retaddr) {					\
3449				NGI_RETADDR(item) = retaddr;		\
3450			} else {					\
3451				/*					\
3452				 * The old return address should be ok.	\
3453				 * If there isn't one, use the address	\
3454				 * here.				\
3455				 */					\
3456				if (NGI_RETADDR(item) == 0) {		\
3457					NGI_RETADDR(item)		\
3458						= ng_node2ID(here);	\
3459				}					\
3460			}						\
3461		}							\
3462	} while (0)
3463
3464int
3465ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr)
3466{
3467	hook_p peer;
3468	node_p peernode;
3469	ITEM_DEBUG_CHECKS;
3470	/*
3471	 * Quick sanity check..
3472	 * Since a hook holds a reference on it's node, once we know
3473	 * that the peer is still connected (even if invalid,) we know
3474	 * that the peer node is present, though maybe invalid.
3475	 */
3476	mtx_lock(&ng_topo_mtx);
3477	if ((hook == NULL) || NG_HOOK_NOT_VALID(hook) ||
3478	    NG_HOOK_NOT_VALID(peer = NG_HOOK_PEER(hook)) ||
3479	    NG_NODE_NOT_VALID(peernode = NG_PEER_NODE(hook))) {
3480		NG_FREE_ITEM(item);
3481		TRAP_ERROR();
3482		mtx_unlock(&ng_topo_mtx);
3483		return (ENETDOWN);
3484	}
3485
3486	/*
3487	 * Transfer our interest to the other (peer) end.
3488	 */
3489	NG_HOOK_REF(peer);
3490	NG_NODE_REF(peernode);
3491	NGI_SET_HOOK(item, peer);
3492	NGI_SET_NODE(item, peernode);
3493	SET_RETADDR(item, here, retaddr);
3494
3495	mtx_unlock(&ng_topo_mtx);
3496
3497	return (0);
3498}
3499
3500int
3501ng_address_path(node_p here, item_p item, const char *address, ng_ID_t retaddr)
3502{
3503	node_p	dest = NULL;
3504	hook_p	hook = NULL;
3505	int	error;
3506
3507	ITEM_DEBUG_CHECKS;
3508	/*
3509	 * Note that ng_path2noderef increments the reference count
3510	 * on the node for us if it finds one. So we don't have to.
3511	 */
3512	error = ng_path2noderef(here, address, &dest, &hook);
3513	if (error) {
3514		NG_FREE_ITEM(item);
3515		return (error);
3516	}
3517	NGI_SET_NODE(item, dest);
3518	if (hook)
3519		NGI_SET_HOOK(item, hook);
3520
3521	SET_RETADDR(item, here, retaddr);
3522	return (0);
3523}
3524
3525int
3526ng_address_ID(node_p here, item_p item, ng_ID_t ID, ng_ID_t retaddr)
3527{
3528	node_p dest;
3529
3530	ITEM_DEBUG_CHECKS;
3531	/*
3532	 * Find the target node.
3533	 */
3534	dest = ng_ID2noderef(ID); /* GETS REFERENCE! */
3535	if (dest == NULL) {
3536		NG_FREE_ITEM(item);
3537		TRAP_ERROR();
3538		return(EINVAL);
3539	}
3540	/* Fill out the contents */
3541	NGI_SET_NODE(item, dest);
3542	NGI_CLR_HOOK(item);
3543	SET_RETADDR(item, here, retaddr);
3544	return (0);
3545}
3546
3547/*
3548 * special case to send a message to self (e.g. destroy node)
3549 * Possibly indicate an arrival hook too.
3550 * Useful for removing that hook :-)
3551 */
3552item_p
3553ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg)
3554{
3555	item_p item;
3556
3557	/*
3558	 * Find the target node.
3559	 * If there is a HOOK argument, then use that in preference
3560	 * to the address.
3561	 */
3562	if ((item = ng_alloc_item(NGQF_MESG, NG_NOFLAGS)) == NULL) {
3563		NG_FREE_MSG(msg);
3564		return (NULL);
3565	}
3566
3567	/* Fill out the contents */
3568	item->el_flags |= NGQF_WRITER;
3569	NG_NODE_REF(here);
3570	NGI_SET_NODE(item, here);
3571	if (hook) {
3572		NG_HOOK_REF(hook);
3573		NGI_SET_HOOK(item, hook);
3574	}
3575	NGI_MSG(item) = msg;
3576	NGI_RETADDR(item) = ng_node2ID(here);
3577	return (item);
3578}
3579
3580/*
3581 * Send ng_item_fn function call to the specified node.
3582 */
3583
3584int
3585ng_send_fn(node_p node, hook_p hook, ng_item_fn *fn, void * arg1, int arg2)
3586{
3587
3588	return ng_send_fn1(node, hook, fn, arg1, arg2, NG_NOFLAGS);
3589}
3590
3591int
3592ng_send_fn1(node_p node, hook_p hook, ng_item_fn *fn, void * arg1, int arg2,
3593	int flags)
3594{
3595	item_p item;
3596
3597	if ((item = ng_alloc_item(NGQF_FN, flags)) == NULL) {
3598		return (ENOMEM);
3599	}
3600	item->el_flags |= NGQF_WRITER;
3601	NG_NODE_REF(node); /* and one for the item */
3602	NGI_SET_NODE(item, node);
3603	if (hook) {
3604		NG_HOOK_REF(hook);
3605		NGI_SET_HOOK(item, hook);
3606	}
3607	NGI_FN(item) = fn;
3608	NGI_ARG1(item) = arg1;
3609	NGI_ARG2(item) = arg2;
3610	return(ng_snd_item(item, flags));
3611}
3612
3613/*
3614 * Send ng_item_fn2 function call to the specified node.
3615 *
3616 * If an optional pitem parameter is supplied, its apply
3617 * callback will be copied to the new item. If also NG_REUSE_ITEM
3618 * flag is set, no new item will be allocated, but pitem will
3619 * be used.
3620 */
3621int
3622ng_send_fn2(node_p node, hook_p hook, item_p pitem, ng_item_fn2 *fn, void *arg1,
3623	int arg2, int flags)
3624{
3625	item_p item;
3626
3627	KASSERT((pitem != NULL || (flags & NG_REUSE_ITEM) == 0),
3628	    ("%s: NG_REUSE_ITEM but no pitem", __func__));
3629
3630	/*
3631	 * Allocate a new item if no supplied or
3632	 * if we can't use supplied one.
3633	 */
3634	if (pitem == NULL || (flags & NG_REUSE_ITEM) == 0) {
3635		if ((item = ng_alloc_item(NGQF_FN2, flags)) == NULL)
3636			return (ENOMEM);
3637		if (pitem != NULL)
3638			item->apply = pitem->apply;
3639	} else {
3640		if ((item = ng_realloc_item(pitem, NGQF_FN2, flags)) == NULL)
3641			return (ENOMEM);
3642	}
3643
3644	item->el_flags = (item->el_flags & ~NGQF_RW) | NGQF_WRITER;
3645	NG_NODE_REF(node); /* and one for the item */
3646	NGI_SET_NODE(item, node);
3647	if (hook) {
3648		NG_HOOK_REF(hook);
3649		NGI_SET_HOOK(item, hook);
3650	}
3651	NGI_FN2(item) = fn;
3652	NGI_ARG1(item) = arg1;
3653	NGI_ARG2(item) = arg2;
3654	return(ng_snd_item(item, flags));
3655}
3656
3657/*
3658 * Official timeout routines for Netgraph nodes.
3659 */
3660static void
3661ng_callout_trampoline(void *arg)
3662{
3663	item_p item = arg;
3664
3665	CURVNET_SET(NGI_NODE(item)->nd_vnet);
3666	ng_snd_item(item, 0);
3667	CURVNET_RESTORE();
3668}
3669
3670
3671int
3672ng_callout(struct callout *c, node_p node, hook_p hook, int ticks,
3673    ng_item_fn *fn, void * arg1, int arg2)
3674{
3675	item_p item, oitem;
3676
3677	if ((item = ng_alloc_item(NGQF_FN, NG_NOFLAGS)) == NULL)
3678		return (ENOMEM);
3679
3680	item->el_flags |= NGQF_WRITER;
3681	NG_NODE_REF(node);		/* and one for the item */
3682	NGI_SET_NODE(item, node);
3683	if (hook) {
3684		NG_HOOK_REF(hook);
3685		NGI_SET_HOOK(item, hook);
3686	}
3687	NGI_FN(item) = fn;
3688	NGI_ARG1(item) = arg1;
3689	NGI_ARG2(item) = arg2;
3690	oitem = c->c_arg;
3691	if (callout_reset(c, ticks, &ng_callout_trampoline, item) == 1 &&
3692	    oitem != NULL)
3693		NG_FREE_ITEM(oitem);
3694	return (0);
3695}
3696
3697/* A special modified version of untimeout() */
3698int
3699ng_uncallout(struct callout *c, node_p node)
3700{
3701	item_p item;
3702	int rval;
3703
3704	KASSERT(c != NULL, ("ng_uncallout: NULL callout"));
3705	KASSERT(node != NULL, ("ng_uncallout: NULL node"));
3706
3707	rval = callout_stop(c);
3708	item = c->c_arg;
3709	/* Do an extra check */
3710	if ((rval > 0) && (c->c_func == &ng_callout_trampoline) &&
3711	    (NGI_NODE(item) == node)) {
3712		/*
3713		 * We successfully removed it from the queue before it ran
3714		 * So now we need to unreference everything that was
3715		 * given extra references. (NG_FREE_ITEM does this).
3716		 */
3717		NG_FREE_ITEM(item);
3718	}
3719	c->c_arg = NULL;
3720
3721	return (rval);
3722}
3723
3724/*
3725 * Set the address, if none given, give the node here.
3726 */
3727void
3728ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr)
3729{
3730	if (retaddr) {
3731		NGI_RETADDR(item) = retaddr;
3732	} else {
3733		/*
3734		 * The old return address should be ok.
3735		 * If there isn't one, use the address here.
3736		 */
3737		NGI_RETADDR(item) = ng_node2ID(here);
3738	}
3739}
3740