2  * Copyright (c) 2012-2014 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   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. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  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. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  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> 
  36 #include <net/if_types.h> 
  38 #include <net/if_ipsec.h> 
  39 #include <libkern/OSMalloc.h> 
  40 #include <libkern/OSAtomic.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> 
  54 /* Kernel Control functions */ 
  55 static errno_t  
ipsec_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl 
*sac
, 
  57 static errno_t  
ipsec_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
, 
  59 static errno_t  
ipsec_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
, 
  60                                                            void *unitinfo
, mbuf_t m
, int flags
); 
  61 static errno_t  
ipsec_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, 
  62                                                                  int opt
, void *data
, size_t *len
); 
  63 static errno_t  
ipsec_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, 
  64                                                                  int opt
, void *data
, size_t len
); 
  66 /* Network Interface functions */ 
  67 static void     ipsec_start(ifnet_t     interface
); 
  68 static errno_t  
ipsec_output(ifnet_t interface
, mbuf_t data
); 
  69 static errno_t  
ipsec_demux(ifnet_t interface
, mbuf_t data
, char *frame_header
, 
  70                                                         protocol_family_t 
*protocol
); 
  71 static 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
); 
  74 static errno_t  
ipsec_del_proto(ifnet_t interface
, protocol_family_t protocol
); 
  75 static errno_t  
ipsec_ioctl(ifnet_t interface
, u_long cmd
, void *data
); 
  76 static void             ipsec_detached(ifnet_t interface
); 
  78 /* Protocol handlers */ 
  79 static errno_t  
ipsec_attach_proto(ifnet_t interface
, protocol_family_t proto
); 
  80 static errno_t  
ipsec_proto_input(ifnet_t interface
, protocol_family_t protocol
, 
  81                                                                   mbuf_t m
, char *frame_header
); 
  82 static 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
); 
  86 static kern_ctl_ref     ipsec_kctlref
; 
  87 static u_int32_t        ipsec_family
; 
  88 static OSMallocTag      ipsec_malloc_tag
; 
  89 static SInt32           ipsec_ifcount 
= 0; 
  91 #define IPSECQ_MAXLEN 256 
  95 ipsec_alloc(size_t size
) 
  97         size_t  *mem 
= OSMalloc(size 
+ sizeof(size_t), ipsec_malloc_tag
); 
 100                 *mem 
= size 
+ sizeof(size_t); 
 108 ipsec_free(void *ptr
) 
 112         OSFree(size
, *size
, ipsec_malloc_tag
); 
 116 ipsec_register_control(void) 
 118         struct kern_ctl_reg     kern_ctl
; 
 121         /* Create a tag to allocate memory */ 
 122         ipsec_malloc_tag 
= OSMalloc_Tagalloc(IPSEC_CONTROL_NAME
, OSMT_DEFAULT
); 
 124         /* Find a unique value for our interface family */ 
 125         result 
= mbuf_tag_id_find(IPSEC_CONTROL_NAME
, &ipsec_family
); 
 127                 printf("ipsec_register_control - mbuf_tag_id_find_internal failed: %d\n", result
); 
 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
; 
 143         result 
= ctl_register(&kern_ctl
, &ipsec_kctlref
); 
 145                 printf("ipsec_register_control - ctl_register failed: %d\n", result
); 
 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
); 
 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
); 
 173 ipsec_interface_isvalid (ifnet_t interface
) 
 175     struct ipsec_pcb 
*pcb 
= NULL
; 
 177     if (interface 
== NULL
) 
 180     pcb 
