2 * Copyright (c) 2012-2018 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>
40 #include <sys/sockio.h>
41 #include <netinet/in.h>
42 #include <netinet/ip6.h>
43 #include <netinet6/in6_var.h>
44 #include <netinet6/ip6_var.h>
45 #include <sys/kauth.h>
46 #include <netinet6/ipsec.h>
47 #include <netinet6/ipsec6.h>
48 #include <netinet6/esp.h>
49 #include <netinet6/esp6.h>
50 #include <netinet/ip.h>
51 #include <net/flowadv.h>
53 #include <netkey/key.h>
54 #include <net/pktap.h>
55 #include <kern/zalloc.h>
59 extern int net_qos_policy_restricted
;
60 extern int net_qos_policy_restrict_avapps
;
62 /* Kernel Control functions */
63 static errno_t
ipsec_ctl_bind(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
65 static errno_t
ipsec_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
67 static errno_t
ipsec_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
,
69 static errno_t
ipsec_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
,
70 void *unitinfo
, mbuf_t m
, int flags
);
71 static errno_t
ipsec_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
72 int opt
, void *data
, size_t *len
);
73 static errno_t
ipsec_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
74 int opt
, void *data
, size_t len
);
76 /* Network Interface functions */
77 static void ipsec_start(ifnet_t interface
);
78 static errno_t
ipsec_output(ifnet_t interface
, mbuf_t data
);
79 static errno_t
ipsec_demux(ifnet_t interface
, mbuf_t data
, char *frame_header
,
80 protocol_family_t
*protocol
);
81 static errno_t
ipsec_add_proto(ifnet_t interface
, protocol_family_t protocol
,
82 const struct ifnet_demux_desc
*demux_array
,
83 u_int32_t demux_count
);
84 static errno_t
ipsec_del_proto(ifnet_t interface
, protocol_family_t protocol
);
85 static errno_t
ipsec_ioctl(ifnet_t interface
, u_long cmd
, void *data
);
86 static void ipsec_detached(ifnet_t interface
);
88 /* Protocol handlers */
89 static errno_t
ipsec_attach_proto(ifnet_t interface
, protocol_family_t proto
);
90 static errno_t
ipsec_proto_input(ifnet_t interface
, protocol_family_t protocol
,
91 mbuf_t m
, char *frame_header
);
92 static errno_t
ipsec_proto_pre_output(ifnet_t interface
, protocol_family_t protocol
,
93 mbuf_t
*packet
, const struct sockaddr
*dest
, void *route
,
94 char *frame_type
, char *link_layer_dest
);
96 static kern_ctl_ref ipsec_kctlref
;
97 static u_int32_t ipsec_family
;
98 static lck_attr_t
*ipsec_lck_attr
;
99 static lck_grp_attr_t
*ipsec_lck_grp_attr
;
100 static lck_grp_t
*ipsec_lck_grp
;
101 static lck_mtx_t ipsec_lock
;
105 SYSCTL_DECL(_net_ipsec
);
106 SYSCTL_NODE(_net
, OID_AUTO
, ipsec
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, "IPsec");
107 static int if_ipsec_verify_interface_creation
= 0;
108 SYSCTL_INT(_net_ipsec
, OID_AUTO
, verify_interface_creation
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &if_ipsec_verify_interface_creation
, 0, "");
110 #define IPSEC_IF_VERIFY(_e) if (__improbable(if_ipsec_verify_interface_creation)) { VERIFY(_e); }
112 #define IPSEC_IF_DEFAULT_SLOT_SIZE 2048
113 #define IPSEC_IF_DEFAULT_RING_SIZE 64
114 #define IPSEC_IF_DEFAULT_TX_FSW_RING_SIZE 64
115 #define IPSEC_IF_DEFAULT_RX_FSW_RING_SIZE 128
116 #define IPSEC_IF_DEFAULT_BUF_SEG_SIZE skmem_usr_buf_seg_size
118 #define IPSEC_IF_MIN_RING_SIZE 16
119 #define IPSEC_IF_MAX_RING_SIZE 1024
121 #define IPSEC_IF_MIN_SLOT_SIZE 1024
122 #define IPSEC_IF_MAX_SLOT_SIZE 4096
124 static int sysctl_if_ipsec_ring_size SYSCTL_HANDLER_ARGS
;
125 static int sysctl_if_ipsec_tx_fsw_ring_size SYSCTL_HANDLER_ARGS
;
126 static int sysctl_if_ipsec_rx_fsw_ring_size SYSCTL_HANDLER_ARGS
;
128 static int if_ipsec_ring_size
= IPSEC_IF_DEFAULT_RING_SIZE
;
129 static int if_ipsec_tx_fsw_ring_size
= IPSEC_IF_DEFAULT_TX_FSW_RING_SIZE
;
130 static int if_ipsec_rx_fsw_ring_size
= IPSEC_IF_DEFAULT_RX_FSW_RING_SIZE
;
132 SYSCTL_PROC(_net_ipsec
, OID_AUTO
, ring_size
, CTLTYPE_INT
| CTLFLAG_LOCKED
| CTLFLAG_RW
,
133 &if_ipsec_ring_size
, IPSEC_IF_DEFAULT_RING_SIZE
, &sysctl_if_ipsec_ring_size
, "I", "");
134 SYSCTL_PROC(_net_ipsec
, OID_AUTO
, tx_fsw_ring_size
, CTLTYPE_INT
| CTLFLAG_LOCKED
| CTLFLAG_RW
,
135 &if_ipsec_tx_fsw_ring_size
, IPSEC_IF_DEFAULT_TX_FSW_RING_SIZE
, &sysctl_if_ipsec_tx_fsw_ring_size
, "I", "");
136 SYSCTL_PROC(_net_ipsec
, OID_AUTO
, rx_fsw_ring_size
, CTLTYPE_INT
| CTLFLAG_LOCKED
| CTLFLAG_RW
,
137 &if_ipsec_rx_fsw_ring_size
, IPSEC_IF_DEFAULT_RX_FSW_RING_SIZE
, &sysctl_if_ipsec_rx_fsw_ring_size
, "I", "");
140 ipsec_register_nexus(void);
142 typedef struct ipsec_nx
{
152 static nexus_controller_t ipsec_ncd
;
153 static int ipsec_ncd_refcount
;
154 static uuid_t ipsec_kpipe_uuid
;
156 #endif // IPSEC_NEXUS
158 /* Control block allocated for each kernel control connection */
160 TAILQ_ENTRY(ipsec_pcb
) ipsec_chain
;
161 kern_ctl_ref ipsec_ctlref
;
163 u_int32_t ipsec_unit
;
164 u_int32_t ipsec_unique_id
;
165 u_int32_t ipsec_flags
;
166 u_int32_t ipsec_input_frag_size
;
167 bool ipsec_frag_size_set
;
168 int ipsec_ext_ifdata_stats
;
169 mbuf_svc_class_t ipsec_output_service_class
;
170 char ipsec_if_xname
[IFXNAMSIZ
];
171 char ipsec_unique_name
[IFXNAMSIZ
];
172 // PCB lock protects state fields, like ipsec_kpipe_enabled
173 decl_lck_rw_data(, ipsec_pcb_lock
);
176 lck_mtx_t ipsec_input_chain_lock
;
177 struct mbuf
* ipsec_input_chain
;
178 struct mbuf
* ipsec_input_chain_last
;
179 // Input chain lock protects the list of input mbufs
180 // The input chain lock must be taken AFTER the PCB lock if both are held
181 struct ipsec_nx ipsec_nx
;
182 int ipsec_kpipe_enabled
;
183 uuid_t ipsec_kpipe_uuid
;
184 void * ipsec_kpipe_rxring
;
185 void * ipsec_kpipe_txring
;
186 kern_pbufpool_t ipsec_kpipe_pp
;
188 kern_nexus_t ipsec_netif_nexus
;
189 kern_pbufpool_t ipsec_netif_pp
;
190 void * ipsec_netif_rxring
;
191 void * ipsec_netif_txring
;
192 uint64_t ipsec_netif_txring_size
;
194 u_int32_t ipsec_slot_size
;
195 u_int32_t ipsec_netif_ring_size
;
196 u_int32_t ipsec_tx_fsw_ring_size
;
197 u_int32_t ipsec_rx_fsw_ring_size
;
198 bool ipsec_use_netif
;
200 #endif // IPSEC_NEXUS
203 TAILQ_HEAD(ipsec_list
, ipsec_pcb
) ipsec_head
;
205 #define IPSEC_PCB_ZONE_MAX 32
206 #define IPSEC_PCB_ZONE_NAME "net.if_ipsec"
208 static unsigned int ipsec_pcb_size
; /* size of zone element */
209 static struct zone
*ipsec_pcb_zone
; /* zone for ipsec_pcb */
211 #define IPSECQ_MAXLEN 256
215 sysctl_if_ipsec_ring_size SYSCTL_HANDLER_ARGS
217 #pragma unused(arg1, arg2)
218 int value
= if_ipsec_ring_size
;
220 int error
= sysctl_handle_int(oidp
, &value
, 0, req
);
221 if (error
|| !req
->newptr
) {
225 if (value
< IPSEC_IF_MIN_RING_SIZE
||
226 value
> IPSEC_IF_MAX_RING_SIZE
) {
230 if_ipsec_ring_size
= value
;
236 sysctl_if_ipsec_tx_fsw_ring_size SYSCTL_HANDLER_ARGS
238 #pragma unused(arg1, arg2)
239 int value
= if_ipsec_tx_fsw_ring_size
;
241 int error
= sysctl_handle_int(oidp
, &value
, 0, req
);
242 if (error
|| !req
->newptr
) {
246 if (value
< IPSEC_IF_MIN_RING_SIZE
||
247 value
> IPSEC_IF_MAX_RING_SIZE
) {
251 if_ipsec_tx_fsw_ring_size
= value
;
257 sysctl_if_ipsec_rx_fsw_ring_size SYSCTL_HANDLER_ARGS
259 #pragma unused(arg1, arg2)
260 int value
= if_ipsec_rx_fsw_ring_size
;
262 int error
= sysctl_handle_int(oidp
, &value
, 0, req
);
263 if (error
|| !req
->newptr
) {
267 if (value
< IPSEC_IF_MIN_RING_SIZE
||
268 value
> IPSEC_IF_MAX_RING_SIZE
) {
272 if_ipsec_rx_fsw_ring_size
= value
;
276 #endif // IPSEC_NEXUS
279 ipsec_register_control(void)
281 struct kern_ctl_reg kern_ctl
;
284 /* Find a unique value for our interface family */
285 result
= mbuf_tag_id_find(IPSEC_CONTROL_NAME
, &ipsec_family
);
287 printf("ipsec_register_control - mbuf_tag_id_find_internal failed: %d\n", result
);
291 ipsec_pcb_size
= sizeof(struct ipsec_pcb
);
292 ipsec_pcb_zone
= zinit(ipsec_pcb_size
,
293 IPSEC_PCB_ZONE_MAX
* ipsec_pcb_size
,
294 0, IPSEC_PCB_ZONE_NAME
);
295 if (ipsec_pcb_zone
== NULL
) {
296 printf("ipsec_register_control - zinit(ipsec_pcb) failed");
301 ipsec_register_nexus();
302 #endif // IPSEC_NEXUS
304 TAILQ_INIT(&ipsec_head
);
306 bzero(&kern_ctl
, sizeof(kern_ctl
));
307 strlcpy(kern_ctl
.ctl_name
, IPSEC_CONTROL_NAME
, sizeof(kern_ctl
.ctl_name
));
308 kern_ctl
.ctl_name
[sizeof(kern_ctl
.ctl_name
) - 1] = 0;
309 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
; /* Require root */
310 kern_ctl
.ctl_sendsize
= 64 * 1024;
311 kern_ctl
.ctl_recvsize
= 64 * 1024;
312 kern_ctl
.ctl_bind
= ipsec_ctl_bind
;
313 kern_ctl
.ctl_connect
= ipsec_ctl_connect
;
314 kern_ctl
.ctl_disconnect
= ipsec_ctl_disconnect
;
315 kern_ctl
.ctl_send
= ipsec_ctl_send
;
316 kern_ctl
.ctl_setopt
= ipsec_ctl_setopt
;
317 kern_ctl
.ctl_getopt
= ipsec_ctl_getopt
;
319 result
= ctl_register(&kern_ctl
, &ipsec_kctlref
);
321 printf("ipsec_register_control - ctl_register failed: %d\n", result
);
325 /* Register the protocol plumbers */
326 if ((result
= proto_register_plumber(PF_INET
, ipsec_family
,
327 ipsec_attach_proto
, NULL
)) != 0) {
328 printf("ipsec_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n",
329 ipsec_family
, result
);
330 ctl_deregister(ipsec_kctlref
);
334 /* Register the protocol plumbers */
335 if ((result
= proto_register_plumber(PF_INET6
, ipsec_family
,
336 ipsec_attach_proto
, NULL
)) != 0) {
337 proto_unregister_plumber(PF_INET
, ipsec_family
);
338 ctl_deregister(ipsec_kctlref
);
339 printf("ipsec_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n",
340 ipsec_family
, result
);
344 ipsec_lck_attr
= lck_attr_alloc_init();
345 ipsec_lck_grp_attr
= lck_grp_attr_alloc_init();
346 ipsec_lck_grp
= lck_grp_alloc_init("ipsec", ipsec_lck_grp_attr
);
347 lck_mtx_init(&ipsec_lock
, ipsec_lck_grp
, ipsec_lck_attr
);
354 ipsec_interface_isvalid (ifnet_t interface
)
356 struct ipsec_pcb
*pcb
= NULL
;
358 if (interface
== NULL
)
361 pcb
= ifnet_softc(interface
);
366 /* When ctl disconnects, ipsec_unit is set to 0 */
367 if (pcb
->ipsec_unit
== 0)
374 ipsec_ifnet_set_attrs(ifnet_t ifp
)
376 /* Set flags and additional information. */
377 ifnet_set_mtu(ifp
, 1500);
378 ifnet_set_flags(ifp
, IFF_UP
| IFF_MULTICAST
| IFF_POINTOPOINT
, 0xffff);
380 /* The interface must generate its own IPv6 LinkLocal address,
381 * if possible following the recommendation of RFC2472 to the 64bit interface ID
383 ifnet_set_eflags(ifp
, IFEF_NOAUTOIPV6LL
, IFEF_NOAUTOIPV6LL
);
386 /* Reset the stats in case as the interface may have been recycled */
387 struct ifnet_stats_param stats
;
388 bzero(&stats
, sizeof(struct ifnet_stats_param
));
389 ifnet_set_stat(ifp
, &stats
);
390 #endif // !IPSEC_NEXUS
397 static uuid_t ipsec_nx_dom_prov
;
400 ipsec_nxdp_init(__unused kern_nexus_domain_provider_t domprov
)
406 ipsec_nxdp_fini(__unused kern_nexus_domain_provider_t domprov
)
412 ipsec_register_nexus(void)
414 const struct kern_nexus_domain_provider_init dp_init
= {
415 .nxdpi_version
= KERN_NEXUS_DOMAIN_PROVIDER_CURRENT_VERSION
,
417 .nxdpi_init
= ipsec_nxdp_init
,
418 .nxdpi_fini
= ipsec_nxdp_fini
422 /* ipsec_nxdp_init() is called before this function returns */
423 err
= kern_nexus_register_domain_provider(NEXUS_TYPE_NET_IF
,
424 (const uint8_t *) "com.apple.ipsec",
425 &dp_init
, sizeof(dp_init
),
428 printf("%s: failed to register domain provider\n", __func__
);
435 ipsec_netif_prepare(kern_nexus_t nexus
, ifnet_t ifp
)
437 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
438 pcb
->ipsec_netif_nexus
= nexus
;
439 return (ipsec_ifnet_set_attrs(ifp
));
443 ipsec_nexus_pre_connect(kern_nexus_provider_t nxprov
,
444 proc_t p
, kern_nexus_t nexus
,
445 nexus_port_t nexus_port
, kern_channel_t channel
, void **ch_ctx
)
447 #pragma unused(nxprov, p)
448 #pragma unused(nexus, nexus_port, channel, ch_ctx)
453 ipsec_nexus_connected(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
454 kern_channel_t channel
)
456 #pragma unused(nxprov, channel)
457 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
458 boolean_t ok
= ifnet_is_attached(pcb
->ipsec_ifp
, 1);
459 return (ok
? 0 : ENXIO
);
463 ipsec_nexus_pre_disconnect(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
464 kern_channel_t channel
)
466 #pragma unused(nxprov, nexus, channel)
470 ipsec_netif_pre_disconnect(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
471 kern_channel_t channel
)
473 #pragma unused(nxprov, nexus, channel)
477 ipsec_nexus_disconnected(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
478 kern_channel_t channel
)
480 #pragma unused(nxprov, channel)
481 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
482 if (pcb
->ipsec_netif_nexus
== nexus
) {
483 pcb
->ipsec_netif_nexus
= NULL
;
485 ifnet_decr_iorefcnt(pcb
->ipsec_ifp
);
489 ipsec_kpipe_ring_init(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
490 kern_channel_t channel
, kern_channel_ring_t ring
, boolean_t is_tx_ring
,
493 #pragma unused(nxprov)
494 #pragma unused(channel)
495 #pragma unused(ring_ctx)
496 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
498 VERIFY(pcb
->ipsec_kpipe_rxring
== NULL
);
499 pcb
->ipsec_kpipe_rxring
= ring
;
501 VERIFY(pcb
->ipsec_kpipe_txring
== NULL
);
502 pcb
->ipsec_kpipe_txring
= ring
;
508 ipsec_kpipe_ring_fini(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
509 kern_channel_ring_t ring
)
511 #pragma unused(nxprov)
512 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
513 if (pcb
->ipsec_kpipe_rxring
== ring
) {
514 pcb
->ipsec_kpipe_rxring
= NULL
;
515 } else if (pcb
->ipsec_kpipe_txring
== ring
) {
516 pcb
->ipsec_kpipe_txring
= NULL
;
521 ipsec_kpipe_sync_tx(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
522 kern_channel_ring_t tx_ring
, uint32_t flags
)
524 #pragma unused(nxprov)
525 #pragma unused(flags)
526 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
528 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
529 int channel_enabled
= pcb
->ipsec_kpipe_enabled
;
530 if (!channel_enabled
) {
531 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
535 kern_channel_slot_t tx_slot
= kern_channel_get_next_slot(tx_ring
, NULL
, NULL
);
536 if (tx_slot
== NULL
) {
537 // Nothing to write, bail
538 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
542 // Signal the netif ring to read
543 kern_channel_ring_t rx_ring
= pcb
->ipsec_netif_rxring
;
544 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
546 if (rx_ring
!= NULL
) {
547 kern_channel_notify(rx_ring
, 0);
553 ipsec_encrypt_mbuf(ifnet_t interface
,
556 struct ipsec_output_state ipsec_state
;
560 // Make sure this packet isn't looping through the interface
561 if (necp_get_last_interface_index_from_packet(data
) == interface
->if_index
) {
563 goto ipsec_output_err
;
566 // Mark the interface so NECP can evaluate tunnel policy
567 necp_mark_packet_from_interface(data
, interface
);
569 struct ip
*ip
= mtod(data
, struct ip
*);
570 u_int ip_version
= ip
->ip_v
;
572 switch (ip_version
) {
576 memset(&ipsec_state
, 0, sizeof(ipsec_state
));
577 ipsec_state
.m
= data
;
578 ipsec_state
.dst
= (struct sockaddr
*)&ip
->ip_dst
;
579 memset(&ipsec_state
.ro
, 0, sizeof(ipsec_state
.ro
));
581 error
= ipsec4_interface_output(&ipsec_state
, interface
);
582 if (error
== 0 && ipsec_state
.tunneled
== 6) {
583 // Tunneled in IPv6 - packet is gone
584 // TODO: Don't lose mbuf
589 data
= ipsec_state
.m
;
590 if (error
|| data
== NULL
) {
592 printf("ipsec_encrypt_mbuf: ipsec4_output error %d\n", error
);
594 goto ipsec_output_err
;
601 data
= ipsec6_splithdr(data
);
603 printf("ipsec_encrypt_mbuf: ipsec6_splithdr returned NULL\n");
604 goto ipsec_output_err
;
607 struct ip6_hdr
*ip6
= mtod(data
, struct ip6_hdr
*);
609 memset(&ipsec_state
, 0, sizeof(ipsec_state
));
610 ipsec_state
.m
= data
;
611 ipsec_state
.dst
= (struct sockaddr
*)&ip6
->ip6_dst
;
612 memset(&ipsec_state
.ro
, 0, sizeof(ipsec_state
.ro
));
614 error
= ipsec6_interface_output(&ipsec_state
, interface
, &ip6
->ip6_nxt
, ipsec_state
.m
);
615 if (error
== 0 && ipsec_state
.tunneled
== 4) {
616 // Tunneled in IPv4 - packet is gone
617 // TODO: Don't lose mbuf
621 data
= ipsec_state
.m
;
622 if (error
|| data
== NULL
) {
624 printf("ipsec_encrypt_mbuf: ipsec6_output error %d\n", error
);
626 goto ipsec_output_err
;
631 printf("ipsec_encrypt_mbuf: Received unknown packet version %d\n", ip_version
);
633 goto ipsec_output_err
;
648 ipsec_kpipe_sync_rx(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
649 kern_channel_ring_t rx_ring
, uint32_t flags
)
651 #pragma unused(nxprov)
652 #pragma unused(flags)
653 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
654 struct kern_channel_ring_stat_increment rx_ring_stats
;
656 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
658 int channel_enabled
= pcb
->ipsec_kpipe_enabled
;
659 if (!channel_enabled
) {
660 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
664 // Reclaim user-released slots
665 (void) kern_channel_reclaim(rx_ring
);
667 uint32_t avail
= kern_channel_available_slot_count(rx_ring
);
669 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
673 kern_channel_ring_t tx_ring
= pcb
->ipsec_netif_txring
;
674 if (tx_ring
== NULL
) {
675 // Net-If TX ring not set up yet, nothing to read
676 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
680 struct netif_stats
*nifs
= &NX_NETIF_PRIVATE(pcb
->ipsec_netif_nexus
)->nif_stats
;
682 // Unlock ipsec before entering ring
683 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
685 (void)kr_enter(tx_ring
, TRUE
);
687 // Lock again after entering and validate
688 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
689 if (tx_ring
!= pcb
->ipsec_netif_txring
) {
690 // Ring no longer valid
691 // Unlock first, then exit ring
692 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
698 struct kern_channel_ring_stat_increment tx_ring_stats
;
699 bzero(&tx_ring_stats
, sizeof(tx_ring_stats
));
700 kern_channel_slot_t tx_pslot
= NULL
;
701 kern_channel_slot_t tx_slot
= kern_channel_get_next_slot(tx_ring
, NULL
, NULL
);
702 if (tx_slot
== NULL
) {
703 // Nothing to read, don't bother signalling
704 // Unlock first, then exit ring
705 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
710 struct kern_pbufpool
*rx_pp
= rx_ring
->ckr_pp
;
711 VERIFY(rx_pp
!= NULL
);
712 bzero(&rx_ring_stats
, sizeof(rx_ring_stats
));
713 kern_channel_slot_t rx_pslot
= NULL
;
714 kern_channel_slot_t rx_slot
= kern_channel_get_next_slot(rx_ring
, NULL
, NULL
);
716 while (rx_slot
!= NULL
&& tx_slot
!= NULL
) {
721 // Allocate rx packet
722 kern_packet_t rx_ph
= 0;
723 error
= kern_pbufpool_alloc_nosleep(rx_pp
, 1, &rx_ph
);
724 if (__improbable(error
!= 0)) {
725 printf("ipsec_kpipe_sync_rx %s: failed to allocate packet\n",
726 pcb
->ipsec_ifp
->if_xname
);
730 kern_packet_t tx_ph
= kern_channel_slot_get_packet(tx_ring
, tx_slot
);
734 tx_slot
= kern_channel_get_next_slot(tx_ring
, tx_slot
, NULL
);
737 kern_pbufpool_free(rx_pp
, rx_ph
);
741 kern_buflet_t tx_buf
= kern_packet_get_next_buflet(tx_ph
, NULL
);
742 VERIFY(tx_buf
!= NULL
);
743 uint8_t *tx_baddr
= kern_buflet_get_object_address(tx_buf
);
744 VERIFY(tx_baddr
!= NULL
);
745 tx_baddr
+= kern_buflet_get_data_offset(tx_buf
);
747 bpf_tap_packet_out(pcb
->ipsec_ifp
, DLT_RAW
, tx_ph
, NULL
, 0);
749 length
= MIN(kern_packet_get_data_length(tx_ph
),
750 pcb
->ipsec_slot_size
);
752 // Increment TX stats
753 tx_ring_stats
.kcrsi_slots_transferred
++;
754 tx_ring_stats
.kcrsi_bytes_transferred
+= length
;
757 error
= mbuf_gethdr(MBUF_DONTWAIT
, MBUF_TYPE_HEADER
, &data
);
759 error
= mbuf_copyback(data
, 0, length
, tx_baddr
, MBUF_DONTWAIT
);
761 // Encrypt and send packet
762 data
= ipsec_encrypt_mbuf(pcb
->ipsec_ifp
, data
);
764 printf("ipsec_kpipe_sync_rx %s - mbuf_copyback(%zu) error %d\n", pcb
->ipsec_ifp
->if_xname
, length
, error
);
765 STATS_INC(nifs
, NETIF_STATS_NOMEM_MBUF
);
766 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
771 printf("ipsec_kpipe_sync_rx %s - mbuf_gethdr error %d\n", pcb
->ipsec_ifp
->if_xname
, error
);
772 STATS_INC(nifs
, NETIF_STATS_NOMEM_MBUF
);
773 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
776 printf("ipsec_kpipe_sync_rx %s - 0 length packet\n", pcb
->ipsec_ifp
->if_xname
);
777 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
778 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
782 printf("ipsec_kpipe_sync_rx %s: no encrypted packet to send\n", pcb
->ipsec_ifp
->if_xname
);
783 kern_pbufpool_free(rx_pp
, rx_ph
);
787 length
= mbuf_pkthdr_len(data
);
788 if (length
> rx_pp
->pp_buflet_size
) {
791 kern_pbufpool_free(rx_pp
, rx_ph
);
792 printf("ipsec_kpipe_sync_rx %s: encrypted packet length %zu > %u\n",
793 pcb
->ipsec_ifp
->if_xname
, length
, rx_pp
->pp_buflet_size
);
798 kern_buflet_t rx_buf
= kern_packet_get_next_buflet(rx_ph
, NULL
);
799 VERIFY(rx_buf
!= NULL
);
800 void *rx_baddr
= kern_buflet_get_object_address(rx_buf
);
801 VERIFY(rx_baddr
!= NULL
);
803 // Copy-in data from mbuf to buflet
804 mbuf_copydata(data
, 0, length
, (void *)rx_baddr
);
805 kern_packet_clear_flow_uuid(rx_ph
); // Zero flow id
807 // Finalize and attach the packet
808 error
= kern_buflet_set_data_offset(rx_buf
, 0);
810 error
= kern_buflet_set_data_length(rx_buf
, length
);
812 error
= kern_packet_finalize(rx_ph
);
814 error
= kern_channel_slot_attach_packet(rx_ring
, rx_slot
, rx_ph
);
817 STATS_INC(nifs
, NETIF_STATS_TXPKTS
);
818 STATS_INC(nifs
, NETIF_STATS_TXCOPY_DIRECT
);
820 rx_ring_stats
.kcrsi_slots_transferred
++;
821 rx_ring_stats
.kcrsi_bytes_transferred
+= length
;
823 if (!pcb
->ipsec_ext_ifdata_stats
) {
824 ifnet_stat_increment_out(pcb
->ipsec_ifp
, 1, length
, 0);
830 rx_slot
= kern_channel_get_next_slot(rx_ring
, rx_slot
, NULL
);
834 kern_channel_advance_slot(rx_ring
, rx_pslot
);
835 kern_channel_increment_ring_net_stats(rx_ring
, pcb
->ipsec_ifp
, &rx_ring_stats
);
839 kern_channel_advance_slot(tx_ring
, tx_pslot
);
840 kern_channel_increment_ring_net_stats(tx_ring
, pcb
->ipsec_ifp
, &tx_ring_stats
);
841 (void)kern_channel_reclaim(tx_ring
);
844 /* always reenable output */
845 errno_t error
= ifnet_enable_output(pcb
->ipsec_ifp
);
847 printf("ipsec_kpipe_sync_rx: ifnet_enable_output returned error %d\n", error
);
850 // Unlock first, then exit ring
851 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
853 if (tx_pslot
!= NULL
) {
854 kern_channel_notify(tx_ring
, 0);
862 ipsec_netif_ring_init(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
863 kern_channel_t channel
, kern_channel_ring_t ring
, boolean_t is_tx_ring
,
866 #pragma unused(nxprov)
867 #pragma unused(channel)
868 #pragma unused(ring_ctx)
869 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
871 VERIFY(pcb
->ipsec_netif_rxring
== NULL
);
872 pcb
->ipsec_netif_rxring
= ring
;
874 VERIFY(pcb
->ipsec_netif_txring
== NULL
);
875 pcb
->ipsec_netif_txring
= ring
;
881 ipsec_netif_ring_fini(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
882 kern_channel_ring_t ring
)
884 #pragma unused(nxprov)
885 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
886 if (pcb
->ipsec_netif_rxring
== ring
) {
887 pcb
->ipsec_netif_rxring
= NULL
;
888 } else if (pcb
->ipsec_netif_txring
== ring
) {
889 pcb
->ipsec_netif_txring
= NULL
;
894 ipsec_netif_check_policy(mbuf_t data
)
896 necp_kernel_policy_result necp_result
= 0;
897 necp_kernel_policy_result_parameter necp_result_parameter
= {};
898 uint32_t necp_matched_policy_id
= 0;
900 // This packet has been marked with IP level policy, do not mark again.
901 if (data
&& data
->m_pkthdr
.necp_mtag
.necp_policy_id
>= NECP_KERNEL_POLICY_ID_FIRST_VALID_IP
) {
905 size_t length
= mbuf_pkthdr_len(data
);
906 if (length
< sizeof(struct ip
)) {
910 struct ip
*ip
= mtod(data
, struct ip
*);
911 u_int ip_version
= ip
->ip_v
;
912 switch (ip_version
) {
914 necp_matched_policy_id
= necp_ip_output_find_policy_match(data
, 0, NULL
,
915 &necp_result
, &necp_result_parameter
);
919 necp_matched_policy_id
= necp_ip6_output_find_policy_match(data
, 0, NULL
,
920 &necp_result
, &necp_result_parameter
);
928 if (necp_result
== NECP_KERNEL_POLICY_RESULT_DROP
||
929 necp_result
== NECP_KERNEL_POLICY_RESULT_SOCKET_DIVERT
) {
930 /* Drop and flow divert packets should be blocked at the IP layer */
934 necp_mark_packet_from_ip(data
, necp_matched_policy_id
);
939 ipsec_netif_sync_tx(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
940 kern_channel_ring_t tx_ring
, uint32_t flags
)
942 #pragma unused(nxprov)
943 #pragma unused(flags)
944 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
946 struct netif_stats
*nifs
= &NX_NETIF_PRIVATE(nexus
)->nif_stats
;
948 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
950 struct kern_channel_ring_stat_increment tx_ring_stats
;
951 bzero(&tx_ring_stats
, sizeof(tx_ring_stats
));
952 kern_channel_slot_t tx_pslot
= NULL
;
953 kern_channel_slot_t tx_slot
= kern_channel_get_next_slot(tx_ring
, NULL
, NULL
);
955 STATS_INC(nifs
, NETIF_STATS_TXSYNC
);
957 if (tx_slot
== NULL
) {
958 // Nothing to write, don't bother signalling
959 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
963 if (pcb
->ipsec_kpipe_enabled
) {
964 kern_channel_ring_t rx_ring
= pcb
->ipsec_kpipe_rxring
;
965 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
967 // Signal the kernel pipe ring to read
968 if (rx_ring
!= NULL
) {
969 kern_channel_notify(rx_ring
, 0);
974 // If we're here, we're injecting into the BSD stack
975 while (tx_slot
!= NULL
) {
979 kern_packet_t tx_ph
= kern_channel_slot_get_packet(tx_ring
, tx_slot
);
983 tx_slot
= kern_channel_get_next_slot(tx_ring
, tx_slot
, NULL
);
989 kern_buflet_t tx_buf
= kern_packet_get_next_buflet(tx_ph
, NULL
);
990 VERIFY(tx_buf
!= NULL
);
991 uint8_t *tx_baddr
= kern_buflet_get_object_address(tx_buf
);
992 VERIFY(tx_baddr
!= 0);
993 tx_baddr
+= kern_buflet_get_data_offset(tx_buf
);
995 bpf_tap_packet_out(pcb
->ipsec_ifp
, DLT_RAW
, tx_ph
, NULL
, 0);
997 length
= MIN(kern_packet_get_data_length(tx_ph
),
998 pcb
->ipsec_slot_size
);
1001 errno_t error
= mbuf_gethdr(MBUF_DONTWAIT
, MBUF_TYPE_HEADER
, &data
);
1003 error
= mbuf_copyback(data
, 0, length
, tx_baddr
, MBUF_DONTWAIT
);
1005 // Mark packet from policy
1006 uint32_t policy_id
= kern_packet_get_policy_id(tx_ph
);
1007 necp_mark_packet_from_ip(data
, policy_id
);
1009 // Check policy with NECP
1010 if (!ipsec_netif_check_policy(data
)) {
1011 printf("ipsec_netif_sync_tx %s - failed policy check\n", pcb
->ipsec_ifp
->if_xname
);
1012 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1016 // Send through encryption
1017 error
= ipsec_output(pcb
->ipsec_ifp
, data
);
1019 printf("ipsec_netif_sync_tx %s - ipsec_output error %d\n", pcb
->ipsec_ifp
->if_xname
, error
);
1023 printf("ipsec_netif_sync_tx %s - mbuf_copyback(%zu) error %d\n", pcb
->ipsec_ifp
->if_xname
, length
, error
);
1024 STATS_INC(nifs
, NETIF_STATS_NOMEM_MBUF
);
1025 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1030 printf("ipsec_netif_sync_tx %s - mbuf_gethdr error %d\n", pcb
->ipsec_ifp
->if_xname
, error
);
1031 STATS_INC(nifs
, NETIF_STATS_NOMEM_MBUF
);
1032 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1035 printf("ipsec_netif_sync_tx %s - 0 length packet\n", pcb
->ipsec_ifp
->if_xname
);
1036 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1037 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1041 printf("ipsec_netif_sync_tx %s: no encrypted packet to send\n", pcb
->ipsec_ifp
->if_xname
);
1045 STATS_INC(nifs
, NETIF_STATS_TXPKTS
);
1046 STATS_INC(nifs
, NETIF_STATS_TXCOPY_MBUF
);
1048 tx_ring_stats
.kcrsi_slots_transferred
++;
1049 tx_ring_stats
.kcrsi_bytes_transferred
+= length
;
1053 kern_channel_advance_slot(tx_ring
, tx_pslot
);
1054 kern_channel_increment_ring_net_stats(tx_ring
, pcb
->ipsec_ifp
, &tx_ring_stats
);
1055 (void)kern_channel_reclaim(tx_ring
);
1058 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
1064 ipsec_netif_tx_doorbell(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
1065 kern_channel_ring_t ring
, __unused
uint32_t flags
)
1067 #pragma unused(nxprov)
1068 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
1069 boolean_t more
= false;
1073 * Refill and sync the ring; we may be racing against another thread doing
1074 * an RX sync that also wants to do kr_enter(), and so use the blocking
1077 rc
= kern_channel_tx_refill_canblock(ring
, UINT32_MAX
, UINT32_MAX
, true, &more
);
1078 if (rc
!= 0 && rc
!= EAGAIN
&& rc
!= EBUSY
) {
1079 printf("%s, tx refill failed %d\n", __func__
, rc
);
1082 (void) kr_enter(ring
, TRUE
);
1083 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
1085 if (pcb
->ipsec_kpipe_enabled
) {
1086 uint32_t tx_available
= kern_channel_available_slot_count(ring
);
1087 if (pcb
->ipsec_netif_txring_size
> 0 &&
1088 tx_available
>= pcb
->ipsec_netif_txring_size
- 1) {
1089 // No room left in tx ring, disable output for now
1090 errno_t error
= ifnet_disable_output(pcb
->ipsec_ifp
);
1092 printf("ipsec_netif_tx_doorbell: ifnet_disable_output returned error %d\n", error
);
1097 if (pcb
->ipsec_kpipe_enabled
) {
1098 kern_channel_ring_t rx_ring
= pcb
->ipsec_kpipe_rxring
;
1100 // Unlock while calling notify
1101 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
1102 // Signal the kernel pipe ring to read
1103 if (rx_ring
!= NULL
) {
1104 kern_channel_notify(rx_ring
, 0);
1107 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
1116 ipsec_netif_sync_rx(kern_nexus_provider_t nxprov
, kern_nexus_t nexus
,
1117 kern_channel_ring_t rx_ring
, uint32_t flags
)
1119 #pragma unused(nxprov)
1120 #pragma unused(flags)
1121 struct ipsec_pcb
*pcb
= kern_nexus_get_context(nexus
);
1122 struct kern_channel_ring_stat_increment rx_ring_stats
;
1124 struct netif_stats
*nifs
= &NX_NETIF_PRIVATE(nexus
)->nif_stats
;
1126 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
1128 // Reclaim user-released slots
1129 (void) kern_channel_reclaim(rx_ring
);
1131 STATS_INC(nifs
, NETIF_STATS_RXSYNC
);
1133 uint32_t avail
= kern_channel_available_slot_count(rx_ring
);
1135 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
1139 struct kern_pbufpool
*rx_pp
= rx_ring
->ckr_pp
;
1140 VERIFY(rx_pp
!= NULL
);
1141 bzero(&rx_ring_stats
, sizeof(rx_ring_stats
));
1142 kern_channel_slot_t rx_pslot
= NULL
;
1143 kern_channel_slot_t rx_slot
= kern_channel_get_next_slot(rx_ring
, NULL
, NULL
);
1145 while (rx_slot
!= NULL
) {
1146 // Check for a waiting packet
1147 lck_mtx_lock(&pcb
->ipsec_input_chain_lock
);
1148 mbuf_t data
= pcb
->ipsec_input_chain
;
1150 lck_mtx_unlock(&pcb
->ipsec_input_chain_lock
);
1154 // Allocate rx packet
1155 kern_packet_t rx_ph
= 0;
1156 errno_t error
= kern_pbufpool_alloc_nosleep(rx_pp
, 1, &rx_ph
);
1157 if (__improbable(error
!= 0)) {
1158 STATS_INC(nifs
, NETIF_STATS_NOMEM_PKT
);
1159 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1160 lck_mtx_unlock(&pcb
->ipsec_input_chain_lock
);
1164 // Advance waiting packets
1165 pcb
->ipsec_input_chain
= data
->m_nextpkt
;
1166 data
->m_nextpkt
= NULL
;
1167 if (pcb
->ipsec_input_chain
== NULL
) {
1168 pcb
->ipsec_input_chain_last
= NULL
;
1170 lck_mtx_unlock(&pcb
->ipsec_input_chain_lock
);
1172 size_t length
= mbuf_pkthdr_len(data
);
1174 if (length
< sizeof(struct ip
)) {
1177 kern_pbufpool_free(rx_pp
, rx_ph
);
1178 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1179 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1180 printf("ipsec_netif_sync_rx %s: legacy decrypted packet length cannot hold IP %zu < %zu\n",
1181 pcb
->ipsec_ifp
->if_xname
, length
, sizeof(struct ip
));
1186 struct ip
*ip
= mtod(data
, struct ip
*);
1187 u_int ip_version
= ip
->ip_v
;
1188 switch (ip_version
) {
1198 printf("ipsec_netif_sync_rx %s: legacy unknown ip version %u\n",
1199 pcb
->ipsec_ifp
->if_xname
, ip_version
);
1204 if (length
> rx_pp
->pp_buflet_size
||
1205 (pcb
->ipsec_frag_size_set
&& length
> pcb
->ipsec_input_frag_size
)) {
1207 // We need to fragment to send up into the netif
1209 u_int32_t fragment_mtu
= rx_pp
->pp_buflet_size
;
1210 if (pcb
->ipsec_frag_size_set
&&
1211 pcb
->ipsec_input_frag_size
< rx_pp
->pp_buflet_size
) {
1212 fragment_mtu
= pcb
->ipsec_input_frag_size
;
1215 mbuf_t fragment_chain
= NULL
;
1218 // ip_fragment expects the length in host order
1219 ip
->ip_len
= ntohs(ip
->ip_len
);
1221 // ip_fragment will modify the original data, don't free
1222 int fragment_error
= ip_fragment(data
, pcb
->ipsec_ifp
, fragment_mtu
, TRUE
);
1223 if (fragment_error
== 0 && data
!= NULL
) {
1224 fragment_chain
= data
;
1226 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1227 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1228 printf("ipsec_netif_sync_rx %s: failed to fragment IPv4 packet of length %zu (%d)\n",
1229 pcb
->ipsec_ifp
->if_xname
, length
, fragment_error
);
1234 if (length
< sizeof(struct ip6_hdr
)) {
1236 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1237 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1238 printf("ipsec_netif_sync_rx %s: failed to fragment IPv6 packet of length %zu < %zu\n",
1239 pcb
->ipsec_ifp
->if_xname
, length
, sizeof(struct ip6_hdr
));
1242 // ip6_do_fragmentation will free the original data on success only
1243 struct ip6_hdr
*ip6
= mtod(data
, struct ip6_hdr
*);
1244 struct ip6_exthdrs exthdrs
;
1245 memset(&exthdrs
, 0, sizeof(exthdrs
));
1247 int fragment_error
= ip6_do_fragmentation(&data
, 0, pcb
->ipsec_ifp
, sizeof(struct ip6_hdr
),
1248 ip6
, &exthdrs
, fragment_mtu
, ip6
->ip6_nxt
);
1249 if (fragment_error
== 0 && data
!= NULL
) {
1250 fragment_chain
= data
;
1253 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1254 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1255 printf("ipsec_netif_sync_rx %s: failed to fragment IPv6 packet of length %zu (%d)\n",
1256 pcb
->ipsec_ifp
->if_xname
, length
, fragment_error
);
1262 // Cannot fragment unknown families
1264 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1265 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1266 printf("ipsec_netif_sync_rx %s: uknown legacy decrypted packet length %zu > %u\n",
1267 pcb
->ipsec_ifp
->if_xname
, length
, rx_pp
->pp_buflet_size
);
1272 if (fragment_chain
!= NULL
) {
1273 // Add fragments to chain before continuing
1274 lck_mtx_lock(&pcb
->ipsec_input_chain_lock
);
1275 if (pcb
->ipsec_input_chain
!= NULL
) {
1276 pcb
->ipsec_input_chain_last
->m_nextpkt
= fragment_chain
;
1278 pcb
->ipsec_input_chain
= fragment_chain
;
1280 while (fragment_chain
->m_nextpkt
) {
1281 VERIFY(fragment_chain
!= fragment_chain
->m_nextpkt
);
1282 fragment_chain
= fragment_chain
->m_nextpkt
;
1284 pcb
->ipsec_input_chain_last
= fragment_chain
;
1285 lck_mtx_unlock(&pcb
->ipsec_input_chain_lock
);
1288 // Make sure to free unused rx packet
1289 kern_pbufpool_free(rx_pp
, rx_ph
);
1294 mbuf_pkthdr_setrcvif(data
, pcb
->ipsec_ifp
);
1296 // Fillout rx packet
1297 kern_buflet_t rx_buf
= kern_packet_get_next_buflet(rx_ph
, NULL
);
1298 VERIFY(rx_buf
!= NULL
);
1299 void *rx_baddr
= kern_buflet_get_object_address(rx_buf
);
1300 VERIFY(rx_baddr
!= NULL
);
1302 // Copy-in data from mbuf to buflet
1303 mbuf_copydata(data
, 0, length
, (void *)rx_baddr
);
1304 kern_packet_clear_flow_uuid(rx_ph
); // Zero flow id
1306 // Finalize and attach the packet
1307 error
= kern_buflet_set_data_offset(rx_buf
, 0);
1309 error
= kern_buflet_set_data_length(rx_buf
, length
);
1311 error
= kern_packet_set_link_header_offset(rx_ph
, 0);
1313 error
= kern_packet_set_network_header_offset(rx_ph
, 0);
1315 error
= kern_packet_finalize(rx_ph
);
1317 error
= kern_channel_slot_attach_packet(rx_ring
, rx_slot
, rx_ph
);
1320 STATS_INC(nifs
, NETIF_STATS_RXPKTS
);
1321 STATS_INC(nifs
, NETIF_STATS_RXCOPY_MBUF
);
1322 bpf_tap_packet_in(pcb
->ipsec_ifp
, DLT_RAW
, rx_ph
, NULL
, 0);
1324 rx_ring_stats
.kcrsi_slots_transferred
++;
1325 rx_ring_stats
.kcrsi_bytes_transferred
+= length
;
1327 if (!pcb
->ipsec_ext_ifdata_stats
) {
1328 ifnet_stat_increment_in(pcb
->ipsec_ifp
, 1, length
, 0);
1335 rx_slot
= kern_channel_get_next_slot(rx_ring
, rx_slot
, NULL
);
1338 struct kern_channel_ring_stat_increment tx_ring_stats
;
1339 bzero(&tx_ring_stats
, sizeof(tx_ring_stats
));
1340 kern_channel_ring_t tx_ring
= pcb
->ipsec_kpipe_txring
;
1341 kern_channel_slot_t tx_pslot
= NULL
;
1342 kern_channel_slot_t tx_slot
= NULL
;
1343 if (tx_ring
== NULL
) {
1344 // Net-If TX ring not set up yet, nothing to read
1349 // Unlock ipsec before entering ring
1350 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
1352 (void)kr_enter(tx_ring
, TRUE
);
1354 // Lock again after entering and validate
1355 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
1357 if (tx_ring
!= pcb
->ipsec_kpipe_txring
) {
1361 tx_slot
= kern_channel_get_next_slot(tx_ring
, NULL
, NULL
);
1362 if (tx_slot
== NULL
) {
1363 // Nothing to read, don't bother signalling
1367 while (rx_slot
!= NULL
&& tx_slot
!= NULL
) {
1373 // Allocate rx packet
1374 kern_packet_t rx_ph
= 0;
1375 error
= kern_pbufpool_alloc_nosleep(rx_pp
, 1, &rx_ph
);
1376 if (__improbable(error
!= 0)) {
1377 STATS_INC(nifs
, NETIF_STATS_NOMEM_PKT
);
1378 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1382 kern_packet_t tx_ph
= kern_channel_slot_get_packet(tx_ring
, tx_slot
);
1386 tx_slot
= kern_channel_get_next_slot(tx_ring
, tx_slot
, NULL
);
1389 kern_pbufpool_free(rx_pp
, rx_ph
);
1393 kern_buflet_t tx_buf
= kern_packet_get_next_buflet(tx_ph
, NULL
);
1394 VERIFY(tx_buf
!= NULL
);
1395 uint8_t *tx_baddr
= kern_buflet_get_object_address(tx_buf
);
1396 VERIFY(tx_baddr
!= 0);
1397 tx_baddr
+= kern_buflet_get_data_offset(tx_buf
);
1399 length
= MIN(kern_packet_get_data_length(tx_ph
),
1400 pcb
->ipsec_slot_size
);
1402 // Increment TX stats
1403 tx_ring_stats
.kcrsi_slots_transferred
++;
1404 tx_ring_stats
.kcrsi_bytes_transferred
+= length
;
1406 if (length
>= sizeof(struct ip
)) {
1407 error
= mbuf_gethdr(MBUF_DONTWAIT
, MBUF_TYPE_HEADER
, &data
);
1409 error
= mbuf_copyback(data
, 0, length
, tx_baddr
, MBUF_DONTWAIT
);
1411 struct ip
*ip
= mtod(data
, struct ip
*);
1412 u_int ip_version
= ip
->ip_v
;
1413 switch (ip_version
) {
1416 ip
->ip_len
= ntohs(ip
->ip_len
) - sizeof(struct ip
);
1417 ip
->ip_off
= ntohs(ip
->ip_off
);
1419 if (length
< ip
->ip_len
) {
1420 printf("ipsec_netif_sync_rx %s: IPv4 packet length too short (%zu < %u)\n",
1421 pcb
->ipsec_ifp
->if_xname
, length
, ip
->ip_len
);
1422 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1423 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1427 data
= esp4_input_extended(data
, sizeof(struct ip
), pcb
->ipsec_ifp
);
1432 if (length
< sizeof(struct ip6_hdr
)) {
1433 printf("ipsec_netif_sync_rx %s: IPv6 packet length too short for header %zu\n",
1434 pcb
->ipsec_ifp
->if_xname
, length
);
1435 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1436 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1441 struct ip6_hdr
*ip6
= mtod(data
, struct ip6_hdr
*);
1442 const size_t ip6_len
= sizeof(*ip6
) + ntohs(ip6
->ip6_plen
);
1443 if (length
< ip6_len
) {
1444 printf("ipsec_netif_sync_rx %s: IPv6 packet length too short (%zu < %zu)\n",
1445 pcb
->ipsec_ifp
->if_xname
, length
, ip6_len
);
1446 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1447 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1451 int offset
= sizeof(struct ip6_hdr
);
1452 esp6_input_extended(&data
, &offset
, ip6
->ip6_nxt
, pcb
->ipsec_ifp
);
1458 printf("ipsec_netif_sync_rx %s: unknown ip version %u\n",
1459 pcb
->ipsec_ifp
->if_xname
, ip_version
);
1460 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1467 printf("ipsec_netif_sync_rx %s - mbuf_copyback(%zu) error %d\n", pcb
->ipsec_ifp
->if_xname
, length
, error
);
1468 STATS_INC(nifs
, NETIF_STATS_NOMEM_MBUF
);
1469 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1474 printf("ipsec_netif_sync_rx %s - mbuf_gethdr error %d\n", pcb
->ipsec_ifp
->if_xname
, error
);
1475 STATS_INC(nifs
, NETIF_STATS_NOMEM_MBUF
);
1476 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1479 printf("ipsec_netif_sync_rx %s - bad packet length %zu\n", pcb
->ipsec_ifp
->if_xname
, length
);
1480 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1481 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1485 // Failed to get decrypted data data
1486 kern_pbufpool_free(rx_pp
, rx_ph
);
1490 length
= mbuf_pkthdr_len(data
);
1491 if (length
> rx_pp
->pp_buflet_size
) {
1494 kern_pbufpool_free(rx_pp
, rx_ph
);
1495 STATS_INC(nifs
, NETIF_STATS_BADLEN
);
1496 STATS_INC(nifs
, NETIF_STATS_DROPPED
);
1497 printf("ipsec_netif_sync_rx %s: decrypted packet length %zu > %u\n",
1498 pcb
->ipsec_ifp
->if_xname
, length
, rx_pp
->pp_buflet_size
);
1502 mbuf_pkthdr_setrcvif(data
, pcb
->ipsec_ifp
);
1504 // Fillout rx packet
1505 kern_buflet_t rx_buf
= kern_packet_get_next_buflet(rx_ph
, NULL
);
1506 VERIFY(rx_buf
!= NULL
);
1507 void *rx_baddr
= kern_buflet_get_object_address(rx_buf
);
1508 VERIFY(rx_baddr
!= NULL
);
1510 // Copy-in data from mbuf to buflet
1511 mbuf_copydata(data
, 0, length
, (void *)rx_baddr
);
1512 kern_packet_clear_flow_uuid(rx_ph
); // Zero flow id
1514 // Finalize and attach the packet
1515 error
= kern_buflet_set_data_offset(rx_buf
, 0);
1517 error
= kern_buflet_set_data_length(rx_buf
, length
);
1519 error
= kern_packet_set_link_header_offset(rx_ph
, 0);
1521 error
= kern_packet_set_network_header_offset(rx_ph
, 0);
1523 error
= kern_packet_finalize(rx_ph
);
1525 error
= kern_channel_slot_attach_packet(rx_ring
, rx_slot
, rx_ph
);
1528 STATS_INC(nifs
, NETIF_STATS_RXPKTS
);
1529 STATS_INC(nifs
, NETIF_STATS_RXCOPY_DIRECT
);
1530 bpf_tap_packet_in(pcb
->ipsec_ifp
, DLT_RAW
, rx_ph
, NULL
, 0);
1532 rx_ring_stats
.kcrsi_slots_transferred
++;
1533 rx_ring_stats
.kcrsi_bytes_transferred
+= length
;
1535 if (!pcb
->ipsec_ext_ifdata_stats
) {
1536 ifnet_stat_increment_in(pcb
->ipsec_ifp
, 1, length
, 0);
1542 rx_slot
= kern_channel_get_next_slot(rx_ring
, rx_slot
, NULL
);
1547 kern_channel_advance_slot(rx_ring
, rx_pslot
);
1548 kern_channel_increment_ring_net_stats(rx_ring
, pcb
->ipsec_ifp
, &rx_ring_stats
);
1552 kern_channel_advance_slot(tx_ring
, tx_pslot
);
1553 kern_channel_increment_ring_net_stats(tx_ring
, pcb
->ipsec_ifp
, &tx_ring_stats
);
1554 (void)kern_channel_reclaim(tx_ring
);
1557 // Unlock first, then exit ring
1558 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
1559 if (tx_ring
!= NULL
) {
1560 if (tx_pslot
!= NULL
) {
1561 kern_channel_notify(tx_ring
, 0);
1570 ipsec_nexus_ifattach(struct ipsec_pcb
*pcb
,
1571 struct ifnet_init_eparams
*init_params
,
1575 nexus_controller_t controller
= kern_nexus_shared_controller();
1576 struct kern_nexus_net_init net_init
;
1577 struct kern_pbufpool_init pp_init
;
1579 nexus_name_t provider_name
;
1580 snprintf((char *)provider_name
, sizeof(provider_name
),
1581 "com.apple.netif.%s", pcb
->ipsec_if_xname
);
1583 struct kern_nexus_provider_init prov_init
= {
1584 .nxpi_version
= KERN_NEXUS_DOMAIN_PROVIDER_CURRENT_VERSION
,
1585 .nxpi_flags
= NXPIF_VIRTUAL_DEVICE
,
1586 .nxpi_pre_connect
= ipsec_nexus_pre_connect
,
1587 .nxpi_connected
= ipsec_nexus_connected
,
1588 .nxpi_pre_disconnect
= ipsec_netif_pre_disconnect
,
1589 .nxpi_disconnected
= ipsec_nexus_disconnected
,
1590 .nxpi_ring_init
= ipsec_netif_ring_init
,
1591 .nxpi_ring_fini
= ipsec_netif_ring_fini
,
1592 .nxpi_slot_init
= NULL
,
1593 .nxpi_slot_fini
= NULL
,
1594 .nxpi_sync_tx
= ipsec_netif_sync_tx
,
1595 .nxpi_sync_rx
= ipsec_netif_sync_rx
,
1596 .nxpi_tx_doorbell
= ipsec_netif_tx_doorbell
,
1599 nexus_attr_t nxa
= NULL
;
1600 err
= kern_nexus_attr_create(&nxa
);
1601 IPSEC_IF_VERIFY(err
== 0);
1603 printf("%s: kern_nexus_attr_create failed: %d\n",
1608 uint64_t slot_buffer_size
= pcb
->ipsec_slot_size
;
1609 err
= kern_nexus_attr_set(nxa
, NEXUS_ATTR_SLOT_BUF_SIZE
, slot_buffer_size
);
1612 // Reset ring size for netif nexus to limit memory usage
1613 uint64_t ring_size
= pcb
->ipsec_netif_ring_size
;
1614 err
= kern_nexus_attr_set(nxa
, NEXUS_ATTR_TX_SLOTS
, ring_size
);
1616 err
= kern_nexus_attr_set(nxa
, NEXUS_ATTR_RX_SLOTS
, ring_size
);
1619 pcb
->ipsec_netif_txring_size
= ring_size
;
1621 bzero(&pp_init
, sizeof (pp_init
));
1622 pp_init
.kbi_version
= KERN_PBUFPOOL_CURRENT_VERSION
;
1623 pp_init
.kbi_packets
= pcb
->ipsec_netif_ring_size
* 2;
1624 pp_init
.kbi_bufsize
= pcb
->ipsec_slot_size
;
1625 pp_init
.kbi_buf_seg_size
= IPSEC_IF_DEFAULT_BUF_SEG_SIZE
;
1626 pp_init
.kbi_max_frags
= 1;
1627 (void) snprintf((char *)pp_init
.kbi_name
, sizeof (pp_init
.kbi_name
),
1628 "%s", provider_name
);
1630 err
= kern_pbufpool_create(&pp_init
, &pp_init
, &pcb
->ipsec_netif_pp
, NULL
);
1632 printf("%s pbufbool create failed, error %d\n", __func__
, err
);
1636 err
= kern_nexus_controller_register_provider(controller
,
1642 &pcb
->ipsec_nx
.if_provider
);
1643 IPSEC_IF_VERIFY(err
== 0);
1645 printf("%s register provider failed, error %d\n",
1650 bzero(&net_init
, sizeof(net_init
));
1651 net_init
.nxneti_version
= KERN_NEXUS_NET_CURRENT_VERSION
;
1652 net_init
.nxneti_flags
= 0;
1653 net_init
.nxneti_eparams
= init_params
;
1654 net_init
.nxneti_lladdr
= NULL
;
1655 net_init
.nxneti_prepare
= ipsec_netif_prepare
;
1656 net_init
.nxneti_tx_pbufpool
= pcb
->ipsec_netif_pp
;
1657 err
= kern_nexus_controller_alloc_net_provider_instance(controller
,
1658 pcb
->ipsec_nx
.if_provider
,
1660 &pcb
->ipsec_nx
.if_instance
,
1663 IPSEC_IF_VERIFY(err
== 0);
1665 printf("%s alloc_net_provider_instance failed, %d\n",
1667 kern_nexus_controller_deregister_provider(controller
,
1668 pcb
->ipsec_nx
.if_provider
);
1669 uuid_clear(pcb
->ipsec_nx
.if_provider
);
1675 kern_nexus_attr_destroy(nxa
);
1677 if (err
&& pcb
->ipsec_netif_pp
!= NULL
) {
1678 kern_pbufpool_destroy(pcb
->ipsec_netif_pp
);
1679 pcb
->ipsec_netif_pp
= NULL
;
1685 ipsec_detach_provider_and_instance(uuid_t provider
, uuid_t instance
)
1687 nexus_controller_t controller
= kern_nexus_shared_controller();
1690 if (!uuid_is_null(instance
)) {
1691 err
= kern_nexus_controller_free_provider_instance(controller
,
1694 printf("%s free_provider_instance failed %d\n",
1697 uuid_clear(instance
);
1699 if (!uuid_is_null(provider
)) {
1700 err
= kern_nexus_controller_deregister_provider(controller
,
1703 printf("%s deregister_provider %d\n", __func__
, err
);
1705 uuid_clear(provider
);
1711 ipsec_nexus_detach(struct ipsec_pcb
*pcb
)
1713 ipsec_nx_t nx
= &pcb
->ipsec_nx
;
1714 nexus_controller_t controller
= kern_nexus_shared_controller();
1717 if (!uuid_is_null(nx
->ms_host
)) {
1718 err
= kern_nexus_ifdetach(controller
,
1722 printf("%s: kern_nexus_ifdetach ms host failed %d\n",
1727 if (!uuid_is_null(nx
->ms_device
)) {
1728 err
= kern_nexus_ifdetach(controller
,
1732 printf("%s: kern_nexus_ifdetach ms device failed %d\n",
1737 ipsec_detach_provider_and_instance(nx
->if_provider
,
1739 ipsec_detach_provider_and_instance(nx
->ms_provider
,
1742 if (pcb
->ipsec_netif_pp
!= NULL
) {
1743 kern_pbufpool_destroy(pcb
->ipsec_netif_pp
);
1744 pcb
->ipsec_netif_pp
= NULL
;
1747 memset(nx
, 0, sizeof(*nx
));
1751 ipsec_create_fs_provider_and_instance(struct ipsec_pcb
*pcb
,
1752 uint32_t subtype
, const char *type_name
,
1754 uuid_t
*provider
, uuid_t
*instance
)
1756 nexus_attr_t attr
= NULL
;
1757 nexus_controller_t controller
= kern_nexus_shared_controller();
1760 struct kern_nexus_init init
;
1761 nexus_name_t provider_name
;
1763 err
= kern_nexus_get_builtin_domain_provider(NEXUS_TYPE_FLOW_SWITCH
,
1765 IPSEC_IF_VERIFY(err
== 0);
1767 printf("%s can't get %s provider, error %d\n",
1768 __func__
, type_name
, err
);
1772 err
= kern_nexus_attr_create(&attr
);
1773 IPSEC_IF_VERIFY(err
== 0);
1775 printf("%s: kern_nexus_attr_create failed: %d\n",
1780 err
= kern_nexus_attr_set(attr
, NEXUS_ATTR_EXTENSIONS
, subtype
);
1783 uint64_t slot_buffer_size
= pcb
->ipsec_slot_size
;
1784 err
= kern_nexus_attr_set(attr
, NEXUS_ATTR_SLOT_BUF_SIZE
, slot_buffer_size
);
1787 // Reset ring size for flowswitch nexus to limit memory usage. Larger RX than netif.
1788 uint64_t tx_ring_size
= pcb
->ipsec_tx_fsw_ring_size
;
1789 err
= kern_nexus_attr_set(attr
, NEXUS_ATTR_TX_SLOTS
, tx_ring_size
);
1791 uint64_t rx_ring_size
= pcb
->ipsec_rx_fsw_ring_size
;
1792 err
= kern_nexus_attr_set(attr
, NEXUS_ATTR_RX_SLOTS
, rx_ring_size
);
1795 snprintf((char *)provider_name
, sizeof(provider_name
),
1796 "com.apple.%s.%s", type_name
, ifname
);
1797 err
= kern_nexus_controller_register_provider(controller
,
1804 kern_nexus_attr_destroy(attr
);
1806 IPSEC_IF_VERIFY(err
== 0);
1808 printf("%s register %s provider failed, error %d\n",
1809 __func__
, type_name
, err
);
1812 bzero(&init
, sizeof (init
));
1813 init
.nxi_version
= KERN_NEXUS_CURRENT_VERSION
;
1814 err
= kern_nexus_controller_alloc_provider_instance(controller
,
1818 IPSEC_IF_VERIFY(err
== 0);
1820 printf("%s alloc_provider_instance %s failed, %d\n",
1821 __func__
, type_name
, err
);
1822 kern_nexus_controller_deregister_provider(controller
,
1824 uuid_clear(*provider
);
1831 ipsec_multistack_attach(struct ipsec_pcb
*pcb
)
1833 nexus_controller_t controller
= kern_nexus_shared_controller();
1835 ipsec_nx_t nx
= &pcb
->ipsec_nx
;
1837 // Allocate multistack flowswitch
1838 err
= ipsec_create_fs_provider_and_instance(pcb
,
1839 NEXUS_EXTENSION_FSW_TYPE_MULTISTACK
,
1841 pcb
->ipsec_ifp
->if_xname
,
1845 printf("%s: failed to create bridge provider and instance\n",
1850 // Attach multistack to device port
1851 err
= kern_nexus_ifattach(controller
, nx
->ms_instance
,
1852 NULL
, nx
->if_instance
,
1853 FALSE
, &nx
->ms_device
);
1855 printf("%s kern_nexus_ifattach ms device %d\n", __func__
, err
);
1859 // Attach multistack to host port
1860 err
= kern_nexus_ifattach(controller
, nx
->ms_instance
,
1861 NULL
, nx
->if_instance
,
1862 TRUE
, &nx
->ms_host
);
1864 printf("%s kern_nexus_ifattach ms host %d\n", __func__
, err
);
1868 // Extract the agent UUID and save for later
1869 struct kern_nexus
*multistack_nx
= nx_find(nx
->ms_instance
, false);
1870 if (multistack_nx
!= NULL
) {
1871 struct nx_flowswitch
*flowswitch
= NX_FSW_PRIVATE(multistack_nx
);
1872 if (flowswitch
!= NULL
) {
1873 FSW_RLOCK(flowswitch
);
1874 struct fsw_ms_context
*ms_context
= (struct fsw_ms_context
*)flowswitch
->fsw_ops_private
;
1875 if (ms_context
!= NULL
) {
1876 uuid_copy(nx
->ms_agent
, ms_context
->mc_agent_uuid
);
1878 printf("ipsec_multistack_attach - fsw_ms_context is NULL\n");
1880 FSW_UNLOCK(flowswitch
);
1882 printf("ipsec_multistack_attach - flowswitch is NULL\n");
1884 nx_release(multistack_nx
);
1886 printf("ipsec_multistack_attach - unable to find multistack nexus\n");
1892 ipsec_nexus_detach(pcb
);
1894 errno_t detach_error
= 0;
1895 if ((detach_error
= ifnet_detach(pcb
->ipsec_ifp
)) != 0) {
1896 panic("ipsec_multistack_attach - ifnet_detach failed: %d\n", detach_error
);
1903 #pragma mark Kernel Pipe Nexus
1906 ipsec_register_kernel_pipe_nexus(void)
1908 nexus_attr_t nxa
= NULL
;
1911 lck_mtx_lock(&ipsec_lock
);
1912 if (ipsec_ncd_refcount
++) {
1913 lck_mtx_unlock(&ipsec_lock
);
1917 result
= kern_nexus_controller_create(&ipsec_ncd
);
1919 printf("%s: kern_nexus_controller_create failed: %d\n",
1920 __FUNCTION__
, result
);
1925 result
= kern_nexus_get_builtin_domain_provider(
1926 NEXUS_TYPE_KERNEL_PIPE
, &dom_prov
);
1928 printf("%s: kern_nexus_get_builtin_domain_provider failed: %d\n",
1929 __FUNCTION__
, result
);
1933 struct kern_nexus_provider_init prov_init
= {
1934 .nxpi_version
= KERN_NEXUS_DOMAIN_PROVIDER_CURRENT_VERSION
,
1935 .nxpi_flags
= NXPIF_VIRTUAL_DEVICE
,
1936 .nxpi_pre_connect
= ipsec_nexus_pre_connect
,
1937 .nxpi_connected
= ipsec_nexus_connected
,
1938 .nxpi_pre_disconnect
= ipsec_nexus_pre_disconnect
,
1939 .nxpi_disconnected
= ipsec_nexus_disconnected
,
1940 .nxpi_ring_init
= ipsec_kpipe_ring_init
,
1941 .nxpi_ring_fini
= ipsec_kpipe_ring_fini
,
1942 .nxpi_slot_init
= NULL
,
1943 .nxpi_slot_fini
= NULL
,
1944 .nxpi_sync_tx
= ipsec_kpipe_sync_tx
,
1945 .nxpi_sync_rx
= ipsec_kpipe_sync_rx
,
1946 .nxpi_tx_doorbell
= NULL
,
1949 result
= kern_nexus_attr_create(&nxa
);
1951 printf("%s: kern_nexus_attr_create failed: %d\n",
1952 __FUNCTION__
, result
);
1956 uint64_t slot_buffer_size
= IPSEC_IF_DEFAULT_SLOT_SIZE
;
1957 result
= kern_nexus_attr_set(nxa
, NEXUS_ATTR_SLOT_BUF_SIZE
, slot_buffer_size
);
1958 VERIFY(result
== 0);
1960 // Reset ring size for kernel pipe nexus to limit memory usage
1961 uint64_t ring_size
= if_ipsec_ring_size
;
1962 result
= kern_nexus_attr_set(nxa
, NEXUS_ATTR_TX_SLOTS
, ring_size
);
1963 VERIFY(result
== 0);
1964 result
= kern_nexus_attr_set(nxa
, NEXUS_ATTR_RX_SLOTS
, ring_size
);
1965 VERIFY(result
== 0);
1967 result
= kern_nexus_controller_register_provider(ipsec_ncd
,
1969 (const uint8_t *)"com.apple.nexus.ipsec.kpipe",
1975 printf("%s: kern_nexus_controller_register_provider failed: %d\n",
1976 __FUNCTION__
, result
);
1982 kern_nexus_attr_destroy(nxa
);
1987 kern_nexus_controller_destroy(ipsec_ncd
);
1990 ipsec_ncd_refcount
= 0;
1993 lck_mtx_unlock(&ipsec_lock
);
1999 ipsec_unregister_kernel_pipe_nexus(void)
2001 lck_mtx_lock(&ipsec_lock
);
2003 VERIFY(ipsec_ncd_refcount
> 0);
2005 if (--ipsec_ncd_refcount
== 0) {
2006 kern_nexus_controller_destroy(ipsec_ncd
);
2010 lck_mtx_unlock(&ipsec_lock
);
2013 // For use by socket option, not internally
2015 ipsec_disable_channel(struct ipsec_pcb
*pcb
)
2021 lck_rw_lock_exclusive(&pcb
->ipsec_pcb_lock
);
2023 enabled
= pcb
->ipsec_kpipe_enabled
;
2024 uuid_copy(uuid
, pcb
->ipsec_kpipe_uuid
);
2026 VERIFY(uuid_is_null(pcb
->ipsec_kpipe_uuid
) == !enabled
);
2028 pcb
->ipsec_kpipe_enabled
= 0;
2029 uuid_clear(pcb
->ipsec_kpipe_uuid
);
2031 lck_rw_unlock_exclusive(&pcb
->ipsec_pcb_lock
);
2034 result
= kern_nexus_controller_free_provider_instance(ipsec_ncd
, uuid
);
2040 if (pcb
->ipsec_kpipe_pp
!= NULL
) {
2041 kern_pbufpool_destroy(pcb
->ipsec_kpipe_pp
);
2042 pcb
->ipsec_kpipe_pp
= NULL
;
2044 ipsec_unregister_kernel_pipe_nexus();
2051 ipsec_enable_channel(struct ipsec_pcb
*pcb
, struct proc
*proc
)
2053 struct kern_nexus_init init
;
2054 struct kern_pbufpool_init pp_init
;
2057 result
= ipsec_register_kernel_pipe_nexus();
2064 lck_rw_lock_exclusive(&pcb
->ipsec_pcb_lock
);
2066 /* ipsec driver doesn't support channels without a netif */
2067 if (!pcb
->ipsec_use_netif
) {
2068 result
= EOPNOTSUPP
;
2072 if (pcb
->ipsec_kpipe_enabled
) {
2073 result
= EEXIST
; // return success instead?
2077 bzero(&pp_init
, sizeof (pp_init
));
2078 pp_init
.kbi_version
= KERN_PBUFPOOL_CURRENT_VERSION
;
2079 pp_init
.kbi_packets
= pcb
->ipsec_netif_ring_size
* 2;
2080 pp_init
.kbi_bufsize
= pcb
->ipsec_slot_size
;
2081 pp_init
.kbi_buf_seg_size
= IPSEC_IF_DEFAULT_BUF_SEG_SIZE
;
2082 pp_init
.kbi_max_frags
= 1;
2083 pp_init
.kbi_flags
|= KBIF_QUANTUM
;
2084 (void) snprintf((char *)pp_init
.kbi_name
, sizeof (pp_init
.kbi_name
),
2085 "com.apple.kpipe.%s", pcb
->ipsec_if_xname
);
2087 result
= kern_pbufpool_create(&pp_init
, &pp_init
, &pcb
->ipsec_kpipe_pp
,
2090 printf("%s pbufbool create failed, error %d\n", __func__
, result
);
2094 VERIFY(uuid_is_null(pcb
->ipsec_kpipe_uuid
));
2095 bzero(&init
, sizeof (init
));
2096 init
.nxi_version
= KERN_NEXUS_CURRENT_VERSION
;
2097 init
.nxi_tx_pbufpool
= pcb
->ipsec_kpipe_pp
;
2098 result
= kern_nexus_controller_alloc_provider_instance(ipsec_ncd
,
2099 ipsec_kpipe_uuid
, pcb
, &pcb
->ipsec_kpipe_uuid
, &init
);
2104 nexus_port_t port
= NEXUS_PORT_KERNEL_PIPE_CLIENT
;
2105 result
= kern_nexus_controller_bind_provider_instance(ipsec_ncd
,
2106 pcb
->ipsec_kpipe_uuid
, &port
,
2107 proc_pid(proc
), NULL
, NULL
, 0, NEXUS_BIND_PID
);
2109 kern_nexus_controller_free_provider_instance(ipsec_ncd
,
2110 pcb
->ipsec_kpipe_uuid
);
2111 uuid_clear(pcb
->ipsec_kpipe_uuid
);
2115 pcb
->ipsec_kpipe_enabled
= 1;
2118 lck_rw_unlock_exclusive(&pcb
->ipsec_pcb_lock
);
2121 if (pcb
->ipsec_kpipe_pp
!= NULL
) {
2122 kern_pbufpool_destroy(pcb
->ipsec_kpipe_pp
);
2123 pcb
->ipsec_kpipe_pp
= NULL
;
2125 ipsec_unregister_kernel_pipe_nexus();
2131 #endif // IPSEC_NEXUS
2134 /* Kernel control functions */
2137 ipsec_free_pcb(struct ipsec_pcb
*pcb
, bool in_list
)
2140 mbuf_freem_list(pcb
->ipsec_input_chain
);
2141 lck_mtx_destroy(&pcb
->ipsec_input_chain_lock
, ipsec_lck_grp
);
2142 #endif // IPSEC_NEXUS
2143 lck_rw_destroy(&pcb
->ipsec_pcb_lock
, ipsec_lck_grp
);
2145 lck_mtx_lock(&ipsec_lock
);
2146 TAILQ_REMOVE(&ipsec_head
, pcb
, ipsec_chain
);
2147 lck_mtx_unlock(&ipsec_lock
);
2149 zfree(ipsec_pcb_zone
, pcb
);
2153 ipsec_ctl_bind(kern_ctl_ref kctlref
,
2154 struct sockaddr_ctl
*sac
,
2157 struct ipsec_pcb
*pcb
= zalloc(ipsec_pcb_zone
);
2158 memset(pcb
, 0, sizeof(*pcb
));
2160 /* Setup the protocol control block */
2162 pcb
->ipsec_ctlref
= kctlref
;
2163 pcb
->ipsec_unit
= sac
->sc_unit
;
2164 pcb
->ipsec_output_service_class
= MBUF_SC_OAM
;
2167 pcb
->ipsec_use_netif
= false;
2168 pcb
->ipsec_slot_size
= IPSEC_IF_DEFAULT_SLOT_SIZE
;
2169 pcb
->ipsec_netif_ring_size
= IPSEC_IF_DEFAULT_RING_SIZE
;
2170 pcb
->ipsec_tx_fsw_ring_size
= IPSEC_IF_DEFAULT_TX_FSW_RING_SIZE
;
2171 pcb
->ipsec_rx_fsw_ring_size
= IPSEC_IF_DEFAULT_RX_FSW_RING_SIZE
;
2172 #endif // IPSEC_NEXUS
2174 lck_rw_init(&pcb
->ipsec_pcb_lock
, ipsec_lck_grp
, ipsec_lck_attr
);
2176 lck_mtx_init(&pcb
->ipsec_input_chain_lock
, ipsec_lck_grp
, ipsec_lck_attr
);
2177 #endif // IPSEC_NEXUS
2183 ipsec_ctl_connect(kern_ctl_ref kctlref
,
2184 struct sockaddr_ctl
*sac
,
2187 struct ifnet_init_eparams ipsec_init
= {};
2190 if (*unitinfo
== NULL
) {
2191 (void)ipsec_ctl_bind(kctlref
, sac
, unitinfo
);
2194 struct ipsec_pcb
*pcb
= *unitinfo
;
2196 lck_mtx_lock(&ipsec_lock
);
2198 /* Find some open interface id */
2199 u_int32_t chosen_unique_id
= 1;
2200 struct ipsec_pcb
*next_pcb
= TAILQ_LAST(&ipsec_head
, ipsec_list
);
2201 if (next_pcb
!= NULL
) {
2202 /* List was not empty, add one to the last item */
2203 chosen_unique_id
= next_pcb
->ipsec_unique_id
+ 1;
2207 * If this wrapped the id number, start looking at
2208 * the front of the list for an unused id.
2210 if (chosen_unique_id
== 0) {
2211 /* Find the next unused ID */
2212 chosen_unique_id
= 1;
2213 TAILQ_FOREACH(next_pcb
, &ipsec_head
, ipsec_chain
) {
2214 if (next_pcb
->ipsec_unique_id
> chosen_unique_id
) {
2215 /* We found a gap */
2219 chosen_unique_id
= next_pcb
->ipsec_unique_id
+ 1;
2224 pcb
->ipsec_unique_id
= chosen_unique_id
;
2226 if (next_pcb
!= NULL
) {
2227 TAILQ_INSERT_BEFORE(next_pcb
, pcb
, ipsec_chain
);
2229 TAILQ_INSERT_TAIL(&ipsec_head
, pcb
, ipsec_chain
);
2231 lck_mtx_unlock(&ipsec_lock
);
2233 snprintf(pcb
->ipsec_if_xname
, sizeof(pcb
->ipsec_if_xname
), "ipsec%d", pcb
->ipsec_unit
- 1);
2234 snprintf(pcb
->ipsec_unique_name
, sizeof(pcb
->ipsec_unique_name
), "ipsecid%d", pcb
->ipsec_unique_id
- 1);
2235 printf("ipsec_ctl_connect: creating interface %s (id %s)\n", pcb
->ipsec_if_xname
, pcb
->ipsec_unique_name
);
2237 /* Create the interface */
2238 bzero(&ipsec_init
, sizeof(ipsec_init
));
2239 ipsec_init
.ver
= IFNET_INIT_CURRENT_VERSION
;
2240 ipsec_init
.len
= sizeof (ipsec_init
);
2243 if (pcb
->ipsec_use_netif
) {
2244 ipsec_init
.flags
= (IFNET_INIT_SKYWALK_NATIVE
| IFNET_INIT_NX_NOAUTO
);
2246 #endif // IPSEC_NEXUS
2248 ipsec_init
.flags
= IFNET_INIT_NX_NOAUTO
;
2249 ipsec_init
.start
= ipsec_start
;
2251 ipsec_init
.name
= "ipsec";
2252 ipsec_init
.unit
= pcb
->ipsec_unit
- 1;
2253 ipsec_init
.uniqueid
= pcb
->ipsec_unique_name
;
2254 ipsec_init
.uniqueid_len
= strlen(pcb
->ipsec_unique_name
);
2255 ipsec_init
.family
= ipsec_family
;
2256 ipsec_init
.subfamily
= IFNET_SUBFAMILY_IPSEC
;
2257 ipsec_init
.type
= IFT_OTHER
;
2258 ipsec_init
.demux
= ipsec_demux
;
2259 ipsec_init
.add_proto
= ipsec_add_proto
;
2260 ipsec_init
.del_proto
= ipsec_del_proto
;
2261 ipsec_init
.softc
= pcb
;
2262 ipsec_init
.ioctl
= ipsec_ioctl
;
2263 ipsec_init
.detach
= ipsec_detached
;
2266 if (pcb
->ipsec_use_netif
) {
2267 result
= ipsec_nexus_ifattach(pcb
, &ipsec_init
, &pcb
->ipsec_ifp
);
2269 printf("ipsec_ctl_connect - ipsec_nexus_ifattach failed: %d\n", result
);
2270 ipsec_free_pcb(pcb
, true);
2275 result
= ipsec_multistack_attach(pcb
);
2277 printf("ipsec_ctl_connect - ipsec_multistack_attach failed: %d\n", result
);
2283 bpfattach(pcb
->ipsec_ifp
, DLT_RAW
, 0);
2285 #endif // IPSEC_NEXUS
2287 result
= ifnet_allocate_extended(&ipsec_init
, &pcb
->ipsec_ifp
);
2289 printf("ipsec_ctl_connect - ifnet_allocate failed: %d\n", result
);
2290 ipsec_free_pcb(pcb
, true);
2294 ipsec_ifnet_set_attrs(pcb
->ipsec_ifp
);
2296 /* Attach the interface */
2297 result
= ifnet_attach(pcb
->ipsec_ifp
, NULL
);
2299 printf("ipsec_ctl_connect - ifnet_attach failed: %d\n", result
);
2300 ifnet_release(pcb
->ipsec_ifp
);
2301 ipsec_free_pcb(pcb
, true);
2307 bpfattach(pcb
->ipsec_ifp
, DLT_NULL
, 0);
2310 /* The interfaces resoures allocated, mark it as running */
2311 ifnet_set_flags(pcb
->ipsec_ifp
, IFF_RUNNING
, IFF_RUNNING
);
2317 ipsec_detach_ip(ifnet_t interface
,
2318 protocol_family_t protocol
,
2321 errno_t result
= EPROTONOSUPPORT
;
2323 /* Attempt a detach */
2324 if (protocol
== PF_INET
) {
2327 bzero(&ifr
, sizeof(ifr
));
2328 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
2329 ifnet_name(interface
), ifnet_unit(interface
));
2331 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH
, &ifr
);
2333 else if (protocol
== PF_INET6
) {
2334 struct in6_ifreq ifr6
;
2336 bzero(&ifr6
, sizeof(ifr6
));
2337 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
2338 ifnet_name(interface
), ifnet_unit(interface
));
2340 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH_IN6
, &ifr6
);
2347 ipsec_remove_address(ifnet_t interface
,
2348 protocol_family_t protocol
,
2354 /* Attempt a detach */
2355 if (protocol
== PF_INET
) {
2358 bzero(&ifr
, sizeof(ifr
));
2359 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
2360 ifnet_name(interface
), ifnet_unit(interface
));
2361 result
= ifaddr_address(address
, &ifr
.ifr_addr
, sizeof(ifr
.ifr_addr
));
2363 printf("ipsec_remove_address - ifaddr_address failed: %d", result
);
2366 result
= sock_ioctl(pf_socket
, SIOCDIFADDR
, &ifr
);
2368 printf("ipsec_remove_address - SIOCDIFADDR failed: %d", result
);
2372 else if (protocol
== PF_INET6
) {
2373 struct in6_ifreq ifr6
;
2375 bzero(&ifr6
, sizeof(ifr6
));
2376 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
2377 ifnet_name(interface
), ifnet_unit(interface
));
2378 result
= ifaddr_address(address
, (struct sockaddr
*)&ifr6
.ifr_addr
,
2379 sizeof(ifr6
.ifr_addr
));
2381 printf("ipsec_remove_address - ifaddr_address failed (v6): %d",
2385 result
= sock_ioctl(pf_socket
, SIOCDIFADDR_IN6
, &ifr6
);
2387 printf("ipsec_remove_address - SIOCDIFADDR_IN6 failed: %d",
2395 ipsec_cleanup_family(ifnet_t interface
,
2396 protocol_family_t protocol
)
2399 socket_t pf_socket
= NULL
;
2400 ifaddr_t
*addresses
= NULL
;
2403 if (protocol
!= PF_INET
&& protocol
!= PF_INET6
) {
2404 printf("ipsec_cleanup_family - invalid protocol family %d\n", protocol
);
2408 /* Create a socket for removing addresses and detaching the protocol */
2409 result
= sock_socket(protocol
, SOCK_DGRAM
, 0, NULL
, NULL
, &pf_socket
);
2411 if (result
!= EAFNOSUPPORT
)
2412 printf("ipsec_cleanup_family - failed to create %s socket: %d\n",
2413 protocol
== PF_INET
? "IP" : "IPv6", result
);
2417 /* always set SS_PRIV, we want to close and detach regardless */
2418 sock_setpriv(pf_socket
, 1);
2420 result
= ipsec_detach_ip(interface
, protocol
, pf_socket
);
2421 if (result
== 0 || result
== ENXIO
) {
2422 /* We are done! We either detached or weren't attached. */
2425 else if (result
!= EBUSY
) {
2426 /* Uh, not really sure what happened here... */
2427 printf("ipsec_cleanup_family - ipsec_detach_ip failed: %d\n", result
);
2432 * At this point, we received an EBUSY error. This means there are
2433 * addresses attached. We should detach them and then try again.
2435 result
= ifnet_get_address_list_family(interface
, &addresses
, protocol
);
2437 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
2438 ifnet_name(interface
), ifnet_unit(interface
),
2439 protocol
== PF_INET
? "PF_INET" : "PF_INET6", result
);
2443 for (i
= 0; addresses
[i
] != 0; i
++) {
2444 ipsec_remove_address(interface
, protocol
, addresses
[i
], pf_socket
);
2446 ifnet_free_address_list(addresses
);
2450 * The addresses should be gone, we should try the remove again.
2452 result
= ipsec_detach_ip(interface
, protocol
, pf_socket
);
2453 if (result
!= 0 && result
!= ENXIO
) {
2454 printf("ipsec_cleanup_family - ipsec_detach_ip failed: %d\n", result
);
2458 if (pf_socket
!= NULL
)
2459 sock_close(pf_socket
);
2461 if (addresses
!= NULL
)
2462 ifnet_free_address_list(addresses
);
2466 ipsec_ctl_disconnect(__unused kern_ctl_ref kctlref
,
2467 __unused u_int32_t unit
,
2470 struct ipsec_pcb
*pcb
= unitinfo
;
2479 // Tell the nexus to stop all rings
2480 if (pcb
->ipsec_netif_nexus
!= NULL
) {
2481 kern_nexus_stop(pcb
->ipsec_netif_nexus
);
2483 #endif // IPSEC_NEXUS
2485 lck_rw_lock_exclusive(&pcb
->ipsec_pcb_lock
);
2489 uuid_copy(kpipe_uuid
, pcb
->ipsec_kpipe_uuid
);
2490 uuid_clear(pcb
->ipsec_kpipe_uuid
);
2491 pcb
->ipsec_kpipe_enabled
= FALSE
;
2492 #endif // IPSEC_NEXUS
2494 pcb
->ipsec_ctlref
= NULL
;
2496 ifp
= pcb
->ipsec_ifp
;
2499 if (pcb
->ipsec_netif_nexus
!= NULL
) {
2501 * Quiesce the interface and flush any pending outbound packets.
2505 /* Increment refcnt, but detach interface */
2506 ifnet_incr_iorefcnt(ifp
);
2507 if ((result
= ifnet_detach(ifp
)) != 0) {
2508 panic("ipsec_ctl_disconnect - ifnet_detach failed: %d\n", result
);
2513 * We want to do everything in our power to ensure that the interface
2514 * really goes away when the socket is closed. We must remove IP/IPv6
2515 * addresses and detach the protocols. Finally, we can remove and
2516 * release the interface.
2518 key_delsp_for_ipsec_if(ifp
);
2520 ipsec_cleanup_family(ifp
, AF_INET
);
2521 ipsec_cleanup_family(ifp
, AF_INET6
);
2523 lck_rw_unlock_exclusive(&pcb
->ipsec_pcb_lock
);
2525 if (!uuid_is_null(kpipe_uuid
)) {
2526 if (kern_nexus_controller_free_provider_instance(ipsec_ncd
, kpipe_uuid
) == 0) {
2527 if (pcb
->ipsec_kpipe_pp
!= NULL
) {
2528 kern_pbufpool_destroy(pcb
->ipsec_kpipe_pp
);
2529 pcb
->ipsec_kpipe_pp
= NULL
;
2531 ipsec_unregister_kernel_pipe_nexus();
2534 ipsec_nexus_detach(pcb
);
2536 /* Decrement refcnt to finish detaching and freeing */
2537 ifnet_decr_iorefcnt(ifp
);
2539 #endif // IPSEC_NEXUS
2541 lck_rw_unlock_exclusive(&pcb
->ipsec_pcb_lock
);
2544 if (!uuid_is_null(kpipe_uuid
)) {
2545 if (kern_nexus_controller_free_provider_instance(ipsec_ncd
, kpipe_uuid
) == 0) {
2546 if (pcb
->ipsec_kpipe_pp
!= NULL
) {
2547 kern_pbufpool_destroy(pcb
->ipsec_kpipe_pp
);
2548 pcb
->ipsec_kpipe_pp
= NULL
;
2550 ipsec_unregister_kernel_pipe_nexus();
2553 #endif // IPSEC_NEXUS
2556 * We want to do everything in our power to ensure that the interface
2557 * really goes away when the socket is closed. We must remove IP/IPv6
2558 * addresses and detach the protocols. Finally, we can remove and
2559 * release the interface.
2561 key_delsp_for_ipsec_if(ifp
);
2563 ipsec_cleanup_family(ifp
, AF_INET
);
2564 ipsec_cleanup_family(ifp
, AF_INET6
);
2567 * Detach now; ipsec_detach() will be called asynchronously once
2568 * the I/O reference count drops to 0. There we will invoke
2571 if ((result
= ifnet_detach(ifp
)) != 0) {
2572 printf("ipsec_ctl_disconnect - ifnet_detach failed: %d\n", result
);
2576 // Bound, but not connected
2577 lck_rw_unlock_exclusive(&pcb
->ipsec_pcb_lock
);
2578 ipsec_free_pcb(pcb
, false);
2585 ipsec_ctl_send(__unused kern_ctl_ref kctlref
,
2586 __unused u_int32_t unit
,
2587 __unused
void *unitinfo
,
2591 /* Receive messages from the control socket. Currently unused. */
2597 ipsec_ctl_setopt(__unused kern_ctl_ref kctlref
,
2598 __unused u_int32_t unit
,
2604 struct ipsec_pcb
*pcb
= unitinfo
;
2607 /* check for privileges for privileged options */
2609 case IPSEC_OPT_FLAGS
:
2610 case IPSEC_OPT_EXT_IFDATA_STATS
:
2611 case IPSEC_OPT_SET_DELEGATE_INTERFACE
:
2612 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS
:
2613 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
2620 case IPSEC_OPT_FLAGS
:
2621 if (len
!= sizeof(u_int32_t
)) {
2624 pcb
->ipsec_flags
= *(u_int32_t
*)data
;
2628 case IPSEC_OPT_EXT_IFDATA_STATS
:
2629 if (len
!= sizeof(int)) {
2633 if (pcb
->ipsec_ifp
== NULL
) {
2634 // Only can set after connecting
2638 pcb
->ipsec_ext_ifdata_stats
= (*(int *)data
) ? 1 : 0;
2641 case IPSEC_OPT_INC_IFDATA_STATS_IN
:
2642 case IPSEC_OPT_INC_IFDATA_STATS_OUT
: {
2643 struct ipsec_stats_param
*utsp
= (struct ipsec_stats_param
*)data
;
2645 if (utsp
== NULL
|| len
< sizeof(struct ipsec_stats_param
)) {
2649 if (pcb
->ipsec_ifp
== NULL
) {
2650 // Only can set after connecting
2654 if (!pcb
->ipsec_ext_ifdata_stats
) {
2658 if (opt
== IPSEC_OPT_INC_IFDATA_STATS_IN
)
2659 ifnet_stat_increment_in(pcb
->ipsec_ifp
, utsp
->utsp_packets
,
2660 utsp
->utsp_bytes
, utsp
->utsp_errors
);
2662 ifnet_stat_increment_out(pcb
->ipsec_ifp
, utsp
->utsp_packets
,
2663 utsp
->utsp_bytes
, utsp
->utsp_errors
);
2667 case IPSEC_OPT_SET_DELEGATE_INTERFACE
: {
2668 ifnet_t del_ifp
= NULL
;
2669 char name
[IFNAMSIZ
];
2671 if (len
> IFNAMSIZ
- 1) {
2675 if (pcb
->ipsec_ifp
== NULL
) {
2676 // Only can set after connecting
2680 if (len
!= 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */
2681 bcopy(data
, name
, len
);
2683 result
= ifnet_find_by_name(name
, &del_ifp
);
2686 printf("%s IPSEC_OPT_SET_DELEGATE_INTERFACE %s to %s\n",
2687 __func__
, pcb
->ipsec_ifp
->if_xname
,
2690 result
= ifnet_set_delegate(pcb
->ipsec_ifp
, del_ifp
);
2692 ifnet_release(del_ifp
);
2697 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS
: {
2698 if (len
!= sizeof(int)) {
2702 if (pcb
->ipsec_ifp
== NULL
) {
2703 // Only can set after connecting
2707 mbuf_svc_class_t output_service_class
= so_tc2msc(*(int *)data
);
2708 if (output_service_class
== MBUF_SC_UNSPEC
) {
2709 pcb
->ipsec_output_service_class
= MBUF_SC_OAM
;
2711 pcb
->ipsec_output_service_class
= output_service_class
;
2713 printf("%s IPSEC_OPT_OUTPUT_TRAFFIC_CLASS %s svc %d\n",
2714 __func__
, pcb
->ipsec_ifp
->if_xname
,
2715 pcb
->ipsec_output_service_class
);
2720 case IPSEC_OPT_ENABLE_CHANNEL
: {
2721 if (len
!= sizeof(int)) {
2725 if (pcb
->ipsec_ifp
== NULL
) {
2726 // Only can set after connecting
2731 result
= ipsec_enable_channel(pcb
, current_proc());
2733 result
= ipsec_disable_channel(pcb
);
2738 case IPSEC_OPT_ENABLE_FLOWSWITCH
: {
2739 if (len
!= sizeof(int)) {
2743 if (pcb
->ipsec_ifp
== NULL
) {
2744 // Only can set after connecting
2748 if (!if_is_netagent_enabled()) {
2752 if (uuid_is_null(pcb
->ipsec_nx
.ms_agent
)) {
2758 if_add_netagent(pcb
->ipsec_ifp
, pcb
->ipsec_nx
.ms_agent
);
2760 if_delete_netagent(pcb
->ipsec_ifp
, pcb
->ipsec_nx
.ms_agent
);
2765 case IPSEC_OPT_INPUT_FRAG_SIZE
: {
2766 if (len
!= sizeof(u_int32_t
)) {
2770 u_int32_t input_frag_size
= *(u_int32_t
*)data
;
2771 if (input_frag_size
<= sizeof(struct ip6_hdr
)) {
2772 pcb
->ipsec_frag_size_set
= FALSE
;
2773 pcb
->ipsec_input_frag_size
= 0;
2775 printf("SET FRAG SIZE TO %u\n", input_frag_size
);
2776 pcb
->ipsec_frag_size_set
= TRUE
;
2777 pcb
->ipsec_input_frag_size
= input_frag_size
;
2781 case IPSEC_OPT_ENABLE_NETIF
: {
2782 if (len
!= sizeof(int)) {
2786 if (pcb
->ipsec_ifp
!= NULL
) {
2787 // Only can set before connecting
2791 lck_rw_lock_exclusive(&pcb
->ipsec_pcb_lock
);
2792 pcb
->ipsec_use_netif
= !!(*(int *)data
);
2793 lck_rw_unlock_exclusive(&pcb
->ipsec_pcb_lock
);
2796 case IPSEC_OPT_SLOT_SIZE
: {
2797 if (len
!= sizeof(u_int32_t
)) {
2801 if (pcb
->ipsec_ifp
!= NULL
) {
2802 // Only can set before connecting
2806 u_int32_t slot_size
= *(u_int32_t
*)data
;
2807 if (slot_size
< IPSEC_IF_MIN_SLOT_SIZE
||
2808 slot_size
> IPSEC_IF_MAX_SLOT_SIZE
) {
2811 pcb
->ipsec_slot_size
= slot_size
;
2814 case IPSEC_OPT_NETIF_RING_SIZE
: {
2815 if (len
!= sizeof(u_int32_t
)) {
2819 if (pcb
->ipsec_ifp
!= NULL
) {
2820 // Only can set before connecting
2824 u_int32_t ring_size
= *(u_int32_t
*)data
;
2825 if (ring_size
< IPSEC_IF_MIN_RING_SIZE
||
2826 ring_size
> IPSEC_IF_MAX_RING_SIZE
) {
2829 pcb
->ipsec_netif_ring_size
= ring_size
;
2832 case IPSEC_OPT_TX_FSW_RING_SIZE
: {
2833 if (len
!= sizeof(u_int32_t
)) {
2837 if (pcb
->ipsec_ifp
!= NULL
) {
2838 // Only can set before connecting
2842 u_int32_t ring_size
= *(u_int32_t
*)data
;
2843 if (ring_size
< IPSEC_IF_MIN_RING_SIZE
||
2844 ring_size
> IPSEC_IF_MAX_RING_SIZE
) {
2847 pcb
->ipsec_tx_fsw_ring_size
= ring_size
;
2850 case IPSEC_OPT_RX_FSW_RING_SIZE
: {
2851 if (len
!= sizeof(u_int32_t
)) {
2855 if (pcb
->ipsec_ifp
!= NULL
) {
2856 // Only can set before connecting
2860 u_int32_t ring_size
= *(u_int32_t
*)data
;
2861 if (ring_size
< IPSEC_IF_MIN_RING_SIZE
||
2862 ring_size
> IPSEC_IF_MAX_RING_SIZE
) {
2865 pcb
->ipsec_rx_fsw_ring_size
= ring_size
;
2869 #endif // IPSEC_NEXUS
2872 result
= ENOPROTOOPT
;
2880 ipsec_ctl_getopt(__unused kern_ctl_ref kctlref
,
2881 __unused u_int32_t unit
,
2887 struct ipsec_pcb
*pcb
= unitinfo
;
2891 case IPSEC_OPT_FLAGS
: {
2892 if (*len
!= sizeof(u_int32_t
)) {
2895 *(u_int32_t
*)data
= pcb
->ipsec_flags
;
2900 case IPSEC_OPT_EXT_IFDATA_STATS
: {
2901 if (*len
!= sizeof(int)) {
2904 *(int *)data
= (pcb
->ipsec_ext_ifdata_stats
) ? 1 : 0;
2909 case IPSEC_OPT_IFNAME
: {
2910 if (*len
< MIN(strlen(pcb
->ipsec_if_xname
) + 1, sizeof(pcb
->ipsec_if_xname
))) {
2913 if (pcb
->ipsec_ifp
== NULL
) {
2914 // Only can get after connecting
2918 *len
= snprintf(data
, *len
, "%s", pcb
->ipsec_if_xname
) + 1;
2923 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS
: {
2924 if (*len
!= sizeof(int)) {
2927 *(int *)data
= so_svc2tc(pcb
->ipsec_output_service_class
);
2934 case IPSEC_OPT_ENABLE_CHANNEL
: {
2935 if (*len
!= sizeof(int)) {
2938 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
2939 *(int *)data
= pcb
->ipsec_kpipe_enabled
;
2940 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
2945 case IPSEC_OPT_ENABLE_FLOWSWITCH
: {
2946 if (*len
!= sizeof(int)) {
2949 *(int *)data
= if_check_netagent(pcb
->ipsec_ifp
, pcb
->ipsec_nx
.ms_agent
);
2954 case IPSEC_OPT_ENABLE_NETIF
: {
2955 if (*len
!= sizeof(int)) {
2958 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
2959 *(int *)data
= !!pcb
->ipsec_use_netif
;
2960 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
2965 case IPSEC_OPT_GET_CHANNEL_UUID
: {
2966 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
2967 if (uuid_is_null(pcb
->ipsec_kpipe_uuid
)) {
2969 } else if (*len
!= sizeof(uuid_t
)) {
2972 uuid_copy(data
, pcb
->ipsec_kpipe_uuid
);
2974 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
2978 case IPSEC_OPT_INPUT_FRAG_SIZE
: {
2979 if (*len
!= sizeof(u_int32_t
)) {
2982 *(u_int32_t
*)data
= pcb
->ipsec_input_frag_size
;
2986 case IPSEC_OPT_SLOT_SIZE
: {
2987 if (*len
!= sizeof(u_int32_t
)) {
2990 *(u_int32_t
*)data
= pcb
->ipsec_slot_size
;
2994 case IPSEC_OPT_NETIF_RING_SIZE
: {
2995 if (*len
!= sizeof(u_int32_t
)) {
2998 *(u_int32_t
*)data
= pcb
->ipsec_netif_ring_size
;
3002 case IPSEC_OPT_TX_FSW_RING_SIZE
: {
3003 if (*len
!= sizeof(u_int32_t
)) {
3006 *(u_int32_t
*)data
= pcb
->ipsec_tx_fsw_ring_size
;
3010 case IPSEC_OPT_RX_FSW_RING_SIZE
: {
3011 if (*len
!= sizeof(u_int32_t
)) {
3014 *(u_int32_t
*)data
= pcb
->ipsec_rx_fsw_ring_size
;
3019 #endif // IPSEC_NEXUS
3022 result
= ENOPROTOOPT
;
3030 /* Network Interface functions */
3032 ipsec_output(ifnet_t interface
,
3035 struct ipsec_pcb
*pcb
= ifnet_softc(interface
);
3036 struct ipsec_output_state ipsec_state
;
3038 struct route_in6 ro6
;
3041 struct ip6_hdr
*ip6
;
3042 struct ip_out_args ipoa
;
3043 struct ip6_out_args ip6oa
;
3045 u_int ip_version
= 0;
3047 struct flowadv
*adv
= NULL
;
3049 // Make sure this packet isn't looping through the interface
3050 if (necp_get_last_interface_index_from_packet(data
) == interface
->if_index
) {
3052 goto ipsec_output_err
;
3055 // Mark the interface so NECP can evaluate tunnel policy
3056 necp_mark_packet_from_interface(data
, interface
);
3058 ip
= mtod(data
, struct ip
*);
3059 ip_version
= ip
->ip_v
;
3061 switch (ip_version
) {
3064 if (!pcb
->ipsec_use_netif
)
3065 #endif // IPSEC_NEXUS
3068 bpf_tap_out(pcb
->ipsec_ifp
, DLT_NULL
, data
, &af
, sizeof(af
));
3071 /* Apply encryption */
3072 memset(&ipsec_state
, 0, sizeof(ipsec_state
));
3073 ipsec_state
.m
= data
;
3074 ipsec_state
.dst
= (struct sockaddr
*)&ip
->ip_dst
;
3075 memset(&ipsec_state
.ro
, 0, sizeof(ipsec_state
.ro
));
3077 error
= ipsec4_interface_output(&ipsec_state
, interface
);
3078 /* Tunneled in IPv6 - packet is gone */
3079 if (error
== 0 && ipsec_state
.tunneled
== 6) {
3083 data
= ipsec_state
.m
;
3084 if (error
|| data
== NULL
) {
3086 printf("ipsec_output: ipsec4_output error %d.\n", error
);
3088 goto ipsec_output_err
;
3091 /* Set traffic class, set flow */
3092 m_set_service_class(data
, pcb
->ipsec_output_service_class
);
3093 data
->m_pkthdr
.pkt_flowsrc
= FLOWSRC_IFNET
;
3094 data
->m_pkthdr
.pkt_flowid
= interface
->if_flowhash
;
3095 data
->m_pkthdr
.pkt_proto
= ip
->ip_p
;
3096 data
->m_pkthdr
.pkt_flags
= (PKTF_FLOW_ID
| PKTF_FLOW_ADV
| PKTF_FLOW_LOCALSRC
);
3098 /* Flip endian-ness for ip_output */
3099 ip
= mtod(data
, struct ip
*);
3103 /* Increment statistics */
3104 length
= mbuf_pkthdr_len(data
);
3105 ifnet_stat_increment_out(interface
, 1, length
, 0);
3107 /* Send to ip_output */
3108 memset(&ro
, 0, sizeof(ro
));
3110 flags
= (IP_OUTARGS
| /* Passing out args to specify interface */
3111 IP_NOIPSEC
); /* To ensure the packet doesn't go through ipsec twice */
3113 memset(&ipoa
, 0, sizeof(ipoa
));
3114 ipoa
.ipoa_flowadv
.code
= 0;
3115 ipoa
.ipoa_flags
= IPOAF_SELECT_SRCIF
| IPOAF_BOUND_SRCADDR
;
3116 if (ipsec_state
.outgoing_if
) {
3117 ipoa
.ipoa_boundif
= ipsec_state
.outgoing_if
;
3118 ipoa
.ipoa_flags
|= IPOAF_BOUND_IF
;
3120 ipsec_set_ipoa_for_interface(pcb
->ipsec_ifp
, &ipoa
);
3122 adv
= &ipoa
.ipoa_flowadv
;
3124 (void)ip_output(data
, NULL
, &ro
, flags
, NULL
, &ipoa
);
3127 if (adv
->code
== FADV_FLOW_CONTROLLED
|| adv
->code
== FADV_SUSPENDED
) {
3129 ifnet_disable_output(interface
);
3136 if (!pcb
->ipsec_use_netif
)
3137 #endif // IPSEC_NEXUS
3140 bpf_tap_out(pcb
->ipsec_ifp
, DLT_NULL
, data
, &af
, sizeof(af
));
3143 data
= ipsec6_splithdr(data
);
3145 printf("ipsec_output: ipsec6_splithdr returned NULL\n");
3146 goto ipsec_output_err
;
3149 ip6
= mtod(data
, struct ip6_hdr
*);
3151 memset(&ipsec_state
, 0, sizeof(ipsec_state
));
3152 ipsec_state
.m
= data
;
3153 ipsec_state
.dst
= (struct sockaddr
*)&ip6
->ip6_dst
;
3154 memset(&ipsec_state
.ro
, 0, sizeof(ipsec_state
.ro
));
3156 error
= ipsec6_interface_output(&ipsec_state
, interface
, &ip6
->ip6_nxt
, ipsec_state
.m
);
3157 if (error
== 0 && ipsec_state
.tunneled
== 4) { /* tunneled in IPv4 - packet is gone */
3160 data
= ipsec_state
.m
;
3161 if (error
|| data
== NULL
) {
3163 printf("ipsec_output: ipsec6_output error %d\n", error
);
3165 goto ipsec_output_err
;
3168 /* Set traffic class, set flow */
3169 m_set_service_class(data
, pcb
->ipsec_output_service_class
);
3170 data
->m_pkthdr
.pkt_flowsrc
= FLOWSRC_IFNET
;
3171 data
->m_pkthdr
.pkt_flowid
= interface
->if_flowhash
;
3172 data
->m_pkthdr
.pkt_proto
= ip6
->ip6_nxt
;
3173 data
->m_pkthdr
.pkt_flags
= (PKTF_FLOW_ID
| PKTF_FLOW_ADV
| PKTF_FLOW_LOCALSRC
);
3175 /* Increment statistics */
3176 length
= mbuf_pkthdr_len(data
);
3177 ifnet_stat_increment_out(interface
, 1, length
, 0);
3179 /* Send to ip6_output */
3180 memset(&ro6
, 0, sizeof(ro6
));
3182 flags
= IPV6_OUTARGS
;
3184 memset(&ip6oa
, 0, sizeof(ip6oa
));
3185 ip6oa
.ip6oa_flowadv
.code
= 0;
3186 ip6oa
.ip6oa_flags
= IP6OAF_SELECT_SRCIF
| IP6OAF_BOUND_SRCADDR
;
3187 if (ipsec_state
.outgoing_if
) {
3188 ip6oa
.ip6oa_boundif
= ipsec_state
.outgoing_if
;
3189 ip6oa
.ip6oa_flags
|= IP6OAF_BOUND_IF
;
3191 ipsec_set_ip6oa_for_interface(pcb
->ipsec_ifp
, &ip6oa
);
3193 adv
= &ip6oa
.ip6oa_flowadv
;
3195 (void) ip6_output(data
, NULL
, &ro6
, flags
, NULL
, NULL
, &ip6oa
);
3198 if (adv
->code
== FADV_FLOW_CONTROLLED
|| adv
->code
== FADV_SUSPENDED
) {
3200 ifnet_disable_output(interface
);
3206 printf("ipsec_output: Received unknown packet version %d.\n", ip_version
);
3208 goto ipsec_output_err
;
3222 ipsec_start(ifnet_t interface
)
3225 struct ipsec_pcb
*pcb
= ifnet_softc(interface
);
3227 VERIFY(pcb
!= NULL
);
3229 if (ifnet_dequeue(interface
, &data
) != 0)
3231 if (ipsec_output(interface
, data
) != 0)
3236 /* Network Interface functions */
3238 ipsec_demux(__unused ifnet_t interface
,
3240 __unused
char *frame_header
,
3241 protocol_family_t
*protocol
)
3246 while (data
!= NULL
&& mbuf_len(data
) < 1) {
3247 data
= mbuf_next(data
);
3253 ip
= mtod(data
, struct ip
*);
3254 ip_version
= ip
->ip_v
;
3256 switch(ip_version
) {
3258 *protocol
= PF_INET
;
3261 *protocol
= PF_INET6
;
3271 ipsec_add_proto(__unused ifnet_t interface
,
3272 protocol_family_t protocol
,
3273 __unused
const struct ifnet_demux_desc
*demux_array
,
3274 __unused u_int32_t demux_count
)
3289 ipsec_del_proto(__unused ifnet_t interface
,
3290 __unused protocol_family_t protocol
)
3296 ipsec_ioctl(ifnet_t interface
,
3305 struct ipsec_pcb
*pcb
= ifnet_softc(interface
);
3306 if (pcb
->ipsec_use_netif
) {
3307 // Make sure we can fit packets in the channel buffers
3308 if (((uint64_t)((struct ifreq
*)data
)->ifr_mtu
) > pcb
->ipsec_slot_size
) {
3311 ifnet_set_mtu(interface
, (uint32_t)((struct ifreq
*)data
)->ifr_mtu
);
3314 #endif // IPSEC_NEXUS
3316 ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
);
3322 /* ifioctl() takes care of it */
3326 result
= EOPNOTSUPP
;
3333 ipsec_detached(ifnet_t interface
)
3335 struct ipsec_pcb
*pcb
= ifnet_softc(interface
);
3336 (void)ifnet_release(interface
);
3337 ipsec_free_pcb(pcb
, true);
3340 /* Protocol Handlers */
3343 ipsec_proto_input(ifnet_t interface
,
3344 protocol_family_t protocol
,
3346 __unused
char *frame_header
)
3348 mbuf_pkthdr_setrcvif(m
, interface
);
3351 struct ipsec_pcb
*pcb
= ifnet_softc(interface
);
3352 if (!pcb
->ipsec_use_netif
)
3353 #endif // IPSEC_NEXUS
3356 struct ip
*ip
= mtod(m
, struct ip
*);
3357 if (ip
->ip_v
== 4) {
3359 } else if (ip
->ip_v
== 6) {
3362 bpf_tap_in(interface
, DLT_NULL
, m
, &af
, sizeof(af
));
3363 pktap_input(interface
, protocol
, m
, NULL
);
3366 int32_t pktlen
= m
->m_pkthdr
.len
;
3367 if (proto_input(protocol
, m
) != 0) {
3368 ifnet_stat_increment_in(interface
, 0, 0, 1);
3371 ifnet_stat_increment_in(interface
, 1, pktlen
, 0);
3378 ipsec_proto_pre_output(__unused ifnet_t interface
,
3379 protocol_family_t protocol
,
3380 __unused mbuf_t
*packet
,
3381 __unused
const struct sockaddr
*dest
,
3382 __unused
void *route
,
3383 __unused
char *frame_type
,
3384 __unused
char *link_layer_dest
)
3387 *(protocol_family_t
*)(void *)frame_type
= protocol
;
3392 ipsec_attach_proto(ifnet_t interface
,
3393 protocol_family_t protocol
)
3395 struct ifnet_attach_proto_param proto
;
3398 bzero(&proto
, sizeof(proto
));
3399 proto
.input
= ipsec_proto_input
;
3400 proto
.pre_output
= ipsec_proto_pre_output
;
3402 result
= ifnet_attach_protocol(interface
, protocol
, &proto
);
3403 if (result
!= 0 && result
!= EEXIST
) {
3404 printf("ipsec_attach_inet - ifnet_attach_protocol %d failed: %d\n",
3412 ipsec_inject_inbound_packet(ifnet_t interface
,
3416 struct ipsec_pcb
*pcb
= ifnet_softc(interface
);
3418 if (pcb
->ipsec_use_netif
) {
3419 lck_rw_lock_shared(&pcb
->ipsec_pcb_lock
);
3421 lck_mtx_lock(&pcb
->ipsec_input_chain_lock
);
3422 if (pcb
->ipsec_input_chain
!= NULL
) {
3423 pcb
->ipsec_input_chain_last
->m_nextpkt
= packet
;
3425 pcb
->ipsec_input_chain
= packet
;
3427 while (packet
->m_nextpkt
) {
3428 VERIFY(packet
!= packet
->m_nextpkt
);
3429 packet
= packet
->m_nextpkt
;
3431 pcb
->ipsec_input_chain_last
= packet
;
3432 lck_mtx_unlock(&pcb
->ipsec_input_chain_lock
);
3434 kern_channel_ring_t rx_ring
= pcb
->ipsec_netif_rxring
;
3435 lck_rw_unlock_shared(&pcb
->ipsec_pcb_lock
);
3437 if (rx_ring
!= NULL
) {
3438 kern_channel_notify(rx_ring
, 0);
3443 #endif // IPSEC_NEXUS
3446 protocol_family_t protocol
;
3447 if ((error
= ipsec_demux(interface
, packet
, NULL
, &protocol
)) != 0) {
3451 return ipsec_proto_input(interface
, protocol
, packet
, NULL
);
3456 ipsec_set_pkthdr_for_interface(ifnet_t interface
, mbuf_t packet
, int family
)
3458 if (packet
!= NULL
&& interface
!= NULL
) {
3459 struct ipsec_pcb
*pcb
= ifnet_softc(interface
);
3461 /* Set traffic class, set flow */
3462 m_set_service_class(packet
, pcb
->ipsec_output_service_class
);
3463 packet
->m_pkthdr
.pkt_flowsrc
= FLOWSRC_IFNET
;
3464 packet
->m_pkthdr
.pkt_flowid
= interface
->if_flowhash
;
3465 if (family
== AF_INET
) {
3466 struct ip
*ip
= mtod(packet
, struct ip
*);
3467 packet
->m_pkthdr
.pkt_proto
= ip
->ip_p
;
3468 } else if (family
== AF_INET6
) {
3469 struct ip6_hdr
*ip6
= mtod(packet
, struct ip6_hdr
*);
3470 packet
->m_pkthdr
.pkt_proto
= ip6
->ip6_nxt
;
3472 packet
->m_pkthdr
.pkt_flags
= (PKTF_FLOW_ID
| PKTF_FLOW_ADV
| PKTF_FLOW_LOCALSRC
);
3478 ipsec_set_ipoa_for_interface(ifnet_t interface
, struct ip_out_args
*ipoa
)
3480 struct ipsec_pcb
*pcb
;
3482 if (interface
== NULL
|| ipoa
== NULL
)
3484 pcb
= ifnet_softc(interface
);
3486 if (net_qos_policy_restricted
== 0) {
3487 ipoa
->ipoa_flags
|= IPOAF_QOSMARKING_ALLOWED
;
3488 ipoa
->ipoa_sotc
= so_svc2tc(pcb
->ipsec_output_service_class
);
3489 } else if (pcb
->ipsec_output_service_class
!= MBUF_SC_VO
||
3490 net_qos_policy_restrict_avapps
!= 0) {
3491 ipoa
->ipoa_flags
&= ~IPOAF_QOSMARKING_ALLOWED
;
3493 ipoa
->ipoa_flags
|= IP6OAF_QOSMARKING_ALLOWED
;
3494 ipoa
->ipoa_sotc
= SO_TC_VO
;
3499 ipsec_set_ip6oa_for_interface(ifnet_t interface
, struct ip6_out_args
*ip6oa
)
3501 struct ipsec_pcb
*pcb
;
3503 if (interface
== NULL
|| ip6oa
== NULL
)
3505 pcb
= ifnet_softc(interface
);
3507 if (net_qos_policy_restricted
== 0) {
3508 ip6oa
->ip6oa_flags
|= IPOAF_QOSMARKING_ALLOWED
;
3509 ip6oa
->ip6oa_sotc
= so_svc2tc(pcb
->ipsec_output_service_class
);
3510 } else if (pcb
->ipsec_output_service_class
!= MBUF_SC_VO
||
3511 net_qos_policy_restrict_avapps
!= 0) {
3512 ip6oa
->ip6oa_flags
&= ~IPOAF_QOSMARKING_ALLOWED
;
3514 ip6oa
->ip6oa_flags
|= IP6OAF_QOSMARKING_ALLOWED
;
3515 ip6oa
->ip6oa_sotc
= SO_TC_VO
;