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