]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/if_utun.c
xnu-3248.60.10.tar.gz
[apple/xnu.git] / bsd / net / if_utun.c
1 /*
2 * Copyright (c) 2008-2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29
30
31 /* ----------------------------------------------------------------------------------
32 Application of kernel control for interface creation
33
34 Theory of operation:
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 ---------------------------------------------------------------------------------- */
38
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>
44 #include <net/if.h>
45 #include <net/if_types.h>
46 #include <net/bpf.h>
47 #include <net/if_utun.h>
48 #include <libkern/OSMalloc.h>
49 #include <libkern/OSAtomic.h>
50 #include <sys/mbuf.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>
56
57
58 /* Kernel Control functions */
59 static errno_t utun_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
60 void **unitinfo);
61 static errno_t utun_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit,
62 void *unitinfo);
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);
69 static void utun_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
70 int flags);
71
72 /* Network Interface functions */
73 static void utun_start(ifnet_t interface);
74 static errno_t utun_output(ifnet_t interface, mbuf_t data);
75 static errno_t utun_demux(ifnet_t interface, mbuf_t data, char *frame_header,
76 protocol_family_t *protocol);
77 static errno_t utun_framer(ifnet_t interface, mbuf_t *packet,
78 const struct sockaddr *dest, const char *desk_linkaddr,
79 const char *frame_type, u_int32_t *prepend_len, u_int32_t *postpend_len);
80 static errno_t utun_add_proto(ifnet_t interface, protocol_family_t protocol,
81 const struct ifnet_demux_desc *demux_array,
82 u_int32_t demux_count);
83 static errno_t utun_del_proto(ifnet_t interface, protocol_family_t protocol);
84 static errno_t utun_ioctl(ifnet_t interface, u_long cmd, void *data);
85 static void utun_detached(ifnet_t interface);
86
87 /* Protocol handlers */
88 static errno_t utun_attach_proto(ifnet_t interface, protocol_family_t proto);
89 static errno_t utun_proto_input(ifnet_t interface, protocol_family_t protocol,
90 mbuf_t m, char *frame_header);
91 static errno_t utun_proto_pre_output(ifnet_t interface, protocol_family_t protocol,
92 mbuf_t *packet, const struct sockaddr *dest, void *route,
93 char *frame_type, char *link_layer_dest);
94 __private_extern__ errno_t utun_pkt_input (struct utun_pcb *pcb, mbuf_t m);
95
96 static kern_ctl_ref utun_kctlref;
97 static u_int32_t utun_family;
98 static OSMallocTag utun_malloc_tag;
99 static SInt32 utun_ifcount = 0;
100
101 /* Prepend length */
102 void*
103 utun_alloc(size_t size)
104 {
105 size_t *mem = OSMalloc(size + sizeof(size_t), utun_malloc_tag);
106
107 if (mem) {
108 *mem = size + sizeof(size_t);
109 mem++;
110 }
111
112 return (void*)mem;
113 }
114
115 void
116 utun_free(void *ptr)
117 {
118 size_t *size = ptr;
119 size--;
120 OSFree(size, *size, utun_malloc_tag);
121 }
122
123 errno_t
124 utun_register_control(void)
125 {
126 struct kern_ctl_reg kern_ctl;
127 errno_t result = 0;
128
129 /* Create a tag to allocate memory */
130 utun_malloc_tag = OSMalloc_Tagalloc(UTUN_CONTROL_NAME, OSMT_DEFAULT);
131
132 /* Find a unique value for our interface family */
133 result = mbuf_tag_id_find(UTUN_CONTROL_NAME, &utun_family);
134 if (result != 0) {
135 printf("utun_register_control - mbuf_tag_id_find_internal failed: %d\n", result);
136 return result;
137 }
138
139 bzero(&kern_ctl, sizeof(kern_ctl));
140 strlcpy(kern_ctl.ctl_name, UTUN_CONTROL_NAME, sizeof(kern_ctl.ctl_name));
141 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0;
142 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED | CTL_FLAG_REG_EXTENDED; /* Require root */
143 kern_ctl.ctl_sendsize = 512 * 1024;
144 kern_ctl.ctl_recvsize = 512 * 1024;
145 kern_ctl.ctl_connect = utun_ctl_connect;
146 kern_ctl.ctl_disconnect = utun_ctl_disconnect;
147 kern_ctl.ctl_send = utun_ctl_send;
148 kern_ctl.ctl_setopt = utun_ctl_setopt;
149 kern_ctl.ctl_getopt = utun_ctl_getopt;
150 kern_ctl.ctl_rcvd = utun_ctl_rcvd;
151
152 utun_ctl_init_crypto();
153
154 result = ctl_register(&kern_ctl, &utun_kctlref);
155 if (result != 0) {
156 printf("utun_register_control - ctl_register failed: %d\n", result);
157 return result;
158 }
159
160 /* Register the protocol plumbers */
161 if ((result = proto_register_plumber(PF_INET, utun_family,
162 utun_attach_proto, NULL)) != 0) {
163 printf("utun_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n",
164 utun_family, result);
165 ctl_deregister(utun_kctlref);
166 return result;
167 }
168
169 /* Register the protocol plumbers */
170 if ((result = proto_register_plumber(PF_INET6, utun_family,
171 utun_attach_proto, NULL)) != 0) {
172 proto_unregister_plumber(PF_INET, utun_family);
173 ctl_deregister(utun_kctlref);
174 printf("utun_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n",
175 utun_family, result);
176 return result;
177 }
178
179 return 0;
180 }
181
182 /* Kernel control functions */
183
184 static errno_t
185 utun_ctl_connect(
186 kern_ctl_ref kctlref,
187 struct sockaddr_ctl *sac,
188 void **unitinfo)
189 {
190 struct ifnet_init_eparams utun_init;
191 struct utun_pcb *pcb;
192 errno_t result;
193 struct ifnet_stats_param stats;
194
195 /* kernel control allocates, interface frees */
196 pcb = utun_alloc(sizeof(*pcb));
197 if (pcb == NULL)
198 return ENOMEM;
199
200 /* Setup the protocol control block */
201 bzero(pcb, sizeof(*pcb));
202 *unitinfo = pcb;
203 pcb->utun_ctlref = kctlref;
204 pcb->utun_unit = sac->sc_unit;
205 pcb->utun_max_pending_packets = 1;
206
207 printf("utun_ctl_connect: creating interface utun%d\n", pcb->utun_unit - 1);
208
209 /* Create the interface */
210 bzero(&utun_init, sizeof(utun_init));
211 utun_init.ver = IFNET_INIT_CURRENT_VERSION;
212 utun_init.len = sizeof (utun_init);
213 utun_init.name = "utun";
214 utun_init.start = utun_start;
215 utun_init.unit = pcb->utun_unit - 1;
216 utun_init.family = utun_family;
217 utun_init.type = IFT_OTHER;
218 utun_init.demux = utun_demux;
219 utun_init.framer_extended = utun_framer;
220 utun_init.add_proto = utun_add_proto;
221 utun_init.del_proto = utun_del_proto;
222 utun_init.softc = pcb;
223 utun_init.ioctl = utun_ioctl;
224 utun_init.detach = utun_detached;
225
226 result = ifnet_allocate_extended(&utun_init, &pcb->utun_ifp);
227 if (result != 0) {
228 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result);
229 utun_free(pcb);
230 return result;
231 }
232 OSIncrementAtomic(&utun_ifcount);
233
234 /* Set flags and additional information. */
235 ifnet_set_mtu(pcb->utun_ifp, 1500);
236 ifnet_set_flags(pcb->utun_ifp, IFF_UP | IFF_MULTICAST | IFF_POINTOPOINT, 0xffff);
237
238 /* The interface must generate its own IPv6 LinkLocal address,
239 * if possible following the recommendation of RFC2472 to the 64bit interface ID
240 */
241 ifnet_set_eflags(pcb->utun_ifp, IFEF_NOAUTOIPV6LL, IFEF_NOAUTOIPV6LL);
242
243 /* Reset the stats in case as the interface may have been recycled */
244 bzero(&stats, sizeof(struct ifnet_stats_param));
245 ifnet_set_stat(pcb->utun_ifp, &stats);
246
247 /* Attach the interface */
248 result = ifnet_attach(pcb->utun_ifp, NULL);
249 if (result != 0) {
250 printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result);
251 ifnet_release(pcb->utun_ifp);
252 utun_free(pcb);
253 }
254
255 /* Attach to bpf */
256 if (result == 0)
257 bpfattach(pcb->utun_ifp, DLT_NULL, 4);
258
259 /* The interfaces resoures allocated, mark it as running */
260 if (result == 0)
261 ifnet_set_flags(pcb->utun_ifp, IFF_RUNNING, IFF_RUNNING);
262
263 return result;
264 }
265
266 static errno_t
267 utun_detach_ip(
268 ifnet_t interface,
269 protocol_family_t protocol,
270 socket_t pf_socket)
271 {
272 errno_t result = EPROTONOSUPPORT;
273
274 /* Attempt a detach */
275 if (protocol == PF_INET) {
276 struct ifreq ifr;
277
278 bzero(&ifr, sizeof(ifr));
279 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d",
280 ifnet_name(interface), ifnet_unit(interface));
281
282 result = sock_ioctl(pf_socket, SIOCPROTODETACH, &ifr);
283 }
284 else if (protocol == PF_INET6) {
285 struct in6_ifreq ifr6;
286
287 bzero(&ifr6, sizeof(ifr6));
288 snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d",
289 ifnet_name(interface), ifnet_unit(interface));
290
291 result = sock_ioctl(pf_socket, SIOCPROTODETACH_IN6, &ifr6);
292 }
293
294 return result;
295 }
296
297 static void
298 utun_remove_address(
299 ifnet_t interface,
300 protocol_family_t protocol,
301 ifaddr_t address,
302 socket_t pf_socket)
303 {
304 errno_t result = 0;
305
306 /* Attempt a detach */
307 if (protocol == PF_INET) {
308 struct ifreq ifr;
309
310 bzero(&ifr, sizeof(ifr));
311 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d",
312 ifnet_name(interface), ifnet_unit(interface));
313 result = ifaddr_address(address, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
314 if (result != 0) {
315 printf("utun_remove_address - ifaddr_address failed: %d", result);
316 }
317 else {
318 result = sock_ioctl(pf_socket, SIOCDIFADDR, &ifr);
319 if (result != 0) {
320 printf("utun_remove_address - SIOCDIFADDR failed: %d", result);
321 }
322 }
323 }
324 else if (protocol == PF_INET6) {
325 struct in6_ifreq ifr6;
326
327 bzero(&ifr6, sizeof(ifr6));
328 snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d",
329 ifnet_name(interface), ifnet_unit(interface));
330 result = ifaddr_address(address, (struct sockaddr*)&ifr6.ifr_addr,
331 sizeof(ifr6.ifr_addr));
332 if (result != 0) {
333 printf("utun_remove_address - ifaddr_address failed (v6): %d",
334 result);
335 }
336 else {
337 result = sock_ioctl(pf_socket, SIOCDIFADDR_IN6, &ifr6);
338 if (result != 0) {
339 printf("utun_remove_address - SIOCDIFADDR_IN6 failed: %d",
340 result);
341 }
342 }
343 }
344 }
345
346 static void
347 utun_cleanup_family(
348 ifnet_t interface,
349 protocol_family_t protocol)
350 {
351 errno_t result = 0;
352 socket_t pf_socket = NULL;
353 ifaddr_t *addresses = NULL;
354 int i;
355
356 if (protocol != PF_INET && protocol != PF_INET6) {
357 printf("utun_cleanup_family - invalid protocol family %d\n", protocol);
358 return;
359 }
360
361 /* Create a socket for removing addresses and detaching the protocol */
362 result = sock_socket(protocol, SOCK_DGRAM, 0, NULL, NULL, &pf_socket);
363 if (result != 0) {
364 if (result != EAFNOSUPPORT)
365 printf("utun_cleanup_family - failed to create %s socket: %d\n",
366 protocol == PF_INET ? "IP" : "IPv6", result);
367 goto cleanup;
368 }
369
370 /* always set SS_PRIV, we want to close and detach regardless */
371 sock_setpriv(pf_socket, 1);
372
373 result = utun_detach_ip(interface, protocol, pf_socket);
374 if (result == 0 || result == ENXIO) {
375 /* We are done! We either detached or weren't attached. */
376 goto cleanup;
377 }
378 else if (result != EBUSY) {
379 /* Uh, not really sure what happened here... */
380 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result);
381 goto cleanup;
382 }
383
384 /*
385 * At this point, we received an EBUSY error. This means there are
386 * addresses attached. We should detach them and then try again.
387 */
388 result = ifnet_get_address_list_family(interface, &addresses, protocol);
389 if (result != 0) {
390 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
391 ifnet_name(interface), ifnet_unit(interface),
392 protocol == PF_INET ? "PF_INET" : "PF_INET6", result);
393 goto cleanup;
394 }
395
396 for (i = 0; addresses[i] != 0; i++) {
397 utun_remove_address(interface, protocol, addresses[i], pf_socket);
398 }
399 ifnet_free_address_list(addresses);
400 addresses = NULL;
401
402 /*
403 * The addresses should be gone, we should try the remove again.
404 */
405 result = utun_detach_ip(interface, protocol, pf_socket);
406 if (result != 0 && result != ENXIO) {
407 printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result);
408 }
409
410 cleanup:
411 if (pf_socket != NULL)
412 sock_close(pf_socket);
413
414 if (addresses != NULL)
415 ifnet_free_address_list(addresses);
416 }
417
418 static errno_t
419 utun_ctl_disconnect(
420 __unused kern_ctl_ref kctlref,
421 __unused u_int32_t unit,
422 void *unitinfo)
423 {
424 struct utun_pcb *pcb = unitinfo;
425 ifnet_t ifp = pcb->utun_ifp;
426 errno_t result = 0;
427
428 utun_cleanup_crypto(pcb);
429
430 pcb->utun_ctlref = NULL;
431 pcb->utun_unit = 0;
432
433 /*
434 * We want to do everything in our power to ensure that the interface
435 * really goes away when the socket is closed. We must remove IP/IPv6
436 * addresses and detach the protocols. Finally, we can remove and
437 * release the interface.
438 */
439 utun_cleanup_family(ifp, AF_INET);
440 utun_cleanup_family(ifp, AF_INET6);
441
442 if ((result = ifnet_detach(ifp)) != 0) {
443 printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result);
444 }
445
446 if ((result = ifnet_release(ifp)) != 0) {
447 printf("utun_ctl_disconnect - ifnet_release failed: %d\n", result);
448 }
449
450 return 0;
451 }
452
453 static errno_t
454 utun_ctl_send(
455 __unused kern_ctl_ref kctlref,
456 __unused u_int32_t unit,
457 void *unitinfo,
458 mbuf_t m,
459 __unused int flags)
460 {
461 /*
462 * The userland ABI requires the first four bytes have the protocol family
463 * in network byte order: swap them
464 */
465 if (m_pktlen(m) >= 4)
466 *(protocol_family_t *)mbuf_data(m) = ntohl(*(protocol_family_t *)mbuf_data(m));
467 else
468 printf("%s - unexpected short mbuf pkt len %d\n", __func__, m_pktlen(m) );
469
470 return utun_pkt_input((struct utun_pcb *)unitinfo, m);
471 }
472
473 static errno_t
474 utun_ctl_setopt(
475 __unused kern_ctl_ref kctlref,
476 __unused u_int32_t unit,
477 void *unitinfo,
478 int opt,
479 void *data,
480 size_t len)
481 {
482 struct utun_pcb *pcb = unitinfo;
483 errno_t result = 0;
484
485 /* check for privileges for privileged options */
486 switch (opt) {
487 case UTUN_OPT_FLAGS:
488 case UTUN_OPT_EXT_IFDATA_STATS:
489 case UTUN_OPT_SET_DELEGATE_INTERFACE:
490 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
491 return EPERM;
492 }
493 break;
494 }
495
496 switch (opt) {
497 case UTUN_OPT_FLAGS:
498 if (len != sizeof(u_int32_t))
499 result = EMSGSIZE;
500 else
501 pcb->utun_flags = *(u_int32_t *)data;
502 break;
503
504 case UTUN_OPT_ENABLE_CRYPTO:
505 result = utun_ctl_enable_crypto(kctlref, unit, unitinfo, opt, data, len);
506 break;
507
508 case UTUN_OPT_CONFIG_CRYPTO_KEYS:
509 result = utun_ctl_config_crypto_keys(kctlref, unit, unitinfo, opt, data, len);
510 break;
511
512 case UTUN_OPT_UNCONFIG_CRYPTO_KEYS:
513 result = utun_ctl_unconfig_crypto_keys(kctlref, unit, unitinfo, opt, data, len);
514 break;
515
516 case UTUN_OPT_DISABLE_CRYPTO:
517 result = utun_ctl_disable_crypto(kctlref, unit, unitinfo, opt, data, len);
518 break;
519
520 case UTUN_OPT_STOP_CRYPTO_DATA_TRAFFIC:
521 result = utun_ctl_stop_crypto_data_traffic(kctlref, unit, unitinfo, opt, data, len);
522 break;
523
524 case UTUN_OPT_START_CRYPTO_DATA_TRAFFIC:
525 result = utun_ctl_start_crypto_data_traffic(kctlref, unit, unitinfo, opt, data, len);
526 break;
527
528 case UTUN_OPT_CONFIG_CRYPTO_FRAMER:
529 result = utun_ctl_config_crypto_framer(kctlref, unit, unitinfo, opt, data, len);
530 break;
531
532 case UTUN_OPT_UNCONFIG_CRYPTO_FRAMER:
533 result = utun_ctl_unconfig_crypto_framer(kctlref, unit, unitinfo, opt, data, len);
534 break;
535
536 case UTUN_OPT_EXT_IFDATA_STATS:
537 if (len != sizeof(int)) {
538 result = EMSGSIZE;
539 break;
540 }
541 pcb->utun_ext_ifdata_stats = (*(int *)data) ? 1 : 0;
542 break;
543
544 case UTUN_OPT_INC_IFDATA_STATS_IN:
545 case UTUN_OPT_INC_IFDATA_STATS_OUT: {
546 struct utun_stats_param *utsp = (struct utun_stats_param *)data;
547
548 if (utsp == NULL || len < sizeof(struct utun_stats_param)) {
549 result = EINVAL;
550 break;
551 }
552 if (!pcb->utun_ext_ifdata_stats) {
553 result = EINVAL;
554 break;
555 }
556 if (opt == UTUN_OPT_INC_IFDATA_STATS_IN)
557 ifnet_stat_increment_in(pcb->utun_ifp, utsp->utsp_packets,
558 utsp->utsp_bytes, utsp->utsp_errors);
559 else
560 ifnet_stat_increment_out(pcb->utun_ifp, utsp->utsp_packets,
561 utsp->utsp_bytes, utsp->utsp_errors);
562 break;
563 }
564 case UTUN_OPT_SET_DELEGATE_INTERFACE: {
565 ifnet_t del_ifp = NULL;
566 char name[IFNAMSIZ];
567
568 if (len > IFNAMSIZ - 1) {
569 result = EMSGSIZE;
570 break;
571 }
572 if (len != 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */
573 bcopy(data, name, len);
574 name[len] = 0;
575 result = ifnet_find_by_name(name, &del_ifp);
576 }
577 if (result == 0) {
578 result = ifnet_set_delegate(pcb->utun_ifp, del_ifp);
579 if (del_ifp)
580 ifnet_release(del_ifp);
581 }
582 break;
583 }
584 case UTUN_OPT_MAX_PENDING_PACKETS: {
585 u_int32_t max_pending_packets = 0;
586 if (len != sizeof(u_int32_t)) {
587 result = EMSGSIZE;
588 break;
589 }
590 max_pending_packets = *(u_int32_t *)data;
591 if (max_pending_packets == 0) {
592 result = EINVAL;
593 break;
594 }
595 pcb->utun_max_pending_packets = max_pending_packets;
596 break;
597 }
598 default: {
599 result = ENOPROTOOPT;
600 break;
601 }
602 }
603
604 return result;
605 }
606
607 static errno_t
608 utun_ctl_getopt(
609 __unused kern_ctl_ref kctlref,
610 __unused u_int32_t unit,
611 void *unitinfo,
612 int opt,
613 void *data,
614 size_t *len)
615 {
616 struct utun_pcb *pcb = unitinfo;
617 errno_t result = 0;
618
619 switch (opt) {
620 case UTUN_OPT_FLAGS:
621 if (*len != sizeof(u_int32_t))
622 result = EMSGSIZE;
623 else
624 *(u_int32_t *)data = pcb->utun_flags;
625 break;
626
627 case UTUN_OPT_EXT_IFDATA_STATS:
628 if (*len != sizeof(int))
629 result = EMSGSIZE;
630 else
631 *(int *)data = (pcb->utun_ext_ifdata_stats) ? 1 : 0;
632 break;
633
634 case UTUN_OPT_IFNAME:
635 *len = snprintf(data, *len, "%s%d", ifnet_name(pcb->utun_ifp), ifnet_unit(pcb->utun_ifp)) + 1;
636 break;
637
638 case UTUN_OPT_GENERATE_CRYPTO_KEYS_IDX:
639 result = utun_ctl_generate_crypto_keys_idx(kctlref, unit, unitinfo, opt, data, len);
640 break;
641 case UTUN_OPT_MAX_PENDING_PACKETS: {
642 *len = sizeof(u_int32_t);
643 *((u_int32_t *)data) = pcb->utun_max_pending_packets;
644 break;
645 }
646 default:
647 result = ENOPROTOOPT;
648 break;
649 }
650
651 return result;
652 }
653
654 static void
655 utun_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags)
656 {
657 #pragma unused(flags)
658 bool reenable_output = false;
659 struct utun_pcb *pcb = unitinfo;
660 if (pcb == NULL) {
661 return;
662 }
663 ifnet_lock_exclusive(pcb->utun_ifp);
664
665 u_int32_t utun_packet_cnt;
666 errno_t error_pc = ctl_getenqueuepacketcount(kctlref, unit, &utun_packet_cnt);
667 if (error_pc != 0) {
668 printf("utun_ctl_rcvd: ctl_getenqueuepacketcount returned error %d\n", error_pc);
669 utun_packet_cnt = 0;
670 }
671
672 if (utun_packet_cnt < pcb->utun_max_pending_packets) {
673 reenable_output = true;
674 }
675
676 if (reenable_output) {
677 errno_t error = ifnet_enable_output(pcb->utun_ifp);
678 if (error != 0) {
679 printf("utun_ctl_rcvd: ifnet_enable_output returned error %d\n", error);
680 }
681 }
682 ifnet_lock_done(pcb->utun_ifp);
683 }
684
685 /* Network Interface functions */
686 static void
687 utun_start(ifnet_t interface)
688 {
689 mbuf_t data;
690 struct utun_pcb*pcb = ifnet_softc(interface);
691 for (;;) {
692 bool can_accept_packets = true;
693 ifnet_lock_shared(pcb->utun_ifp);
694
695 u_int32_t utun_packet_cnt;
696 errno_t error_pc = ctl_getenqueuepacketcount(pcb->utun_ctlref, pcb->utun_unit, &utun_packet_cnt);
697 if (error_pc != 0) {
698 printf("utun_start: ctl_getenqueuepacketcount returned error %d\n", error_pc);
699 utun_packet_cnt = 0;
700 }
701
702 can_accept_packets = (utun_packet_cnt < pcb->utun_max_pending_packets);
703 if (!can_accept_packets && pcb->utun_ctlref) {
704 u_int32_t difference = 0;
705 if (ctl_getenqueuereadable(pcb->utun_ctlref, pcb->utun_unit, &difference) == 0) {
706 if (difference > 0) {
707 // If the low-water mark has not yet been reached, we still need to enqueue data
708 // into the buffer
709 can_accept_packets = true;
710 }
711 }
712 }
713 if (!can_accept_packets) {
714 errno_t error = ifnet_disable_output(interface);
715 if (error != 0) {
716 printf("utun_start: ifnet_disable_output returned error %d\n", error);
717 }
718 ifnet_lock_done(pcb->utun_ifp);
719 break;
720 }
721 ifnet_lock_done(pcb->utun_ifp);
722 if (ifnet_dequeue(interface, &data) != 0)
723 break;
724 if (utun_output(interface, data) != 0)
725 break;
726 }
727 }
728
729 static errno_t
730 utun_output(
731 ifnet_t interface,
732 mbuf_t data)
733 {
734 struct utun_pcb *pcb = ifnet_softc(interface);
735 errno_t result;
736
737 if (m_pktlen(data) >= 4) {
738 bpf_tap_out(pcb->utun_ifp, DLT_NULL, data, 0, 0);
739 }
740
741 if (pcb->utun_flags & UTUN_FLAGS_NO_OUTPUT) {
742 /* flush data */
743 mbuf_freem(data);
744 return 0;
745 }
746
747 // otherwise, fall thru to ctl_enqueumbuf
748 if (pcb->utun_ctlref) {
749 int length;
750
751 // only pass packets to utun-crypto if crypto is enabled and 'suspend data traffic' is not.
752 if ((pcb->utun_flags & (UTUN_FLAGS_CRYPTO | UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC)) == UTUN_FLAGS_CRYPTO) {
753 if (utun_pkt_crypto_output(pcb, &data) == 0) {
754 return 0;
755 }
756 }
757
758 /*
759 * The ABI requires the protocol in network byte order
760 */
761 if (m_pktlen(data) >= 4)
762 *(u_int32_t *)mbuf_data(data) = htonl(*(u_int32_t *)mbuf_data(data));
763
764 length = mbuf_pkthdr_len(data);
765 result = ctl_enqueuembuf(pcb->utun_ctlref, pcb->utun_unit, data, CTL_DATA_EOR);
766 if (result != 0) {
767 mbuf_freem(data);
768 printf("utun_output - ctl_enqueuembuf failed: %d\n", result);
769
770 ifnet_stat_increment_out(interface, 0, 0, 1);
771 }
772 else {
773 if (!pcb->utun_ext_ifdata_stats)
774 ifnet_stat_increment_out(interface, 1, length, 0);
775 }
776 }
777 else
778 mbuf_freem(data);
779
780 return 0;
781 }
782
783 static errno_t
784 utun_demux(
785 __unused ifnet_t interface,
786 mbuf_t data,
787 __unused char *frame_header,
788 protocol_family_t *protocol)
789 {
790
791 while (data != NULL && mbuf_len(data) < 1) {
792 data = mbuf_next(data);
793 }
794
795 if (data == NULL)
796 return ENOENT;
797
798 *protocol = *(u_int32_t *)mbuf_data(data);
799 return 0;
800 }
801
802 static errno_t
803 utun_framer(
804 __unused ifnet_t interface,
805 mbuf_t *packet,
806 __unused const struct sockaddr *dest,
807 __unused const char *desk_linkaddr,
808 const char *frame_type,
809 u_int32_t *prepend_len,
810 u_int32_t *postpend_len)
811 {
812 if (mbuf_prepend(packet, sizeof(protocol_family_t), MBUF_DONTWAIT) != 0) {
813 printf("utun_framer - ifnet_output prepend failed\n");
814
815 ifnet_stat_increment_out(interface, 0, 0, 1);
816
817 // just return, because the buffer was freed in mbuf_prepend
818 return EJUSTRETURN;
819 }
820 if (prepend_len != NULL)
821 *prepend_len = sizeof(protocol_family_t);
822 if (postpend_len != NULL)
823 *postpend_len = 0;
824
825 // place protocol number at the beginning of the mbuf
826 *(protocol_family_t *)mbuf_data(*packet) = *(protocol_family_t *)(uintptr_t)(size_t)frame_type;
827
828 return 0;
829 }
830
831 static errno_t
832 utun_add_proto(
833 __unused ifnet_t interface,
834 protocol_family_t protocol,
835 __unused const struct ifnet_demux_desc *demux_array,
836 __unused u_int32_t demux_count)
837 {
838 switch(protocol) {
839 case PF_INET:
840 return 0;
841 case PF_INET6:
842 return 0;
843 default:
844 break;
845 }
846
847 return ENOPROTOOPT;
848 }
849
850 static errno_t
851 utun_del_proto(
852 __unused ifnet_t interface,
853 __unused protocol_family_t protocol)
854 {
855 return 0;
856 }
857
858 static errno_t
859 utun_ioctl(
860 ifnet_t interface,
861 u_long command,
862 void *data)
863 {
864 errno_t result = 0;
865
866 switch(command) {
867 case SIOCSIFMTU:
868 ifnet_set_mtu(interface, ((struct ifreq*)data)->ifr_mtu);
869 break;
870
871 case SIOCSIFFLAGS:
872 /* ifioctl() takes care of it */
873 break;
874
875 default:
876 result = EOPNOTSUPP;
877 }
878
879 return result;
880 }
881
882 static void
883 utun_detached(
884 ifnet_t interface)
885 {
886 struct utun_pcb *pcb = ifnet_softc(interface);
887
888 utun_free(pcb);
889
890 OSDecrementAtomic(&utun_ifcount);
891 }
892
893 /* Protocol Handlers */
894
895 static errno_t
896 utun_proto_input(
897 __unused ifnet_t interface,
898 protocol_family_t protocol,
899 mbuf_t m,
900 __unused char *frame_header)
901 {
902
903 // remove protocol family first
904 mbuf_adj(m, sizeof(u_int32_t));
905
906 if (proto_input(protocol, m) != 0)
907 m_freem(m);
908
909 return 0;
910 }
911
912 static errno_t
913 utun_proto_pre_output(
914 __unused ifnet_t interface,
915 protocol_family_t protocol,
916 __unused mbuf_t *packet,
917 __unused const struct sockaddr *dest,
918 __unused void *route,
919 __unused char *frame_type,
920 __unused char *link_layer_dest)
921 {
922
923 *(protocol_family_t *)(void *)frame_type = protocol;
924 return 0;
925 }
926
927 static errno_t
928 utun_attach_proto(
929 ifnet_t interface,
930 protocol_family_t protocol)
931 {
932 struct ifnet_attach_proto_param proto;
933 errno_t result;
934
935 bzero(&proto, sizeof(proto));
936 proto.input = utun_proto_input;
937 proto.pre_output = utun_proto_pre_output;
938
939 result = ifnet_attach_protocol(interface, protocol, &proto);
940 if (result != 0 && result != EEXIST) {
941 printf("utun_attach_inet - ifnet_attach_protocol %d failed: %d\n",
942 protocol, result);
943 }
944
945 return result;
946 }
947
948 errno_t
949 utun_pkt_input (struct utun_pcb *pcb, mbuf_t m)
950 {
951 errno_t result;
952 protocol_family_t protocol = 0;
953
954 mbuf_pkthdr_setrcvif(m, pcb->utun_ifp);
955
956 if (m_pktlen(m) >= 4) {
957 protocol = *(u_int32_t *)mbuf_data(m);
958
959 bpf_tap_in(pcb->utun_ifp, DLT_NULL, m, 0, 0);
960 }
961 if (pcb->utun_flags & UTUN_FLAGS_NO_INPUT) {
962 /* flush data */
963 mbuf_freem(m);
964 return 0;
965 }
966
967 // quick exit for keepalive packets
968 if (protocol == AF_UTUN && pcb->utun_flags & UTUN_FLAGS_CRYPTO) {
969 if (utun_pkt_crypto_output(pcb, &m) == 0) {
970 return 0;
971 }
972 printf("%s: utun_pkt_crypto_output failed, flags %x\n", __FUNCTION__, pcb->utun_flags);
973 return EINVAL;
974 }
975
976 if (!pcb->utun_ext_ifdata_stats) {
977 struct ifnet_stat_increment_param incs;
978
979 bzero(&incs, sizeof(incs));
980 incs.packets_in = 1;
981 incs.bytes_in = mbuf_pkthdr_len(m);
982 result = ifnet_input(pcb->utun_ifp, m, &incs);
983 } else {
984 result = ifnet_input(pcb->utun_ifp, m, NULL);
985 }
986 if (result != 0) {
987 ifnet_stat_increment_in(pcb->utun_ifp, 0, 0, 1);
988
989 printf("%s - ifnet_input failed: %d\n", __FUNCTION__, result);
990 mbuf_freem(m);
991 }
992
993 return 0;
994 }