2 * Copyright (c) 2008-2009 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 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
);
92 /* Control block allocated for each kernel control connection */
94 kern_ctl_ref utun_ctlref
;
98 int utun_ext_ifdata_stats
;
101 static kern_ctl_ref utun_kctlref
;
102 static u_int32_t utun_family
;
103 static OSMallocTag utun_malloc_tag
;
104 static SInt32 utun_ifcount
= 0;
108 utun_alloc(size_t size
)
110 size_t *mem
= OSMalloc(size
+ sizeof(size_t), utun_malloc_tag
);
113 *mem
= size
+ sizeof(size_t);
125 OSFree(size
, *size
, utun_malloc_tag
);
129 utun_register_control(void)
131 struct kern_ctl_reg kern_ctl
;
134 /* Create a tag to allocate memory */
135 utun_malloc_tag
= OSMalloc_Tagalloc(UTUN_CONTROL_NAME
, OSMT_DEFAULT
);
137 /* Find a unique value for our interface family */
138 result
= mbuf_tag_id_find(UTUN_CONTROL_NAME
, &utun_family
);
140 printf("utun_register_control - mbuf_tag_id_find_internal failed: %d\n", result
);
144 bzero(&kern_ctl
, sizeof(kern_ctl
));
145 strncpy(kern_ctl
.ctl_name
, UTUN_CONTROL_NAME
, sizeof(kern_ctl
.ctl_name
));
146 kern_ctl
.ctl_name
[sizeof(kern_ctl
.ctl_name
) - 1] = 0;
147 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
; /* Require root */
148 kern_ctl
.ctl_sendsize
= 64 * 1024;
149 kern_ctl
.ctl_recvsize
= 64 * 1024;
150 kern_ctl
.ctl_connect
= utun_ctl_connect
;
151 kern_ctl
.ctl_disconnect
= utun_ctl_disconnect
;
152 kern_ctl
.ctl_send
= utun_ctl_send
;
153 kern_ctl
.ctl_setopt
= utun_ctl_setopt
;
154 kern_ctl
.ctl_getopt
= utun_ctl_getopt
;
156 result
= ctl_register(&kern_ctl
, &utun_kctlref
);
158 printf("utun_register_control - ctl_register failed: %d\n", result
);
162 /* Register the protocol plumbers */
163 if ((result
= proto_register_plumber(PF_INET
, utun_family
,
164 utun_attach_proto
, NULL
)) != 0) {
165 printf("utun_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n",
166 utun_family
, result
);
167 ctl_deregister(utun_kctlref
);
171 /* Register the protocol plumbers */
172 if ((result
= proto_register_plumber(PF_INET6
, utun_family
,
173 utun_attach_proto
, NULL
)) != 0) {
174 proto_unregister_plumber(PF_INET
, utun_family
);
175 ctl_deregister(utun_kctlref
);
176 printf("utun_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n",
177 utun_family
, result
);
184 /* Kernel control functions */
188 kern_ctl_ref kctlref
,
189 struct sockaddr_ctl
*sac
,
192 struct ifnet_init_params utun_init
;
193 struct utun_pcb
*pcb
;
195 struct ifnet_stats_param stats
;
197 /* kernel control allocates, interface frees */
198 pcb
= utun_alloc(sizeof(*pcb
));
202 /* Setup the protocol control block */
203 bzero(pcb
, sizeof(*pcb
));
205 pcb
->utun_ctlref
= kctlref
;
206 pcb
->utun_unit
= sac
->sc_unit
;
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
.name
= "utun";
213 utun_init
.unit
= pcb
->utun_unit
- 1;
214 utun_init
.family
= utun_family
;
215 utun_init
.type
= IFT_OTHER
;
216 utun_init
.output
= utun_output
;
217 utun_init
.demux
= utun_demux
;
218 utun_init
.framer
= utun_framer
;
219 utun_init
.add_proto
= utun_add_proto
;
220 utun_init
.del_proto
= utun_del_proto
;
221 utun_init
.softc
= pcb
;
222 utun_init
.ioctl
= utun_ioctl
;
223 utun_init
.detach
= utun_detached
;
225 result
= ifnet_allocate(&utun_init
, &pcb
->utun_ifp
);
227 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
231 OSIncrementAtomic(&utun_ifcount
);
233 /* Set flags and additional information. */
234 ifnet_set_mtu(pcb
->utun_ifp
, 1500);
235 ifnet_set_flags(pcb
->utun_ifp
, IFF_UP
| IFF_MULTICAST
| IFF_POINTOPOINT
, 0xffff);
237 /* The interface must generate its own IPv6 LinkLocal address,
238 * if possible following the recommendation of RFC2472 to the 64bit interface ID
240 ifnet_set_eflags(pcb
->utun_ifp
, IFEF_NOAUTOIPV6LL
, IFEF_NOAUTOIPV6LL
);
242 /* Reset the stats in case as the interface may have been recycled */
243 bzero(&stats
, sizeof(struct ifnet_stats_param
));
244 ifnet_set_stat(pcb
->utun_ifp
, &stats
);
246 /* Attach the interface */
247 result
= ifnet_attach(pcb
->utun_ifp
, NULL
);
249 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
250 ifnet_release(pcb
->utun_ifp
);
256 bpfattach(pcb
->utun_ifp
, DLT_NULL
, 4);
258 /* The interfaces resoures allocated, mark it as running */
260 ifnet_set_flags(pcb
->utun_ifp
, IFF_RUNNING
, IFF_RUNNING
);
268 protocol_family_t protocol
,
271 errno_t result
= EPROTONOSUPPORT
;
273 /* Attempt a detach */
274 if (protocol
== PF_INET
) {
277 bzero(&ifr
, sizeof(ifr
));
278 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
279 ifnet_name(interface
), ifnet_unit(interface
));
281 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH
, &ifr
);
283 else if (protocol
== PF_INET6
) {
284 struct in6_ifreq ifr6
;
286 bzero(&ifr6
, sizeof(ifr6
));
287 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
288 ifnet_name(interface
), ifnet_unit(interface
));
290 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH_IN6
, &ifr6
);
299 protocol_family_t protocol
,
305 /* Attempt a detach */
306 if (protocol
== PF_INET
) {
309 bzero(&ifr
, sizeof(ifr
));
310 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
311 ifnet_name(interface
), ifnet_unit(interface
));
312 result
= ifaddr_address(address
, &ifr
.ifr_addr
, sizeof(ifr
.ifr_addr
));
314 printf("utun_remove_address - ifaddr_address failed: %d", result
);
317 result
= sock_ioctl(pf_socket
, SIOCDIFADDR
, &ifr
);
319 printf("utun_remove_address - SIOCDIFADDR failed: %d", result
);
323 else if (protocol
== PF_INET6
) {
324 struct in6_ifreq ifr6
;
326 bzero(&ifr6
, sizeof(ifr6
));
327 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
328 ifnet_name(interface
), ifnet_unit(interface
));
329 result
= ifaddr_address(address
, (struct sockaddr
*)&ifr6
.ifr_addr
,
330 sizeof(ifr6
.ifr_addr
));
332 printf("utun_remove_address - ifaddr_address failed (v6): %d",
336 result
= sock_ioctl(pf_socket
, SIOCDIFADDR_IN6
, &ifr6
);
338 printf("utun_remove_address - SIOCDIFADDR_IN6 failed: %d",
348 protocol_family_t protocol
)
351 socket_t pf_socket
= NULL
;
352 ifaddr_t
*addresses
= NULL
;
355 if (protocol
!= PF_INET
&& protocol
!= PF_INET6
) {
356 printf("utun_cleanup_family - invalid protocol family %d\n", protocol
);
360 /* Create a socket for removing addresses and detaching the protocol */
361 result
= sock_socket(protocol
, SOCK_DGRAM
, 0, NULL
, NULL
, &pf_socket
);
363 if (result
!= EAFNOSUPPORT
)
364 printf("utun_cleanup_family - failed to create %s socket: %d\n",
365 protocol
== PF_INET
? "IP" : "IPv6", result
);
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 pcb
->utun_ctlref
= NULL
;
428 * We want to do everything in our power to ensure that the interface
429 * really goes away when the socket is closed. We must remove IP/IPv6
430 * addresses and detach the protocols. Finally, we can remove and
431 * release the interface.
433 utun_cleanup_family(ifp
, AF_INET
);
434 utun_cleanup_family(ifp
, AF_INET6
);
436 if ((result
= ifnet_detach(ifp
)) != 0) {
437 printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result
);
440 if ((result
= ifnet_release(ifp
)) != 0) {
441 printf("utun_ctl_disconnect - ifnet_release failed: %d\n", result
);
449 __unused kern_ctl_ref kctlref
,
450 __unused u_int32_t unit
,
455 struct utun_pcb
*pcb
= unitinfo
;
458 mbuf_pkthdr_setrcvif(m
, pcb
->utun_ifp
);
460 bpf_tap_in(pcb
->utun_ifp
, DLT_NULL
, m
, 0, 0);
462 if (pcb
->utun_flags
& UTUN_FLAGS_NO_INPUT
) {
468 if (!pcb
->utun_ext_ifdata_stats
) {
469 struct ifnet_stat_increment_param incs
;
471 bzero(&incs
, sizeof(incs
));
473 incs
.bytes_in
= mbuf_pkthdr_len(m
);
474 result
= ifnet_input(pcb
->utun_ifp
, m
, &incs
);
476 result
= ifnet_input(pcb
->utun_ifp
, m
, NULL
);
479 ifnet_stat_increment_in(pcb
->utun_ifp
, 0, 0, 1);
481 printf("utun_ctl_send - ifnet_input failed: %d\n", result
);
490 __unused kern_ctl_ref kctlref
,
491 __unused u_int32_t unit
,
497 struct utun_pcb
*pcb
= unitinfo
;
500 /* check for privileges for privileged options */
503 case UTUN_OPT_EXT_IFDATA_STATS
:
504 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
512 if (len
!= sizeof(u_int32_t
))
515 pcb
->utun_flags
= *(u_int32_t
*)data
;
518 case UTUN_OPT_EXT_IFDATA_STATS
:
519 if (len
!= sizeof(int)) {
523 pcb
->utun_ext_ifdata_stats
= (*(int *)data
) ? 1 : 0;
526 case UTUN_OPT_INC_IFDATA_STATS_IN
:
527 case UTUN_OPT_INC_IFDATA_STATS_OUT
: {
528 struct utun_stats_param
*utsp
= (struct utun_stats_param
*)data
;
530 if (utsp
== NULL
|| len
< sizeof(struct utun_stats_param
)) {
534 if (!pcb
->utun_ext_ifdata_stats
) {
538 if (opt
== UTUN_OPT_INC_IFDATA_STATS_IN
)
539 ifnet_stat_increment_in(pcb
->utun_ifp
, utsp
->utsp_packets
,
540 utsp
->utsp_bytes
, utsp
->utsp_errors
);
542 ifnet_stat_increment_out(pcb
->utun_ifp
, utsp
->utsp_packets
,
543 utsp
->utsp_bytes
, utsp
->utsp_errors
);
548 result
= ENOPROTOOPT
;
557 __unused kern_ctl_ref kctlref
,
558 __unused u_int32_t unit
,
564 struct utun_pcb
*pcb
= unitinfo
;
569 if (*len
!= sizeof(u_int32_t
))
572 *(u_int32_t
*)data
= pcb
->utun_flags
;
575 case UTUN_OPT_EXT_IFDATA_STATS
:
576 if (*len
!= sizeof(int))
579 *(int *)data
= (pcb
->utun_ext_ifdata_stats
) ? 1 : 0;
582 case UTUN_OPT_IFNAME
:
583 *len
= snprintf(data
, *len
, "%s%d", ifnet_name(pcb
->utun_ifp
), ifnet_unit(pcb
->utun_ifp
)) + 1;
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 if (pcb
->utun_ctlref
) {
612 int length
= mbuf_pkthdr_len(data
);
613 result
= ctl_enqueuembuf(pcb
->utun_ctlref
, pcb
->utun_unit
, data
, CTL_DATA_EOR
);
616 printf("utun_output - ctl_enqueuembuf failed: %d\n", result
);
618 ifnet_stat_increment_out(interface
, 0, 0, 1);
621 if (!pcb
->utun_ext_ifdata_stats
)
622 ifnet_stat_increment_out(interface
, 1, length
, 0);
631 /* Network Interface functions */
634 __unused ifnet_t interface
,
636 __unused
char *frame_header
,
637 protocol_family_t
*protocol
)
640 while (data
!= NULL
&& mbuf_len(data
) < 1) {
641 data
= mbuf_next(data
);
647 *protocol
= ntohl(*(u_int32_t
*)mbuf_data(data
));
653 __unused ifnet_t interface
,
655 __unused
const struct sockaddr
*dest
,
656 __unused
const char *desk_linkaddr
,
657 const char *frame_type
)
659 if (mbuf_prepend(packet
, sizeof(protocol_family_t
), MBUF_DONTWAIT
) != 0) {
660 printf("utun_framer - ifnet_output prepend failed\n");
662 ifnet_stat_increment_out(interface
, 0, 0, 1);
664 // just return, because the buffer was freed in mbuf_prepend
668 // place protocol number at the beginning of the mbuf
669 *(protocol_family_t
*)mbuf_data(*packet
) = htonl(*(protocol_family_t
*)(uintptr_t)(size_t)frame_type
);
676 __unused ifnet_t interface
,
677 protocol_family_t protocol
,
678 __unused
const struct ifnet_demux_desc
*demux_array
,
679 __unused u_int32_t demux_count
)
695 __unused ifnet_t interface
,
696 __unused protocol_family_t protocol
)
708 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
712 ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
);
716 /* ifioctl() takes care of it */
721 /* This will be called for called for IPv6 Address additions */
722 if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
724 /* Fall though for other families like IPv4 */
737 struct utun_pcb
*pcb
= ifnet_softc(interface
);
741 OSDecrementAtomic(&utun_ifcount
);
744 /* Protocol Handlers */
748 __unused ifnet_t interface
,
749 protocol_family_t protocol
,
751 __unused
char *frame_header
)
754 // remove protocol family first
755 mbuf_adj(m
, sizeof(u_int32_t
));
757 proto_input(protocol
, m
);
763 utun_proto_pre_output(
764 __unused ifnet_t interface
,
765 protocol_family_t protocol
,
766 __unused mbuf_t
*packet
,
767 __unused
const struct sockaddr
*dest
,
768 __unused
void *route
,
769 __unused
char *frame_type
,
770 __unused
char *link_layer_dest
)
773 *(protocol_family_t
*)(void *)frame_type
= protocol
;
780 protocol_family_t protocol
)
782 struct ifnet_attach_proto_param proto
;
785 bzero(&proto
, sizeof(proto
));
786 proto
.input
= utun_proto_input
;
787 proto
.pre_output
= utun_proto_pre_output
;
789 result
= ifnet_attach_protocol(interface
, protocol
, &proto
);
790 if (result
!= 0 && result
!= EEXIST
) {
791 printf("utun_attach_inet - ifnet_attach_protocol %d failed: %d\n",