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 105extern sysctlfn net_sysctl; 106 107static u_int64_t _net_uptime; 108 109static void 110pr_init_old(struct protosw *pp, struct domain *dp) 111{ 112#pragma unused(dp) 113 VERIFY(pp->pr_flags & PR_OLD); 114 VERIFY(pp->pr_old != NULL); 115 116 if (pp->pr_old->pr_init != NULL) 117 pp->pr_old->pr_init(); 118} 119 120static void 121init_proto(struct protosw *pp, struct domain *dp) 122{ 123 VERIFY(pp->pr_flags & PR_ATTACHED); 124 125 if (!(pp->pr_flags & PR_INITIALIZED)) { 126 TAILQ_INIT(&pp->pr_filter_head); 127 if (pp->pr_init != NULL) 128 pp->pr_init(pp, dp); 129 pp->pr_flags |= PR_INITIALIZED; 130 } 131} 132 133static void 134attach_proto(struct protosw *pp, struct domain *dp) 135{ 136 domain_proto_mtx_lock_assert_held(); 137 VERIFY(!(pp->pr_flags & PR_ATTACHED)); 138 VERIFY(pp->pr_domain == NULL); 139 VERIFY(pp->pr_protosw == NULL); 140 141 TAILQ_INSERT_TAIL(&dp->dom_protosw, pp, pr_entry); 142 pp->pr_flags |= PR_ATTACHED; 143 pp->pr_domain = dp; 144 pp->pr_protosw = pp; 145 146 /* do some cleaning up on user request callbacks */ 147 pru_sanitize(pp->pr_usrreqs); 148} 149 150static void 151detach_proto(struct protosw *pp, struct domain *dp) 152{ 153 domain_proto_mtx_lock_assert_held(); 154 VERIFY(pp->pr_flags & PR_ATTACHED); 155 VERIFY(pp->pr_domain == dp); 156 VERIFY(pp->pr_protosw == pp); 157 158 TAILQ_REMOVE(&dp->dom_protosw, pp, pr_entry); 159 pp->pr_flags &= ~PR_ATTACHED; 160 pp->pr_domain = NULL; 161 pp->pr_protosw = NULL; 162} 163 164static void 165dom_init_old(struct domain *dp) 166{ 167 VERIFY(dp->dom_flags & DOM_OLD); 168 VERIFY(dp->dom_old != NULL); 169 170 if (dp->dom_old->dom_init != NULL) 171 dp->dom_old->dom_init(); 172} 173 174static void 175init_domain(struct domain *dp) 176{ 177 VERIFY(dp->dom_flags & DOM_ATTACHED); 178 179 if (!(dp->dom_flags & DOM_INITIALIZED)) { 180 lck_mtx_init(&dp->dom_mtx_s, domain_proto_mtx_grp, 181 domain_proto_mtx_attr); 182 dp->dom_mtx = &dp->dom_mtx_s; 183 TAILQ_INIT(&dp->dom_protosw); 184 if (dp->dom_init != NULL) 185 dp->dom_init(dp); 186 dp->dom_flags |= DOM_INITIALIZED; 187 } 188 189 /* Recompute for new protocol */ 190 if (_max_linkhdr < 16) /* XXX - Sheesh; everything's ether? */ 191 _max_linkhdr = 16; 192 _max_linkhdr = max_linkhdr; /* round it up */ 193 194 if (dp->dom_protohdrlen > _max_protohdr) 195 _max_protohdr = dp->dom_protohdrlen; 196 _max_protohdr = max_protohdr; /* round it up */ 197 198 max_hdr = max_linkhdr + max_protohdr; 199 max_datalen = MHLEN - max_hdr; 200} 201 202static void 203attach_domain(struct domain *dp) 204{ 205 domain_proto_mtx_lock_assert_held(); 206 VERIFY(!(dp->dom_flags & DOM_ATTACHED)); 207 208 TAILQ_INSERT_TAIL(&domains, dp, dom_entry); 209 dp->dom_flags |= DOM_ATTACHED; 210} 211 212static void 213detach_domain(struct domain *dp) 214{ 215 domain_proto_mtx_lock_assert_held(); 216 VERIFY(dp->dom_flags & DOM_ATTACHED); 217 218 TAILQ_REMOVE(&domains, dp, dom_entry); 219 dp->dom_flags &= ~DOM_ATTACHED; 220 221 if (dp->dom_flags & DOM_OLD) { 222 struct domain_old *odp = dp->dom_old; 223 224 VERIFY(odp != NULL); 225 odp->dom_next = NULL; 226 odp->dom_mtx = NULL; 227 } 228} 229 230/* 231 * Exported (private) routine, indirection of net_add_domain. 232 */ 233void 234net_add_domain_old(struct domain_old *odp) 235{ 236 struct domain *dp; 237 domain_guard_t guard; 238 239 VERIFY(odp != NULL); 240 241 guard = domain_guard_deploy(); 242 if ((dp = pffinddomain_locked(odp->dom_family)) != NULL) { 243 /* 244 * There is really nothing better than to panic here, 245 * as the caller would not have been able to handle 246 * any failures otherwise. 247 */ 248 panic("%s: domain (%d,%s) already exists for %s\n", __func__, 249 dp->dom_family, dp->dom_name, odp->dom_name); 250 /* NOTREACHED */ 251 } 252 253 /* Make sure nothing is currently pointing to the odp. */ 254 TAILQ_FOREACH(dp, &domains, dom_entry) { 255 if (dp->dom_old == odp) { 256 panic("%s: domain %p (%d,%s) is already " 257 "associated with %p (%d,%s)\n", __func__, 258 odp, odp->dom_family, odp->dom_name, dp, 259 dp->dom_family, dp->dom_name); 260 /* NOTREACHED */ 261 } 262 } 263 264 if (odp->dom_protosw != NULL) { 265 panic("%s: domain (%d,%s) protocols need to added " 266 "via net_add_proto\n", __func__, odp->dom_family, 267 odp->dom_name); 268 /* NOTREACHED */ 269 } 270 271 dp = _MALLOC(sizeof (*dp), M_TEMP, M_WAITOK | M_ZERO); 272 if (dp == NULL) { 273 /* 274 * There is really nothing better than to panic here, 275 * as the caller would not have been able to handle 276 * any failures otherwise. 277 */ 278 panic("%s: unable to allocate memory for domain family " 279 "%d (%s)\n", __func__, odp->dom_family, odp->dom_name); 280 /* NOTREACHED */ 281 } 282 283 /* Copy everything but dom_init, dom_mtx, dom_next and dom_refs */ 284 dp->dom_family = odp->dom_family; 285 dp->dom_flags = (odp->dom_flags & DOMF_USERFLAGS) | DOM_OLD; 286 dp->dom_name = odp->dom_name; 287 dp->dom_init = dom_init_old; 288 dp->dom_externalize = odp->dom_externalize; 289 dp->dom_dispose = odp->dom_dispose; 290 dp->dom_rtattach = odp->dom_rtattach; 291 dp->dom_rtoffset = odp->dom_rtoffset; 292 dp->dom_maxrtkey = odp->dom_maxrtkey; 293 dp->dom_protohdrlen = odp->dom_protohdrlen; 294 dp->dom_old = odp; 295 296 attach_domain(dp); 297 init_domain(dp); 298 299 /* Point the mutex back to the internal structure's */ 300 odp->dom_mtx = dp->dom_mtx; 301 domain_guard_release(guard); 302} 303 304/* 305 * Exported (private) routine, indirection of net_del_domain. 306 */ 307int 308net_del_domain_old(struct domain_old *odp) 309{ 310 struct domain *dp1, *dp2; 311 int error = 0; 312 domain_guard_t guard; 313 314 VERIFY(odp != NULL); 315 316 guard = domain_guard_deploy(); 317 if (odp->dom_refs != 0) { 318 error = EBUSY; 319 goto done; 320 } 321 322 TAILQ_FOREACH_SAFE(dp1, &domains, dom_entry, dp2) { 323 if (!(dp1->dom_flags & DOM_OLD)) 324 continue; 325 VERIFY(dp1->dom_old != NULL); 326 if (odp == dp1->dom_old) 327 break; 328 } 329 if (dp1 != NULL) { 330 struct protosw *pp1, *pp2; 331 332 VERIFY(dp1->dom_flags & DOM_OLD); 333 VERIFY(dp1->dom_old == odp); 334 335 /* Remove all protocols attached to this domain */ 336 TAILQ_FOREACH_SAFE(pp1, &dp1->dom_protosw, pr_entry, pp2) { 337 detach_proto(pp1, dp1); 338 if (pp1->pr_usrreqs->pru_flags & PRUF_OLD) 339 FREE(pp1->pr_usrreqs, M_TEMP); 340 if (pp1->pr_flags & PR_OLD) 341 FREE(pp1, M_TEMP); 342 } 343 344 detach_domain(dp1); 345 FREE(dp1, M_TEMP); 346 } else { 347 error = EPFNOSUPPORT; 348 } 349done: 350 domain_guard_release(guard); 351 return (error); 352} 353 354/* 355 * Internal routine, not exported. 356 * 357 * net_add_proto - link a protosw into a domain's protosw chain 358 * 359 * NOTE: Caller must have acquired domain_proto_mtx 360 */ 361int 362net_add_proto(struct protosw *pp, struct domain *dp, int doinit) 363{ 364 struct protosw *pp1; 365 366 /* 367 * This could be called as part of initializing the domain, 368 * and thus DOM_INITIALIZED may not be set (yet). 369 */ 370 domain_proto_mtx_lock_assert_held(); 371 VERIFY(!(pp->pr_flags & PR_ATTACHED)); 372 373 /* pr_domain is set only after the protocol is attached */ 374 if (pp->pr_domain != NULL) { 375 panic("%s: domain (%d,%s), proto %d has non-NULL pr_domain!\n", 376 __func__, dp->dom_family, dp->dom_name, pp->pr_protocol); 377 /* NOTREACHED */ 378 } 379 380 if (pp->pr_usrreqs == NULL) { 381 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n", 382 __func__, dp->dom_family, dp->dom_name, pp->pr_protocol); 383 /* NOTREACHED */ 384 } 385 386 TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) { 387 if (pp1->pr_type == pp->pr_type && 388 pp1->pr_protocol == pp->pr_protocol) 389 return (EEXIST); 390 } 391 392 attach_proto(pp, dp); 393 if (doinit) 394 net_init_proto(pp, dp); 395 396 return (0); 397} 398 399void 400net_init_proto(struct protosw *pp, struct domain *dp) 401{ 402 /* 403 * This could be called as part of initializing the domain, 404 * and thus DOM_INITIALIZED may not be set (yet). The protocol 405 * must have been attached via net_addr_protosw() by now. 406 */ 407 domain_proto_mtx_lock_assert_held(); 408 VERIFY(pp->pr_flags & PR_ATTACHED); 409 410 init_proto(pp, dp); 411} 412 413/* 414 * Exported (private) routine, indirection of net_add_proto. 415 */ 416int 417net_add_proto_old(struct protosw_old *opp, struct domain_old *odp) 418{ 419 struct pr_usrreqs_old *opru; 420 struct pr_usrreqs *pru = NULL; 421 struct protosw *pp = NULL, *pp1; 422 int error = 0; 423 struct domain *dp; 424 domain_guard_t guard; 425 426 /* 427 * This could be called as part of initializing the domain, 428 * and thus DOM_INITIALIZED may not be set (yet). 429 */ 430 guard = domain_guard_deploy(); 431 432 /* Make sure the domain has been added via net_add_domain */ 433 TAILQ_FOREACH(dp, &domains, dom_entry) { 434 if (!(dp->dom_flags & DOM_OLD)) 435 continue; 436 if (dp->dom_old == odp) 437 break; 438 } 439 if (dp == NULL) { 440 error = EINVAL; 441 goto done; 442 } 443 444 TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) { 445 if (pp1->pr_type == opp->pr_type && 446 pp1->pr_protocol == opp->pr_protocol) { 447 error = EEXIST; 448 goto done; 449 } 450 } 451 452 if ((opru = opp->pr_usrreqs) == NULL) { 453 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n", 454 __func__, odp->dom_family, odp->dom_name, opp->pr_protocol); 455 /* NOTREACHED */ 456 } 457 458 pru = _MALLOC(sizeof (*pru), M_TEMP, M_WAITOK | M_ZERO); 459 if (pru == NULL) { 460 error = ENOMEM; 461 goto done; 462 } 463 464 pru->pru_flags = PRUF_OLD; 465 pru->pru_abort = opru->pru_abort; 466 pru->pru_accept = opru->pru_accept; 467 pru->pru_attach = opru->pru_attach; 468 pru->pru_bind = opru->pru_bind; 469 pru->pru_connect = opru->pru_connect; 470 pru->pru_connect2 = opru->pru_connect2; 471 pru->pru_control = opru->pru_control; 472 pru->pru_detach = opru->pru_detach; 473 pru->pru_disconnect = opru->pru_disconnect; 474 pru->pru_listen = opru->pru_listen; 475 pru->pru_peeraddr = opru->pru_peeraddr; 476 pru->pru_rcvd = opru->pru_rcvd; 477 pru->pru_rcvoob = opru->pru_rcvoob; 478 pru->pru_send = opru->pru_send; 479 pru->pru_sense = opru->pru_sense; 480 pru->pru_shutdown = opru->pru_shutdown; 481 pru->pru_sockaddr = opru->pru_sockaddr; 482 pru->pru_sosend = opru->pru_sosend; 483 pru->pru_soreceive = opru->pru_soreceive; 484 pru->pru_sopoll = opru->pru_sopoll; 485 486 pp = _MALLOC(sizeof (*pp), M_TEMP, M_WAITOK | M_ZERO); 487 if (pp == NULL) { 488 error = ENOMEM; 489 goto done; 490 } 491 492 /* 493 * Protocol fast and slow timers are now deprecated. 494 */ 495 if (opp->pr_unused != NULL) { 496 printf("%s: domain (%d,%s), proto %d: pr_fasttimo is " 497 "deprecated and won't be called\n", __func__, 498 odp->dom_family, odp->dom_name, opp->pr_protocol); 499 } 500 if (opp->pr_unused2 != NULL) { 501 printf("%s: domain (%d,%s), proto %d: pr_slowtimo is " 502 "deprecated and won't be called\n", __func__, 503 odp->dom_family, odp->dom_name, opp->pr_protocol); 504 } 505 506 /* Copy everything but pr_init, pr_next, pr_domain, pr_protosw */ 507 pp->pr_type = opp->pr_type; 508 pp->pr_protocol = opp->pr_protocol; 509 pp->pr_flags = (opp->pr_flags & PRF_USERFLAGS) | PR_OLD; 510 pp->pr_input = opp->pr_input; 511 pp->pr_output = opp->pr_output; 512 pp->pr_ctlinput = opp->pr_ctlinput; 513 pp->pr_ctloutput = opp->pr_ctloutput; 514 pp->pr_usrreqs = pru; 515 pp->pr_init = pr_init_old; 516 pp->pr_drain = opp->pr_drain; 517 pp->pr_sysctl = opp->pr_sysctl; 518 pp->pr_lock = opp->pr_lock; 519 pp->pr_unlock = opp->pr_unlock; 520 pp->pr_getlock = opp->pr_getlock; 521 pp->pr_old = opp; 522 523 /* attach as well as initialize */ 524 attach_proto(pp, dp); 525 net_init_proto(pp, dp); 526done: 527 if (error != 0) { 528 printf("%s: domain (%d,%s), proto %d: failed to attach, " 529 "error %d\n", __func__, odp->dom_family, 530 odp->dom_name, opp->pr_protocol, error); 531 532 if (pru != NULL) 533 FREE(pru, M_TEMP); 534 if (pp != NULL) 535 FREE(pp, M_TEMP); 536 } 537 538 domain_guard_release(guard); 539 return (error); 540} 541 542/* 543 * Internal routine, not exported. 544 * 545 * net_del_proto - remove a protosw from a domain's protosw chain. 546 * Search the protosw chain for the element with matching data. 547 * Then unlink and return. 548 * 549 * NOTE: Caller must have acquired domain_proto_mtx 550 */ 551int 552net_del_proto(int type, int protocol, struct domain *dp) 553{ 554 struct protosw *pp; 555 556 /* 557 * This could be called as part of initializing the domain, 558 * and thus DOM_INITIALIZED may not be set (yet). 559 */ 560 domain_proto_mtx_lock_assert_held(); 561 562 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 563 if (pp->pr_type == type && pp->pr_protocol == protocol) 564 break; 565 } 566 if (pp == NULL) 567 return (ENXIO); 568 569 detach_proto(pp, dp); 570 if (pp->pr_usrreqs->pru_flags & PRUF_OLD) 571 FREE(pp->pr_usrreqs, M_TEMP); 572 if (pp->pr_flags & PR_OLD) 573 FREE(pp, M_TEMP); 574 575 return (0); 576} 577 578/* 579 * Exported (private) routine, indirection of net_del_proto. 580 */ 581int 582net_del_proto_old(int type, int protocol, struct domain_old *odp) 583{ 584 int error = 0; 585 struct protosw *pp; 586 struct domain *dp; 587 domain_guard_t guard; 588 589 /* 590 * This could be called as part of initializing the domain, 591 * and thus DOM_INITIALIZED may not be set (yet). 592 */ 593 guard = domain_guard_deploy(); 594 595 /* Make sure the domain has been added via net_add_domain */ 596 TAILQ_FOREACH(dp, &domains, dom_entry) { 597 if (!(dp->dom_flags & DOM_OLD)) 598 continue; 599 if (dp->dom_old == odp) 600 break; 601 } 602 if (dp == NULL) { 603 error = ENXIO; 604 goto done; 605 } 606 607 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 608 if (pp->pr_type == type && pp->pr_protocol == protocol) 609 break; 610 } 611 if (pp == NULL) { 612 error = ENXIO; 613 goto done; 614 } 615 detach_proto(pp, dp); 616 if (pp->pr_usrreqs->pru_flags & PRUF_OLD) 617 FREE(pp->pr_usrreqs, M_TEMP); 618 if (pp->pr_flags & PR_OLD) 619 FREE(pp, M_TEMP); 620 621done: 622 domain_guard_release(guard); 623 return (error); 624} 625 626static void 627domain_sched_timeout(void) 628{ 629 lck_mtx_assert(&domain_timeout_mtx, LCK_MTX_ASSERT_OWNED); 630 631 if (!domain_timeout_run && domain_draining) { 632 domain_timeout_run = TRUE; 633 timeout(domain_timeout, NULL, hz); 634 } 635} 636 637void 638net_drain_domains(void) 639{ 640 lck_mtx_lock(&domain_timeout_mtx); 641 domain_draining = TRUE; 642 domain_sched_timeout(); 643 lck_mtx_unlock(&domain_timeout_mtx); 644} 645 646#if INET6 647extern struct domain inet6domain_s; 648#endif 649#if IPSEC 650extern struct domain keydomain_s; 651#endif 652 653extern struct domain routedomain_s, ndrvdomain_s, inetdomain_s; 654extern struct domain systemdomain_s, localdomain_s; 655 656#if MULTIPATH 657extern struct domain mpdomain_s; 658#endif /* MULTIPATH */ 659 660static void 661domain_timeout(void *arg) 662{ 663#pragma unused(arg) 664 struct protosw *pp; 665 struct domain *dp; 666 domain_guard_t guard; 667 668 lck_mtx_lock(&domain_timeout_mtx); 669 if (domain_draining) { 670 domain_draining = FALSE; 671 lck_mtx_unlock(&domain_timeout_mtx); 672 673 guard = domain_guard_deploy(); 674 TAILQ_FOREACH(dp, &domains, dom_entry) { 675 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 676 if (pp->pr_drain != NULL) 677 (*pp->pr_drain)(); 678 } 679 } 680 domain_guard_release(guard); 681 682 lck_mtx_lock(&domain_timeout_mtx); 683 } 684 685 /* re-arm the timer if there's work to do */ 686 domain_timeout_run = FALSE; 687 domain_sched_timeout(); 688 lck_mtx_unlock(&domain_timeout_mtx); 689} 690 691void 692domaininit(void) 693{ 694 struct domain *dp; 695 domain_guard_t guard; 696 697 /* 698 * allocate lock group attribute and group for domain mutexes 699 */ 700 domain_proto_mtx_grp_attr = lck_grp_attr_alloc_init(); 701 702 domain_proto_mtx_grp = lck_grp_alloc_init("domain", 703 domain_proto_mtx_grp_attr); 704 705 /* 706 * allocate the lock attribute for per domain mutexes 707 */ 708 domain_proto_mtx_attr = lck_attr_alloc_init(); 709 710 lck_mtx_init(&domain_proto_mtx, domain_proto_mtx_grp, 711 domain_proto_mtx_attr); 712 lck_mtx_init(&domain_timeout_mtx, domain_proto_mtx_grp, 713 domain_proto_mtx_attr); 714 715 guard = domain_guard_deploy(); 716 /* 717 * Add all the static domains to the domains list. route domain 718 * gets added and initialized last, since we need it to attach 719 * rt_tables[] to everything that's already there. This also 720 * means that domains added after this point won't get their 721 * dom_rtattach() called on rt_tables[]. 722 */ 723 attach_domain(&inetdomain_s); 724#if INET6 725 attach_domain(&inet6domain_s); 726#endif /* INET6 */ 727#if MULTIPATH 728 attach_domain(&mpdomain_s); 729#endif /* MULTIPATH */ 730 attach_domain(&systemdomain_s); 731 attach_domain(&localdomain_s); 732#if IPSEC 733 attach_domain(&keydomain_s); 734#endif /* IPSEC */ 735 attach_domain(&ndrvdomain_s); 736 attach_domain(&routedomain_s); /* must be last domain */ 737 738 /* 739 * Now ask them all to init (XXX including the routing domain, 740 * see above) 741 */ 742 TAILQ_FOREACH(dp, &domains, dom_entry) 743 init_domain(dp); 744 745 domain_guard_release(guard); 746} 747 748static __inline__ struct domain * 749pffinddomain_locked(int pf) 750{ 751 struct domain *dp; 752 753 domain_proto_mtx_lock_assert_held(); 754 755 TAILQ_FOREACH(dp, &domains, dom_entry) { 756 if (dp->dom_family == pf) 757 break; 758 } 759 return (dp); 760} 761 762struct protosw * 763pffindtype(int family, int type) 764{ 765 struct protosw *pp = NULL; 766 struct domain *dp; 767 domain_guard_t guard; 768 769 guard = domain_guard_deploy(); 770 if ((dp = pffinddomain_locked(family)) == NULL) 771 goto done; 772 773 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 774 if (pp->pr_type != 0 && pp->pr_type == type) 775 goto done; 776 } 777done: 778 domain_guard_release(guard); 779 return (pp); 780} 781 782/* 783 * Internal routine, not exported. 784 */ 785struct domain * 786pffinddomain(int pf) 787{ 788 struct domain *dp; 789 domain_guard_t guard; 790 791 guard = domain_guard_deploy(); 792 dp = pffinddomain_locked(pf); 793 domain_guard_release(guard); 794 return (dp); 795} 796 797/* 798 * Exported (private) routine, indirection of pffinddomain. 799 */ 800struct domain_old * 801pffinddomain_old(int pf) 802{ 803 struct domain_old *odp = NULL; 804 struct domain *dp; 805 domain_guard_t guard; 806 807 guard = domain_guard_deploy(); 808 if ((dp = pffinddomain_locked(pf)) != NULL && (dp->dom_flags & DOM_OLD)) 809 odp = dp->dom_old; 810 domain_guard_release(guard); 811 return (odp); 812} 813 814/* 815 * Internal routine, not exported. 816 */ 817struct protosw * 818pffindproto(int family, int protocol, int type) 819{ 820 struct protosw *pp; 821 domain_guard_t guard; 822 823 guard = domain_guard_deploy(); 824 pp = pffindproto_locked(family, protocol, type); 825 domain_guard_release(guard); 826 return (pp); 827} 828 829struct protosw * 830pffindproto_locked(int family, int protocol, int type) 831{ 832 struct protosw *maybe = NULL; 833 struct protosw *pp; 834 struct domain *dp; 835 836 domain_proto_mtx_lock_assert_held(); 837 838 if (family == 0) 839 return (0); 840 841 dp = pffinddomain_locked(family); 842 if (dp == NULL) 843 return (NULL); 844 845 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 846 if ((pp->pr_protocol == protocol) && (pp->pr_type == type)) 847 return (pp); 848 849 if (type == SOCK_RAW && pp->pr_type == SOCK_RAW && 850 pp->pr_protocol == 0 && maybe == NULL) 851 maybe = pp; 852 } 853 return (maybe); 854} 855 856/* 857 * Exported (private) routine, indirection of pffindproto. 858 */ 859struct protosw_old * 860pffindproto_old(int family, int protocol, int type) 861{ 862 struct protosw_old *opr = NULL; 863 struct protosw *pp; 864 domain_guard_t guard; 865 866 guard = domain_guard_deploy(); 867 if ((pp = pffindproto_locked(family, protocol, type)) != NULL && 868 (pp->pr_flags & PR_OLD)) 869 opr = pp->pr_old; 870 domain_guard_release(guard); 871 return (opr); 872} 873 874static struct protosw * 875pffindprotonotype_locked(int family, int protocol, int type) 876{ 877#pragma unused(type) 878 struct domain *dp; 879 struct protosw *pp; 880 881 domain_proto_mtx_lock_assert_held(); 882 883 if (family == 0) 884 return (0); 885 886 dp = pffinddomain_locked(family); 887 if (dp == NULL) 888 return (NULL); 889 890 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 891 if (pp->pr_protocol == protocol) 892 return (pp); 893 } 894 return (NULL); 895} 896 897struct protosw * 898pffindprotonotype(int family, int protocol) 899{ 900 struct protosw *pp; 901 domain_guard_t guard; 902 903 if (protocol == 0) 904 return (NULL); 905 906 guard = domain_guard_deploy(); 907 pp = pffindprotonotype_locked(family, protocol, 0); 908 domain_guard_release(guard); 909 return (pp); 910} 911 912int 913net_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp, 914 user_addr_t newp, size_t newlen, struct proc *p) 915{ 916#pragma unused(p) 917 int family, protocol, error = 0; 918 struct domain *dp; 919 struct protosw *pp; 920 domain_guard_t guard; 921 922 /* 923 * All sysctl names at this level are nonterminal; 924 * next two components are protocol family and protocol number, 925 * then at least one addition component. 926 */ 927 if (namelen < 3) 928 return (EISDIR); /* overloaded */ 929 family = name[0]; 930 protocol = name[1]; 931 932 if (family == 0) 933 return (0); 934 935 guard = domain_guard_deploy(); 936 TAILQ_FOREACH(dp, &domains, dom_entry) { 937 if (dp->dom_family == family) 938 break; 939 } 940 if (dp == NULL) { 941 error = ENOPROTOOPT; 942 goto done; 943 } 944 945 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 946 if (pp->pr_protocol == protocol && pp->pr_sysctl != NULL) { 947 error = (*pp->pr_sysctl)(name + 2, namelen - 2, 948 (void *)(uintptr_t)oldp, oldlenp, 949 (void *)(uintptr_t)newp, newlen); 950 goto done; 951 } 952 } 953 error = ENOPROTOOPT; 954done: 955 domain_guard_release(guard); 956 return (error); 957} 958 959void 960pfctlinput(int cmd, struct sockaddr *sa) 961{ 962 pfctlinput2(cmd, sa, NULL); 963} 964 965void 966pfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam) 967{ 968 struct domain *dp; 969 struct protosw *pp; 970 domain_guard_t guard; 971 972 if (sa == NULL) 973 return; 974 975 guard = domain_guard_deploy(); 976 TAILQ_FOREACH(dp, &domains, dom_entry) { 977 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) { 978 if (pp->pr_ctlinput != NULL) 979 (*pp->pr_ctlinput)(cmd, sa, ctlparam); 980 } 981 } 982 domain_guard_release(guard); 983} 984 985void 986net_update_uptime(void) 987{ 988 struct timeval tv; 989 990 microuptime(&tv); 991 _net_uptime = tv.tv_sec; 992 /* 993 * Round up the timer to the nearest integer value because otherwise 994 * we might setup networking timers that are off by almost 1 second. 995 */ 996 if (tv.tv_usec > 500000) 997 _net_uptime++; 998} 999 1000void 1001net_update_uptime_secs(uint64_t secs) 1002{ 1003 _net_uptime = secs; 1004} 1005 1006/* 1007 * Convert our uin64_t net_uptime to a struct timeval. 1008 */ 1009void 1010net_uptime2timeval(struct timeval *tv) 1011{ 1012 if (tv == NULL) 1013 return; 1014 1015 tv->tv_usec = 0; 1016 tv->tv_sec = net_uptime(); 1017} 1018 1019/* 1020 * An alternative way to obtain the coarse-grained uptime (in seconds) 1021 * for networking code which do not require high-precision timestamp, 1022 * as this is significantly cheaper than microuptime(). 1023 */ 1024u_int64_t 1025net_uptime(void) 1026{ 1027 if (_net_uptime == 0) 1028 net_update_uptime(); 1029 1030 return (_net_uptime); 1031} 1032 1033void 1034domain_proto_mtx_lock_assert_held(void) 1035{ 1036 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED); 1037} 1038 1039void 1040domain_proto_mtx_lock_assert_notheld(void) 1041{ 1042 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED); 1043} 1044 1045domain_guard_t 1046domain_guard_deploy(void) 1047{ 1048 net_thread_marks_t marks; 1049 1050 marks = net_thread_marks_push(NET_THREAD_HELD_DOMAIN); 1051 if (marks != net_thread_marks_none) { 1052 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED); 1053 lck_mtx_lock(&domain_proto_mtx); 1054 } 1055 else 1056 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED); 1057 1058 return ((domain_guard_t)(const void*)marks); 1059} 1060 1061void 1062domain_guard_release(domain_guard_t guard) 1063{ 1064 net_thread_marks_t marks = (net_thread_marks_t)(const void*)guard; 1065 1066 if (marks != net_thread_marks_none) { 1067 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED); 1068 lck_mtx_unlock(&domain_proto_mtx); 1069 net_thread_marks_pop(marks); 1070 } 1071 else 1072 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED); 1073} 1074 1075domain_unguard_t 1076domain_unguard_deploy(void) 1077{ 1078 net_thread_marks_t marks; 1079 1080 marks = net_thread_unmarks_push(NET_THREAD_HELD_DOMAIN); 1081 if (marks != net_thread_marks_none) { 1082 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED); 1083 lck_mtx_unlock(&domain_proto_mtx); 1084 } 1085 else 1086 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED); 1087 1088 return ((domain_unguard_t)(const void*)marks); 1089} 1090 1091void 1092domain_unguard_release(domain_unguard_t unguard) 1093{ 1094 net_thread_marks_t marks = (net_thread_marks_t)(const void*)unguard; 1095 1096 if (marks != net_thread_marks_none) { 1097 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED); 1098 lck_mtx_lock(&domain_proto_mtx); 1099 net_thread_unmarks_pop(marks); 1100 } 1101 else 1102 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED); 1103} 1104