xref: /freebsd/sys/netgraph/netgraph.h (revision 5069714534cba67f1985e6dfe23b145178372b5f)
1 /*
2  * netgraph.h
3  *
4  * Copyright (c) 1996-1999 Whistle Communications, Inc.
5  * All rights reserved.
6  *
7  * Subject to the following obligations and disclaimer of warranty, use and
8  * redistribution of this software, in source or object code forms, with or
9  * without modifications are expressly permitted by Whistle Communications;
10  * provided, however, that:
11  * 1. Any and all reproductions of the source or object code must include the
12  *    copyright notice above and the following disclaimer of warranties; and
13  * 2. No rights are granted, in any manner or form, to use Whistle
14  *    Communications, Inc. trademarks, including the mark "WHISTLE
15  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
16  *    such appears in the above copyright notice or in the software.
17  *
18  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
19  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
20  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
21  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
23  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
24  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
25  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
26  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
27  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
28  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
29  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
34  * OF SUCH DAMAGE.
35  *
36  * Author: Julian Elischer <julian@freebsd.org>
37  *
38  * $FreeBSD$
39  * $Whistle: netgraph.h,v 1.29 1999/11/01 07:56:13 julian Exp $
40  */
41 
42 #ifndef _NETGRAPH_NETGRAPH_H_
43 #define _NETGRAPH_NETGRAPH_H_ 1
44 
45 #ifndef _KERNEL
46 #error "This file should not be included in user level programs"
47 #endif
48 
49 #include <sys/queue.h>
50 #include <sys/malloc.h>
51 #include <sys/module.h>
52 #include <sys/mutex.h>
53 /* debugging options */
54 #define NETGRAPH_DEBUG
55 #define NG_SEPARATE_MALLOC	/* make modules use their own malloc types */
56 
57 /*
58  * This defines the in-kernel binary interface version.
59  * It is possible to change this but leave the external message
60  * API the same. Each type also has it's own cookies for versioning as well.
61  * Change it for NETGRAPH_DEBUG version so we cannot mix debug and non debug
62  * modules.
63  */
64 #define _NG_ABI_VERSION 5
65 #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
66 #define NG_ABI_VERSION	(_NG_ABI_VERSION + 0x10000)
67 #else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
68 #define NG_ABI_VERSION	_NG_ABI_VERSION
69 #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
70 
71 
72 /*
73  * Forward references for the basic structures so we can
74  * define the typedefs and use them in the structures themselves.
75  */
76 struct ng_hook ;
77 struct ng_node ;
78 struct ng_item ;
79 typedef	struct ng_item *item_p;
80 typedef struct ng_node *node_p;
81 typedef struct ng_hook *hook_p;
82 
83 /***********************************************************************
84  ***************** Hook Structure and Methods **************************
85  ***********************************************************************
86  *
87  * Structure of a hook
88  */
89 struct ng_hook {
90 	char	hk_name[NG_HOOKLEN+1];	/* what this node knows this link as */
91 	void   *hk_private;		/* node dependant ID for this hook */
92 	int	hk_flags;		/* info about this hook/link */
93 	int	hk_refs;		/* dont actually free this till 0 */
94 	struct	ng_hook *hk_peer;	/* the other end of this link */
95 	struct	ng_node *hk_node;	/* The node this hook is attached to */
96 	LIST_ENTRY(ng_hook) hk_hooks;	/* linked list of all hooks on node */
97 #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
98 #define HK_MAGIC 0x78573011
99 	int	hk_magic;
100 	char	*lastfile;
101 	int	lastline;
102 	SLIST_ENTRY(ng_hook)	  hk_all;		/* all existing items */
103 #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
104 };
105 /* Flags for a hook */
106 #define HK_INVALID		0x0001	/* don't trust it! */
107 #define HK_QUEUE		0x0002	/* queue for later delivery */
108 #define HK_FORCE_WRITER		0x0004	/* Incoming data queued as a writer */
109 #define HK_DEAD			0x0008	/* This is the dead hook.. don't free */
110 
111 /*
112  * Public Methods for hook
113  * If you can't do it with these you probably shouldn;t be doing it.
114  */
115 void ng_unref_hook(hook_p hook); /* don't move this */
116 #define	_NG_HOOK_REF(hook)	atomic_add_int(&(hook)->hk_refs, 1)
117 #define _NG_HOOK_NAME(hook)	((hook)->hk_name)
118 #define _NG_HOOK_UNREF(hook)	ng_unref_hook(hook)
119 #define	_NG_HOOK_SET_PRIVATE(hook, val)	do {(hook)->hk_private = val;} while (0)
120 #define	_NG_HOOK_PRIVATE(hook)	((hook)->hk_private)
121 #define _NG_HOOK_NOT_VALID(hook)	((hook)->hk_flags & HK_INVALID)
122 #define _NG_HOOK_IS_VALID(hook)	(!(hook)->hk_flags & HK_INVALID)
123 #define _NG_HOOK_NODE(hook)	((hook)->hk_node) /* only rvalue! */
124 #define _NG_HOOK_PEER(hook)	((hook)->hk_peer) /* only rvalue! */
125 #define _NG_HOOK_FORCE_WRITER(hook)				\
126 		do { hook->hk_flags |= HK_FORCE_WRITER; } while (0)
127 #define _NG_HOOK_FORCE_QUEUE(hook) do { hook->hk_flags |= HK_QUEUE; } while (0)
128 
129 /* Some shortcuts */
130 #define NG_PEER_NODE(hook)	NG_HOOK_NODE(NG_HOOK_PEER(hook))
131 #define NG_PEER_HOOK_NAME(hook)	NG_HOOK_NAME(NG_HOOK_PEER(hook))
132 #define NG_PEER_NODE_NAME(hook)	NG_NODE_NAME(NG_PEER_NODE(hook))
133 
134 #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
135 #define _NN_ __FILE__,__LINE__
136 void	dumphook (hook_p hook, char *file, int line);
137 static __inline void	_chkhook(hook_p hook, char *file, int line);
138 static __inline void	_ng_hook_ref(hook_p hook, char * file, int line);
139 static __inline char *	_ng_hook_name(hook_p hook, char * file, int line);
140 static __inline void	_ng_hook_unref(hook_p hook, char * file, int line);
141 static __inline void	_ng_hook_set_private(hook_p hook,
142 					void * val, char * file, int line);
143 static __inline void *	_ng_hook_private(hook_p hook, char * file, int line);
144 static __inline int	_ng_hook_not_valid(hook_p hook, char * file, int line);
145 static __inline int	_ng_hook_is_valid(hook_p hook, char * file, int line);
146 static __inline node_p	_ng_hook_node(hook_p hook, char * file, int line);
147 static __inline hook_p	_ng_hook_peer(hook_p hook, char * file, int line);
148 static __inline void	_ng_hook_force_writer(hook_p hook, char * file,
149 					int line);
150 static __inline void	_ng_hook_force_queue(hook_p hook, char * file, int line);
151 
152 static void __inline
153 _chkhook(hook_p hook, char *file, int line)
154 {
155 	if (hook->hk_magic != HK_MAGIC) {
156 		printf("Accessing freed hook ");
157 		dumphook(hook, file, line);
158 	}
159 	hook->lastline = line;
160 	hook->lastfile = file;
161 }
162 
163 static __inline void
164 _ng_hook_ref(hook_p hook, char * file, int line)
165 {
166 	_chkhook(hook, file, line);
167 	_NG_HOOK_REF(hook);
168 }
169 
170 static __inline char *
171 _ng_hook_name(hook_p hook, char * file, int line)
172 {
173 	_chkhook(hook, file, line);
174 	return (_NG_HOOK_NAME(hook));
175 }
176 
177 static __inline void
178 _ng_hook_unref(hook_p hook, char * file, int line)
179 {
180 	_chkhook(hook, file, line);
181 	_NG_HOOK_UNREF(hook);
182 }
183 
184 static __inline void
185 _ng_hook_set_private(hook_p hook, void *val, char * file, int line)
186 {
187 	_chkhook(hook, file, line);
188 	_NG_HOOK_SET_PRIVATE(hook, val);
189 }
190 
191 static __inline void *
192 _ng_hook_private(hook_p hook, char * file, int line)
193 {
194 	_chkhook(hook, file, line);
195 	return (_NG_HOOK_PRIVATE(hook));
196 }
197 
198 static __inline int
199 _ng_hook_not_valid(hook_p hook, char * file, int line)
200 {
201 	_chkhook(hook, file, line);
202 	return (_NG_HOOK_NOT_VALID(hook));
203 }
204 
205 static __inline int
206 _ng_hook_is_valid(hook_p hook, char * file, int line)
207 {
208 	_chkhook(hook, file, line);
209 	return (_NG_HOOK_IS_VALID(hook));
210 }
211 
212 static __inline node_p
213 _ng_hook_node(hook_p hook, char * file, int line)
214 {
215 	_chkhook(hook, file, line);
216 	return (_NG_HOOK_NODE(hook));
217 }
218 
219 static __inline hook_p
220 _ng_hook_peer(hook_p hook, char * file, int line)
221 {
222 	_chkhook(hook, file, line);
223 	return (_NG_HOOK_PEER(hook));
224 }
225 
226 static __inline void
227 _ng_hook_force_writer(hook_p hook, char * file, int line)
228 {
229 	_chkhook(hook, file, line);
230 	_NG_HOOK_FORCE_WRITER(hook);
231 }
232 
233 static __inline void
234 _ng_hook_force_queue(hook_p hook, char * file, int line)
235 {
236 	_chkhook(hook, file, line);
237 	_NG_HOOK_FORCE_QUEUE(hook);
238 }
239 
240 
241 #define	NG_HOOK_REF(hook)		_ng_hook_ref(hook, _NN_)
242 #define NG_HOOK_NAME(hook)		_ng_hook_name(hook, _NN_)
243 #define NG_HOOK_UNREF(hook)		_ng_hook_unref(hook, _NN_)
244 #define	NG_HOOK_SET_PRIVATE(hook, val)	_ng_hook_set_private(hook, val, _NN_)
245 #define	NG_HOOK_PRIVATE(hook)		_ng_hook_private(hook, _NN_)
246 #define NG_HOOK_NOT_VALID(hook)		_ng_hook_not_valid(hook, _NN_)
247 #define NG_HOOK_IS_VALID(hook)		_ng_hook_is_valid(hook, _NN_)
248 #define NG_HOOK_NODE(hook)		_ng_hook_node(hook, _NN_)
249 #define NG_HOOK_PEER(hook)		_ng_hook_peer(hook, _NN_)
250 #define NG_HOOK_FORCE_WRITER(hook)	_ng_hook_force_writer(hook, _NN_)
251 #define NG_HOOK_FORCE_QUEUE(hook)	_ng_hook_force_queue(hook, _NN_)
252 
253 #else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
254 
255 #define	NG_HOOK_REF(hook)		_NG_HOOK_REF(hook)
256 #define NG_HOOK_NAME(hook)		_NG_HOOK_NAME(hook)
257 #define NG_HOOK_UNREF(hook)		_NG_HOOK_UNREF(hook)
258 #define	NG_HOOK_SET_PRIVATE(hook, val)	_NG_HOOK_SET_PRIVATE(hook, val)
259 #define	NG_HOOK_PRIVATE(hook)		_NG_HOOK_PRIVATE(hook)
260 #define NG_HOOK_NOT_VALID(hook)		_NG_HOOK_NOT_VALID(hook)
261 #define NG_HOOK_IS_VALID(hook)		_NG_HOOK_IS_VALID(hook)
262 #define NG_HOOK_NODE(hook)		_NG_HOOK_NODE(hook)
263 #define NG_HOOK_PEER(hook)		_NG_HOOK_PEER(hook)
264 #define NG_HOOK_FORCE_WRITER(hook)	_NG_HOOK_FORCE_WRITER(hook)
265 #define NG_HOOK_FORCE_QUEUE(hook)	_NG_HOOK_FORCE_QUEUE(hook)
266 
267 #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
268 
269 /***********************************************************************
270  ***************** Node Structure and Methods **************************
271  ***********************************************************************
272  * Structure of a node
273  * including the eembedded queue structure.
274  *
275  * The structure for queueing Netgraph request items
276  * embedded in the node structure
277  */
278 struct ng_queue {
279 	u_long          q_flags;
280 	struct mtx      q_mtx;
281 	item_p queue;
282 	item_p *last;
283 	struct ng_node *q_node;		/* find the front of the node.. */
284 };
285 
286 struct ng_node {
287 	char	nd_name[NG_NODELEN+1];	/* optional globally unique name */
288 	struct	ng_type *nd_type;	/* the installed 'type' */
289 	int	nd_flags;		/* see below for bit definitions */
290 	int	nd_refs;		/* # of references to this node */
291 	int	nd_numhooks;		/* number of hooks */
292 	void   *nd_private;		/* node type dependant node ID */
293 	ng_ID_t	nd_ID;			/* Unique per node */
294 	LIST_HEAD(hooks, ng_hook) nd_hooks;	/* linked list of node hooks */
295 	LIST_ENTRY(ng_node)	  nd_nodes;	/* linked list of all nodes */
296 	LIST_ENTRY(ng_node)	  nd_idnodes;	/* ID hash collision list */
297 	TAILQ_ENTRY(ng_node)	  nd_work;	/* nodes with work to do */
298 	struct	ng_queue	  nd_input_queue; /* input queue for locking */
299 #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
300 #define ND_MAGIC 0x59264837
301 	int	nd_magic;
302 	char	*lastfile;
303 	int	lastline;
304 	SLIST_ENTRY(ng_node)	  nd_all;	/* all existing nodes */
305 #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
306 };
307 
308 /* Flags for a node */
309 #define NG_INVALID	0x00000001	/* free when refs go to 0 */
310 #define NG_WORKQ	0x00000002	/* node is on the work queue */
311 #define NG_FORCE_WRITER	0x00000004	/* Never multithread this node */
312 #define NG_CLOSING	0x00000008	/* ng_rmnode() at work */
313 #define NGF_TYPE1	0x10000000	/* reserved for type specific storage */
314 #define NGF_TYPE2	0x20000000	/* reserved for type specific storage */
315 #define NGF_TYPE3	0x40000000	/* reserved for type specific storage */
316 #define NGF_TYPE4	0x80000000	/* reserved for type specific storage */
317 
318 /*
319  * Public methods for nodes.
320  * If you can't do it with these you probably shouldn't be doing it.
321  */
322 void	ng_unref_node(node_p node); /* don't move this */
323 #define _NG_NODE_NAME(node)	((node)->nd_name + 0)
324 #define _NG_NODE_HAS_NAME(node)	((node)->nd_name[0] + 0)
325 #define _NG_NODE_ID(node)	((node)->nd_ID + 0)
326 #define	_NG_NODE_REF(node)	atomic_add_int(&(node)->nd_refs, 1)
327 #define	_NG_NODE_UNREF(node)	ng_unref_node(node)
328 #define	_NG_NODE_SET_PRIVATE(node, val)	do {(node)->nd_private = val;} while (0)
329 #define	_NG_NODE_PRIVATE(node)	((node)->nd_private)
330 #define _NG_NODE_IS_VALID(node)	(!((node)->nd_flags & NG_INVALID))
331 #define _NG_NODE_NOT_VALID(node)	((node)->nd_flags & NG_INVALID)
332 #define _NG_NODE_NUMHOOKS(node)	((node)->nd_numhooks + 0) /* rvalue */
333 #define _NG_NODE_FORCE_WRITER(node)					\
334 	do{ node->nd_flags |= NG_FORCE_WRITER; }while (0)
335 /*
336  * The hook iterator.
337  * This macro will call a function of type ng_fn_eachhook for each
338  * hook attached to the node. If the function returns 0, then the
339  * iterator will stop and return a pointer to the hook that returned 0.
340  */
341 typedef	int	ng_fn_eachhook(hook_p hook, void* arg);
342 #define _NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)			\
343 	do {								\
344 		hook_p hook;						\
345 		LIST_FOREACH(hook, &((node)->nd_hooks), hk_hooks) {	\
346 			if ((fn)(hook, arg) == 0) {			\
347 				(rethook) = hook;			\
348 				break;					\
349 			}						\
350 		}							\
351 	} while (0)
352 
353 #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
354 void	dumpnode(node_p node, char *file, int line);
355 static void __inline _chknode(node_p node, char *file, int line);
356 static __inline char * _ng_node_name(node_p node, char *file, int line);
357 static __inline int _ng_node_has_name(node_p node, char *file, int line);
358 static __inline ng_ID_t _ng_node_id(node_p node, char *file, int line);
359 static __inline void _ng_node_ref(node_p node, char *file, int line);
360 static __inline void _ng_node_unref(node_p node, char *file, int line);
361 static __inline void _ng_node_set_private(node_p node, void * val,
362 							char *file, int line);
363 static __inline void * _ng_node_private(node_p node, char *file, int line);
364 static __inline int _ng_node_is_valid(node_p node, char *file, int line);
365 static __inline int _ng_node_not_valid(node_p node, char *file, int line);
366 static __inline int _ng_node_numhooks(node_p node, char *file, int line);
367 static __inline void _ng_node_force_writer(node_p node, char *file, int line);
368 static __inline hook_p _ng_node_foreach_hook(node_p node,
369 			ng_fn_eachhook *fn, void *arg, char *file, int line);
370 
371 static void __inline
372 _chknode(node_p node, char *file, int line)
373 {
374 	if (node->nd_magic != ND_MAGIC) {
375 		printf("Accessing freed node ");
376 		dumpnode(node, file, line);
377 	}
378 	node->lastline = line;
379 	node->lastfile = file;
380 }
381 
382 static __inline char *
383 _ng_node_name(node_p node, char *file, int line)
384 {
385 	_chknode(node, file, line);
386 	return(_NG_NODE_NAME(node));
387 }
388 
389 static __inline int
390 _ng_node_has_name(node_p node, char *file, int line)
391 {
392 	_chknode(node, file, line);
393 	return(_NG_NODE_HAS_NAME(node));
394 }
395 
396 static __inline ng_ID_t
397 _ng_node_id(node_p node, char *file, int line)
398 {
399 	_chknode(node, file, line);
400 	return(_NG_NODE_ID(node));
401 }
402 
403 static __inline void
404 _ng_node_ref(node_p node, char *file, int line)
405 {
406 	_chknode(node, file, line);
407 	_NG_NODE_REF(node);
408 }
409 
410 static __inline void
411 _ng_node_unref(node_p node, char *file, int line)
412 {
413 	_chknode(node, file, line);
414 	_NG_NODE_UNREF(node);
415 }
416 
417 static __inline void
418 _ng_node_set_private(node_p node, void * val, char *file, int line)
419 {
420 	_chknode(node, file, line);
421 	_NG_NODE_SET_PRIVATE(node, val);
422 }
423 
424 static __inline void *
425 _ng_node_private(node_p node, char *file, int line)
426 {
427 	_chknode(node, file, line);
428 	return (_NG_NODE_PRIVATE(node));
429 }
430 
431 static __inline int
432 _ng_node_is_valid(node_p node, char *file, int line)
433 {
434 	_chknode(node, file, line);
435 	return(_NG_NODE_IS_VALID(node));
436 }
437 
438 static __inline int
439 _ng_node_not_valid(node_p node, char *file, int line)
440 {
441 	_chknode(node, file, line);
442 	return(_NG_NODE_NOT_VALID(node));
443 }
444 
445 static __inline int
446 _ng_node_numhooks(node_p node, char *file, int line)
447 {
448 	_chknode(node, file, line);
449 	return(_NG_NODE_NUMHOOKS(node));
450 }
451 
452 static __inline void
453 _ng_node_force_writer(node_p node, char *file, int line)
454 {
455 	_chknode(node, file, line);
456 	_NG_NODE_FORCE_WRITER(node);
457 }
458 
459 static __inline hook_p
460 _ng_node_foreach_hook(node_p node, ng_fn_eachhook *fn, void *arg,
461 						char *file, int line)
462 {
463 	hook_p hook;
464 	_chknode(node, file, line);
465 	_NG_NODE_FOREACH_HOOK(node, fn, arg, hook);
466 	return (hook);
467 }
468 
469 #define NG_NODE_NAME(node)		_ng_node_name(node, _NN_)
470 #define NG_NODE_HAS_NAME(node)		_ng_node_has_name(node, _NN_)
471 #define NG_NODE_ID(node)		_ng_node_id(node, _NN_)
472 #define NG_NODE_REF(node)		_ng_node_ref(node, _NN_)
473 #define	NG_NODE_UNREF(node)		_ng_node_unref(node, _NN_)
474 #define	NG_NODE_SET_PRIVATE(node, val)	_ng_node_set_private(node, val, _NN_)
475 #define	NG_NODE_PRIVATE(node)		_ng_node_private(node, _NN_)
476 #define NG_NODE_IS_VALID(node)		_ng_node_is_valid(node, _NN_)
477 #define NG_NODE_NOT_VALID(node)		_ng_node_not_valid(node, _NN_)
478 #define NG_NODE_FORCE_WRITER(node) 	_ng_node_force_writer(node, _NN_)
479 #define NG_NODE_NUMHOOKS(node)		_ng_node_numhooks(node, _NN_)
480 #define NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)			      \
481 	do {								      \
482 		rethook = _ng_node_foreach_hook(node, fn, (void *)arg, _NN_); \
483 	} while (0)
484 
485 #else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
486 
487 #define NG_NODE_NAME(node)		_NG_NODE_NAME(node)
488 #define NG_NODE_HAS_NAME(node)		_NG_NODE_HAS_NAME(node)
489 #define NG_NODE_ID(node)		_NG_NODE_ID(node)
490 #define	NG_NODE_REF(node)		_NG_NODE_REF(node)
491 #define	NG_NODE_UNREF(node)		_NG_NODE_UNREF(node)
492 #define	NG_NODE_SET_PRIVATE(node, val)	_NG_NODE_SET_PRIVATE(node, val)
493 #define	NG_NODE_PRIVATE(node)		_NG_NODE_PRIVATE(node)
494 #define NG_NODE_IS_VALID(node)		_NG_NODE_IS_VALID(node)
495 #define NG_NODE_NOT_VALID(node)		_NG_NODE_NOT_VALID(node)
496 #define NG_NODE_FORCE_WRITER(node) 	_NG_NODE_FORCE_WRITER(node)
497 #define NG_NODE_NUMHOOKS(node)		_NG_NODE_NUMHOOKS(node)
498 #define NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)			\
499 		_NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)
500 #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
501 
502 /***********************************************************************
503  ***************** Meta Data Structures and Methods ********************
504  ***********************************************************************
505  *
506  * The structure that holds meta_data about a data packet (e.g. priority)
507  * Nodes might add or subtract options as needed if there is room.
508  * They might reallocate the struct to make more room if they need to.
509  * Meta-data is still experimental.
510  */
511 struct meta_field_header {
512 	u_long	cookie;		/* cookie for the field. Skip fields you don't
513 				 * know about (same cookie as in messgaes) */
514 	u_short type;		/* field ID */
515 	u_short len;		/* total len of this field including extra
516 				 * data */
517 	char	data[0];	/* data starts here */
518 };
519 
520 /* To zero out an option 'in place' set it's cookie to this */
521 #define NGM_INVALID_COOKIE	865455152
522 
523 /* This part of the metadata is always present if the pointer is non NULL */
524 struct ng_meta {
525 	char	priority;	/* -ve is less priority,  0 is default */
526 	char	discardability; /* higher is less valuable.. discard first */
527 	u_short allocated_len;	/* amount malloc'd */
528 	u_short used_len;	/* sum of all fields, options etc. */
529 	u_short flags;		/* see below.. generic flags */
530 	struct meta_field_header options[0];	/* add as (if) needed */
531 };
532 typedef struct ng_meta *meta_p;
533 
534 /* Flags for meta-data */
535 #define NGMF_TEST	0x01	/* discard at the last moment before sending */
536 #define NGMF_TRACE	0x02	/* trace when handing this data to a node */
537 
538 /***********************************************************************
539  ************* Node Queue and Item Structures and Methods **************
540  ***********************************************************************
541  *
542  */
543 typedef	int	ng_item_fn(node_p node, hook_p hook, void *arg1, int arg2);
544 struct ng_item {
545 	u_long	el_flags;
546 	item_p	el_next;
547 	node_p	el_dest; /* The node it will be applied against (or NULL) */
548 	hook_p	el_hook; /* Entering hook. Optional in Control messages */
549 	union {
550 		struct {
551 			struct mbuf	*da_m;
552 			meta_p		da_meta;
553 		} data;
554 		struct {
555 			struct ng_mesg	*msg_msg;
556 			ng_ID_t		msg_retaddr;
557 		} msg;
558 		struct {
559 			ng_item_fn	*fn_fn;
560 			void 		*fn_arg1;
561 			int		fn_arg2;
562 		} fn;
563 	} body;
564 #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
565 	char *lastfile;
566 	int  lastline;
567 	TAILQ_ENTRY(ng_item)	  all;		/* all existing items */
568 #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
569 };
570 
571 #define NGQF_TYPE	0x03		/* MASK of content definition */
572 #define NGQF_MESG	0x00		/* the queue element is a message */
573 #define NGQF_DATA	0x01		/* the queue element is data */
574 #define NGQF_FN		0x02		/* the queue element is a function */
575 #define NGQF_UNDEF	0x03		/* UNDEFINED */
576 
577 #define NGQF_RW		0x04		/* MASK for queue entry read/write */
578 #define NGQF_READER	0x04		/* queued as a reader */
579 #define NGQF_WRITER	0x00		/* queued as a writer */
580 
581 #define NGQF_FREE	0x08
582 
583 /*
584  * Get the mbuf (etc) out of an item.
585  * Sets the value in the item to NULL in case we need to call NG_FREE_ITEM()
586  * with it, (to avoid freeing the things twice).
587  * If you don't want to zero out the item then realise that the
588  * item still owns it.
589  * Retaddr is different. There are no references on that. It's just a number.
590  * The debug versions must be either all used everywhere or not at all.
591  */
592 
593 #define _NGI_M(i) ((i)->body.data.da_m)
594 #define _NGI_META(i) ((i)->body.data.da_meta)
595 #define _NGI_MSG(i) ((i)->body.msg.msg_msg)
596 #define _NGI_RETADDR(i) ((i)->body.msg.msg_retaddr)
597 #define	_NGI_FN(i) ((i)->body.fn.fn_fn)
598 #define	_NGI_ARG1(i) ((i)->body.fn.fn_arg1)
599 #define	_NGI_ARG2(i) ((i)->body.fn.fn_arg2)
600 
601 #ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
602 void				dumpitem(item_p item, char *file, int line);
603 static __inline void		_ngi_check(item_p item, char *file, int line) ;
604 static __inline struct mbuf **	_ngi_m(item_p item, char *file, int line) ;
605 static __inline meta_p *	_ngi_meta(item_p item, char *file, int line) ;
606 static __inline ng_ID_t *	_ngi_retaddr(item_p item, char *file,
607 							int line) ;
608 static __inline struct ng_mesg **	_ngi_msg(item_p item, char *file,
609 							int line) ;
610 
611 static __inline void
612 _ngi_check(item_p item, char *file, int line)
613 {
614 	if (item->el_flags & NGQF_FREE) {
615 		dumpitem(item, file, line);
616 		panic ("free item!");
617 	}
618 	(item)->lastline = line;
619 	(item)->lastfile = file;
620 }
621 
622 static __inline struct mbuf **
623 _ngi_m(item_p item, char *file, int line)
624 {
625 	_ngi_check(item, file, line);
626 	return (&_NGI_M(item));
627 }
628 
629 static __inline meta_p *
630 _ngi_meta(item_p item, char *file, int line)
631 {
632 	_ngi_check(item, file, line);
633 	return (&_NGI_META(item));
634 }
635 
636 static __inline struct ng_mesg **
637 _ngi_msg(item_p item, char *file, int line)
638 {
639 	_ngi_check(item, file, line);
640 	return (&_NGI_MSG(item));
641 }
642 
643 static __inline ng_ID_t *
644 _ngi_retaddr(item_p item, char *file, int line)
645 {
646 	_ngi_check(item, file, line);
647 	return (&_NGI_RETADDR(item));
648 }
649 
650 static __inline ng_item_fn **
651 _ngi_fn(item_p item, char *file, int line)
652 {
653 	_ngi_check(item, file, line);
654 	return (&_NGI_FN(item));
655 }
656 
657 static __inline void **
658 _ngi_arg1(item_p item, char *file, int line)
659 {
660 	_ngi_check(item, file, line);
661 	return (&_NGI_ARG1(item));
662 }
663 
664 static __inline int *
665 _ngi_arg2(item_p item, char *file, int line)
666 {
667 	_ngi_check(item, file, line);
668 	return (&_NGI_ARG2(item));
669 }
670 
671 #define NGI_M(i)	(*_ngi_m(i, _NN_))
672 #define NGI_META(i)	(*_ngi_meta(i, _NN_))
673 #define NGI_MSG(i)	(*_ngi_msg(i, _NN_))
674 #define NGI_RETADDR(i)	(*_ngi_retaddr(i, _NN_))
675 #define NGI_FN(i)	(*_ngi_fn(i, _NN_))
676 #define NGI_ARG1(i)	(*_ngi_arg1(i, _NN_))
677 #define NGI_ARG2(i)	(*_ngi_arg2(i, _NN_))
678 
679 #define NGI_GET_M(i,m)							\
680 	do {								\
681 		m = NGI_M(i);						\
682 		_NGI_M(i) = NULL;					\
683 	} while (0)
684 
685 #define NGI_GET_META(i,m)						\
686 	do {								\
687 		m = NGI_META(i);					\
688 		_NGI_META(i) = NULL;					\
689 	} while (0)
690 
691 #define NGI_GET_MSG(i,m)						\
692 	do {								\
693 		m = NGI_MSG(i);						\
694 		_NGI_MSG(i) = NULL;					\
695 	} while (0)
696 
697 #define NG_FREE_ITEM(item)						\
698 	do {								\
699 		_ngi_check(item, _NN_);					\
700 		ng_free_item((item));					\
701 	} while (0)
702 
703 #define	SAVE_LINE(item)							\
704 	do {								\
705 		(item)->lastline = __LINE__;				\
706 		(item)->lastfile = __FILE__;				\
707 	} while (0)
708 
709 #else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
710 
711 #define NGI_M(i)	_NGI_M(i)
712 #define NGI_META(i)	_NGI_META(i)
713 #define NGI_MSG(i)	_NGI_MSG(i)
714 #define NGI_RETADDR(i)	_NGI_RETADDR(i)
715 #define NGI_FN(i)	_NGI_FN(i)
716 #define NGI_ARG1(i)	_NGI_ARG1(i)
717 #define NGI_ARG2(i)	_NGI_ARG2(i)
718 
719 #define NGI_GET_M(i,m)       do {m = NGI_M(i); NGI_M(i) = NULL;      } while (0)
720 #define NGI_GET_META(i,m)    do {m = NGI_META(i); NGI_META(i) = NULL;} while (0)
721 #define NGI_GET_MSG(i,m)     do {m = NGI_MSG(i); NGI_MSG(i) = NULL;  } while (0)
722 
723 #define	NG_FREE_ITEM(item)	ng_free_item((item))
724 #define	SAVE_LINE(item)		do {} while (0)
725 
726 #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
727 
728 /**********************************************************************
729 * Data macros.  Send, manipulate and free.
730 **********************************************************************/
731 /* Send previously unpackeged data and metadata. */
732 #define NG_SEND_DATA(error, hook, m, meta)				\
733 	do {								\
734 		item_p item;						\
735 		if ((item = ng_package_data((m), (meta)))) {		\
736 			if (!((error) = ng_address_hook(NULL, item,	\
737 							hook, NULL))) {	\
738 				SAVE_LINE(item);			\
739 				(error) = ng_snd_item((item), 0);	\
740 			}						\
741 		} else {						\
742 			(error) = ENOMEM;				\
743 		}							\
744 		(m) = NULL;						\
745 		(meta) = NULL;						\
746 	} while (0)
747 
748 /* Send a previously unpackaged mbuf when we have no metadata to send */
749 #define NG_SEND_DATA_ONLY(error, hook, m)				\
750 	do {								\
751 		item_p item;						\
752 		if ((item = ng_package_data((m), NULL))) {		\
753 			if (!((error) = ng_address_hook(NULL, item,	\
754 							hook, NULL))) {	\
755 				SAVE_LINE(item);			\
756 				(error) = ng_snd_item((item), 0);	\
757 			}						\
758 		} else {						\
759 			(error) = ENOMEM;				\
760 		}							\
761 		(m) = NULL;						\
762 	} while (0)
763 
764 /*
765  * Forward a data packet with no new meta-data.
766  * old metadata is passed along without change.
767  * Mbuf pointer is updated to new value. We presume you dealt with the
768  * old one when you update it to the new one (or it maybe the old one).
769  * We got a packet and possibly had to modify the mbuf.
770  * You should probably use NGI_GET_M() if you are going to use this too
771  */
772 #define NG_FWD_NEW_DATA(error, item, hook, m)				\
773 	do {								\
774 		NGI_M(item) = m;					\
775 		if (!((error) = ng_address_hook(NULL, (item),		\
776 						(hook), NULL))) {	\
777 			SAVE_LINE(item);				\
778 			(error) = ng_snd_item((item), 0);		\
779 		}							\
780 		(item) = NULL;						\
781 		(m) = NULL;						\
782 	} while (0)
783 
784 /*
785  * Assuming the data is already ok, just set the new address and send
786  */
787 #define NG_FWD_ITEM_HOOK(error, item, hook)				\
788 	do {								\
789 		if (!((error) = ng_address_hook(NULL, (item),		\
790 						(hook), NULL))) {	\
791 			SAVE_LINE(item);				\
792 			(error) = ng_snd_item((item), 0);		\
793 		} else {						\
794 			(error) = ENXIO;				\
795 		}							\
796 		(item) = NULL;						\
797 	} while (0)
798 
799 
800 /* Note that messages can be static (e.g. in ng_rmnode_self()) */
801 /* XXX flag should not be user visible  */
802 #define NG_FREE_MSG(msg)						\
803 	do {								\
804 		if ((msg)) {						\
805 			if ((msg->header.flags & NGF_STATIC) == 0) {	\
806 				FREE((msg), M_NETGRAPH_MSG);		\
807 			}						\
808 			(msg) = NULL;					\
809 		}	 						\
810 	} while (0)
811 
812 #define NG_FREE_META(meta)						\
813 	do {								\
814 		if ((meta)) {						\
815 			FREE((meta), M_NETGRAPH_META);			\
816 			(meta) = NULL;					\
817 		}	 						\
818 	} while (0)
819 
820 #define NG_FREE_M(m)							\
821 	do {								\
822 		if ((m)) {						\
823 			m_freem((m));					\
824 			(m) = NULL;					\
825 		}							\
826 	} while (0)
827 
828 /*****************************************
829 * Message macros
830 *****************************************/
831 
832 #define NG_SEND_MSG_HOOK(error, here, msg, hook, retaddr)		\
833 	do {								\
834 		item_p item;						\
835 		if ((item = ng_package_msg(msg)) == NULL) {		\
836 			(msg) = NULL;					\
837 			(error) = ENOMEM;				\
838 			break;						\
839 		}							\
840 		if (((error) = ng_address_hook((here), (item),		\
841 					(hook), (retaddr))) == 0) {	\
842 			SAVE_LINE(item);				\
843 			(error) = ng_snd_item((item), 0);		\
844 		}							\
845 		(msg) = NULL;						\
846 	} while (0)
847 
848 #define NG_SEND_MSG_PATH(error, here, msg, path, retaddr)		\
849 	do {								\
850 		item_p item;						\
851 		if ((item = ng_package_msg(msg)) == NULL) {		\
852 			(msg) = NULL;					\
853 			(error) = ENOMEM;				\
854 			break;						\
855 		}							\
856 		if (((error) = ng_address_path((here), (item),		\
857 					(path), (retaddr))) == 0) {	\
858 			SAVE_LINE(item);				\
859 			(error) = ng_snd_item((item), 0);		\
860 		}							\
861 		(msg) = NULL;						\
862 	} while (0)
863 
864 #define NG_SEND_MSG_ID(error, here, msg, ID, retaddr)			\
865 	do {								\
866 		item_p item;						\
867 		if ((item = ng_package_msg(msg)) == NULL) {		\
868 			(msg) = NULL;					\
869 			(error) = ENOMEM;				\
870 			break;						\
871 		}							\
872 		if (((error) = ng_address_ID((here), (item),		\
873 					(ID), (retaddr))) == 0) {	\
874 			SAVE_LINE(item);				\
875 			(error) = ng_snd_item((item), 0);		\
876 		}							\
877 		(msg) = NULL;						\
878 	} while (0)
879 
880 #define NG_QUEUE_MSG(error, here, msg, path, retaddr)			\
881 	do {								\
882 		item_p item;						\
883 		if ((item = ng_package_msg(msg)) == NULL) {		\
884 			(msg) = NULL;					\
885 			(error) = ENOMEM;				\
886 			break;						\
887 		}							\
888 		if (((error) = ng_address_path((here), (item),		\
889 					(path), (retaddr))) == 0) {	\
890 			SAVE_LINE(item);				\
891 			(error) = ng_snd_item((item), 1);		\
892 		}							\
893 		(msg) = NULL;						\
894 	} while (0)
895 
896 /*
897  * Redirect the message to the next hop using the given hook.
898  * ng_retarget_msg() frees the item if there is an error
899  * and returns an error code.  It returns 0 on success.
900  */
901 #define NG_FWD_MSG_HOOK(error, here, item, hook, retaddr)		\
902 	do {								\
903 		if (((error) = ng_address_hook((here), (item),		\
904 					(hook), (retaddr))) == 0) {	\
905 			SAVE_LINE(item);				\
906 			(error) = ng_snd_item((item), 0);		\
907 		}							\
908 		(item) = NULL;						\
909 	} while (0)
910 
911 /*
912  * Send a queue item back to it's originator with a response message.
913  * Assume original message was removed and freed separatly.
914  */
915 #define NG_RESPOND_MSG(error, here, item, resp)				\
916 	do {								\
917 		if (resp) {						\
918 			ng_ID_t dest = NGI_RETADDR(item);		\
919 			NGI_RETADDR(item) = NULL;			\
920 			NGI_MSG(item) = resp;				\
921 			if ((ng_address_ID((here), (item),		\
922 					dest, NULL )) == 0) {		\
923 				SAVE_LINE(item);			\
924 				(error) = ng_snd_item((item), 1);	\
925 			} else {					\
926 				(error) = EINVAL;			\
927 			}						\
928 		} else {						\
929 			NG_FREE_ITEM(item);				\
930 		}							\
931 		(item) = NULL;						\
932 	} while (0)
933 
934 
935 /***********************************************************************
936  ******** Structures Definitions and Macros for defining a node  *******
937  ***********************************************************************
938  *
939  * Here we define the structures needed to actually define a new node
940  * type.
941  */
942 
943 /* node method definitions */
944 typedef	int	ng_constructor_t(node_p node);
945 typedef	int	ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook);
946 typedef	int	ng_shutdown_t(node_p node);
947 typedef	int	ng_newhook_t(node_p node, hook_p hook, const char *name);
948 typedef	hook_p	ng_findhook_t(node_p node, const char *name);
949 typedef	int	ng_connect_t(hook_p hook);
950 typedef	int	ng_rcvdata_t(hook_p hook, item_p item);
951 typedef	int	ng_disconnect_t(hook_p hook);
952 typedef	int	ng_rcvitem (node_p node, hook_p hook, item_p item);
953 /*
954  * Command list -- each node type specifies the command that it knows
955  * how to convert between ASCII and binary using an array of these.
956  * The last element in the array must be a terminator with cookie=0.
957  */
958 
959 struct ng_cmdlist {
960 	u_int32_t			cookie;		/* command typecookie */
961 	int				cmd;		/* command number */
962 	const char			*name;		/* command name */
963 	const struct ng_parse_type	*mesgType;	/* args if !NGF_RESP */
964 	const struct ng_parse_type	*respType;	/* args if NGF_RESP */
965 };
966 
967 /*
968  * Structure of a node type
969  * If data is sent to the "rcvdata()" entrypoint then the system
970  * may decide to defer it until later by queing it with the normal netgraph
971  * input queuing system.  This is decidde by the HK_QUEUE flag being set in
972  * the flags word of the peer (receiving) hook. The dequeuing mechanism will
973  * ensure it is not requeued again.
974  * Note the input queueing system is to allow modules
975  * to 'release the stack' or to pass data across spl layers.
976  * The data will be redelivered as soon as the NETISR code runs
977  * which may be almost immediatly.  A node may also do it's own queueing
978  * for other reasons (e.g. device output queuing).
979  */
980 struct ng_type {
981 
982 	u_int32_t	version; 	/* must equal NG_API_VERSION */
983 	const char	*name;		/* Unique type name */
984 	modeventhand_t	mod_event;	/* Module event handler (optional) */
985 	ng_constructor_t *constructor;	/* Node constructor */
986 	ng_rcvmsg_t	*rcvmsg;	/* control messages come here */
987 	ng_shutdown_t	*shutdown;	/* reset, and free resources */
988 	ng_newhook_t	*newhook;	/* first notification of new hook */
989 	ng_findhook_t	*findhook;	/* only if you have lots of hooks */
990 	ng_connect_t	*connect;	/* final notification of new hook */
991 	ng_rcvdata_t	*rcvdata;	/* data comes here */
992 	ng_disconnect_t	*disconnect;	/* notify on disconnect */
993 
994 	const struct	ng_cmdlist *cmdlist;	/* commands we can convert */
995 
996 	/* R/W data private to the base netgraph code DON'T TOUCH! */
997 	LIST_ENTRY(ng_type) types;		/* linked list of all types */
998 	int		    refs;		/* number of instances */
999 };
1000 
1001 /*
1002  * Use the NETGRAPH_INIT() macro to link a node type into the
1003  * netgraph system. This works for types compiled into the kernel
1004  * as well as KLD modules. The first argument should be the type
1005  * name (eg, echo) and the second a pointer to the type struct.
1006  *
1007  * If a different link time is desired, e.g., a device driver that
1008  * needs to install its netgraph type before probing, use the
1009  * NETGRAPH_INIT_ORDERED() macro instead. Deivce drivers probably
1010  * want to use SI_SUB_DRIVERS instead of SI_SUB_PSEUDO.
1011  */
1012 
1013 #define NETGRAPH_INIT_ORDERED(typename, typestructp, sub, order)	\
1014 static moduledata_t ng_##typename##_mod = {				\
1015 	"ng_" #typename,						\
1016 	ng_mod_event,							\
1017 	(typestructp)							\
1018 };									\
1019 DECLARE_MODULE(ng_##typename, ng_##typename##_mod, sub, order);		\
1020 MODULE_DEPEND(ng_##typename, netgraph, 1, 1, 1)
1021 
1022 #define NETGRAPH_INIT(tn, tp)						\
1023 	NETGRAPH_INIT_ORDERED(tn, tp, SI_SUB_PSEUDO, SI_ORDER_ANY)
1024 
1025 /* Special malloc() type for netgraph structs and ctrl messages */
1026 /* Only these two types should be visible to nodes */
1027 MALLOC_DECLARE(M_NETGRAPH);
1028 MALLOC_DECLARE(M_NETGRAPH_MSG);
1029 MALLOC_DECLARE(M_NETGRAPH_META);
1030 
1031 
1032 
1033 /*
1034  * Methods that the nodes can use.
1035  * Many of these methods should usually NOT be used directly but via
1036  * Macros above.
1037  */
1038 int	ng_address_ID(node_p here, item_p item, ng_ID_t ID, ng_ID_t retaddr);
1039 int	ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr);
1040 int	ng_address_path(node_p here, item_p item, char *address, ng_ID_t raddr);
1041 meta_p	ng_copy_meta(meta_p meta);
1042 hook_p	ng_findhook(node_p node, const char *name);
1043 int	ng_make_node_common(struct ng_type *typep, node_p *nodep);
1044 int	ng_name_node(node_p node, const char *name);
1045 int	ng_newtype(struct ng_type *tp);
1046 ng_ID_t ng_node2ID(node_p node);
1047 item_p	ng_package_data(struct mbuf *m, meta_p meta);
1048 item_p	ng_package_msg(struct ng_mesg *msg);
1049 item_p	ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg);
1050 void	ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr);
1051 int	ng_rmhook_self(hook_p hook);	/* if a node wants to kill a hook */
1052 int	ng_rmnode_self(node_p here);	/* if a node wants to suicide */
1053 int	ng_snd_item(item_p item, int queue);
1054 int 	ng_send_fn(node_p node, hook_p hook, ng_item_fn *fn,
1055 	void *arg1, int arg2);
1056 
1057 /*
1058  * prototypes the user should DEFINITLY not use directly
1059  */
1060 void	ng_free_item(item_p item); /* Use NG_FREE_ITEM instead */
1061 int	ng_mod_event(module_t mod, int what, void *arg);
1062 
1063 #endif /* _NETGRAPH_NETGRAPH_H_ */
1064 
1065