2 * Copyright (c) 2008-2011 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@
31 /* ----------------------------------------------------------------------------------
32 Application of kernel control for interface creation
35 utun (user tunnel) acts as glue between kernel control sockets and network interfaces.
36 This kernel control will register an interface for every client that connects.
37 ---------------------------------------------------------------------------------- */
39 #include <sys/systm.h>
40 #include <sys/kern_control.h>
41 #include <net/kpi_protocol.h>
42 #include <net/kpi_interface.h>
43 #include <sys/socket.h>
45 #include <net/if_types.h>
47 #include <net/if_utun.h>
48 #include <libkern/OSMalloc.h>
49 #include <libkern/OSAtomic.h>
51 #include <sys/sockio.h>
52 #include <netinet/in.h>
53 #include <netinet6/in6_var.h>
54 #include <netinet6/in6_var.h>
55 #include <sys/kauth.h>
58 /* Kernel Control functions */
59 static errno_t
utun_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
61 static errno_t
utun_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
,
63 static errno_t
utun_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
,
64 void *unitinfo
, mbuf_t m
, int flags
);
65 static errno_t
utun_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
66 int opt
, void *data
, size_t *len
);
67 static errno_t
utun_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
68 int opt
, void *data
, size_t len
);
70 /* Network Interface functions */
71 static errno_t
utun_output(ifnet_t interface
, mbuf_t data
);
72 static errno_t
utun_demux(ifnet_t interface
, mbuf_t data
, char *frame_header
,
73 protocol_family_t
*protocol
);
74 static errno_t
utun_framer(ifnet_t interface
, mbuf_t
*packet
,
75 const struct sockaddr
*dest
, const char *desk_linkaddr
,
76 const char *frame_type
77 #if KPI_INTERFACE_EMBEDDED
79 u_int32_t
*prepend_len
, u_int32_t
*postpend_len
80 #endif /* KPI_INTERFACE_EMBEDDED */
82 static errno_t
utun_add_proto(ifnet_t interface
, protocol_family_t protocol
,
83 const struct ifnet_demux_desc
*demux_array
,
84 u_int32_t demux_count
);
85 static errno_t
utun_del_proto(ifnet_t interface
, protocol_family_t protocol
);
86 static errno_t
utun_ioctl(ifnet_t interface
, u_long cmd
, void *data
);
87 static void utun_detached(ifnet_t interface
);
89 /* Protocol handlers */
90 static errno_t
utun_attach_proto(ifnet_t interface
, protocol_family_t proto
);
91 static errno_t
utun_proto_input(ifnet_t interface
, protocol_family_t protocol
,
92 mbuf_t m
, char *frame_header
);
93 static errno_t
utun_proto_pre_output(ifnet_t interface
, protocol_family_t protocol
,
94 mbuf_t
*packet
, const struct sockaddr
*dest
, void *route
,
95 char *frame_type
, char *link_layer_dest
);
96 __private_extern__ errno_t
utun_pkt_input (struct utun_pcb
*pcb
, mbuf_t m
);
98 static kern_ctl_ref utun_kctlref
;
99 static u_int32_t utun_family
;
100 static OSMallocTag utun_malloc_tag
;
101 static SInt32 utun_ifcount
= 0;
105 utun_alloc(size_t size
)
107 size_t *mem
= OSMalloc(size
+ sizeof(size_t), utun_malloc_tag
);
110 *mem
= size
+ sizeof(size_t);
122 OSFree(size
, *size
, utun_malloc_tag
);
126 utun_register_control(void)
128 struct kern_ctl_reg kern_ctl
;
131 /* Create a tag to allocate memory */
132 utun_malloc_tag
= OSMalloc_Tagalloc(UTUN_CONTROL_NAME
, OSMT_DEFAULT
);
134 /* Find a unique value for our interface family */
135 result
= mbuf_tag_id_find(UTUN_CONTROL_NAME
, &utun_family
);
137 printf("utun_register_control - mbuf_tag_id_find_internal failed: %d\n", result
);
141 bzero(&kern_ctl
, sizeof(kern_ctl
));
142 strncpy(kern_ctl
.ctl_name
, UTUN_CONTROL_NAME
, sizeof(kern_ctl
.ctl_name
));
143 kern_ctl
.ctl_name
[sizeof(kern_ctl
.ctl_name
) - 1] = 0;
144 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
; /* Require root */
145 kern_ctl
.ctl_sendsize
= 64 * 1024;
146 kern_ctl
.ctl_recvsize
= 64 * 1024;
147 kern_ctl
.ctl_connect
= utun_ctl_connect
;
148 kern_ctl
.ctl_disconnect
= utun_ctl_disconnect
;
149 kern_ctl
.ctl_send
= utun_ctl_send
;
150 kern_ctl
.ctl_setopt
= utun_ctl_setopt
;
151 kern_ctl
.ctl_getopt
= utun_ctl_getopt
;
153 result
= ctl_register(&kern_ctl
, &utun_kctlref
);
155 printf("utun_register_control - ctl_register failed: %d\n", result
);
159 /* Register the protocol plumbers */
160 if ((result
= proto_register_plumber(PF_INET
, utun_family
,
161 utun_attach_proto
, NULL
)) != 0) {
162 printf("utun_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n",
163 utun_family
, result
);
164 ctl_deregister(utun_kctlref
);
168 /* Register the protocol plumbers */
169 if ((result
= proto_register_plumber(PF_INET6
, utun_family
,
170 utun_attach_proto
, NULL
)) != 0) {
171 proto_unregister_plumber(PF_INET
, utun_family
);
172 ctl_deregister(utun_kctlref
);
173 printf("utun_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n",
174 utun_family
, result
);
181 /* Kernel control functions */
185 kern_ctl_ref kctlref
,
186 struct sockaddr_ctl
*sac
,
189 struct ifnet_init_params utun_init
;
190 struct utun_pcb
*pcb
;
192 struct ifnet_stats_param stats
;
194 /* kernel control allocates, interface frees */
195 pcb
= utun_alloc(sizeof(*pcb
));
199 /* Setup the protocol control block */
200 bzero(pcb
, sizeof(*pcb
));
202 pcb
->utun_ctlref
= kctlref
;
203 pcb
->utun_unit
= sac
->sc_unit
;
205 printf("utun_ctl_connect: creating interface utun%d\n", pcb
->utun_unit
- 1);
207 /* Create the interface */
208 bzero(&utun_init
, sizeof(utun_init
));
209 utun_init
.name
= "utun";
210 utun_init
.unit
= pcb
->utun_unit
- 1;
211 utun_init
.family
= utun_family
;
212 utun_init
.type
= IFT_OTHER
;
213 utun_init
.output
= utun_output
;
214 utun_init
.demux
= utun_demux
;
215 utun_init
.framer
= utun_framer
;
216 utun_init
.add_proto
= utun_add_proto
;
217 utun_init
.del_proto
= utun_del_proto
;
218 utun_init
.softc
= pcb
;
219 utun_init
.ioctl
= utun_ioctl
;
220 utun_init
.detach
= utun_detached
;
222 result
= ifnet_allocate(&utun_init
, &pcb
->utun_ifp
);
224 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
228 OSIncrementAtomic(&utun_ifcount
);
230 /* Set flags and additional information. */
231 ifnet_set_mtu(pcb
->utun_ifp
, 1500);
232 ifnet_set_flags(pcb
->utun_ifp
, IFF_UP
| IFF_MULTICAST
| IFF_POINTOPOINT
, 0xffff);
234 /* The interface must generate its own IPv6 LinkLocal address,
235 * if possible following the recommendation of RFC2472 to the 64bit interface ID
237 ifnet_set_eflags(pcb
->utun_ifp
, IFEF_NOAUTOIPV6LL
, IFEF_NOAUTOIPV6LL
);
239 /* Reset the stats in case as the interface may have been recycled */
240 bzero(&stats
, sizeof(struct ifnet_stats_param
));
241 ifnet_set_stat(pcb
->utun_ifp
, &stats
);
243 /* Attach the interface */
244 result
= ifnet_attach(pcb
->utun_ifp
, NULL
);
246 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
247 ifnet_release(pcb
->utun_ifp
);
253 bpfattach(pcb
->utun_ifp
, DLT_NULL
, 4);
255 /* The interfaces resoures allocated, mark it as running */
257 ifnet_set_flags(pcb
->utun_ifp
, IFF_RUNNING
, IFF_RUNNING
);
265 protocol_family_t protocol
,
268 errno_t result
= EPROTONOSUPPORT
;
270 /* Attempt a detach */
271 if (protocol
== PF_INET
) {
274 bzero(&ifr
, sizeof(ifr
));
275 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
276 ifnet_name(interface
), ifnet_unit(interface
));
278 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH
, &ifr
);
280 else if (protocol
== PF_INET6
) {
281 struct in6_ifreq ifr6
;
283 bzero(&ifr6
, sizeof(ifr6
));
284 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
285 ifnet_name(interface
), ifnet_unit(interface
));
287 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH_IN6
, &ifr6
);
296 protocol_family_t protocol
,
302 /* Attempt a detach */
303 if (protocol
== PF_INET
) {
306 bzero(&ifr
, sizeof(ifr
));
307 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
308 ifnet_name(interface
), ifnet_unit(interface
));
309 result
= ifaddr_address(address
, &ifr
.ifr_addr
, sizeof(ifr
.ifr_addr
));
311 printf("utun_remove_address - ifaddr_address failed: %d", result
);
314 result
= sock_ioctl(pf_socket
, SIOCDIFADDR
, &ifr
);
316 printf("utun_remove_address - SIOCDIFADDR failed: %d", result
);
320 else if (protocol
== PF_INET6
) {
321 struct in6_ifreq ifr6
;
323 bzero(&ifr6
, sizeof(ifr6
));
324 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
325 ifnet_name(interface
), ifnet_unit(interface
));
326 result
= ifaddr_address(address
, (struct sockaddr
*)&ifr6
.ifr_addr
,
327 sizeof(ifr6
.ifr_addr
));
329 printf("utun_remove_address - ifaddr_address failed (v6): %d",
333 result
= sock_ioctl(pf_socket
, SIOCDIFADDR_IN6
, &ifr6
);
335 printf("utun_remove_address - SIOCDIFADDR_IN6 failed: %d",
345 protocol_family_t protocol
)
348 socket_t pf_socket
= NULL
;
349 ifaddr_t
*addresses
= NULL
;
352 if (protocol
!= PF_INET
&& protocol
!= PF_INET6
) {
353 printf("utun_cleanup_family - invalid protocol family %d\n", protocol
);
357 /* Create a socket for removing addresses and detaching the protocol */
358 result
= sock_socket(protocol
, SOCK_DGRAM
, 0, NULL
, NULL
, &pf_socket
);
360 if (result
!= EAFNOSUPPORT
)
361 printf("utun_cleanup_family - failed to create %s socket: %d\n",
362 protocol
== PF_INET
? "IP" : "IPv6", result
);
366 /* always set SS_PRIV, we want to close and detach regardless */
367 sock_setpriv(pf_socket
, 1);
369 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
370 if (result
== 0 || result
== ENXIO
) {
371 /* We are done! We either detached or weren't attached. */
374 else if (result
!= EBUSY
) {
375 /* Uh, not really sure what happened here... */
376 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
381 * At this point, we received an EBUSY error. This means there are
382 * addresses attached. We should detach them and then try again.
384 result
= ifnet_get_address_list_family(interface
, &addresses
, protocol
);
386 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
387 ifnet_name(interface
), ifnet_unit(interface
),
388 protocol
== PF_INET
? "PF_INET" : "PF_INET6", result
);
392 for (i
= 0; addresses
[i
] != 0; i
++) {
393 utun_remove_address(interface
, protocol
, addresses
[i
], pf_socket
);
395 ifnet_free_address_list(addresses
);
399 * The addresses should be gone, we should try the remove again.
401 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
402 if (result
!= 0 && result
!= ENXIO
) {
403 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
407 if (pf_socket
!= NULL
)
408 sock_close(pf_socket
);
410 if (addresses
!= NULL
)
411 ifnet_free_address_list(addresses
);
416 __unused kern_ctl_ref kctlref
,
417 __unused u_int32_t unit
,
420 struct utun_pcb
*pcb
= unitinfo
;
421 ifnet_t ifp
= pcb
->utun_ifp
;
424 utun_cleanup_crypto(pcb
);
426 pcb
->utun_ctlref
= NULL
;
430 * We want to do everything in our power to ensure that the interface
431 * really goes away when the socket is closed. We must remove IP/IPv6
432 * addresses and detach the protocols. Finally, we can remove and
433 * release the interface.
435 utun_cleanup_family(ifp
, AF_INET
);
436 utun_cleanup_family(ifp
, AF_INET6
);
438 if ((result
= ifnet_detach(ifp
)) != 0) {
439 printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result
);
442 if ((result
= ifnet_release(ifp
)) != 0) {
443 printf("utun_ctl_disconnect - ifnet_release failed: %d\n", result
);
451 __unused kern_ctl_ref kctlref
,
452 __unused u_int32_t unit
,
457 return utun_pkt_input((struct utun_pcb
*)unitinfo
, m
);
462 __unused kern_ctl_ref kctlref
,
463 __unused u_int32_t unit
,
469 struct utun_pcb
*pcb
= unitinfo
;
472 /* check for privileges for privileged options */
475 case UTUN_OPT_EXT_IFDATA_STATS
:
476 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
484 if (len
!= sizeof(u_int32_t
))
487 pcb
->utun_flags
= *(u_int32_t
*)data
;
490 case UTUN_OPT_ENABLE_CRYPTO
:
491 result
= utun_ctl_enable_crypto(kctlref
, unit
, unitinfo
, opt
, data
, len
);
494 case UTUN_OPT_CONFIG_CRYPTO_KEYS
:
495 result
= utun_ctl_config_crypto_keys(kctlref
, unit
, unitinfo
, opt
, data
, len
);
498 case UTUN_OPT_UNCONFIG_CRYPTO_KEYS
:
499 result
= utun_ctl_unconfig_crypto_keys(kctlref
, unit
, unitinfo
, opt
, data
, len
);
502 case UTUN_OPT_DISABLE_CRYPTO
:
503 result
= utun_ctl_disable_crypto(kctlref
, unit
, unitinfo
, opt
, data
, len
);
506 case UTUN_OPT_STOP_CRYPTO_DATA_TRAFFIC
:
507 result
= utun_ctl_stop_crypto_data_traffic(kctlref
, unit
, unitinfo
, opt
, data
, len
);
510 case UTUN_OPT_START_CRYPTO_DATA_TRAFFIC
:
511 result
= utun_ctl_start_crypto_data_traffic(kctlref
, unit
, unitinfo
, opt
, data
, len
);
514 case UTUN_OPT_EXT_IFDATA_STATS
:
515 if (len
!= sizeof(int)) {
519 pcb
->utun_ext_ifdata_stats
= (*(int *)data
) ? 1 : 0;
522 case UTUN_OPT_INC_IFDATA_STATS_IN
:
523 case UTUN_OPT_INC_IFDATA_STATS_OUT
: {
524 struct utun_stats_param
*utsp
= (struct utun_stats_param
*)data
;
526 if (utsp
== NULL
|| len
< sizeof(struct utun_stats_param
)) {
530 if (!pcb
->utun_ext_ifdata_stats
) {
534 if (opt
== UTUN_OPT_INC_IFDATA_STATS_IN
)
535 ifnet_stat_increment_in(pcb
->utun_ifp
, utsp
->utsp_packets
,
536 utsp
->utsp_bytes
, utsp
->utsp_errors
);
538 ifnet_stat_increment_out(pcb
->utun_ifp
, utsp
->utsp_packets
,
539 utsp
->utsp_bytes
, utsp
->utsp_errors
);
544 result
= ENOPROTOOPT
;
553 __unused kern_ctl_ref kctlref
,
554 __unused u_int32_t unit
,
560 struct utun_pcb
*pcb
= unitinfo
;
565 if (*len
!= sizeof(u_int32_t
))
568 *(u_int32_t
*)data
= pcb
->utun_flags
;
571 case UTUN_OPT_EXT_IFDATA_STATS
:
572 if (*len
!= sizeof(int))
575 *(int *)data
= (pcb
->utun_ext_ifdata_stats
) ? 1 : 0;
578 case UTUN_OPT_IFNAME
:
579 *len
= snprintf(data
, *len
, "%s%d", ifnet_name(pcb
->utun_ifp
), ifnet_unit(pcb
->utun_ifp
)) + 1;
582 case UTUN_OPT_GENERATE_CRYPTO_KEYS_IDX
:
583 result
= utun_ctl_generate_crypto_keys_idx(kctlref
, unit
, unitinfo
, opt
, data
, len
);
587 result
= ENOPROTOOPT
;
594 /* Network Interface functions */
600 struct utun_pcb
*pcb
= ifnet_softc(interface
);
603 bpf_tap_out(pcb
->utun_ifp
, DLT_NULL
, data
, 0, 0);
605 if (pcb
->utun_flags
& UTUN_FLAGS_NO_OUTPUT
) {
611 // otherwise, fall thru to ctl_enqueumbuf
612 if (pcb
->utun_ctlref
) {
615 // only pass packets to utun-crypto if crypto is enabled and 'suspend data traffic' is not.
616 if ((pcb
->utun_flags
& (UTUN_FLAGS_CRYPTO
| UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC
)) == UTUN_FLAGS_CRYPTO
) {
617 if (utun_pkt_crypto_output(pcb
, &data
) == 0) {
622 length
= mbuf_pkthdr_len(data
);
623 result
= ctl_enqueuembuf(pcb
->utun_ctlref
, pcb
->utun_unit
, data
, CTL_DATA_EOR
);
626 printf("utun_output - ctl_enqueuembuf failed: %d\n", result
);
628 ifnet_stat_increment_out(interface
, 0, 0, 1);
631 if (!pcb
->utun_ext_ifdata_stats
)
632 ifnet_stat_increment_out(interface
, 1, length
, 0);
641 /* Network Interface functions */
644 __unused ifnet_t interface
,
646 __unused
char *frame_header
,
647 protocol_family_t
*protocol
)
650 while (data
!= NULL
&& mbuf_len(data
) < 1) {
651 data
= mbuf_next(data
);
657 *protocol
= ntohl(*(u_int32_t
*)mbuf_data(data
));
663 __unused ifnet_t interface
,
665 __unused
const struct sockaddr
*dest
,
666 __unused
const char *desk_linkaddr
,
667 const char *frame_type
668 #if KPI_INTERFACE_EMBEDDED
670 u_int32_t
*prepend_len
,
671 u_int32_t
*postpend_len
672 #endif /* KPI_INTERFACE_EMBEDDED */
675 if (mbuf_prepend(packet
, sizeof(protocol_family_t
), MBUF_DONTWAIT
) != 0) {
676 printf("utun_framer - ifnet_output prepend failed\n");
678 ifnet_stat_increment_out(interface
, 0, 0, 1);
680 // just return, because the buffer was freed in mbuf_prepend
683 #if KPI_INTERFACE_EMBEDDED
684 *prepend_len
= sizeof(protocol_family_t
);
686 #endif /* KPI_INTERFACE_EMBEDDED */
688 // place protocol number at the beginning of the mbuf
689 *(protocol_family_t
*)mbuf_data(*packet
) = htonl(*(protocol_family_t
*)(uintptr_t)(size_t)frame_type
);
696 __unused ifnet_t interface
,
697 protocol_family_t protocol
,
698 __unused
const struct ifnet_demux_desc
*demux_array
,
699 __unused u_int32_t demux_count
)
715 __unused ifnet_t interface
,
716 __unused protocol_family_t protocol
)
731 ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
);
735 /* ifioctl() takes care of it */
749 struct utun_pcb
*pcb
= ifnet_softc(interface
);
753 OSDecrementAtomic(&utun_ifcount
);
756 /* Protocol Handlers */
760 __unused ifnet_t interface
,
761 protocol_family_t protocol
,
763 __unused
char *frame_header
)
766 // remove protocol family first
767 mbuf_adj(m
, sizeof(u_int32_t
));
769 if (proto_input(protocol
, m
) != 0)
776 utun_proto_pre_output(
777 __unused ifnet_t interface
,
778 protocol_family_t protocol
,
779 __unused mbuf_t
*packet
,
780 __unused
const struct sockaddr
*dest
,
781 __unused
void *route
,
782 __unused
char *frame_type
,
783 __unused
char *link_layer_dest
)
786 *(protocol_family_t
*)(void *)frame_type
= protocol
;
793 protocol_family_t protocol
)
795 struct ifnet_attach_proto_param proto
;
798 bzero(&proto
, sizeof(proto
));
799 proto
.input
= utun_proto_input
;
800 proto
.pre_output
= utun_proto_pre_output
;
802 result
= ifnet_attach_protocol(interface
, protocol
, &proto
);
803 if (result
!= 0 && result
!= EEXIST
) {
804 printf("utun_attach_inet - ifnet_attach_protocol %d failed: %d\n",
812 utun_pkt_input (struct utun_pcb
*pcb
, mbuf_t m
)
815 protocol_family_t protocol
;
817 mbuf_pkthdr_setrcvif(m
, pcb
->utun_ifp
);
819 bpf_tap_in(pcb
->utun_ifp
, DLT_NULL
, m
, 0, 0);
821 if (pcb
->utun_flags
& UTUN_FLAGS_NO_INPUT
) {
826 protocol
= ntohl(*(u_int32_t
*)mbuf_data(m
));
828 // quick exit for keepalive packets
829 if (protocol
== AF_UTUN
&& pcb
->utun_flags
& UTUN_FLAGS_CRYPTO
) {
830 if (utun_pkt_crypto_output(pcb
, &m
) == 0) {
833 printf("%s: utun_pkt_crypto_output failed, flags %x\n", __FUNCTION__
, pcb
->utun_flags
);
837 if (!pcb
->utun_ext_ifdata_stats
) {
838 struct ifnet_stat_increment_param incs
;
840 bzero(&incs
, sizeof(incs
));
842 incs
.bytes_in
= mbuf_pkthdr_len(m
);
843 result
= ifnet_input(pcb
->utun_ifp
, m
, &incs
);
845 result
= ifnet_input(pcb
->utun_ifp
, m
, NULL
);
848 ifnet_stat_increment_in(pcb
->utun_ifp
, 0, 0, 1);
850 printf("%s - ifnet_input failed: %d\n", __FUNCTION__
, result
);