2 * Copyright (c) 2008-2014 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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
);
69 static void utun_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
72 /* Network Interface functions */
73 static void utun_start(ifnet_t interface
);
74 static errno_t
utun_output(ifnet_t interface
, mbuf_t data
);
75 static errno_t
utun_demux(ifnet_t interface
, mbuf_t data
, char *frame_header
,
76 protocol_family_t
*protocol
);
77 static errno_t
utun_framer(ifnet_t interface
, mbuf_t
*packet
,
78 const struct sockaddr
*dest
, const char *desk_linkaddr
,
79 const char *frame_type
, u_int32_t
*prepend_len
, u_int32_t
*postpend_len
);
80 static errno_t
utun_add_proto(ifnet_t interface
, protocol_family_t protocol
,
81 const struct ifnet_demux_desc
*demux_array
,
82 u_int32_t demux_count
);
83 static errno_t
utun_del_proto(ifnet_t interface
, protocol_family_t protocol
);
84 static errno_t
utun_ioctl(ifnet_t interface
, u_long cmd
, void *data
);
85 static void utun_detached(ifnet_t interface
);
87 /* Protocol handlers */
88 static errno_t
utun_attach_proto(ifnet_t interface
, protocol_family_t proto
);
89 static errno_t
utun_proto_input(ifnet_t interface
, protocol_family_t protocol
,
90 mbuf_t m
, char *frame_header
);
91 static errno_t
utun_proto_pre_output(ifnet_t interface
, protocol_family_t protocol
,
92 mbuf_t
*packet
, const struct sockaddr
*dest
, void *route
,
93 char *frame_type
, char *link_layer_dest
);
94 __private_extern__ errno_t
utun_pkt_input (struct utun_pcb
*pcb
, mbuf_t m
);
96 static kern_ctl_ref utun_kctlref
;
97 static u_int32_t utun_family
;
98 static OSMallocTag utun_malloc_tag
;
99 static SInt32 utun_ifcount
= 0;
103 utun_alloc(size_t size
)
105 size_t *mem
= OSMalloc(size
+ sizeof(size_t), utun_malloc_tag
);
108 *mem
= size
+ sizeof(size_t);
120 OSFree(size
, *size
, utun_malloc_tag
);
124 utun_register_control(void)
126 struct kern_ctl_reg kern_ctl
;
129 /* Create a tag to allocate memory */
130 utun_malloc_tag
= OSMalloc_Tagalloc(UTUN_CONTROL_NAME
, OSMT_DEFAULT
);
132 /* Find a unique value for our interface family */
133 result
= mbuf_tag_id_find(UTUN_CONTROL_NAME
, &utun_family
);
135 printf("utun_register_control - mbuf_tag_id_find_internal failed: %d\n", result
);
139 bzero(&kern_ctl
, sizeof(kern_ctl
));
140 strlcpy(kern_ctl
.ctl_name
, UTUN_CONTROL_NAME
, sizeof(kern_ctl
.ctl_name
));
141 kern_ctl
.ctl_name
[sizeof(kern_ctl
.ctl_name
) - 1] = 0;
142 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
| CTL_FLAG_REG_EXTENDED
; /* Require root */
143 kern_ctl
.ctl_sendsize
= 512 * 1024;
144 kern_ctl
.ctl_recvsize
= 512 * 1024;
145 kern_ctl
.ctl_connect
= utun_ctl_connect
;
146 kern_ctl
.ctl_disconnect
= utun_ctl_disconnect
;
147 kern_ctl
.ctl_send
= utun_ctl_send
;
148 kern_ctl
.ctl_setopt
= utun_ctl_setopt
;
149 kern_ctl
.ctl_getopt
= utun_ctl_getopt
;
150 kern_ctl
.ctl_rcvd
= utun_ctl_rcvd
;
152 utun_ctl_init_crypto();
154 result
= ctl_register(&kern_ctl
, &utun_kctlref
);
156 printf("utun_register_control - ctl_register failed: %d\n", result
);
160 /* Register the protocol plumbers */
161 if ((result
= proto_register_plumber(PF_INET
, utun_family
,
162 utun_attach_proto
, NULL
)) != 0) {
163 printf("utun_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n",
164 utun_family
, result
);
165 ctl_deregister(utun_kctlref
);
169 /* Register the protocol plumbers */
170 if ((result
= proto_register_plumber(PF_INET6
, utun_family
,
171 utun_attach_proto
, NULL
)) != 0) {
172 proto_unregister_plumber(PF_INET
, utun_family
);
173 ctl_deregister(utun_kctlref
);
174 printf("utun_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n",
175 utun_family
, result
);
182 /* Kernel control functions */
186 kern_ctl_ref kctlref
,
187 struct sockaddr_ctl
*sac
,
190 struct ifnet_init_eparams utun_init
;
191 struct utun_pcb
*pcb
;
193 struct ifnet_stats_param stats
;
195 /* kernel control allocates, interface frees */
196 pcb
= utun_alloc(sizeof(*pcb
));
200 /* Setup the protocol control block */
201 bzero(pcb
, sizeof(*pcb
));
203 pcb
->utun_ctlref
= kctlref
;
204 pcb
->utun_unit
= sac
->sc_unit
;
205 pcb
->utun_max_pending_packets
= 1;
207 printf("utun_ctl_connect: creating interface utun%d\n", pcb
->utun_unit
- 1);
209 /* Create the interface */
210 bzero(&utun_init
, sizeof(utun_init
));
211 utun_init
.ver
= IFNET_INIT_CURRENT_VERSION
;
212 utun_init
.len
= sizeof (utun_init
);
213 utun_init
.name
= "utun";
214 utun_init
.start
= utun_start
;
215 utun_init
.unit
= pcb
->utun_unit
- 1;
216 utun_init
.family
= utun_family
;
217 utun_init
.type
= IFT_OTHER
;
218 utun_init
.demux
= utun_demux
;
219 utun_init
.framer_extended
= utun_framer
;
220 utun_init
.add_proto
= utun_add_proto
;
221 utun_init
.del_proto
= utun_del_proto
;
222 utun_init
.softc
= pcb
;
223 utun_init
.ioctl
= utun_ioctl
;
224 utun_init
.detach
= utun_detached
;
226 result
= ifnet_allocate_extended(&utun_init
, &pcb
->utun_ifp
);
228 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
232 OSIncrementAtomic(&utun_ifcount
);
234 /* Set flags and additional information. */
235 ifnet_set_mtu(pcb
->utun_ifp
, 1500);
236 ifnet_set_flags(pcb
->utun_ifp
, IFF_UP
| IFF_MULTICAST
| IFF_POINTOPOINT
, 0xffff);
238 /* The interface must generate its own IPv6 LinkLocal address,
239 * if possible following the recommendation of RFC2472 to the 64bit interface ID
241 ifnet_set_eflags(pcb
->utun_ifp
, IFEF_NOAUTOIPV6LL
, IFEF_NOAUTOIPV6LL
);
243 /* Reset the stats in case as the interface may have been recycled */
244 bzero(&stats
, sizeof(struct ifnet_stats_param
));
245 ifnet_set_stat(pcb
->utun_ifp
, &stats
);
247 /* Attach the interface */
248 result
= ifnet_attach(pcb
->utun_ifp
, NULL
);
250 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
251 ifnet_release(pcb
->utun_ifp
);
257 bpfattach(pcb
->utun_ifp
, DLT_NULL
, 4);
259 /* The interfaces resoures allocated, mark it as running */
261 ifnet_set_flags(pcb
->utun_ifp
, IFF_RUNNING
, IFF_RUNNING
);
269 protocol_family_t protocol
,
272 errno_t result
= EPROTONOSUPPORT
;
274 /* Attempt a detach */
275 if (protocol
== PF_INET
) {
278 bzero(&ifr
, sizeof(ifr
));
279 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
280 ifnet_name(interface
), ifnet_unit(interface
));
282 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH
, &ifr
);
284 else if (protocol
== PF_INET6
) {
285 struct in6_ifreq ifr6
;
287 bzero(&ifr6
, sizeof(ifr6
));
288 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
289 ifnet_name(interface
), ifnet_unit(interface
));
291 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH_IN6
, &ifr6
);
300 protocol_family_t protocol
,
306 /* Attempt a detach */
307 if (protocol
== PF_INET
) {
310 bzero(&ifr
, sizeof(ifr
));
311 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
312 ifnet_name(interface
), ifnet_unit(interface
));
313 result
= ifaddr_address(address
, &ifr
.ifr_addr
, sizeof(ifr
.ifr_addr
));
315 printf("utun_remove_address - ifaddr_address failed: %d", result
);
318 result
= sock_ioctl(pf_socket
, SIOCDIFADDR
, &ifr
);
320 printf("utun_remove_address - SIOCDIFADDR failed: %d", result
);
324 else if (protocol
== PF_INET6
) {
325 struct in6_ifreq ifr6
;
327 bzero(&ifr6
, sizeof(ifr6
));
328 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
329 ifnet_name(interface
), ifnet_unit(interface
));
330 result
= ifaddr_address(address
, (struct sockaddr
*)&ifr6
.ifr_addr
,
331 sizeof(ifr6
.ifr_addr
));
333 printf("utun_remove_address - ifaddr_address failed (v6): %d",
337 result
= sock_ioctl(pf_socket
, SIOCDIFADDR_IN6
, &ifr6
);
339 printf("utun_remove_address - SIOCDIFADDR_IN6 failed: %d",
349 protocol_family_t protocol
)
352 socket_t pf_socket
= NULL
;
353 ifaddr_t
*addresses
= NULL
;
356 if (protocol
!= PF_INET
&& protocol
!= PF_INET6
) {
357 printf("utun_cleanup_family - invalid protocol family %d\n", protocol
);
361 /* Create a socket for removing addresses and detaching the protocol */
362 result
= sock_socket(protocol
, SOCK_DGRAM
, 0, NULL
, NULL
, &pf_socket
);
364 if (result
!= EAFNOSUPPORT
)
365 printf("utun_cleanup_family - failed to create %s socket: %d\n",
366 protocol
== PF_INET
? "IP" : "IPv6", result
);
370 /* always set SS_PRIV, we want to close and detach regardless */
371 sock_setpriv(pf_socket
, 1);
373 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
374 if (result
== 0 || result
== ENXIO
) {
375 /* We are done! We either detached or weren't attached. */
378 else if (result
!= EBUSY
) {
379 /* Uh, not really sure what happened here... */
380 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
385 * At this point, we received an EBUSY error. This means there are
386 * addresses attached. We should detach them and then try again.
388 result
= ifnet_get_address_list_family(interface
, &addresses
, protocol
);
390 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
391 ifnet_name(interface
), ifnet_unit(interface
),
392 protocol
== PF_INET
? "PF_INET" : "PF_INET6", result
);
396 for (i
= 0; addresses
[i
] != 0; i
++) {
397 utun_remove_address(interface
, protocol
, addresses
[i
], pf_socket
);
399 ifnet_free_address_list(addresses
);
403 * The addresses should be gone, we should try the remove again.
405 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
406 if (result
!= 0 && result
!= ENXIO
) {
407 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
411 if (pf_socket
!= NULL
)
412 sock_close(pf_socket
);
414 if (addresses
!= NULL
)
415 ifnet_free_address_list(addresses
);
420 __unused kern_ctl_ref kctlref
,
421 __unused u_int32_t unit
,
424 struct utun_pcb
*pcb
= unitinfo
;
425 ifnet_t ifp
= pcb
->utun_ifp
;
428 utun_cleanup_crypto(pcb
);
430 pcb
->utun_ctlref
= NULL
;
434 * We want to do everything in our power to ensure that the interface
435 * really goes away when the socket is closed. We must remove IP/IPv6
436 * addresses and detach the protocols. Finally, we can remove and
437 * release the interface.
439 utun_cleanup_family(ifp
, AF_INET
);
440 utun_cleanup_family(ifp
, AF_INET6
);
442 if ((result
= ifnet_detach(ifp
)) != 0) {
443 printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result
);
446 if ((result
= ifnet_release(ifp
)) != 0) {
447 printf("utun_ctl_disconnect - ifnet_release failed: %d\n", result
);
455 __unused kern_ctl_ref kctlref
,
456 __unused u_int32_t unit
,
462 * The userland ABI requires the first four bytes have the protocol family
463 * in network byte order: swap them
465 if (m_pktlen(m
) >= 4)
466 *(protocol_family_t
*)mbuf_data(m
) = ntohl(*(protocol_family_t
*)mbuf_data(m
));
468 printf("%s - unexpected short mbuf pkt len %d\n", __func__
, m_pktlen(m
) );
470 return utun_pkt_input((struct utun_pcb
*)unitinfo
, m
);
475 __unused kern_ctl_ref kctlref
,
476 __unused u_int32_t unit
,
482 struct utun_pcb
*pcb
= unitinfo
;
485 /* check for privileges for privileged options */
488 case UTUN_OPT_EXT_IFDATA_STATS
:
489 case UTUN_OPT_SET_DELEGATE_INTERFACE
:
490 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
498 if (len
!= sizeof(u_int32_t
))
501 pcb
->utun_flags
= *(u_int32_t
*)data
;
504 case UTUN_OPT_ENABLE_CRYPTO
:
505 result
= utun_ctl_enable_crypto(kctlref
, unit
, unitinfo
, opt
, data
, len
);
508 case UTUN_OPT_CONFIG_CRYPTO_KEYS
:
509 result
= utun_ctl_config_crypto_keys(kctlref
, unit
, unitinfo
, opt
, data
, len
);
512 case UTUN_OPT_UNCONFIG_CRYPTO_KEYS
:
513 result
= utun_ctl_unconfig_crypto_keys(kctlref
, unit
, unitinfo
, opt
, data
, len
);
516 case UTUN_OPT_DISABLE_CRYPTO
:
517 result
= utun_ctl_disable_crypto(kctlref
, unit
, unitinfo
, opt
, data
, len
);
520 case UTUN_OPT_STOP_CRYPTO_DATA_TRAFFIC
:
521 result
= utun_ctl_stop_crypto_data_traffic(kctlref
, unit
, unitinfo
, opt
, data
, len
);
524 case UTUN_OPT_START_CRYPTO_DATA_TRAFFIC
:
525 result
= utun_ctl_start_crypto_data_traffic(kctlref
, unit
, unitinfo
, opt
, data
, len
);
528 case UTUN_OPT_CONFIG_CRYPTO_FRAMER
:
529 result
= utun_ctl_config_crypto_framer(kctlref
, unit
, unitinfo
, opt
, data
, len
);
532 case UTUN_OPT_UNCONFIG_CRYPTO_FRAMER
:
533 result
= utun_ctl_unconfig_crypto_framer(kctlref
, unit
, unitinfo
, opt
, data
, len
);
536 case UTUN_OPT_EXT_IFDATA_STATS
:
537 if (len
!= sizeof(int)) {
541 pcb
->utun_ext_ifdata_stats
= (*(int *)data
) ? 1 : 0;
544 case UTUN_OPT_INC_IFDATA_STATS_IN
:
545 case UTUN_OPT_INC_IFDATA_STATS_OUT
: {
546 struct utun_stats_param
*utsp
= (struct utun_stats_param
*)data
;
548 if (utsp
== NULL
|| len
< sizeof(struct utun_stats_param
)) {
552 if (!pcb
->utun_ext_ifdata_stats
) {
556 if (opt
== UTUN_OPT_INC_IFDATA_STATS_IN
)
557 ifnet_stat_increment_in(pcb
->utun_ifp
, utsp
->utsp_packets
,
558 utsp
->utsp_bytes
, utsp
->utsp_errors
);
560 ifnet_stat_increment_out(pcb
->utun_ifp
, utsp
->utsp_packets
,
561 utsp
->utsp_bytes
, utsp
->utsp_errors
);
564 case UTUN_OPT_SET_DELEGATE_INTERFACE
: {
565 ifnet_t del_ifp
= NULL
;
568 if (len
> IFNAMSIZ
- 1) {
572 if (len
!= 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */
573 bcopy(data
, name
, len
);
575 result
= ifnet_find_by_name(name
, &del_ifp
);
578 result
= ifnet_set_delegate(pcb
->utun_ifp
, del_ifp
);
580 ifnet_release(del_ifp
);
584 case UTUN_OPT_MAX_PENDING_PACKETS
: {
585 u_int32_t max_pending_packets
= 0;
586 if (len
!= sizeof(u_int32_t
)) {
590 max_pending_packets
= *(u_int32_t
*)data
;
591 if (max_pending_packets
== 0) {
595 pcb
->utun_max_pending_packets
= max_pending_packets
;
599 result
= ENOPROTOOPT
;
609 __unused kern_ctl_ref kctlref
,
610 __unused u_int32_t unit
,
616 struct utun_pcb
*pcb
= unitinfo
;
621 if (*len
!= sizeof(u_int32_t
))
624 *(u_int32_t
*)data
= pcb
->utun_flags
;
627 case UTUN_OPT_EXT_IFDATA_STATS
:
628 if (*len
!= sizeof(int))
631 *(int *)data
= (pcb
->utun_ext_ifdata_stats
) ? 1 : 0;
634 case UTUN_OPT_IFNAME
:
635 *len
= snprintf(data
, *len
, "%s%d", ifnet_name(pcb
->utun_ifp
), ifnet_unit(pcb
->utun_ifp
)) + 1;
638 case UTUN_OPT_GENERATE_CRYPTO_KEYS_IDX
:
639 result
= utun_ctl_generate_crypto_keys_idx(kctlref
, unit
, unitinfo
, opt
, data
, len
);
641 case UTUN_OPT_MAX_PENDING_PACKETS
: {
642 *len
= sizeof(u_int32_t
);
643 *((u_int32_t
*)data
) = pcb
->utun_max_pending_packets
;
647 result
= ENOPROTOOPT
;
655 utun_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int flags
)
657 #pragma unused(flags)
658 bool reenable_output
= false;
659 struct utun_pcb
*pcb
= unitinfo
;
663 ifnet_lock_exclusive(pcb
->utun_ifp
);
665 u_int32_t utun_packet_cnt
;
666 errno_t error_pc
= ctl_getenqueuepacketcount(kctlref
, unit
, &utun_packet_cnt
);
668 printf("utun_ctl_rcvd: ctl_getenqueuepacketcount returned error %d\n", error_pc
);
672 if (utun_packet_cnt
< pcb
->utun_max_pending_packets
) {
673 reenable_output
= true;
676 if (reenable_output
) {
677 errno_t error
= ifnet_enable_output(pcb
->utun_ifp
);
679 printf("utun_ctl_rcvd: ifnet_enable_output returned error %d\n", error
);
682 ifnet_lock_done(pcb
->utun_ifp
);
685 /* Network Interface functions */
687 utun_start(ifnet_t interface
)
690 struct utun_pcb
*pcb
= ifnet_softc(interface
);
692 bool can_accept_packets
= true;
693 ifnet_lock_shared(pcb
->utun_ifp
);
695 u_int32_t utun_packet_cnt
;
696 errno_t error_pc
= ctl_getenqueuepacketcount(pcb
->utun_ctlref
, pcb
->utun_unit
, &utun_packet_cnt
);
698 printf("utun_start: ctl_getenqueuepacketcount returned error %d\n", error_pc
);
702 can_accept_packets
= (utun_packet_cnt
< pcb
->utun_max_pending_packets
);
703 if (!can_accept_packets
&& pcb
->utun_ctlref
) {
704 u_int32_t difference
= 0;
705 if (ctl_getenqueuereadable(pcb
->utun_ctlref
, pcb
->utun_unit
, &difference
) == 0) {
706 if (difference
> 0) {
707 // If the low-water mark has not yet been reached, we still need to enqueue data
709 can_accept_packets
= true;
713 if (!can_accept_packets
) {
714 errno_t error
= ifnet_disable_output(interface
);
716 printf("utun_start: ifnet_disable_output returned error %d\n", error
);
718 ifnet_lock_done(pcb
->utun_ifp
);
721 ifnet_lock_done(pcb
->utun_ifp
);
722 if (ifnet_dequeue(interface
, &data
) != 0)
724 if (utun_output(interface
, data
) != 0)
734 struct utun_pcb
*pcb
= ifnet_softc(interface
);
737 if (m_pktlen(data
) >= 4) {
738 bpf_tap_out(pcb
->utun_ifp
, DLT_NULL
, data
, 0, 0);
741 if (pcb
->utun_flags
& UTUN_FLAGS_NO_OUTPUT
) {
747 // otherwise, fall thru to ctl_enqueumbuf
748 if (pcb
->utun_ctlref
) {
751 // only pass packets to utun-crypto if crypto is enabled and 'suspend data traffic' is not.
752 if ((pcb
->utun_flags
& (UTUN_FLAGS_CRYPTO
| UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC
)) == UTUN_FLAGS_CRYPTO
) {
753 if (utun_pkt_crypto_output(pcb
, &data
) == 0) {
759 * The ABI requires the protocol in network byte order
761 if (m_pktlen(data
) >= 4)
762 *(u_int32_t
*)mbuf_data(data
) = htonl(*(u_int32_t
*)mbuf_data(data
));
764 length
= mbuf_pkthdr_len(data
);
765 result
= ctl_enqueuembuf(pcb
->utun_ctlref
, pcb
->utun_unit
, data
, CTL_DATA_EOR
);
768 printf("utun_output - ctl_enqueuembuf failed: %d\n", result
);
770 ifnet_stat_increment_out(interface
, 0, 0, 1);
773 if (!pcb
->utun_ext_ifdata_stats
)
774 ifnet_stat_increment_out(interface
, 1, length
, 0);
785 __unused ifnet_t interface
,
787 __unused
char *frame_header
,
788 protocol_family_t
*protocol
)
791 while (data
!= NULL
&& mbuf_len(data
) < 1) {
792 data
= mbuf_next(data
);
798 *protocol
= *(u_int32_t
*)mbuf_data(data
);
804 __unused ifnet_t interface
,
806 __unused
const struct sockaddr
*dest
,
807 __unused
const char *desk_linkaddr
,
808 const char *frame_type
,
809 u_int32_t
*prepend_len
,
810 u_int32_t
*postpend_len
)
812 if (mbuf_prepend(packet
, sizeof(protocol_family_t
), MBUF_DONTWAIT
) != 0) {
813 printf("utun_framer - ifnet_output prepend failed\n");
815 ifnet_stat_increment_out(interface
, 0, 0, 1);
817 // just return, because the buffer was freed in mbuf_prepend
820 if (prepend_len
!= NULL
)
821 *prepend_len
= sizeof(protocol_family_t
);
822 if (postpend_len
!= NULL
)
825 // place protocol number at the beginning of the mbuf
826 *(protocol_family_t
*)mbuf_data(*packet
) = *(protocol_family_t
*)(uintptr_t)(size_t)frame_type
;
833 __unused ifnet_t interface
,
834 protocol_family_t protocol
,
835 __unused
const struct ifnet_demux_desc
*demux_array
,
836 __unused u_int32_t demux_count
)
852 __unused ifnet_t interface
,
853 __unused protocol_family_t protocol
)
868 ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
);
872 /* ifioctl() takes care of it */
886 struct utun_pcb
*pcb
= ifnet_softc(interface
);
890 OSDecrementAtomic(&utun_ifcount
);
893 /* Protocol Handlers */
897 __unused ifnet_t interface
,
898 protocol_family_t protocol
,
900 __unused
char *frame_header
)
903 // remove protocol family first
904 mbuf_adj(m
, sizeof(u_int32_t
));
906 if (proto_input(protocol
, m
) != 0)
913 utun_proto_pre_output(
914 __unused ifnet_t interface
,
915 protocol_family_t protocol
,
916 __unused mbuf_t
*packet
,
917 __unused
const struct sockaddr
*dest
,
918 __unused
void *route
,
919 __unused
char *frame_type
,
920 __unused
char *link_layer_dest
)
923 *(protocol_family_t
*)(void *)frame_type
= protocol
;
930 protocol_family_t protocol
)
932 struct ifnet_attach_proto_param proto
;
935 bzero(&proto
, sizeof(proto
));
936 proto
.input
= utun_proto_input
;
937 proto
.pre_output
= utun_proto_pre_output
;
939 result
= ifnet_attach_protocol(interface
, protocol
, &proto
);
940 if (result
!= 0 && result
!= EEXIST
) {
941 printf("utun_attach_inet - ifnet_attach_protocol %d failed: %d\n",
949 utun_pkt_input (struct utun_pcb
*pcb
, mbuf_t m
)
952 protocol_family_t protocol
= 0;
954 mbuf_pkthdr_setrcvif(m
, pcb
->utun_ifp
);
956 if (m_pktlen(m
) >= 4) {
957 protocol
= *(u_int32_t
*)mbuf_data(m
);
959 bpf_tap_in(pcb
->utun_ifp
, DLT_NULL
, m
, 0, 0);
961 if (pcb
->utun_flags
& UTUN_FLAGS_NO_INPUT
) {
967 // quick exit for keepalive packets
968 if (protocol
== AF_UTUN
&& pcb
->utun_flags
& UTUN_FLAGS_CRYPTO
) {
969 if (utun_pkt_crypto_output(pcb
, &m
) == 0) {
972 printf("%s: utun_pkt_crypto_output failed, flags %x\n", __FUNCTION__
, pcb
->utun_flags
);
976 if (!pcb
->utun_ext_ifdata_stats
) {
977 struct ifnet_stat_increment_param incs
;
979 bzero(&incs
, sizeof(incs
));
981 incs
.bytes_in
= mbuf_pkthdr_len(m
);
982 result
= ifnet_input(pcb
->utun_ifp
, m
, &incs
);
984 result
= ifnet_input(pcb
->utun_ifp
, m
, NULL
);
987 ifnet_stat_increment_in(pcb
->utun_ifp
, 0, 0, 1);
989 printf("%s - ifnet_input failed: %d\n", __FUNCTION__
, result
);