1/* 2 * Copyright (c) 1998-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ 29/* 30 * Copyright (c) 1982, 1986, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. All advertising materials mentioning features or use of this software 42 * must display the following acknowledgement: 43 * This product includes software developed by the University of 44 * California, Berkeley and its contributors. 45 * 4. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * @(#)uipc_domain.c 8.3 (Berkeley) 2/14/95 62 */ 63 64#include <sys/param.h> 65#include <sys/socket.h> 66#include <sys/protosw.h> 67#include <sys/domain.h> 68#include <sys/mcache.h> 69#include <sys/mbuf.h> 70#include <sys/time.h> 71#include <sys/kernel.h> 72#include <sys/systm.h> 73#include <sys/proc_internal.h> 74#include <sys/sysctl.h> 75#include <sys/syslog.h> 76#include <sys/queue.h> 77 78#include <net/dlil.h> 79 80#include <mach/boolean.h> 81#include <pexpert/pexpert.h> 82 83static void pr_init_old(struct protosw *, struct domain *); 84static void init_proto(struct protosw *, struct domain *); 85static void attach_proto(struct protosw *, struct domain *); 86static void detach_proto(struct protosw *, struct domain *); 87static void dom_init_old(struct domain *); 88static void init_domain(struct domain *); 89static void attach_domain(struct domain *); 90static void detach_domain(struct domain *); 91static struct protosw *pffindprotonotype_locked(int, int, int); 92static struct domain *pffinddomain_locked(int); 93 94static boolean_t domain_timeout_run; /* domain timer is scheduled to run */ 95static boolean_t domain_draining; 96static void domain_sched_timeout(void); 97static void domain_timeout(void *); 98 99lck_grp_t *domain_proto_mtx_grp; 100lck_attr_t *domain_proto_mtx_attr; 101static lck_grp_attr_t *domain_proto_mtx_grp_attr; 102decl_lck_mtx_data(static, domain_proto_mtx); 103decl_lck_mtx_data(static, domain_timeout_mtx); 104 105static u_int64_t _net_uptime; 106 107static void 108pr_init_old(struct protosw *pp, struct domain *dp) 109{ 110#pragma unused(dp) 111 VERIFY(pp->pr_flags & PR_OLD); 112 VERIFY(pp->pr_old != NULL); 113 114 if (pp->pr_old->pr_init != NULL) 115 pp->pr_old->pr_init(); 116} 117 118static void 119init_proto(struct protosw *pp, struct domain *dp) 120{ 121 VERIFY(pp->pr_flags & PR_ATTACHED); 122 123 if (!(pp->pr_flags & PR_INITIALIZED)) { 124 TAILQ_INIT(&pp->pr_filter_head); 125 if (pp->pr_init != NULL) 126 pp->pr_init(pp, dp); 127 pp->pr_flags |= PR_INITIALIZED; 128 } 129} 130 131static void 132attach_proto(struct protosw *pp, struct domain *dp) 133{ 134 domain_proto_mtx_lock_assert_held(); 135 VERIFY(!(pp->pr_flags & PR_ATTACHED)); 136 VERIFY(pp->pr_domain == NULL); 137 VERIFY(pp->pr_protosw == NULL); 138 139 TAILQ_INSERT_TAIL(&dp->dom_protosw, pp, pr_entry); 140 pp->pr_flags |= PR_ATTACHED; 141 pp->pr_domain = dp; 142 pp->pr_protosw = pp; 143 144 /* do some cleaning up on user request callbacks */ 145 pru_sanitize(pp->pr_usrreqs); 146} 147 148static void 149detach_proto(struct protosw *pp, struct domain *dp) 150{ 151 domain_proto_mtx_lock_assert_held(); 152 VERIFY(pp->pr_flags & PR_ATTACHED); 153 VERIFY(pp->pr_domain == dp); 154 VERIFY(pp->pr_protosw == pp); 155 156 TAILQ_REMOVE(&dp->dom_protosw, pp, pr_entry); 157 pp->pr_flags &= ~PR_ATTACHED; 158 pp->pr_domain = NULL; 159 pp->pr_protosw = NULL; 160} 161 162static void 163dom_init_old(struct domain *dp) 164{ 165 VERIFY(dp->dom_flags & DOM_OLD); 166 VERIFY(dp->dom_old != NULL); 167 168 if (dp->dom_old->dom_init != NULL) 169 dp->dom_old->dom_init(); 170} 171 172static void 173init_domain(struct domain *dp) 174{ 175 VERIFY(dp->dom_flags & DOM_ATTACHED); 176 177 if (!(dp->dom_flags & DOM_INITIALIZED)) { 178 lck_mtx_init(&dp->dom_mtx_s, domain_proto_mtx_grp, 179 domain_proto_mtx_attr); 180 dp->dom_mtx = &dp->dom_mtx_s; 181 TAILQ_INIT(&dp->dom_protosw); 182 if (dp->dom_init != NULL) 183 dp->dom_init(dp); 184 dp->dom_flags |= DOM_INITIALIZED; 185 } 186 187 /* Recompute for new protocol */ 188 if (_max_linkhdr < 16) /* XXX - Sheesh; everything's ether? */ 189 _max_linkhdr = 16; 190 _max_linkhdr = max_linkhdr; /* round it up */ 191 192 if (dp->dom_protohdrlen > _max_protohdr) 193 _max_protohdr = dp->dom_protohdrlen; 194 _max_protohdr = max_protohdr; /* round it up */ 195 196 max_hdr = max_linkhdr + max_protohdr; 197 max_datalen = MHLEN - max_hdr; 198} 199 200static void 201attach_domain(struct domain *dp) 202{ 203 domain_proto_mtx_lock_assert_held(); 204 VERIFY(!(dp->dom_flags & DOM_ATTACHED)); 205 206 TAILQ_INSERT_TAIL(&domains, dp, dom_entry); 207 dp->dom_flags |= DOM_ATTACHED; 208} 209 210static void 211detach_domain(struct domain *dp) 212{ 213 domain_proto_mtx_lock_assert_held(); 214 VERIFY(dp->dom_flags & DOM_ATTACHED); 215 216 TAILQ_REMOVE(&domains, dp, dom_entry); 217 dp->dom_flags &= ~DOM_ATTACHED; 218 219 if (dp->dom_flags & DOM_OLD) { 220 struct domain_old *odp = dp->dom_old; 221 222 VERIFY(odp != NULL); 223 odp->dom_next = NULL; 224 odp->dom_mtx = NULL; 225 } 226} 227 228/* 229 * Exported (private) routine, indirection of net_add_domain. 230 */ 231void 232net_add_domain_old(struct domain_old *odp) 233{ 234 struct domain *dp; 235 domain_guard_t guard; 236 237 VERIFY(odp != NULL); 238 239 guard = domain_guard_deploy(); 240 if ((dp = pffinddomain_locked(odp->dom_family)) != NULL) { 241 /* 242 * There is really nothing better than to panic here, 243 * as the caller would not have been able to handle 244 * any failures otherwise. 245 */ 246 panic("%s: domain (%d,%s) already exists for %s\n", __func__, 247 dp->dom_family, dp->dom_name, odp->dom_name); 248 /* NOTREACHED */ 249 } 250 251 /* Make sure nothing is currently pointing to the odp. */ 252 TAILQ_FOREACH(dp, &domains, dom_entry) { 253 if (dp->dom_old == odp) { 254 panic("%s: domain %p (%d,%s) is already " 255 "associated with %p (%d,%s)\n", __func__, 256 odp, odp->dom_family, odp->dom_name, dp, 257 dp->dom_family, dp->dom_name); 258 /* NOTREACHED */ 259 } 260 } 261 262 if (odp->dom_protosw != NULL) { 263 panic("%s: domain (%d,%s) protocols need to added " 264 "via net_add_proto\n", __func__, odp->dom_family, 265 odp->dom_name); 266 /* NOTREACHED */ 267 } 268 269 dp = _MALLOC(sizeof (*dp), M_TEMP, M_WAITOK | M_ZERO); 270 if (dp == NULL) { 271 /* 272 * There is really nothing better than to panic here, 273 * as the caller would not have been able to handle 274 * any failures otherwise. 275 */ 276 panic("%s: unable to allocate memory for domain family " 277 "%d (%s)\n", __func__, odp->dom_family, odp->dom_name); 278 /* NOTREACHED */ 279 } 280 281 /* Copy everything but dom_init, dom_mtx, dom_next and dom_refs */ 282 dp->dom_family = odp->dom_family; 283 dp->dom_flags = (odp->dom_flags & DOMF_USERFLAGS) | DOM_OLD; 284 dp->dom_name = odp->dom_name; 285 dp->dom_init = dom_init_old; 286 dp->dom_externalize = odp->dom_externalize; 287 dp->dom_dispose = odp->dom_dispose; 288 dp->dom_rtattach = odp->dom_rtattach; 289 dp->dom_rtoffset = odp->dom_rtoffset; 290 dp->dom_maxrtkey = odp->dom_maxrtkey; 291 dp->dom_protohdrlen = odp->dom_protohdrlen; 292 dp->dom_old = odp; 293 294 attach_domain(dp); 295 init_domain(dp); 296 297 /* Point the mutex back to the internal structure's */ 298 odp->dom_mtx = dp->dom_mtx; 299 domain_guard_release(guard); 300} 301 302/* 303 * Exported (private) routine, indirection of net_del_domain. 304 */ 305int 306net_del_domain_old(struct domain_old *odp) 307{ 308 struct domain *dp1, *dp2; 309 int error = 0; 310 domain_guard_t guard; 311 312 VERIFY(odp != NULL); 313 314 guard = domain_guard_deploy(); 315 if (odp->dom_refs != 0) { 316 error = EBUSY; 317 goto done; 318 } 319 320 TAILQ_FOREACH_SAFE(dp1, &domains, dom_entry, dp2) { 321 if (!(dp1->dom_flags & DOM_OLD)) 322 continue; 323 VERIFY(dp1->dom_old != NULL); 324 if (odp == dp1->dom_old) 325 break; 326 } 327 if (dp1 != NULL) { 328 struct protosw *pp1, *pp2; 329 330 VERIFY(dp1->dom_flags & DOM_OLD); 331 VERIFY(dp1->dom_old == odp); 332 333 /* Remove all protocols attached to this domain */ 334 TAILQ_FOREACH_SAFE(pp1, &dp1->dom_protosw, pr_entry, pp2) { 335 detach_proto(pp1, dp1); 336 if (pp1->pr_usrreqs->pru_flags & PRUF_OLD) 337 FREE(pp1->pr_usrreqs, M_TEMP); 338 if (pp1->pr_flags & PR_OLD) 339 FREE(pp1, M_TEMP); 340 } 341 342 detach_domain(dp1); 343 FREE(dp1, M_TEMP); 344 } else { 345 error = EPFNOSUPPORT; 346 } 347done: 348 domain_guard_release(guard); 349 return (error); 350} 351 352/* 353 * Internal routine, not exported. 354 * 355 * net_add_proto - link a protosw into a domain's protosw chain 356 * 357 * NOTE: Caller must have acquired domain_proto_mtx 358 */ 359int 360net_add_proto(struct protosw *pp, struct domain *dp, int doinit) 361{ 362 struct protosw *pp1; 363 364 /* 365 * This could be called as part of initializing the domain, 366 * and thus DOM_INITIALIZED may not be set (yet). 367 */ 368 domain_proto_mtx_lock_assert_held(); 369 VERIFY(!(pp->pr_flags & PR_ATTACHED)); 370 371 /* pr_domain is set only after the protocol is attached */ 372 if (pp->pr_domain != NULL) { 373 panic("%s: domain (%d,%s), proto %d has non-NULL pr_domain!\n", 374 __func__, dp->dom_family, dp->dom_name, pp->pr_protocol); 375 /* NOTREACHED */ 376 } 377 378 if (pp->pr_usrreqs == NULL) { 379 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n", 380 __func__, dp->dom_family, dp->dom_name, pp->pr_protocol); 381 /* NOTREACHED */ 382 } 383 384 TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) { 385 if (pp1->pr_type == pp->pr_type && 386 pp1->pr_protocol == pp->pr_protocol) 387 return (EEXIST); 388 } 389 390 attach_proto(pp, dp); 391 if (doinit) 392 net_init_proto(pp, dp); 393 394 return (0); 395} 396 397void 398net_init_proto(struct protosw *pp, struct domain *dp) 399{ 400 /* 401 * This could be called as part of initializing the domain, 402 * and thus DOM_INITIALIZED may not be set (yet). The protocol 403 * must have been attached via net_addr_protosw() by now. 404 */ 405 domain_proto_mtx_lock_assert_held(); 406 VERIFY(pp->pr_flags & PR_ATTACHED); 407 408 init_proto(pp, dp); 409} 410 411/* 412 * Exported (private) routine, indirection of net_add_proto. 413 */ 414int 415net_add_proto_old(struct protosw_old *opp, struct domain_old *odp) 416{ 417 struct pr_usrreqs_old *opru; 418 struct pr_usrreqs *pru = NULL; 419 struct protosw *pp = NULL, *pp1; 420 int error = 0; 421 struct domain *dp; 422 domain_guard_t guard; 423 424 /* 425 * This could be called as part of initializing the domain, 426 * and thus DOM_INITIALIZED may not be set (yet). 427 */ 428 guard = domain_guard_deploy(); 429 430 /* Make sure the domain has been added via net_add_domain */ 431 TAILQ_FOREACH(dp, &domains, dom_entry) { 432 if (!(dp->dom_flags & DOM_OLD)) 433 continue; 434 if (dp->dom_old == odp) 435 break; 436 } 437 if (dp == NULL) { 438 error = EINVAL; 439 goto done; 440 } 441 442 TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) { 443 if (pp1->pr_type == opp->pr_type && 444 pp1->pr_protocol == opp->pr_protocol) { 445 error = EEXIST; 446 goto done; 447 } 448 } 449 450 if ((opru = opp->pr_usrreqs) == NULL) { 451 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n", 452 __func__, odp->dom_family, odp->dom_name, opp->pr_protocol); 453 /* NOTREACHED */ 454 } 455 456 pru = _MALLOC(sizeof (*pru), M_TEMP, M_WAITOK | M_ZERO); 457 if (pru == NULL) { 458 error = ENOMEM; 459 goto done; 460 } 461 462 pru->pru_flags = PRUF_OLD; 463 pru->pru_abort = opru->pru_abort; 464 pru->pru_accept = opru->pru_accept; 465 pru->pru_attach = opru->pru_attach; 466 pru->pru_bind = opru->pru_bind; 467 pru->pru_connect = opru->pru_connect; 468 pru->pru_connect2 = opru->pru_connect2; 469 pru->pru_control = opru->pru_control; 470 pru->pru_detach = opru->pru_detach; 471 pru->pru_disconnect = opru->pru_disconnect; 472 pru->pru_listen = opru->pru_listen; 473 pru->pru_peeraddr = opru->pru_peeraddr; 474 pru->pru_rcvd = opru->pru_rcvd; 475 pru->pru_rcvoob = opru->pru_rcvoob; 476 pru->pru_send = opru->pru_send; 477 pru->pru_sense = opru->pru_sense; 478 pru->pru_shutdown = opru->pru_shutdown; 479 pru->pru_sockaddr = opru->pru_sockaddr; 480 pru->pru_sosend = opru->pru_sosend; 481 pru->pru_soreceive = opru->pru_soreceive; 482 pru->pru_sopoll = opru->pru_sopoll; 483 484 pp = _MALLOC(sizeof (*pp), M_TEMP, M_WAITOK | M_ZERO); 485 if (pp == NULL) { 486 error = ENOMEM; 487 goto done; 488 } 489 490 /* 491 * Protocol fast and slow timers are now deprecated. 492 */ 493 if (opp->pr_unused != NULL) { 494 printf("%s: domain (%d,%s), proto %d: pr_fasttimo is " 495 "deprecated and won't be called\n", __func__, 496 odp->dom_family, odp->dom_name, opp->pr_protocol); 497 } 498 if (opp->pr_unused2 != NULL) { 499 printf("%s: domain (%d,%s), proto %d: pr_slowtimo is " 500 "deprecated and won't be called\n", __func__, 501 odp->dom_family, odp->dom_name, opp->pr_protocol); 502 } 503 504 /* Copy everything but pr_init, pr_next, pr_domain, pr_protosw */ 505 pp->pr_type = opp->pr_type; 506 pp->pr_protocol = opp->pr_protocol; 507 pp->pr_flags = (opp->pr_flags & PRF_USERFLAGS) | PR_OLD; 508 pp->pr_input = opp->pr_input; 509 pp->pr_output = opp->pr_output; 510 pp->pr_ctlinput = opp->pr_ctlinput; 511 pp->pr_ctloutput = opp->pr_ctloutput; 512 pp->pr_usrreqs = pru; 513 pp->pr_init = pr_init_old; 514 pp->pr_drain = opp->pr_drain; 515 pp->pr_sysctl = opp->pr_sysctl; 516 pp->pr_lock = opp->pr_lock; 517 pp->pr_unlock = opp->pr_unlock; 518 pp->pr_getlock = opp->pr_getlock; 519 pp->pr_old = opp; 520 521 /* attach as well as initialize */ 522 attach_proto(pp, dp); 523 net_init_proto(pp, dp); 524done: 525 if (error != 0) { 526 printf("%s: domain (%d,%s), proto %d: failed to attach, " 527 "error %d\n", __func__, odp->dom_family, 528 odp->dom_name, opp->pr_protocol, error); 529 530 if (pru != NULL) 531 FREE(pru, M_TEMP); 532 if (pp != NULL) 533 FREE(pp, M_TEMP); 534 } 535 536 domain_guard_release(guard); 537 return (error); 538} 539 540/* 541 * Internal routine, not exported. 542 * 543 * net_del_proto - remove a protosw from a domain's protosw chain. 544 * Search the protosw chain for the element with matching data. 545 * Then unlink and return. 546 * 547 * NOTE: Caller must have acquired domain_proto_mtx 548 */ 549int 550net_del_proto(int type, int protocol, struct domain *dp) 551{ 552 struct protosw *pp; 553 554 /* 555 * This could be called as part of initializing the domain, 556 * and thus DOM_INITIALIZED may not be set (yet). 557 */ 558 domain_proto_mtx_lock_assert_held(); 559 560 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 561 if (pp->pr_type == type && pp->pr_protocol == protocol) 562 break; 563 } 564 if (pp == NULL) 565 return (ENXIO); 566 567 detach_proto(pp, dp); 568 if (pp->pr_usrreqs->pru_flags & PRUF_OLD) 569 FREE(pp->pr_usrreqs, M_TEMP); 570 if (pp->pr_flags & PR_OLD) 571 FREE(pp, M_TEMP); 572 573 return (0); 574} 575 576/* 577 * Exported (private) routine, indirection of net_del_proto. 578 */ 579int 580net_del_proto_old(int type, int protocol, struct domain_old *odp) 581{ 582 int error = 0; 583 struct protosw *pp; 584 struct domain *dp; 585 domain_guard_t guard; 586 587 /* 588 * This could be called as part of initializing the domain, 589 * and thus DOM_INITIALIZED may not be set (yet). 590 */ 591 guard = domain_guard_deploy(); 592 593 /* Make sure the domain has been added via net_add_domain */ 594 TAILQ_FOREACH(dp, &domains, dom_entry) { 595 if (!(dp->dom_flags & DOM_OLD)) 596 continue; 597 if (dp->dom_old == odp) 598 break; 599 } 600 if (dp == NULL) { 601 error = ENXIO; 602 goto done; 603 } 604 605 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 606 if (pp->pr_type == type && pp->pr_protocol == protocol) 607 break; 608 } 609 if (pp == NULL) { 610 error = ENXIO; 611 goto done; 612 } 613 detach_proto(pp, dp); 614 if (pp->pr_usrreqs->pru_flags & PRUF_OLD) 615 FREE(pp->pr_usrreqs, M_TEMP); 616 if (pp->pr_flags & PR_OLD) 617 FREE(pp, M_TEMP); 618 619done: 620 domain_guard_release(guard); 621 return (error); 622} 623 624static void 625domain_sched_timeout(void) 626{ 627 lck_mtx_assert(&domain_timeout_mtx, LCK_MTX_ASSERT_OWNED); 628 629 if (!domain_timeout_run && domain_draining) { 630 domain_timeout_run = TRUE; 631 timeout(domain_timeout, NULL, hz); 632 } 633} 634 635void 636net_drain_domains(void) 637{ 638 lck_mtx_lock(&domain_timeout_mtx); 639 domain_draining = TRUE; 640 domain_sched_timeout(); 641 lck_mtx_unlock(&domain_timeout_mtx); 642} 643 644#if INET6 645extern struct domain inet6domain_s; 646#endif 647#if IPSEC 648extern struct domain keydomain_s; 649#endif 650 651extern struct domain routedomain_s, ndrvdomain_s, inetdomain_s; 652extern struct domain systemdomain_s, localdomain_s; 653 654#if MULTIPATH 655extern struct domain mpdomain_s; 656#endif /* MULTIPATH */ 657 658static void 659domain_timeout(void *arg) 660{ 661#pragma unused(arg) 662 struct protosw *pp; 663 struct domain *dp; 664 domain_guard_t guard; 665 666 lck_mtx_lock(&domain_timeout_mtx); 667 if (domain_draining) { 668 domain_draining = FALSE; 669 lck_mtx_unlock(&domain_timeout_mtx); 670 671 guard = domain_guard_deploy(); 672 TAILQ_FOREACH(dp, &domains, dom_entry) { 673 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 674 if (pp->pr_drain != NULL) 675 (*pp->pr_drain)(); 676 } 677 } 678 domain_guard_release(guard); 679 680 lck_mtx_lock(&domain_timeout_mtx); 681 } 682 683 /* re-arm the timer if there's work to do */ 684 domain_timeout_run = FALSE; 685 domain_sched_timeout(); 686 lck_mtx_unlock(&domain_timeout_mtx); 687} 688 689void 690domaininit(void) 691{ 692 struct domain *dp; 693 domain_guard_t guard; 694 695 /* 696 * allocate lock group attribute and group for domain mutexes 697 */ 698 domain_proto_mtx_grp_attr = lck_grp_attr_alloc_init(); 699 700 domain_proto_mtx_grp = lck_grp_alloc_init("domain", 701 domain_proto_mtx_grp_attr); 702 703 /* 704 * allocate the lock attribute for per domain mutexes 705 */ 706 domain_proto_mtx_attr = lck_attr_alloc_init(); 707 708 lck_mtx_init(&domain_proto_mtx, domain_proto_mtx_grp, 709 domain_proto_mtx_attr); 710 lck_mtx_init(&domain_timeout_mtx, domain_proto_mtx_grp, 711 domain_proto_mtx_attr); 712 713 guard = domain_guard_deploy(); 714 /* 715 * Add all the static domains to the domains list. route domain 716 * gets added and initialized last, since we need it to attach 717 * rt_tables[] to everything that's already there. This also 718 * means that domains added after this point won't get their 719 * dom_rtattach() called on rt_tables[]. 720 */ 721 attach_domain(&inetdomain_s); 722#if INET6 723 attach_domain(&inet6domain_s); 724#endif /* INET6 */ 725#if MULTIPATH 726 attach_domain(&mpdomain_s); 727#endif /* MULTIPATH */ 728 attach_domain(&systemdomain_s); 729 attach_domain(&localdomain_s); 730#if IPSEC 731 attach_domain(&keydomain_s); 732#endif /* IPSEC */ 733 attach_domain(&ndrvdomain_s); 734 attach_domain(&routedomain_s); /* must be last domain */ 735 736 /* 737 * Now ask them all to init (XXX including the routing domain, 738 * see above) 739 */ 740 TAILQ_FOREACH(dp, &domains, dom_entry) 741 init_domain(dp); 742 743 domain_guard_release(guard); 744} 745 746static __inline__ struct domain * 747pffinddomain_locked(int pf) 748{ 749 struct domain *dp; 750 751 domain_proto_mtx_lock_assert_held(); 752 753 TAILQ_FOREACH(dp, &domains, dom_entry) { 754 if (dp->dom_family == pf) 755 break; 756 } 757 return (dp); 758} 759 760struct protosw * 761pffindtype(int family, int type) 762{ 763 struct protosw *pp = NULL; 764 struct domain *dp; 765 domain_guard_t guard; 766 767 guard = domain_guard_deploy(); 768 if ((dp = pffinddomain_locked(family)) == NULL) 769 goto done; 770 771 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 772 if (pp->pr_type != 0 && pp->pr_type == type) 773 goto done; 774 } 775done: 776 domain_guard_release(guard); 777 return (pp); 778} 779 780/* 781 * Internal routine, not exported. 782 */ 783struct domain * 784pffinddomain(int pf) 785{ 786 struct domain *dp; 787 domain_guard_t guard; 788 789 guard = domain_guard_deploy(); 790 dp = pffinddomain_locked(pf); 791 domain_guard_release(guard); 792 return (dp); 793} 794 795/* 796 * Exported (private) routine, indirection of pffinddomain. 797 */ 798struct domain_old * 799pffinddomain_old(int pf) 800{ 801 struct domain_old *odp = NULL; 802 struct domain *dp; 803 domain_guard_t guard; 804 805 guard = domain_guard_deploy(); 806 if ((dp = pffinddomain_locked(pf)) != NULL && (dp->dom_flags & DOM_OLD)) 807 odp = dp->dom_old; 808 domain_guard_release(guard); 809 return (odp); 810} 811 812/* 813 * Internal routine, not exported. 814 */ 815struct protosw * 816pffindproto(int family, int protocol, int type) 817{ 818 struct protosw *pp; 819 domain_guard_t guard; 820 821 guard = domain_guard_deploy(); 822 pp = pffindproto_locked(family, protocol, type); 823 domain_guard_release(guard); 824 return (pp); 825} 826 827struct protosw * 828pffindproto_locked(int family, int protocol, int type) 829{ 830 struct protosw *maybe = NULL; 831 struct protosw *pp; 832 struct domain *dp; 833 834 domain_proto_mtx_lock_assert_held(); 835 836 if (family == 0) 837 return (0); 838 839 dp = pffinddomain_locked(family); 840 if (dp == NULL) 841 return (NULL); 842 843 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 844 if ((pp->pr_protocol == protocol) && (pp->pr_type == type)) 845 return (pp); 846 847 if (type == SOCK_RAW && pp->pr_type == SOCK_RAW && 848 pp->pr_protocol == 0 && maybe == NULL) 849 maybe = pp; 850 } 851 return (maybe); 852} 853 854/* 855 * Exported (private) routine, indirection of pffindproto. 856 */ 857struct protosw_old * 858pffindproto_old(int family, int protocol, int type) 859{ 860 struct protosw_old *opr = NULL; 861 struct protosw *pp; 862 domain_guard_t guard; 863 864 guard = domain_guard_deploy(); 865 if ((pp = pffindproto_locked(family, protocol, type)) != NULL && 866 (pp->pr_flags & PR_OLD)) 867 opr = pp->pr_old; 868 domain_guard_release(guard); 869 return (opr); 870} 871 872static struct protosw * 873pffindprotonotype_locked(int family, int protocol, int type) 874{ 875#pragma unused(type) 876 struct domain *dp; 877 struct protosw *pp; 878 879 domain_proto_mtx_lock_assert_held(); 880 881 if (family == 0) 882 return (0); 883 884 dp = pffinddomain_locked(family); 885 if (dp == NULL) 886 return (NULL); 887 888 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 889 if (pp->pr_protocol == protocol) 890 return (pp); 891 } 892 return (NULL); 893} 894 895struct protosw * 896pffindprotonotype(int family, int protocol) 897{ 898 struct protosw *pp; 899 domain_guard_t guard; 900 901 if (protocol == 0) 902 return (NULL); 903 904 guard = domain_guard_deploy(); 905 pp = pffindprotonotype_locked(family, protocol, 0); 906 domain_guard_release(guard); 907 return (pp); 908} 909 910void 911pfctlinput(int cmd, struct sockaddr *sa) 912{ 913 pfctlinput2(cmd, sa, NULL); 914} 915 916void 917pfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam) 918{ 919 struct domain *dp; 920 struct protosw *pp; 921 domain_guard_t guard; 922 923 if (sa == NULL) 924 return; 925 926 guard = domain_guard_deploy(); 927 TAILQ_FOREACH(dp, &domains, dom_entry) { 928 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 929 if (pp->pr_ctlinput != NULL) 930 (*pp->pr_ctlinput)(cmd, sa, ctlparam); 931 } 932 } 933 domain_guard_release(guard); 934} 935 936void 937net_update_uptime(void) 938{ 939 struct timeval tv; 940 941 microuptime(&tv); 942 _net_uptime = tv.tv_sec; 943 /* 944 * Round up the timer to the nearest integer value because otherwise 945 * we might setup networking timers that are off by almost 1 second. 946 */ 947 if (tv.tv_usec > 500000) 948 _net_uptime++; 949} 950 951void 952net_update_uptime_secs(uint64_t secs) 953{ 954 _net_uptime = secs; 955} 956 957/* 958 * Convert our uin64_t net_uptime to a struct timeval. 959 */ 960void 961net_uptime2timeval(struct timeval *tv) 962{ 963 if (tv == NULL) 964 return; 965 966 tv->tv_usec = 0; 967 tv->tv_sec = net_uptime(); 968} 969 970/* 971 * An alternative way to obtain the coarse-grained uptime (in seconds) 972 * for networking code which do not require high-precision timestamp, 973 * as this is significantly cheaper than microuptime(). 974 */ 975u_int64_t 976net_uptime(void) 977{ 978 if (_net_uptime == 0) 979 net_update_uptime(); 980 981 return (_net_uptime); 982} 983 984void 985domain_proto_mtx_lock_assert_held(void) 986{ 987 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED); 988} 989 990void 991domain_proto_mtx_lock_assert_notheld(void) 992{ 993 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED); 994} 995 996domain_guard_t 997domain_guard_deploy(void) 998{ 999 net_thread_marks_t marks; 1000 1001 marks = net_thread_marks_push(NET_THREAD_HELD_DOMAIN); 1002 if (marks != net_thread_marks_none) { 1003 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED); 1004 lck_mtx_lock(&domain_proto_mtx); 1005 } 1006 else 1007 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED); 1008 1009 return ((domain_guard_t)(const void*)marks); 1010} 1011 1012void 1013domain_guard_release(domain_guard_t guard) 1014{ 1015 net_thread_marks_t marks = (net_thread_marks_t)(const void*)guard; 1016 1017 if (marks != net_thread_marks_none) { 1018 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED); 1019 lck_mtx_unlock(&domain_proto_mtx); 1020 net_thread_marks_pop(marks); 1021 } 1022 else 1023 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED); 1024} 1025 1026domain_unguard_t 1027domain_unguard_deploy(void) 1028{ 1029 net_thread_marks_t marks; 1030 1031 marks = net_thread_unmarks_push(NET_THREAD_HELD_DOMAIN); 1032 if (marks != net_thread_marks_none) { 1033 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED); 1034 lck_mtx_unlock(&domain_proto_mtx); 1035 } 1036 else 1037 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED); 1038 1039 return ((domain_unguard_t)(const void*)marks); 1040} 1041 1042void 1043domain_unguard_release(domain_unguard_t unguard) 1044{ 1045 net_thread_marks_t marks = (net_thread_marks_t)(const void*)unguard; 1046 1047 if (marks != net_thread_marks_none) { 1048 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED); 1049 lck_mtx_lock(&domain_proto_mtx); 1050 net_thread_unmarks_pop(marks); 1051 } 1052 else 1053 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED); 1054} 1055