1/* 2 * Copyright (c) 2012-2014 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#include <sys/systm.h> 30#include <sys/kern_control.h> 31#include <net/kpi_protocol.h> 32#include <net/kpi_interface.h> 33#include <sys/socket.h> 34#include <sys/socketvar.h> 35#include <net/if.h> 36#include <net/if_types.h> 37#include <net/bpf.h> 38#include <net/if_ipsec.h> 39#include <libkern/OSMalloc.h> 40#include <libkern/OSAtomic.h> 41#include <sys/mbuf.h> 42#include <sys/sockio.h> 43#include <netinet/in.h> 44#include <netinet/ip6.h> 45#include <netinet6/in6_var.h> 46#include <netinet6/ip6_var.h> 47#include <sys/kauth.h> 48#include <netinet6/ipsec.h> 49#include <netinet6/ipsec6.h> 50#include <netinet/ip.h> 51#include <net/flowadv.h> 52#include <net/necp.h> 53 54/* Kernel Control functions */ 55static errno_t ipsec_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, 56 void **unitinfo); 57static errno_t ipsec_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, 58 void *unitinfo); 59static errno_t ipsec_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, 60 void *unitinfo, mbuf_t m, int flags); 61static errno_t ipsec_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, 62 int opt, void *data, size_t *len); 63static errno_t ipsec_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, 64 int opt, void *data, size_t len); 65 66/* Network Interface functions */ 67static void ipsec_start(ifnet_t interface); 68static errno_t ipsec_output(ifnet_t interface, mbuf_t data); 69static errno_t ipsec_demux(ifnet_t interface, mbuf_t data, char *frame_header, 70 protocol_family_t *protocol); 71static errno_t ipsec_add_proto(ifnet_t interface, protocol_family_t protocol, 72 const struct ifnet_demux_desc *demux_array, 73 u_int32_t demux_count); 74static errno_t ipsec_del_proto(ifnet_t interface, protocol_family_t protocol); 75static errno_t ipsec_ioctl(ifnet_t interface, u_long cmd, void *data); 76static void ipsec_detached(ifnet_t interface); 77 78/* Protocol handlers */ 79static errno_t ipsec_attach_proto(ifnet_t interface, protocol_family_t proto); 80static errno_t ipsec_proto_input(ifnet_t interface, protocol_family_t protocol, 81 mbuf_t m, char *frame_header); 82static errno_t ipsec_proto_pre_output(ifnet_t interface, protocol_family_t protocol, 83 mbuf_t *packet, const struct sockaddr *dest, void *route, 84 char *frame_type, char *link_layer_dest); 85 86static kern_ctl_ref ipsec_kctlref; 87static u_int32_t ipsec_family; 88static OSMallocTag ipsec_malloc_tag; 89static SInt32 ipsec_ifcount = 0; 90 91#define IPSECQ_MAXLEN 256 92 93/* Prepend length */ 94static void* 95ipsec_alloc(size_t size) 96{ 97 size_t *mem = OSMalloc(size + sizeof(size_t), ipsec_malloc_tag); 98 99 if (mem) { 100 *mem = size + sizeof(size_t); 101 mem++; 102 } 103 104 return (void*)mem; 105} 106 107static void 108ipsec_free(void *ptr) 109{ 110 size_t *size = ptr; 111 size--; 112 OSFree(size, *size, ipsec_malloc_tag); 113} 114 115errno_t 116ipsec_register_control(void) 117{ 118 struct kern_ctl_reg kern_ctl; 119 errno_t result = 0; 120 121 /* Create a tag to allocate memory */ 122 ipsec_malloc_tag = OSMalloc_Tagalloc(IPSEC_CONTROL_NAME, OSMT_DEFAULT); 123 124 /* Find a unique value for our interface family */ 125 result = mbuf_tag_id_find(IPSEC_CONTROL_NAME, &ipsec_family); 126 if (result != 0) { 127 printf("ipsec_register_control - mbuf_tag_id_find_internal failed: %d\n", result); 128 return result; 129 } 130 131 bzero(&kern_ctl, sizeof(kern_ctl)); 132 strlcpy(kern_ctl.ctl_name, IPSEC_CONTROL_NAME, sizeof(kern_ctl.ctl_name)); 133 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0; 134 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED; /* Require root */ 135 kern_ctl.ctl_sendsize = 64 * 1024; 136 kern_ctl.ctl_recvsize = 64 * 1024; 137 kern_ctl.ctl_connect = ipsec_ctl_connect; 138 kern_ctl.ctl_disconnect = ipsec_ctl_disconnect; 139 kern_ctl.ctl_send = ipsec_ctl_send; 140 kern_ctl.ctl_setopt = ipsec_ctl_setopt; 141 kern_ctl.ctl_getopt = ipsec_ctl_getopt; 142 143 result = ctl_register(&kern_ctl, &ipsec_kctlref); 144 if (result != 0) { 145 printf("ipsec_register_control - ctl_register failed: %d\n", result); 146 return result; 147 } 148 149 /* Register the protocol plumbers */ 150 if ((result = proto_register_plumber(PF_INET, ipsec_family, 151 ipsec_attach_proto, NULL)) != 0) { 152 printf("ipsec_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n", 153 ipsec_family, result); 154 ctl_deregister(ipsec_kctlref); 155 return result; 156 } 157 158 /* Register the protocol plumbers */ 159 if ((result = proto_register_plumber(PF_INET6, ipsec_family, 160 ipsec_attach_proto, NULL)) != 0) { 161 proto_unregister_plumber(PF_INET, ipsec_family); 162 ctl_deregister(ipsec_kctlref); 163 printf("ipsec_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n", 164 ipsec_family, result); 165 return result; 166 } 167 168 return 0; 169} 170 171/* Helpers */ 172int 173ipsec_interface_isvalid (ifnet_t interface) 174{ 175 struct ipsec_pcb *pcb = NULL; 176 177 if (interface == NULL) 178 return 0; 179 180 pcb = ifnet_softc(interface); 181 182 if (pcb == NULL) 183 return 0; 184 185 /* When ctl disconnects, ipsec_unit is set to 0 */ 186 if (pcb->ipsec_unit == 0) 187 return 0; 188 189 return 1; 190} 191 192/* Kernel control functions */ 193 194static errno_t 195ipsec_ctl_connect(kern_ctl_ref kctlref, 196 struct sockaddr_ctl *sac, 197 void **unitinfo) 198{ 199 struct ifnet_init_eparams ipsec_init; 200 struct ipsec_pcb *pcb; 201 errno_t result; 202 struct ifnet_stats_param stats; 203 204 /* kernel control allocates, interface frees */ 205 pcb = ipsec_alloc(sizeof(*pcb)); 206 if (pcb == NULL) 207 return ENOMEM; 208 209 /* Setup the protocol control block */ 210 bzero(pcb, sizeof(*pcb)); 211 *unitinfo = pcb; 212 pcb->ipsec_ctlref = kctlref; 213 pcb->ipsec_unit = sac->sc_unit; 214 pcb->ipsec_output_service_class = MBUF_SC_OAM; 215 216 printf("ipsec_ctl_connect: creating interface ipsec%d\n", pcb->ipsec_unit - 1); 217 218 /* Create the interface */ 219 bzero(&ipsec_init, sizeof(ipsec_init)); 220 ipsec_init.ver = IFNET_INIT_CURRENT_VERSION; 221 ipsec_init.len = sizeof (ipsec_init); 222 ipsec_init.name = "ipsec"; 223 ipsec_init.start = ipsec_start; 224 ipsec_init.unit = pcb->ipsec_unit - 1; 225 ipsec_init.family = ipsec_family; 226 ipsec_init.type = IFT_OTHER; 227 ipsec_init.demux = ipsec_demux; 228 ipsec_init.add_proto = ipsec_add_proto; 229 ipsec_init.del_proto = ipsec_del_proto; 230 ipsec_init.softc = pcb; 231 ipsec_init.ioctl = ipsec_ioctl; 232 ipsec_init.detach = ipsec_detached; 233 234 result = ifnet_allocate_extended(&ipsec_init, &pcb->ipsec_ifp); 235 if (result != 0) { 236 printf("ipsec_ctl_connect - ifnet_allocate failed: %d\n", result); 237 ipsec_free(pcb); 238 return result; 239 } 240 OSIncrementAtomic(&ipsec_ifcount); 241 242 /* Set flags and additional information. */ 243 ifnet_set_mtu(pcb->ipsec_ifp, 1500); 244 ifnet_set_flags(pcb->ipsec_ifp, IFF_UP | IFF_MULTICAST | IFF_POINTOPOINT, 0xffff); 245 246 /* The interface must generate its own IPv6 LinkLocal address, 247 * if possible following the recommendation of RFC2472 to the 64bit interface ID 248 */ 249 ifnet_set_eflags(pcb->ipsec_ifp, IFEF_NOAUTOIPV6LL, IFEF_NOAUTOIPV6LL); 250 251 /* Reset the stats in case as the interface may have been recycled */ 252 bzero(&stats, sizeof(struct ifnet_stats_param)); 253 ifnet_set_stat(pcb->ipsec_ifp, &stats); 254 255 /* Attach the interface */ 256 result = ifnet_attach(pcb->ipsec_ifp, NULL); 257 if (result != 0) { 258 printf("ipsec_ctl_connect - ifnet_allocate failed: %d\n", result); 259 ifnet_release(pcb->ipsec_ifp); 260 ipsec_free(pcb); 261 } 262 263 /* Attach to bpf */ 264 if (result == 0) 265 bpfattach(pcb->ipsec_ifp, DLT_NULL, 4); 266 267 /* The interfaces resoures allocated, mark it as running */ 268 if (result == 0) 269 ifnet_set_flags(pcb->ipsec_ifp, IFF_RUNNING, IFF_RUNNING); 270 271 return result; 272} 273 274static errno_t 275ipsec_detach_ip(ifnet_t interface, 276 protocol_family_t protocol, 277 socket_t pf_socket) 278{ 279 errno_t result = EPROTONOSUPPORT; 280 281 /* Attempt a detach */ 282 if (protocol == PF_INET) { 283 struct ifreq ifr; 284 285 bzero(&ifr, sizeof(ifr)); 286 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", 287 ifnet_name(interface), ifnet_unit(interface)); 288 289 result = sock_ioctl(pf_socket, SIOCPROTODETACH, &ifr); 290 } 291 else if (protocol == PF_INET6) { 292 struct in6_ifreq ifr6; 293 294 bzero(&ifr6, sizeof(ifr6)); 295 snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d", 296 ifnet_name(interface), ifnet_unit(interface)); 297 298 result = sock_ioctl(pf_socket, SIOCPROTODETACH_IN6, &ifr6); 299 } 300 301 return result; 302} 303 304static void 305ipsec_remove_address(ifnet_t interface, 306 protocol_family_t protocol, 307 ifaddr_t address, 308 socket_t pf_socket) 309{ 310 errno_t result = 0; 311 312 /* Attempt a detach */ 313 if (protocol == PF_INET) { 314 struct ifreq ifr; 315 316 bzero(&ifr, sizeof(ifr)); 317 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", 318 ifnet_name(interface), ifnet_unit(interface)); 319 result = ifaddr_address(address, &ifr.ifr_addr, sizeof(ifr.ifr_addr)); 320 if (result != 0) { 321 printf("ipsec_remove_address - ifaddr_address failed: %d", result); 322 } 323 else { 324 result = sock_ioctl(pf_socket, SIOCDIFADDR, &ifr); 325 if (result != 0) { 326 printf("ipsec_remove_address - SIOCDIFADDR failed: %d", result); 327 } 328 } 329 } 330 else if (protocol == PF_INET6) { 331 struct in6_ifreq ifr6; 332 333 bzero(&ifr6, sizeof(ifr6)); 334 snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d", 335 ifnet_name(interface), ifnet_unit(interface)); 336 result = ifaddr_address(address, (struct sockaddr*)&ifr6.ifr_addr, 337 sizeof(ifr6.ifr_addr)); 338 if (result != 0) { 339 printf("ipsec_remove_address - ifaddr_address failed (v6): %d", 340 result); 341 } 342 else { 343 result = sock_ioctl(pf_socket, SIOCDIFADDR_IN6, &ifr6); 344 if (result != 0) { 345 printf("ipsec_remove_address - SIOCDIFADDR_IN6 failed: %d", 346 result); 347 } 348 } 349 } 350} 351 352static void 353ipsec_cleanup_family(ifnet_t interface, 354 protocol_family_t protocol) 355{ 356 errno_t result = 0; 357 socket_t pf_socket = NULL; 358 ifaddr_t *addresses = NULL; 359 int i; 360 361 if (protocol != PF_INET && protocol != PF_INET6) { 362 printf("ipsec_cleanup_family - invalid protocol family %d\n", protocol); 363 return; 364 } 365 366 /* Create a socket for removing addresses and detaching the protocol */ 367 result = sock_socket(protocol, SOCK_DGRAM, 0, NULL, NULL, &pf_socket); 368 if (result != 0) { 369 if (result != EAFNOSUPPORT) 370 printf("ipsec_cleanup_family - failed to create %s socket: %d\n", 371 protocol == PF_INET ? "IP" : "IPv6", result); 372 goto cleanup; 373 } 374 375 /* always set SS_PRIV, we want to close and detach regardless */ 376 sock_setpriv(pf_socket, 1); 377 378 result = ipsec_detach_ip(interface, protocol, pf_socket); 379 if (result == 0 || result == ENXIO) { 380 /* We are done! We either detached or weren't attached. */ 381 goto cleanup; 382 } 383 else if (result != EBUSY) { 384 /* Uh, not really sure what happened here... */ 385 printf("ipsec_cleanup_family - ipsec_detach_ip failed: %d\n", result); 386 goto cleanup; 387 } 388 389 /* 390 * At this point, we received an EBUSY error. This means there are 391 * addresses attached. We should detach them and then try again. 392 */ 393 result = ifnet_get_address_list_family(interface, &addresses, protocol); 394 if (result != 0) { 395 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n", 396 ifnet_name(interface), ifnet_unit(interface), 397 protocol == PF_INET ? "PF_INET" : "PF_INET6", result); 398 goto cleanup; 399 } 400 401 for (i = 0; addresses[i] != 0; i++) { 402 ipsec_remove_address(interface, protocol, addresses[i], pf_socket); 403 } 404 ifnet_free_address_list(addresses); 405 addresses = NULL; 406 407 /* 408 * The addresses should be gone, we should try the remove again. 409 */ 410 result = ipsec_detach_ip(interface, protocol, pf_socket); 411 if (result != 0 && result != ENXIO) { 412 printf("ipsec_cleanup_family - ipsec_detach_ip failed: %d\n", result); 413 } 414 415cleanup: 416 if (pf_socket != NULL) 417 sock_close(pf_socket); 418 419 if (addresses != NULL) 420 ifnet_free_address_list(addresses); 421} 422 423static errno_t 424ipsec_ctl_disconnect(__unused kern_ctl_ref kctlref, 425 __unused u_int32_t unit, 426 void *unitinfo) 427{ 428 struct ipsec_pcb *pcb = unitinfo; 429 ifnet_t ifp = pcb->ipsec_ifp; 430 errno_t result = 0; 431 432 pcb->ipsec_ctlref = NULL; 433 pcb->ipsec_unit = 0; 434 435 /* 436 * We want to do everything in our power to ensure that the interface 437 * really goes away when the socket is closed. We must remove IP/IPv6 438 * addresses and detach the protocols. Finally, we can remove and 439 * release the interface. 440 */ 441 key_delsp_for_ipsec_if(ifp); 442 443 ipsec_cleanup_family(ifp, AF_INET); 444 ipsec_cleanup_family(ifp, AF_INET6); 445 446 if ((result = ifnet_detach(ifp)) != 0) { 447 printf("ipsec_ctl_disconnect - ifnet_detach failed: %d\n", result); 448 } 449 450 return 0; 451} 452 453static errno_t 454ipsec_ctl_send(__unused kern_ctl_ref kctlref, 455 __unused u_int32_t unit, 456 __unused void *unitinfo, 457 mbuf_t m, 458 __unused int flags) 459{ 460 /* Receive messages from the control socket. Currently unused. */ 461 mbuf_freem(m); 462 return 0; 463} 464 465static errno_t 466ipsec_ctl_setopt(__unused kern_ctl_ref kctlref, 467 __unused u_int32_t unit, 468 void *unitinfo, 469 int opt, 470 void *data, 471 size_t len) 472{ 473 struct ipsec_pcb *pcb = unitinfo; 474 errno_t result = 0; 475 476 /* check for privileges for privileged options */ 477 switch (opt) { 478 case IPSEC_OPT_FLAGS: 479 case IPSEC_OPT_EXT_IFDATA_STATS: 480 case IPSEC_OPT_SET_DELEGATE_INTERFACE: 481 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS: 482 if (kauth_cred_issuser(kauth_cred_get()) == 0) { 483 return EPERM; 484 } 485 break; 486 } 487 488 switch (opt) { 489 case IPSEC_OPT_FLAGS: 490 if (len != sizeof(u_int32_t)) 491 result = EMSGSIZE; 492 else 493 pcb->ipsec_flags = *(u_int32_t *)data; 494 break; 495 496 case IPSEC_OPT_EXT_IFDATA_STATS: 497 if (len != sizeof(int)) { 498 result = EMSGSIZE; 499 break; 500 } 501 pcb->ipsec_ext_ifdata_stats = (*(int *)data) ? 1 : 0; 502 break; 503 504 case IPSEC_OPT_INC_IFDATA_STATS_IN: 505 case IPSEC_OPT_INC_IFDATA_STATS_OUT: { 506 struct ipsec_stats_param *utsp = (struct ipsec_stats_param *)data; 507 508 if (utsp == NULL || len < sizeof(struct ipsec_stats_param)) { 509 result = EINVAL; 510 break; 511 } 512 if (!pcb->ipsec_ext_ifdata_stats) { 513 result = EINVAL; 514 break; 515 } 516 if (opt == IPSEC_OPT_INC_IFDATA_STATS_IN) 517 ifnet_stat_increment_in(pcb->ipsec_ifp, utsp->utsp_packets, 518 utsp->utsp_bytes, utsp->utsp_errors); 519 else 520 ifnet_stat_increment_out(pcb->ipsec_ifp, utsp->utsp_packets, 521 utsp->utsp_bytes, utsp->utsp_errors); 522 break; 523 } 524 525 case IPSEC_OPT_SET_DELEGATE_INTERFACE: { 526 ifnet_t del_ifp = NULL; 527 char name[IFNAMSIZ]; 528 529 if (len > IFNAMSIZ - 1) { 530 result = EMSGSIZE; 531 break; 532 } 533 if (len != 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */ 534 bcopy(data, name, len); 535 name[len] = 0; 536 result = ifnet_find_by_name(name, &del_ifp); 537 } 538 if (result == 0) { 539 result = ifnet_set_delegate(pcb->ipsec_ifp, del_ifp); 540 if (del_ifp) 541 ifnet_release(del_ifp); 542 } 543 break; 544 } 545 546 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS: { 547 if (len != sizeof(int)) { 548 result = EMSGSIZE; 549 break; 550 } 551 mbuf_svc_class_t output_service_class = so_tc2msc(*(int *)data); 552 if (output_service_class == MBUF_SC_UNSPEC) { 553 pcb->ipsec_output_service_class = MBUF_SC_OAM; 554 } else { 555 pcb->ipsec_output_service_class = output_service_class; 556 } 557 break; 558 } 559 560 default: 561 result = ENOPROTOOPT; 562 break; 563 } 564 565 return result; 566} 567 568static errno_t 569ipsec_ctl_getopt(__unused kern_ctl_ref kctlref, 570 __unused u_int32_t unit, 571 void *unitinfo, 572 int opt, 573 void *data, 574 size_t *len) 575{ 576 struct ipsec_pcb *pcb = unitinfo; 577 errno_t result = 0; 578 579 switch (opt) { 580 case IPSEC_OPT_FLAGS: 581 if (*len != sizeof(u_int32_t)) 582 result = EMSGSIZE; 583 else 584 *(u_int32_t *)data = pcb->ipsec_flags; 585 break; 586 587 case IPSEC_OPT_EXT_IFDATA_STATS: 588 if (*len != sizeof(int)) 589 result = EMSGSIZE; 590 else 591 *(int *)data = (pcb->ipsec_ext_ifdata_stats) ? 1 : 0; 592 break; 593 594 case IPSEC_OPT_IFNAME: 595 *len = snprintf(data, *len, "%s%d", ifnet_name(pcb->ipsec_ifp), ifnet_unit(pcb->ipsec_ifp)) + 1; 596 break; 597 598 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS: { 599 if (*len != sizeof(int)) { 600 result = EMSGSIZE; 601 break; 602 } 603 *(int *)data = so_svc2tc(pcb->ipsec_output_service_class); 604 break; 605 } 606 default: 607 result = ENOPROTOOPT; 608 break; 609 } 610 611 return result; 612} 613 614/* Network Interface functions */ 615static errno_t 616ipsec_output(ifnet_t interface, 617 mbuf_t data) 618{ 619 struct ipsec_pcb *pcb = ifnet_softc(interface); 620 struct ipsec_output_state ipsec_state; 621 struct route ro; 622 struct route_in6 ro6; 623 int length; 624 struct ip *ip; 625 struct ip6_hdr *ip6; 626 struct ip_out_args ipoa; 627 struct ip6_out_args ip6oa; 628 int error = 0; 629 u_int ip_version = 0; 630 uint32_t af; 631 int flags = 0; 632 struct flowadv *adv = NULL; 633 634 // Make sure this packet isn't looping through the interface 635 if (necp_get_last_interface_index_from_packet(data) == interface->if_index) { 636 error = -1; 637 goto ipsec_output_err; 638 } 639 640 // Mark the interface so NECP can evaluate tunnel policy 641 necp_mark_packet_from_interface(data, interface); 642 643 ip = mtod(data, struct ip *); 644 ip_version = ip->ip_v; 645 646 switch (ip_version) { 647 case 4: 648 /* Tap */ 649 af = AF_INET; 650 bpf_tap_out(pcb->ipsec_ifp, DLT_NULL, data, &af, sizeof(af)); 651 652 /* Apply encryption */ 653 bzero(&ipsec_state, sizeof(ipsec_state)); 654 ipsec_state.m = data; 655 ipsec_state.dst = (struct sockaddr *)&ip->ip_dst; 656 bzero(&ipsec_state.ro, sizeof(ipsec_state.ro)); 657 658 error = ipsec4_interface_output(&ipsec_state, interface); 659 data = ipsec_state.m; 660 if (error || data == NULL) { 661 printf("ipsec_output: ipsec4_output error %d.\n", error); 662 goto ipsec_output_err; 663 } 664 665 /* Set traffic class, set flow */ 666 m_set_service_class(data, pcb->ipsec_output_service_class); 667 data->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET; 668 data->m_pkthdr.pkt_flowid = interface->if_flowhash; 669 data->m_pkthdr.pkt_proto = ip->ip_p; 670 data->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC); 671 672 /* Flip endian-ness for ip_output */ 673 ip = mtod(data, struct ip *); 674 NTOHS(ip->ip_len); 675 NTOHS(ip->ip_off); 676 677 /* Increment statistics */ 678 length = mbuf_pkthdr_len(data); 679 ifnet_stat_increment_out(interface, 1, length, 0); 680 681 /* Send to ip_output */ 682 bzero(&ro, sizeof(ro)); 683 684 flags = IP_OUTARGS | /* Passing out args to specify interface */ 685 IP_NOIPSEC; /* To ensure the packet doesn't go through ipsec twice */ 686 687 bzero(&ipoa, sizeof(ipoa)); 688 ipoa.ipoa_flowadv.code = 0; 689 ipoa.ipoa_flags = IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR; 690 if (ipsec_state.outgoing_if) { 691 ipoa.ipoa_boundif = ipsec_state.outgoing_if; 692 ipoa.ipoa_flags |= IPOAF_BOUND_IF; 693 } 694 695 adv = &ipoa.ipoa_flowadv; 696 697 (void) ip_output(data, NULL, &ro, flags, NULL, &ipoa); 698 data = NULL; 699 700 if (adv->code == FADV_FLOW_CONTROLLED || adv->code == FADV_SUSPENDED) { 701 error = ENOBUFS; 702 ifnet_disable_output(interface); 703 } 704 705 goto done; 706 case 6: 707 af = AF_INET6; 708 bpf_tap_out(pcb->ipsec_ifp, DLT_NULL, data, &af, sizeof(af)); 709 710 data = ipsec6_splithdr(data); 711 ip6 = mtod(data, struct ip6_hdr *); 712 713 bzero(&ipsec_state, sizeof(ipsec_state)); 714 ipsec_state.m = data; 715 ipsec_state.dst = (struct sockaddr *)&ip6->ip6_dst; 716 bzero(&ipsec_state.ro, sizeof(ipsec_state.ro)); 717 718 error = ipsec6_interface_output(&ipsec_state, interface, &ip6->ip6_nxt, ipsec_state.m); 719 if (error == 0 && ipsec_state.tunneled == 4) /* tunneled in IPv4 - packet is gone */ 720 goto done; 721 data = ipsec_state.m; 722 if (error || data == NULL) { 723 printf("ipsec_output: ipsec6_output error %d.\n", error); 724 goto ipsec_output_err; 725 } 726 727 /* Set traffic class, set flow */ 728 m_set_service_class(data, pcb->ipsec_output_service_class); 729 data->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET; 730 data->m_pkthdr.pkt_flowid = interface->if_flowhash; 731 data->m_pkthdr.pkt_proto = ip6->ip6_nxt; 732 data->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC); 733 734 /* Increment statistics */ 735 length = mbuf_pkthdr_len(data); 736 ifnet_stat_increment_out(interface, 1, length, 0); 737 738 /* Send to ip6_output */ 739 bzero(&ro6, sizeof(ro6)); 740 741 flags = IPV6_OUTARGS; 742 743 bzero(&ip6oa, sizeof(ip6oa)); 744 ip6oa.ip6oa_flowadv.code = 0; 745 ip6oa.ip6oa_flags = IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR; 746 if (ipsec_state.outgoing_if) { 747 ip6oa.ip6oa_boundif = ipsec_state.outgoing_if; 748 ip6oa.ip6oa_flags |= IPOAF_BOUND_IF; 749 } 750 751 adv = &ip6oa.ip6oa_flowadv; 752 753 (void) ip6_output(data, NULL, &ro6, flags, NULL, NULL, &ip6oa); 754 data = NULL; 755 756 if (adv->code == FADV_FLOW_CONTROLLED || adv->code == FADV_SUSPENDED) { 757 error = ENOBUFS; 758 ifnet_disable_output(interface); 759 } 760 761 goto done; 762 default: 763 printf("ipsec_output: Received unknown packet version %d.\n", ip_version); 764 error = -1; 765 goto ipsec_output_err; 766 } 767 768done: 769 return error; 770 771ipsec_output_err: 772 if (data) 773 mbuf_freem(data); 774 goto done; 775} 776 777static void 778ipsec_start(ifnet_t interface) 779{ 780 mbuf_t data; 781 782 for (;;) { 783 if (ifnet_dequeue(interface, &data) != 0) 784 break; 785 if (ipsec_output(interface, data) != 0) 786 break; 787 } 788} 789 790/* Network Interface functions */ 791static errno_t 792ipsec_demux(__unused ifnet_t interface, 793 mbuf_t data, 794 __unused char *frame_header, 795 protocol_family_t *protocol) 796{ 797 struct ip *ip; 798 u_int ip_version; 799 800 while (data != NULL && mbuf_len(data) < 1) { 801 data = mbuf_next(data); 802 } 803 804 if (data == NULL) 805 return ENOENT; 806 807 ip = mtod(data, struct ip *); 808 ip_version = ip->ip_v; 809 810 switch(ip_version) { 811 case 4: 812 *protocol = PF_INET; 813 return 0; 814 case 6: 815 *protocol = PF_INET6; 816 return 0; 817 default: 818 break; 819 } 820 821 return 0; 822} 823 824static errno_t 825ipsec_add_proto(__unused ifnet_t interface, 826 protocol_family_t protocol, 827 __unused const struct ifnet_demux_desc *demux_array, 828 __unused u_int32_t demux_count) 829{ 830 switch(protocol) { 831 case PF_INET: 832 return 0; 833 case PF_INET6: 834 return 0; 835 default: 836 break; 837 } 838 839 return ENOPROTOOPT; 840} 841 842static errno_t 843ipsec_del_proto(__unused ifnet_t interface, 844 __unused protocol_family_t protocol) 845{ 846 return 0; 847} 848 849static errno_t 850ipsec_ioctl(ifnet_t interface, 851 u_long command, 852 void *data) 853{ 854 errno_t result = 0; 855 856 switch(command) { 857 case SIOCSIFMTU: 858 ifnet_set_mtu(interface, ((struct ifreq*)data)->ifr_mtu); 859 break; 860 861 case SIOCSIFFLAGS: 862 /* ifioctl() takes care of it */ 863 break; 864 865 default: 866 result = EOPNOTSUPP; 867 } 868 869 return result; 870} 871 872static void 873ipsec_detached( 874 ifnet_t interface) 875{ 876 struct ipsec_pcb *pcb = ifnet_softc(interface); 877 878 ifnet_release(pcb->ipsec_ifp); 879 ipsec_free(pcb); 880 881 OSDecrementAtomic(&ipsec_ifcount); 882} 883 884/* Protocol Handlers */ 885 886static errno_t 887ipsec_proto_input(ifnet_t interface, 888 protocol_family_t protocol, 889 mbuf_t m, 890 __unused char *frame_header) 891{ 892 struct ip *ip; 893 uint32_t af = 0; 894 ip = mtod(m, struct ip *); 895 if (ip->ip_v == 4) 896 af = AF_INET; 897 else if (ip->ip_v == 6) 898 af = AF_INET6; 899 900 mbuf_pkthdr_setrcvif(m, interface); 901 bpf_tap_in(interface, DLT_NULL, m, &af, sizeof(af)); 902 903 if (proto_input(protocol, m) != 0) 904 m_freem(m); 905 906 return 0; 907} 908 909static errno_t 910ipsec_proto_pre_output(__unused ifnet_t interface, 911 protocol_family_t protocol, 912 __unused mbuf_t *packet, 913 __unused const struct sockaddr *dest, 914 __unused void *route, 915 __unused char *frame_type, 916 __unused char *link_layer_dest) 917{ 918 919 *(protocol_family_t *)(void *)frame_type = protocol; 920 return 0; 921} 922 923static errno_t 924ipsec_attach_proto(ifnet_t interface, 925 protocol_family_t protocol) 926{ 927 struct ifnet_attach_proto_param proto; 928 errno_t result; 929 930 bzero(&proto, sizeof(proto)); 931 proto.input = ipsec_proto_input; 932 proto.pre_output = ipsec_proto_pre_output; 933 934 result = ifnet_attach_protocol(interface, protocol, &proto); 935 if (result != 0 && result != EEXIST) { 936 printf("ipsec_attach_inet - ifnet_attach_protocol %d failed: %d\n", 937 protocol, result); 938 } 939 940 return result; 941} 942 943errno_t 944ipsec_inject_inbound_packet(ifnet_t interface, 945 mbuf_t packet) 946{ 947 errno_t error; 948 protocol_family_t protocol; 949 if ((error = ipsec_demux(interface, packet, NULL, &protocol)) != 0) { 950 return error; 951 } 952 953 return ipsec_proto_input(interface, protocol, packet, NULL); 954} 955 956void 957ipsec_set_pkthdr_for_interface(ifnet_t interface, mbuf_t packet, int family) 958{ 959 if (packet != NULL && interface != NULL) { 960 struct ipsec_pcb *pcb = ifnet_softc(interface); 961 if (pcb != NULL) { 962 /* Set traffic class, set flow */ 963 m_set_service_class(packet, pcb->ipsec_output_service_class); 964 packet->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET; 965 packet->m_pkthdr.pkt_flowid = interface->if_flowhash; 966 if (family == AF_INET) { 967 struct ip *ip = mtod(packet, struct ip *); 968 packet->m_pkthdr.pkt_proto = ip->ip_p; 969 } else if (family == AF_INET) { 970 struct ip6_hdr *ip6 = mtod(packet, struct ip6_hdr *); 971 packet->m_pkthdr.pkt_proto = ip6->ip6_nxt; 972 } 973 packet->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC); 974 } 975 } 976} 977