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