Path: blob/main/share/examples/kld/khelp/h_example.c
104132 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2010-2011 The FreeBSD Foundation4*5* This software was developed at the Centre for Advanced Internet6* Architectures, Swinburne University of Technology, Melbourne, Australia by7* Lawrence Stewart under sponsorship from the FreeBSD Foundation.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND19* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE20* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE22* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL23* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS24* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)25* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT26* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY27* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF28* SUCH DAMAGE.29*/3031/*32* This example Khelp module uses the helper hook points available in the TCP33* stack to calculate a per-connection count of inbound and outbound packets34* when the connection is in the established state. The code is verbosely35* documented in an attempt to explain how everything fits together.36*/3738#include <sys/param.h>39#include <sys/kernel.h>40#include <sys/hhook.h>41#include <sys/khelp.h>42#include <sys/module.h>43#include <sys/module_khelp.h>44#include <sys/socket.h>45#include <sys/socketvar.h>4647#include <netinet/in.h>48#include <netinet/in_pcb.h>49#include <netinet/tcp_var.h>5051#include <vm/uma.h>5253/*54* Function prototype for our helper hook (man 9 hhook) compatible hook55* function.56*/57static int example_hook(int hhook_type, int hhook_id, void *udata,58void *ctx_data, void *hdata, struct osd *hosd);5960/*61* Our per-connection persistent data storage struct.62*/63struct example {64uint32_t est_in_count;65uint32_t est_out_count;66};6768/*69* Fill in the required bits of our module's struct helper (defined in70* <sys/module_khelp.h>).71*72* - Our helper will be storing persistent state for each TCP connection, so we73* request the use the Object Specific Data (OSD) feature from the framework by74* setting the HELPER_NEEDS_OSD flag.75*76* - Our helper is related to the TCP subsystem, so tell the Khelp framework77* this by setting an appropriate class for the module. When a new TCP78* connection is created, the Khelp framework takes care of associating helper79* modules of the appropriate class with the new connection.80*/81struct helper example_helper = {82.h_flags = HELPER_NEEDS_OSD,83.h_classes = HELPER_CLASS_TCP84};8586/*87* Set which helper hook points our module wants to hook by creating an array of88* hookinfo structs (defined in <sys/hhook.h>). We hook the TCP established89* inbound/outbound hook points (TCP hhook points are defined in90* <netinet/tcp_var.h>) with our example_hook() function. We don't require a user91* data pointer to be passed to our hook function when called, so we set it to92* NULL.93*/94struct hookinfo example_hooks[] = {95{96.hook_type = HHOOK_TYPE_TCP,97.hook_id = HHOOK_TCP_EST_IN,98.hook_udata = NULL,99.hook_func = &example_hook100},101{102.hook_type = HHOOK_TYPE_TCP,103.hook_id = HHOOK_TCP_EST_OUT,104.hook_udata = NULL,105.hook_func = &example_hook106}107};108109/*110* Very simple helper hook function. Here's a quick run through the arguments:111*112* - hhook_type and hhook_id are useful if you use a single function with many113* hook points and want to know which hook point called the function.114*115* - udata will be NULL, because we didn't elect to pass a pointer in either of116* the hookinfo structs we instantiated above in the example_hooks array.117*118* - ctx_data contains context specific data from the hook point call site. The119* data type passed is subsystem dependent. In the case of TCP, the hook points120* pass a pointer to a "struct tcp_hhook_data" (defined in <netinet/tcp_var.h>).121*122* - hdata is a pointer to the persistent per-object storage for our module. The123* pointer is allocated automagically by the Khelp framework when the connection124* is created, and comes from a dedicated UMA zone. It will never be NULL.125*126* - hosd can be used with the Khelp framework's khelp_get_osd() function to127* access data belonging to a different Khelp module.128*/129static int130example_hook(int hhook_type, int hhook_id, void *udata, void *ctx_data,131void *hdata, struct osd *hosd)132{133struct example *data;134135data = hdata;136137if (hhook_id == HHOOK_TCP_EST_IN)138data->est_in_count++;139else if (hhook_id == HHOOK_TCP_EST_OUT)140data->est_out_count++;141142return (0);143}144145/*146* We use a convenient macro which handles registering our module with the Khelp147* framework. Note that Khelp modules which set the HELPER_NEEDS_OSD flag (i.e.148* require persistent per-object storage) must use the KHELP_DECLARE_MOD_UMA()149* macro. If you don't require per-object storage, use the KHELP_DECLARE_MOD()150* macro instead.151*/152KHELP_DECLARE_MOD_UMA(example, &example_helper, example_hooks, 1,153sizeof(struct example), NULL, NULL);154155156