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.\" $FreeBSD$ 31.\" 32.Dd June 21, 2013 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 of Technology's Centre for Advanced Internet Architectures, 367Melbourne, Australia. 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 Mt lstewart@FreeBSD.org . 377.Pp 378This manual page was written by 379.An David Hayes Aq Mt david.hayes@ieee.org 380and 381.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org . 382