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