xref: /freebsd/share/man/man9/hhook.9 (revision e0c4386e)
1.\"
2.\" Copyright (c) 2010-2011 The FreeBSD Foundation
3.\"
4.\" This documentation was written at the Centre for Advanced Internet
5.\" Architectures, Swinburne University of Technology, Melbourne, Australia by
6.\" David Hayes and Lawrence Stewart under sponsorship from the FreeBSD
7.\" Foundation.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd June 21, 2013
31.Dt HHOOK 9
32.Os
33.Sh NAME
34.Nm hhook ,
35.Nm hhook_head_register ,
36.Nm hhook_head_deregister ,
37.Nm hhook_head_deregister_lookup ,
38.Nm hhook_run_hooks ,
39.Nm HHOOKS_RUN_IF ,
40.Nm HHOOKS_RUN_LOOKUP_IF
41.Nd Helper Hook Framework
42.Sh SYNOPSIS
43.In sys/hhook.h
44.Ft typedef int
45.Fn "\*(lp*hhook_func_t\*(rp" "int32_t hhook_type" "int32_t hhook_id" \
46"void *udata" "void *ctx_data" "void *hdata" "struct osd *hosd"
47.Fn "int hhook_head_register" "int32_t hhook_type" "int32_t hhook_id" \
48"struct hhook_head **hhh" "uint32_t flags"
49.Fn "int hhook_head_deregister" "struct hhook_head *hhh"
50.Fn "int hhook_head_deregister_lookup" "int32_t hhook_type" "int32_t hhook_id"
51.Fn "void hhook_run_hooks" "struct hhook_head *hhh" "void *ctx_data" \
52"struct osd *hosd"
53.Fn HHOOKS_RUN_IF "hhh" "ctx_data" "hosd"
54.Fn HHOOKS_RUN_LOOKUP_IF "hhook_type" "hhook_id" "ctx_data" "hosd"
55.Sh DESCRIPTION
56.Nm
57provides a framework for managing and running arbitrary hook functions at
58defined hook points within the kernel.
59The KPI was inspired by
60.Xr pfil 9 ,
61and in many respects can be thought of as a more generic superset of pfil.
62.Pp
63The
64.Xr khelp 9
65and
66.Nm
67frameworks are tightly integrated.
68Khelp is responsible for registering and deregistering Khelp module hook
69functions with
70.Nm
71points.
72The KPI functions used by
73.Xr khelp 9
74to do this are not documented here as they are not relevant to consumers wishing
75to instantiate hook points.
76.Ss Information for Khelp Module Implementors
77Khelp modules indirectly interact with
78.Nm
79by defining appropriate hook functions for insertion into hook points.
80Hook functions must conform to the
81.Ft hhook_func_t
82function pointer declaration
83outlined in the
84.Sx SYNOPSIS .
85.Pp
86The
87.Fa hhook_type
88and
89.Fa hhook_id
90arguments identify the hook point which has called into the hook function.
91These are useful when a single hook function is registered for multiple hook
92points and wants to know which hook point has called into it.
93.In sys/hhook.h
94lists available
95.Fa hhook_type
96defines and subsystems which export hook points are responsible for defining
97the
98.Fa hhook_id
99value in appropriate header files.
100.Pp
101The
102.Fa udata
103argument will be passed to the hook function if it was specified in the
104.Vt struct hookinfo
105at hook registration time.
106.Pp
107The
108.Fa ctx_data
109argument contains context specific data from the hook point call site.
110The data type passed is subsystem dependent.
111.Pp
112The
113.Fa hdata
114argument is a pointer to the persistent per-object storage allocated for use by
115the module if required.
116The pointer will only ever be NULL if the module did not request per-object
117storage.
118.Pp
119The
120.Fa hosd
121argument can be used with the
122.Xr khelp 9
123framework's
124.Fn khelp_get_osd
125function to access data belonging to a different Khelp module.
126.Pp
127Khelp modules instruct the Khelp framework to register their hook functions with
128.Nm
129points by creating a
130.Vt "struct hookinfo"
131per hook point, which contains the following members:
132.Bd -literal -offset indent
133struct hookinfo {
134	hhook_func_t	hook_func;
135	struct helper	*hook_helper;
136	void		*hook_udata;
137	int32_t		hook_id;
138	int32_t		hook_type;
139};
140.Ed
141.Pp
142Khelp modules are responsible for setting all members of the struct except
143.Va hook_helper
144which is handled by the Khelp framework.
145.Ss Creating and Managing Hook Points
146Kernel subsystems that wish to provide
147.Nm
148points typically need to make four and possibly five key changes to their
149implementation:
150.Bl -bullet
151.It
152Define a list of
153.Va hhook_id
154mappings in an appropriate subsystem header.
155.It
156Register each hook point with the
157.Fn hhook_head_register
158function during initialisation of the subsystem.
159.It
160Select or create a standardised data type to pass to hook functions as
161contextual data.
162.It
163Add a call to
164.Fn HHOOKS_RUN_IF
165or
166.Fn HHOOKS_RUN_IF_LOOKUP
167at the point in the subsystem's code where the hook point should be executed.
168.It
169If the subsystem can be dynamically added/removed at runtime, each hook
170point registered with the
171.Fn hhook_head_register
172function when the subsystem was initialised needs to be deregistered with the
173.Fn hhook_head_deregister
174or
175.Fn hhook_head_deregister_lookup
176functions when the subsystem is being deinitialised prior to removal.
177.El
178.Pp
179The
180.Fn hhook_head_register
181function registers a hook point with the
182.Nm
183framework.
184The
185.Fa hook_type
186argument defines the high level type for the hook point.
187Valid types are defined in
188.In sys/hhook.h
189and new types should be added as required.
190The
191.Fa hook_id
192argument specifies a unique, subsystem specific identifier for the hook point.
193The
194.Fa hhh
195argument will, if not NULL, be used to store a reference to the
196.Vt struct hhook_head
197created as part of the registration process.
198Subsystems will generally want to store a local copy of the
199.Vt struct hhook_head
200so that they can use the
201.Fn HHOOKS_RUN_IF
202macro to instantiate hook points.
203The HHOOK_WAITOK flag may be passed in via the
204.Fa flags
205argument if
206.Xr malloc 9
207is allowed to sleep waiting for memory to become available.
208If the hook point is within a virtualised subsystem (e.g. the network stack),
209the HHOOK_HEADISINVNET flag should be passed in via the
210.Fa flags
211argument so that the
212.Vt struct hhook_head
213created during the registration process will be added to a virtualised list.
214.Pp
215The
216.Fn hhook_head_deregister
217function deregisters a previously registered hook point from the
218.Nm
219framework.
220The
221.Fa hhh
222argument is the pointer to the
223.Vt struct hhook_head
224returned by
225.Fn hhoook_head_register
226when the hook point was registered.
227.Pp
228The
229.Fn hhook_head_deregister_lookup
230function can be used instead of
231.Fn hhook_head_deregister
232in situations where the caller does not have a cached copy of the
233.Vt struct hhook_head
234and wants to deregister a hook point using the appropriate
235.Fa hook_type
236and
237.Fa hook_id
238identifiers instead.
239.Pp
240The
241.Fn hhook_run_hooks
242function should normally not be called directly and should instead be called
243indirectly via the
244.Fn HHOOKS_RUN_IF
245macro.
246However, there may be circumstances where it is preferable to call the function
247directly, and so it is documented here for completeness.
248The
249.Fa hhh
250argument references the
251.Nm
252point to call all registered hook functions for.
253The
254.Fa ctx_data
255argument specifies a pointer to the contextual hook point data to pass into the
256hook functions.
257The
258.Fa hosd
259argument should be the pointer to the appropriate object's
260.Vt struct osd
261if the subsystem provides the ability for Khelp modules to associate per-object
262data.
263Subsystems which do not should pass NULL.
264.Pp
265The
266.Fn HHOOKS_RUN_IF
267macro is the preferred way to implement hook points.
268It only calls the
269.Fn hhook_run_hooks
270function if at least one hook function is registered for the hook point.
271By checking for registered hook functions, the macro minimises the cost
272associated with adding hook points to frequently used code paths by reducing to
273a simple if test in the common case where no hook functions are registered.
274The arguments are as described for the
275.Fn hhook_run_hooks
276function.
277.Pp
278The
279.Fn HHOOKS_RUN_IF_LOOKUP
280macro performs the same function as the
281.Fn HHOOKS_RUN_IF
282macro, but performs an additional step to look up the
283.Vt struct hhook_head
284for the specified
285.Fa hook_type
286and
287.Fa hook_id
288identifiers.
289It should not be used except in code paths which are infrequently executed
290because of the reference counting overhead associated with the look up.
291.Sh IMPLEMENTATION NOTES
292Each
293.Vt struct hhook_head
294protects its internal list of hook functions with a
295.Xr rmlock 9 .
296Therefore, anytime
297.Fn hhook_run_hooks
298is called directly or indirectly via the
299.Fn HHOOKS_RUN_IF
300or
301.Fn HHOOKS_RUN_IF_LOOKUP
302macros, a non-sleepable read lock will be acquired and held across the calls to
303all registered hook functions.
304.Sh RETURN VALUES
305.Fn hhook_head_register
306returns 0 if no errors occurred.
307It returns EEXIST if a hook point with the same
308.Fa hook_type
309and
310.Fa hook_id
311is already registered.
312It returns EINVAL if the HHOOK_HEADISINVNET flag is not set in
313.Fa flags
314because the implementation does not yet support hook points in non-virtualised
315subsystems (see the
316.Sx BUGS
317section for details).
318It returns ENOMEM if
319.Xr malloc 9
320failed to allocate memory for the new
321.Vt struct hhook_head .
322.Pp
323.Fn hhook_head_deregister
324and
325.Fn hhook_head_deregister_lookup
326return 0 if no errors occurred.
327They return ENOENT if
328.Fa hhh
329is NULL.
330They return EBUSY if the reference count of
331.Fa hhh
332is greater than one.
333.Sh EXAMPLES
334A well commented example Khelp module can be found at:
335.Pa /usr/share/examples/kld/khelp/h_example.c
336.Pp
337The
338.Xr tcp 4
339implementation provides two
340.Nm
341points which are called for packets sent/received when a connection is in the
342established phase.
343Search for HHOOK in the following files:
344.Pa sys/netinet/tcp_var.h ,
345.Pa sys/netinet/tcp_input.c ,
346.Pa sys/netinet/tcp_output.c
347and
348.Pa sys/netinet/tcp_subr.c .
349.Sh SEE ALSO
350.Xr khelp 9
351.Sh ACKNOWLEDGEMENTS
352Development and testing of this software were made possible in part by grants
353from the FreeBSD Foundation and Cisco University Research Program Fund at
354Community Foundation Silicon Valley.
355.Sh HISTORY
356The
357.Nm
358framework first appeared in
359.Fx 9.0 .
360.Pp
361The
362.Nm
363framework was first released in 2010 by Lawrence Stewart whilst studying at
364Swinburne University of Technology's Centre for Advanced Internet Architectures,
365Melbourne, Australia.
366More details are available at:
367.Pp
368http://caia.swin.edu.au/urp/newtcp/
369.Sh AUTHORS
370.An -nosplit
371The
372.Nm
373framework was written by
374.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org .
375.Pp
376This manual page was written by
377.An David Hayes Aq Mt david.hayes@ieee.org
378and
379.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org .
380