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