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