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