= ifnet_softc(interface
); 
 185     /* When ctl disconnects, ipsec_unit is set to 0 */ 
 186     if (pcb
->ipsec_unit 
== 0) 
 192 /* Kernel control functions */ 
 195 ipsec_ctl_connect(kern_ctl_ref          kctlref
, 
 196                                   struct sockaddr_ctl   
*sac
, 
 199         struct ifnet_init_eparams       ipsec_init
; 
 200         struct ipsec_pcb                                
*pcb
; 
 202         struct ifnet_stats_param        stats
; 
 204         /* kernel control allocates, interface frees */ 
 205         pcb 
= ipsec_alloc(sizeof(*pcb
)); 
 209         /* Setup the protocol control block */ 
 210         bzero(pcb
, sizeof(*pcb
)); 
 212         pcb
->ipsec_ctlref 
= kctlref
; 
 213         pcb
->ipsec_unit 
= sac
->sc_unit
; 
 214         pcb
->ipsec_output_service_class 
= MBUF_SC_OAM
; 
 216         printf("ipsec_ctl_connect: creating interface ipsec%d\n", pcb
->ipsec_unit 
- 1); 
 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
; 
 234         result 
= ifnet_allocate_extended(&ipsec_init
, &pcb
->ipsec_ifp
); 
 236                 printf("ipsec_ctl_connect - ifnet_allocate failed: %d\n", result
); 
 240         OSIncrementAtomic(&ipsec_ifcount
); 
 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); 
 246         /* The interface must generate its own IPv6 LinkLocal address, 
 247          * if possible following the recommendation of RFC2472 to the 64bit interface ID 
 249         ifnet_set_eflags(pcb
->ipsec_ifp
, IFEF_NOAUTOIPV6LL
, IFEF_NOAUTOIPV6LL
); 
 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
); 
 255         /* Attach the interface */ 
 256         result 
