1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * This file include internal used definition and data structure of hooks
28 */
29
30#ifndef _SYS_HOOK_IMPL_H
31#define	_SYS_HOOK_IMPL_H
32
33#include <sys/hook.h>
34#include <sys/condvar_impl.h>
35#include <sys/netstack.h>
36
37#ifdef	__cplusplus
38extern "C" {
39#endif
40
41typedef enum fwflag_e {
42	FWF_NONE		= 0x00,
43	FWF_DESTROY_ACTIVE	= 0x01,
44	FWF_ADD_ACTIVE		= 0x04,
45	FWF_DEL_ACTIVE		= 0x08,
46	FWF_DESTROY_WANTED	= 0x10,
47	FWF_ADD_WANTED		= 0x40,
48	FWF_DEL_WANTED		= 0x80,
49	FWF_NOT_READY		= 0x100
50} fwflag_t;
51
52#define	FWF_ADD_WAIT_MASK	(FWF_ADD_ACTIVE|FWF_DEL_ACTIVE|FWF_ADD_WANTED)
53#define	FWF_DEL_WAIT_MASK	(FWF_ADD_ACTIVE|FWF_DEL_ACTIVE|\
54    FWF_ADD_WANTED|FWF_DEL_WANTED)
55#define	FWF_UNSAFE		(FWF_DESTROY_ACTIVE|FWF_NOT_READY)
56#define	FWF_DESTROY		(FWF_DESTROY_ACTIVE|FWF_DESTROY_WANTED)
57#define	FWF_DESTROY_OK(x)	((x)->fw_flags == FWF_DESTROY_WANTED)
58
59typedef struct flagwait_s {
60	kcondvar_t	fw_cv;
61	kmutex_t	fw_lock;
62	uint32_t	fw_flags;
63	cvwaitlock_t	*fw_owner;
64} flagwait_t;
65
66
67/*
68 * The following diagram describes the linking together of data structures
69 * used in this implementation of callback hooks.  The start of it all is
70 * the "familylist" variable in hook.c.  The relationships between data
71 * structures is:
72 * - there is a list of hook families;
73 * - each hook family can have a list of hook events;
74 * - each hook_event_t must be uniquely associated with one family and event;
75 * - each hook event can have a list of registered hooks to call.
76 *
77 *   familylist                    +--------------+
78 *       |                         | hook_event_t |<--\
79 *       |                         +--------------+   |
80 *       V                                            |
81 * +-------------------+       ->+------------------+ |     ->+--------------+
82 * | hook_family_int_t |      /  | hook_event_int_t | |    /  | hook_int_t   |
83 * | +---------------+ |     /   |                  | /   /   | +----------+ |
84 * | | hook_family_t | |    /    | hei_event---------/   /    | | hook_t   | |
85 * | +---------------+ |   /     | hei_nhead----------\ /     | +----------+ |
86 * |                   |  /      |                  |  X      |              |
87 * | hfi_head------------/       | hei_head-----------/ \     | hi_entry--\  |
88 * | hfi_entry--\      |         | hei_entry--\     |   |     +-----------|--+
89 * +------------|------+         +------------|-----+   |                 |
90 *              |                             |         |                 |
91 *              V                             V         |                 V
92 * +-------------------+         +------------------+   |     +--------------+
93 * | hook_family_int_t |         | hook_event_int_t |   |     | hook_int_t   |
94 *                                                      V
95 *                                             +--------------+
96 *                                             |
97 * ...
98 */
99
100typedef struct hook_hook_kstat {
101	kstat_named_t			hook_version;
102	kstat_named_t			hook_flags;
103	kstat_named_t			hook_hint;
104	kstat_named_t			hook_hintvalue;
105	kstat_named_t			hook_position;
106	kstat_named_t			hook_hits;
107} hook_hook_kstat_t;
108
109/*
110 * hook_int: internal storage of hook
111 */
112typedef struct hook_int {
113	TAILQ_ENTRY(hook_int)		hi_entry;
114	hook_t				hi_hook;
115	hook_hook_kstat_t		hi_kstats;
116	kstat_t				*hi_kstatp;
117	char				*hi_ksname;
118	cvwaitlock_t			hi_notify_lock;
119} hook_int_t;
120
121/*
122 * hook_int_head: tail queue of hook_int
123 */
124TAILQ_HEAD(hook_int_head, hook_int);
125typedef struct hook_int_head hook_int_head_t;
126
127
128typedef struct hook_notify {
129	TAILQ_ENTRY(hook_notify)	hn_entry;
130	hook_notify_fn_t		hn_func;
131	void				*hn_arg;
132	uint32_t			hn_flags;
133} hook_notify_t;
134
135TAILQ_HEAD(hook_notify_head, hook_notify);
136typedef struct hook_notify_head hook_notify_head_t;
137
138
139typedef struct hook_event_kstat {
140	kstat_named_t			hooks_added;
141	kstat_named_t			hooks_removed;
142	kstat_named_t			events;
143} hook_event_kstat_t;
144
145/*
146 * hook_event_int: internal storage of hook_event
147 */
148typedef struct hook_event_int {
149	cvwaitlock_t			hei_lock;
150	SLIST_ENTRY(hook_event_int)	hei_entry;
151	hook_event_t			*hei_event;
152	hook_int_head_t			hei_head;
153	kstat_t				*hei_kstatp;
154	hook_event_kstat_t		hei_kstats;
155	hook_notify_head_t		hei_nhead;
156	flagwait_t			hei_waiter;
157	boolean_t			hei_condemned;
158	boolean_t			hei_shutdown;
159} hook_event_int_t;
160
161/*
162 * hook_event_int_head: singly-linked list of hook_event_int
163 */
164SLIST_HEAD(hook_event_int_head, hook_event_int);
165typedef struct hook_event_int_head hook_event_int_head_t;
166
167/*
168 * hook_family_int: internal storage of hook_family
169 */
170typedef struct hook_family_int {
171	cvwaitlock_t			hfi_lock;
172	SLIST_ENTRY(hook_family_int)	hfi_entry;
173	hook_event_int_head_t		hfi_head;
174	hook_family_t 			hfi_family;
175	kstat_t				*hfi_kstat;
176	struct hook_stack		*hfi_stack;
177	hook_notify_head_t		hfi_nhead;
178	flagwait_t			hfi_waiter;
179	boolean_t			hfi_condemned;
180	boolean_t			hfi_shutdown;
181} hook_family_int_t;
182
183/*
184 * hook_family_int_head: singly-linked list of hook_family
185 */
186SLIST_HEAD(hook_family_int_head, hook_family_int);
187typedef struct hook_family_int_head hook_family_int_head_t;
188
189/*
190 * hook stack instances
191 */
192struct hook_stack {
193	cvwaitlock_t			hks_lock;
194	SLIST_ENTRY(hook_stack)		hks_entry;
195	hook_family_int_head_t		hks_familylist;	/* family list head */
196	netstack_t			*hks_netstack;
197	netstackid_t			hks_netstackid;
198	hook_notify_head_t		hks_nhead;
199	int				hks_shutdown;
200	flagwait_t			hks_waiter;
201};
202typedef struct hook_stack hook_stack_t;
203SLIST_HEAD(hook_stack_head, hook_stack);
204typedef struct hook_stack_head hook_stack_head_t;
205
206/*
207 * Names of hooks families currently defined by Solaris
208 */
209#define	Hn_ARP	"arp"
210#define	Hn_IPV4	"inet"
211#define	Hn_IPV6	"inet6"
212
213extern int hook_run(hook_family_int_t *, hook_event_token_t, hook_data_t);
214extern int hook_register(hook_family_int_t *, char *, hook_t *);
215
216extern int hook_unregister(hook_family_int_t *, char *, hook_t *);
217extern hook_event_int_t *hook_event_add(hook_family_int_t *, hook_event_t *);
218extern int hook_event_notify_register(hook_family_int_t *, char *,
219    hook_notify_fn_t, void *);
220extern int hook_event_notify_unregister(hook_family_int_t *, char *,
221    hook_notify_fn_t);
222extern int hook_event_remove(hook_family_int_t *, hook_event_t *);
223extern int hook_event_shutdown(hook_family_int_t *, hook_event_t *);
224
225extern hook_family_int_t *hook_family_add(hook_family_t *, hook_stack_t *,
226    void **);
227extern int hook_family_notify_register(hook_family_int_t *, hook_notify_fn_t,
228    void *);
229extern int hook_family_notify_unregister(hook_family_int_t *, hook_notify_fn_t);
230extern int hook_family_remove(hook_family_int_t *);
231extern int hook_family_shutdown(hook_family_int_t *);
232
233extern int hook_stack_notify_register(netstackid_t, hook_notify_fn_t, void *);
234extern int hook_stack_notify_unregister(netstackid_t, hook_notify_fn_t);
235
236
237#ifdef	__cplusplus
238}
239#endif
240
241#endif /* _SYS_HOOK_IMPL_H */
242