2 * Copyright (c) 2008-2013 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
, u_int32_t
*prepend_len
, u_int32_t
*postpend_len
);
77 static errno_t
utun_add_proto(ifnet_t interface
, protocol_family_t protocol
,
78 const struct ifnet_demux_desc
*demux_array
,
79 u_int32_t demux_count
);
80 static errno_t
utun_del_proto(ifnet_t interface
, protocol_family_t protocol
);
81 static errno_t
utun_ioctl(ifnet_t interface
, u_long cmd
, void *data
);
82 static void utun_detached(ifnet_t interface
);
84 /* Protocol handlers */
85 static errno_t
utun_attach_proto(ifnet_t interface
, protocol_family_t proto
);
86 static errno_t
utun_proto_input(ifnet_t interface
, protocol_family_t protocol
,
87 mbuf_t m
, char *frame_header
);
88 static errno_t
utun_proto_pre_output(ifnet_t interface
, protocol_family_t protocol
,
89 mbuf_t
*packet
, const struct sockaddr
*dest
, void *route
,
90 char *frame_type
, char *link_layer_dest
);
91 __private_extern__ errno_t
utun_pkt_input (struct utun_pcb
*pcb
, mbuf_t m
);
93 static kern_ctl_ref utun_kctlref
;
94 static u_int32_t utun_family
;
95 static OSMallocTag utun_malloc_tag
;
96 static SInt32 utun_ifcount
= 0;
100 utun_alloc(size_t size
)
102 size_t *mem
= OSMalloc(size
+ sizeof(size_t), utun_malloc_tag
);
105 *mem
= size
+ sizeof(size_t);
117 OSFree(size
, *size
, utun_malloc_tag
);
121 utun_register_control(void)
123 struct kern_ctl_reg kern_ctl
;
126 /* Create a tag to allocate memory */
127 utun_malloc_tag
= OSMalloc_Tagalloc(UTUN_CONTROL_NAME
, OSMT_DEFAULT
);
129 /* Find a unique value for our interface family */
130 result
= mbuf_tag_id_find(UTUN_CONTROL_NAME
, &utun_family
);
132 printf("utun_register_control - mbuf_tag_id_find_internal failed: %d\n", result
);
136 bzero(&kern_ctl
, sizeof(kern_ctl
));
137 strncpy(kern_ctl
.ctl_name
, UTUN_CONTROL_NAME
, sizeof(kern_ctl
.ctl_name
));
138 kern_ctl
.ctl_name
[sizeof(kern_ctl
.ctl_name
) - 1] = 0;
139 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
; /* Require root */
140 kern_ctl
.ctl_sendsize
= 512 * 1024;
141 kern_ctl
.ctl_recvsize
= 512 * 1024;
142 kern_ctl
.ctl_connect
= utun_ctl_connect
;
143 kern_ctl
.ctl_disconnect
= utun_ctl_disconnect
;
144 kern_ctl
.ctl_send
= utun_ctl_send
;
145 kern_ctl
.ctl_setopt
= utun_ctl_setopt
;
146 kern_ctl
.ctl_getopt
= utun_ctl_getopt
;
148 utun_ctl_init_crypto();
150 result
= ctl_register(&kern_ctl
, &utun_kctlref
);
152 printf("utun_register_control - ctl_register failed: %d\n", result
);
156 /* Register the protocol plumbers */
157 if ((result
= proto_register_plumber(PF_INET
, utun_family
,
158 utun_attach_proto
, NULL
)) != 0) {
159 printf("utun_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n",
160 utun_family
, result
);
161 ctl_deregister(utun_kctlref
);
165 /* Register the protocol plumbers */
166 if ((result
= proto_register_plumber(PF_INET6
, utun_family
,
167 utun_attach_proto
, NULL
)) != 0) {
168 proto_unregister_plumber(PF_INET
, utun_family
);
169 ctl_deregister(utun_kctlref
);
170 printf("utun_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n",
171 utun_family
, result
);
178 /* Kernel control functions */
182 kern_ctl_ref kctlref
,
183 struct sockaddr_ctl
*sac
,
186 struct ifnet_init_eparams utun_init
;
187 struct utun_pcb
*pcb
;
189 struct ifnet_stats_param stats
;
191 /* kernel control allocates, interface frees */
192 pcb
= utun_alloc(sizeof(*pcb
));
196 /* Setup the protocol control block */
197 bzero(pcb
, sizeof(*pcb
));
199 pcb
->utun_ctlref
= kctlref
;
200 pcb
->utun_unit
= sac
->sc_unit
;
202 printf("utun_ctl_connect: creating interface utun%d\n", pcb
->utun_unit
- 1);
204 /* Create the interface */
205 bzero(&utun_init
, sizeof(utun_init
));
206 utun_init
.ver
= IFNET_INIT_CURRENT_VERSION
;
207 utun_init
.len
= sizeof (utun_init
);
208 utun_init
.flags
= IFNET_INIT_LEGACY
;
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_extended
= 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_extended(&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
,
458 * The userland ABI requires the first four bytes have the protocol family
459 * in network byte order: swap them
461 if (m_pktlen(m
) >= 4)
462 *(protocol_family_t
*)mbuf_data(m
) = ntohl(*(protocol_family_t
*)mbuf_data(m
));
464 printf("%s - unexpected short mbuf pkt len %d\n", __func__
, m_pktlen(m
) );
466 return utun_pkt_input((struct utun_pcb
*)unitinfo
, m
);
471 __unused kern_ctl_ref kctlref
,
472 __unused u_int32_t unit
,
478 struct utun_pcb
*pcb
= unitinfo
;
481 /* check for privileges for privileged options */
484 case UTUN_OPT_EXT_IFDATA_STATS
:
485 case UTUN_OPT_SET_DELEGATE_INTERFACE
:
486 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
494 if (len
!= sizeof(u_int32_t
))
497 pcb
->utun_flags
= *(u_int32_t
*)data
;
500 case UTUN_OPT_ENABLE_CRYPTO
:
501 result
= utun_ctl_enable_crypto(kctlref
, unit
, unitinfo
, opt
, data
, len
);
504 case UTUN_OPT_CONFIG_CRYPTO_KEYS
:
505 result
= utun_ctl_config_crypto_keys(kctlref
, unit
, unitinfo
, opt
, data
, len
);
508 case UTUN_OPT_UNCONFIG_CRYPTO_KEYS
:
509 result
= utun_ctl_unconfig_crypto_keys(kctlref
, unit
, unitinfo
, opt
, data
, len
);
512 case UTUN_OPT_DISABLE_CRYPTO
:
513 result
= utun_ctl_disable_crypto(kctlref
, unit
, unitinfo
, opt
, data
, len
);
516 case UTUN_OPT_STOP_CRYPTO_DATA_TRAFFIC
:
517 result
= utun_ctl_stop_crypto_data_traffic(kctlref
, unit
, unitinfo
, opt
, data
, len
);
520 case UTUN_OPT_START_CRYPTO_DATA_TRAFFIC
:
521 result
= utun_ctl_start_crypto_data_traffic(kctlref
, unit
, unitinfo
, opt
, data
, len
);
524 case UTUN_OPT_CONFIG_CRYPTO_FRAMER
:
525 result
= utun_ctl_config_crypto_framer(kctlref
, unit
, unitinfo
, opt
, data
, len
);
528 case UTUN_OPT_UNCONFIG_CRYPTO_FRAMER
:
529 result
= utun_ctl_unconfig_crypto_framer(kctlref
, unit
, unitinfo
, opt
, data
, len
);
532 case UTUN_OPT_EXT_IFDATA_STATS
:
533 if (len
!= sizeof(int)) {
537 pcb
->utun_ext_ifdata_stats
= (*(int *)data
) ? 1 : 0;
540 case UTUN_OPT_INC_IFDATA_STATS_IN
:
541 case UTUN_OPT_INC_IFDATA_STATS_OUT
: {
542 struct utun_stats_param
*utsp
= (struct utun_stats_param
*)data
;
544 if (utsp
== NULL
|| len
< sizeof(struct utun_stats_param
)) {
548 if (!pcb
->utun_ext_ifdata_stats
) {
552 if (opt
== UTUN_OPT_INC_IFDATA_STATS_IN
)
553 ifnet_stat_increment_in(pcb
->utun_ifp
, utsp
->utsp_packets
,
554 utsp
->utsp_bytes
, utsp
->utsp_errors
);
556 ifnet_stat_increment_out(pcb
->utun_ifp
, utsp
->utsp_packets
,
557 utsp
->utsp_bytes
, utsp
->utsp_errors
);
561 case UTUN_OPT_SET_DELEGATE_INTERFACE
: {
562 ifnet_t del_ifp
= NULL
;
565 if (len
> IFNAMSIZ
- 1) {
569 if (len
!= 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */
570 bcopy(data
, name
, len
);
572 result
= ifnet_find_by_name(name
, &del_ifp
);
575 result
= ifnet_set_delegate(pcb
->utun_ifp
, del_ifp
);
577 ifnet_release(del_ifp
);
583 result
= ENOPROTOOPT
;
592 __unused kern_ctl_ref kctlref
,
593 __unused u_int32_t unit
,
599 struct utun_pcb
*pcb
= unitinfo
;
604 if (*len
!= sizeof(u_int32_t
))
607 *(u_int32_t
*)data
= pcb
->utun_flags
;
610 case UTUN_OPT_EXT_IFDATA_STATS
:
611 if (*len
!= sizeof(int))
614 *(int *)data
= (pcb
->utun_ext_ifdata_stats
) ? 1 : 0;
617 case UTUN_OPT_IFNAME
:
618 *len
= snprintf(data
, *len
, "%s%d", ifnet_name(pcb
->utun_ifp
), ifnet_unit(pcb
->utun_ifp
)) + 1;
621 case UTUN_OPT_GENERATE_CRYPTO_KEYS_IDX
:
622 result
= utun_ctl_generate_crypto_keys_idx(kctlref
, unit
, unitinfo
, opt
, data
, len
);
626 result
= ENOPROTOOPT
;
633 /* Network Interface functions */
639 struct utun_pcb
*pcb
= ifnet_softc(interface
);
642 if (m_pktlen(data
) >= 4) {
643 bpf_tap_out(pcb
->utun_ifp
, DLT_NULL
, data
, 0, 0);
646 if (pcb
->utun_flags
& UTUN_FLAGS_NO_OUTPUT
) {
652 // otherwise, fall thru to ctl_enqueumbuf
653 if (pcb
->utun_ctlref
) {
656 // only pass packets to utun-crypto if crypto is enabled and 'suspend data traffic' is not.
657 if ((pcb
->utun_flags
& (UTUN_FLAGS_CRYPTO
| UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC
)) == UTUN_FLAGS_CRYPTO
) {
658 if (utun_pkt_crypto_output(pcb
, &data
) == 0) {
664 * The ABI requires the protocol in network byte order
666 if (m_pktlen(data
) >= 4)
667 *(u_int32_t
*)mbuf_data(data
) = htonl(*(u_int32_t
*)mbuf_data(data
));
669 length
= mbuf_pkthdr_len(data
);
670 result
= ctl_enqueuembuf(pcb
->utun_ctlref
, pcb
->utun_unit
, data
, CTL_DATA_EOR
);
673 printf("utun_output - ctl_enqueuembuf failed: %d\n", result
);
675 ifnet_stat_increment_out(interface
, 0, 0, 1);
678 if (!pcb
->utun_ext_ifdata_stats
)
679 ifnet_stat_increment_out(interface
, 1, length
, 0);
688 /* Network Interface functions */
691 __unused ifnet_t interface
,
693 __unused
char *frame_header
,
694 protocol_family_t
*protocol
)
697 while (data
!= NULL
&& mbuf_len(data
) < 1) {
698 data
= mbuf_next(data
);
704 *protocol
= *(u_int32_t
*)mbuf_data(data
);
710 __unused ifnet_t interface
,
712 __unused
const struct sockaddr
*dest
,
713 __unused
const char *desk_linkaddr
,
714 const char *frame_type
,
715 u_int32_t
*prepend_len
,
716 u_int32_t
*postpend_len
)
718 if (mbuf_prepend(packet
, sizeof(protocol_family_t
), MBUF_DONTWAIT
) != 0) {
719 printf("utun_framer - ifnet_output prepend failed\n");
721 ifnet_stat_increment_out(interface
, 0, 0, 1);
723 // just return, because the buffer was freed in mbuf_prepend
726 if (prepend_len
!= NULL
)
727 *prepend_len
= sizeof(protocol_family_t
);
728 if (postpend_len
!= NULL
)
731 // place protocol number at the beginning of the mbuf
732 *(protocol_family_t
*)mbuf_data(*packet
) = *(protocol_family_t
*)(uintptr_t)(size_t)frame_type
;
739 __unused ifnet_t interface
,
740 protocol_family_t protocol
,
741 __unused
const struct ifnet_demux_desc
*demux_array
,
742 __unused u_int32_t demux_count
)
758 __unused ifnet_t interface
,
759 __unused protocol_family_t protocol
)
774 ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
);
778 /* ifioctl() takes care of it */
792 struct utun_pcb
*pcb
= ifnet_softc(interface
);
796 OSDecrementAtomic(&utun_ifcount
);
799 /* Protocol Handlers */
803 __unused ifnet_t interface
,
804 protocol_family_t protocol
,
806 __unused
char *frame_header
)
809 // remove protocol family first
810 mbuf_adj(m
, sizeof(u_int32_t
));
812 if (proto_input(protocol
, m
) != 0)
819 utun_proto_pre_output(
820 __unused ifnet_t interface
,
821 protocol_family_t protocol
,
822 __unused mbuf_t
*packet
,
823 __unused
const struct sockaddr
*dest
,
824 __unused
void *route
,
825 __unused
char *frame_type
,
826 __unused
char *link_layer_dest
)
829 *(protocol_family_t
*)(void *)frame_type
= protocol
;
836 protocol_family_t protocol
)
838 struct ifnet_attach_proto_param proto
;
841 bzero(&proto
, sizeof(proto
));
842 proto
.input
= utun_proto_input
;
843 proto
.pre_output
= utun_proto_pre_output
;
845 result
= ifnet_attach_protocol(interface
, protocol
, &proto
);
846 if (result
!= 0 && result
!= EEXIST
) {
847 printf("utun_attach_inet - ifnet_attach_protocol %d failed: %d\n",
855 utun_pkt_input (struct utun_pcb
*pcb
, mbuf_t m
)
858 protocol_family_t protocol
= 0;
860 mbuf_pkthdr_setrcvif(m
, pcb
->utun_ifp
);
862 if (m_pktlen(m
) >= 4) {
863 protocol
= *(u_int32_t
*)mbuf_data(m
);
865 bpf_tap_in(pcb
->utun_ifp
, DLT_NULL
, m
, 0, 0);
867 if (pcb
->utun_flags
& UTUN_FLAGS_NO_INPUT
) {
873 // quick exit for keepalive packets
874 if (protocol
== AF_UTUN
&& pcb
->utun_flags
& UTUN_FLAGS_CRYPTO
) {
875 if (utun_pkt_crypto_output(pcb
, &m
) == 0) {
878 printf("%s: utun_pkt_crypto_output failed, flags %x\n", __FUNCTION__
, pcb
->utun_flags
);
882 if (!pcb
->utun_ext_ifdata_stats
) {
883 struct ifnet_stat_increment_param incs
;
885 bzero(&incs
, sizeof(incs
));
887 incs
.bytes_in
= mbuf_pkthdr_len(m
);
888 result
= ifnet_input(pcb
->utun_ifp
, m
, &incs
);
890 result
= ifnet_input(pcb
->utun_ifp
, m
, NULL
);
893 ifnet_stat_increment_in(pcb
->utun_ifp
, 0, 0, 1);
895 printf("%s - ifnet_input failed: %d\n", __FUNCTION__
, result
);