= ifnet_attach(pcb
->ipsec_ifp
, NULL
); 
 258                 printf("ipsec_ctl_connect - ifnet_allocate failed: %d\n", result
); 
 259                 ifnet_release(pcb
->ipsec_ifp
); 
 265                 bpfattach(pcb
->ipsec_ifp
, DLT_NULL
, 4); 
 267         /* The interfaces resoures allocated, mark it as running */ 
 269                 ifnet_set_flags(pcb
->ipsec_ifp
, IFF_RUNNING
, IFF_RUNNING
); 
 275 ipsec_detach_ip(ifnet_t                         interface
, 
 276                                 protocol_family_t       protocol
, 
 279         errno_t result 
= EPROTONOSUPPORT
; 
 281         /* Attempt a detach */ 
 282         if (protocol 
== PF_INET
) { 
 285                 bzero(&ifr
, sizeof(ifr
)); 
 286                 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d", 
 287                                  ifnet_name(interface
), ifnet_unit(interface
)); 
 289                 result 
= sock_ioctl(pf_socket
, SIOCPROTODETACH
, &ifr
); 
 291         else if (protocol 
== PF_INET6
) { 
 292                 struct in6_ifreq        ifr6
; 
 294                 bzero(&ifr6
, sizeof(ifr6
)); 
 295                 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d", 
 296                                  ifnet_name(interface
), ifnet_unit(interface
)); 
 298                 result 
= sock_ioctl(pf_socket
, SIOCPROTODETACH_IN6
, &ifr6
); 
 305 ipsec_remove_address(ifnet_t                            interface
, 
 306                                          protocol_family_t      protocol
, 
 312         /* Attempt a detach */ 
 313         if (protocol 
== PF_INET
) { 
 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
)); 
 321                         printf("ipsec_remove_address - ifaddr_address failed: %d", result
); 
 324                         result 
= sock_ioctl(pf_socket
, SIOCDIFADDR
, &ifr
); 
 326                                 printf("ipsec_remove_address - SIOCDIFADDR failed: %d", result
); 
 330         else if (protocol 
== PF_INET6
) { 
 331                 struct in6_ifreq        ifr6
; 
 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
)); 
 339                         printf("ipsec_remove_address - ifaddr_address failed (v6): %d", 
 343                         result 
= sock_ioctl(pf_socket
, SIOCDIFADDR_IN6
, &ifr6
); 
 345                                 printf("ipsec_remove_address - SIOCDIFADDR_IN6 failed: %d", 
 353 ipsec_cleanup_family(ifnet_t                            interface
, 
 354                                          protocol_family_t      protocol
) 
 357         socket_t        pf_socket 
= NULL
; 
 358         ifaddr_t        
*addresses 
= NULL
; 
 361         if (protocol 
!= PF_INET 
&& protocol 
!= PF_INET6
) { 
 362                 printf("ipsec_cleanup_family - invalid protocol family %d\n", protocol
); 
 366         /* Create a socket for removing addresses and detaching the protocol */ 
 367         result 
= sock_socket(protocol
, SOCK_DGRAM
, 0, NULL
, NULL
, &pf_socket
); 
 369                 if (result 
!= EAFNOSUPPORT
) 
 370                         printf("ipsec_cleanup_family - failed to create %s socket: %d\n", 
 371                                    protocol 
== PF_INET 
? "IP" : "IPv6", result
); 
 375         /* always set SS_PRIV, we want to close and detach regardless */ 
 376         sock_setpriv(pf_socket
, 1); 
 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. */ 
 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
); 
 390          * At this point, we received an EBUSY error. This means there are 
 391          * addresses attached. We should detach them and then try again. 
 393         result 
= ifnet_get_address_list_family(interface
, &addresses
, protocol
); 
 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
); 
 401         for (i 
= 0; addresses
[i
] != 0; i
++) { 
 402                 ipsec_remove_address(interface
, protocol
, addresses
[i
], pf_socket
); 
 404         ifnet_free_address_list(addresses
); 
 408          * The addresses should be gone, we should try the remove again. 
 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
); 
 416         if (pf_socket 
!= NULL
) 
 417                 sock_close(pf_socket
); 
 419         if (addresses 
!= NULL
) 
 420                 ifnet_free_address_list(addresses
); 
 424 ipsec_ctl_disconnect(__unused kern_ctl_ref      kctlref
, 
 425                                          __unused u_int32_t             unit
, 
 428         struct ipsec_pcb        
*pcb 
= unitinfo
; 
 429         ifnet_t                 ifp 
= pcb
->ipsec_ifp
; 
 432         pcb
->ipsec_ctlref 
= NULL
; 
 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. 
 441     key_delsp_for_ipsec_if(ifp
); 
 443         ipsec_cleanup_family(ifp
, AF_INET
); 
 444         ipsec_cleanup_family(ifp
, AF_INET6
); 
 446         if ((result 
= ifnet_detach(ifp
)) != 0) { 
 447                 printf("ipsec_ctl_disconnect - ifnet_detach failed: %d\n", result
); 
 454 ipsec_ctl_send(__unused kern_ctl_ref    kctlref
, 
 455                            __unused u_int32_t           unit
, 
 456                            __unused 
void                        *unitinfo
, 
 460     /* Receive messages from the control socket. Currently unused. */ 
 466 ipsec_ctl_setopt(__unused kern_ctl_ref  kctlref
, 
 467                                  __unused u_int32_t             unit
, 
 473         struct ipsec_pcb                        
*pcb 
= unitinfo
; 
 476         /* check for privileges for privileged options */ 
 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) { 
 489                 case IPSEC_OPT_FLAGS
: 
 490                         if (len 
!= sizeof(u_int32_t
)) 
 493                                 pcb
->ipsec_flags 
= *(u_int32_t 
*)data
; 
 496                 case IPSEC_OPT_EXT_IFDATA_STATS
: 
 497                         if (len 
!= sizeof(int)) { 
 501                         pcb
->ipsec_ext_ifdata_stats 
= (*(int *)data
) ? 1 : 0; 
 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
; 
 508                         if (utsp 
== NULL 
|| len 
< sizeof(struct ipsec_stats_param
)) { 
 512                         if (!pcb
->ipsec_ext_ifdata_stats
) { 
 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
); 
 520                                 ifnet_stat_increment_out(pcb
->ipsec_ifp
, utsp
->utsp_packets
, 
 521                                                                                  utsp
->utsp_bytes
, utsp
->utsp_errors
); 
 525                 case IPSEC_OPT_SET_DELEGATE_INTERFACE
: { 
 526                         ifnet_t         del_ifp 
= NULL
; 
 529                         if (len 
> IFNAMSIZ 
- 1) { 
 533                         if (len 
!= 0) {   /* if len==0, del_ifp will be NULL causing the delegate to be removed */ 
 534                                 bcopy(data
, name
, len
); 
 536                                 result 
= ifnet_find_by_name(name
, &del_ifp
); 
 539                                 result 
= ifnet_set_delegate(pcb
->ipsec_ifp
, del_ifp
); 
 541                                         ifnet_release(del_ifp
); 
 546                 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS
: { 
 547                         if (len 
!= sizeof(int)) { 
 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
; 
 555                                 pcb
->ipsec_output_service_class 
= output_service_class
; 
 561                         result 
= ENOPROTOOPT
; 
 569 ipsec_ctl_getopt(__unused kern_ctl_ref  kctlref
, 
 570                                  __unused u_int32_t             unit
, 
 576         struct ipsec_pcb                        
*pcb 
= unitinfo
; 
 580                 case IPSEC_OPT_FLAGS
: 
 581                         if (*len 
!= sizeof(u_int32_t
)) 
 584                                 *(u_int32_t 
*)data 
= pcb
->ipsec_flags
; 
 587                 case IPSEC_OPT_EXT_IFDATA_STATS
: 
 588                         if (*len 
!= sizeof(int)) 
 591                                 *(int *)data 
= (pcb
->ipsec_ext_ifdata_stats
) ? 1 : 0; 
 594                 case IPSEC_OPT_IFNAME
: 
 595                         *len 
= snprintf(data
, *len
, "%s%d", ifnet_name(pcb
->ipsec_ifp
), ifnet_unit(pcb
->ipsec_ifp
)) + 1; 
 598                 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS
: { 
 599                         if (*len 
!= sizeof(int)) { 
 603                         *(int *)data 
= so_svc2tc(pcb
->ipsec_output_service_class
); 
 607                         result 
= ENOPROTOOPT
; 
 614 /* Network Interface functions */ 
 616 ipsec_output(ifnet_t    interface
, 
 619         struct ipsec_pcb        
*pcb 
= ifnet_softc(interface
); 
 620     struct ipsec_output_state ipsec_state
; 
 622     struct route_in6 ro6
; 
 626     struct ip_out_args ipoa
; 
 627     struct ip6_out_args ip6oa
; 
 629     u_int ip_version 
= 0; 
 632     struct flowadv 
*adv 
= NULL
; 
 634         // Make sure this packet isn't looping through the interface 
 635         if (necp_get_last_interface_index_from_packet(data
) == interface
->if_index
) { 
 637                 goto ipsec_output_err
; 
 640         // Mark the interface so NECP can evaluate tunnel policy 
 641         necp_mark_packet_from_interface(data
, interface
); 
 643     ip 
= mtod(data
, struct ip 
*); 
 644     ip_version 
= ip
->ip_v
; 
 646     switch (ip_version
) { 
 650             bpf_tap_out(pcb
->ipsec_ifp
, DLT_NULL
, data
, &af
, sizeof(af
)); 
 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
)); 
 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
; 
 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
); 
 672             /* Flip endian-ness for ip_output */ 
 673             ip 
= mtod(data
, struct ip 
*); 
 677             /* Increment statistics */ 
 678             length 
= mbuf_pkthdr_len(data
); 
 679             ifnet_stat_increment_out(interface
, 1, length
, 0); 
 681             /* Send to ip_output */ 
 682             bzero(&ro
, sizeof(ro
)); 
 684             flags 
= IP_OUTARGS 
|        /* Passing out args to specify interface */ 
 685                         IP_NOIPSEC
;                             /* To ensure the packet doesn't go through ipsec twice */ 
 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
; 
 695             adv 
= &ipoa
.ipoa_flowadv
; 
 697             (void) ip_output(data
, NULL
, &ro
, flags
, NULL
, &ipoa
); 
 700             if (adv
->code 
== FADV_FLOW_CONTROLLED 
|| adv
->code 
== FADV_SUSPENDED
) { 
 702                 ifnet_disable_output(interface
); 
 708             bpf_tap_out(pcb
->ipsec_ifp
, DLT_NULL
, data
, &af
, sizeof(af
)); 
 710             data 
= ipsec6_splithdr(data
); 
 711             ip6 
= mtod(data
, struct ip6_hdr 
*); 
 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
)); 
 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 */ 
 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
; 
 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
); 
 734             /* Increment statistics */ 
 735             length 
= mbuf_pkthdr_len(data
); 
 736             ifnet_stat_increment_out(interface
, 1, length
, 0); 
 738             /* Send to ip6_output */ 
 739             bzero(&ro6
, sizeof(ro6
)); 
 741             flags 
= IPV6_OUTARGS
; 
 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
; 
 751             adv 
= &ip6oa
.ip6oa_flowadv
; 
 753             (void) ip6_output(data
, NULL
, &ro6
, flags
, NULL
, NULL
, &ip6oa
); 
 756             if (adv
->code 
== FADV_FLOW_CONTROLLED 
|| adv
->code 
== FADV_SUSPENDED
) { 
 758                 ifnet_disable_output(interface
); 
 763             printf("ipsec_output: Received unknown packet version %d.\n", ip_version
); 
 765             goto ipsec_output_err
; 
 778 ipsec_start(ifnet_t     interface
) 
 783                 if (ifnet_dequeue(interface
, &data
) != 0) 
 785                 if (ipsec_output(interface
, data
) != 0) 
 790 /* Network Interface functions */ 
 792 ipsec_demux(__unused ifnet_t    interface
, 
 794                         __unused 
char           *frame_header
, 
 795                         protocol_family_t       
*protocol
) 
 800         while (data 
!= NULL 
&& mbuf_len(data
) < 1) { 
 801                 data 
= mbuf_next(data
); 
 807     ip 
= mtod(data
, struct ip 
*); 
 808     ip_version 
= ip
->ip_v
; 
 815             *protocol 
= PF_INET6
; 
 825 ipsec_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
) 
 843 ipsec_del_proto(__unused ifnet_t                        interface
, 
 844                                 __unused protocol_family_t      protocol
) 
 850 ipsec_ioctl(ifnet_t             interface
, 
 858                         ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
); 
 862                         /* ifioctl() takes care of it */ 
 876         struct ipsec_pcb        
*pcb 
= ifnet_softc(interface
); 
 878         ifnet_release(pcb
->ipsec_ifp
); 
 881         OSDecrementAtomic(&ipsec_ifcount
); 
 884 /* Protocol Handlers */ 
 887 ipsec_proto_input(ifnet_t interface
, 
 888                                   protocol_family_t     protocol
, 
 890                                   __unused 
char *frame_header
) 
 894         ip 
= mtod(m
, struct ip 
*); 
 897         else if (ip
->ip_v 
== 6) 
 900         mbuf_pkthdr_setrcvif(m
, interface
); 
 901         bpf_tap_in(interface
, DLT_NULL
, m
, &af
, sizeof(af
)); 
 903         if (proto_input(protocol
, m
) != 0) 
 910 ipsec_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
) 
 919         *(protocol_family_t 
*)(void *)frame_type 
= protocol
; 
 924 ipsec_attach_proto(ifnet_t                              interface
, 
 925                                    protocol_family_t    protocol
) 
 927         struct ifnet_attach_proto_param proto
; 
 930         bzero(&proto
, sizeof(proto
)); 
 931         proto
.input 
= ipsec_proto_input
; 
 932         proto
.pre_output 
= ipsec_proto_pre_output
; 
 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", 
 944 ipsec_inject_inbound_packet(ifnet_t     interface
, 
 948         protocol_family_t protocol
; 
 949         if ((error 
= ipsec_demux(interface
, packet
, NULL
, &protocol
)) != 0) { 
 953         return ipsec_proto_input(interface
, protocol
, packet
, NULL
); 
 957 ipsec_set_pkthdr_for_interface(ifnet_t interface
, mbuf_t packet
, int family
) 
 959         if (packet 
!= NULL 
&& interface 
!= NULL
) { 
 960                 struct ipsec_pcb 
*pcb 
= ifnet_softc(interface
); 
 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
; 
 973                         packet
->m_pkthdr
.pkt_flags 
= (PKTF_FLOW_ID 
| PKTF_FLOW_ADV 
| PKTF_FLOW_LOCALSRC
);