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