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