1/* 2 * Copyright (c) 2008-2011 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 29 30 31/* ---------------------------------------------------------------------------------- 32Application of kernel control for interface creation 33 34Theory of operation: 35utun (user tunnel) acts as glue between kernel control sockets and network interfaces. 36This kernel control will register an interface for every client that connects. 37---------------------------------------------------------------------------------- */ 38 39#include <sys/systm.h> 40#include <sys/kern_control.h> 41#include <net/kpi_protocol.h> 42#include <net/kpi_interface.h> 43#include <sys/socket.h> 44#include <net/if.h> 45#include <net/if_types.h> 46#include <net/bpf.h> 47#include <net/if_utun.h> 48#include <libkern/OSMalloc.h> 49#include <libkern/OSAtomic.h> 50#include <sys/mbuf.h> 51#include <sys/sockio.h> 52#include <netinet/in.h> 53#include <netinet6/in6_var.h> 54#include <netinet6/in6_var.h> 55#include <sys/kauth.h> 56 57 58/* Kernel Control functions */ 59static errno_t utun_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, 60 void **unitinfo); 61static errno_t utun_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, 62 void *unitinfo); 63static errno_t utun_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, 64 void *unitinfo, mbuf_t m, int flags); 65static errno_t utun_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, 66 int opt, void *data, size_t *len); 67static errno_t utun_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, 68 int opt, void *data, size_t len); 69 70/* Network Interface functions */ 71static errno_t utun_output(ifnet_t interface, mbuf_t data); 72static errno_t utun_demux(ifnet_t interface, mbuf_t data, char *frame_header, 73 protocol_family_t *protocol); 74static errno_t utun_framer(ifnet_t interface, mbuf_t *packet, 75 const struct sockaddr *dest, const char *desk_linkaddr, 76 const char *frame_type 77#if KPI_INTERFACE_EMBEDDED 78 , 79 u_int32_t *prepend_len, u_int32_t *postpend_len 80#endif /* KPI_INTERFACE_EMBEDDED */ 81 ); 82static errno_t utun_add_proto(ifnet_t interface, protocol_family_t protocol, 83 const struct ifnet_demux_desc *demux_array, 84 u_int32_t demux_count); 85static errno_t utun_del_proto(ifnet_t interface, protocol_family_t protocol); 86static errno_t utun_ioctl(ifnet_t interface, u_long cmd, void *data); 87static void utun_detached(ifnet_t interface); 88 89/* Protocol handlers */ 90static errno_t utun_attach_proto(ifnet_t interface, protocol_family_t proto); 91static errno_t utun_proto_input(ifnet_t interface, protocol_family_t protocol, 92 mbuf_t m, char *frame_header); 93static errno_t utun_proto_pre_output(ifnet_t interface, protocol_family_t protocol, 94 mbuf_t *packet, const struct sockaddr *dest, void *route, 95 char *frame_type, char *link_layer_dest); 96__private_extern__ errno_t utun_pkt_input (struct utun_pcb *pcb, mbuf_t m); 97 98static kern_ctl_ref utun_kctlref; 99static u_int32_t utun_family; 100static OSMallocTag utun_malloc_tag; 101static SInt32 utun_ifcount = 0; 102 103/* Prepend length */ 104void* 105utun_alloc(size_t size) 106{ 107 size_t *mem = OSMalloc(size + sizeof(size_t), utun_malloc_tag); 108 109 if (mem) { 110 *mem = size + sizeof(size_t); 111 mem++; 112 } 113 114 return (void*)mem; 115} 116 117void 118utun_free(void *ptr) 119{ 120 size_t *size = ptr; 121 size--; 122 OSFree(size, *size, utun_malloc_tag); 123} 124 125errno_t 126utun_register_control(void) 127{ 128 struct kern_ctl_reg kern_ctl; 129 errno_t result = 0; 130 131 /* Create a tag to allocate memory */ 132 utun_malloc_tag = OSMalloc_Tagalloc(UTUN_CONTROL_NAME, OSMT_DEFAULT); 133 134 /* Find a unique value for our interface family */ 135 result = mbuf_tag_id_find(UTUN_CONTROL_NAME, &utun_family); 136 if (result != 0) { 137 printf("utun_register_control - mbuf_tag_id_find_internal failed: %d\n", result); 138 return result; 139 } 140 141 bzero(&kern_ctl, sizeof(kern_ctl)); 142 strncpy(kern_ctl.ctl_name, UTUN_CONTROL_NAME, sizeof(kern_ctl.ctl_name)); 143 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0; 144 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED; /* Require root */ 145 kern_ctl.ctl_sendsize = 64 * 1024; 146 kern_ctl.ctl_recvsize = 64 * 1024; 147 kern_ctl.ctl_connect = utun_ctl_connect; 148 kern_ctl.ctl_disconnect = utun_ctl_disconnect; 149 kern_ctl.ctl_send = utun_ctl_send; 150 kern_ctl.ctl_setopt = utun_ctl_setopt; 151 kern_ctl.ctl_getopt = utun_ctl_getopt; 152 153 result = ctl_register(&kern_ctl, &utun_kctlref); 154 if (result != 0) { 155 printf("utun_register_control - ctl_register failed: %d\n", result); 156 return result; 157 } 158 159 /* Register the protocol plumbers */ 160 if ((result = proto_register_plumber(PF_INET, utun_family, 161 utun_attach_proto, NULL)) != 0) { 162 printf("utun_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n", 163 utun_family, result); 164 ctl_deregister(utun_kctlref); 165 return result; 166 } 167 168 /* Register the protocol plumbers */ 169 if ((result = proto_register_plumber(PF_INET6, utun_family, 170 utun_attach_proto, NULL)) != 0) { 171 proto_unregister_plumber(PF_INET, utun_family); 172 ctl_deregister(utun_kctlref); 173 printf("utun_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n", 174 utun_family, result); 175 return result; 176 } 177 178 return 0; 179} 180 181/* Kernel control functions */ 182 183static errno_t 184utun_ctl_connect( 185 kern_ctl_ref kctlref, 186 struct sockaddr_ctl *sac, 187 void **unitinfo) 188{ 189 struct ifnet_init_params utun_init; 190 struct utun_pcb *pcb; 191 errno_t result; 192 struct ifnet_stats_param stats; 193 194 /* kernel control allocates, interface frees */ 195 pcb = utun_alloc(sizeof(*pcb)); 196 if (pcb == NULL) 197 return ENOMEM; 198 199 /* Setup the protocol control block */ 200 bzero(pcb, sizeof(*pcb)); 201 *unitinfo = pcb; 202 pcb->utun_ctlref = kctlref; 203 pcb->utun_unit = sac->sc_unit; 204 205 printf("utun_ctl_connect: creating interface utun%d\n", pcb->utun_unit - 1); 206 207 /* Create the interface */ 208 bzero(&utun_init, sizeof(utun_init)); 209 utun_init.name = "utun"; 210 utun_init.unit = pcb->utun_unit - 1; 211 utun_init.family = utun_family; 212 utun_init.type = IFT_OTHER; 213 utun_init.output = utun_output; 214 utun_init.demux = utun_demux; 215 utun_init.framer = utun_framer; 216 utun_init.add_proto = utun_add_proto; 217 utun_init.del_proto = utun_del_proto; 218 utun_init.softc = pcb; 219 utun_init.ioctl = utun_ioctl; 220 utun_init.detach = utun_detached; 221 222 result = ifnet_allocate(&utun_init, &pcb->utun_ifp); 223 if (result != 0) { 224 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result); 225 utun_free(pcb); 226 return result; 227 } 228 OSIncrementAtomic(&utun_ifcount); 229 230 /* Set flags and additional information. */ 231 ifnet_set_mtu(pcb->utun_ifp, 1500); 232 ifnet_set_flags(pcb->utun_ifp, IFF_UP | IFF_MULTICAST | IFF_POINTOPOINT, 0xffff); 233 234 /* The interface must generate its own IPv6 LinkLocal address, 235 * if possible following the recommendation of RFC2472 to the 64bit interface ID 236 */ 237 ifnet_set_eflags(pcb->utun_ifp, IFEF_NOAUTOIPV6LL, IFEF_NOAUTOIPV6LL); 238 239 /* Reset the stats in case as the interface may have been recycled */ 240 bzero(&stats, sizeof(struct ifnet_stats_param)); 241 ifnet_set_stat(pcb->utun_ifp, &stats); 242 243 /* Attach the interface */ 244 result = ifnet_attach(pcb->utun_ifp, NULL); 245 if (result != 0) { 246 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result); 247 ifnet_release(pcb->utun_ifp); 248 utun_free(pcb); 249 } 250 251 /* Attach to bpf */ 252 if (result == 0) 253 bpfattach(pcb->utun_ifp, DLT_NULL, 4); 254 255 /* The interfaces resoures allocated, mark it as running */ 256 if (result == 0) 257 ifnet_set_flags(pcb->utun_ifp, IFF_RUNNING, IFF_RUNNING); 258 259 return result; 260} 261 262static errno_t 263utun_detach_ip( 264 ifnet_t interface, 265 protocol_family_t protocol, 266 socket_t pf_socket) 267{ 268 errno_t result = EPROTONOSUPPORT; 269 270 /* Attempt a detach */ 271 if (protocol == PF_INET) { 272 struct ifreq ifr; 273 274 bzero(&ifr, sizeof(ifr)); 275 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", 276 ifnet_name(interface), ifnet_unit(interface)); 277 278 result = sock_ioctl(pf_socket, SIOCPROTODETACH, &ifr); 279 } 280 else if (protocol == PF_INET6) { 281 struct in6_ifreq ifr6; 282 283 bzero(&ifr6, sizeof(ifr6)); 284 snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d", 285 ifnet_name(interface), ifnet_unit(interface)); 286 287 result = sock_ioctl(pf_socket, SIOCPROTODETACH_IN6, &ifr6); 288 } 289 290 return result; 291} 292 293static void 294utun_remove_address( 295 ifnet_t interface, 296 protocol_family_t protocol, 297 ifaddr_t address, 298 socket_t pf_socket) 299{ 300 errno_t result = 0; 301 302 /* Attempt a detach */ 303 if (protocol == PF_INET) { 304 struct ifreq ifr; 305 306 bzero(&ifr, sizeof(ifr)); 307 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", 308 ifnet_name(interface), ifnet_unit(interface)); 309 result = ifaddr_address(address, &ifr.ifr_addr, sizeof(ifr.ifr_addr)); 310 if (result != 0) { 311 printf("utun_remove_address - ifaddr_address failed: %d", result); 312 } 313 else { 314 result = sock_ioctl(pf_socket, SIOCDIFADDR, &ifr); 315 if (result != 0) { 316 printf("utun_remove_address - SIOCDIFADDR failed: %d", result); 317 } 318 } 319 } 320 else if (protocol == PF_INET6) { 321 struct in6_ifreq ifr6; 322 323 bzero(&ifr6, sizeof(ifr6)); 324 snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d", 325 ifnet_name(interface), ifnet_unit(interface)); 326 result = ifaddr_address(address, (struct sockaddr*)&ifr6.ifr_addr, 327 sizeof(ifr6.ifr_addr)); 328 if (result != 0) { 329 printf("utun_remove_address - ifaddr_address failed (v6): %d", 330 result); 331 } 332 else { 333 result = sock_ioctl(pf_socket, SIOCDIFADDR_IN6, &ifr6); 334 if (result != 0) { 335 printf("utun_remove_address - SIOCDIFADDR_IN6 failed: %d", 336 result); 337 } 338 } 339 } 340} 341 342static void 343utun_cleanup_family( 344 ifnet_t interface, 345 protocol_family_t protocol) 346{ 347 errno_t result = 0; 348 socket_t pf_socket = NULL; 349 ifaddr_t *addresses = NULL; 350 int i; 351 352 if (protocol != PF_INET && protocol != PF_INET6) { 353 printf("utun_cleanup_family - invalid protocol family %d\n", protocol); 354 return; 355 } 356 357 /* Create a socket for removing addresses and detaching the protocol */ 358 result = sock_socket(protocol, SOCK_DGRAM, 0, NULL, NULL, &pf_socket); 359 if (result != 0) { 360 if (result != EAFNOSUPPORT) 361 printf("utun_cleanup_family - failed to create %s socket: %d\n", 362 protocol == PF_INET ? "IP" : "IPv6", result); 363 goto cleanup; 364 } 365 366 /* always set SS_PRIV, we want to close and detach regardless */ 367 sock_setpriv(pf_socket, 1); 368 369 result = utun_detach_ip(interface, protocol, pf_socket); 370 if (result == 0 || result == ENXIO) { 371 /* We are done! We either detached or weren't attached. */ 372 goto cleanup; 373 } 374 else if (result != EBUSY) { 375 /* Uh, not really sure what happened here... */ 376 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result); 377 goto cleanup; 378 } 379 380 /* 381 * At this point, we received an EBUSY error. This means there are 382 * addresses attached. We should detach them and then try again. 383 */ 384 result = ifnet_get_address_list_family(interface, &addresses, protocol); 385 if (result != 0) { 386 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n", 387 ifnet_name(interface), ifnet_unit(interface), 388 protocol == PF_INET ? "PF_INET" : "PF_INET6", result); 389 goto cleanup; 390 } 391 392 for (i = 0; addresses[i] != 0; i++) { 393 utun_remove_address(interface, protocol, addresses[i], pf_socket); 394 } 395 ifnet_free_address_list(addresses); 396 addresses = NULL; 397 398 /* 399 * The addresses should be gone, we should try the remove again. 400 */ 401 result = utun_detach_ip(interface, protocol, pf_socket); 402 if (result != 0 && result != ENXIO) { 403 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result); 404 } 405 406cleanup: 407 if (pf_socket != NULL) 408 sock_close(pf_socket); 409 410 if (addresses != NULL) 411 ifnet_free_address_list(addresses); 412} 413 414static errno_t 415utun_ctl_disconnect( 416 __unused kern_ctl_ref kctlref, 417 __unused u_int32_t unit, 418 void *unitinfo) 419{ 420 struct utun_pcb *pcb = unitinfo; 421 ifnet_t ifp = pcb->utun_ifp; 422 errno_t result = 0; 423 424 utun_cleanup_crypto(pcb); 425 426 pcb->utun_ctlref = NULL; 427 pcb->utun_unit = 0; 428 429 /* 430 * We want to do everything in our power to ensure that the interface 431 * really goes away when the socket is closed. We must remove IP/IPv6 432 * addresses and detach the protocols. Finally, we can remove and 433 * release the interface. 434 */ 435 utun_cleanup_family(ifp, AF_INET); 436 utun_cleanup_family(ifp, AF_INET6); 437 438 if ((result = ifnet_detach(ifp)) != 0) { 439 printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result); 440 } 441 442 if ((result = ifnet_release(ifp)) != 0) { 443 printf("utun_ctl_disconnect - ifnet_release failed: %d\n", result); 444 } 445 446 return 0; 447} 448 449static errno_t 450utun_ctl_send( 451 __unused kern_ctl_ref kctlref, 452 __unused u_int32_t unit, 453 void *unitinfo, 454 mbuf_t m, 455 __unused int flags) 456{ 457 return utun_pkt_input((struct utun_pcb *)unitinfo, m); 458} 459 460static errno_t 461utun_ctl_setopt( 462 __unused kern_ctl_ref kctlref, 463 __unused u_int32_t unit, 464 void *unitinfo, 465 int opt, 466 void *data, 467 size_t len) 468{ 469 struct utun_pcb *pcb = unitinfo; 470 errno_t result = 0; 471 472 /* check for privileges for privileged options */ 473 switch (opt) { 474 case UTUN_OPT_FLAGS: 475 case UTUN_OPT_EXT_IFDATA_STATS: 476 if (kauth_cred_issuser(kauth_cred_get()) == 0) { 477 return EPERM; 478 } 479 break; 480 } 481 482 switch (opt) { 483 case UTUN_OPT_FLAGS: 484 if (len != sizeof(u_int32_t)) 485 result = EMSGSIZE; 486 else 487 pcb->utun_flags = *(u_int32_t *)data; 488 break; 489 490 case UTUN_OPT_ENABLE_CRYPTO: 491 result = utun_ctl_enable_crypto(kctlref, unit, unitinfo, opt, data, len); 492 break; 493 494 case UTUN_OPT_CONFIG_CRYPTO_KEYS: 495 result = utun_ctl_config_crypto_keys(kctlref, unit, unitinfo, opt, data, len); 496 break; 497 498 case UTUN_OPT_UNCONFIG_CRYPTO_KEYS: 499 result = utun_ctl_unconfig_crypto_keys(kctlref, unit, unitinfo, opt, data, len); 500 break; 501 502 case UTUN_OPT_DISABLE_CRYPTO: 503 result = utun_ctl_disable_crypto(kctlref, unit, unitinfo, opt, data, len); 504 break; 505 506 case UTUN_OPT_STOP_CRYPTO_DATA_TRAFFIC: 507 result = utun_ctl_stop_crypto_data_traffic(kctlref, unit, unitinfo, opt, data, len); 508 break; 509 510 case UTUN_OPT_START_CRYPTO_DATA_TRAFFIC: 511 result = utun_ctl_start_crypto_data_traffic(kctlref, unit, unitinfo, opt, data, len); 512 break; 513 514 case UTUN_OPT_EXT_IFDATA_STATS: 515 if (len != sizeof(int)) { 516 result = EMSGSIZE; 517 break; 518 } 519 pcb->utun_ext_ifdata_stats = (*(int *)data) ? 1 : 0; 520 break; 521 522 case UTUN_OPT_INC_IFDATA_STATS_IN: 523 case UTUN_OPT_INC_IFDATA_STATS_OUT: { 524 struct utun_stats_param *utsp = (struct utun_stats_param *)data; 525 526 if (utsp == NULL || len < sizeof(struct utun_stats_param)) { 527 result = EINVAL; 528 break; 529 } 530 if (!pcb->utun_ext_ifdata_stats) { 531 result = EINVAL; 532 break; 533 } 534 if (opt == UTUN_OPT_INC_IFDATA_STATS_IN) 535 ifnet_stat_increment_in(pcb->utun_ifp, utsp->utsp_packets, 536 utsp->utsp_bytes, utsp->utsp_errors); 537 else 538 ifnet_stat_increment_out(pcb->utun_ifp, utsp->utsp_packets, 539 utsp->utsp_bytes, utsp->utsp_errors); 540 break; 541 } 542 543 default: 544 result = ENOPROTOOPT; 545 break; 546 } 547 548 return result; 549} 550 551static errno_t 552utun_ctl_getopt( 553 __unused kern_ctl_ref kctlref, 554 __unused u_int32_t unit, 555 void *unitinfo, 556 int opt, 557 void *data, 558 size_t *len) 559{ 560 struct utun_pcb *pcb = unitinfo; 561 errno_t result = 0; 562 563 switch (opt) { 564 case UTUN_OPT_FLAGS: 565 if (*len != sizeof(u_int32_t)) 566 result = EMSGSIZE; 567 else 568 *(u_int32_t *)data = pcb->utun_flags; 569 break; 570 571 case UTUN_OPT_EXT_IFDATA_STATS: 572 if (*len != sizeof(int)) 573 result = EMSGSIZE; 574 else 575 *(int *)data = (pcb->utun_ext_ifdata_stats) ? 1 : 0; 576 break; 577 578 case UTUN_OPT_IFNAME: 579 *len = snprintf(data, *len, "%s%d", ifnet_name(pcb->utun_ifp), ifnet_unit(pcb->utun_ifp)) + 1; 580 break; 581 582 case UTUN_OPT_GENERATE_CRYPTO_KEYS_IDX: 583 result = utun_ctl_generate_crypto_keys_idx(kctlref, unit, unitinfo, opt, data, len); 584 break; 585 586 default: 587 result = ENOPROTOOPT; 588 break; 589 } 590 591 return result; 592} 593 594/* Network Interface functions */ 595static errno_t 596utun_output( 597 ifnet_t interface, 598 mbuf_t data) 599{ 600 struct utun_pcb *pcb = ifnet_softc(interface); 601 errno_t result; 602 603 bpf_tap_out(pcb->utun_ifp, DLT_NULL, data, 0, 0); 604 605 if (pcb->utun_flags & UTUN_FLAGS_NO_OUTPUT) { 606 /* flush data */ 607 mbuf_freem(data); 608 return 0; 609 } 610 611 // otherwise, fall thru to ctl_enqueumbuf 612 if (pcb->utun_ctlref) { 613 int length; 614 615 // only pass packets to utun-crypto if crypto is enabled and 'suspend data traffic' is not. 616 if ((pcb->utun_flags & (UTUN_FLAGS_CRYPTO | UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC)) == UTUN_FLAGS_CRYPTO) { 617 if (utun_pkt_crypto_output(pcb, &data) == 0) { 618 return 0; 619 } 620 } 621 622 length = mbuf_pkthdr_len(data); 623 result = ctl_enqueuembuf(pcb->utun_ctlref, pcb->utun_unit, data, CTL_DATA_EOR); 624 if (result != 0) { 625 mbuf_freem(data); 626 printf("utun_output - ctl_enqueuembuf failed: %d\n", result); 627 628 ifnet_stat_increment_out(interface, 0, 0, 1); 629 } 630 else { 631 if (!pcb->utun_ext_ifdata_stats) 632 ifnet_stat_increment_out(interface, 1, length, 0); 633 } 634 } 635 else 636 mbuf_freem(data); 637 638 return 0; 639} 640 641/* Network Interface functions */ 642static errno_t 643utun_demux( 644 __unused ifnet_t interface, 645 mbuf_t data, 646 __unused char *frame_header, 647 protocol_family_t *protocol) 648{ 649 650 while (data != NULL && mbuf_len(data) < 1) { 651 data = mbuf_next(data); 652 } 653 654 if (data == NULL) 655 return ENOENT; 656 657 *protocol = ntohl(*(u_int32_t *)mbuf_data(data)); 658 return 0; 659} 660 661static errno_t 662utun_framer( 663 __unused ifnet_t interface, 664 mbuf_t *packet, 665 __unused const struct sockaddr *dest, 666 __unused const char *desk_linkaddr, 667 const char *frame_type 668#if KPI_INTERFACE_EMBEDDED 669 , 670 u_int32_t *prepend_len, 671 u_int32_t *postpend_len 672#endif /* KPI_INTERFACE_EMBEDDED */ 673 ) 674{ 675 if (mbuf_prepend(packet, sizeof(protocol_family_t), MBUF_DONTWAIT) != 0) { 676 printf("utun_framer - ifnet_output prepend failed\n"); 677 678 ifnet_stat_increment_out(interface, 0, 0, 1); 679 680 // just return, because the buffer was freed in mbuf_prepend 681 return EJUSTRETURN; 682 } 683#if KPI_INTERFACE_EMBEDDED 684 *prepend_len = sizeof(protocol_family_t); 685 *postpend_len = 0; 686#endif /* KPI_INTERFACE_EMBEDDED */ 687 688 // place protocol number at the beginning of the mbuf 689 *(protocol_family_t *)mbuf_data(*packet) = htonl(*(protocol_family_t *)(uintptr_t)(size_t)frame_type); 690 691 return 0; 692} 693 694static errno_t 695utun_add_proto( 696 __unused ifnet_t interface, 697 protocol_family_t protocol, 698 __unused const struct ifnet_demux_desc *demux_array, 699 __unused u_int32_t demux_count) 700{ 701 switch(protocol) { 702 case PF_INET: 703 return 0; 704 case PF_INET6: 705 return 0; 706 default: 707 break; 708 } 709 710 return ENOPROTOOPT; 711} 712 713static errno_t 714utun_del_proto( 715 __unused ifnet_t interface, 716 __unused protocol_family_t protocol) 717{ 718 return 0; 719} 720 721static errno_t 722utun_ioctl( 723 ifnet_t interface, 724 u_long command, 725 void *data) 726{ 727 errno_t result = 0; 728 729 switch(command) { 730 case SIOCSIFMTU: 731 ifnet_set_mtu(interface, ((struct ifreq*)data)->ifr_mtu); 732 break; 733 734 case SIOCSIFFLAGS: 735 /* ifioctl() takes care of it */ 736 break; 737 738 default: 739 result = EOPNOTSUPP; 740 } 741 742 return result; 743} 744 745static void 746utun_detached( 747 ifnet_t interface) 748{ 749 struct utun_pcb *pcb = ifnet_softc(interface); 750 751 utun_free(pcb); 752 753 OSDecrementAtomic(&utun_ifcount); 754} 755 756/* Protocol Handlers */ 757 758static errno_t 759utun_proto_input( 760 __unused ifnet_t interface, 761 protocol_family_t protocol, 762 mbuf_t m, 763 __unused char *frame_header) 764{ 765 766 // remove protocol family first 767 mbuf_adj(m, sizeof(u_int32_t)); 768 769 if (proto_input(protocol, m) != 0) 770 m_freem(m); 771 772 return 0; 773} 774 775static errno_t 776utun_proto_pre_output( 777 __unused ifnet_t interface, 778 protocol_family_t protocol, 779 __unused mbuf_t *packet, 780 __unused const struct sockaddr *dest, 781 __unused void *route, 782 __unused char *frame_type, 783 __unused char *link_layer_dest) 784{ 785 786 *(protocol_family_t *)(void *)frame_type = protocol; 787 return 0; 788} 789 790static errno_t 791utun_attach_proto( 792 ifnet_t interface, 793 protocol_family_t protocol) 794{ 795 struct ifnet_attach_proto_param proto; 796 errno_t result; 797 798 bzero(&proto, sizeof(proto)); 799 proto.input = utun_proto_input; 800 proto.pre_output = utun_proto_pre_output; 801 802 result = ifnet_attach_protocol(interface, protocol, &proto); 803 if (result != 0 && result != EEXIST) { 804 printf("utun_attach_inet - ifnet_attach_protocol %d failed: %d\n", 805 protocol, result); 806 } 807 808 return result; 809} 810 811errno_t 812utun_pkt_input (struct utun_pcb *pcb, mbuf_t m) 813{ 814 errno_t result; 815 protocol_family_t protocol; 816 817 mbuf_pkthdr_setrcvif(m, pcb->utun_ifp); 818 819 bpf_tap_in(pcb->utun_ifp, DLT_NULL, m, 0, 0); 820 821 if (pcb->utun_flags & UTUN_FLAGS_NO_INPUT) { 822 /* flush data */ 823 mbuf_freem(m); 824 return 0; 825 } 826 protocol = ntohl(*(u_int32_t *)mbuf_data(m)); 827 828 // quick exit for keepalive packets 829 if (protocol == AF_UTUN && pcb->utun_flags & UTUN_FLAGS_CRYPTO) { 830 if (utun_pkt_crypto_output(pcb, &m) == 0) { 831 return 0; 832 } 833 printf("%s: utun_pkt_crypto_output failed, flags %x\n", __FUNCTION__, pcb->utun_flags); 834 return EINVAL; 835 } 836 837 if (!pcb->utun_ext_ifdata_stats) { 838 struct ifnet_stat_increment_param incs; 839 840 bzero(&incs, sizeof(incs)); 841 incs.packets_in = 1; 842 incs.bytes_in = mbuf_pkthdr_len(m); 843 result = ifnet_input(pcb->utun_ifp, m, &incs); 844 } else { 845 result = ifnet_input(pcb->utun_ifp, m, NULL); 846 } 847 if (result != 0) { 848 ifnet_stat_increment_in(pcb->utun_ifp, 0, 0, 1); 849 850 printf("%s - ifnet_input failed: %d\n", __FUNCTION__, result); 851 mbuf_freem(m); 852 } 853 854 return 0; 855} 856