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 (c) 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <sys/systm.h> 26 #include <sys/sysmacros.h> 27 #include <sys/cmn_err.h> 28 #include <sys/disp.h> 29 #include <sys/list.h> 30 #include <sys/mutex.h> 31 #include <sys/note.h> 32 #include <sys/rwlock.h> 33 #include <sys/stropts.h> 34 #include <sys/taskq.h> 35 #include <sys/socketvar.h> 36 #include <fs/sockfs/sockcommon.h> 37 #include <fs/sockfs/sockfilter_impl.h> 38 39 /* 40 * Socket Filter Framework 41 * 42 * Socket filter entry (sof_entry_t): 43 * 44 * There exists one entry for each configured filter (done via soconfig(1M)), 45 * and they are all in sof_entry_list. In addition to the global list, each 46 * sockparams entry maintains a list of filters that is interested in that 47 * particular socket type. So the filter entry may be referenced by multiple 48 * sockparams. The set of sockparams referencing a filter may change as 49 * socket types are added and/or removed from the system. Both sof_entry_list 50 * and the sockparams list is protected by sockconf_lock. 51 * 52 * Each filter entry has a ref count which is incremented whenever a filter 53 * is attached to a socket. An entry is marked SOFEF_CONDEMED when it is 54 * unconfigured, which will result in the entry being freed when its ref 55 * count reaches zero. 56 * 57 * Socket filter module (sof_module_t): 58 * 59 * Modules are created by sof_register() and placed in sof_module_list, 60 * which is protected by sof_module_lock. Each module has a reference count 61 * that is incremented when a filter entry is using the module. A module 62 * can be destroyed by sof_register() only when it's ref count is zero. 63 * 64 * Socket filter instance (sof_instance_t): 65 * 66 * Whenever a filter is attached to a socket (sonode), a new instance is 67 * created. The socket is guaranteed to be single threaded when filters are 68 * being attached/detached. The instance uses the sonode's so_lock for 69 * protection. 70 * 71 * The lifetime of an instance is the same as the socket it's attached to. 72 * 73 * How things link together: 74 * 75 * sockparams.sp_{auto,prog}_filters -> sp_filter_t -> sp_filter_t 76 * ^ | | 77 * | | | 78 * sonode.so_filter_top -> sof_instance_t | | 79 * | | | 80 * v v v 81 * sof_entry_list -> sof_entry_t -> sof_entry -> ... -> sof_entry_t 82 * | 83 * v 84 * sof_module_list -> sof_module_t -> ... -> sof_module_t 85 */ 86 87 static list_t sof_entry_list; /* list of configured filters */ 88 89 static list_t sof_module_list; /* list of loaded filter modules */ 90 static kmutex_t sof_module_lock; /* protect the module list */ 91 92 static sof_kstat_t sof_stat; 93 static kstat_t *sof_stat_ksp; 94 95 #ifdef DEBUG 96 static int socket_filter_debug = 0; 97 #endif 98 99 /* 100 * A connection that has been deferred for more than `sof_defer_drop_time' 101 * ticks can be dropped to make room for new connections. A connection that 102 * is to be dropped is moved over to `sof_close_deferred_list' where it will 103 * be closed by sof_close_deferred() (which is running on a taskq). Connections 104 * will not be moved over to the close list if it grows larger than 105 * `sof_close_deferred_max_backlog'. 106 */ 107 clock_t sof_defer_drop_time = 3000; 108 uint_t sof_close_deferred_max_backlog = 1000; 109 110 taskq_t *sof_close_deferred_taskq; 111 boolean_t sof_close_deferred_running; 112 uint_t sof_close_deferred_backlog; 113 list_t sof_close_deferred_list; 114 kmutex_t sof_close_deferred_lock; 115 116 static void sof_close_deferred(void *); 117 118 static void sof_module_rele(sof_module_t *); 119 static sof_module_t *sof_module_hold_by_name(const char *, const char *); 120 121 static int sof_entry_load_module(sof_entry_t *); 122 static void sof_entry_hold(sof_entry_t *); 123 static void sof_entry_rele(sof_entry_t *); 124 static int sof_entry_kstat_create(sof_entry_t *); 125 static void sof_entry_kstat_destroy(sof_entry_t *); 126 127 static sof_instance_t *sof_instance_create(sof_entry_t *, struct sonode *); 128 static void sof_instance_destroy(sof_instance_t *); 129 130 static int 131 sof_kstat_update(kstat_t *ksp, int rw) 132 { 133 _NOTE(ARGUNUSED(ksp)); 134 135 if (rw == KSTAT_WRITE) 136 return (EACCES); 137 138 sof_stat.sofks_defer_close_backlog.value.ui64 = 139 sof_close_deferred_backlog; 140 141 return (0); 142 } 143 144 void 145 sof_init(void) 146 { 147 list_create(&sof_entry_list, sizeof (sof_entry_t), 148 offsetof(sof_entry_t, sofe_node)); 149 list_create(&sof_module_list, sizeof (sof_module_t), 150 offsetof(sof_module_t, sofm_node)); 151 list_create(&sof_close_deferred_list, sizeof (struct sonode), 152 offsetof(struct sonode, so_acceptq_node)); 153 154 sof_close_deferred_taskq = taskq_create("sof_close_deferred_taskq", 155 1, minclsyspri, 1, INT_MAX, TASKQ_PREPOPULATE); 156 sof_close_deferred_running = B_FALSE; 157 sof_close_deferred_backlog = 0; 158 159 mutex_init(&sof_close_deferred_lock, NULL, MUTEX_DEFAULT, 0); 160 mutex_init(&sof_module_lock, NULL, MUTEX_DEFAULT, 0); 161 162 sof_stat_ksp = kstat_create("sockfs", 0, "sockfilter", "misc", 163 KSTAT_TYPE_NAMED, sizeof (sof_kstat_t) / sizeof (kstat_named_t), 164 KSTAT_FLAG_VIRTUAL); 165 166 if (sof_stat_ksp == NULL) 167 return; 168 169 kstat_named_init(&sof_stat.sofks_defer_closed, "defer_closed", 170 KSTAT_DATA_UINT64); 171 kstat_named_init(&sof_stat.sofks_defer_close_backlog, 172 "defer_close_backlog", KSTAT_DATA_UINT64); 173 kstat_named_init(&sof_stat.sofks_defer_close_failed_backlog_too_big, 174 "defer_close_failed_backlog_too_big", KSTAT_DATA_UINT64); 175 176 sof_stat_ksp->ks_data = &sof_stat; 177 sof_stat_ksp->ks_update = sof_kstat_update; 178 kstat_install(sof_stat_ksp); 179 } 180 181 /* 182 * Process filter options. 183 */ 184 static int 185 sof_setsockopt_impl(struct sonode *so, int option_name, 186 const void *optval, socklen_t optlen, struct cred *cr) 187 { 188 struct sockparams *sp = so->so_sockparams; 189 sof_entry_t *ent = NULL; 190 sp_filter_t *fil; 191 sof_instance_t *inst; 192 sof_rval_t rval; 193 int error; 194 195 _NOTE(ARGUNUSED(optlen)); 196 197 /* 198 * Is the filter in a state where filters can be attached? 199 */ 200 if (!(so->so_state & SS_FILOP_OK)) 201 return (EINVAL); 202 203 if (option_name == FIL_ATTACH) { 204 /* 205 * Make sure there isn't already another instance of the 206 * same filter attached to the socket. 207 */ 208 for (inst = so->so_filter_top; inst != NULL; 209 inst = inst->sofi_next) { 210 if (strncmp(inst->sofi_filter->sofe_name, 211 (const char *)optval, SOF_MAXNAMELEN) == 0) 212 return (EEXIST); 213 } 214 /* Look up the filter. */ 215 rw_enter(&sockconf_lock, RW_READER); 216 for (fil = list_head(&sp->sp_prog_filters); fil != NULL; 217 fil = list_next(&sp->sp_prog_filters, fil)) { 218 ent = fil->spf_filter; 219 ASSERT(ent->sofe_flags & SOFEF_PROG); 220 221 if (strncmp(ent->sofe_name, (const char *)optval, 222 SOF_MAXNAMELEN) == 0) 223 break; 224 } 225 /* No such filter */ 226 if (fil == NULL) { 227 rw_exit(&sockconf_lock); 228 return (ENOENT); 229 } 230 inst = sof_instance_create(ent, so); 231 rw_exit(&sockconf_lock); 232 233 /* Failed to create an instance; must be out of memory */ 234 if (inst == NULL) 235 return (ENOMEM); 236 237 /* 238 * This might be the first time the filter is being used, 239 * so try to load the module if it's not already registered. 240 */ 241 if (ent->sofe_mod == NULL && 242 (error = sof_entry_load_module(ent)) != 0) { 243 sof_instance_destroy(inst); 244 return (error); 245 } 246 247 /* Module loaded OK, so there must be an ops vector */ 248 ASSERT(ent->sofe_mod != NULL); 249 inst->sofi_ops = &ent->sofe_mod->sofm_ops; 250 251 SOF_STAT_ADD(inst, tot_active_attach, 1); 252 if (inst->sofi_ops->sofop_attach_active != NULL) { 253 rval = inst->sofi_ops->sofop_attach_active( 254 (sof_handle_t)inst, so->so_family, so->so_type, 255 so->so_protocol, cr, &inst->sofi_cookie); 256 if (rval != SOF_RVAL_CONTINUE) { 257 sof_instance_destroy(inst); 258 switch (rval) { 259 case SOF_RVAL_DETACH: 260 /* 261 * Filter does not want to to attach. 262 * An error is returned so the user 263 * knows the request did not go 264 * through. 265 */ 266 error = EINVAL; 267 break; 268 default: 269 SOF_STAT_ADD(inst, attach_failures, 1); 270 /* Not a valid rval for active attach */ 271 ASSERT(rval != SOF_RVAL_DEFER); 272 error = sof_rval2errno(rval); 273 break; 274 } 275 return (error); 276 } 277 } 278 return (0); 279 } else if (option_name == FIL_DETACH) { 280 for (inst = so->so_filter_top; inst != NULL; 281 inst = inst->sofi_next) { 282 283 ent = inst->sofi_filter; 284 if (strncmp(ent->sofe_name, (const char *)optval, 285 SOF_MAXNAMELEN) == 0) 286 break; 287 } 288 if (inst == NULL) 289 return (ENXIO); 290 291 /* automatic filters cannot be detached */ 292 if (inst->sofi_filter->sofe_flags & SOFEF_AUTO) 293 return (EINVAL); 294 295 if (inst->sofi_ops->sofop_detach != NULL) 296 inst->sofi_ops->sofop_detach((sof_handle_t)inst, 297 inst->sofi_cookie, cr); 298 sof_instance_destroy(inst); 299 300 return (0); 301 } else { 302 return (EINVAL); 303 } 304 } 305 306 int 307 sof_setsockopt(struct sonode *so, int option_name, 308 const void *optval, socklen_t optlen, struct cred *cr) 309 { 310 int error; 311 312 /* 313 * By grabbing the lock as a writer we ensure that no other socket 314 * operations can start while the filter stack is being manipulated. 315 * 316 * We do a tryenter so that in case there is an active thread we 317 * ask the caller to try again instead of blocking here until the 318 * other thread is done (which could be indefinitely in case of recv). 319 */ 320 if (!rw_tryenter(&so->so_fallback_rwlock, RW_WRITER)) { 321 return (EAGAIN); 322 } 323 324 /* Bail out if a fallback has taken place */ 325 if (so->so_state & SS_FALLBACK_COMP) 326 error = EINVAL; 327 else 328 error = sof_setsockopt_impl(so, option_name, optval, 329 optlen, cr); 330 rw_exit(&so->so_fallback_rwlock); 331 332 return (error); 333 } 334 335 /* 336 * Get filter socket options. 337 */ 338 static int 339 sof_getsockopt_impl(struct sonode *so, int option_name, 340 void *optval, socklen_t *optlenp, struct cred *cr) 341 { 342 sof_instance_t *inst; 343 struct fil_info *fi; 344 socklen_t maxsz = *optlenp; 345 int i; 346 uint_t cnt; 347 348 _NOTE(ARGUNUSED(cr)); 349 350 if (option_name == FIL_LIST) { 351 fi = (struct fil_info *)optval; 352 353 if (maxsz < sizeof (*fi)) 354 return (EINVAL); 355 356 for (inst = so->so_filter_top, cnt = 0; inst != NULL; 357 inst = inst->sofi_next) 358 cnt++; 359 for (inst = so->so_filter_top, i = 0; 360 inst != NULL && (i+1) * sizeof (*fi) <= maxsz; 361 inst = inst->sofi_next, i++) { 362 fi[i].fi_flags = 363 (inst->sofi_filter->sofe_flags & SOFEF_AUTO) ? 364 FILF_AUTO : FILF_PROG; 365 if (inst->sofi_flags & SOFIF_BYPASS) 366 fi[i].fi_flags |= FILF_BYPASS; 367 (void) strncpy(fi[i].fi_name, 368 inst->sofi_filter->sofe_name, FILNAME_MAX); 369 ASSERT(cnt > 0); 370 fi[i].fi_pos = --cnt; 371 } 372 *optlenp = i * sizeof (*fi); 373 return (0); 374 } else { 375 return (EINVAL); 376 } 377 } 378 379 int 380 sof_getsockopt(struct sonode *so, int option_name, 381 void *optval, socklen_t *optlenp, struct cred *cr) 382 { 383 int error; 384 385 /* 386 * The fallback lock is used here to serialize set and get 387 * filter operations. 388 */ 389 rw_enter(&so->so_fallback_rwlock, RW_READER); 390 if (so->so_state & SS_FALLBACK_COMP) 391 error = EINVAL; 392 else 393 error = sof_getsockopt_impl(so, option_name, optval, optlenp, 394 cr); 395 rw_exit(&so->so_fallback_rwlock); 396 397 return (error); 398 } 399 400 /* 401 * The socket `so' wants to inherit the filter stack from `pso'. 402 * Returns 0 if all went well or an errno otherwise. 403 */ 404 int 405 sof_sonode_inherit_filters(struct sonode *so, struct sonode *pso) 406 { 407 sof_instance_t *inst, *pinst; 408 sof_rval_t rval; 409 int error; 410 struct sockaddr_in6 laddrbuf, faddrbuf; 411 struct sockaddr_in6 *laddr, *faddr; 412 socklen_t laddrlen, faddrlen; 413 414 /* 415 * Make sure there is enough room to retrieve the addresses 416 */ 417 if (so->so_proto_props.sopp_maxaddrlen > sizeof (laddrbuf)) { 418 laddr = kmem_zalloc(so->so_proto_props.sopp_maxaddrlen, 419 KM_NOSLEEP); 420 if (laddr == NULL) 421 return (ENOMEM); 422 faddr = kmem_zalloc(so->so_proto_props.sopp_maxaddrlen, 423 KM_NOSLEEP); 424 if (faddr == NULL) { 425 kmem_free(laddr, so->so_proto_props.sopp_maxaddrlen); 426 return (ENOMEM); 427 } 428 laddrlen = faddrlen = so->so_proto_props.sopp_maxaddrlen; 429 } else { 430 laddrlen = faddrlen = sizeof (laddrbuf); 431 laddr = &laddrbuf; 432 faddr = &faddrbuf; 433 } 434 435 error = (*so->so_downcalls->sd_getpeername) 436 (so->so_proto_handle, (struct sockaddr *)faddr, &faddrlen, kcred); 437 if (error != 0) 438 goto out; 439 error = (*so->so_downcalls->sd_getsockname) 440 (so->so_proto_handle, (struct sockaddr *)laddr, &laddrlen, kcred); 441 if (error != 0) 442 goto out; 443 444 /* 445 * The stack is built bottom up. Filters are allowed to modify the 446 * the foreign and local addresses during attach. 447 */ 448 for (pinst = pso->so_filter_bottom; 449 pinst != NULL && !(pinst->sofi_flags & SOFIF_BYPASS); 450 pinst = pinst->sofi_prev) { 451 inst = sof_instance_create(pinst->sofi_filter, so); 452 if (inst == NULL) { 453 error = ENOMEM; 454 goto out; 455 } 456 /* 457 * The filter module must be loaded since it's already 458 * attached to the listener. 459 */ 460 ASSERT(pinst->sofi_ops != NULL); 461 inst->sofi_ops = pinst->sofi_ops; 462 463 SOF_STAT_ADD(inst, tot_passive_attach, 1); 464 if (inst->sofi_ops->sofop_attach_passive != NULL) { 465 rval = inst->sofi_ops->sofop_attach_passive( 466 (sof_handle_t)inst, 467 (sof_handle_t)pinst, pinst->sofi_cookie, 468 (struct sockaddr *)laddr, laddrlen, 469 (struct sockaddr *)faddr, faddrlen, 470 &inst->sofi_cookie); 471 if (rval != SOF_RVAL_CONTINUE) { 472 if (rval == SOF_RVAL_DEFER) { 473 mutex_enter(&so->so_lock); 474 inst->sofi_flags |= SOFIF_DEFER; 475 so->so_state |= SS_FIL_DEFER; 476 mutex_exit(&so->so_lock); 477 so->so_filter_defertime = 478 ddi_get_lbolt(); 479 SOF_STAT_ADD(inst, ndeferred, 1); 480 } else if (rval == SOF_RVAL_DETACH) { 481 sof_instance_destroy(inst); 482 } else { 483 SOF_STAT_ADD(inst, attach_failures, 1); 484 error = sof_rval2errno(rval); 485 /* 486 * Filters that called attached will be 487 * destroyed when the socket goes away, 488 * after detach is called. 489 */ 490 goto out; 491 } 492 } 493 } 494 } 495 496 out: 497 if (laddr != &laddrbuf) { 498 kmem_free(laddr, so->so_proto_props.sopp_maxaddrlen); 499 kmem_free(faddr, so->so_proto_props.sopp_maxaddrlen); 500 } 501 return (error); 502 } 503 504 /* 505 * Attach any automatic filters to sonode `so'. Returns 0 if all went well 506 * and an errno otherwise. 507 */ 508 int 509 sof_sonode_autoattach_filters(struct sonode *so, cred_t *cr) 510 { 511 struct sockparams *sp = so->so_sockparams; 512 sp_filter_t *fil; 513 sof_instance_t *inst; 514 sof_rval_t rval; 515 int error; 516 517 /* 518 * A created instance is added to the top of the sonode's filter 519 * stack, so traverse the config list in reverse order. 520 */ 521 rw_enter(&sockconf_lock, RW_READER); 522 for (fil = list_tail(&sp->sp_auto_filters); 523 fil != NULL; fil = list_prev(&sp->sp_auto_filters, fil)) { 524 ASSERT(fil->spf_filter->sofe_flags & SOFEF_AUTO); 525 if (!sof_instance_create(fil->spf_filter, so)) { 526 rw_exit(&sockconf_lock); 527 error = ENOMEM; /* must have run out of memory */ 528 goto free_all; 529 } 530 } 531 rw_exit(&sockconf_lock); 532 533 /* 534 * Notify each filter that it's being attached. 535 */ 536 inst = so->so_filter_top; 537 while (inst != NULL) { 538 sof_entry_t *ent = inst->sofi_filter; 539 sof_instance_t *ninst = inst->sofi_next; 540 541 /* 542 * This might be the first time the filter is being used, 543 * so try to load the module if it's not already registered. 544 */ 545 if (ent->sofe_mod == NULL && 546 (error = sof_entry_load_module(ent)) != 0) 547 goto free_detached; 548 549 /* Module loaded OK, so there must be an ops vector */ 550 ASSERT(ent->sofe_mod != NULL); 551 inst->sofi_ops = &ent->sofe_mod->sofm_ops; 552 553 SOF_STAT_ADD(inst, tot_active_attach, 1); 554 if (inst->sofi_ops->sofop_attach_active != NULL) { 555 rval = inst->sofi_ops->sofop_attach_active( 556 (sof_handle_t)inst, so->so_family, so->so_type, 557 so->so_protocol, cr, &inst->sofi_cookie); 558 if (rval != SOF_RVAL_CONTINUE) { 559 switch (rval) { 560 case SOF_RVAL_DETACH: 561 /* filter does not want to attach */ 562 sof_instance_destroy(inst); 563 break; 564 default: 565 SOF_STAT_ADD(inst, attach_failures, 1); 566 /* Not a valid rval for active attach */ 567 ASSERT(rval != SOF_RVAL_DEFER); 568 error = sof_rval2errno(rval); 569 goto free_detached; 570 } 571 } 572 } 573 inst = ninst; 574 } 575 return (0); 576 577 free_all: 578 inst = so->so_filter_top; 579 free_detached: 580 ASSERT(inst != NULL); 581 /* 582 * Destroy all filters for which attach was not called. The other 583 * filters will be destroyed (and detach called) when the socket 584 * is freed. 585 */ 586 do { 587 sof_instance_t *t = inst->sofi_next; 588 sof_instance_destroy(inst); 589 inst = t; 590 } while (inst != NULL); 591 592 return (error); 593 } 594 595 /* 596 * Detaches and frees all filters attached to sonode `so'. 597 */ 598 void 599 sof_sonode_cleanup(struct sonode *so) 600 { 601 sof_instance_t *inst; 602 603 while ((inst = so->so_filter_top) != NULL) { 604 (inst->sofi_ops->sofop_detach)((sof_handle_t)inst, 605 inst->sofi_cookie, kcred); 606 sof_instance_destroy(inst); 607 } 608 } 609 610 /* 611 * Notifies all active filters attached to `so' about the `event' and 612 * where `arg' is an event specific argument. 613 */ 614 void 615 sof_sonode_notify_filters(struct sonode *so, sof_event_t event, uintptr_t arg) 616 { 617 sof_instance_t *inst; 618 619 for (inst = so->so_filter_bottom; inst != NULL; 620 inst = inst->sofi_prev) { 621 if (SOF_INTERESTED(inst, notify)) 622 (inst->sofi_ops->sofop_notify)((sof_handle_t)inst, 623 inst->sofi_cookie, event, arg); 624 } 625 } 626 627 /* 628 * The socket `so' is closing. Notify filters and make sure that there 629 * are no pending tx operations. 630 */ 631 void 632 sof_sonode_closing(struct sonode *so) 633 { 634 /* 635 * Notify filters that the socket is being closed. It's OK for 636 * filters to inject data. 637 */ 638 sof_sonode_notify_filters(so, SOF_EV_CLOSING, (uintptr_t)B_TRUE); 639 640 /* wait for filters that are sending out data */ 641 mutex_enter(&so->so_lock); 642 while (so->so_filter_tx > 0) 643 cv_wait(&so->so_closing_cv, &so->so_lock); 644 mutex_exit(&so->so_lock); 645 } 646 647 /* 648 * Called when socket `so' wants to get rid of a deferred connection. 649 * Returns TRUE if a connection was dropped. 650 */ 651 boolean_t 652 sof_sonode_drop_deferred(struct sonode *so) 653 { 654 struct sonode *def; 655 clock_t now = ddi_get_lbolt(); 656 657 if (sof_close_deferred_backlog > sof_close_deferred_max_backlog) { 658 SOF_GLOBAL_STAT_BUMP(defer_close_failed_backlog_too_big); 659 return (B_FALSE); 660 } 661 mutex_enter(&so->so_acceptq_lock); 662 if ((def = list_head(&so->so_acceptq_defer)) != NULL && 663 (now - def->so_filter_defertime) > sof_defer_drop_time) { 664 list_remove(&so->so_acceptq_defer, def); 665 so->so_acceptq_len--; 666 mutex_exit(&so->so_acceptq_lock); 667 def->so_listener = NULL; 668 } else { 669 mutex_exit(&so->so_acceptq_lock); 670 return (B_FALSE); 671 } 672 673 mutex_enter(&sof_close_deferred_lock); 674 list_insert_tail(&sof_close_deferred_list, def); 675 sof_close_deferred_backlog++; 676 if (!sof_close_deferred_running) { 677 mutex_exit(&sof_close_deferred_lock); 678 (void) taskq_dispatch(sof_close_deferred_taskq, 679 sof_close_deferred, NULL, TQ_NOSLEEP); 680 } else { 681 mutex_exit(&sof_close_deferred_lock); 682 } 683 return (B_TRUE); 684 } 685 686 /* 687 * Called from a taskq to close connections that have been deferred for 688 * too long. 689 */ 690 void 691 sof_close_deferred(void *unused) 692 { 693 struct sonode *drop; 694 695 _NOTE(ARGUNUSED(unused)); 696 697 mutex_enter(&sof_close_deferred_lock); 698 if (!sof_close_deferred_running) { 699 sof_close_deferred_running = B_TRUE; 700 while ((drop = 701 list_remove_head(&sof_close_deferred_list)) != NULL) { 702 sof_close_deferred_backlog--; 703 mutex_exit(&sof_close_deferred_lock); 704 705 SOF_GLOBAL_STAT_BUMP(defer_closed); 706 (void) socket_close(drop, 0, kcred); 707 socket_destroy(drop); 708 709 mutex_enter(&sof_close_deferred_lock); 710 } 711 sof_close_deferred_running = B_FALSE; 712 ASSERT(sof_close_deferred_backlog == 0); 713 } 714 mutex_exit(&sof_close_deferred_lock); 715 } 716 717 /* 718 * Creates a new filter instance from the entry `ent' and attaches 719 * it to the sonode `so'. On success, return a pointer to the created 720 * instance. 721 * 722 * The new instance will be placed on the top of the filter stack. 723 * 724 * The caller is responsible for assigning the instance's ops vector and 725 * calling the filter's attach callback. 726 * 727 * No locks are held while manipulating the sonode fields because we are 728 * guaranteed that this operation is serialized. 729 * 730 * We can be sure that the entry `ent' will not disappear, because the 731 * caller is either holding sockconf_lock (in case of an active open), or is 732 * already holding a reference (in case of a passive open, the listener has 733 * one). 734 */ 735 static sof_instance_t * 736 sof_instance_create(sof_entry_t *ent, struct sonode *so) 737 { 738 sof_instance_t *inst; 739 740 inst = kmem_zalloc(sizeof (sof_instance_t), KM_NOSLEEP); 741 if (inst == NULL) 742 return (NULL); 743 sof_entry_hold(ent); 744 inst->sofi_filter = ent; 745 inst->sofi_sonode = so; 746 747 inst->sofi_next = so->so_filter_top; 748 if (so->so_filter_top != NULL) 749 so->so_filter_top->sofi_prev = inst; 750 else 751 so->so_filter_bottom = inst; 752 so->so_filter_top = inst; 753 so->so_filter_active++; 754 755 return (inst); 756 } 757 /* 758 * Destroys the filter instance `inst' and unlinks it from the sonode. 759 * 760 * Any filter private state must be destroyed (via the detach callback) 761 * before the instance is destroyed. 762 */ 763 static void 764 sof_instance_destroy(sof_instance_t *inst) 765 { 766 struct sonode *so = inst->sofi_sonode; 767 768 ASSERT(inst->sofi_sonode != NULL); 769 ASSERT(inst->sofi_filter != NULL); 770 ASSERT(inst->sofi_prev != NULL || so->so_filter_top == inst); 771 ASSERT(inst->sofi_next != NULL || so->so_filter_bottom == inst); 772 773 if (inst->sofi_prev != NULL) 774 inst->sofi_prev->sofi_next = inst->sofi_next; 775 else 776 so->so_filter_top = inst->sofi_next; 777 778 if (inst->sofi_next != NULL) 779 inst->sofi_next->sofi_prev = inst->sofi_prev; 780 else 781 so->so_filter_bottom = inst->sofi_prev; 782 783 if (!(inst->sofi_flags & SOFIF_BYPASS)) { 784 ASSERT(so->so_filter_active > 0); 785 so->so_filter_active--; 786 } 787 if (inst->sofi_flags & SOFIF_DEFER) 788 SOF_STAT_ADD(inst, ndeferred, -1); 789 sof_entry_rele(inst->sofi_filter); 790 kmem_free(inst, sizeof (sof_instance_t)); 791 } 792 793 static sof_entry_t * 794 sof_entry_find(const char *name) 795 { 796 sof_entry_t *ent; 797 798 for (ent = list_head(&sof_entry_list); ent != NULL; 799 ent = list_next(&sof_entry_list, ent)) { 800 if (strncmp(ent->sofe_name, name, SOF_MAXNAMELEN) == 0) 801 return (ent); 802 } 803 return (NULL); 804 } 805 806 void 807 sof_entry_free(sof_entry_t *ent) 808 { 809 ASSERT(ent->sofe_refcnt == 0); 810 ASSERT(!list_link_active(&ent->sofe_node)); 811 812 if (ent->sofe_hintarg != NULL) { 813 ASSERT(ent->sofe_hint == SOF_HINT_BEFORE || 814 ent->sofe_hint == SOF_HINT_AFTER); 815 kmem_free(ent->sofe_hintarg, strlen(ent->sofe_hintarg) + 1); 816 ent->sofe_hintarg = NULL; 817 } 818 if (ent->sofe_socktuple_cnt > 0) { 819 ASSERT(ent->sofe_socktuple != NULL); 820 kmem_free(ent->sofe_socktuple, 821 sizeof (sof_socktuple_t) * ent->sofe_socktuple_cnt); 822 ent->sofe_socktuple = NULL; 823 ent->sofe_socktuple_cnt = 0; 824 } 825 sof_entry_kstat_destroy(ent); 826 827 mutex_destroy(&ent->sofe_lock); 828 kmem_free(ent, sizeof (sof_entry_t)); 829 } 830 831 static int 832 sof_entry_kstat_update(kstat_t *ksp, int rw) 833 { 834 sof_entry_t *ent = ksp->ks_private; 835 836 if (rw == KSTAT_WRITE) 837 return (EACCES); 838 839 ent->sofe_kstat.sofek_nactive.value.ui64 = ent->sofe_refcnt; 840 841 return (0); 842 } 843 844 /* 845 * Create the kstat for filter entry `ent'. 846 */ 847 static int 848 sof_entry_kstat_create(sof_entry_t *ent) 849 { 850 char name[SOF_MAXNAMELEN + 7]; 851 852 (void) snprintf(name, sizeof (name), "filter_%s", ent->sofe_name); 853 ent->sofe_ksp = kstat_create("sockfs", 0, name, "misc", 854 KSTAT_TYPE_NAMED, 855 sizeof (sof_entry_kstat_t) / sizeof (kstat_named_t), 856 KSTAT_FLAG_VIRTUAL); 857 858 if (ent->sofe_ksp == NULL) 859 return (ENOMEM); 860 861 kstat_named_init(&ent->sofe_kstat.sofek_nactive, "nactive", 862 KSTAT_DATA_UINT64); 863 kstat_named_init(&ent->sofe_kstat.sofek_tot_active_attach, 864 "tot_active_attach", KSTAT_DATA_UINT64); 865 kstat_named_init(&ent->sofe_kstat.sofek_tot_passive_attach, 866 "tot_passive_attach", KSTAT_DATA_UINT64); 867 kstat_named_init(&ent->sofe_kstat.sofek_ndeferred, "ndeferred", 868 KSTAT_DATA_UINT64); 869 kstat_named_init(&ent->sofe_kstat.sofek_attach_failures, 870 "attach_failures", KSTAT_DATA_UINT64); 871 872 ent->sofe_ksp->ks_data = &ent->sofe_kstat; 873 ent->sofe_ksp->ks_update = sof_entry_kstat_update; 874 ent->sofe_ksp->ks_private = ent; 875 kstat_install(ent->sofe_ksp); 876 877 return (0); 878 } 879 880 /* 881 * Destroys the kstat for filter entry `ent'. 882 */ 883 static void 884 sof_entry_kstat_destroy(sof_entry_t *ent) 885 { 886 if (ent->sofe_ksp != NULL) { 887 kstat_delete(ent->sofe_ksp); 888 ent->sofe_ksp = NULL; 889 } 890 } 891 892 static void 893 sof_entry_hold(sof_entry_t *ent) 894 { 895 mutex_enter(&ent->sofe_lock); 896 ent->sofe_refcnt++; 897 mutex_exit(&ent->sofe_lock); 898 } 899 900 /* 901 * Decrement the reference count for `ent'. The entry will 902 * drop its' reference on the filter module whenever its' 903 * ref count reaches zero. 904 */ 905 static void 906 sof_entry_rele(sof_entry_t *ent) 907 { 908 mutex_enter(&ent->sofe_lock); 909 if (--ent->sofe_refcnt == 0) { 910 sof_module_t *mod = ent->sofe_mod; 911 ent->sofe_mod = NULL; 912 if (ent->sofe_flags & SOFEF_CONDEMED) { 913 mutex_exit(&ent->sofe_lock); 914 sof_entry_free(ent); 915 } else { 916 mutex_exit(&ent->sofe_lock); 917 } 918 if (mod != NULL) 919 sof_module_rele(mod); 920 } else { 921 mutex_exit(&ent->sofe_lock); 922 } 923 } 924 925 /* 926 * Loads the module used by `ent' 927 */ 928 static int 929 sof_entry_load_module(sof_entry_t *ent) 930 { 931 sof_module_t *mod = sof_module_hold_by_name(ent->sofe_name, 932 ent->sofe_modname); 933 934 if (mod == NULL) 935 return (EINVAL); 936 937 mutex_enter(&ent->sofe_lock); 938 /* Another thread might have already loaded the module */ 939 ASSERT(ent->sofe_mod == mod || ent->sofe_mod == NULL); 940 if (ent->sofe_mod != NULL) { 941 mutex_exit(&ent->sofe_lock); 942 sof_module_rele(mod); 943 } else { 944 ent->sofe_mod = mod; 945 mutex_exit(&ent->sofe_lock); 946 } 947 948 return (0); 949 } 950 951 /* 952 * Add filter entry `ent' to the global list and attach it to all sockparam 953 * entries which the filter is interested in. Upon successful return the filter 954 * will be available for applications to use. 955 */ 956 int 957 sof_entry_add(sof_entry_t *ent) 958 { 959 int error; 960 961 /* 962 * We hold sockconf_lock as a WRITER for the whole operation, 963 * so all operations must be non-blocking. 964 */ 965 rw_enter(&sockconf_lock, RW_WRITER); 966 if (sof_entry_find(ent->sofe_name) != NULL) { 967 rw_exit(&sockconf_lock); 968 return (EEXIST); 969 } 970 971 /* The entry is unique; create the kstats */ 972 if (sof_entry_kstat_create(ent) != 0) { 973 rw_exit(&sockconf_lock); 974 return (ENOMEM); 975 } 976 977 /* 978 * Attach the filter to sockparams of interest. 979 */ 980 if ((error = sockparams_new_filter(ent)) != 0) { 981 sof_entry_kstat_destroy(ent); 982 rw_exit(&sockconf_lock); 983 return (error); 984 } 985 /* 986 * Everything is OK; insert in global list. 987 */ 988 list_insert_tail(&sof_entry_list, ent); 989 rw_exit(&sockconf_lock); 990 991 return (0); 992 } 993 994 /* 995 * Removes the filter entry `ent' from global list and all sockparams. 996 */ 997 sof_entry_t * 998 sof_entry_remove_by_name(const char *name) 999 { 1000 sof_entry_t *ent; 1001 1002 rw_enter(&sockconf_lock, RW_WRITER); 1003 if ((ent = sof_entry_find(name)) == NULL) { 1004 rw_exit(&sockconf_lock); 1005 return (NULL); 1006 } 1007 list_remove(&sof_entry_list, ent); 1008 sockparams_filter_cleanup(ent); 1009 sof_entry_kstat_destroy(ent); 1010 rw_exit(&sockconf_lock); 1011 1012 return (ent); 1013 } 1014 1015 /* 1016 * Filter entry `ent' will process sockparams entry `sp' to determine whether 1017 * it should be attached to the sockparams. It should be called whenever a new 1018 * filter or sockparams is being added. Returns zero either if the filter is 1019 * not interested in the sockparams or if it successfully attached to the 1020 * sockparams. On failure an errno is returned. 1021 */ 1022 int 1023 sof_entry_proc_sockparams(sof_entry_t *ent, struct sockparams *sp) 1024 { 1025 uint_t i; 1026 sof_socktuple_t *t = ent->sofe_socktuple; 1027 sp_filter_t *new, *fil; 1028 1029 /* Only interested in non-TPI sockets */ 1030 if (strcmp(sp->sp_smod_name, SOTPI_SMOD_NAME) == 0) 1031 return (0); 1032 1033 for (i = 0; i < ent->sofe_socktuple_cnt; i++) { 1034 if (t[i].sofst_family == sp->sp_family && 1035 t[i].sofst_type == sp->sp_type && 1036 t[i].sofst_protocol == sp->sp_protocol) 1037 break; 1038 } 1039 /* This filter is not interested in the sockparams entry */ 1040 if (i == ent->sofe_socktuple_cnt) 1041 return (0); 1042 1043 new = kmem_zalloc(sizeof (sp_filter_t), KM_NOSLEEP); 1044 if (new == NULL) 1045 return (ENOMEM); 1046 1047 new->spf_filter = ent; 1048 if (ent->sofe_flags & SOFEF_PROG) { 1049 /* placement is irrelevant for programmatic filters */ 1050 list_insert_head(&sp->sp_prog_filters, new); 1051 return (0); 1052 } else { 1053 ASSERT(ent->sofe_flags & SOFEF_AUTO); 1054 /* 1055 * If the filter specifies a placement hint, then make sure 1056 * it can be satisfied. 1057 */ 1058 switch (ent->sofe_hint) { 1059 case SOF_HINT_TOP: 1060 if ((fil = list_head(&sp->sp_auto_filters)) != NULL && 1061 fil->spf_filter->sofe_hint == SOF_HINT_TOP) 1062 break; 1063 list_insert_head(&sp->sp_auto_filters, new); 1064 return (0); 1065 case SOF_HINT_BOTTOM: 1066 if ((fil = list_tail(&sp->sp_auto_filters)) != NULL && 1067 fil->spf_filter->sofe_hint == SOF_HINT_BOTTOM) 1068 break; 1069 list_insert_tail(&sp->sp_auto_filters, new); 1070 return (0); 1071 case SOF_HINT_BEFORE: 1072 case SOF_HINT_AFTER: 1073 for (fil = list_head(&sp->sp_auto_filters); 1074 fil != NULL; 1075 fil = list_next(&sp->sp_auto_filters, fil)) { 1076 if (strncmp(ent->sofe_hintarg, 1077 fil->spf_filter->sofe_name, 1078 SOF_MAXNAMELEN) == 0) 1079 break; 1080 } 1081 1082 if (fil != NULL) { 1083 if (ent->sofe_hint == SOF_HINT_BEFORE) { 1084 if (fil->spf_filter->sofe_hint == 1085 SOF_HINT_TOP) 1086 break; 1087 list_insert_before(&sp->sp_auto_filters, 1088 fil, new); 1089 } else { 1090 if (fil->spf_filter->sofe_hint == 1091 SOF_HINT_BOTTOM) 1092 break; 1093 list_insert_after(&sp->sp_auto_filters, 1094 fil, new); 1095 } 1096 return (0); 1097 } 1098 /*FALLTHRU*/ 1099 case SOF_HINT_NONE: 1100 /* 1101 * Insert the new filter at the beginning as long as it 1102 * does not violate a TOP hint, otherwise insert in the 1103 * next suitable location. 1104 */ 1105 if ((fil = list_head(&sp->sp_auto_filters)) != NULL && 1106 fil->spf_filter->sofe_hint == SOF_HINT_TOP) { 1107 list_insert_after(&sp->sp_auto_filters, fil, 1108 new); 1109 } else { 1110 list_insert_head(&sp->sp_auto_filters, new); 1111 } 1112 return (0); 1113 } 1114 /* Failed to insert the filter */ 1115 kmem_free(new, sizeof (sp_filter_t)); 1116 return (ENOSPC); 1117 } 1118 } 1119 1120 /* 1121 * Remove all filter entries attached to the sockparams entry `sp'. 1122 */ 1123 void 1124 sof_sockparams_fini(struct sockparams *sp) 1125 { 1126 sp_filter_t *fil; 1127 1128 ASSERT(!list_link_active(&sp->sp_node)); 1129 1130 while ((fil = list_remove_head(&sp->sp_auto_filters)) != NULL) 1131 kmem_free(fil, sizeof (sp_filter_t)); 1132 while ((fil = list_remove_head(&sp->sp_prog_filters)) != NULL) 1133 kmem_free(fil, sizeof (sp_filter_t)); 1134 } 1135 1136 /* 1137 * A new sockparams is being added. Walk all filters and attach those that 1138 * are interested in the entry. 1139 * 1140 * It should be called when the sockparams entry is about to be made available 1141 * for use and while holding the sockconf_lock. 1142 */ 1143 int 1144 sof_sockparams_init(struct sockparams *sp) 1145 { 1146 sof_entry_t *ent; 1147 1148 ASSERT(RW_WRITE_HELD(&sockconf_lock)); 1149 1150 for (ent = list_head(&sof_entry_list); ent != NULL; 1151 ent = list_next(&sof_entry_list, ent)) { 1152 if (sof_entry_proc_sockparams(ent, sp) != 0) { 1153 sof_sockparams_fini(sp); 1154 return (ENOMEM); 1155 } 1156 } 1157 return (0); 1158 } 1159 1160 static sof_module_t * 1161 sof_module_find(const char *name) 1162 { 1163 sof_module_t *ent; 1164 1165 ASSERT(MUTEX_HELD(&sof_module_lock)); 1166 1167 for (ent = list_head(&sof_module_list); ent != NULL; 1168 ent = list_next(&sof_module_list, ent)) 1169 if (strcmp(ent->sofm_name, name) == 0) 1170 return (ent); 1171 return (NULL); 1172 } 1173 1174 /* 1175 * Returns a pointer to a module identified by `name' with its ref count 1176 * bumped. An attempt to load the module is done if it's not found in the 1177 * global list. 1178 */ 1179 sof_module_t * 1180 sof_module_hold_by_name(const char *name, const char *modname) 1181 { 1182 ddi_modhandle_t handle = NULL; 1183 sof_module_t *mod = NULL; 1184 char *modpath; 1185 int error; 1186 1187 /* 1188 * We'll go through the loop at most two times, which will only 1189 * happen if the module needs to be loaded. 1190 */ 1191 for (;;) { 1192 mutex_enter(&sof_module_lock); 1193 mod = sof_module_find(name); 1194 if (mod != NULL || handle != NULL) 1195 break; 1196 mutex_exit(&sof_module_lock); 1197 1198 modpath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1199 (void) snprintf(modpath, MAXPATHLEN, "%s/%s", SOF_MODPATH, 1200 modname); 1201 handle = ddi_modopen(modpath, KRTLD_MODE_FIRST, &error); 1202 kmem_free(modpath, MAXPATHLEN); 1203 /* Failed to load, then bail */ 1204 if (handle == NULL) { 1205 cmn_err(CE_WARN, 1206 "Failed to load socket filter module: %s (err %d)", 1207 modname, error); 1208 return (NULL); 1209 } 1210 } 1211 if (mod != NULL) 1212 mod->sofm_refcnt++; 1213 mutex_exit(&sof_module_lock); 1214 1215 if (handle != NULL) { 1216 (void) ddi_modclose(handle); 1217 /* 1218 * The module was loaded, but the filter module could not be 1219 * found. It's likely a misconfigured filter. 1220 */ 1221 if (mod == NULL) { 1222 cmn_err(CE_WARN, 1223 "Socket filter module %s was loaded, but did not" \ 1224 "register. Filter %s is likely misconfigured.", 1225 modname, name); 1226 } 1227 } 1228 1229 return (mod); 1230 } 1231 1232 void 1233 sof_module_rele(sof_module_t *mod) 1234 { 1235 mutex_enter(&sof_module_lock); 1236 mod->sofm_refcnt--; 1237 mutex_exit(&sof_module_lock); 1238 } 1239 1240 int 1241 sof_rval2errno(sof_rval_t rval) 1242 { 1243 if (rval > SOF_RVAL_CONTINUE) { 1244 return ((int)rval); 1245 } else { 1246 #ifdef DEBUG 1247 if (socket_filter_debug) 1248 printf("sof_rval2errno: invalid rval '%d'\n", rval); 1249 #endif 1250 return (EINVAL); 1251 } 1252 } 1253 1254 /* 1255 * Walk through all the filters attached to `so' and allow each filter 1256 * to process the data using its data_out callback. `mp' is a b_cont chain. 1257 * 1258 * Returns the processed mblk, or NULL if mblk was consumed. The mblk might 1259 * have been consumed as a result of an error, in which case `errp' is set to 1260 * the appropriate errno. 1261 */ 1262 mblk_t * 1263 sof_filter_data_out_from(struct sonode *so, sof_instance_t *start, 1264 mblk_t *mp, struct nmsghdr *msg, cred_t *cr, int *errp) 1265 { 1266 sof_instance_t *inst; 1267 sof_rval_t rval; 1268 1269 _NOTE(ARGUNUSED(so)); 1270 1271 for (inst = start; inst != NULL; inst = inst->sofi_next) { 1272 if (!SOF_INTERESTED(inst, data_out)) 1273 continue; 1274 mp = (inst->sofi_ops->sofop_data_out)((sof_handle_t)inst, 1275 inst->sofi_cookie, mp, msg, cr, &rval); 1276 DTRACE_PROBE2(filter__data, (sof_instance_t), inst, 1277 (mblk_t *), mp); 1278 if (mp == NULL) { 1279 *errp = sof_rval2errno(rval); 1280 break; 1281 } 1282 } 1283 return (mp); 1284 } 1285 1286 /* 1287 * Walk through all the filters attached to `so' and allow each filter 1288 * to process the data using its data_in_proc callback. `mp' is the start of 1289 * a possible b_next chain, and `lastmp' points to the last mblk in the chain. 1290 * 1291 * Returns the processed mblk, or NULL if all mblks in the chain were 1292 * consumed. `lastmp' is updated to point to the last mblk in the processed 1293 * chain. 1294 */ 1295 mblk_t * 1296 sof_filter_data_in_proc(struct sonode *so, mblk_t *mp, mblk_t **lastmp) 1297 { 1298 sof_instance_t *inst; 1299 size_t len = 0, orig = 0; 1300 ssize_t diff = 0; 1301 mblk_t *retmp = NULL, *tailmp, *nextmp; 1302 1303 *lastmp = NULL; 1304 do { 1305 nextmp = mp->b_next; 1306 mp->b_next = mp->b_prev = NULL; 1307 len = orig = msgdsize(mp); 1308 for (inst = so->so_filter_bottom; inst != NULL; 1309 inst = inst->sofi_prev) { 1310 if (!SOF_INTERESTED(inst, data_in_proc)) 1311 continue; 1312 mp = (inst->sofi_ops->sofop_data_in_proc)( 1313 (sof_handle_t)inst, inst->sofi_cookie, mp, 1314 kcred, &len); 1315 if (mp == NULL) 1316 break; 1317 } 1318 DTRACE_PROBE2(filter__data, (sof_instance_t), inst, 1319 (mblk_t *), mp); 1320 diff += len - orig; 1321 if (mp == NULL) 1322 continue; 1323 1324 for (tailmp = mp; tailmp->b_cont != NULL; 1325 tailmp = tailmp->b_cont) 1326 ; 1327 mp->b_prev = tailmp; 1328 1329 if (*lastmp == NULL) 1330 retmp = mp; 1331 else 1332 (*lastmp)->b_next = mp; 1333 *lastmp = mp; 1334 } while ((mp = nextmp) != NULL); 1335 1336 /* 1337 * The size of the chain has changed; make sure the rcv queue 1338 * stays consistent and check if the flow control state should 1339 * change. 1340 */ 1341 if (diff != 0) { 1342 DTRACE_PROBE2(filter__data__adjust__qlen, 1343 (struct sonode *), so, (size_t), diff); 1344 mutex_enter(&so->so_lock); 1345 so->so_rcv_queued += diff; 1346 /* so_check_flow_control drops so_lock */ 1347 so_check_flow_control(so); 1348 } 1349 1350 return (retmp); 1351 } 1352 1353 int 1354 sof_filter_bind(struct sonode *so, struct sockaddr *addr, 1355 socklen_t *addrlen, cred_t *cr) 1356 { 1357 __SOF_FILTER_OP(so, bind, cr, addr, addrlen) 1358 } 1359 1360 int 1361 sof_filter_listen(struct sonode *so, int *backlogp, cred_t *cr) 1362 { 1363 __SOF_FILTER_OP(so, listen, cr, backlogp) 1364 } 1365 1366 int 1367 sof_filter_connect(struct sonode *so, struct sockaddr *addr, 1368 socklen_t *addrlen, cred_t *cr) 1369 { 1370 __SOF_FILTER_OP(so, connect, cr, addr, addrlen) 1371 } 1372 1373 int 1374 sof_filter_accept(struct sonode *so, cred_t *cr) 1375 { 1376 sof_instance_t *inst; 1377 sof_rval_t rval; 1378 1379 for (inst = so->so_filter_top; inst != NULL; inst = inst->sofi_next) { 1380 if (!SOF_INTERESTED(inst, accept)) 1381 continue; 1382 rval = (inst->sofi_ops->sofop_accept)((sof_handle_t)inst, 1383 inst->sofi_cookie, cr); 1384 DTRACE_PROBE2(filter__action, (sof_instance_t), inst, 1385 (sof_rval_t), rval); 1386 if (rval != SOF_RVAL_CONTINUE) { 1387 ASSERT(rval != SOF_RVAL_RETURN); 1388 return (sof_rval2errno(rval)); 1389 } 1390 } 1391 return (-1); 1392 } 1393 1394 int 1395 sof_filter_shutdown(struct sonode *so, int *howp, cred_t *cr) 1396 { 1397 __SOF_FILTER_OP(so, shutdown, cr, howp) 1398 } 1399 1400 int 1401 sof_filter_getsockname(struct sonode *so, struct sockaddr *addr, 1402 socklen_t *addrlenp, cred_t *cr) 1403 { 1404 __SOF_FILTER_OP(so, getsockname, cr, addr, addrlenp) 1405 } 1406 1407 int 1408 sof_filter_getpeername(struct sonode *so, struct sockaddr *addr, 1409 socklen_t *addrlenp, cred_t *cr) 1410 { 1411 __SOF_FILTER_OP(so, getpeername, cr, addr, addrlenp) 1412 } 1413 1414 int 1415 sof_filter_setsockopt(struct sonode *so, int level, int option_name, 1416 void *optval, socklen_t *optlenp, cred_t *cr) 1417 { 1418 __SOF_FILTER_OP(so, setsockopt, cr, level, option_name, 1419 optval, optlenp) 1420 } 1421 1422 int 1423 sof_filter_getsockopt(struct sonode *so, int level, int option_name, 1424 void *optval, socklen_t *optlenp, cred_t *cr) 1425 { 1426 __SOF_FILTER_OP(so, getsockopt, cr, level, option_name, 1427 optval, optlenp) 1428 } 1429 1430 int 1431 sof_filter_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode, 1432 int32_t *rvalp, cred_t *cr) 1433 { 1434 __SOF_FILTER_OP(so, ioctl, cr, cmd, arg, mode, rvalp) 1435 } 1436 1437 /* 1438 * sof_register(version, name, ops, flags) 1439 * 1440 * Register a socket filter identified by name `name' and which should use 1441 * the ops vector `ops' for event notification. `flags' should be set to 0. 1442 * On success 0 is returned, otherwise an errno is returned. 1443 */ 1444 int 1445 sof_register(int version, const char *name, const sof_ops_t *ops, int flags) 1446 { 1447 sof_module_t *mod; 1448 1449 _NOTE(ARGUNUSED(flags)); 1450 1451 if (version != SOF_VERSION) 1452 return (EINVAL); 1453 1454 mod = kmem_zalloc(sizeof (sof_module_t), KM_SLEEP); 1455 mod->sofm_name = kmem_alloc(strlen(name) + 1, KM_SLEEP); 1456 (void) strcpy(mod->sofm_name, name); 1457 mod->sofm_ops = *ops; 1458 1459 mutex_enter(&sof_module_lock); 1460 if (sof_module_find(name) != NULL) { 1461 mutex_exit(&sof_module_lock); 1462 kmem_free(mod->sofm_name, strlen(mod->sofm_name) + 1); 1463 kmem_free(mod, sizeof (sof_module_t)); 1464 return (EEXIST); 1465 } 1466 list_insert_tail(&sof_module_list, mod); 1467 mutex_exit(&sof_module_lock); 1468 1469 return (0); 1470 } 1471 1472 /* 1473 * sof_unregister(name) 1474 * 1475 * Try to unregister the socket filter identified by `name'. If the filter 1476 * is successfully unregistered, then 0 is returned, otherwise an errno is 1477 * returned. 1478 */ 1479 int 1480 sof_unregister(const char *name) 1481 { 1482 sof_module_t *mod; 1483 1484 mutex_enter(&sof_module_lock); 1485 mod = sof_module_find(name); 1486 if (mod != NULL) { 1487 if (mod->sofm_refcnt == 0) { 1488 list_remove(&sof_module_list, mod); 1489 mutex_exit(&sof_module_lock); 1490 1491 kmem_free(mod->sofm_name, strlen(mod->sofm_name) + 1); 1492 kmem_free(mod, sizeof (sof_module_t)); 1493 return (0); 1494 } else { 1495 mutex_exit(&sof_module_lock); 1496 return (EBUSY); 1497 } 1498 } 1499 mutex_exit(&sof_module_lock); 1500 1501 return (ENXIO); 1502 } 1503 1504 /* 1505 * sof_newconn_ready(handle) 1506 * 1507 * The filter `handle` no longer wants to defer the socket it is attached 1508 * to. A newconn notification will be generated if there is no other filter 1509 * that wants the socket deferred. 1510 */ 1511 void 1512 sof_newconn_ready(sof_handle_t handle) 1513 { 1514 sof_instance_t *inst = (sof_instance_t *)handle; 1515 struct sonode *so = inst->sofi_sonode; 1516 struct sonode *pso = so->so_listener; 1517 1518 mutex_enter(&so->so_lock); 1519 if (!(inst->sofi_flags & SOFIF_DEFER)) { 1520 mutex_exit(&so->so_lock); 1521 return; 1522 } 1523 ASSERT(so->so_state & SS_FIL_DEFER); 1524 inst->sofi_flags &= ~SOFIF_DEFER; 1525 SOF_STAT_ADD(inst, ndeferred, -1); 1526 1527 /* 1528 * Check if any other filter has deferred the socket. The last 1529 * filter to remove its DEFER flag will be the one generating the 1530 * wakeup. 1531 */ 1532 for (inst = so->so_filter_top; inst != NULL; inst = inst->sofi_next) { 1533 /* Still deferred; nothing to do */ 1534 if (inst->sofi_flags & SOFIF_DEFER) { 1535 mutex_exit(&so->so_lock); 1536 return; 1537 } 1538 } 1539 so->so_state &= ~SS_FIL_DEFER; 1540 mutex_exit(&so->so_lock); 1541 1542 /* 1543 * The socket is no longer deferred; move it over to the regular 1544 * accept list and notify the user. However, it is possible that 1545 * the socket is being dropped by sof_sonode_drop_deferred(), so 1546 * first make sure the socket is on the deferred list. 1547 */ 1548 mutex_enter(&pso->so_acceptq_lock); 1549 if (!list_link_active(&so->so_acceptq_node)) { 1550 mutex_exit(&pso->so_acceptq_lock); 1551 return; 1552 } 1553 list_remove(&pso->so_acceptq_defer, so); 1554 list_insert_tail(&pso->so_acceptq_list, so); 1555 cv_signal(&pso->so_acceptq_cv); 1556 mutex_exit(&pso->so_acceptq_lock); 1557 1558 mutex_enter(&pso->so_lock); 1559 so_notify_newconn(pso); /* so_notify_newconn drops the lock */ 1560 } 1561 1562 /* 1563 * sof_bypass(handle) 1564 * 1565 * Stop generating callbacks for `handle'. 1566 */ 1567 void 1568 sof_bypass(sof_handle_t handle) 1569 { 1570 sof_instance_t *inst = (sof_instance_t *)handle; 1571 struct sonode *so = inst->sofi_sonode; 1572 1573 mutex_enter(&so->so_lock); 1574 if (!(inst->sofi_flags & SOFIF_BYPASS)) { 1575 inst->sofi_flags |= SOFIF_BYPASS; 1576 ASSERT(so->so_filter_active > 0); 1577 so->so_filter_active--; 1578 } 1579 mutex_exit(&so->so_lock); 1580 } 1581 1582 /* 1583 * sof_rcv_flowctrl(handle, enable) 1584 * 1585 * If `enable' is TRUE, then recv side flow control will be asserted for 1586 * the socket associated with `handle'. When `enable' is FALSE the filter 1587 * indicates that it no longer wants to assert flow control, however, the 1588 * condition will not be removed until there are no other filters asserting 1589 * flow control and there is space available in the receive buffer. 1590 */ 1591 void 1592 sof_rcv_flowctrl(sof_handle_t handle, boolean_t enable) 1593 { 1594 sof_instance_t *inst = (sof_instance_t *)handle; 1595 struct sonode *so = inst->sofi_sonode; 1596 1597 mutex_enter(&so->so_lock); 1598 if (enable) { 1599 inst->sofi_flags |= SOFIF_RCV_FLOWCTRL; 1600 so->so_flowctrld = B_TRUE; 1601 so->so_state |= SS_FIL_RCV_FLOWCTRL; 1602 mutex_exit(&so->so_lock); 1603 } else { 1604 inst->sofi_flags &= ~SOFIF_RCV_FLOWCTRL; 1605 for (inst = so->so_filter_top; inst != NULL; 1606 inst = inst->sofi_next) { 1607 /* another filter is asserting flow control */ 1608 if (inst->sofi_flags & SOFIF_RCV_FLOWCTRL) { 1609 mutex_exit(&so->so_lock); 1610 return; 1611 } 1612 } 1613 so->so_state &= ~SS_FIL_RCV_FLOWCTRL; 1614 /* so_check_flow_control drops so_lock */ 1615 so_check_flow_control(so); 1616 } 1617 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 1618 } 1619 1620 /* 1621 * sof_snd_flowctrl(handle, enable) 1622 * 1623 * If `enable' is TRUE, then send side flow control will be asserted for 1624 * the socket associated with `handle'. When `enable' is FALSE the filter 1625 * indicates that is no longer wants to assert flow control, however, the 1626 * condition will not be removed until there are no other filters asserting 1627 * flow control and there are tx buffers available. 1628 */ 1629 void 1630 sof_snd_flowctrl(sof_handle_t handle, boolean_t enable) 1631 { 1632 sof_instance_t *inst = (sof_instance_t *)handle; 1633 struct sonode *so = inst->sofi_sonode; 1634 1635 mutex_enter(&so->so_lock); 1636 if (enable) { 1637 inst->sofi_flags |= SOFIF_SND_FLOWCTRL; 1638 so->so_state |= SS_FIL_SND_FLOWCTRL; 1639 } else { 1640 inst->sofi_flags &= ~SOFIF_SND_FLOWCTRL; 1641 for (inst = so->so_filter_top; inst != NULL; 1642 inst = inst->sofi_next) { 1643 if (inst->sofi_flags & SOFIF_SND_FLOWCTRL) { 1644 mutex_exit(&so->so_lock); 1645 return; 1646 } 1647 } 1648 so->so_state &= ~SS_FIL_SND_FLOWCTRL; 1649 /* 1650 * Wake up writer if the socket is no longer flow controlled. 1651 */ 1652 if (!SO_SND_FLOWCTRLD(so)) { 1653 /* so_notify_writable drops so_lock */ 1654 so_notify_writable(so); 1655 return; 1656 } 1657 } 1658 mutex_exit(&so->so_lock); 1659 } 1660 1661 /* 1662 * sof_get_cookie(handle) 1663 * 1664 * Returns the cookie used by `handle'. 1665 */ 1666 void * 1667 sof_get_cookie(sof_handle_t handle) 1668 { 1669 return (((sof_instance_t *)handle)->sofi_cookie); 1670 } 1671 1672 /* 1673 * sof_cas_cookie(handle, old, new) 1674 * 1675 * Compare-and-swap the cookie used by `handle'. 1676 */ 1677 void * 1678 sof_cas_cookie(sof_handle_t handle, void *old, void *new) 1679 { 1680 sof_instance_t *inst = (sof_instance_t *)handle; 1681 1682 return (atomic_cas_ptr(&inst->sofi_cookie, old, new)); 1683 } 1684 1685 /* 1686 * sof_inject_data_out(handle, mp, msg, flowctrld) 1687 * 1688 * Submit `mp' for transmission. `msg' cannot by NULL, and may contain 1689 * ancillary data and destination address. Returns 0 when successful 1690 * in which case `flowctrld' is updated. If flow controlled, no new data 1691 * should be injected until a SOF_EV_INJECT_DATA_OUT_OK event is observed. 1692 * In case of failure, an errno is returned. 1693 * 1694 * Filters that are lower in the stack than `handle' will see the data 1695 * before it is transmitted and may end up modifying or freeing the data. 1696 */ 1697 int 1698 sof_inject_data_out(sof_handle_t handle, mblk_t *mp, struct nmsghdr *msg, 1699 boolean_t *flowctrld) 1700 { 1701 sof_instance_t *inst = (sof_instance_t *)handle; 1702 struct sonode *so = inst->sofi_sonode; 1703 int error; 1704 1705 /* 1706 * Data cannot be sent down to the protocol once the socket has 1707 * started the process of closing. 1708 */ 1709 mutex_enter(&so->so_lock); 1710 if (so->so_state & SS_CLOSING) { 1711 mutex_exit(&so->so_lock); 1712 freemsg(mp); 1713 return (EPIPE); 1714 } 1715 so->so_filter_tx++; 1716 mutex_exit(&so->so_lock); 1717 1718 error = so_sendmblk_impl(inst->sofi_sonode, msg, FNONBLOCK, 1719 kcred, &mp, inst->sofi_next, B_TRUE); 1720 1721 mutex_enter(&so->so_lock); 1722 ASSERT(so->so_filter_tx > 0); 1723 so->so_filter_tx--; 1724 if (so->so_state & SS_CLOSING) 1725 cv_signal(&so->so_closing_cv); 1726 mutex_exit(&so->so_lock); 1727 1728 if (mp != NULL) 1729 freemsg(mp); 1730 1731 if (error == ENOSPC) { 1732 *flowctrld = B_TRUE; 1733 error = 0; 1734 } else { 1735 *flowctrld = B_FALSE; 1736 } 1737 1738 return (error); 1739 } 1740 1741 /* 1742 * sof_inject_data_in(handle, mp, len, flag, flowctrld) 1743 * 1744 * Enqueue `mp' which contains `len' bytes of M_DATA onto the socket 1745 * associated with `handle'. `flags' should be set to 0. Returns 0 when 1746 * successful in which case `flowctrld' is updated. If flow controlled, 1747 * no new data should be injected until a SOF_EV_INJECT_DATA_IN_OK event 1748 * is observed. In case of failure, an errno is returned. 1749 * 1750 * Filters that are higher in the stack than `handle' will see the data 1751 * before it is enqueued on the receive queue and may end up modifying or 1752 * freeing the data. 1753 */ 1754 int 1755 sof_inject_data_in(sof_handle_t handle, mblk_t *mp, size_t len, int flags, 1756 boolean_t *flowctrld) 1757 { 1758 sof_instance_t *inst = (sof_instance_t *)handle; 1759 ssize_t avail; 1760 int error = 0; 1761 1762 ASSERT(flags == 0); 1763 avail = so_queue_msg_impl(inst->sofi_sonode, mp, len, flags, &error, 1764 NULL, inst->sofi_prev); 1765 /* fallback should never happen when there is an active filter */ 1766 ASSERT(error != EOPNOTSUPP); 1767 1768 *flowctrld = (avail > 0) ? B_FALSE : B_TRUE; 1769 return (error); 1770 } 1771 1772 /* 1773 * sof_newconn_move(handle, newparent) 1774 * 1775 * Private interface only to be used by KSSL. 1776 * 1777 * Moves the socket associated with `handle' from its current listening 1778 * socket to the listener associated with `newparent'. The socket being 1779 * moved must be in a deferred state and it is up to the consumer of the 1780 * interface to ensure that the `newparent' does not go away while this 1781 * operation is pending. 1782 */ 1783 boolean_t 1784 sof_newconn_move(sof_handle_t handle, sof_handle_t newparent) 1785 { 1786 sof_instance_t *inst = (sof_instance_t *)handle; 1787 sof_instance_t *newpinst = (sof_instance_t *)newparent; 1788 struct sonode *so, *old, *new; 1789 1790 so = inst->sofi_sonode; 1791 ASSERT(so->so_state & SS_FIL_DEFER); 1792 1793 if (inst->sofi_next != NULL || inst->sofi_prev != NULL || 1794 !(so->so_state & SS_FIL_DEFER)) 1795 return (B_FALSE); 1796 1797 old = so->so_listener; 1798 mutex_enter(&old->so_acceptq_lock); 1799 list_remove(&old->so_acceptq_defer, so); 1800 old->so_acceptq_len--; 1801 mutex_exit(&old->so_acceptq_lock); 1802 1803 new = newpinst->sofi_sonode; 1804 mutex_enter(&new->so_acceptq_lock); 1805 list_insert_tail(&new->so_acceptq_defer, so); 1806 new->so_acceptq_len++; 1807 mutex_exit(&new->so_acceptq_lock); 1808 1809 so->so_listener = new; 1810 1811 return (B_TRUE); 1812 } 1813