2 * Copyright (c) 2008-2016 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>
49 #include <sys/sockio.h>
50 #include <netinet/in.h>
51 #include <netinet6/in6_var.h>
52 #include <netinet6/in6_var.h>
53 #include <sys/kauth.h>
57 /* Kernel Control functions */
58 static errno_t
utun_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
60 static errno_t
utun_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
,
62 static errno_t
utun_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
,
63 void *unitinfo
, mbuf_t m
, int flags
);
64 static errno_t
utun_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
65 int opt
, void *data
, size_t *len
);
66 static errno_t
utun_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
67 int opt
, void *data
, size_t len
);
68 static void utun_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
71 /* Network Interface functions */
72 static void utun_start(ifnet_t interface
);
73 static errno_t
utun_output(ifnet_t interface
, mbuf_t data
);
74 static errno_t
utun_demux(ifnet_t interface
, mbuf_t data
, char *frame_header
,
75 protocol_family_t
*protocol
);
76 static errno_t
utun_framer(ifnet_t interface
, mbuf_t
*packet
,
77 const struct sockaddr
*dest
, const char *desk_linkaddr
,
78 const char *frame_type
, u_int32_t
*prepend_len
, u_int32_t
*postpend_len
);
79 static errno_t
utun_add_proto(ifnet_t interface
, protocol_family_t protocol
,
80 const struct ifnet_demux_desc
*demux_array
,
81 u_int32_t demux_count
);
82 static errno_t
utun_del_proto(ifnet_t interface
, protocol_family_t protocol
);
83 static errno_t
utun_ioctl(ifnet_t interface
, u_long cmd
, void *data
);
84 static void utun_detached(ifnet_t interface
);
86 /* Protocol handlers */
87 static errno_t
utun_attach_proto(ifnet_t interface
, protocol_family_t proto
);
88 static errno_t
utun_proto_input(ifnet_t interface
, protocol_family_t protocol
,
89 mbuf_t m
, char *frame_header
);
90 static errno_t
utun_proto_pre_output(ifnet_t interface
, protocol_family_t protocol
,
91 mbuf_t
*packet
, const struct sockaddr
*dest
, void *route
,
92 char *frame_type
, char *link_layer_dest
);
93 static errno_t
utun_pkt_input (struct utun_pcb
*pcb
, mbuf_t m
);
96 #define UTUN_DEFAULT_MTU 1500
97 #define UTUN_HEADER_SIZE(_pcb) (sizeof(u_int32_t) + (((_pcb)->utun_flags & UTUN_FLAGS_ENABLE_PROC_UUID) ? sizeof(uuid_t) : 0))
99 static kern_ctl_ref utun_kctlref
;
100 static u_int32_t utun_family
;
104 utun_register_control(void)
106 struct kern_ctl_reg kern_ctl
;
109 /* Find a unique value for our interface family */
110 result
= mbuf_tag_id_find(UTUN_CONTROL_NAME
, &utun_family
);
112 printf("utun_register_control - mbuf_tag_id_find_internal failed: %d\n", result
);
116 bzero(&kern_ctl
, sizeof(kern_ctl
));
117 strlcpy(kern_ctl
.ctl_name
, UTUN_CONTROL_NAME
, sizeof(kern_ctl
.ctl_name
));
118 kern_ctl
.ctl_name
[sizeof(kern_ctl
.ctl_name
) - 1] = 0;
119 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
| CTL_FLAG_REG_EXTENDED
; /* Require root */
120 kern_ctl
.ctl_sendsize
= 512 * 1024;
121 kern_ctl
.ctl_recvsize
= 512 * 1024;
122 kern_ctl
.ctl_connect
= utun_ctl_connect
;
123 kern_ctl
.ctl_disconnect
= utun_ctl_disconnect
;
124 kern_ctl
.ctl_send
= utun_ctl_send
;
125 kern_ctl
.ctl_setopt
= utun_ctl_setopt
;
126 kern_ctl
.ctl_getopt
= utun_ctl_getopt
;
127 kern_ctl
.ctl_rcvd
= utun_ctl_rcvd
;
129 result
= ctl_register(&kern_ctl
, &utun_kctlref
);
131 printf("utun_register_control - ctl_register failed: %d\n", result
);
135 /* Register the protocol plumbers */
136 if ((result
= proto_register_plumber(PF_INET
, utun_family
,
137 utun_attach_proto
, NULL
)) != 0) {
138 printf("utun_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n",
139 utun_family
, result
);
140 ctl_deregister(utun_kctlref
);
144 /* Register the protocol plumbers */
145 if ((result
= proto_register_plumber(PF_INET6
, utun_family
,
146 utun_attach_proto
, NULL
)) != 0) {
147 proto_unregister_plumber(PF_INET
, utun_family
);
148 ctl_deregister(utun_kctlref
);
149 printf("utun_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n",
150 utun_family
, result
);
158 /* Kernel control functions */
162 kern_ctl_ref kctlref
,
163 struct sockaddr_ctl
*sac
,
166 struct ifnet_init_eparams utun_init
;
167 struct utun_pcb
*pcb
;
169 struct ifnet_stats_param stats
;
171 /* kernel control allocates, interface frees */
172 MALLOC(pcb
, struct utun_pcb
*, sizeof(*pcb
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
175 pcb
->utun_ctlref
= kctlref
;
176 pcb
->utun_unit
= sac
->sc_unit
;
177 pcb
->utun_max_pending_packets
= 1;
179 printf("utun_ctl_connect: creating interface utun%d\n", pcb
->utun_unit
- 1);
181 /* Create the interface */
182 bzero(&utun_init
, sizeof(utun_init
));
183 utun_init
.ver
= IFNET_INIT_CURRENT_VERSION
;
184 utun_init
.len
= sizeof (utun_init
);
185 utun_init
.name
= "utun";
186 utun_init
.start
= utun_start
;
187 utun_init
.unit
= pcb
->utun_unit
- 1;
188 utun_init
.family
= utun_family
;
189 utun_init
.subfamily
= IFNET_SUBFAMILY_UTUN
;
190 utun_init
.type
= IFT_OTHER
;
191 utun_init
.demux
= utun_demux
;
192 utun_init
.framer_extended
= utun_framer
;
193 utun_init
.add_proto
= utun_add_proto
;
194 utun_init
.del_proto
= utun_del_proto
;
195 utun_init
.softc
= pcb
;
196 utun_init
.ioctl
= utun_ioctl
;
197 utun_init
.detach
= utun_detached
;
200 * Upon success, this holds an ifnet reference which we will
201 * release via ifnet_release() at final detach time.
203 result
= ifnet_allocate_extended(&utun_init
, &pcb
->utun_ifp
);
205 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
211 /* Set flags and additional information. */
212 ifnet_set_mtu(pcb
->utun_ifp
, UTUN_DEFAULT_MTU
);
213 ifnet_set_flags(pcb
->utun_ifp
, IFF_UP
| IFF_MULTICAST
| IFF_POINTOPOINT
, 0xffff);
215 /* The interface must generate its own IPv6 LinkLocal address,
216 * if possible following the recommendation of RFC2472 to the 64bit interface ID
218 ifnet_set_eflags(pcb
->utun_ifp
, IFEF_NOAUTOIPV6LL
, IFEF_NOAUTOIPV6LL
);
220 /* Reset the stats in case as the interface may have been recycled */
221 bzero(&stats
, sizeof(struct ifnet_stats_param
));
222 ifnet_set_stat(pcb
->utun_ifp
, &stats
);
224 /* Attach the interface */
225 result
= ifnet_attach(pcb
->utun_ifp
, NULL
);
227 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
228 /* Release reference now since attach failed */
229 ifnet_release(pcb
->utun_ifp
);
234 bpfattach(pcb
->utun_ifp
, DLT_NULL
, UTUN_HEADER_SIZE(pcb
));
235 /* The interfaces resoures allocated, mark it as running */
236 ifnet_set_flags(pcb
->utun_ifp
, IFF_RUNNING
, IFF_RUNNING
);
244 protocol_family_t protocol
,
247 errno_t result
= EPROTONOSUPPORT
;
249 /* Attempt a detach */
250 if (protocol
== PF_INET
) {
253 bzero(&ifr
, sizeof(ifr
));
254 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
255 ifnet_name(interface
), ifnet_unit(interface
));
257 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH
, &ifr
);
259 else if (protocol
== PF_INET6
) {
260 struct in6_ifreq ifr6
;
262 bzero(&ifr6
, sizeof(ifr6
));
263 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
264 ifnet_name(interface
), ifnet_unit(interface
));
266 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH_IN6
, &ifr6
);
275 protocol_family_t protocol
,
281 /* Attempt a detach */
282 if (protocol
== PF_INET
) {
285 bzero(&ifr
, sizeof(ifr
));
286 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
287 ifnet_name(interface
), ifnet_unit(interface
));
288 result
= ifaddr_address(address
, &ifr
.ifr_addr
, sizeof(ifr
.ifr_addr
));
290 printf("utun_remove_address - ifaddr_address failed: %d", result
);
293 result
= sock_ioctl(pf_socket
, SIOCDIFADDR
, &ifr
);
295 printf("utun_remove_address - SIOCDIFADDR failed: %d", result
);
299 else if (protocol
== PF_INET6
) {
300 struct in6_ifreq ifr6
;
302 bzero(&ifr6
, sizeof(ifr6
));
303 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
304 ifnet_name(interface
), ifnet_unit(interface
));
305 result
= ifaddr_address(address
, (struct sockaddr
*)&ifr6
.ifr_addr
,
306 sizeof(ifr6
.ifr_addr
));
308 printf("utun_remove_address - ifaddr_address failed (v6): %d",
312 result
= sock_ioctl(pf_socket
, SIOCDIFADDR_IN6
, &ifr6
);
314 printf("utun_remove_address - SIOCDIFADDR_IN6 failed: %d",
324 protocol_family_t protocol
)
327 socket_t pf_socket
= NULL
;
328 ifaddr_t
*addresses
= NULL
;
331 if (protocol
!= PF_INET
&& protocol
!= PF_INET6
) {
332 printf("utun_cleanup_family - invalid protocol family %d\n", protocol
);
336 /* Create a socket for removing addresses and detaching the protocol */
337 result
= sock_socket(protocol
, SOCK_DGRAM
, 0, NULL
, NULL
, &pf_socket
);
339 if (result
!= EAFNOSUPPORT
)
340 printf("utun_cleanup_family - failed to create %s socket: %d\n",
341 protocol
== PF_INET
? "IP" : "IPv6", result
);
345 /* always set SS_PRIV, we want to close and detach regardless */
346 sock_setpriv(pf_socket
, 1);
348 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
349 if (result
== 0 || result
== ENXIO
) {
350 /* We are done! We either detached or weren't attached. */
353 else if (result
!= EBUSY
) {
354 /* Uh, not really sure what happened here... */
355 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
360 * At this point, we received an EBUSY error. This means there are
361 * addresses attached. We should detach them and then try again.
363 result
= ifnet_get_address_list_family(interface
, &addresses
, protocol
);
365 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
366 ifnet_name(interface
), ifnet_unit(interface
),
367 protocol
== PF_INET
? "PF_INET" : "PF_INET6", result
);
371 for (i
= 0; addresses
[i
] != 0; i
++) {
372 utun_remove_address(interface
, protocol
, addresses
[i
], pf_socket
);
374 ifnet_free_address_list(addresses
);
378 * The addresses should be gone, we should try the remove again.
380 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
381 if (result
!= 0 && result
!= ENXIO
) {
382 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
386 if (pf_socket
!= NULL
)
387 sock_close(pf_socket
);
389 if (addresses
!= NULL
)
390 ifnet_free_address_list(addresses
);
395 __unused kern_ctl_ref kctlref
,
396 __unused u_int32_t unit
,
399 struct utun_pcb
*pcb
= unitinfo
;
409 pcb
->utun_ctlref
= NULL
;
413 * We want to do everything in our power to ensure that the interface
414 * really goes away when the socket is closed. We must remove IP/IPv6
415 * addresses and detach the protocols. Finally, we can remove and
416 * release the interface.
418 utun_cleanup_family(ifp
, AF_INET
);
419 utun_cleanup_family(ifp
, AF_INET6
);
422 * Detach now; utun_detach() will be called asynchronously once
423 * the I/O reference count drops to 0. There we will invoke
426 if ((result
= ifnet_detach(ifp
)) != 0) {
427 printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result
);
435 __unused kern_ctl_ref kctlref
,
436 __unused u_int32_t unit
,
442 * The userland ABI requires the first four bytes have the protocol family
443 * in network byte order: swap them
445 if (m_pktlen(m
) >= (int32_t)UTUN_HEADER_SIZE((struct utun_pcb
*)unitinfo
)) {
446 *(protocol_family_t
*)mbuf_data(m
) = ntohl(*(protocol_family_t
*)mbuf_data(m
));
448 printf("%s - unexpected short mbuf pkt len %d\n", __func__
, m_pktlen(m
) );
451 return utun_pkt_input((struct utun_pcb
*)unitinfo
, m
);
456 __unused kern_ctl_ref kctlref
,
457 __unused u_int32_t unit
,
463 struct utun_pcb
*pcb
= unitinfo
;
465 /* check for privileges for privileged options */
468 case UTUN_OPT_EXT_IFDATA_STATS
:
469 case UTUN_OPT_SET_DELEGATE_INTERFACE
:
470 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
478 if (len
!= sizeof(u_int32_t
)) {
481 u_int32_t old_flags
= pcb
->utun_flags
;
482 pcb
->utun_flags
= *(u_int32_t
*)data
;
484 if (((old_flags
^ pcb
->utun_flags
) & UTUN_FLAGS_ENABLE_PROC_UUID
)) {
485 // If UTUN_FLAGS_ENABLE_PROC_UUID flag changed, update bpf
486 bpfdetach(pcb
->utun_ifp
);
487 bpfattach(pcb
->utun_ifp
, DLT_NULL
, UTUN_HEADER_SIZE(pcb
));
492 case UTUN_OPT_EXT_IFDATA_STATS
:
493 if (len
!= sizeof(int)) {
497 pcb
->utun_ext_ifdata_stats
= (*(int *)data
) ? 1 : 0;
500 case UTUN_OPT_INC_IFDATA_STATS_IN
:
501 case UTUN_OPT_INC_IFDATA_STATS_OUT
: {
502 struct utun_stats_param
*utsp
= (struct utun_stats_param
*)data
;
504 if (utsp
== NULL
|| len
< sizeof(struct utun_stats_param
)) {
508 if (!pcb
->utun_ext_ifdata_stats
) {
512 if (opt
== UTUN_OPT_INC_IFDATA_STATS_IN
)
513 ifnet_stat_increment_in(pcb
->utun_ifp
, utsp
->utsp_packets
,
514 utsp
->utsp_bytes
, utsp
->utsp_errors
);
516 ifnet_stat_increment_out(pcb
->utun_ifp
, utsp
->utsp_packets
,
517 utsp
->utsp_bytes
, utsp
->utsp_errors
);
520 case UTUN_OPT_SET_DELEGATE_INTERFACE
: {
521 ifnet_t del_ifp
= NULL
;
524 if (len
> IFNAMSIZ
- 1) {
528 if (len
!= 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */
529 bcopy(data
, name
, len
);
531 result
= ifnet_find_by_name(name
, &del_ifp
);
534 result
= ifnet_set_delegate(pcb
->utun_ifp
, del_ifp
);
536 ifnet_release(del_ifp
);
540 case UTUN_OPT_MAX_PENDING_PACKETS
: {
541 u_int32_t max_pending_packets
= 0;
542 if (len
!= sizeof(u_int32_t
)) {
546 max_pending_packets
= *(u_int32_t
*)data
;
547 if (max_pending_packets
== 0) {
551 pcb
->utun_max_pending_packets
= max_pending_packets
;
555 result
= ENOPROTOOPT
;
565 __unused kern_ctl_ref kctlref
,
566 __unused u_int32_t unit
,
572 struct utun_pcb
*pcb
= unitinfo
;
577 if (*len
!= sizeof(u_int32_t
))
580 *(u_int32_t
*)data
= pcb
->utun_flags
;
583 case UTUN_OPT_EXT_IFDATA_STATS
:
584 if (*len
!= sizeof(int))
587 *(int *)data
= (pcb
->utun_ext_ifdata_stats
) ? 1 : 0;
590 case UTUN_OPT_IFNAME
:
591 *len
= snprintf(data
, *len
, "%s%d", ifnet_name(pcb
->utun_ifp
), ifnet_unit(pcb
->utun_ifp
)) + 1;
594 case UTUN_OPT_MAX_PENDING_PACKETS
: {
595 *len
= sizeof(u_int32_t
);
596 *((u_int32_t
*)data
) = pcb
->utun_max_pending_packets
;
602 result
= ENOPROTOOPT
;
610 utun_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int flags
)
612 #pragma unused(flags)
613 bool reenable_output
= false;
614 struct utun_pcb
*pcb
= unitinfo
;
618 ifnet_lock_exclusive(pcb
->utun_ifp
);
620 u_int32_t utun_packet_cnt
;
621 errno_t error_pc
= ctl_getenqueuepacketcount(kctlref
, unit
, &utun_packet_cnt
);
623 printf("utun_ctl_rcvd: ctl_getenqueuepacketcount returned error %d\n", error_pc
);
627 if (utun_packet_cnt
< pcb
->utun_max_pending_packets
) {
628 reenable_output
= true;
631 if (reenable_output
) {
632 errno_t error
= ifnet_enable_output(pcb
->utun_ifp
);
634 printf("utun_ctl_rcvd: ifnet_enable_output returned error %d\n", error
);
637 ifnet_lock_done(pcb
->utun_ifp
);
640 /* Network Interface functions */
642 utun_start(ifnet_t interface
)
645 struct utun_pcb
*pcb
= ifnet_softc(interface
);
651 bool can_accept_packets
= true;
652 ifnet_lock_shared(pcb
->utun_ifp
);
654 u_int32_t utun_packet_cnt
;
655 errno_t error_pc
= ctl_getenqueuepacketcount(pcb
->utun_ctlref
, pcb
->utun_unit
, &utun_packet_cnt
);
657 printf("utun_start: ctl_getenqueuepacketcount returned error %d\n", error_pc
);
661 can_accept_packets
= (utun_packet_cnt
< pcb
->utun_max_pending_packets
);
662 if (!can_accept_packets
&& pcb
->utun_ctlref
) {
663 u_int32_t difference
= 0;
664 if (ctl_getenqueuereadable(pcb
->utun_ctlref
, pcb
->utun_unit
, &difference
) == 0) {
665 if (difference
> 0) {
666 // If the low-water mark has not yet been reached, we still need to enqueue data
668 can_accept_packets
= true;
672 if (!can_accept_packets
) {
673 errno_t error
= ifnet_disable_output(interface
);
675 printf("utun_start: ifnet_disable_output returned error %d\n", error
);
677 ifnet_lock_done(pcb
->utun_ifp
);
680 ifnet_lock_done(pcb
->utun_ifp
);
681 if (ifnet_dequeue(interface
, &data
) != 0)
683 if (utun_output(interface
, data
) != 0)
689 utun_output(ifnet_t interface
,
692 struct utun_pcb
*pcb
= ifnet_softc(interface
);
695 VERIFY(interface
== pcb
->utun_ifp
);
697 if (m_pktlen(data
) >= (int32_t)UTUN_HEADER_SIZE(pcb
)) {
698 bpf_tap_out(pcb
->utun_ifp
, DLT_NULL
, data
, 0, 0);
701 if (pcb
->utun_flags
& UTUN_FLAGS_NO_OUTPUT
) {
707 // otherwise, fall thru to ctl_enqueumbuf
708 if (pcb
->utun_ctlref
) {
712 * The ABI requires the protocol in network byte order
714 if (m_pktlen(data
) >= (int32_t)UTUN_HEADER_SIZE(pcb
)) {
715 *(u_int32_t
*)mbuf_data(data
) = htonl(*(u_int32_t
*)mbuf_data(data
));
718 length
= mbuf_pkthdr_len(data
);
719 result
= ctl_enqueuembuf(pcb
->utun_ctlref
, pcb
->utun_unit
, data
, CTL_DATA_EOR
);
722 printf("utun_output - ctl_enqueuembuf failed: %d\n", result
);
724 ifnet_stat_increment_out(interface
, 0, 0, 1);
727 if (!pcb
->utun_ext_ifdata_stats
)
728 ifnet_stat_increment_out(interface
, 1, length
, 0);
739 __unused ifnet_t interface
,
741 __unused
char *frame_header
,
742 protocol_family_t
*protocol
)
745 while (data
!= NULL
&& mbuf_len(data
) < 1) {
746 data
= mbuf_next(data
);
752 *protocol
= *(u_int32_t
*)mbuf_data(data
);
758 __unused ifnet_t interface
,
760 __unused
const struct sockaddr
*dest
,
761 __unused
const char *desk_linkaddr
,
762 const char *frame_type
,
763 u_int32_t
*prepend_len
,
764 u_int32_t
*postpend_len
)
766 struct utun_pcb
*pcb
= ifnet_softc(interface
);
767 VERIFY(interface
== pcb
->utun_ifp
);
769 u_int32_t header_length
= UTUN_HEADER_SIZE(pcb
);
770 if (mbuf_prepend(packet
, header_length
, MBUF_DONTWAIT
) != 0) {
771 printf("utun_framer - ifnet_output prepend failed\n");
773 ifnet_stat_increment_out(interface
, 0, 0, 1);
775 // just return, because the buffer was freed in mbuf_prepend
778 if (prepend_len
!= NULL
)
779 *prepend_len
= header_length
;
780 if (postpend_len
!= NULL
)
783 // place protocol number at the beginning of the mbuf
784 *(protocol_family_t
*)mbuf_data(*packet
) = *(protocol_family_t
*)(uintptr_t)(size_t)frame_type
;
792 __unused ifnet_t interface
,
793 protocol_family_t protocol
,
794 __unused
const struct ifnet_demux_desc
*demux_array
,
795 __unused u_int32_t demux_count
)
811 __unused ifnet_t interface
,
812 __unused protocol_family_t protocol
)
827 ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
);
831 /* ifioctl() takes care of it */
845 struct utun_pcb
*pcb
= ifnet_softc(interface
);
848 /* Release reference acquired via ifnet_allocate_extended() */
849 (void) ifnet_release(interface
);
852 /* Protocol Handlers */
857 protocol_family_t protocol
,
859 __unused
char *frame_header
)
862 // remove protocol family first
863 struct utun_pcb
*pcb
= ifnet_softc(interface
);
864 mbuf_adj(m
, UTUN_HEADER_SIZE(pcb
));
866 if (proto_input(protocol
, m
) != 0) {
874 utun_proto_pre_output(
875 __unused ifnet_t interface
,
876 protocol_family_t protocol
,
877 __unused mbuf_t
*packet
,
878 __unused
const struct sockaddr
*dest
,
879 __unused
void *route
,
881 __unused
char *link_layer_dest
)
883 *(protocol_family_t
*)(void *)frame_type
= protocol
;
890 protocol_family_t protocol
)
892 struct ifnet_attach_proto_param proto
;
895 bzero(&proto
, sizeof(proto
));
896 proto
.input
= utun_proto_input
;
897 proto
.pre_output
= utun_proto_pre_output
;
899 result
= ifnet_attach_protocol(interface
, protocol
, &proto
);
900 if (result
!= 0 && result
!= EEXIST
) {
901 printf("utun_attach_inet - ifnet_attach_protocol %d failed: %d\n",
909 utun_pkt_input (struct utun_pcb
*pcb
, mbuf_t m
)
912 protocol_family_t protocol
= 0;
914 mbuf_pkthdr_setrcvif(m
, pcb
->utun_ifp
);
916 if (m_pktlen(m
) >= (int32_t)UTUN_HEADER_SIZE(pcb
)) {
917 protocol
= *(u_int32_t
*)mbuf_data(m
);
919 bpf_tap_in(pcb
->utun_ifp
, DLT_NULL
, m
, 0, 0);
921 if (pcb
->utun_flags
& UTUN_FLAGS_NO_INPUT
) {
927 if (!pcb
->utun_ext_ifdata_stats
) {
928 struct ifnet_stat_increment_param incs
;
930 bzero(&incs
, sizeof(incs
));
932 incs
.bytes_in
= mbuf_pkthdr_len(m
);
933 result
= ifnet_input(pcb
->utun_ifp
, m
, &incs
);
935 result
= ifnet_input(pcb
->utun_ifp
, m
, NULL
);
938 ifnet_stat_increment_in(pcb
->utun_ifp
, 0, 0, 1);
940 printf("%s - ifnet_input failed: %d\n", __FUNCTION__
, result
);
950 * These are place holders until coreTLS kext stops caling them
952 errno_t
utun_ctl_register_dtls (void *reg
);
953 int utun_pkt_dtls_input(struct utun_pcb
*pcb
, mbuf_t
*pkt
, protocol_family_t family
);
954 void utun_ctl_disable_crypto_dtls(struct utun_pcb
*pcb
);
957 utun_ctl_register_dtls (void *reg
)
964 utun_pkt_dtls_input(struct utun_pcb
*pcb
, mbuf_t
*pkt
, protocol_family_t family
)
968 #pragma unused(family)
973 utun_ctl_disable_crypto_dtls(struct utun_pcb
*pcb
)