2 * Copyright (c) 2008-2010 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 /* always set SS_PRIV, we want to close and detach regardless */
370 sock_setpriv(pf_socket
, 1);
372 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
373 if (result
== 0 || result
== ENXIO
) {
374 /* We are done! We either detached or weren't attached. */
377 else if (result
!= EBUSY
) {
378 /* Uh, not really sure what happened here... */
379 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
384 * At this point, we received an EBUSY error. This means there are
385 * addresses attached. We should detach them and then try again.
387 result
= ifnet_get_address_list_family(interface
, &addresses
, protocol
);
389 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
390 ifnet_name(interface
), ifnet_unit(interface
),
391 protocol
== PF_INET
? "PF_INET" : "PF_INET6", result
);
395 for (i
= 0; addresses
[i
] != 0; i
++) {
396 utun_remove_address(interface
, protocol
, addresses
[i
], pf_socket
);
398 ifnet_free_address_list(addresses
);
402 * The addresses should be gone, we should try the remove again.
404 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
405 if (result
!= 0 && result
!= ENXIO
) {
406 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
410 if (pf_socket
!= NULL
)
411 sock_close(pf_socket
);
413 if (addresses
!= NULL
)
414 ifnet_free_address_list(addresses
);
419 __unused kern_ctl_ref kctlref
,
420 __unused u_int32_t unit
,
423 struct utun_pcb
*pcb
= unitinfo
;
424 ifnet_t ifp
= pcb
->utun_ifp
;
427 pcb
->utun_ctlref
= NULL
;
431 * We want to do everything in our power to ensure that the interface
432 * really goes away when the socket is closed. We must remove IP/IPv6
433 * addresses and detach the protocols. Finally, we can remove and
434 * release the interface.
436 utun_cleanup_family(ifp
, AF_INET
);
437 utun_cleanup_family(ifp
, AF_INET6
);
439 if ((result
= ifnet_detach(ifp
)) != 0) {
440 printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result
);
443 if ((result
= ifnet_release(ifp
)) != 0) {
444 printf("utun_ctl_disconnect - ifnet_release failed: %d\n", result
);
452 __unused kern_ctl_ref kctlref
,
453 __unused u_int32_t unit
,
458 struct utun_pcb
*pcb
= unitinfo
;
461 mbuf_pkthdr_setrcvif(m
, pcb
->utun_ifp
);
463 bpf_tap_in(pcb
->utun_ifp
, DLT_NULL
, m
, 0, 0);
465 if (pcb
->utun_flags
& UTUN_FLAGS_NO_INPUT
) {
471 if (!pcb
->utun_ext_ifdata_stats
) {
472 struct ifnet_stat_increment_param incs
;
474 bzero(&incs
, sizeof(incs
));
476 incs
.bytes_in
= mbuf_pkthdr_len(m
);
477 result
= ifnet_input(pcb
->utun_ifp
, m
, &incs
);
479 result
= ifnet_input(pcb
->utun_ifp
, m
, NULL
);
482 ifnet_stat_increment_in(pcb
->utun_ifp
, 0, 0, 1);
484 printf("utun_ctl_send - ifnet_input failed: %d\n", result
);
493 __unused kern_ctl_ref kctlref
,
494 __unused u_int32_t unit
,
500 struct utun_pcb
*pcb
= unitinfo
;
503 /* check for privileges for privileged options */
506 case UTUN_OPT_EXT_IFDATA_STATS
:
507 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
515 if (len
!= sizeof(u_int32_t
))
518 pcb
->utun_flags
= *(u_int32_t
*)data
;
521 case UTUN_OPT_EXT_IFDATA_STATS
:
522 if (len
!= sizeof(int)) {
526 pcb
->utun_ext_ifdata_stats
= (*(int *)data
) ? 1 : 0;
529 case UTUN_OPT_INC_IFDATA_STATS_IN
:
530 case UTUN_OPT_INC_IFDATA_STATS_OUT
: {
531 struct utun_stats_param
*utsp
= (struct utun_stats_param
*)data
;
533 if (utsp
== NULL
|| len
< sizeof(struct utun_stats_param
)) {
537 if (!pcb
->utun_ext_ifdata_stats
) {
541 if (opt
== UTUN_OPT_INC_IFDATA_STATS_IN
)
542 ifnet_stat_increment_in(pcb
->utun_ifp
, utsp
->utsp_packets
,
543 utsp
->utsp_bytes
, utsp
->utsp_errors
);
545 ifnet_stat_increment_out(pcb
->utun_ifp
, utsp
->utsp_packets
,
546 utsp
->utsp_bytes
, utsp
->utsp_errors
);
551 result
= ENOPROTOOPT
;
560 __unused kern_ctl_ref kctlref
,
561 __unused u_int32_t unit
,
567 struct utun_pcb
*pcb
= unitinfo
;
572 if (*len
!= sizeof(u_int32_t
))
575 *(u_int32_t
*)data
= pcb
->utun_flags
;
578 case UTUN_OPT_EXT_IFDATA_STATS
:
579 if (*len
!= sizeof(int))
582 *(int *)data
= (pcb
->utun_ext_ifdata_stats
) ? 1 : 0;
585 case UTUN_OPT_IFNAME
:
586 *len
= snprintf(data
, *len
, "%s%d", ifnet_name(pcb
->utun_ifp
), ifnet_unit(pcb
->utun_ifp
)) + 1;
590 result
= ENOPROTOOPT
;
597 /* Network Interface functions */
603 struct utun_pcb
*pcb
= ifnet_softc(interface
);
606 bpf_tap_out(pcb
->utun_ifp
, DLT_NULL
, data
, 0, 0);
608 if (pcb
->utun_flags
& UTUN_FLAGS_NO_OUTPUT
) {
614 if (pcb
->utun_ctlref
) {
615 int length
= mbuf_pkthdr_len(data
);
616 result
= ctl_enqueuembuf(pcb
->utun_ctlref
, pcb
->utun_unit
, data
, CTL_DATA_EOR
);
619 printf("utun_output - ctl_enqueuembuf failed: %d\n", result
);
621 ifnet_stat_increment_out(interface
, 0, 0, 1);
624 if (!pcb
->utun_ext_ifdata_stats
)
625 ifnet_stat_increment_out(interface
, 1, length
, 0);
634 /* Network Interface functions */
637 __unused ifnet_t interface
,
639 __unused
char *frame_header
,
640 protocol_family_t
*protocol
)
643 while (data
!= NULL
&& mbuf_len(data
) < 1) {
644 data
= mbuf_next(data
);
650 *protocol
= ntohl(*(u_int32_t
*)mbuf_data(data
));
656 __unused ifnet_t interface
,
658 __unused
const struct sockaddr
*dest
,
659 __unused
const char *desk_linkaddr
,
660 const char *frame_type
)
662 if (mbuf_prepend(packet
, sizeof(protocol_family_t
), MBUF_DONTWAIT
) != 0) {
663 printf("utun_framer - ifnet_output prepend failed\n");
665 ifnet_stat_increment_out(interface
, 0, 0, 1);
667 // just return, because the buffer was freed in mbuf_prepend
671 // place protocol number at the beginning of the mbuf
672 *(protocol_family_t
*)mbuf_data(*packet
) = htonl(*(protocol_family_t
*)(uintptr_t)(size_t)frame_type
);
679 __unused ifnet_t interface
,
680 protocol_family_t protocol
,
681 __unused
const struct ifnet_demux_desc
*demux_array
,
682 __unused u_int32_t demux_count
)
698 __unused ifnet_t interface
,
699 __unused protocol_family_t protocol
)
714 ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
);
718 /* ifioctl() takes care of it */
732 struct utun_pcb
*pcb
= ifnet_softc(interface
);
736 OSDecrementAtomic(&utun_ifcount
);
739 /* Protocol Handlers */
743 __unused ifnet_t interface
,
744 protocol_family_t protocol
,
746 __unused
char *frame_header
)
749 // remove protocol family first
750 mbuf_adj(m
, sizeof(u_int32_t
));
752 if (proto_input(protocol
, m
) != 0)
759 utun_proto_pre_output(
760 __unused ifnet_t interface
,
761 protocol_family_t protocol
,
762 __unused mbuf_t
*packet
,
763 __unused
const struct sockaddr
*dest
,
764 __unused
void *route
,
765 __unused
char *frame_type
,
766 __unused
char *link_layer_dest
)
769 *(protocol_family_t
*)(void *)frame_type
= protocol
;
776 protocol_family_t protocol
)
778 struct ifnet_attach_proto_param proto
;
781 bzero(&proto
, sizeof(proto
));
782 proto
.input
= utun_proto_input
;
783 proto
.pre_output
= utun_proto_pre_output
;
785 result
= ifnet_attach_protocol(interface
, protocol
, &proto
);
786 if (result
!= 0 && result
!= EEXIST
) {
787 printf("utun_attach_inet - ifnet_attach_protocol %d failed: %d\n",