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_pending_packets
= 0;
206 pcb
->utun_max_pending_packets
= 1;
208 printf("utun_ctl_connect: creating interface utun%d\n", pcb
->utun_unit
- 1);
210 /* Create the interface */
211 bzero(&utun_init
, sizeof(utun_init
));
212 utun_init
.ver
= IFNET_INIT_CURRENT_VERSION
;
213 utun_init
.len
= sizeof (utun_init
);
214 utun_init
.name
= "utun";
215 utun_init
.start
= utun_start
;
216 utun_init
.unit
= pcb
->utun_unit
- 1;
217 utun_init
.family
= utun_family
;
218 utun_init
.type
= IFT_OTHER
;
219 utun_init
.demux
= utun_demux
;
220 utun_init
.framer_extended
= utun_framer
;
221 utun_init
.add_proto
= utun_add_proto
;
222 utun_init
.del_proto
= utun_del_proto
;
223 utun_init
.softc
= pcb
;
224 utun_init
.ioctl
= utun_ioctl
;
225 utun_init
.detach
= utun_detached
;
227 result
= ifnet_allocate_extended(&utun_init
, &pcb
->utun_ifp
);
229 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
233 OSIncrementAtomic(&utun_ifcount
);
235 /* Set flags and additional information. */
236 ifnet_set_mtu(pcb
->utun_ifp
, 1500);
237 ifnet_set_flags(pcb
->utun_ifp
, IFF_UP
| IFF_MULTICAST
| IFF_POINTOPOINT
, 0xffff);
239 /* The interface must generate its own IPv6 LinkLocal address,
240 * if possible following the recommendation of RFC2472 to the 64bit interface ID
242 ifnet_set_eflags(pcb
->utun_ifp
, IFEF_NOAUTOIPV6LL
, IFEF_NOAUTOIPV6LL
);
244 /* Reset the stats in case as the interface may have been recycled */
245 bzero(&stats
, sizeof(struct ifnet_stats_param
));
246 ifnet_set_stat(pcb
->utun_ifp
, &stats
);
248 /* Attach the interface */
249 result
= ifnet_attach(pcb
->utun_ifp
, NULL
);
251 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
252 ifnet_release(pcb
->utun_ifp
);
258 bpfattach(pcb
->utun_ifp
, DLT_NULL
, 4);
260 /* The interfaces resoures allocated, mark it as running */
262 ifnet_set_flags(pcb
->utun_ifp
, IFF_RUNNING
, IFF_RUNNING
);
270 protocol_family_t protocol
,
273 errno_t result
= EPROTONOSUPPORT
;
275 /* Attempt a detach */
276 if (protocol
== PF_INET
) {
279 bzero(&ifr
, sizeof(ifr
));
280 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
281 ifnet_name(interface
), ifnet_unit(interface
));
283 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH
, &ifr
);
285 else if (protocol
== PF_INET6
) {
286 struct in6_ifreq ifr6
;
288 bzero(&ifr6
, sizeof(ifr6
));
289 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
290 ifnet_name(interface
), ifnet_unit(interface
));
292 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH_IN6
, &ifr6
);
301 protocol_family_t protocol
,
307 /* Attempt a detach */
308 if (protocol
== PF_INET
) {
311 bzero(&ifr
, sizeof(ifr
));
312 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
313 ifnet_name(interface
), ifnet_unit(interface
));
314 result
= ifaddr_address(address
, &ifr
.ifr_addr
, sizeof(ifr
.ifr_addr
));
316 printf("utun_remove_address - ifaddr_address failed: %d", result
);
319 result
= sock_ioctl(pf_socket
, SIOCDIFADDR
, &ifr
);
321 printf("utun_remove_address - SIOCDIFADDR failed: %d", result
);
325 else if (protocol
== PF_INET6
) {
326 struct in6_ifreq ifr6
;
328 bzero(&ifr6
, sizeof(ifr6
));
329 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
330 ifnet_name(interface
), ifnet_unit(interface
));
331 result
= ifaddr_address(address
, (struct sockaddr
*)&ifr6
.ifr_addr
,
332 sizeof(ifr6
.ifr_addr
));
334 printf("utun_remove_address - ifaddr_address failed (v6): %d",
338 result
= sock_ioctl(pf_socket
, SIOCDIFADDR_IN6
, &ifr6
);
340 printf("utun_remove_address - SIOCDIFADDR_IN6 failed: %d",
350 protocol_family_t protocol
)
353 socket_t pf_socket
= NULL
;
354 ifaddr_t
*addresses
= NULL
;
357 if (protocol
!= PF_INET
&& protocol
!= PF_INET6
) {
358 printf("utun_cleanup_family - invalid protocol family %d\n", protocol
);
362 /* Create a socket for removing addresses and detaching the protocol */
363 result
= sock_socket(protocol
, SOCK_DGRAM
, 0, NULL
, NULL
, &pf_socket
);
365 if (result
!= EAFNOSUPPORT
)
366 printf("utun_cleanup_family - failed to create %s socket: %d\n",
367 protocol
== PF_INET
? "IP" : "IPv6", result
);
371 /* always set SS_PRIV, we want to close and detach regardless */
372 sock_setpriv(pf_socket
, 1);
374 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
375 if (result
== 0 || result
== ENXIO
) {
376 /* We are done! We either detached or weren't attached. */
379 else if (result
!= EBUSY
) {
380 /* Uh, not really sure what happened here... */
381 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
386 * At this point, we received an EBUSY error. This means there are
387 * addresses attached. We should detach them and then try again.
389 result
= ifnet_get_address_list_family(interface
, &addresses
, protocol
);
391 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
392 ifnet_name(interface
), ifnet_unit(interface
),
393 protocol
== PF_INET
? "PF_INET" : "PF_INET6", result
);
397 for (i
= 0; addresses
[i
] != 0; i
++) {
398 utun_remove_address(interface
, protocol
, addresses
[i
], pf_socket
);
400 ifnet_free_address_list(addresses
);
404 * The addresses should be gone, we should try the remove again.
406 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
407 if (result
!= 0 && result
!= ENXIO
) {
408 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
412 if (pf_socket
!= NULL
)
413 sock_close(pf_socket
);
415 if (addresses
!= NULL
)
416 ifnet_free_address_list(addresses
);
421 __unused kern_ctl_ref kctlref
,
422 __unused u_int32_t unit
,
425 struct utun_pcb
*pcb
= unitinfo
;
426 ifnet_t ifp
= pcb
->utun_ifp
;
429 utun_cleanup_crypto(pcb
);
431 pcb
->utun_ctlref
= NULL
;
435 * We want to do everything in our power to ensure that the interface
436 * really goes away when the socket is closed. We must remove IP/IPv6
437 * addresses and detach the protocols. Finally, we can remove and
438 * release the interface.
440 utun_cleanup_family(ifp
, AF_INET
);
441 utun_cleanup_family(ifp
, AF_INET6
);
443 if ((result
= ifnet_detach(ifp
)) != 0) {
444 printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result
);
447 if ((result
= ifnet_release(ifp
)) != 0) {
448 printf("utun_ctl_disconnect - ifnet_release failed: %d\n", result
);
456 __unused kern_ctl_ref kctlref
,
457 __unused u_int32_t unit
,
463 * The userland ABI requires the first four bytes have the protocol family
464 * in network byte order: swap them
466 if (m_pktlen(m
) >= 4)
467 *(protocol_family_t
*)mbuf_data(m
) = ntohl(*(protocol_family_t
*)mbuf_data(m
));
469 printf("%s - unexpected short mbuf pkt len %d\n", __func__
, m_pktlen(m
) );
471 return utun_pkt_input((struct utun_pcb
*)unitinfo
, m
);
476 __unused kern_ctl_ref kctlref
,
477 __unused u_int32_t unit
,
483 struct utun_pcb
*pcb
= unitinfo
;
486 /* check for privileges for privileged options */
489 case UTUN_OPT_EXT_IFDATA_STATS
:
490 case UTUN_OPT_SET_DELEGATE_INTERFACE
:
491 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
499 if (len
!= sizeof(u_int32_t
))
502 pcb
->utun_flags
= *(u_int32_t
*)data
;
505 case UTUN_OPT_ENABLE_CRYPTO
:
506 result
= utun_ctl_enable_crypto(kctlref
, unit
, unitinfo
, opt
, data
, len
);
509 case UTUN_OPT_CONFIG_CRYPTO_KEYS
:
510 result
= utun_ctl_config_crypto_keys(kctlref
, unit
, unitinfo
, opt
, data
, len
);
513 case UTUN_OPT_UNCONFIG_CRYPTO_KEYS
:
514 result
= utun_ctl_unconfig_crypto_keys(kctlref
, unit
, unitinfo
, opt
, data
, len
);
517 case UTUN_OPT_DISABLE_CRYPTO
:
518 result
= utun_ctl_disable_crypto(kctlref
, unit
, unitinfo
, opt
, data
, len
);
521 case UTUN_OPT_STOP_CRYPTO_DATA_TRAFFIC
:
522 result
= utun_ctl_stop_crypto_data_traffic(kctlref
, unit
, unitinfo
, opt
, data
, len
);
525 case UTUN_OPT_START_CRYPTO_DATA_TRAFFIC
:
526 result
= utun_ctl_start_crypto_data_traffic(kctlref
, unit
, unitinfo
, opt
, data
, len
);
529 case UTUN_OPT_CONFIG_CRYPTO_FRAMER
:
530 result
= utun_ctl_config_crypto_framer(kctlref
, unit
, unitinfo
, opt
, data
, len
);
533 case UTUN_OPT_UNCONFIG_CRYPTO_FRAMER
:
534 result
= utun_ctl_unconfig_crypto_framer(kctlref
, unit
, unitinfo
, opt
, data
, len
);
537 case UTUN_OPT_EXT_IFDATA_STATS
:
538 if (len
!= sizeof(int)) {
542 pcb
->utun_ext_ifdata_stats
= (*(int *)data
) ? 1 : 0;
545 case UTUN_OPT_INC_IFDATA_STATS_IN
:
546 case UTUN_OPT_INC_IFDATA_STATS_OUT
: {
547 struct utun_stats_param
*utsp
= (struct utun_stats_param
*)data
;
549 if (utsp
== NULL
|| len
< sizeof(struct utun_stats_param
)) {
553 if (!pcb
->utun_ext_ifdata_stats
) {
557 if (opt
== UTUN_OPT_INC_IFDATA_STATS_IN
)
558 ifnet_stat_increment_in(pcb
->utun_ifp
, utsp
->utsp_packets
,
559 utsp
->utsp_bytes
, utsp
->utsp_errors
);
561 ifnet_stat_increment_out(pcb
->utun_ifp
, utsp
->utsp_packets
,
562 utsp
->utsp_bytes
, utsp
->utsp_errors
);
565 case UTUN_OPT_SET_DELEGATE_INTERFACE
: {
566 ifnet_t del_ifp
= NULL
;
569 if (len
> IFNAMSIZ
- 1) {
573 if (len
!= 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */
574 bcopy(data
, name
, len
);
576 result
= ifnet_find_by_name(name
, &del_ifp
);
579 result
= ifnet_set_delegate(pcb
->utun_ifp
, del_ifp
);
581 ifnet_release(del_ifp
);
585 case UTUN_OPT_MAX_PENDING_PACKETS
: {
586 u_int32_t max_pending_packets
= 0;
587 if (len
!= sizeof(u_int32_t
)) {
591 max_pending_packets
= *(u_int32_t
*)data
;
592 if (max_pending_packets
== 0) {
596 pcb
->utun_max_pending_packets
= max_pending_packets
;
600 result
= ENOPROTOOPT
;
610 __unused kern_ctl_ref kctlref
,
611 __unused u_int32_t unit
,
617 struct utun_pcb
*pcb
= unitinfo
;
622 if (*len
!= sizeof(u_int32_t
))
625 *(u_int32_t
*)data
= pcb
->utun_flags
;
628 case UTUN_OPT_EXT_IFDATA_STATS
:
629 if (*len
!= sizeof(int))
632 *(int *)data
= (pcb
->utun_ext_ifdata_stats
) ? 1 : 0;
635 case UTUN_OPT_IFNAME
:
636 *len
= snprintf(data
, *len
, "%s%d", ifnet_name(pcb
->utun_ifp
), ifnet_unit(pcb
->utun_ifp
)) + 1;
639 case UTUN_OPT_GENERATE_CRYPTO_KEYS_IDX
:
640 result
= utun_ctl_generate_crypto_keys_idx(kctlref
, unit
, unitinfo
, opt
, data
, len
);
642 case UTUN_OPT_MAX_PENDING_PACKETS
: {
643 *len
= sizeof(u_int32_t
);
644 *((u_int32_t
*)data
) = pcb
->utun_max_pending_packets
;
648 result
= ENOPROTOOPT
;
656 utun_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int flags
)
658 #pragma unused(kctlref, unit, flags)
659 bool reenable_output
= false;
660 struct utun_pcb
*pcb
= unitinfo
;
664 ifnet_lock_exclusive(pcb
->utun_ifp
);
665 if (pcb
->utun_pending_packets
> 0) {
666 pcb
->utun_pending_packets
--;
667 if (pcb
->utun_pending_packets
< pcb
->utun_max_pending_packets
) {
668 reenable_output
= true;
672 if (reenable_output
) {
673 errno_t error
= ifnet_enable_output(pcb
->utun_ifp
);
675 printf("utun_ctl_rcvd: ifnet_enable_output returned error %d\n", error
);
678 ifnet_lock_done(pcb
->utun_ifp
);
681 /* Network Interface functions */
683 utun_start(ifnet_t interface
)
686 struct utun_pcb
*pcb
= ifnet_softc(interface
);
688 bool can_accept_packets
= true;
689 ifnet_lock_shared(pcb
->utun_ifp
);
690 can_accept_packets
= (pcb
->utun_pending_packets
< pcb
->utun_max_pending_packets
);
691 if (!can_accept_packets
&& pcb
->utun_ctlref
) {
692 u_int32_t difference
= 0;
693 if (ctl_getenqueuereadable(pcb
->utun_ctlref
, pcb
->utun_unit
, &difference
) == 0) {
694 if (difference
> 0) {
695 // If the low-water mark has not yet been reached, we still need to enqueue data
697 can_accept_packets
= true;
701 if (!can_accept_packets
) {
702 errno_t error
= ifnet_disable_output(interface
);
704 printf("utun_start: ifnet_disable_output returned error %d\n", error
);
706 ifnet_lock_done(pcb
->utun_ifp
);
709 ifnet_lock_done(pcb
->utun_ifp
);
710 if (ifnet_dequeue(interface
, &data
) != 0)
712 if (utun_output(interface
, data
) != 0)
722 struct utun_pcb
*pcb
= ifnet_softc(interface
);
725 if (m_pktlen(data
) >= 4) {
726 bpf_tap_out(pcb
->utun_ifp
, DLT_NULL
, data
, 0, 0);
729 if (pcb
->utun_flags
& UTUN_FLAGS_NO_OUTPUT
) {
735 // otherwise, fall thru to ctl_enqueumbuf
736 if (pcb
->utun_ctlref
) {
739 // only pass packets to utun-crypto if crypto is enabled and 'suspend data traffic' is not.
740 if ((pcb
->utun_flags
& (UTUN_FLAGS_CRYPTO
| UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC
)) == UTUN_FLAGS_CRYPTO
) {
741 if (utun_pkt_crypto_output(pcb
, &data
) == 0) {
747 * The ABI requires the protocol in network byte order
749 if (m_pktlen(data
) >= 4)
750 *(u_int32_t
*)mbuf_data(data
) = htonl(*(u_int32_t
*)mbuf_data(data
));
752 length
= mbuf_pkthdr_len(data
);
753 // Increment packet count optimistically
754 ifnet_lock_exclusive(pcb
->utun_ifp
);
755 pcb
->utun_pending_packets
++;
756 ifnet_lock_done(pcb
->utun_ifp
);
757 result
= ctl_enqueuembuf(pcb
->utun_ctlref
, pcb
->utun_unit
, data
, CTL_DATA_EOR
);
759 // Decrement packet count if errored
760 ifnet_lock_exclusive(pcb
->utun_ifp
);
761 pcb
->utun_pending_packets
--;
762 ifnet_lock_done(pcb
->utun_ifp
);
764 printf("utun_output - ctl_enqueuembuf failed: %d\n", result
);
766 ifnet_stat_increment_out(interface
, 0, 0, 1);
769 if (!pcb
->utun_ext_ifdata_stats
)
770 ifnet_stat_increment_out(interface
, 1, length
, 0);
781 __unused ifnet_t interface
,
783 __unused
char *frame_header
,
784 protocol_family_t
*protocol
)
787 while (data
!= NULL
&& mbuf_len(data
) < 1) {
788 data
= mbuf_next(data
);
794 *protocol
= *(u_int32_t
*)mbuf_data(data
);
800 __unused ifnet_t interface
,
802 __unused
const struct sockaddr
*dest
,
803 __unused
const char *desk_linkaddr
,
804 const char *frame_type
,
805 u_int32_t
*prepend_len
,
806 u_int32_t
*postpend_len
)
808 if (mbuf_prepend(packet
, sizeof(protocol_family_t
), MBUF_DONTWAIT
) != 0) {
809 printf("utun_framer - ifnet_output prepend failed\n");
811 ifnet_stat_increment_out(interface
, 0, 0, 1);
813 // just return, because the buffer was freed in mbuf_prepend
816 if (prepend_len
!= NULL
)
817 *prepend_len
= sizeof(protocol_family_t
);
818 if (postpend_len
!= NULL
)
821 // place protocol number at the beginning of the mbuf
822 *(protocol_family_t
*)mbuf_data(*packet
) = *(protocol_family_t
*)(uintptr_t)(size_t)frame_type
;
829 __unused ifnet_t interface
,
830 protocol_family_t protocol
,
831 __unused
const struct ifnet_demux_desc
*demux_array
,
832 __unused u_int32_t demux_count
)
848 __unused ifnet_t interface
,
849 __unused protocol_family_t protocol
)
864 ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
);
868 /* ifioctl() takes care of it */
882 struct utun_pcb
*pcb
= ifnet_softc(interface
);
886 OSDecrementAtomic(&utun_ifcount
);
889 /* Protocol Handlers */
893 __unused ifnet_t interface
,
894 protocol_family_t protocol
,
896 __unused
char *frame_header
)
899 // remove protocol family first
900 mbuf_adj(m
, sizeof(u_int32_t
));
902 if (proto_input(protocol
, m
) != 0)
909 utun_proto_pre_output(
910 __unused ifnet_t interface
,
911 protocol_family_t protocol
,
912 __unused mbuf_t
*packet
,
913 __unused
const struct sockaddr
*dest
,
914 __unused
void *route
,
915 __unused
char *frame_type
,
916 __unused
char *link_layer_dest
)
919 *(protocol_family_t
*)(void *)frame_type
= protocol
;
926 protocol_family_t protocol
)
928 struct ifnet_attach_proto_param proto
;
931 bzero(&proto
, sizeof(proto
));
932 proto
.input
= utun_proto_input
;
933 proto
.pre_output
= utun_proto_pre_output
;
935 result
= ifnet_attach_protocol(interface
, protocol
, &proto
);
936 if (result
!= 0 && result
!= EEXIST
) {
937 printf("utun_attach_inet - ifnet_attach_protocol %d failed: %d\n",
945 utun_pkt_input (struct utun_pcb
*pcb
, mbuf_t m
)
948 protocol_family_t protocol
= 0;
950 mbuf_pkthdr_setrcvif(m
, pcb
->utun_ifp
);
952 if (m_pktlen(m
) >= 4) {
953 protocol
= *(u_int32_t
*)mbuf_data(m
);
955 bpf_tap_in(pcb
->utun_ifp
, DLT_NULL
, m
, 0, 0);
957 if (pcb
->utun_flags
& UTUN_FLAGS_NO_INPUT
) {
963 // quick exit for keepalive packets
964 if (protocol
== AF_UTUN
&& pcb
->utun_flags
& UTUN_FLAGS_CRYPTO
) {
965 if (utun_pkt_crypto_output(pcb
, &m
) == 0) {
968 printf("%s: utun_pkt_crypto_output failed, flags %x\n", __FUNCTION__
, pcb
->utun_flags
);
972 if (!pcb
->utun_ext_ifdata_stats
) {
973 struct ifnet_stat_increment_param incs
;
975 bzero(&incs
, sizeof(incs
));
977 incs
.bytes_in
= mbuf_pkthdr_len(m
);
978 result
= ifnet_input(pcb
->utun_ifp
, m
, &incs
);
980 result
= ifnet_input(pcb
->utun_ifp
, m
, NULL
);
983 ifnet_stat_increment_in(pcb
->utun_ifp
, 0, 0, 1);
985 printf("%s - ifnet_input failed: %d\n", __FUNCTION__
, result
);