1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2018 Joyent, Inc. All rights reserved. 26 * Copyright (c) 2016 by Delphix. All rights reserved. 27 */ 28 #include <sys/param.h> 29 #include <sys/types.h> 30 #include <sys/systm.h> 31 #include <sys/errno.h> 32 #include <sys/kmem.h> 33 #include <sys/mutex.h> 34 #include <sys/condvar.h> 35 #include <sys/modctl.h> 36 #include <sys/hook_impl.h> 37 #include <sys/sdt.h> 38 #include <sys/cmn_err.h> 39 40 /* 41 * This file provides kernel hook framework. 42 */ 43 44 static struct modldrv modlmisc = { 45 &mod_miscops, /* drv_modops */ 46 "Hooks Interface v1.0", /* drv_linkinfo */ 47 }; 48 49 static struct modlinkage modlinkage = { 50 MODREV_1, /* ml_rev */ 51 &modlmisc, /* ml_linkage */ 52 NULL 53 }; 54 55 static const char *hook_hintvalue_none = "<none>"; 56 57 /* 58 * How it works. 59 * ============= 60 * Use of the hook framework here is tied up with zones - when a new zone 61 * is created, we create a new hook_stack_t and are open to business for 62 * allowing new hook families and their events. 63 * 64 * A consumer of these hooks is expected to operate in this fashion: 65 * 1) call hook_family_add() to create a new family of hooks. It is a 66 * current requirement that this call must be made with the value 67 * returned from hook_stack_init, by way of infrastructure elsewhere. 68 * 2) add events to the registered family with calls to hook_event_add. 69 * 70 * At this point, the structures in place should be open to others to 71 * add hooks to the event or add notifiers for when the contents of the 72 * hook stack changes. 73 * 74 * The interesting stuff happens on teardown. 75 * 76 * It is a requirement that the provider of hook events work in the reverse 77 * order to the above, so that the first step is: 78 * 1) remove events from each hook family created earlier 79 * 2) remove hook families from the hook stack. 80 * 81 * When doing teardown of both events and families, a check is made to see 82 * if either structure is still "busy". If so then a boolean flag (FWF_DESTROY) 83 * is set to say that the structure is condemned. The presence of this flag 84 * being set must be checked for in _add()/_register()/ functions and a 85 * failure returned if it is set. It is ignored by the _find() functions 86 * because they're used by _remove()/_unregister(). 87 * While setting the condemned flag when trying to delete a structure would 88 * normally be keyed from the presence of a reference count being greater 89 * than 1, in this implementation there are no reference counts required: 90 * instead the presence of objects on linked lists is taken to mean 91 * something is still "busy." 92 * 93 * ONLY the caller that adds the family and the events ever has a direct 94 * reference to the internal structures and thus ONLY it should be doing 95 * the removal of either the event or family. In practise, what this means 96 * is that in ip_netinfo.c, we have calls to net_protocol_register(), followed 97 * by net_event_register() (these interface to hook_family_add() and 98 * hook_event_add(), respectively) that are made when we create an instance 99 * of IP and when the IP instance is shutdown/destroyed, it calls 100 * net_event_unregister() and net_protocol_unregister(), which in turn call 101 * hook_event_remove() and hook_family_remove() respectively. Nobody else 102 * is entitled to call the _unregister() functions. It is imperative that 103 * there be only one _remove() call for every _add() call. 104 * 105 * It is possible that code which is interfacing with this hook framework 106 * won't do all the cleaning up that it needs to at the right time. While 107 * we can't prevent programmers from creating memory leaks, we can synchronise 108 * when we clean up data structures to prevent code accessing free'd memory. 109 * 110 * A simple diagram showing the ownership is as follows: 111 * 112 * Owned +--------------+ 113 * by | hook_stack_t | 114 * the +--------------+ 115 * Instance | 116 * - - - - - - - -|- - - - - - - - - - - - - - - - - - 117 * V 118 * Owned +-------------------+ +-------------------+ 119 * | hook_family_int_t |---->| hook_family_int_t | 120 * by +-------------------+ +-------------------+ 121 * | \+---------------+ \+---------------+ 122 * network | | hook_family_t | | hook_family_t | 123 * V +---------------+ +---------------+ 124 * protocol +------------------+ +------------------+ 125 * | hook_event_int_t |---->| hook_event_int_t | 126 * (ipv4,ipv6) +------------------+ +------------------+ 127 * | \+--------------+ \+--------------+ 128 * | | hook_event_t | | hook_event_t | 129 * | +--------------+ +--------------+ 130 * - - - - - - - -|- - - - - - - - - - - - - - - - - - 131 * V 132 * Owned +------------+ 133 * | hook_int_t | 134 * by +------------+ 135 * \+--------+ 136 * the consumer | hook_t | 137 * +--------+ 138 * 139 * The consumers, such as IPFilter, do not have any pointers or hold any 140 * references to hook_int_t, hook_event_t or hook_event_int_t. By placing 141 * a hook on an event through net_hook_register(), an implicit reference 142 * to the hook_event_int_t is returned with a successful call. Additionally, 143 * IPFilter does not see the hook_family_int_t or hook_family_t directly. 144 * Rather it is returned a net_handle_t (from net_protocol_lookup()) that 145 * contains a pointer to hook_family_int_t. The structure behind the 146 * net_handle_t (struct net_data) *is* reference counted and managed 147 * appropriately. 148 * 149 * A more detailed picture that describes how the family/event structures 150 * are linked together can be found in <sys/hook_impl.h> 151 * 152 * Notification callbacks. 153 * ======================= 154 * For each of the hook stack, hook family and hook event, it is possible 155 * to request notificatin of change to them. Why? 156 * First, lets equate the hook stack to an IP instance, a hook family to 157 * a network protocol and a hook event to IP packets on the input path. 158 * If a kernel module wants to apply security from the very start of 159 * things, it needs to know as soon as a new instance of networking 160 * is initiated. Whilst for the global zone, it is taken for granted that 161 * this instance will always exist before any interaction takes place, 162 * that is not true for zones running with an exclusive networking instance. 163 * Thus when a local zone is started and a new instance is created to support 164 * that, parties that wish to monitor it and apply a security policy from 165 * the onset need to be informed as early as possible - quite probably 166 * before any networking is started by the zone's boot scripts. 167 * Inside each instance, it is possible to have a number of network protocols 168 * (hook families) in operation. Inside the context of the global zone, 169 * it is possible to have code run before the kernel module providing the 170 * IP networking is loaded. From here, to apply the appropriate security, 171 * it is necessary to become informed of when IP is being configured into 172 * the zone and this is done by registering a notification callback with 173 * the hook stack for changes to it. The next step is to know when packets 174 * can be received through the physical_in, etc, events. This is achieved 175 * by registering a callback with the appropriate network protocol (or in 176 * this file, the correct hook family.) Thus when IP finally attaches a 177 * physical_in event to inet, the module looking to enforce a security 178 * policy can become aware of it being present. Of course there's no 179 * requirement for such a module to be present before all of the above 180 * happens and in such a case, it is reasonable for the same module to 181 * work after everything has been put in place. For this reason, when 182 * a notification callback is added, a series of fake callback events 183 * is generated to simulate the arrival of those entities. There is one 184 * final series of callbacks that can be registered - those to monitor 185 * actual hooks that are added or removed from an event. In practice, 186 * this is useful when there are multiple kernel modules participating 187 * in the processing of packets and there are behaviour dependencies 188 * involved, such that one kernel module might only register its hook 189 * if another is already present and also might want to remove its hook 190 * when the other disappears. 191 * 192 * If you know a kernel module will not be loaded before the infrastructure 193 * used in this file is present then it is not necessary to use this 194 * notification callback mechanism. 195 */ 196 197 /* 198 * Locking 199 * ======= 200 * The use of CVW_* macros to do locking is driven by the need to allow 201 * recursive locking with read locks when we're processing packets. This 202 * is necessary because various netinfo functions need to hold read locks, 203 * by design, as they can be called in or out of packet context. 204 */ 205 /* 206 * Hook internal functions 207 */ 208 static hook_int_t *hook_copy(hook_t *src); 209 static hook_event_int_t *hook_event_checkdup(hook_event_t *he, 210 hook_stack_t *hks); 211 static hook_event_int_t *hook_event_copy(hook_event_t *src); 212 static hook_event_int_t *hook_event_find(hook_family_int_t *hfi, char *event); 213 static void hook_event_free(hook_event_int_t *hei, hook_family_int_t *hfi); 214 static hook_family_int_t *hook_family_copy(hook_family_t *src); 215 static hook_family_int_t *hook_family_find(char *family, hook_stack_t *hks); 216 static void hook_family_free(hook_family_int_t *hfi, hook_stack_t *hks); 217 static hook_int_t *hook_find(hook_event_int_t *hei, hook_t *h); 218 static void hook_int_free(hook_int_t *hi, netstackid_t); 219 static void hook_init(void); 220 static void hook_fini(void); 221 static void *hook_stack_init(netstackid_t stackid, netstack_t *ns); 222 static void hook_stack_fini(netstackid_t stackid, void *arg); 223 static void hook_stack_shutdown(netstackid_t stackid, void *arg); 224 static int hook_insert(hook_int_head_t *head, hook_int_t *new); 225 static void hook_insert_plain(hook_int_head_t *head, hook_int_t *new); 226 static int hook_insert_afterbefore(hook_int_head_t *head, hook_int_t *new); 227 static hook_int_t *hook_find_byname(hook_int_head_t *head, char *name); 228 static void hook_event_init_kstats(hook_family_int_t *, hook_event_int_t *); 229 static void hook_event_notify_run(hook_event_int_t *, hook_family_int_t *, 230 char *event, char *name, hook_notify_cmd_t cmd); 231 static void hook_init_kstats(hook_family_int_t *hfi, hook_event_int_t *hei, 232 hook_int_t *hi); 233 static int hook_notify_register(hook_notify_head_t *head, 234 hook_notify_fn_t callback, void *arg); 235 static int hook_notify_unregister(hook_notify_head_t *head, 236 hook_notify_fn_t callback, void **); 237 static void hook_notify_run(hook_notify_head_t *head, char *family, 238 char *event, char *name, hook_notify_cmd_t cmd); 239 static void hook_stack_notify_run(hook_stack_t *hks, char *name, 240 hook_notify_cmd_t cmd); 241 static void hook_stack_remove(hook_stack_t *hks); 242 243 /* 244 * A list of the hook stacks is kept here because we need to enable 245 * net_instance_notify_register() to be called during the creation 246 * of a new instance. Previously hook_stack_get() would just use 247 * the netstack functions for this work but they will return NULL 248 * until the zone has been fully initialised. 249 */ 250 static hook_stack_head_t hook_stacks; 251 static kmutex_t hook_stack_lock; 252 253 /* 254 * Module entry points. 255 */ 256 int 257 _init(void) 258 { 259 int error; 260 261 hook_init(); 262 error = mod_install(&modlinkage); 263 if (error != 0) 264 hook_fini(); 265 266 return (error); 267 } 268 269 int 270 _fini(void) 271 { 272 int error; 273 274 error = mod_remove(&modlinkage); 275 if (error == 0) 276 hook_fini(); 277 278 return (error); 279 } 280 281 int 282 _info(struct modinfo *modinfop) 283 { 284 return (mod_info(&modlinkage, modinfop)); 285 } 286 287 /* 288 * Function: hook_init 289 * Returns: None 290 * Parameters: None 291 * 292 * Initialize hooks 293 */ 294 static void 295 hook_init(void) 296 { 297 mutex_init(&hook_stack_lock, NULL, MUTEX_DRIVER, NULL); 298 SLIST_INIT(&hook_stacks); 299 300 /* 301 * We want to be informed each time a stack is created or 302 * destroyed in the kernel. 303 */ 304 netstack_register(NS_HOOK, hook_stack_init, hook_stack_shutdown, 305 hook_stack_fini); 306 } 307 308 /* 309 * Function: hook_fini 310 * Returns: None 311 * Parameters: None 312 * 313 * Deinitialize hooks 314 */ 315 static void 316 hook_fini(void) 317 { 318 netstack_unregister(NS_HOOK); 319 320 mutex_destroy(&hook_stack_lock); 321 ASSERT(SLIST_EMPTY(&hook_stacks)); 322 } 323 324 /* 325 * Function: hook_wait_setflag 326 * Returns: -1 = setting flag is disallowed, 0 = flag set and did 327 * not have to wait (ie no lock droped), 1 = flag set but 328 * it was necessary to drop locks to set it. 329 * Parameters: waiter(I) - control data structure 330 * busyset(I) - set of flags that we don't want set while 331 * we are active. 332 * wanted(I) - flag associated with newflag to indicate 333 * what we want to do. 334 * newflag(I) - the new ACTIVE flag we want to set that 335 * indicates what we are doing. 336 * 337 * The set of functions hook_wait_* implement an API that builds on top of 338 * the kcondvar_t to provide controlled execution through a critical region. 339 * For each flag that indicates work is being done (FWF_*_ACTIVE) there is 340 * also a flag that we set to indicate that we want to do it (FWF_*_WANTED). 341 * The combination of flags is required as when this function exits to do 342 * the task, the structure is then free for another caller to use and 343 * to indicate that it wants to do work. The flags used when a caller wants 344 * to destroy an object take precedence over those that are used for making 345 * changes to it (add/remove.) In this case, we don't try to secure the 346 * ability to run and return with an error. 347 * 348 * "wantedset" is used here to determine who has the right to clear the 349 * wanted bit from the fw_flags set: only whomever sets the flag has the 350 * right to clear it at the bottom of the loop, even if someone else 351 * wants to set it. 352 * 353 * wanted - the FWF_*_WANTED flag that describes the action being requested 354 * busyset- the set of FWF_* flags we don't want set when we run 355 * newflag- the FWF_*_ACTIVE flag we will set to indicate we are busy 356 */ 357 int 358 hook_wait_setflag(flagwait_t *waiter, uint32_t busyset, fwflag_t wanted, 359 fwflag_t newflag) 360 { 361 boolean_t wantedset; 362 int waited = 0; 363 364 mutex_enter(&waiter->fw_lock); 365 if (waiter->fw_flags & FWF_DESTROY) { 366 cv_signal(&waiter->fw_cv); 367 mutex_exit(&waiter->fw_lock); 368 return (-1); 369 } 370 while (waiter->fw_flags & busyset) { 371 wantedset = ((waiter->fw_flags & wanted) == wanted); 372 if (!wantedset) 373 waiter->fw_flags |= wanted; 374 CVW_EXIT_WRITE(waiter->fw_owner); 375 cv_wait(&waiter->fw_cv, &waiter->fw_lock); 376 /* 377 * This lock needs to be dropped here to preserve the order 378 * of acquisition that is fw_owner followed by fw_lock, else 379 * we can deadlock. 380 */ 381 mutex_exit(&waiter->fw_lock); 382 waited = 1; 383 CVW_ENTER_WRITE(waiter->fw_owner); 384 mutex_enter(&waiter->fw_lock); 385 if (!wantedset) 386 waiter->fw_flags &= ~wanted; 387 if (waiter->fw_flags & FWF_DESTROY) { 388 cv_signal(&waiter->fw_cv); 389 mutex_exit(&waiter->fw_lock); 390 return (-1); 391 } 392 } 393 waiter->fw_flags &= ~wanted; 394 ASSERT((waiter->fw_flags & wanted) == 0); 395 ASSERT((waiter->fw_flags & newflag) == 0); 396 waiter->fw_flags |= newflag; 397 mutex_exit(&waiter->fw_lock); 398 return (waited); 399 } 400 401 /* 402 * Function: hook_wait_unsetflag 403 * Returns: None 404 * Parameters: waiter(I) - control data structure 405 * oldflag(I) - flag to reset 406 * 407 * Turn off the bit that we had set to run and let others know that 408 * they should now check to see if they can run. 409 */ 410 void 411 hook_wait_unsetflag(flagwait_t *waiter, fwflag_t oldflag) 412 { 413 mutex_enter(&waiter->fw_lock); 414 waiter->fw_flags &= ~oldflag; 415 cv_signal(&waiter->fw_cv); 416 mutex_exit(&waiter->fw_lock); 417 } 418 419 /* 420 * Function: hook_wait_destroy 421 * Returns: None 422 * Parameters: waiter(I) - control data structure 423 * 424 * Since outer locking (on fw_owner) should ensure that only one function 425 * at a time gets to call hook_wait_destroy() on a given object, there is 426 * no need to guard against setting FWF_DESTROY_WANTED already being set. 427 * It is, however, necessary to wait for all activity on the owning 428 * structure to cease. 429 */ 430 int 431 hook_wait_destroy(flagwait_t *waiter) 432 { 433 ASSERT((waiter->fw_flags & FWF_DESTROY_WANTED) == 0); 434 mutex_enter(&waiter->fw_lock); 435 if (waiter->fw_flags & FWF_DESTROY_WANTED) { 436 cv_signal(&waiter->fw_cv); 437 mutex_exit(&waiter->fw_lock); 438 return (EINPROGRESS); 439 } 440 waiter->fw_flags |= FWF_DESTROY_WANTED; 441 while (!FWF_DESTROY_OK(waiter)) { 442 CVW_EXIT_WRITE(waiter->fw_owner); 443 cv_wait(&waiter->fw_cv, &waiter->fw_lock); 444 CVW_ENTER_WRITE(waiter->fw_owner); 445 } 446 /* 447 * There should now be nothing else using "waiter" or its 448 * owner, so we can safely assign here without risk of wiiping 449 * out someone's bit. 450 */ 451 waiter->fw_flags = FWF_DESTROY_ACTIVE; 452 cv_signal(&waiter->fw_cv); 453 mutex_exit(&waiter->fw_lock); 454 455 return (0); 456 } 457 458 /* 459 * Function: hook_wait_init 460 * Returns: None 461 * Parameters: waiter(I) - control data structure 462 * ownder(I) - pointer to lock that the owner of this 463 * waiter uses 464 * 465 * "owner" gets passed in here so that when we need to call cv_wait, 466 * for example in hook_wait_setflag(), we can drop the lock for the 467 * next layer out, which is likely to be held in an exclusive manner. 468 */ 469 void 470 hook_wait_init(flagwait_t *waiter, cvwaitlock_t *owner) 471 { 472 cv_init(&waiter->fw_cv, NULL, CV_DRIVER, NULL); 473 mutex_init(&waiter->fw_lock, NULL, MUTEX_DRIVER, NULL); 474 waiter->fw_flags = FWF_NONE; 475 waiter->fw_owner = owner; 476 } 477 478 /* 479 * Function: hook_stack_init 480 * Returns: void * - pointer to new hook stack structure 481 * Parameters: stackid(I) - identifier for the network instance that owns this 482 * ns(I) - pointer to the network instance data structure 483 * 484 * Allocate and initialize the hook stack instance. This function is not 485 * allowed to fail, so KM_SLEEP is used here when allocating memory. The 486 * value returned is passed back into the shutdown and destroy hooks. 487 */ 488 /*ARGSUSED*/ 489 static void * 490 hook_stack_init(netstackid_t stackid, netstack_t *ns) 491 { 492 hook_stack_t *hks; 493 494 #ifdef NS_DEBUG 495 printf("hook_stack_init(stack %d)\n", stackid); 496 #endif 497 498 hks = (hook_stack_t *)kmem_zalloc(sizeof (*hks), KM_SLEEP); 499 hks->hks_netstack = ns; 500 hks->hks_netstackid = stackid; 501 502 CVW_INIT(&hks->hks_lock); 503 TAILQ_INIT(&hks->hks_nhead); 504 SLIST_INIT(&hks->hks_familylist); 505 506 hook_wait_init(&hks->hks_waiter, &hks->hks_lock); 507 508 mutex_enter(&hook_stack_lock); 509 SLIST_INSERT_HEAD(&hook_stacks, hks, hks_entry); 510 mutex_exit(&hook_stack_lock); 511 512 return (hks); 513 } 514 515 /* 516 * Function: hook_stack_shutdown 517 * Returns: void 518 * Parameters: stackid(I) - identifier for the network instance that owns this 519 * arg(I) - pointer returned by hook_stack_init 520 * 521 * Set the shutdown flag to indicate that we should stop accepting new 522 * register calls as we're now in the cleanup process. The cleanup is a 523 * two stage process and we're not required to free any memory here. 524 * 525 * The curious would wonder why isn't there any code that walks through 526 * all of the data structures and sets the flag(s) there? The answer is 527 * that it is expected that this will happen when the zone shutdown calls 528 * the shutdown callbacks for other modules that they will initiate the 529 * free'ing and shutdown of the hooks themselves. 530 */ 531 /*ARGSUSED*/ 532 static void 533 hook_stack_shutdown(netstackid_t stackid, void *arg) 534 { 535 hook_stack_t *hks = (hook_stack_t *)arg; 536 537 mutex_enter(&hook_stack_lock); 538 /* 539 * Once this flag gets set to one, no more additions are allowed 540 * to any of the structures that make up this stack. 541 */ 542 hks->hks_shutdown = 1; 543 mutex_exit(&hook_stack_lock); 544 } 545 546 /* 547 * Function: hook_stack_destroy 548 * Returns: void 549 * Parameters: stackid(I) - identifier for the network instance that owns this 550 * arg(I) - pointer returned by hook_stack_init 551 * 552 * Free the hook stack instance. 553 * 554 * The rationale for the shutdown being lazy (see the comment above for 555 * hook_stack_shutdown) also applies to the destroy being lazy. Only if 556 * the hook_stack_t data structure is unused will it go away. Else it 557 * is left up to the last user of a data structure to actually free it. 558 */ 559 /*ARGSUSED*/ 560 static void 561 hook_stack_fini(netstackid_t stackid, void *arg) 562 { 563 hook_stack_t *hks = (hook_stack_t *)arg; 564 565 mutex_enter(&hook_stack_lock); 566 hks->hks_shutdown = 2; 567 hook_stack_remove(hks); 568 mutex_exit(&hook_stack_lock); 569 } 570 571 /* 572 * Function: hook_stack_remove 573 * Returns: void 574 * Parameters: hks(I) - pointer to an instance of a hook_stack_t 575 * 576 * This function assumes that it is called with hook_stack_lock held. 577 * It functions differently to hook_family/event_remove in that it does 578 * the checks to see if it can be removed. This difference exists 579 * because this structure has nothing higher up that depends on it. 580 */ 581 static void 582 hook_stack_remove(hook_stack_t *hks) 583 { 584 585 ASSERT(mutex_owned(&hook_stack_lock)); 586 587 /* 588 * Is the structure still in use? 589 */ 590 if (!SLIST_EMPTY(&hks->hks_familylist) || 591 !TAILQ_EMPTY(&hks->hks_nhead)) 592 return; 593 594 SLIST_REMOVE(&hook_stacks, hks, hook_stack, hks_entry); 595 596 VERIFY(hook_wait_destroy(&hks->hks_waiter) == 0); 597 CVW_DESTROY(&hks->hks_lock); 598 kmem_free(hks, sizeof (*hks)); 599 } 600 601 /* 602 * Function: hook_stack_get 603 * Returns: hook_stack_t * - NULL if not found, else matching instance 604 * Parameters: stackid(I) - instance id to search for 605 * 606 * Search the list of currently active hook_stack_t structures for one that 607 * has a matching netstackid_t to the value passed in. The linked list can 608 * only ever have at most one match for this value. 609 */ 610 static hook_stack_t * 611 hook_stack_get(netstackid_t stackid) 612 { 613 hook_stack_t *hks; 614 615 SLIST_FOREACH(hks, &hook_stacks, hks_entry) { 616 if (hks->hks_netstackid == stackid) 617 break; 618 } 619 620 return (hks); 621 } 622 623 /* 624 * Function: hook_stack_notify_register 625 * Returns: int - 0 = success, else failure 626 * Parameters: stackid(I) - netstack identifier 627 * callback(I)- function to be called 628 * arg(I) - arg to provide callback when it is called 629 * 630 * If we're not shutting down this instance, append a new function to the 631 * list of those to call when a new family of hooks is added to this stack. 632 * If the function can be successfully added to the list of callbacks 633 * activated when there is a change to the stack (addition or removal of 634 * a hook family) then generate a fake HN_REGISTER event by directly 635 * calling the callback with the relevant information for each hook 636 * family that currently exists (and isn't being shutdown.) 637 */ 638 int 639 hook_stack_notify_register(netstackid_t stackid, hook_notify_fn_t callback, 640 void *arg) 641 { 642 hook_family_int_t *hfi; 643 hook_stack_t *hks; 644 boolean_t canrun; 645 char buffer[16]; 646 int error; 647 648 ASSERT(callback != NULL); 649 650 canrun = B_FALSE; 651 mutex_enter(&hook_stack_lock); 652 hks = hook_stack_get(stackid); 653 if (hks != NULL) { 654 if (hks->hks_shutdown != 0) { 655 error = ESHUTDOWN; 656 } else { 657 CVW_ENTER_WRITE(&hks->hks_lock); 658 canrun = (hook_wait_setflag(&hks->hks_waiter, 659 FWF_ADD_WAIT_MASK, FWF_ADD_WANTED, 660 FWF_ADD_ACTIVE) != -1); 661 error = hook_notify_register(&hks->hks_nhead, 662 callback, arg); 663 CVW_EXIT_WRITE(&hks->hks_lock); 664 } 665 } else { 666 error = ESRCH; 667 } 668 mutex_exit(&hook_stack_lock); 669 670 if (error == 0 && canrun) { 671 /* 672 * Generate fake register event for callback that 673 * is being added, letting it know everything that 674 * already exists. 675 */ 676 (void) snprintf(buffer, sizeof (buffer), "%u", 677 hks->hks_netstackid); 678 679 SLIST_FOREACH(hfi, &hks->hks_familylist, hfi_entry) { 680 if (hfi->hfi_condemned || hfi->hfi_shutdown) 681 continue; 682 callback(HN_REGISTER, arg, buffer, NULL, 683 hfi->hfi_family.hf_name); 684 } 685 } 686 687 if (canrun) 688 hook_wait_unsetflag(&hks->hks_waiter, FWF_ADD_ACTIVE); 689 690 return (error); 691 } 692 693 /* 694 * Function: hook_stack_notify_unregister 695 * Returns: int - 0 = success, else failure 696 * Parameters: stackid(I) - netstack identifier 697 * callback(I) - function to be called 698 * 699 * Attempt to remove a registered function from a hook stack's list of 700 * callbacks to activiate when protocols are added/deleted. 701 * As with hook_stack_notify_register, if all things are going well then 702 * a fake unregister event is delivered to the callback being removed 703 * for each hook family that presently exists. 704 */ 705 int 706 hook_stack_notify_unregister(netstackid_t stackid, hook_notify_fn_t callback) 707 { 708 hook_family_int_t *hfi; 709 hook_stack_t *hks; 710 char buffer[16]; 711 void *arg; 712 int error; 713 714 mutex_enter(&hook_stack_lock); 715 hks = hook_stack_get(stackid); 716 if (hks == NULL) { 717 mutex_exit(&hook_stack_lock); 718 return (ESRCH); 719 } 720 721 CVW_ENTER_WRITE(&hks->hks_lock); 722 /* 723 * If hook_wait_setflag returns -1, another thread has flagged that it 724 * is attempting to destroy this hook stack. Before it can flag that 725 * it's destroying the hook stack, it must first verify (with 726 * hook_stack_lock held) that the hook stack is empty. If we 727 * encounter this, it means we should have nothing to do and we 728 * just snuck in. 729 */ 730 if (hook_wait_setflag(&hks->hks_waiter, FWF_DEL_WAIT_MASK, 731 FWF_DEL_WANTED, FWF_DEL_ACTIVE) == -1) { 732 VERIFY(TAILQ_EMPTY(&hks->hks_nhead)); 733 CVW_EXIT_WRITE(&hks->hks_lock); 734 mutex_exit(&hook_stack_lock); 735 return (ESRCH); 736 } 737 738 error = hook_notify_unregister(&hks->hks_nhead, callback, &arg); 739 CVW_EXIT_WRITE(&hks->hks_lock); 740 mutex_exit(&hook_stack_lock); 741 742 if (error == 0) { 743 /* 744 * Generate fake unregister event for callback that 745 * is being removed, letting it know everything that 746 * currently exists is now "disappearing." 747 */ 748 (void) snprintf(buffer, sizeof (buffer), "%u", 749 hks->hks_netstackid); 750 751 SLIST_FOREACH(hfi, &hks->hks_familylist, hfi_entry) { 752 callback(HN_UNREGISTER, arg, buffer, NULL, 753 hfi->hfi_family.hf_name); 754 } 755 } else { 756 /* 757 * hook_notify_unregister() should only fail if the callback has 758 * already been deleted (ESRCH). 759 */ 760 VERIFY3S(error, ==, ESRCH); 761 } 762 763 mutex_enter(&hook_stack_lock); 764 hook_wait_unsetflag(&hks->hks_waiter, FWF_DEL_ACTIVE); 765 if (hks->hks_shutdown == 2) 766 hook_stack_remove(hks); 767 mutex_exit(&hook_stack_lock); 768 769 return (error); 770 } 771 772 /* 773 * Function: hook_stack_notify_run 774 * Returns: None 775 * Parameters: hks(I) - hook stack pointer to execute callbacks for 776 * name(I) - name of a hook family 777 * cmd(I) - either HN_UNREGISTER or HN_REGISTER 778 * 779 * Run through the list of callbacks on the hook stack to be called when 780 * a new hook family is added 781 * 782 * As hook_notify_run() expects 3 names, one for the family that is associated 783 * with the cmd (HN_REGISTER or HN_UNREGISTER), one for the event and one 784 * for the object being introduced and we really only have one name (that 785 * of the new hook family), fake the hook stack's name by converting the 786 * integer to a string and for the event just pass NULL. 787 */ 788 static void 789 hook_stack_notify_run(hook_stack_t *hks, char *name, 790 hook_notify_cmd_t cmd) 791 { 792 char buffer[16]; 793 794 ASSERT(hks != NULL); 795 ASSERT(name != NULL); 796 797 (void) snprintf(buffer, sizeof (buffer), "%u", hks->hks_netstackid); 798 799 hook_notify_run(&hks->hks_nhead, buffer, NULL, name, cmd); 800 } 801 802 /* 803 * Function: hook_run 804 * Returns: int - return value according to callback func 805 * Parameters: token(I) - event pointer 806 * info(I) - message 807 * 808 * Run hooks for specific provider. The hooks registered are stepped through 809 * until either the end of the list is reached or a hook function returns a 810 * non-zero value. If a non-zero value is returned from a hook function, we 811 * return that value back to our caller. By design, a hook function can be 812 * called more than once, simultaneously. 813 */ 814 int 815 hook_run(hook_family_int_t *hfi, hook_event_token_t token, hook_data_t info) 816 { 817 hook_event_int_t *hei; 818 hook_int_t *hi; 819 int rval = 0; 820 821 ASSERT(token != NULL); 822 823 hei = (hook_event_int_t *)token; 824 DTRACE_PROBE2(hook__run__start, 825 hook_event_token_t, token, 826 hook_data_t, info); 827 828 /* 829 * If we consider that this function is only called from within the 830 * stack while an instance is currently active, 831 */ 832 CVW_ENTER_READ(&hfi->hfi_lock); 833 834 TAILQ_FOREACH(hi, &hei->hei_head, hi_entry) { 835 ASSERT(hi->hi_hook.h_func != NULL); 836 DTRACE_PROBE3(hook__func__start, 837 hook_event_token_t, token, 838 hook_data_t, info, 839 hook_int_t *, hi); 840 rval = (*hi->hi_hook.h_func)(token, info, hi->hi_hook.h_arg); 841 DTRACE_PROBE4(hook__func__end, 842 hook_event_token_t, token, 843 hook_data_t, info, 844 hook_int_t *, hi, 845 int, rval); 846 hi->hi_kstats.hook_hits.value.ui64++; 847 if (rval != 0) 848 break; 849 } 850 851 hei->hei_kstats.events.value.ui64++; 852 853 CVW_EXIT_READ(&hfi->hfi_lock); 854 855 DTRACE_PROBE3(hook__run__end, 856 hook_event_token_t, token, 857 hook_data_t, info, 858 hook_int_t *, hi); 859 860 return (rval); 861 } 862 863 /* 864 * Function: hook_family_add 865 * Returns: internal family pointer - NULL = Fail 866 * Parameters: hf(I) - family pointer 867 * hks(I) - pointer to an instance of a hook_stack_t 868 * store(O) - where returned pointer will be stored 869 * 870 * Add new family to the family list. The requirements for the addition to 871 * succeed are that the family name must not already be registered and that 872 * the hook stack is not being shutdown. 873 * If store is non-NULL, it is expected to be a pointer to the same variable 874 * that is awaiting to be assigned the return value of this function. 875 * In its current use, the returned value is assigned to netd_hooks in 876 * net_family_register. The use of "store" allows the return value to be 877 * used before this function returns. How can this happen? Through the 878 * callbacks that can be activated at the bottom of this function, when 879 * hook_stack_notify_run is called. 880 */ 881 hook_family_int_t * 882 hook_family_add(hook_family_t *hf, hook_stack_t *hks, void **store) 883 { 884 hook_family_int_t *hfi, *new; 885 886 ASSERT(hf != NULL); 887 ASSERT(hf->hf_name != NULL); 888 889 new = hook_family_copy(hf); 890 if (new == NULL) 891 return (NULL); 892 893 mutex_enter(&hook_stack_lock); 894 CVW_ENTER_WRITE(&hks->hks_lock); 895 896 if (hks->hks_shutdown != 0) { 897 CVW_EXIT_WRITE(&hks->hks_lock); 898 mutex_exit(&hook_stack_lock); 899 hook_family_free(new, NULL); 900 return (NULL); 901 } 902 903 /* search family list */ 904 hfi = hook_family_find(hf->hf_name, hks); 905 if (hfi != NULL) { 906 CVW_EXIT_WRITE(&hks->hks_lock); 907 mutex_exit(&hook_stack_lock); 908 hook_family_free(new, NULL); 909 return (NULL); 910 } 911 912 /* 913 * Try and set the FWF_ADD_ACTIVE flag so that we can drop all the 914 * lock further down when calling all of the functions registered 915 * for notification when a new hook family is added. 916 */ 917 if (hook_wait_setflag(&hks->hks_waiter, FWF_ADD_WAIT_MASK, 918 FWF_ADD_WANTED, FWF_ADD_ACTIVE) == -1) { 919 CVW_EXIT_WRITE(&hks->hks_lock); 920 mutex_exit(&hook_stack_lock); 921 hook_family_free(new, NULL); 922 return (NULL); 923 } 924 925 CVW_INIT(&new->hfi_lock); 926 SLIST_INIT(&new->hfi_head); 927 TAILQ_INIT(&new->hfi_nhead); 928 929 hook_wait_init(&new->hfi_waiter, &new->hfi_lock); 930 931 new->hfi_stack = hks; 932 if (store != NULL) 933 *store = new; 934 935 /* Add to family list head */ 936 SLIST_INSERT_HEAD(&hks->hks_familylist, new, hfi_entry); 937 938 CVW_EXIT_WRITE(&hks->hks_lock); 939 mutex_exit(&hook_stack_lock); 940 941 hook_stack_notify_run(hks, hf->hf_name, HN_REGISTER); 942 943 hook_wait_unsetflag(&hks->hks_waiter, FWF_ADD_ACTIVE); 944 945 return (new); 946 } 947 948 /* 949 * Function: hook_family_remove 950 * Returns: int - 0 = success, else = failure 951 * Parameters: hfi(I) - internal family pointer 952 * 953 * Remove family from family list. This function has been designed to be 954 * called once and once only per hook_family_int_t. Thus when cleaning up 955 * this structure as an orphan, callers should only call hook_family_free. 956 */ 957 int 958 hook_family_remove(hook_family_int_t *hfi) 959 { 960 hook_stack_t *hks; 961 boolean_t notifydone; 962 963 ASSERT(hfi != NULL); 964 hks = hfi->hfi_stack; 965 966 CVW_ENTER_WRITE(&hfi->hfi_lock); 967 notifydone = hfi->hfi_shutdown; 968 hfi->hfi_shutdown = B_TRUE; 969 CVW_EXIT_WRITE(&hfi->hfi_lock); 970 971 CVW_ENTER_WRITE(&hks->hks_lock); 972 973 if (hook_wait_setflag(&hks->hks_waiter, FWF_DEL_WAIT_MASK, 974 FWF_DEL_WANTED, FWF_DEL_ACTIVE) == -1) { 975 /* 976 * If we're trying to destroy the hook_stack_t... 977 */ 978 CVW_EXIT_WRITE(&hks->hks_lock); 979 return (ENXIO); 980 } 981 982 /* 983 * Check if the family is in use by the presence of either events 984 * or notify callbacks on the hook family. 985 */ 986 if (!SLIST_EMPTY(&hfi->hfi_head) || !TAILQ_EMPTY(&hfi->hfi_nhead)) { 987 hfi->hfi_condemned = B_TRUE; 988 } else { 989 VERIFY(hook_wait_destroy(&hfi->hfi_waiter) == 0); 990 /* 991 * Although hfi_condemned = B_FALSE is implied from creation, 992 * putting a comment here inside the else upsets lint. 993 */ 994 hfi->hfi_condemned = B_FALSE; 995 } 996 CVW_EXIT_WRITE(&hks->hks_lock); 997 998 if (!notifydone) 999 hook_stack_notify_run(hks, hfi->hfi_family.hf_name, 1000 HN_UNREGISTER); 1001 1002 hook_wait_unsetflag(&hks->hks_waiter, FWF_DEL_ACTIVE); 1003 1004 /* 1005 * If we don't have to wait for anything else to disappear from this 1006 * structure then we can free it up. 1007 */ 1008 if (!hfi->hfi_condemned) 1009 hook_family_free(hfi, hks); 1010 1011 return (0); 1012 } 1013 1014 1015 /* 1016 * Function: hook_family_free 1017 * Returns: None 1018 * Parameters: hfi(I) - internal family pointer 1019 * 1020 * Free alloc memory for family 1021 */ 1022 static void 1023 hook_family_free(hook_family_int_t *hfi, hook_stack_t *hks) 1024 { 1025 1026 /* 1027 * This lock gives us possession of the hks pointer after the 1028 * SLIST_REMOVE, for which it is not needed, when hks_shutdown 1029 * is checked and hook_stack_remove called. 1030 */ 1031 mutex_enter(&hook_stack_lock); 1032 1033 ASSERT(hfi != NULL); 1034 1035 if (hks != NULL) { 1036 CVW_ENTER_WRITE(&hks->hks_lock); 1037 /* Remove from family list */ 1038 SLIST_REMOVE(&hks->hks_familylist, hfi, hook_family_int, 1039 hfi_entry); 1040 1041 CVW_EXIT_WRITE(&hks->hks_lock); 1042 } 1043 1044 /* Free name space */ 1045 if (hfi->hfi_family.hf_name != NULL) { 1046 kmem_free(hfi->hfi_family.hf_name, 1047 strlen(hfi->hfi_family.hf_name) + 1); 1048 } 1049 1050 /* Free container */ 1051 kmem_free(hfi, sizeof (*hfi)); 1052 1053 if (hks->hks_shutdown == 2) 1054 hook_stack_remove(hks); 1055 1056 mutex_exit(&hook_stack_lock); 1057 } 1058 1059 /* 1060 * Function: hook_family_shutdown 1061 * Returns: int - 0 = success, else = failure 1062 * Parameters: hfi(I) - internal family pointer 1063 * 1064 * As an alternative to removing a family, we may desire to just generate 1065 * a series of callbacks to indicate that we will be going away in the 1066 * future. The hfi_condemned flag isn't set because we aren't trying to 1067 * remove the structure. 1068 */ 1069 int 1070 hook_family_shutdown(hook_family_int_t *hfi) 1071 { 1072 hook_stack_t *hks; 1073 boolean_t notifydone; 1074 1075 ASSERT(hfi != NULL); 1076 hks = hfi->hfi_stack; 1077 1078 CVW_ENTER_WRITE(&hfi->hfi_lock); 1079 notifydone = hfi->hfi_shutdown; 1080 hfi->hfi_shutdown = B_TRUE; 1081 CVW_EXIT_WRITE(&hfi->hfi_lock); 1082 1083 CVW_ENTER_WRITE(&hks->hks_lock); 1084 1085 if (hook_wait_setflag(&hks->hks_waiter, FWF_DEL_WAIT_MASK, 1086 FWF_DEL_WANTED, FWF_DEL_ACTIVE) == -1) { 1087 /* 1088 * If we're trying to destroy the hook_stack_t... 1089 */ 1090 CVW_EXIT_WRITE(&hks->hks_lock); 1091 return (ENXIO); 1092 } 1093 1094 CVW_EXIT_WRITE(&hks->hks_lock); 1095 1096 if (!notifydone) 1097 hook_stack_notify_run(hks, hfi->hfi_family.hf_name, 1098 HN_UNREGISTER); 1099 1100 hook_wait_unsetflag(&hks->hks_waiter, FWF_DEL_ACTIVE); 1101 1102 return (0); 1103 } 1104 1105 /* 1106 * Function: hook_family_copy 1107 * Returns: internal family pointer - NULL = Failed 1108 * Parameters: src(I) - family pointer 1109 * 1110 * Allocate internal family block and duplicate incoming family 1111 * No locks should be held across this function as it may sleep. 1112 */ 1113 static hook_family_int_t * 1114 hook_family_copy(hook_family_t *src) 1115 { 1116 hook_family_int_t *new; 1117 hook_family_t *dst; 1118 1119 ASSERT(src != NULL); 1120 ASSERT(src->hf_name != NULL); 1121 1122 new = (hook_family_int_t *)kmem_zalloc(sizeof (*new), KM_SLEEP); 1123 1124 /* Copy body */ 1125 dst = &new->hfi_family; 1126 *dst = *src; 1127 1128 SLIST_INIT(&new->hfi_head); 1129 TAILQ_INIT(&new->hfi_nhead); 1130 1131 /* Copy name */ 1132 dst->hf_name = (char *)kmem_alloc(strlen(src->hf_name) + 1, KM_SLEEP); 1133 (void) strcpy(dst->hf_name, src->hf_name); 1134 1135 return (new); 1136 } 1137 1138 /* 1139 * Function: hook_family_find 1140 * Returns: internal family pointer - NULL = Not match 1141 * Parameters: family(I) - family name string 1142 * 1143 * Search family list with family name 1144 * A lock on hfi_lock must be held when called. 1145 */ 1146 static hook_family_int_t * 1147 hook_family_find(char *family, hook_stack_t *hks) 1148 { 1149 hook_family_int_t *hfi = NULL; 1150 1151 ASSERT(family != NULL); 1152 1153 SLIST_FOREACH(hfi, &hks->hks_familylist, hfi_entry) { 1154 if (strcmp(hfi->hfi_family.hf_name, family) == 0) 1155 break; 1156 } 1157 return (hfi); 1158 } 1159 1160 /* 1161 * Function: hook_family_notify_register 1162 * Returns: int - 0 = success, else failure 1163 * Parameters: hfi(I) - hook family 1164 * callback(I) - function to be called 1165 * arg(I) - arg to provide callback when it is called 1166 * 1167 * So long as this hook stack isn't being shut down, register a new 1168 * callback to be activated each time a new event is added to this 1169 * family. 1170 * 1171 * To call this function we must have an active handle in use on the family, 1172 * so if we take this into account, then neither the hook_family_int_t nor 1173 * the hook_stack_t that owns it can disappear. We have to put some trust 1174 * in the callers to be properly synchronised... 1175 * 1176 * Holding hks_lock is required to provide synchronisation for hks_shutdown. 1177 */ 1178 int 1179 hook_family_notify_register(hook_family_int_t *hfi, 1180 hook_notify_fn_t callback, void *arg) 1181 { 1182 hook_event_int_t *hei; 1183 hook_stack_t *hks; 1184 boolean_t canrun; 1185 int error; 1186 1187 ASSERT(hfi != NULL); 1188 canrun = B_FALSE; 1189 hks = hfi->hfi_stack; 1190 1191 CVW_ENTER_READ(&hks->hks_lock); 1192 1193 if ((hfi->hfi_stack->hks_shutdown != 0) || 1194 hfi->hfi_condemned || hfi->hfi_shutdown) { 1195 CVW_EXIT_READ(&hks->hks_lock); 1196 return (ESHUTDOWN); 1197 } 1198 1199 CVW_ENTER_WRITE(&hfi->hfi_lock); 1200 canrun = (hook_wait_setflag(&hfi->hfi_waiter, FWF_ADD_WAIT_MASK, 1201 FWF_ADD_WANTED, FWF_ADD_ACTIVE) != -1); 1202 error = hook_notify_register(&hfi->hfi_nhead, callback, arg); 1203 CVW_EXIT_WRITE(&hfi->hfi_lock); 1204 1205 CVW_EXIT_READ(&hks->hks_lock); 1206 1207 if (error == 0 && canrun) { 1208 SLIST_FOREACH(hei, &hfi->hfi_head, hei_entry) { 1209 callback(HN_REGISTER, arg, 1210 hfi->hfi_family.hf_name, NULL, 1211 hei->hei_event->he_name); 1212 } 1213 } 1214 1215 if (canrun) 1216 hook_wait_unsetflag(&hfi->hfi_waiter, FWF_ADD_ACTIVE); 1217 1218 return (error); 1219 } 1220 1221 /* 1222 * Function: hook_family_notify_unregister 1223 * Returns: int - 0 = success, else failure 1224 * Parameters: hfi(I) - hook family 1225 * callback(I) - function to be called 1226 * 1227 * Remove a callback from the list of those executed when a new event is 1228 * added to a hook family. If the family is not in the process of being 1229 * destroyed then simulate an unregister callback for each event that is 1230 * on the family. This pairs up with the hook_family_notify_register 1231 * action that simulates register events. 1232 * The order of what happens here is important and goes like this. 1233 * 1) Remove the callback from the list of functions to be called as part 1234 * of the notify operation when an event is added or removed from the 1235 * hook family. 1236 * 2) If the hook_family_int_t structure is on death row (free_family will 1237 * be set to true) then there's nothing else to do than let it be free'd. 1238 * 3) If the structure isn't about to die, mark it up as being busy using 1239 * hook_wait_setflag and then drop the lock so the loop can be run. 1240 * 4) if hook_wait_setflag was successful, tell all of the notify callback 1241 * functions that this family has been unregistered. 1242 * 5) Cleanup 1243 */ 1244 int 1245 hook_family_notify_unregister(hook_family_int_t *hfi, 1246 hook_notify_fn_t callback) 1247 { 1248 hook_event_int_t *hei; 1249 boolean_t free_family; 1250 boolean_t canrun; 1251 int error; 1252 void *arg; 1253 1254 canrun = B_FALSE; 1255 1256 CVW_ENTER_WRITE(&hfi->hfi_lock); 1257 1258 (void) hook_wait_setflag(&hfi->hfi_waiter, FWF_DEL_WAIT_MASK, 1259 FWF_DEL_WANTED, FWF_DEL_ACTIVE); 1260 1261 error = hook_notify_unregister(&hfi->hfi_nhead, callback, &arg); 1262 1263 hook_wait_unsetflag(&hfi->hfi_waiter, FWF_DEL_ACTIVE); 1264 1265 /* 1266 * If hook_family_remove has been called but the structure was still 1267 * "busy" ... but we might have just made it "unbusy"... 1268 */ 1269 if ((error == 0) && hfi->hfi_condemned && 1270 SLIST_EMPTY(&hfi->hfi_head) && TAILQ_EMPTY(&hfi->hfi_nhead)) { 1271 free_family = B_TRUE; 1272 } else { 1273 free_family = B_FALSE; 1274 } 1275 1276 if (error == 0 && !free_family) { 1277 canrun = (hook_wait_setflag(&hfi->hfi_waiter, FWF_ADD_WAIT_MASK, 1278 FWF_ADD_WANTED, FWF_ADD_ACTIVE) != -1); 1279 } 1280 1281 CVW_EXIT_WRITE(&hfi->hfi_lock); 1282 1283 if (canrun) { 1284 SLIST_FOREACH(hei, &hfi->hfi_head, hei_entry) { 1285 callback(HN_UNREGISTER, arg, 1286 hfi->hfi_family.hf_name, NULL, 1287 hei->hei_event->he_name); 1288 } 1289 1290 hook_wait_unsetflag(&hfi->hfi_waiter, FWF_ADD_ACTIVE); 1291 } else if (free_family) { 1292 hook_family_free(hfi, hfi->hfi_stack); 1293 } 1294 1295 return (error); 1296 } 1297 1298 /* 1299 * Function: hook_event_add 1300 * Returns: internal event pointer - NULL = Fail 1301 * Parameters: hfi(I) - internal family pointer 1302 * he(I) - event pointer 1303 * 1304 * Add new event to event list on specific family. 1305 * This function can fail to return successfully if (1) it cannot allocate 1306 * enough memory for its own internal data structures, (2) the event has 1307 * already been registered (for any hook family.) 1308 */ 1309 hook_event_int_t * 1310 hook_event_add(hook_family_int_t *hfi, hook_event_t *he) 1311 { 1312 hook_event_int_t *hei, *new; 1313 hook_stack_t *hks; 1314 1315 ASSERT(hfi != NULL); 1316 ASSERT(he != NULL); 1317 ASSERT(he->he_name != NULL); 1318 1319 new = hook_event_copy(he); 1320 if (new == NULL) 1321 return (NULL); 1322 1323 hks = hfi->hfi_stack; 1324 CVW_ENTER_READ(&hks->hks_lock); 1325 1326 hks = hfi->hfi_stack; 1327 if (hks->hks_shutdown != 0) { 1328 CVW_EXIT_READ(&hks->hks_lock); 1329 hook_event_free(new, NULL); 1330 return (NULL); 1331 } 1332 1333 /* Check whether this event pointer is already registered */ 1334 hei = hook_event_checkdup(he, hks); 1335 if (hei != NULL) { 1336 CVW_EXIT_READ(&hks->hks_lock); 1337 hook_event_free(new, NULL); 1338 return (NULL); 1339 } 1340 1341 CVW_ENTER_WRITE(&hfi->hfi_lock); 1342 1343 if (hfi->hfi_condemned || hfi->hfi_shutdown) { 1344 CVW_EXIT_WRITE(&hfi->hfi_lock); 1345 CVW_EXIT_READ(&hks->hks_lock); 1346 hook_event_free(new, NULL); 1347 return (NULL); 1348 } 1349 CVW_EXIT_READ(&hks->hks_lock); 1350 1351 if (hook_wait_setflag(&hfi->hfi_waiter, FWF_ADD_WAIT_MASK, 1352 FWF_ADD_WANTED, FWF_ADD_ACTIVE) == -1) { 1353 CVW_EXIT_WRITE(&hfi->hfi_lock); 1354 hook_event_free(new, NULL); 1355 return (NULL); 1356 } 1357 1358 TAILQ_INIT(&new->hei_nhead); 1359 1360 hook_event_init_kstats(hfi, new); 1361 hook_wait_init(&new->hei_waiter, &new->hei_lock); 1362 1363 /* Add to event list head */ 1364 SLIST_INSERT_HEAD(&hfi->hfi_head, new, hei_entry); 1365 1366 CVW_EXIT_WRITE(&hfi->hfi_lock); 1367 1368 hook_notify_run(&hfi->hfi_nhead, 1369 hfi->hfi_family.hf_name, NULL, he->he_name, HN_REGISTER); 1370 1371 hook_wait_unsetflag(&hfi->hfi_waiter, FWF_ADD_ACTIVE); 1372 1373 return (new); 1374 } 1375 1376 /* 1377 * Function: hook_event_init_kstats 1378 * Returns: None 1379 * Parameters: hfi(I) - pointer to the family that owns this event. 1380 * hei(I) - pointer to the hook event that needs some kstats. 1381 * 1382 * Create a set of kstats that relate to each event registered with 1383 * the hook framework. A counter is kept for each time the event is 1384 * activated and for each time a hook is added or removed. As the 1385 * kstats just count the events as they happen, the total number of 1386 * hooks registered must be obtained by subtractived removed from added. 1387 */ 1388 static void 1389 hook_event_init_kstats(hook_family_int_t *hfi, hook_event_int_t *hei) 1390 { 1391 hook_event_kstat_t template = { 1392 { "hooksAdded", KSTAT_DATA_UINT64 }, 1393 { "hooksRemoved", KSTAT_DATA_UINT64 }, 1394 { "events", KSTAT_DATA_UINT64 } 1395 }; 1396 hook_stack_t *hks; 1397 1398 hks = hfi->hfi_stack; 1399 hei->hei_kstatp = kstat_create_netstack(hfi->hfi_family.hf_name, 0, 1400 hei->hei_event->he_name, "hook_event", KSTAT_TYPE_NAMED, 1401 sizeof (hei->hei_kstats) / sizeof (kstat_named_t), 1402 KSTAT_FLAG_VIRTUAL, hks->hks_netstackid); 1403 1404 bcopy((char *)&template, &hei->hei_kstats, sizeof (template)); 1405 1406 if (hei->hei_kstatp != NULL) { 1407 hei->hei_kstatp->ks_data = (void *)&hei->hei_kstats; 1408 hei->hei_kstatp->ks_private = 1409 (void *)(uintptr_t)hks->hks_netstackid; 1410 1411 kstat_install(hei->hei_kstatp); 1412 } 1413 } 1414 1415 /* 1416 * Function: hook_event_remove 1417 * Returns: int - 0 = success, else = failure 1418 * Parameters: hfi(I) - internal family pointer 1419 * he(I) - event pointer 1420 * 1421 * Remove event from event list on specific family 1422 * 1423 * This function assumes that the caller has received a pointer to a the 1424 * hook_family_int_t via a call to net_protocol_lookup or net_protocol_unreg'. 1425 * This the hook_family_int_t is guaranteed to be around for the life of this 1426 * call, unless the caller has decided to call net_protocol_release or 1427 * net_protocol_unregister before calling net_event_unregister - an error. 1428 */ 1429 int 1430 hook_event_remove(hook_family_int_t *hfi, hook_event_t *he) 1431 { 1432 boolean_t free_family; 1433 hook_event_int_t *hei; 1434 boolean_t notifydone; 1435 1436 ASSERT(hfi != NULL); 1437 ASSERT(he != NULL); 1438 1439 CVW_ENTER_WRITE(&hfi->hfi_lock); 1440 1441 /* 1442 * Set the flag so that we can call hook_event_notify_run without 1443 * holding any locks but at the same time prevent other changes to 1444 * the event at the same time. 1445 */ 1446 if (hook_wait_setflag(&hfi->hfi_waiter, FWF_DEL_WAIT_MASK, 1447 FWF_DEL_WANTED, FWF_DEL_ACTIVE) == -1) { 1448 CVW_EXIT_WRITE(&hfi->hfi_lock); 1449 return (ENXIO); 1450 } 1451 1452 hei = hook_event_find(hfi, he->he_name); 1453 if (hei == NULL) { 1454 hook_wait_unsetflag(&hfi->hfi_waiter, FWF_DEL_ACTIVE); 1455 CVW_EXIT_WRITE(&hfi->hfi_lock); 1456 return (ESRCH); 1457 } 1458 1459 free_family = B_FALSE; 1460 1461 CVW_ENTER_WRITE(&hei->hei_lock); 1462 /* 1463 * The hei_shutdown flag is used to indicate whether or not we have 1464 * done a shutdown and thus already walked through the notify list. 1465 */ 1466 notifydone = hei->hei_shutdown; 1467 hei->hei_shutdown = B_TRUE; 1468 /* 1469 * If there are any hooks still registered for this event or 1470 * there are any notifiers registered, return an error indicating 1471 * that the event is still busy. 1472 */ 1473 if (!TAILQ_EMPTY(&hei->hei_head) || !TAILQ_EMPTY(&hei->hei_nhead)) { 1474 hei->hei_condemned = B_TRUE; 1475 CVW_EXIT_WRITE(&hei->hei_lock); 1476 } else { 1477 /* hei_condemned = B_FALSE is implied from creation */ 1478 /* 1479 * Even though we know the notify list is empty, we call 1480 * hook_wait_destroy here to synchronise wait removing a 1481 * hook from an event. 1482 */ 1483 VERIFY(hook_wait_destroy(&hei->hei_waiter) == 0); 1484 1485 CVW_EXIT_WRITE(&hei->hei_lock); 1486 1487 if (hfi->hfi_condemned && SLIST_EMPTY(&hfi->hfi_head) && 1488 TAILQ_EMPTY(&hfi->hfi_nhead)) 1489 free_family = B_TRUE; 1490 } 1491 1492 CVW_EXIT_WRITE(&hfi->hfi_lock); 1493 1494 if (!notifydone) 1495 hook_notify_run(&hfi->hfi_nhead, 1496 hfi->hfi_family.hf_name, NULL, he->he_name, HN_UNREGISTER); 1497 1498 hook_wait_unsetflag(&hfi->hfi_waiter, FWF_DEL_ACTIVE); 1499 1500 if (!hei->hei_condemned) { 1501 hook_event_free(hei, hfi); 1502 if (free_family) 1503 hook_family_free(hfi, hfi->hfi_stack); 1504 } 1505 1506 return (0); 1507 } 1508 1509 /* 1510 * Function: hook_event_shutdown 1511 * Returns: int - 0 = success, else = failure 1512 * Parameters: hfi(I) - internal family pointer 1513 * he(I) - event pointer 1514 * 1515 * As with hook_family_shutdown, we want to generate the notify callbacks 1516 * as if the event was being removed but not actually do the remove. 1517 */ 1518 int 1519 hook_event_shutdown(hook_family_int_t *hfi, hook_event_t *he) 1520 { 1521 hook_event_int_t *hei; 1522 boolean_t notifydone; 1523 1524 ASSERT(hfi != NULL); 1525 ASSERT(he != NULL); 1526 1527 CVW_ENTER_WRITE(&hfi->hfi_lock); 1528 1529 /* 1530 * Set the flag so that we can call hook_event_notify_run without 1531 * holding any locks but at the same time prevent other changes to 1532 * the event at the same time. 1533 */ 1534 if (hook_wait_setflag(&hfi->hfi_waiter, FWF_DEL_WAIT_MASK, 1535 FWF_DEL_WANTED, FWF_DEL_ACTIVE) == -1) { 1536 CVW_EXIT_WRITE(&hfi->hfi_lock); 1537 return (ENXIO); 1538 } 1539 1540 hei = hook_event_find(hfi, he->he_name); 1541 if (hei == NULL) { 1542 hook_wait_unsetflag(&hfi->hfi_waiter, FWF_DEL_ACTIVE); 1543 CVW_EXIT_WRITE(&hfi->hfi_lock); 1544 return (ESRCH); 1545 } 1546 1547 CVW_ENTER_WRITE(&hei->hei_lock); 1548 notifydone = hei->hei_shutdown; 1549 hei->hei_shutdown = B_TRUE; 1550 CVW_EXIT_WRITE(&hei->hei_lock); 1551 1552 CVW_EXIT_WRITE(&hfi->hfi_lock); 1553 1554 if (!notifydone) 1555 hook_notify_run(&hfi->hfi_nhead, 1556 hfi->hfi_family.hf_name, NULL, he->he_name, HN_UNREGISTER); 1557 1558 hook_wait_unsetflag(&hfi->hfi_waiter, FWF_DEL_ACTIVE); 1559 1560 return (0); 1561 } 1562 1563 /* 1564 * Function: hook_event_free 1565 * Returns: None 1566 * Parameters: hei(I) - internal event pointer 1567 * 1568 * Free alloc memory for event 1569 */ 1570 static void 1571 hook_event_free(hook_event_int_t *hei, hook_family_int_t *hfi) 1572 { 1573 boolean_t free_family; 1574 1575 ASSERT(hei != NULL); 1576 1577 if (hfi != NULL) { 1578 CVW_ENTER_WRITE(&hfi->hfi_lock); 1579 /* 1580 * Remove the event from the hook family's list. 1581 */ 1582 SLIST_REMOVE(&hfi->hfi_head, hei, hook_event_int, hei_entry); 1583 if (hfi->hfi_condemned && SLIST_EMPTY(&hfi->hfi_head) && 1584 TAILQ_EMPTY(&hfi->hfi_nhead)) { 1585 free_family = B_TRUE; 1586 } else { 1587 free_family = B_FALSE; 1588 } 1589 CVW_EXIT_WRITE(&hfi->hfi_lock); 1590 } 1591 1592 if (hei->hei_kstatp != NULL) { 1593 ASSERT(hfi != NULL); 1594 1595 kstat_delete_netstack(hei->hei_kstatp, 1596 hfi->hfi_stack->hks_netstackid); 1597 hei->hei_kstatp = NULL; 1598 } 1599 1600 /* Free container */ 1601 kmem_free(hei, sizeof (*hei)); 1602 1603 if (free_family) 1604 hook_family_free(hfi, hfi->hfi_stack); 1605 } 1606 1607 /* 1608 * Function: hook_event_checkdup 1609 * Returns: internal event pointer - NULL = Not match 1610 * Parameters: he(I) - event pointer 1611 * 1612 * Search all of the hook families to see if the event being passed in 1613 * has already been associated with one. 1614 */ 1615 static hook_event_int_t * 1616 hook_event_checkdup(hook_event_t *he, hook_stack_t *hks) 1617 { 1618 hook_family_int_t *hfi; 1619 hook_event_int_t *hei; 1620 1621 ASSERT(he != NULL); 1622 1623 CVW_ENTER_READ(&hks->hks_lock); 1624 SLIST_FOREACH(hfi, &hks->hks_familylist, hfi_entry) { 1625 SLIST_FOREACH(hei, &hfi->hfi_head, hei_entry) { 1626 if (hei->hei_event == he) { 1627 CVW_EXIT_READ(&hks->hks_lock); 1628 return (hei); 1629 } 1630 } 1631 } 1632 CVW_EXIT_READ(&hks->hks_lock); 1633 1634 return (NULL); 1635 } 1636 1637 /* 1638 * Function: hook_event_copy 1639 * Returns: internal event pointer - NULL = Failed 1640 * Parameters: src(I) - event pointer 1641 * 1642 * Allocate internal event block and duplicate incoming event 1643 * No locks should be held across this function as it may sleep. 1644 */ 1645 static hook_event_int_t * 1646 hook_event_copy(hook_event_t *src) 1647 { 1648 hook_event_int_t *new; 1649 1650 ASSERT(src != NULL); 1651 ASSERT(src->he_name != NULL); 1652 1653 new = (hook_event_int_t *)kmem_zalloc(sizeof (*new), KM_SLEEP); 1654 1655 /* Copy body */ 1656 TAILQ_INIT(&new->hei_head); 1657 new->hei_event = src; 1658 1659 return (new); 1660 } 1661 1662 /* 1663 * Function: hook_event_find 1664 * Returns: internal event pointer - NULL = Not match 1665 * Parameters: hfi(I) - internal family pointer 1666 * event(I) - event name string 1667 * 1668 * Search event list with event name 1669 * A lock on hfi->hfi_lock must be held when called. 1670 */ 1671 static hook_event_int_t * 1672 hook_event_find(hook_family_int_t *hfi, char *event) 1673 { 1674 hook_event_int_t *hei = NULL; 1675 1676 ASSERT(hfi != NULL); 1677 ASSERT(event != NULL); 1678 1679 SLIST_FOREACH(hei, &hfi->hfi_head, hei_entry) { 1680 if ((strcmp(hei->hei_event->he_name, event) == 0) && 1681 ((hei->hei_waiter.fw_flags & FWF_UNSAFE) == 0)) 1682 break; 1683 } 1684 return (hei); 1685 } 1686 1687 /* 1688 * Function: hook_event_notify_register 1689 * Returns: int - 0 = success, else failure 1690 * Parameters: hfi(I) - hook family 1691 * event(I) - name of the event 1692 * callback(I) - function to be called 1693 * arg(I) - arg to provide callback when it is called 1694 * 1695 * Adds a new callback to the event named by "event" (we must find it) 1696 * that will be executed each time a new hook is added to the event. 1697 * Of course, if the stack is being shut down, this call should fail. 1698 */ 1699 int 1700 hook_event_notify_register(hook_family_int_t *hfi, char *event, 1701 hook_notify_fn_t callback, void *arg) 1702 { 1703 hook_event_int_t *hei; 1704 hook_stack_t *hks; 1705 boolean_t canrun; 1706 hook_int_t *h; 1707 int error; 1708 1709 canrun = B_FALSE; 1710 hks = hfi->hfi_stack; 1711 CVW_ENTER_READ(&hks->hks_lock); 1712 if (hks->hks_shutdown != 0) { 1713 CVW_EXIT_READ(&hks->hks_lock); 1714 return (ESHUTDOWN); 1715 } 1716 1717 CVW_ENTER_READ(&hfi->hfi_lock); 1718 1719 if (hfi->hfi_condemned || hfi->hfi_shutdown) { 1720 CVW_EXIT_READ(&hfi->hfi_lock); 1721 CVW_EXIT_READ(&hks->hks_lock); 1722 return (ESHUTDOWN); 1723 } 1724 1725 hei = hook_event_find(hfi, event); 1726 if (hei == NULL) { 1727 CVW_EXIT_READ(&hfi->hfi_lock); 1728 CVW_EXIT_READ(&hks->hks_lock); 1729 return (ESRCH); 1730 } 1731 1732 if (hei->hei_condemned || hei->hei_shutdown) { 1733 CVW_EXIT_READ(&hfi->hfi_lock); 1734 CVW_EXIT_READ(&hks->hks_lock); 1735 return (ESHUTDOWN); 1736 } 1737 1738 CVW_ENTER_WRITE(&hei->hei_lock); 1739 canrun = (hook_wait_setflag(&hei->hei_waiter, FWF_ADD_WAIT_MASK, 1740 FWF_ADD_WANTED, FWF_ADD_ACTIVE) != -1); 1741 error = hook_notify_register(&hei->hei_nhead, callback, arg); 1742 CVW_EXIT_WRITE(&hei->hei_lock); 1743 1744 CVW_EXIT_READ(&hfi->hfi_lock); 1745 CVW_EXIT_READ(&hks->hks_lock); 1746 1747 if (error == 0 && canrun) { 1748 TAILQ_FOREACH(h, &hei->hei_head, hi_entry) { 1749 callback(HN_REGISTER, arg, 1750 hfi->hfi_family.hf_name, hei->hei_event->he_name, 1751 h->hi_hook.h_name); 1752 } 1753 } 1754 1755 if (canrun) 1756 hook_wait_unsetflag(&hei->hei_waiter, FWF_ADD_ACTIVE); 1757 1758 return (error); 1759 } 1760 1761 /* 1762 * Function: hook_event_notify_unregister 1763 * Returns: int - 0 = success, else failure 1764 * Parameters: hfi(I) - hook family 1765 * event(I) - name of the event 1766 * callback(I) - function to be called 1767 * 1768 * Remove the given callback from the named event's list of functions 1769 * to call when a hook is added or removed. 1770 */ 1771 int 1772 hook_event_notify_unregister(hook_family_int_t *hfi, char *event, 1773 hook_notify_fn_t callback) 1774 { 1775 hook_event_int_t *hei; 1776 boolean_t free_event; 1777 boolean_t canrun; 1778 hook_int_t *h; 1779 void *arg; 1780 int error; 1781 1782 canrun = B_FALSE; 1783 1784 CVW_ENTER_READ(&hfi->hfi_lock); 1785 1786 hei = hook_event_find(hfi, event); 1787 if (hei == NULL) { 1788 CVW_EXIT_READ(&hfi->hfi_lock); 1789 return (ESRCH); 1790 } 1791 1792 CVW_ENTER_WRITE(&hei->hei_lock); 1793 1794 (void) hook_wait_setflag(&hei->hei_waiter, FWF_DEL_WAIT_MASK, 1795 FWF_DEL_WANTED, FWF_DEL_ACTIVE); 1796 1797 error = hook_notify_unregister(&hei->hei_nhead, callback, &arg); 1798 1799 hook_wait_unsetflag(&hei->hei_waiter, FWF_DEL_ACTIVE); 1800 1801 /* 1802 * hei_condemned has been set if someone tried to remove the 1803 * event but couldn't because there were still things attached to 1804 * it. Now that we've done a successful remove, if it is now empty 1805 * then by all rights we should be free'ing it too. Note that the 1806 * expectation is that only the caller of hook_event_add will ever 1807 * call hook_event_remove. 1808 */ 1809 if ((error == 0) && hei->hei_condemned && 1810 TAILQ_EMPTY(&hei->hei_head) && TAILQ_EMPTY(&hei->hei_nhead)) { 1811 free_event = B_TRUE; 1812 } else { 1813 free_event = B_FALSE; 1814 } 1815 1816 if (error == 0 && !free_event) { 1817 canrun = (hook_wait_setflag(&hei->hei_waiter, FWF_ADD_WAIT_MASK, 1818 FWF_ADD_WANTED, FWF_ADD_ACTIVE) != -1); 1819 } 1820 1821 CVW_EXIT_WRITE(&hei->hei_lock); 1822 CVW_EXIT_READ(&hfi->hfi_lock); 1823 1824 if (canrun) { 1825 TAILQ_FOREACH(h, &hei->hei_head, hi_entry) { 1826 callback(HN_UNREGISTER, arg, 1827 hfi->hfi_family.hf_name, hei->hei_event->he_name, 1828 h->hi_hook.h_name); 1829 } 1830 1831 hook_wait_unsetflag(&hei->hei_waiter, FWF_ADD_ACTIVE); 1832 } 1833 1834 if (free_event) { 1835 /* 1836 * It is safe to pass in hfi here, without a lock, because 1837 * our structure (hei) is still on one of its lists and thus 1838 * it won't be able to disappear yet... 1839 */ 1840 hook_event_free(hei, hfi); 1841 } 1842 1843 return (error); 1844 } 1845 1846 /* 1847 * Function: hook_event_notify_run 1848 * Returns: None 1849 * Parameters: nrun(I) - pointer to the list of callbacks to execute 1850 * hfi(I) - hook stack pointer to execute callbacks for 1851 * name(I) - name of a hook family 1852 * cmd(I) - either HN_UNREGISTER or HN_REGISTER 1853 * 1854 * Execute all of the callbacks registered for this event. 1855 */ 1856 static void 1857 hook_event_notify_run(hook_event_int_t *hei, hook_family_int_t *hfi, 1858 char *event, char *name, hook_notify_cmd_t cmd) 1859 { 1860 1861 hook_notify_run(&hei->hei_nhead, hfi->hfi_family.hf_name, 1862 event, name, cmd); 1863 } 1864 1865 /* 1866 * Function: hook_register 1867 * Returns: int - 0 = success, else = failure 1868 * Parameters: hfi(I) - internal family pointer 1869 * event(I) - event name string 1870 * h(I) - hook pointer 1871 * 1872 * Add new hook to hook list on the specified family and event. 1873 */ 1874 int 1875 hook_register(hook_family_int_t *hfi, char *event, hook_t *h) 1876 { 1877 hook_event_int_t *hei; 1878 hook_int_t *hi, *new; 1879 int error; 1880 1881 ASSERT(hfi != NULL); 1882 ASSERT(event != NULL); 1883 ASSERT(h != NULL); 1884 1885 if (hfi->hfi_stack->hks_shutdown) 1886 return (NULL); 1887 1888 /* Alloc hook_int_t and copy hook */ 1889 new = hook_copy(h); 1890 if (new == NULL) 1891 return (ENOMEM); 1892 1893 /* 1894 * Since hook add/remove only impact event, so it is unnecessary 1895 * to hold global family write lock. Just get read lock here to 1896 * ensure event will not be removed when doing hooks operation 1897 */ 1898 CVW_ENTER_WRITE(&hfi->hfi_lock); 1899 1900 hei = hook_event_find(hfi, event); 1901 if (hei == NULL) { 1902 CVW_EXIT_WRITE(&hfi->hfi_lock); 1903 hook_int_free(new, hfi->hfi_stack->hks_netstackid); 1904 return (ENXIO); 1905 } 1906 1907 CVW_ENTER_WRITE(&hei->hei_lock); 1908 1909 /* 1910 * If we've run either the remove() or shutdown(), do not allow any 1911 * more hooks to be added to this event. 1912 */ 1913 if (hei->hei_shutdown) { 1914 error = ESHUTDOWN; 1915 goto bad_add; 1916 } 1917 1918 hi = hook_find(hei, h); 1919 if (hi != NULL) { 1920 error = EEXIST; 1921 goto bad_add; 1922 } 1923 1924 if (hook_wait_setflag(&hei->hei_waiter, FWF_ADD_WAIT_MASK, 1925 FWF_ADD_WANTED, FWF_ADD_ACTIVE) == -1) { 1926 error = ENOENT; 1927 bad_add: 1928 CVW_EXIT_WRITE(&hei->hei_lock); 1929 CVW_EXIT_WRITE(&hfi->hfi_lock); 1930 hook_int_free(new, hfi->hfi_stack->hks_netstackid); 1931 return (error); 1932 } 1933 1934 /* Add to hook list head */ 1935 error = hook_insert(&hei->hei_head, new); 1936 if (error == 0) { 1937 hei->hei_event->he_interested = B_TRUE; 1938 hei->hei_kstats.hooks_added.value.ui64++; 1939 1940 hook_init_kstats(hfi, hei, new); 1941 } 1942 1943 CVW_EXIT_WRITE(&hei->hei_lock); 1944 CVW_EXIT_WRITE(&hfi->hfi_lock); 1945 1946 /* 1947 * Note that the name string passed through to the notify callbacks 1948 * is from the original hook being registered, not the copy being 1949 * inserted. 1950 */ 1951 if (error == 0) 1952 hook_event_notify_run(hei, hfi, event, h->h_name, HN_REGISTER); 1953 1954 hook_wait_unsetflag(&hei->hei_waiter, FWF_ADD_ACTIVE); 1955 1956 return (error); 1957 } 1958 1959 /* 1960 * Function: hook_insert 1961 * Returns: int - 0 = success, else = failure 1962 * Parameters: head(I) - pointer to hook list to insert hook onto 1963 * new(I) - pointer to hook to be inserted 1964 * 1965 * Try to insert the hook onto the list of hooks according to the hints 1966 * given in the hook to be inserted and those that already exist on the 1967 * list. For now, the implementation permits only a single hook to be 1968 * either first or last and names provided with before or after are only 1969 * loosely coupled with the action. 1970 */ 1971 static int 1972 hook_insert(hook_int_head_t *head, hook_int_t *new) 1973 { 1974 hook_int_t *before; 1975 hook_int_t *hi; 1976 hook_t *hih; 1977 hook_t *h = &new->hi_hook; 1978 1979 switch (new->hi_hook.h_hint) { 1980 case HH_NONE : 1981 before = NULL; 1982 /* 1983 * If there is no hint present (or not one that can be 1984 * satisfied now) then try to at least respect the wishes 1985 * of those that want to be last. If there are none wanting 1986 * to be last then add the new hook to the tail of the 1987 * list - this means we keep any wanting to be first 1988 * happy without having to search for HH_FIRST. 1989 */ 1990 TAILQ_FOREACH(hi, head, hi_entry) { 1991 hih = &hi->hi_hook; 1992 if ((hih->h_hint == HH_AFTER) && 1993 (strcmp(h->h_name, 1994 (char *)hih->h_hintvalue) == 0)) { 1995 TAILQ_INSERT_BEFORE(hi, new, hi_entry); 1996 return (0); 1997 } 1998 if ((hih->h_hint == HH_BEFORE) && (before == NULL) && 1999 (strcmp(h->h_name, 2000 (char *)hih->h_hintvalue) == 0)) { 2001 before = hi; 2002 } 2003 } 2004 if (before != NULL) { 2005 TAILQ_INSERT_AFTER(head, before, new, hi_entry); 2006 return (0); 2007 } 2008 hook_insert_plain(head, new); 2009 break; 2010 2011 case HH_FIRST : 2012 hi = TAILQ_FIRST(head); 2013 if ((hi != NULL) && (hi->hi_hook.h_hint == HH_FIRST)) 2014 return (EBUSY); 2015 TAILQ_INSERT_HEAD(head, new, hi_entry); 2016 break; 2017 2018 case HH_LAST : 2019 hi = TAILQ_LAST(head, hook_int_head); 2020 if ((hi != NULL) && (hi->hi_hook.h_hint == HH_LAST)) 2021 return (EBUSY); 2022 TAILQ_INSERT_TAIL(head, new, hi_entry); 2023 break; 2024 2025 case HH_BEFORE : 2026 hi = hook_find_byname(head, (char *)new->hi_hook.h_hintvalue); 2027 if (hi == NULL) 2028 return (hook_insert_afterbefore(head, new)); 2029 2030 if (hi->hi_hook.h_hint == HH_FIRST) 2031 return (EBUSY); 2032 2033 TAILQ_INSERT_BEFORE(hi, new, hi_entry); 2034 break; 2035 2036 case HH_AFTER : 2037 hi = hook_find_byname(head, (char *)new->hi_hook.h_hintvalue); 2038 if (hi == NULL) 2039 return (hook_insert_afterbefore(head, new)); 2040 2041 if (hi->hi_hook.h_hint == HH_LAST) 2042 return (EBUSY); 2043 2044 TAILQ_INSERT_AFTER(head, hi, new, hi_entry); 2045 break; 2046 2047 default : 2048 return (EINVAL); 2049 } 2050 2051 return (0); 2052 } 2053 2054 /* 2055 * Function: hook_insert_plain 2056 * Returns: int - 0 = success, else = failure 2057 * Parameters: head(I) - pointer to hook list to insert hook onto 2058 * new(I) - pointer to hook to be inserted 2059 * 2060 * Insert a hook such that it respects the wishes of those that want to 2061 * be last. If there are none wanting to be last then add the new hook 2062 * to the tail of the list - this means we keep any wanting to be first 2063 * happy without having to search for HH_FIRST. 2064 */ 2065 static void 2066 hook_insert_plain(hook_int_head_t *head, hook_int_t *new) 2067 { 2068 hook_int_t *hi; 2069 2070 hi = TAILQ_FIRST(head); 2071 if (hi != NULL) { 2072 if (hi->hi_hook.h_hint == HH_LAST) { 2073 TAILQ_INSERT_BEFORE(hi, new, hi_entry); 2074 } else { 2075 TAILQ_INSERT_TAIL(head, new, hi_entry); 2076 } 2077 } else { 2078 TAILQ_INSERT_TAIL(head, new, hi_entry); 2079 } 2080 } 2081 2082 /* 2083 * Function: hook_insert_afterbefore 2084 * Returns: int - 0 = success, else = failure 2085 * Parameters: head(I) - pointer to hook list to insert hook onto 2086 * new(I) - pointer to hook to be inserted 2087 * 2088 * Simple insertion of a hook specifying a HH_BEFORE or HH_AFTER was not 2089 * possible, so now we need to be more careful. The first pass is to go 2090 * through the list and look for any other hooks that also specify the 2091 * same hint name as the new one. The object of this exercise is to make 2092 * sure that hooks with HH_BEFORE always appear on the list before those 2093 * with HH_AFTER so that when said hook arrives, it can be placed in the 2094 * middle of the BEFOREs and AFTERs. If this condition does not arise, 2095 * just use hook_insert_plain() to try and insert the hook somewhere that 2096 * is innocuous to existing efforts. 2097 */ 2098 static int 2099 hook_insert_afterbefore(hook_int_head_t *head, hook_int_t *new) 2100 { 2101 hook_int_t *hi; 2102 hook_t *nh; 2103 hook_t *h; 2104 2105 nh = &new->hi_hook; 2106 ASSERT(new->hi_hook.h_hint != HH_NONE); 2107 ASSERT(new->hi_hook.h_hint != HH_LAST); 2108 ASSERT(new->hi_hook.h_hint != HH_FIRST); 2109 2110 /* 2111 * First, look through the list to see if there are any other 2112 * before's or after's that have a matching hint name. 2113 */ 2114 TAILQ_FOREACH(hi, head, hi_entry) { 2115 h = &hi->hi_hook; 2116 switch (h->h_hint) { 2117 case HH_FIRST : 2118 case HH_LAST : 2119 case HH_NONE : 2120 break; 2121 case HH_BEFORE : 2122 if ((nh->h_hint == HH_BEFORE) && 2123 (strcmp((char *)h->h_hintvalue, 2124 (char *)nh->h_hintvalue) == 0)) { 2125 TAILQ_INSERT_AFTER(head, hi, new, hi_entry); 2126 return (0); 2127 } 2128 if ((nh->h_hint == HH_AFTER) && 2129 (strcmp((char *)h->h_hintvalue, 2130 (char *)nh->h_hintvalue) == 0)) { 2131 TAILQ_INSERT_BEFORE(hi, new, hi_entry); 2132 return (0); 2133 } 2134 break; 2135 case HH_AFTER : 2136 if ((nh->h_hint == HH_AFTER) && 2137 (strcmp((char *)h->h_hintvalue, 2138 (char *)nh->h_hintvalue) == 0)) { 2139 TAILQ_INSERT_AFTER(head, hi, new, hi_entry); 2140 return (0); 2141 } 2142 if ((nh->h_hint == HH_BEFORE) && 2143 (strcmp((char *)h->h_hintvalue, 2144 (char *)nh->h_hintvalue) == 0)) { 2145 TAILQ_INSERT_BEFORE(hi, new, hi_entry); 2146 return (0); 2147 } 2148 break; 2149 } 2150 } 2151 2152 hook_insert_plain(head, new); 2153 2154 return (0); 2155 } 2156 2157 /* 2158 * Function: hook_unregister 2159 * Returns: int - 0 = success, else = failure 2160 * Parameters: hfi(I) - internal family pointer 2161 * event(I) - event name string 2162 * h(I) - hook pointer 2163 * 2164 * Remove hook from hook list on specific family, event 2165 */ 2166 int 2167 hook_unregister(hook_family_int_t *hfi, char *event, hook_t *h) 2168 { 2169 hook_event_int_t *hei; 2170 hook_int_t *hi; 2171 boolean_t free_event; 2172 2173 ASSERT(hfi != NULL); 2174 ASSERT(h != NULL); 2175 2176 CVW_ENTER_WRITE(&hfi->hfi_lock); 2177 2178 hei = hook_event_find(hfi, event); 2179 if (hei == NULL) { 2180 CVW_EXIT_WRITE(&hfi->hfi_lock); 2181 return (ENXIO); 2182 } 2183 2184 /* Hold write lock for event */ 2185 CVW_ENTER_WRITE(&hei->hei_lock); 2186 2187 hi = hook_find(hei, h); 2188 if (hi == NULL) { 2189 CVW_EXIT_WRITE(&hei->hei_lock); 2190 CVW_EXIT_WRITE(&hfi->hfi_lock); 2191 return (ENXIO); 2192 } 2193 2194 if (hook_wait_setflag(&hei->hei_waiter, FWF_DEL_WAIT_MASK, 2195 FWF_DEL_WANTED, FWF_DEL_ACTIVE) == -1) { 2196 CVW_EXIT_WRITE(&hei->hei_lock); 2197 CVW_EXIT_WRITE(&hfi->hfi_lock); 2198 return (ENOENT); 2199 } 2200 2201 /* Remove from hook list */ 2202 TAILQ_REMOVE(&hei->hei_head, hi, hi_entry); 2203 2204 free_event = B_FALSE; 2205 if (TAILQ_EMPTY(&hei->hei_head)) { 2206 hei->hei_event->he_interested = B_FALSE; 2207 /* 2208 * If the delete pending flag has been set and there are 2209 * no notifiers on the event (and we've removed the last 2210 * hook) then we need to free this event after we're done. 2211 */ 2212 if (hei->hei_condemned && TAILQ_EMPTY(&hei->hei_nhead)) 2213 free_event = B_TRUE; 2214 } 2215 hei->hei_kstats.hooks_removed.value.ui64++; 2216 2217 CVW_EXIT_WRITE(&hei->hei_lock); 2218 CVW_EXIT_WRITE(&hfi->hfi_lock); 2219 /* 2220 * While the FWF_DEL_ACTIVE flag is set, the hook_event_int_t 2221 * will not be free'd and thus the hook_family_int_t wil not 2222 * be free'd either. 2223 */ 2224 hook_event_notify_run(hei, hfi, event, h->h_name, HN_UNREGISTER); 2225 hook_wait_unsetflag(&hei->hei_waiter, FWF_DEL_ACTIVE); 2226 2227 hook_int_free(hi, hfi->hfi_stack->hks_netstackid); 2228 2229 if (free_event) 2230 hook_event_free(hei, hfi); 2231 2232 return (0); 2233 } 2234 2235 /* 2236 * Function: hook_find_byname 2237 * Returns: internal hook pointer - NULL = Not match 2238 * Parameters: hei(I) - internal event pointer 2239 * name(I)- hook name 2240 * 2241 * Search an event's list of hooks to see if there is a hook present that 2242 * has a matching name to the one being looked for. 2243 */ 2244 static hook_int_t * 2245 hook_find_byname(hook_int_head_t *head, char *name) 2246 { 2247 hook_int_t *hi; 2248 2249 TAILQ_FOREACH(hi, head, hi_entry) { 2250 if (strcmp(hi->hi_hook.h_name, name) == 0) 2251 return (hi); 2252 } 2253 2254 return (NULL); 2255 } 2256 2257 /* 2258 * Function: hook_find 2259 * Returns: internal hook pointer - NULL = Not match 2260 * Parameters: hei(I) - internal event pointer 2261 * h(I) - hook pointer 2262 * 2263 * Search an event's list of hooks to see if there is already one that 2264 * matches the hook being passed in. Currently the only criteria for a 2265 * successful search here is for the names to be the same. 2266 */ 2267 static hook_int_t * 2268 hook_find(hook_event_int_t *hei, hook_t *h) 2269 { 2270 2271 ASSERT(hei != NULL); 2272 ASSERT(h != NULL); 2273 2274 return (hook_find_byname(&hei->hei_head, h->h_name)); 2275 } 2276 2277 /* 2278 * Function: hook_copy 2279 * Returns: internal hook pointer - NULL = Failed 2280 * Parameters: src(I) - hook pointer 2281 * 2282 * Allocate internal hook block and duplicate incoming hook. 2283 * No locks should be held across this function as it may sleep. 2284 * Because hook_copy() is responsible for the creation of the internal 2285 * hook structure that is used here, it takes on population the structure 2286 * with the kstat information. Note that while the kstat bits are 2287 * seeded here, their installation of the kstats is handled elsewhere. 2288 */ 2289 static hook_int_t * 2290 hook_copy(hook_t *src) 2291 { 2292 hook_int_t *new; 2293 hook_t *dst; 2294 int len; 2295 2296 ASSERT(src != NULL); 2297 ASSERT(src->h_name != NULL); 2298 2299 new = (hook_int_t *)kmem_zalloc(sizeof (*new), KM_SLEEP); 2300 2301 /* Copy body */ 2302 dst = &new->hi_hook; 2303 *dst = *src; 2304 2305 /* Copy name */ 2306 len = strlen(src->h_name); 2307 dst->h_name = (char *)kmem_alloc(len + 1, KM_SLEEP); 2308 (void) strcpy(dst->h_name, src->h_name); 2309 2310 /* 2311 * This is initialised in this manner to make it safer to use the 2312 * same pointer in the kstats field. 2313 */ 2314 dst->h_hintvalue = (uintptr_t)""; 2315 2316 if (dst->h_hint == HH_BEFORE || dst->h_hint == HH_AFTER) { 2317 len = strlen((char *)src->h_hintvalue); 2318 if (len > 0) { 2319 dst->h_hintvalue = (uintptr_t)kmem_alloc(len + 1, 2320 KM_SLEEP); 2321 (void) strcpy((char *)dst->h_hintvalue, 2322 (char *)src->h_hintvalue); 2323 } 2324 } 2325 2326 return (new); 2327 } 2328 2329 /* 2330 * Function: hook_init_kstats 2331 * Returns: None 2332 * Parameters: hfi(I) - pointer to the family that owns the event. 2333 * hei(I) - pointer to the event that owns this hook 2334 * hi(I) - pointer to the hook for which we create kstats for 2335 * 2336 * Each hook that is registered with this framework has its own kstats 2337 * set up so that we can provide an easy way in which to observe the 2338 * look of hooks (using the kstat command.) The position is set to 0 2339 * here but is recalculated after we know the insertion has been a 2340 * success. 2341 */ 2342 static void 2343 hook_init_kstats(hook_family_int_t *hfi, hook_event_int_t *hei, hook_int_t *hi) 2344 { 2345 hook_hook_kstat_t template = { 2346 { "version", KSTAT_DATA_INT32 }, 2347 { "flags", KSTAT_DATA_UINT32 }, 2348 { "hint", KSTAT_DATA_INT32 }, 2349 { "hint_value", KSTAT_DATA_STRING }, 2350 { "position", KSTAT_DATA_INT32 }, 2351 { "hook_hits", KSTAT_DATA_UINT64 } 2352 }; 2353 hook_stack_t *hks; 2354 size_t kslen; 2355 int position; 2356 hook_int_t *h; 2357 2358 kslen = strlen(hfi->hfi_family.hf_name) + 2359 strlen(hei->hei_event->he_name) + 2; 2360 2361 hi->hi_ksname = (char *)kmem_zalloc(kslen, KM_SLEEP); 2362 (void) snprintf(hi->hi_ksname, kslen, "%s/%s", 2363 hfi->hfi_family.hf_name, hei->hei_event->he_name); 2364 2365 hks = hfi->hfi_stack; 2366 hi->hi_kstatp = kstat_create_netstack(hi->hi_ksname, 0, 2367 hi->hi_hook.h_name, "hook", KSTAT_TYPE_NAMED, 2368 sizeof (hi->hi_kstats) / sizeof (kstat_named_t), 2369 KSTAT_FLAG_VIRTUAL, hks->hks_netstackid); 2370 2371 /* Initialise the kstats for the structure */ 2372 bcopy(&template, &hi->hi_kstats, sizeof (template)); 2373 hi->hi_kstats.hook_version.value.i32 = hi->hi_hook.h_version; 2374 hi->hi_kstats.hook_flags.value.ui32 = hi->hi_hook.h_flags; 2375 hi->hi_kstats.hook_hint.value.i32 = hi->hi_hook.h_hint; 2376 hi->hi_kstats.hook_position.value.i32 = 0; 2377 hi->hi_kstats.hook_hits.value.ui64 = 0; 2378 2379 switch (hi->hi_hook.h_hint) { 2380 case HH_BEFORE : 2381 case HH_AFTER : 2382 kstat_named_setstr(&(hi->hi_kstats.hook_hintvalue), 2383 (const char *)hi->hi_hook.h_hintvalue); 2384 break; 2385 default : 2386 kstat_named_setstr(&(hi->hi_kstats.hook_hintvalue), 2387 hook_hintvalue_none); 2388 break; 2389 } 2390 2391 if (hi->hi_kstatp != NULL) { 2392 hi->hi_kstatp->ks_data = (void *)&hi->hi_kstats; 2393 hi->hi_kstatp->ks_private = 2394 (void *)(uintptr_t)hks->hks_netstackid; 2395 hi->hi_kstatp->ks_data_size += 2396 KSTAT_NAMED_STR_BUFLEN(&(hi->hi_kstats.hook_hintvalue)) + 1; 2397 2398 kstat_install(hi->hi_kstatp); 2399 } 2400 2401 position = 1; 2402 TAILQ_FOREACH(h, &hei->hei_head, hi_entry) { 2403 h->hi_kstats.hook_position.value.ui32 = position++; 2404 } 2405 } 2406 2407 /* 2408 * Function: hook_int_free 2409 * Returns: None 2410 * Parameters: hi(I) - internal hook pointer 2411 * 2412 * Free memory allocated to support a hook. 2413 */ 2414 static void 2415 hook_int_free(hook_int_t *hi, netstackid_t stackid) 2416 { 2417 int len; 2418 2419 ASSERT(hi != NULL); 2420 2421 /* Free name space */ 2422 if (hi->hi_hook.h_name != NULL) { 2423 kmem_free(hi->hi_hook.h_name, strlen(hi->hi_hook.h_name) + 1); 2424 } 2425 if (hi->hi_ksname != NULL) { 2426 kmem_free(hi->hi_ksname, strlen(hi->hi_ksname) + 1); 2427 } 2428 2429 /* Free the name used with the before/after hints. */ 2430 switch (hi->hi_hook.h_hint) { 2431 case HH_BEFORE : 2432 case HH_AFTER : 2433 len = strlen((char *)hi->hi_hook.h_hintvalue); 2434 if (len > 0) 2435 kmem_free((void *)hi->hi_hook.h_hintvalue, len + 1); 2436 break; 2437 default : 2438 break; 2439 } 2440 2441 if (hi->hi_kstatp != NULL) 2442 kstat_delete_netstack(hi->hi_kstatp, stackid); 2443 2444 /* Free container */ 2445 kmem_free(hi, sizeof (*hi)); 2446 } 2447 2448 /* 2449 * Function: hook_alloc 2450 * Returns: hook_t * - pointer to new hook structure 2451 * Parameters: version(I) - version number of the API when compiled 2452 * 2453 * This function serves as the interface for consumers to obtain a hook_t 2454 * structure. At this point in time, there is only a single "version" of 2455 * it, leading to a straight forward function. In a perfect world the 2456 * h_vesion would be a protected data structure member, but C isn't that 2457 * advanced... 2458 */ 2459 hook_t * 2460 hook_alloc(const int h_version) 2461 { 2462 hook_t *h; 2463 2464 h = kmem_zalloc(sizeof (hook_t), KM_SLEEP); 2465 h->h_version = h_version; 2466 return (h); 2467 } 2468 2469 /* 2470 * Function: hook_free 2471 * Returns: None 2472 * Parameters: h(I) - external hook pointer 2473 * 2474 * This function only free's memory allocated with hook_alloc(), so that if 2475 * (for example) kernel memory was allocated for h_name, this needs to be 2476 * free'd before calling hook_free(). 2477 */ 2478 void 2479 hook_free(hook_t *h) 2480 { 2481 kmem_free(h, sizeof (*h)); 2482 } 2483 2484 /* 2485 * Function: hook_notify_register 2486 * Returns: int - 0 = success, else failure 2487 * Parameters: head(I) - top of the list of callbacks 2488 * callback(I) - function to be called 2489 * arg(I) - arg to pass back to the function 2490 * 2491 * This function implements the modification of the list of callbacks 2492 * that are registered when someone wants to be advised of a change 2493 * that has happened. 2494 */ 2495 static int 2496 hook_notify_register(hook_notify_head_t *head, hook_notify_fn_t callback, 2497 void *arg) 2498 { 2499 hook_notify_t *hn; 2500 2501 TAILQ_FOREACH(hn, head, hn_entry) { 2502 if (hn->hn_func == callback) { 2503 return (EEXIST); 2504 } 2505 } 2506 2507 hn = (hook_notify_t *)kmem_alloc(sizeof (*hn), KM_SLEEP); 2508 hn->hn_func = callback; 2509 hn->hn_arg = arg; 2510 TAILQ_INSERT_TAIL(head, hn, hn_entry); 2511 2512 return (0); 2513 } 2514 2515 /* 2516 * Function: hook_notify_unregister 2517 * Returns: int - 0 = success, else failure 2518 * Parameters: stackid(I) - netstack identifier 2519 * callback(I) - function to be called 2520 * parg(O) - pointer to storage for pointer 2521 * 2522 * When calling this function, the provision of a valid pointer in parg 2523 * allows the caller to be made aware of what argument the hook function 2524 * was expecting. This then allows the simulation of HN_UNREGISTER events 2525 * when a notify-unregister is performed. 2526 */ 2527 static int 2528 hook_notify_unregister(hook_notify_head_t *head, 2529 hook_notify_fn_t callback, void **parg) 2530 { 2531 hook_notify_t *hn; 2532 2533 ASSERT(parg != NULL); 2534 2535 TAILQ_FOREACH(hn, head, hn_entry) { 2536 if (hn->hn_func == callback) 2537 break; 2538 } 2539 2540 if (hn == NULL) 2541 return (ESRCH); 2542 2543 *parg = hn->hn_arg; 2544 2545 TAILQ_REMOVE(head, hn, hn_entry); 2546 2547 kmem_free(hn, sizeof (*hn)); 2548 2549 return (0); 2550 } 2551 2552 /* 2553 * Function: hook_notify_run 2554 * Returns: None 2555 * Parameters: head(I) - top of the list of callbacks 2556 * family(I) - name of the hook family that owns the event 2557 * event(I) - name of the event being changed 2558 * name(I) - name of the object causing change 2559 * cmd(I) - either HN_UNREGISTER or HN_REGISTER 2560 * 2561 * This function walks through the list of registered callbacks and 2562 * executes each one, passing back the arg supplied when registered 2563 * and the name of the family (that owns the event), event (the thing 2564 * to which we're making a change) and finally a name that describes 2565 * what is being added or removed, as indicated by cmd. 2566 * 2567 * This function does not acquire or release any lock as it is required 2568 * that code calling it do so before hand. The use of hook_notify_head_t 2569 * is protected by the use of flagwait_t in the structures that own this 2570 * list and with the use of the FWF_ADD/DEL_ACTIVE flags. 2571 */ 2572 static void 2573 hook_notify_run(hook_notify_head_t *head, char *family, char *event, 2574 char *name, hook_notify_cmd_t cmd) 2575 { 2576 hook_notify_t *hn; 2577 2578 TAILQ_FOREACH(hn, head, hn_entry) { 2579 (*hn->hn_func)(cmd, hn->hn_arg, family, event, name); 2580 } 2581 } 2582