2 * Copyright (c) 2008 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 */
100 static kern_ctl_ref utun_kctlref
;
101 static u_int32_t utun_family
;
102 static OSMallocTag utun_malloc_tag
;
103 static SInt32 utun_ifcount
= 0;
107 utun_alloc(size_t size
)
109 size_t *mem
= OSMalloc(size
+ sizeof(size_t), utun_malloc_tag
);
112 *mem
= size
+ sizeof(size_t);
124 OSFree(size
, *size
, utun_malloc_tag
);
128 utun_register_control(void)
130 struct kern_ctl_reg kern_ctl
;
133 /* Create a tag to allocate memory */
134 utun_malloc_tag
= OSMalloc_Tagalloc(UTUN_CONTROL_NAME
, OSMT_DEFAULT
);
136 /* Find a unique value for our interface family */
137 result
= mbuf_tag_id_find(UTUN_CONTROL_NAME
, &utun_family
);
139 printf("utun_register_control - mbuf_tag_id_find_internal failed: %d\n", result
);
143 bzero(&kern_ctl
, sizeof(kern_ctl
));
144 strncpy(kern_ctl
.ctl_name
, UTUN_CONTROL_NAME
, sizeof(kern_ctl
.ctl_name
));
145 kern_ctl
.ctl_name
[sizeof(kern_ctl
.ctl_name
) - 1] = 0;
146 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
; /* Require root */
147 kern_ctl
.ctl_connect
= utun_ctl_connect
;
148 kern_ctl
.ctl_disconnect
= utun_ctl_disconnect
;
149 kern_ctl
.ctl_send
= utun_ctl_send
;
150 kern_ctl
.ctl_setopt
= utun_ctl_setopt
;
151 kern_ctl
.ctl_getopt
= utun_ctl_getopt
;
153 result
= ctl_register(&kern_ctl
, &utun_kctlref
);
155 printf("utun_register_control - ctl_register failed: %d\n", result
);
159 /* Register the protocol plumbers */
160 if ((result
= proto_register_plumber(PF_INET
, utun_family
,
161 utun_attach_proto
, NULL
)) != 0) {
162 printf("utun_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n",
163 utun_family
, result
);
164 ctl_deregister(utun_kctlref
);
168 /* Register the protocol plumbers */
169 if ((result
= proto_register_plumber(PF_INET6
, utun_family
,
170 utun_attach_proto
, NULL
)) != 0) {
171 proto_unregister_plumber(PF_INET
, utun_family
);
172 ctl_deregister(utun_kctlref
);
173 printf("utun_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n",
174 utun_family
, result
);
181 /* Kernel control functions */
185 kern_ctl_ref kctlref
,
186 struct sockaddr_ctl
*sac
,
189 struct ifnet_init_params utun_init
;
190 struct utun_pcb
*pcb
;
193 /* kernel control allocates, interface frees */
194 pcb
= utun_alloc(sizeof(*pcb
));
198 /* Setup the protocol control block */
199 bzero(pcb
, sizeof(*pcb
));
201 pcb
->ctlref
= kctlref
;
202 pcb
->unit
= sac
->sc_unit
;
204 printf("utun_ctl_connect: creating interface utun%d\n", pcb
->unit
- 1);
206 /* Create the interface */
207 bzero(&utun_init
, sizeof(utun_init
));
208 utun_init
.name
= "utun";
209 utun_init
.unit
= pcb
->unit
- 1;
210 utun_init
.family
= utun_family
;
211 utun_init
.type
= IFT_OTHER
;
212 utun_init
.output
= utun_output
;
213 utun_init
.demux
= utun_demux
;
214 utun_init
.framer
= utun_framer
;
215 utun_init
.add_proto
= utun_add_proto
;
216 utun_init
.del_proto
= utun_del_proto
;
217 utun_init
.softc
= pcb
;
218 utun_init
.ioctl
= utun_ioctl
;
219 utun_init
.detach
= utun_detached
;
221 result
= ifnet_allocate(&utun_init
, &pcb
->ifp
);
223 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
227 OSIncrementAtomic(&utun_ifcount
);
229 /* Set flags and additional information. */
230 ifnet_set_mtu(pcb
->ifp
, 1500);
231 ifnet_set_flags(pcb
->ifp
, IFF_UP
| IFF_MULTICAST
| IFF_POINTOPOINT
, 0xffff);
233 /* The interface must generate its own IPv6 LinkLocal address,
234 * if possible following the recommendation of RFC2472 to the 64bit interface ID
236 ifnet_set_eflags(pcb
->ifp
, IFEF_NOAUTOIPV6LL
, IFEF_NOAUTOIPV6LL
);
238 /* Attach the interface */
239 result
= ifnet_attach(pcb
->ifp
, NULL
);
241 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result
);
242 ifnet_release(pcb
->ifp
);
248 bpfattach(pcb
->ifp
, DLT_NULL
, 4);
256 protocol_family_t protocol
,
259 errno_t result
= EPROTONOSUPPORT
;
261 /* Attempt a detach */
262 if (protocol
== PF_INET
) {
265 bzero(&ifr
, sizeof(ifr
));
266 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
267 ifnet_name(interface
), ifnet_unit(interface
));
269 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH
, &ifr
);
271 else if (protocol
== PF_INET6
) {
272 struct in6_ifreq ifr6
;
274 bzero(&ifr6
, sizeof(ifr6
));
275 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
276 ifnet_name(interface
), ifnet_unit(interface
));
278 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH_IN6
, &ifr6
);
287 protocol_family_t protocol
,
293 /* Attempt a detach */
294 if (protocol
== PF_INET
) {
297 bzero(&ifr
, sizeof(ifr
));
298 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
299 ifnet_name(interface
), ifnet_unit(interface
));
300 result
= ifaddr_address(address
, &ifr
.ifr_addr
, sizeof(ifr
.ifr_addr
));
302 printf("utun_remove_address - ifaddr_address failed: %d", result
);
305 result
= sock_ioctl(pf_socket
, SIOCDIFADDR
, &ifr
);
307 printf("utun_remove_address - SIOCDIFADDR failed: %d", result
);
311 else if (protocol
== PF_INET6
) {
312 struct in6_ifreq ifr6
;
314 bzero(&ifr6
, sizeof(ifr6
));
315 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
316 ifnet_name(interface
), ifnet_unit(interface
));
317 result
= ifaddr_address(address
, (struct sockaddr
*)&ifr6
.ifr_addr
,
318 sizeof(ifr6
.ifr_addr
));
320 printf("utun_remove_address - ifaddr_address failed (v6): %d",
324 result
= sock_ioctl(pf_socket
, SIOCDIFADDR_IN6
, &ifr6
);
326 printf("utun_remove_address - SIOCDIFADDR_IN6 failed: %d",
336 protocol_family_t protocol
)
339 socket_t pf_socket
= NULL
;
340 ifaddr_t
*addresses
= NULL
;
343 if (protocol
!= PF_INET
&& protocol
!= PF_INET6
) {
344 printf("utun_cleanup_family - invalid protocol family %d\n", protocol
);
348 /* Create a socket for removing addresses and detaching the protocol */
349 result
= sock_socket(protocol
, SOCK_DGRAM
, 0, NULL
, NULL
, &pf_socket
);
351 if (result
!= EAFNOSUPPORT
)
352 printf("utun_cleanup_family - failed to create %s socket: %d\n",
353 protocol
== PF_INET
? "IP" : "IPv6", result
);
357 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
358 if (result
== 0 || result
== ENXIO
) {
359 /* We are done! We either detached or weren't attached. */
362 else if (result
!= EBUSY
) {
363 /* Uh, not really sure what happened here... */
364 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
369 * At this point, we received an EBUSY error. This means there are
370 * addresses attached. We should detach them and then try again.
372 result
= ifnet_get_address_list_family(interface
, &addresses
, protocol
);
374 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
375 ifnet_name(interface
), ifnet_unit(interface
),
376 protocol
== PF_INET
? "PF_INET" : "PF_INET6", result
);
380 for (i
= 0; addresses
[i
] != 0; i
++) {
381 utun_remove_address(interface
, protocol
, addresses
[i
], pf_socket
);
383 ifnet_free_address_list(addresses
);
387 * The addresses should be gone, we should try the remove again.
389 result
= utun_detach_ip(interface
, protocol
, pf_socket
);
390 if (result
!= 0 && result
!= ENXIO
) {
391 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result
);
395 if (pf_socket
!= NULL
)
396 sock_close(pf_socket
);
398 if (addresses
!= NULL
)
399 ifnet_free_address_list(addresses
);
404 __unused kern_ctl_ref kctlref
,
405 __unused u_int32_t unit
,
408 struct utun_pcb
*pcb
= unitinfo
;
409 ifnet_t ifp
= pcb
->ifp
;
416 * We want to do everything in our power to ensure that the interface
417 * really goes away when the socket is closed. We must remove IP/IPv6
418 * addresses and detach the protocols. Finally, we can remove and
419 * release the interface.
421 utun_cleanup_family(ifp
, AF_INET
);
422 utun_cleanup_family(ifp
, AF_INET6
);
424 if ((result
= ifnet_detach(ifp
)) != 0) {
425 printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result
);
428 if ((result
= ifnet_release(ifp
)) != 0) {
429 printf("utun_ctl_disconnect - ifnet_release failed: %d\n", result
);
437 __unused kern_ctl_ref kctlref
,
438 __unused u_int32_t unit
,
443 struct utun_pcb
*pcb
= unitinfo
;
444 struct ifnet_stat_increment_param incs
;
447 mbuf_pkthdr_setrcvif(m
, pcb
->ifp
);
449 bpf_tap_in(pcb
->ifp
, DLT_NULL
, m
, 0, 0);
451 if (pcb
->flags
& UTUN_FLAGS_NO_INPUT
) {
457 bzero(&incs
, sizeof(incs
));
459 incs
.bytes_in
= mbuf_pkthdr_len(m
);
460 result
= ifnet_input(pcb
->ifp
, m
, &incs
);
462 ifnet_stat_increment_in(pcb
->ifp
, 0, 0, 1);
463 printf("utun_ctl_send - ifnet_input failed: %d\n", result
);
472 __unused kern_ctl_ref kctlref
,
473 __unused u_int32_t unit
,
479 struct utun_pcb
*pcb
= unitinfo
;
482 /* check for privileges for privileged options */
485 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
493 if (len
!= sizeof(u_int32_t
))
496 pcb
->flags
= *(u_int32_t
*)data
;
499 result
= ENOPROTOOPT
;
508 __unused kern_ctl_ref kctlref
,
509 __unused u_int32_t unit
,
515 struct utun_pcb
*pcb
= unitinfo
;
520 if (*len
!= sizeof(u_int32_t
))
523 *(u_int32_t
*)data
= pcb
->flags
;
525 case UTUN_OPT_IFNAME
:
526 *len
= snprintf(data
, *len
, "%s%d", ifnet_name(pcb
->ifp
), ifnet_unit(pcb
->ifp
)) + 1;
529 result
= ENOPROTOOPT
;
536 /* Network Interface functions */
542 struct utun_pcb
*pcb
= ifnet_softc(interface
);
545 bpf_tap_out(pcb
->ifp
, DLT_NULL
, data
, 0, 0);
547 if (pcb
->flags
& UTUN_FLAGS_NO_OUTPUT
) {
554 int length
= mbuf_pkthdr_len(data
);
555 result
= ctl_enqueuembuf(pcb
->ctlref
, pcb
->unit
, data
, CTL_DATA_EOR
);
558 printf("utun_output - ctl_enqueuembuf failed: %d\n", result
);
559 ifnet_stat_increment_out(interface
, 0, 0, 1);
562 ifnet_stat_increment_out(interface
, 1, length
, 0);
571 /* Network Interface functions */
574 __unused ifnet_t interface
,
576 __unused
char *frame_header
,
577 protocol_family_t
*protocol
)
580 while (data
!= NULL
&& mbuf_len(data
) < 1) {
581 data
= mbuf_next(data
);
587 *protocol
= ntohl(*(u_int32_t
*)mbuf_data(data
));
593 __unused ifnet_t interface
,
595 __unused
const struct sockaddr
*dest
,
596 __unused
const char *desk_linkaddr
,
597 const char *frame_type
)
600 if (mbuf_prepend(packet
, sizeof(protocol_family_t
), MBUF_DONTWAIT
) != 0) {
601 printf("utun_framer - ifnet_output prepend failed\n");
602 ifnet_stat_increment_out(interface
, 0, 0, 1);
603 // just return, because the buffer was freed in mbuf_prepend
607 // place protocol number at the beginning of the mbuf
608 *(protocol_family_t
*)mbuf_data(*packet
) = htonl(*(protocol_family_t
*)(uintptr_t)(size_t)frame_type
);
615 __unused ifnet_t interface
,
616 protocol_family_t protocol
,
617 __unused
const struct ifnet_demux_desc
*demux_array
,
618 __unused u_int32_t demux_count
)
634 __unused ifnet_t interface
,
635 __unused protocol_family_t protocol
)
642 __unused ifnet_t interface
,
643 __unused u_long command
,
647 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
651 ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
);
656 /* This will be called for called for IPv6 Address additions */
657 if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
659 /* Fall though for other families like IPv4 */
672 struct utun_pcb
*pcb
= ifnet_softc(interface
);
676 OSDecrementAtomic(&utun_ifcount
);
679 /* Protocol Handlers */
683 __unused ifnet_t interface
,
684 protocol_family_t protocol
,
686 __unused
char *frame_header
)
689 // remove protocol family first
690 mbuf_adj(m
, sizeof(u_int32_t
));
692 proto_input(protocol
, m
);
698 utun_proto_pre_output(
699 __unused ifnet_t interface
,
700 protocol_family_t protocol
,
701 __unused mbuf_t
*packet
,
702 __unused
const struct sockaddr
*dest
,
703 __unused
void *route
,
704 __unused
char *frame_type
,
705 __unused
char *link_layer_dest
)
708 *(protocol_family_t
*)(void *)frame_type
= protocol
;
715 protocol_family_t protocol
)
717 struct ifnet_attach_proto_param proto
;
720 bzero(&proto
, sizeof(proto
));
721 proto
.input
= utun_proto_input
;
722 proto
.pre_output
= utun_proto_pre_output
;
724 result
= ifnet_attach_protocol(interface
, protocol
, &proto
);
725 if (result
!= 0 && result
!= EEXIST
) {
726 printf("utun_attach_inet - ifnet_attach_protocol %d failed: %d\n",