]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/if_utun.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / net / if_utun.c
CommitLineData
b0d623f7 1/*
f427ee49 2 * Copyright (c) 2008-2020 Apple Inc. All rights reserved.
b0d623f7
A
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
b0d623f7
A
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.
0a7de745 14 *
b0d623f7
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
b0d623f7
A
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.
0a7de745 25 *
b0d623f7
A
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29
30
31/* ----------------------------------------------------------------------------------
0a7de745
A
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 * ---------------------------------------------------------------------------------- */
b0d623f7
A
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>
0a7de745 48#include <sys/mbuf.h>
b0d623f7
A
49#include <sys/sockio.h>
50#include <netinet/in.h>
5ba3f43e 51#include <netinet/ip.h>
b0d623f7
A
52#include <netinet6/in6_var.h>
53#include <netinet6/in6_var.h>
54#include <sys/kauth.h>
5ba3f43e
A
55#include <net/necp.h>
56#include <kern/zalloc.h>
cb323159 57#include <os/log.h>
5ba3f43e
A
58
59#define UTUN_NEXUS 0
60
5ba3f43e
A
61#if UTUN_NEXUS
62static nexus_controller_t utun_ncd;
63static int utun_ncd_refcount;
64static uuid_t utun_kpipe_uuid;
65static uuid_t utun_nx_dom_prov;
66
67typedef struct utun_nx {
68 uuid_t if_provider;
69 uuid_t if_instance;
cb323159
A
70 uuid_t fsw_provider;
71 uuid_t fsw_instance;
72 uuid_t fsw_device;
73 uuid_t fsw_host;
74 uuid_t fsw_agent;
5ba3f43e
A
75} *utun_nx_t;
76
77#endif // UTUN_NEXUS
78
79/* Control block allocated for each kernel control connection */
80struct utun_pcb {
0a7de745
A
81 TAILQ_ENTRY(utun_pcb) utun_chain;
82 kern_ctl_ref utun_ctlref;
83 ifnet_t utun_ifp;
84 u_int32_t utun_unit;
85 u_int32_t utun_unique_id;
86 u_int32_t utun_flags;
87 int utun_ext_ifdata_stats;
88 u_int32_t utun_max_pending_packets;
89 char utun_if_xname[IFXNAMSIZ];
90 char utun_unique_name[IFXNAMSIZ];
5ba3f43e
A
91 // PCB lock protects state fields and rings
92 decl_lck_rw_data(, utun_pcb_lock);
0a7de745
A
93 struct mbuf * utun_input_chain;
94 struct mbuf * utun_input_chain_last;
cb323159 95 u_int32_t utun_input_chain_count;
5ba3f43e
A
96 // Input chain lock protects the list of input mbufs
97 // The input chain lock must be taken AFTER the PCB lock if both are held
0a7de745 98 lck_mtx_t utun_input_chain_lock;
5ba3f43e
A
99
100#if UTUN_NEXUS
0a7de745
A
101 struct utun_nx utun_nx;
102 int utun_kpipe_enabled;
103 uuid_t utun_kpipe_uuid;
104 void * utun_kpipe_rxring;
105 void * utun_kpipe_txring;
106 kern_pbufpool_t utun_kpipe_pp;
cb323159
A
107 u_int32_t utun_kpipe_tx_ring_size;
108 u_int32_t utun_kpipe_rx_ring_size;
0a7de745
A
109
110 kern_nexus_t utun_netif_nexus;
111 kern_pbufpool_t utun_netif_pp;
112 void * utun_netif_rxring;
113 void * utun_netif_txring;
114 uint64_t utun_netif_txring_size;
115
116 u_int32_t utun_slot_size;
117 u_int32_t utun_netif_ring_size;
118 u_int32_t utun_tx_fsw_ring_size;
119 u_int32_t utun_rx_fsw_ring_size;
cb323159
A
120 // Auto attach flowswitch when netif is enabled. When set to false,
121 // it allows userspace nexus controller to attach and own flowswitch.
122 bool utun_attach_fsw;
123 bool utun_netif_connected;
0a7de745
A
124 bool utun_use_netif;
125 bool utun_needs_netagent;
5ba3f43e
A
126#endif // UTUN_NEXUS
127};
39037602 128
b0d623f7 129/* Kernel Control functions */
f427ee49 130static errno_t utun_ctl_setup(u_int32_t *unit, void **unitinfo);
0a7de745
A
131static errno_t utun_ctl_bind(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
132 void **unitinfo);
133static errno_t utun_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
134 void **unitinfo);
135static errno_t utun_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit,
136 void *unitinfo);
137static errno_t utun_ctl_send(kern_ctl_ref kctlref, u_int32_t unit,
138 void *unitinfo, mbuf_t m, int flags);
139static errno_t utun_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
140 int opt, void *data, size_t *len);
141static errno_t utun_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
142 int opt, void *data, size_t len);
143static void utun_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
144 int flags);
b0d623f7
A
145
146/* Network Interface functions */
fe8ab488 147static void utun_start(ifnet_t interface);
0a7de745
A
148static errno_t utun_framer(ifnet_t interface, mbuf_t *packet,
149 const struct sockaddr *dest, const char *desk_linkaddr,
150 const char *frame_type, u_int32_t *prepend_len, u_int32_t *postpend_len);
151static errno_t utun_output(ifnet_t interface, mbuf_t data);
152static errno_t utun_demux(ifnet_t interface, mbuf_t data, char *frame_header,
153 protocol_family_t *protocol);
154static errno_t utun_add_proto(ifnet_t interface, protocol_family_t protocol,
155 const struct ifnet_demux_desc *demux_array,
156 u_int32_t demux_count);
157static errno_t utun_del_proto(ifnet_t interface, protocol_family_t protocol);
158static errno_t utun_ioctl(ifnet_t interface, u_long cmd, void *data);
159static void utun_detached(ifnet_t interface);
b0d623f7
A
160
161/* Protocol handlers */
0a7de745
A
162static errno_t utun_attach_proto(ifnet_t interface, protocol_family_t proto);
163static errno_t utun_proto_input(ifnet_t interface, protocol_family_t protocol,
164 mbuf_t m, char *frame_header);
165static errno_t utun_proto_pre_output(ifnet_t interface, protocol_family_t protocol,
166 mbuf_t *packet, const struct sockaddr *dest, void *route,
167 char *frame_type, char *link_layer_dest);
5c9f4661 168static errno_t utun_pkt_input(struct utun_pcb *pcb, mbuf_t m);
39037602 169
5ba3f43e
A
170#if UTUN_NEXUS
171
5c9f4661 172#define UTUN_IF_DEFAULT_SLOT_SIZE 2048
5ba3f43e
A
173#define UTUN_IF_DEFAULT_RING_SIZE 64
174#define UTUN_IF_DEFAULT_TX_FSW_RING_SIZE 64
175#define UTUN_IF_DEFAULT_RX_FSW_RING_SIZE 128
0a7de745 176#define UTUN_IF_DEFAULT_BUF_SEG_SIZE skmem_usr_buf_seg_size
5ba3f43e
A
177#define UTUN_IF_HEADROOM_SIZE 32
178
cb323159 179#define UTUN_IF_MIN_RING_SIZE 8
5ba3f43e
A
180#define UTUN_IF_MAX_RING_SIZE 1024
181
5c9f4661
A
182#define UTUN_IF_MIN_SLOT_SIZE 1024
183#define UTUN_IF_MAX_SLOT_SIZE 4096
184
cb323159
A
185#define UTUN_DEFAULT_MAX_PENDING_INPUT_COUNT 512
186
187static int if_utun_max_pending_input = UTUN_DEFAULT_MAX_PENDING_INPUT_COUNT;
188
5ba3f43e
A
189static int sysctl_if_utun_ring_size SYSCTL_HANDLER_ARGS;
190static int sysctl_if_utun_tx_fsw_ring_size SYSCTL_HANDLER_ARGS;
191static int sysctl_if_utun_rx_fsw_ring_size SYSCTL_HANDLER_ARGS;
192
193static int if_utun_ring_size = UTUN_IF_DEFAULT_RING_SIZE;
194static int if_utun_tx_fsw_ring_size = UTUN_IF_DEFAULT_TX_FSW_RING_SIZE;
195static int if_utun_rx_fsw_ring_size = UTUN_IF_DEFAULT_RX_FSW_RING_SIZE;
196
197SYSCTL_DECL(_net_utun);
198SYSCTL_NODE(_net, OID_AUTO, utun, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "UTun");
199
cb323159 200SYSCTL_INT(_net_utun, OID_AUTO, max_pending_input, CTLFLAG_LOCKED | CTLFLAG_RW, &if_utun_max_pending_input, 0, "");
5ba3f43e 201SYSCTL_PROC(_net_utun, OID_AUTO, ring_size, CTLTYPE_INT | CTLFLAG_LOCKED | CTLFLAG_RW,
0a7de745 202 &if_utun_ring_size, UTUN_IF_DEFAULT_RING_SIZE, &sysctl_if_utun_ring_size, "I", "");
5ba3f43e 203SYSCTL_PROC(_net_utun, OID_AUTO, tx_fsw_ring_size, CTLTYPE_INT | CTLFLAG_LOCKED | CTLFLAG_RW,
0a7de745 204 &if_utun_tx_fsw_ring_size, UTUN_IF_DEFAULT_TX_FSW_RING_SIZE, &sysctl_if_utun_tx_fsw_ring_size, "I", "");
5ba3f43e 205SYSCTL_PROC(_net_utun, OID_AUTO, rx_fsw_ring_size, CTLTYPE_INT | CTLFLAG_LOCKED | CTLFLAG_RW,
0a7de745 206 &if_utun_rx_fsw_ring_size, UTUN_IF_DEFAULT_RX_FSW_RING_SIZE, &sysctl_if_utun_rx_fsw_ring_size, "I", "");
5ba3f43e
A
207
208static errno_t
209utun_register_nexus(void);
210
211static errno_t
212utun_netif_prepare(__unused kern_nexus_t nexus, ifnet_t ifp);
213static errno_t
214utun_nexus_pre_connect(kern_nexus_provider_t nxprov,
215 proc_t p, kern_nexus_t nexus,
216 nexus_port_t nexus_port, kern_channel_t channel, void **ch_ctx);
217static errno_t
218utun_nexus_connected(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
219 kern_channel_t channel);
220static void
221utun_netif_pre_disconnect(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
222 kern_channel_t channel);
223static void
224utun_nexus_pre_disconnect(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745 225 kern_channel_t channel);
5ba3f43e
A
226static void
227utun_nexus_disconnected(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
228 kern_channel_t channel);
229static errno_t
230utun_kpipe_ring_init(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
231 kern_channel_t channel, kern_channel_ring_t ring, boolean_t is_tx_ring,
232 void **ring_ctx);
233static void
234utun_kpipe_ring_fini(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
235 kern_channel_ring_t ring);
236static errno_t
237utun_kpipe_sync_tx(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
238 kern_channel_ring_t ring, uint32_t flags);
239static errno_t
240utun_kpipe_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
241 kern_channel_ring_t ring, uint32_t flags);
242#endif // UTUN_NEXUS
39037602
A
243
244#define UTUN_DEFAULT_MTU 1500
245#define UTUN_HEADER_SIZE(_pcb) (sizeof(u_int32_t) + (((_pcb)->utun_flags & UTUN_FLAGS_ENABLE_PROC_UUID) ? sizeof(uuid_t) : 0))
b0d623f7 246
0a7de745 247static kern_ctl_ref utun_kctlref;
5ba3f43e
A
248static lck_attr_t *utun_lck_attr;
249static lck_grp_attr_t *utun_lck_grp_attr;
250static lck_grp_t *utun_lck_grp;
251static lck_mtx_t utun_lock;
252
253TAILQ_HEAD(utun_list, utun_pcb) utun_head;
254
f427ee49
A
255static ZONE_DECLARE(utun_pcb_zone, "net.if_utun",
256 sizeof(struct utun_pcb), ZC_ZFREE_CLEARMEM);
5ba3f43e
A
257
258#if UTUN_NEXUS
259
260static int
261sysctl_if_utun_ring_size SYSCTL_HANDLER_ARGS
262{
263#pragma unused(arg1, arg2)
264 int value = if_utun_ring_size;
265
266 int error = sysctl_handle_int(oidp, &value, 0, req);
267 if (error || !req->newptr) {
0a7de745 268 return error;
5ba3f43e
A
269 }
270
271 if (value < UTUN_IF_MIN_RING_SIZE ||
0a7de745
A
272 value > UTUN_IF_MAX_RING_SIZE) {
273 return EINVAL;
5ba3f43e
A
274 }
275
276 if_utun_ring_size = value;
277
0a7de745 278 return 0;
5ba3f43e
A
279}
280
281static int
282sysctl_if_utun_tx_fsw_ring_size SYSCTL_HANDLER_ARGS
283{
284#pragma unused(arg1, arg2)
285 int value = if_utun_tx_fsw_ring_size;
286
287 int error = sysctl_handle_int(oidp, &value, 0, req);
288 if (error || !req->newptr) {
0a7de745 289 return error;
5ba3f43e
A
290 }
291
292 if (value < UTUN_IF_MIN_RING_SIZE ||
0a7de745
A
293 value > UTUN_IF_MAX_RING_SIZE) {
294 return EINVAL;
5ba3f43e
A
295 }
296
297 if_utun_tx_fsw_ring_size = value;
298
0a7de745 299 return 0;
5ba3f43e
A
300}
301
302static int
303sysctl_if_utun_rx_fsw_ring_size SYSCTL_HANDLER_ARGS
304{
305#pragma unused(arg1, arg2)
306 int value = if_utun_rx_fsw_ring_size;
307
308 int error = sysctl_handle_int(oidp, &value, 0, req);
309 if (error || !req->newptr) {
0a7de745 310 return error;
5ba3f43e
A
311 }
312
313 if (value < UTUN_IF_MIN_RING_SIZE ||
0a7de745
A
314 value > UTUN_IF_MAX_RING_SIZE) {
315 return EINVAL;
5ba3f43e
A
316 }
317
318 if_utun_rx_fsw_ring_size = value;
319
0a7de745 320 return 0;
5ba3f43e
A
321}
322
323static errno_t
324utun_netif_ring_init(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745
A
325 kern_channel_t channel, kern_channel_ring_t ring, boolean_t is_tx_ring,
326 void **ring_ctx)
5ba3f43e
A
327{
328#pragma unused(nxprov)
329#pragma unused(channel)
330#pragma unused(ring_ctx)
331 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
332 if (!is_tx_ring) {
333 VERIFY(pcb->utun_netif_rxring == NULL);
334 pcb->utun_netif_rxring = ring;
335 } else {
336 VERIFY(pcb->utun_netif_txring == NULL);
337 pcb->utun_netif_txring = ring;
338 }
339 return 0;
340}
341
342static void
343utun_netif_ring_fini(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745 344 kern_channel_ring_t ring)
5ba3f43e
A
345{
346#pragma unused(nxprov)
347 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
348 if (pcb->utun_netif_rxring == ring) {
349 pcb->utun_netif_rxring = NULL;
350 } else if (pcb->utun_netif_txring == ring) {
351 pcb->utun_netif_txring = NULL;
352 }
353}
354
355static errno_t
356utun_netif_sync_tx(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745 357 kern_channel_ring_t tx_ring, uint32_t flags)
5ba3f43e
A
358{
359#pragma unused(nxprov)
360#pragma unused(flags)
361 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
362
363 struct netif_stats *nifs = &NX_NETIF_PRIVATE(nexus)->nif_stats;
364
365 lck_rw_lock_shared(&pcb->utun_pcb_lock);
366
367 struct kern_channel_ring_stat_increment tx_ring_stats;
368 bzero(&tx_ring_stats, sizeof(tx_ring_stats));
369 kern_channel_slot_t tx_pslot = NULL;
370 kern_channel_slot_t tx_slot = kern_channel_get_next_slot(tx_ring, NULL, NULL);
371
cb323159 372 STATS_INC(nifs, NETIF_STATS_TX_SYNC);
5ba3f43e
A
373
374 if (tx_slot == NULL) {
375 // Nothing to write, don't bother signalling
376 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
377 return 0;
378 }
379
380 if (pcb->utun_kpipe_enabled) {
381 kern_channel_ring_t rx_ring = pcb->utun_kpipe_rxring;
382 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
383
384 // Signal the kernel pipe ring to read
385 if (rx_ring != NULL) {
386 kern_channel_notify(rx_ring, 0);
387 }
388 return 0;
389 }
390
391 // If we're here, we're injecting into the utun kernel control socket
392 while (tx_slot != NULL) {
393 size_t length = 0;
394 mbuf_t data = NULL;
395
396 kern_packet_t tx_ph = kern_channel_slot_get_packet(tx_ring, tx_slot);
397
398 if (tx_ph == 0) {
399 // Advance TX ring
400 tx_pslot = tx_slot;
401 tx_slot = kern_channel_get_next_slot(tx_ring, tx_slot, NULL);
402 continue;
403 }
404 (void) kern_channel_slot_detach_packet(tx_ring, tx_slot, tx_ph);
405
406 // Advance TX ring
407 tx_pslot = tx_slot;
408 tx_slot = kern_channel_get_next_slot(tx_ring, tx_slot, NULL);
409
410 kern_buflet_t tx_buf = kern_packet_get_next_buflet(tx_ph, NULL);
411 VERIFY(tx_buf != NULL);
412
413 /* tx_baddr is the absolute buffer address */
f427ee49 414 uint8_t *tx_baddr = kern_buflet_get_data_address(tx_buf);
5ba3f43e
A
415 VERIFY(tx_baddr != 0);
416
417 bpf_tap_packet_out(pcb->utun_ifp, DLT_RAW, tx_ph, NULL, 0);
418
419 uint16_t tx_offset = kern_buflet_get_data_offset(tx_buf);
420 uint32_t tx_length = kern_buflet_get_data_length(tx_buf);
421
422 // The offset must be large enough for the headers
423 VERIFY(tx_offset >= UTUN_HEADER_SIZE(pcb));
424
425 // Find family
426 uint32_t af = 0;
427 uint8_t vhl = *(uint8_t *)(tx_baddr + tx_offset);
428 u_int ip_version = (vhl >> 4);
429 switch (ip_version) {
0a7de745
A
430 case 4: {
431 af = AF_INET;
432 break;
433 }
434 case 6: {
435 af = AF_INET6;
436 break;
437 }
438 default: {
cb323159 439 os_log_error(OS_LOG_DEFAULT, "utun_netif_sync_tx %s: unknown ip version %u vhl %u tx_offset %u len %u header_size %zu\n",
0a7de745
A
440 pcb->utun_ifp->if_xname, ip_version, vhl, tx_offset, tx_length,
441 UTUN_HEADER_SIZE(pcb));
442 break;
443 }
5ba3f43e
A
444 }
445
446 tx_offset -= UTUN_HEADER_SIZE(pcb);
447 tx_length += UTUN_HEADER_SIZE(pcb);
448 tx_baddr += tx_offset;
449
5c9f4661 450 length = MIN(tx_length, pcb->utun_slot_size);
5ba3f43e
A
451
452 // Copy in family
453 memcpy(tx_baddr, &af, sizeof(af));
454 if (pcb->utun_flags & UTUN_FLAGS_ENABLE_PROC_UUID) {
455 kern_packet_get_euuid(tx_ph, (void *)(tx_baddr + sizeof(af)));
456 }
457
458 if (length > 0) {
459 errno_t error = mbuf_gethdr(MBUF_DONTWAIT, MBUF_TYPE_HEADER, &data);
460 if (error == 0) {
461 error = mbuf_copyback(data, 0, length, tx_baddr, MBUF_DONTWAIT);
462 if (error == 0) {
463 error = utun_output(pcb->utun_ifp, data);
464 if (error != 0) {
cb323159 465 os_log_error(OS_LOG_DEFAULT, "utun_netif_sync_tx %s - utun_output error %d\n", pcb->utun_ifp->if_xname, error);
5ba3f43e
A
466 }
467 } else {
cb323159
A
468 os_log_error(OS_LOG_DEFAULT, "utun_netif_sync_tx %s - mbuf_copyback(%zu) error %d\n", pcb->utun_ifp->if_xname, length, error);
469 STATS_INC(nifs, NETIF_STATS_DROP_NOMEM_MBUF);
470 STATS_INC(nifs, NETIF_STATS_DROP);
5ba3f43e
A
471 mbuf_freem(data);
472 data = NULL;
473 }
474 } else {
cb323159
A
475 os_log_error(OS_LOG_DEFAULT, "utun_netif_sync_tx %s - mbuf_gethdr error %d\n", pcb->utun_ifp->if_xname, error);
476 STATS_INC(nifs, NETIF_STATS_DROP_NOMEM_MBUF);
477 STATS_INC(nifs, NETIF_STATS_DROP);
5ba3f43e
A
478 }
479 } else {
cb323159
A
480 os_log_error(OS_LOG_DEFAULT, "utun_netif_sync_tx %s - 0 length packet\n", pcb->utun_ifp->if_xname);
481 STATS_INC(nifs, NETIF_STATS_DROP_NOMEM_MBUF);
482 STATS_INC(nifs, NETIF_STATS_DROP);
5ba3f43e
A
483 }
484
485 kern_pbufpool_free(tx_ring->ckr_pp, tx_ph);
486
487 if (data == NULL) {
488 continue;
489 }
490
cb323159
A
491 STATS_INC(nifs, NETIF_STATS_TX_PACKETS);
492 STATS_INC(nifs, NETIF_STATS_TX_COPY_MBUF);
5ba3f43e
A
493
494 tx_ring_stats.kcrsi_slots_transferred++;
495 tx_ring_stats.kcrsi_bytes_transferred += length;
496 }
497
498 if (tx_pslot) {
499 kern_channel_advance_slot(tx_ring, tx_pslot);
500 kern_channel_increment_ring_net_stats(tx_ring, pcb->utun_ifp, &tx_ring_stats);
501 (void)kern_channel_reclaim(tx_ring);
502 }
503
504 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
505
506 return 0;
507}
508
509static errno_t
510utun_netif_tx_doorbell(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745 511 kern_channel_ring_t ring, __unused uint32_t flags)
5ba3f43e
A
512{
513#pragma unused(nxprov)
514 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
5ba3f43e
A
515 boolean_t more = false;
516 errno_t rc = 0;
5ba3f43e 517
5c9f4661
A
518 /*
519 * Refill and sync the ring; we may be racing against another thread doing
520 * an RX sync that also wants to do kr_enter(), and so use the blocking
521 * variant here.
522 */
523 rc = kern_channel_tx_refill_canblock(ring, UINT32_MAX, UINT32_MAX, true, &more);
524 if (rc != 0 && rc != EAGAIN && rc != EBUSY) {
cb323159 525 os_log_error(OS_LOG_DEFAULT, "%s, tx refill failed %d\n", __func__, rc);
5c9f4661
A
526 }
527
528 (void) kr_enter(ring, TRUE);
529 lck_rw_lock_shared(&pcb->utun_pcb_lock);
530
531 if (pcb->utun_kpipe_enabled) {
5ba3f43e
A
532 uint32_t tx_available = kern_channel_available_slot_count(ring);
533 if (pcb->utun_netif_txring_size > 0 &&
0a7de745 534 tx_available >= pcb->utun_netif_txring_size - 1) {
5ba3f43e
A
535 // No room left in tx ring, disable output for now
536 errno_t error = ifnet_disable_output(pcb->utun_ifp);
537 if (error != 0) {
cb323159 538 os_log_error(OS_LOG_DEFAULT, "utun_netif_tx_doorbell: ifnet_disable_output returned error %d\n", error);
5ba3f43e
A
539 }
540 }
541 }
b0d623f7 542
5c9f4661 543 if (pcb->utun_kpipe_enabled) {
5ba3f43e
A
544 kern_channel_ring_t rx_ring = pcb->utun_kpipe_rxring;
545
546 // Unlock while calling notify
547 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
548 // Signal the kernel pipe ring to read
549 if (rx_ring != NULL) {
550 kern_channel_notify(rx_ring, 0);
551 }
552 } else {
553 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
554 }
555
5c9f4661
A
556 kr_exit(ring);
557
0a7de745 558 return 0;
5ba3f43e
A
559}
560
561static errno_t
562utun_netif_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745 563 kern_channel_ring_t rx_ring, uint32_t flags)
5ba3f43e
A
564{
565#pragma unused(nxprov)
566#pragma unused(flags)
567 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
568 struct kern_channel_ring_stat_increment rx_ring_stats;
569
570 struct netif_stats *nifs = &NX_NETIF_PRIVATE(nexus)->nif_stats;
571
572 lck_rw_lock_shared(&pcb->utun_pcb_lock);
573
574 // Reclaim user-released slots
575 (void) kern_channel_reclaim(rx_ring);
576
cb323159 577 STATS_INC(nifs, NETIF_STATS_RX_SYNC);
5ba3f43e
A
578
579 uint32_t avail = kern_channel_available_slot_count(rx_ring);
580 if (avail == 0) {
581 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
582 return 0;
583 }
584
585 struct kern_pbufpool *rx_pp = rx_ring->ckr_pp;
586 VERIFY(rx_pp != NULL);
587 bzero(&rx_ring_stats, sizeof(rx_ring_stats));
588 kern_channel_slot_t rx_pslot = NULL;
589 kern_channel_slot_t rx_slot = kern_channel_get_next_slot(rx_ring, NULL, NULL);
590
591 while (rx_slot != NULL) {
592 // Check for a waiting packet
593 lck_mtx_lock(&pcb->utun_input_chain_lock);
594 mbuf_t data = pcb->utun_input_chain;
595 if (data == NULL) {
596 lck_mtx_unlock(&pcb->utun_input_chain_lock);
597 break;
598 }
599
600 // Allocate rx packet
601 kern_packet_t rx_ph = 0;
602 errno_t error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph);
a39ff7e2 603 if (__improbable(error != 0)) {
cb323159
A
604 STATS_INC(nifs, NETIF_STATS_DROP_NOMEM_PKT);
605 STATS_INC(nifs, NETIF_STATS_DROP);
5ba3f43e
A
606 lck_mtx_unlock(&pcb->utun_input_chain_lock);
607 break;
608 }
609
610 // Advance waiting packets
cb323159
A
611 if (pcb->utun_input_chain_count > 0) {
612 pcb->utun_input_chain_count--;
613 }
5ba3f43e
A
614 pcb->utun_input_chain = data->m_nextpkt;
615 data->m_nextpkt = NULL;
616 if (pcb->utun_input_chain == NULL) {
617 pcb->utun_input_chain_last = NULL;
618 }
619 lck_mtx_unlock(&pcb->utun_input_chain_lock);
620
621 size_t header_offset = UTUN_HEADER_SIZE(pcb);
622 size_t length = mbuf_pkthdr_len(data);
623
624 if (length < header_offset) {
625 // mbuf is too small
626 mbuf_freem(data);
627 kern_pbufpool_free(rx_pp, rx_ph);
cb323159
A
628 STATS_INC(nifs, NETIF_STATS_DROP_BADLEN);
629 STATS_INC(nifs, NETIF_STATS_DROP);
630 os_log_error(OS_LOG_DEFAULT, "utun_netif_sync_rx %s: legacy packet length too short for header %zu < %zu\n",
0a7de745 631 pcb->utun_ifp->if_xname, length, header_offset);
5ba3f43e
A
632 continue;
633 }
634
635 length -= header_offset;
636 if (length > rx_pp->pp_buflet_size) {
637 // Flush data
638 mbuf_freem(data);
639 kern_pbufpool_free(rx_pp, rx_ph);
cb323159
A
640 STATS_INC(nifs, NETIF_STATS_DROP_BADLEN);
641 STATS_INC(nifs, NETIF_STATS_DROP);
642 os_log_error(OS_LOG_DEFAULT, "utun_netif_sync_rx %s: legacy packet length %zu > %u\n",
0a7de745 643 pcb->utun_ifp->if_xname, length, rx_pp->pp_buflet_size);
5ba3f43e
A
644 continue;
645 }
646
647 mbuf_pkthdr_setrcvif(data, pcb->utun_ifp);
648
649 // Fillout rx packet
650 kern_buflet_t rx_buf = kern_packet_get_next_buflet(rx_ph, NULL);
651 VERIFY(rx_buf != NULL);
f427ee49 652 void *rx_baddr = kern_buflet_get_data_address(rx_buf);
5ba3f43e
A
653 VERIFY(rx_baddr != NULL);
654
655 // Copy-in data from mbuf to buflet
656 mbuf_copydata(data, header_offset, length, (void *)rx_baddr);
0a7de745 657 kern_packet_clear_flow_uuid(rx_ph); // Zero flow id
5ba3f43e
A
658
659 // Finalize and attach the packet
660 error = kern_buflet_set_data_offset(rx_buf, 0);
661 VERIFY(error == 0);
662 error = kern_buflet_set_data_length(rx_buf, length);
663 VERIFY(error == 0);
cb323159 664 error = kern_packet_set_headroom(rx_ph, 0);
5ba3f43e
A
665 VERIFY(error == 0);
666 error = kern_packet_finalize(rx_ph);
667 VERIFY(error == 0);
668 error = kern_channel_slot_attach_packet(rx_ring, rx_slot, rx_ph);
669 VERIFY(error == 0);
670
cb323159
A
671 STATS_INC(nifs, NETIF_STATS_RX_PACKETS);
672 STATS_INC(nifs, NETIF_STATS_RX_COPY_MBUF);
5ba3f43e
A
673 bpf_tap_packet_in(pcb->utun_ifp, DLT_RAW, rx_ph, NULL, 0);
674
675 rx_ring_stats.kcrsi_slots_transferred++;
676 rx_ring_stats.kcrsi_bytes_transferred += length;
677
678 mbuf_freem(data);
679
680 // Advance ring
681 rx_pslot = rx_slot;
682 rx_slot = kern_channel_get_next_slot(rx_ring, rx_slot, NULL);
683 }
684
685 struct kern_channel_ring_stat_increment tx_ring_stats;
686 bzero(&tx_ring_stats, sizeof(tx_ring_stats));
687 kern_channel_ring_t tx_ring = pcb->utun_kpipe_txring;
688 kern_channel_slot_t tx_pslot = NULL;
689 kern_channel_slot_t tx_slot = NULL;
690 if (tx_ring == NULL) {
691 // Net-If TX ring not set up yet, nothing to read
692 goto done;
693 }
694
695 // Unlock utun before entering ring
696 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
697
698 (void)kr_enter(tx_ring, TRUE);
699
700 // Lock again after entering and validate
701 lck_rw_lock_shared(&pcb->utun_pcb_lock);
702 if (tx_ring != pcb->utun_kpipe_txring) {
703 goto done;
704 }
705
706 tx_slot = kern_channel_get_next_slot(tx_ring, NULL, NULL);
707 if (tx_slot == NULL) {
708 // Nothing to read, don't bother signalling
709 goto done;
710 }
711
712 while (rx_slot != NULL && tx_slot != NULL) {
713 // Allocate rx packet
714 kern_packet_t rx_ph = 0;
715 kern_packet_t tx_ph = kern_channel_slot_get_packet(tx_ring, tx_slot);
716
717 // Advance TX ring
718 tx_pslot = tx_slot;
719 tx_slot = kern_channel_get_next_slot(tx_ring, tx_slot, NULL);
720
721 /* Skip slot if packet is zero-length or marked as dropped (QUMF_DROPPED) */
722 if (tx_ph == 0) {
723 continue;
724 }
725
a39ff7e2
A
726 /* XXX We could try this alloc before advancing the slot to avoid
727 * dropping the packet on failure to allocate.
728 */
5ba3f43e 729 errno_t error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph);
a39ff7e2 730 if (__improbable(error != 0)) {
cb323159
A
731 STATS_INC(nifs, NETIF_STATS_DROP_NOMEM_PKT);
732 STATS_INC(nifs, NETIF_STATS_DROP);
5ba3f43e
A
733 break;
734 }
735
736 kern_buflet_t tx_buf = kern_packet_get_next_buflet(tx_ph, NULL);
737 VERIFY(tx_buf != NULL);
f427ee49 738 uint8_t *tx_baddr = kern_buflet_get_data_address(tx_buf);
5ba3f43e
A
739 VERIFY(tx_baddr != 0);
740 tx_baddr += kern_buflet_get_data_offset(tx_buf);
741
742 // Check packet length
743 size_t header_offset = UTUN_HEADER_SIZE(pcb);
744 uint32_t tx_length = kern_packet_get_data_length(tx_ph);
745 if (tx_length < header_offset) {
746 // Packet is too small
747 kern_pbufpool_free(rx_pp, rx_ph);
cb323159
A
748 STATS_INC(nifs, NETIF_STATS_DROP_BADLEN);
749 STATS_INC(nifs, NETIF_STATS_DROP);
750 os_log_error(OS_LOG_DEFAULT, "utun_netif_sync_rx %s: packet length too short for header %u < %zu\n",
0a7de745 751 pcb->utun_ifp->if_xname, tx_length, header_offset);
5ba3f43e
A
752 continue;
753 }
754
755 size_t length = MIN(tx_length - header_offset,
0a7de745 756 pcb->utun_slot_size);
5ba3f43e
A
757
758 tx_ring_stats.kcrsi_slots_transferred++;
759 tx_ring_stats.kcrsi_bytes_transferred += length;
760
761 // Fillout rx packet
762 kern_buflet_t rx_buf = kern_packet_get_next_buflet(rx_ph, NULL);
763 VERIFY(rx_buf != NULL);
f427ee49 764 void *rx_baddr = kern_buflet_get_data_address(rx_buf);
5ba3f43e
A
765 VERIFY(rx_baddr != NULL);
766
767 // Copy-in data from tx to rx
768 memcpy((void *)rx_baddr, (void *)(tx_baddr + header_offset), length);
0a7de745 769 kern_packet_clear_flow_uuid(rx_ph); // Zero flow id
5ba3f43e
A
770
771 // Finalize and attach the packet
772 error = kern_buflet_set_data_offset(rx_buf, 0);
773 VERIFY(error == 0);
774 error = kern_buflet_set_data_length(rx_buf, length);
775 VERIFY(error == 0);
cb323159 776 error = kern_packet_set_headroom(rx_ph, 0);
5ba3f43e
A
777 VERIFY(error == 0);
778 error = kern_packet_finalize(rx_ph);
779 VERIFY(error == 0);
780 error = kern_channel_slot_attach_packet(rx_ring, rx_slot, rx_ph);
781 VERIFY(error == 0);
782
cb323159
A
783 STATS_INC(nifs, NETIF_STATS_RX_PACKETS);
784 STATS_INC(nifs, NETIF_STATS_RX_COPY_DIRECT);
5ba3f43e
A
785 bpf_tap_packet_in(pcb->utun_ifp, DLT_RAW, rx_ph, NULL, 0);
786
787 rx_ring_stats.kcrsi_slots_transferred++;
788 rx_ring_stats.kcrsi_bytes_transferred += length;
789
790 rx_pslot = rx_slot;
791 rx_slot = kern_channel_get_next_slot(rx_ring, rx_slot, NULL);
792 }
793
794done:
795 if (rx_pslot) {
796 kern_channel_advance_slot(rx_ring, rx_pslot);
797 kern_channel_increment_ring_net_stats(rx_ring, pcb->utun_ifp, &rx_ring_stats);
798 }
799
800 if (tx_pslot) {
801 kern_channel_advance_slot(tx_ring, tx_pslot);
802 kern_channel_increment_ring_net_stats(tx_ring, pcb->utun_ifp, &tx_ring_stats);
803 (void)kern_channel_reclaim(tx_ring);
804 }
805
806 // Unlock first, then exit ring
807 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
808 if (tx_ring != NULL) {
809 if (tx_pslot != NULL) {
810 kern_channel_notify(tx_ring, 0);
811 }
812 kr_exit(tx_ring);
813 }
814
815 return 0;
816}
817
818static errno_t
819utun_nexus_ifattach(struct utun_pcb *pcb,
0a7de745
A
820 struct ifnet_init_eparams *init_params,
821 struct ifnet **ifp)
5ba3f43e
A
822{
823 errno_t err;
824 nexus_controller_t controller = kern_nexus_shared_controller();
825 struct kern_nexus_net_init net_init;
a39ff7e2 826 struct kern_pbufpool_init pp_init;
5ba3f43e
A
827
828 nexus_name_t provider_name;
829 snprintf((char *)provider_name, sizeof(provider_name),
0a7de745 830 "com.apple.netif.%s", pcb->utun_if_xname);
5ba3f43e
A
831
832 struct kern_nexus_provider_init prov_init = {
833 .nxpi_version = KERN_NEXUS_DOMAIN_PROVIDER_CURRENT_VERSION,
834 .nxpi_flags = NXPIF_VIRTUAL_DEVICE,
835 .nxpi_pre_connect = utun_nexus_pre_connect,
836 .nxpi_connected = utun_nexus_connected,
837 .nxpi_pre_disconnect = utun_netif_pre_disconnect,
838 .nxpi_disconnected = utun_nexus_disconnected,
839 .nxpi_ring_init = utun_netif_ring_init,
840 .nxpi_ring_fini = utun_netif_ring_fini,
841 .nxpi_slot_init = NULL,
842 .nxpi_slot_fini = NULL,
843 .nxpi_sync_tx = utun_netif_sync_tx,
844 .nxpi_sync_rx = utun_netif_sync_rx,
845 .nxpi_tx_doorbell = utun_netif_tx_doorbell,
846 };
847
848 nexus_attr_t nxa = NULL;
849 err = kern_nexus_attr_create(&nxa);
850 if (err != 0) {
cb323159 851 os_log_error(OS_LOG_DEFAULT, "%s: kern_nexus_attr_create failed: %d\n",
0a7de745 852 __func__, err);
5ba3f43e
A
853 goto failed;
854 }
855
5c9f4661 856 uint64_t slot_buffer_size = pcb->utun_slot_size;
5ba3f43e
A
857 err = kern_nexus_attr_set(nxa, NEXUS_ATTR_SLOT_BUF_SIZE, slot_buffer_size);
858 VERIFY(err == 0);
859
860 // Reset ring size for netif nexus to limit memory usage
5c9f4661 861 uint64_t ring_size = pcb->utun_netif_ring_size;
5ba3f43e
A
862 err = kern_nexus_attr_set(nxa, NEXUS_ATTR_TX_SLOTS, ring_size);
863 VERIFY(err == 0);
864 err = kern_nexus_attr_set(nxa, NEXUS_ATTR_RX_SLOTS, ring_size);
865 VERIFY(err == 0);
866
867 pcb->utun_netif_txring_size = ring_size;
868
0a7de745 869 bzero(&pp_init, sizeof(pp_init));
a39ff7e2 870 pp_init.kbi_version = KERN_PBUFPOOL_CURRENT_VERSION;
cb323159 871 pp_init.kbi_flags |= KBIF_VIRTUAL_DEVICE;
a39ff7e2
A
872 pp_init.kbi_packets = pcb->utun_netif_ring_size * 2;
873 pp_init.kbi_bufsize = pcb->utun_slot_size;
874 pp_init.kbi_buf_seg_size = UTUN_IF_DEFAULT_BUF_SEG_SIZE;
875 pp_init.kbi_max_frags = 1;
0a7de745 876 (void) snprintf((char *)pp_init.kbi_name, sizeof(pp_init.kbi_name),
a39ff7e2 877 "%s", provider_name);
cb323159
A
878 pp_init.kbi_ctx = NULL;
879 pp_init.kbi_ctx_retain = NULL;
880 pp_init.kbi_ctx_release = NULL;
a39ff7e2 881
cb323159 882 err = kern_pbufpool_create(&pp_init, &pcb->utun_netif_pp, NULL);
a39ff7e2 883 if (err != 0) {
cb323159 884 os_log_error(OS_LOG_DEFAULT, "%s pbufbool create failed, error %d\n", __func__, err);
a39ff7e2
A
885 goto failed;
886 }
887
5ba3f43e 888 err = kern_nexus_controller_register_provider(controller,
0a7de745
A
889 utun_nx_dom_prov,
890 provider_name,
891 &prov_init,
892 sizeof(prov_init),
893 nxa,
894 &pcb->utun_nx.if_provider);
5ba3f43e 895 if (err != 0) {
cb323159 896 os_log_error(OS_LOG_DEFAULT, "%s register provider failed, error %d\n",
0a7de745 897 __func__, err);
5ba3f43e
A
898 goto failed;
899 }
900
901 bzero(&net_init, sizeof(net_init));
902 net_init.nxneti_version = KERN_NEXUS_NET_CURRENT_VERSION;
903 net_init.nxneti_flags = 0;
904 net_init.nxneti_eparams = init_params;
905 net_init.nxneti_lladdr = NULL;
906 net_init.nxneti_prepare = utun_netif_prepare;
f427ee49 907 net_init.nxneti_rx_pbufpool = pcb->utun_netif_pp;
a39ff7e2 908 net_init.nxneti_tx_pbufpool = pcb->utun_netif_pp;
5ba3f43e 909 err = kern_nexus_controller_alloc_net_provider_instance(controller,
0a7de745
A
910 pcb->utun_nx.if_provider,
911 pcb,
912 &pcb->utun_nx.if_instance,
913 &net_init,
914 ifp);
5ba3f43e 915 if (err != 0) {
cb323159 916 os_log_error(OS_LOG_DEFAULT, "%s alloc_net_provider_instance failed, %d\n",
0a7de745 917 __func__, err);
5ba3f43e 918 kern_nexus_controller_deregister_provider(controller,
0a7de745 919 pcb->utun_nx.if_provider);
5ba3f43e
A
920 uuid_clear(pcb->utun_nx.if_provider);
921 goto failed;
922 }
923
924failed:
925 if (nxa) {
926 kern_nexus_attr_destroy(nxa);
927 }
a39ff7e2
A
928 if (err && pcb->utun_netif_pp != NULL) {
929 kern_pbufpool_destroy(pcb->utun_netif_pp);
930 pcb->utun_netif_pp = NULL;
931 }
0a7de745 932 return err;
5ba3f43e
A
933}
934
935static void
936utun_detach_provider_and_instance(uuid_t provider, uuid_t instance)
937{
938 nexus_controller_t controller = kern_nexus_shared_controller();
0a7de745 939 errno_t err;
5ba3f43e
A
940
941 if (!uuid_is_null(instance)) {
942 err = kern_nexus_controller_free_provider_instance(controller,
0a7de745 943 instance);
5ba3f43e 944 if (err != 0) {
cb323159 945 os_log_error(OS_LOG_DEFAULT, "%s free_provider_instance failed %d\n",
0a7de745 946 __func__, err);
5ba3f43e
A
947 }
948 uuid_clear(instance);
949 }
950 if (!uuid_is_null(provider)) {
951 err = kern_nexus_controller_deregister_provider(controller,
0a7de745 952 provider);
5ba3f43e 953 if (err != 0) {
cb323159 954 os_log_error(OS_LOG_DEFAULT, "%s deregister_provider %d\n", __func__, err);
5ba3f43e
A
955 }
956 uuid_clear(provider);
957 }
958 return;
959}
960
961static void
a39ff7e2 962utun_nexus_detach(struct utun_pcb *pcb)
5ba3f43e 963{
a39ff7e2 964 utun_nx_t nx = &pcb->utun_nx;
5ba3f43e 965 nexus_controller_t controller = kern_nexus_shared_controller();
0a7de745 966 errno_t err;
5ba3f43e 967
cb323159 968 if (!uuid_is_null(nx->fsw_host)) {
5ba3f43e 969 err = kern_nexus_ifdetach(controller,
cb323159
A
970 nx->fsw_instance,
971 nx->fsw_host);
5ba3f43e 972 if (err != 0) {
cb323159 973 os_log_error(OS_LOG_DEFAULT, "%s: kern_nexus_ifdetach ms host failed %d\n",
0a7de745 974 __func__, err);
5ba3f43e
A
975 }
976 }
977
cb323159 978 if (!uuid_is_null(nx->fsw_device)) {
5ba3f43e 979 err = kern_nexus_ifdetach(controller,
cb323159
A
980 nx->fsw_instance,
981 nx->fsw_device);
5ba3f43e 982 if (err != 0) {
cb323159 983 os_log_error(OS_LOG_DEFAULT, "%s: kern_nexus_ifdetach ms device failed %d\n",
0a7de745 984 __func__, err);
5ba3f43e
A
985 }
986 }
987
988 utun_detach_provider_and_instance(nx->if_provider,
0a7de745 989 nx->if_instance);
cb323159
A
990 utun_detach_provider_and_instance(nx->fsw_provider,
991 nx->fsw_instance);
5ba3f43e 992
a39ff7e2
A
993 if (pcb->utun_netif_pp != NULL) {
994 kern_pbufpool_destroy(pcb->utun_netif_pp);
995 pcb->utun_netif_pp = NULL;
a39ff7e2 996 }
5ba3f43e
A
997 memset(nx, 0, sizeof(*nx));
998}
999
1000static errno_t
5c9f4661 1001utun_create_fs_provider_and_instance(struct utun_pcb *pcb,
cb323159 1002 const char *type_name,
0a7de745
A
1003 const char *ifname,
1004 uuid_t *provider, uuid_t *instance)
5ba3f43e
A
1005{
1006 nexus_attr_t attr = NULL;
1007 nexus_controller_t controller = kern_nexus_shared_controller();
1008 uuid_t dom_prov;
1009 errno_t err;
1010 struct kern_nexus_init init;
0a7de745 1011 nexus_name_t provider_name;
5ba3f43e 1012
cb323159 1013 err = kern_nexus_get_default_domain_provider(NEXUS_TYPE_FLOW_SWITCH,
0a7de745 1014 &dom_prov);
5ba3f43e 1015 if (err != 0) {
cb323159 1016 os_log_error(OS_LOG_DEFAULT, "%s can't get %s provider, error %d\n",
0a7de745 1017 __func__, type_name, err);
5ba3f43e
A
1018 goto failed;
1019 }
1020
1021 err = kern_nexus_attr_create(&attr);
1022 if (err != 0) {
cb323159 1023 os_log_error(OS_LOG_DEFAULT, "%s: kern_nexus_attr_create failed: %d\n",
0a7de745 1024 __func__, err);
5ba3f43e
A
1025 goto failed;
1026 }
1027
5c9f4661 1028 uint64_t slot_buffer_size = pcb->utun_slot_size;
5ba3f43e
A
1029 err = kern_nexus_attr_set(attr, NEXUS_ATTR_SLOT_BUF_SIZE, slot_buffer_size);
1030 VERIFY(err == 0);
1031
1032 // Reset ring size for flowswitch nexus to limit memory usage. Larger RX than netif.
5c9f4661 1033 uint64_t tx_ring_size = pcb->utun_tx_fsw_ring_size;
5ba3f43e
A
1034 err = kern_nexus_attr_set(attr, NEXUS_ATTR_TX_SLOTS, tx_ring_size);
1035 VERIFY(err == 0);
5c9f4661 1036 uint64_t rx_ring_size = pcb->utun_rx_fsw_ring_size;
5ba3f43e
A
1037 err = kern_nexus_attr_set(attr, NEXUS_ATTR_RX_SLOTS, rx_ring_size);
1038 VERIFY(err == 0);
f427ee49
A
1039 /*
1040 * Configure flowswitch to use super-packet (multi-buflet).
1041 * This allows flowswitch to perform intra-stack packet aggregation.
1042 */
1043 err = kern_nexus_attr_set(attr, NEXUS_ATTR_MAX_FRAGS,
1044 sk_fsw_rx_agg_tcp ? NX_PBUF_FRAGS_MAX : 1);
1045 VERIFY(err == 0);
5ba3f43e
A
1046
1047 snprintf((char *)provider_name, sizeof(provider_name),
0a7de745 1048 "com.apple.%s.%s", type_name, ifname);
5ba3f43e 1049 err = kern_nexus_controller_register_provider(controller,
0a7de745
A
1050 dom_prov,
1051 provider_name,
1052 NULL,
1053 0,
1054 attr,
1055 provider);
5ba3f43e
A
1056 kern_nexus_attr_destroy(attr);
1057 attr = NULL;
1058 if (err != 0) {
cb323159 1059 os_log_error(OS_LOG_DEFAULT, "%s register %s provider failed, error %d\n",
0a7de745 1060 __func__, type_name, err);
5ba3f43e
A
1061 goto failed;
1062 }
0a7de745 1063 bzero(&init, sizeof(init));
5ba3f43e
A
1064 init.nxi_version = KERN_NEXUS_CURRENT_VERSION;
1065 err = kern_nexus_controller_alloc_provider_instance(controller,
0a7de745
A
1066 *provider,
1067 NULL,
1068 instance, &init);
5ba3f43e 1069 if (err != 0) {
cb323159 1070 os_log_error(OS_LOG_DEFAULT, "%s alloc_provider_instance %s failed, %d\n",
0a7de745 1071 __func__, type_name, err);
5ba3f43e 1072 kern_nexus_controller_deregister_provider(controller,
0a7de745 1073 *provider);
5ba3f43e
A
1074 uuid_clear(*provider);
1075 }
1076failed:
0a7de745 1077 return err;
5ba3f43e
A
1078}
1079
1080static errno_t
cb323159 1081utun_flowswitch_attach(struct utun_pcb *pcb)
5ba3f43e
A
1082{
1083 nexus_controller_t controller = kern_nexus_shared_controller();
1084 errno_t err = 0;
1085 utun_nx_t nx = &pcb->utun_nx;
1086
cb323159 1087 // Allocate flowswitch
5c9f4661 1088 err = utun_create_fs_provider_and_instance(pcb,
cb323159 1089 "flowswitch",
0a7de745 1090 pcb->utun_ifp->if_xname,
cb323159
A
1091 &nx->fsw_provider,
1092 &nx->fsw_instance);
5ba3f43e 1093 if (err != 0) {
cb323159 1094 os_log_error(OS_LOG_DEFAULT, "%s: failed to create bridge provider and instance\n",
0a7de745 1095 __func__);
5ba3f43e
A
1096 goto failed;
1097 }
1098
cb323159
A
1099 // Attach flowswitch to device port
1100 err = kern_nexus_ifattach(controller, nx->fsw_instance,
0a7de745 1101 NULL, nx->if_instance,
cb323159 1102 FALSE, &nx->fsw_device);
5ba3f43e 1103 if (err != 0) {
cb323159 1104 os_log_error(OS_LOG_DEFAULT, "%s kern_nexus_ifattach ms device %d\n", __func__, err);
5ba3f43e
A
1105 goto failed;
1106 }
1107
cb323159
A
1108 // Attach flowswitch to host port
1109 err = kern_nexus_ifattach(controller, nx->fsw_instance,
0a7de745 1110 NULL, nx->if_instance,
cb323159 1111 TRUE, &nx->fsw_host);
5ba3f43e 1112 if (err != 0) {
cb323159 1113 os_log_error(OS_LOG_DEFAULT, "%s kern_nexus_ifattach ms host %d\n", __func__, err);
5ba3f43e
A
1114 goto failed;
1115 }
1116
1117 // Extract the agent UUID and save for later
cb323159
A
1118 struct kern_nexus *flowswitch_nx = nx_find(nx->fsw_instance, false);
1119 if (flowswitch_nx != NULL) {
1120 struct nx_flowswitch *flowswitch = NX_FSW_PRIVATE(flowswitch_nx);
5ba3f43e
A
1121 if (flowswitch != NULL) {
1122 FSW_RLOCK(flowswitch);
cb323159 1123 uuid_copy(nx->fsw_agent, flowswitch->fsw_agent_uuid);
5ba3f43e
A
1124 FSW_UNLOCK(flowswitch);
1125 } else {
cb323159 1126 os_log_error(OS_LOG_DEFAULT, "utun_flowswitch_attach - flowswitch is NULL\n");
5ba3f43e 1127 }
cb323159 1128 nx_release(flowswitch_nx);
5ba3f43e 1129 } else {
cb323159 1130 os_log_error(OS_LOG_DEFAULT, "utun_flowswitch_attach - unable to find flowswitch nexus\n");
5ba3f43e
A
1131 }
1132
0a7de745 1133 return 0;
5ba3f43e
A
1134
1135failed:
a39ff7e2 1136 utun_nexus_detach(pcb);
5ba3f43e
A
1137
1138 errno_t detach_error = 0;
1139 if ((detach_error = ifnet_detach(pcb->utun_ifp)) != 0) {
cb323159 1140 panic("utun_flowswitch_attach - ifnet_detach failed: %d\n", detach_error);
5ba3f43e
A
1141 /* NOT REACHED */
1142 }
0a7de745
A
1143
1144 return err;
5ba3f43e
A
1145}
1146
1147static errno_t
cb323159 1148utun_register_kernel_pipe_nexus(struct utun_pcb *pcb)
5ba3f43e
A
1149{
1150 nexus_attr_t nxa = NULL;
1151 errno_t result;
1152
1153 lck_mtx_lock(&utun_lock);
1154 if (utun_ncd_refcount++) {
1155 lck_mtx_unlock(&utun_lock);
1156 return 0;
1157 }
1158
1159 result = kern_nexus_controller_create(&utun_ncd);
1160 if (result) {
cb323159 1161 os_log_error(OS_LOG_DEFAULT, "%s: kern_nexus_controller_create failed: %d\n",
0a7de745 1162 __FUNCTION__, result);
5ba3f43e
A
1163 goto done;
1164 }
1165
1166 uuid_t dom_prov;
cb323159 1167 result = kern_nexus_get_default_domain_provider(
5ba3f43e
A
1168 NEXUS_TYPE_KERNEL_PIPE, &dom_prov);
1169 if (result) {
cb323159 1170 os_log_error(OS_LOG_DEFAULT, "%s: kern_nexus_get_default_domain_provider failed: %d\n",
0a7de745 1171 __FUNCTION__, result);
5ba3f43e
A
1172 goto done;
1173 }
1174
1175 struct kern_nexus_provider_init prov_init = {
1176 .nxpi_version = KERN_NEXUS_DOMAIN_PROVIDER_CURRENT_VERSION,
1177 .nxpi_flags = NXPIF_VIRTUAL_DEVICE,
1178 .nxpi_pre_connect = utun_nexus_pre_connect,
1179 .nxpi_connected = utun_nexus_connected,
1180 .nxpi_pre_disconnect = utun_nexus_pre_disconnect,
1181 .nxpi_disconnected = utun_nexus_disconnected,
1182 .nxpi_ring_init = utun_kpipe_ring_init,
1183 .nxpi_ring_fini = utun_kpipe_ring_fini,
1184 .nxpi_slot_init = NULL,
1185 .nxpi_slot_fini = NULL,
1186 .nxpi_sync_tx = utun_kpipe_sync_tx,
1187 .nxpi_sync_rx = utun_kpipe_sync_rx,
1188 .nxpi_tx_doorbell = NULL,
1189 };
1190
1191 result = kern_nexus_attr_create(&nxa);
1192 if (result) {
cb323159 1193 os_log_error(OS_LOG_DEFAULT, "%s: kern_nexus_attr_create failed: %d\n",
0a7de745 1194 __FUNCTION__, result);
5ba3f43e
A
1195 goto done;
1196 }
1197
1198 uint64_t slot_buffer_size = UTUN_IF_DEFAULT_SLOT_SIZE;
1199 result = kern_nexus_attr_set(nxa, NEXUS_ATTR_SLOT_BUF_SIZE, slot_buffer_size);
1200 VERIFY(result == 0);
1201
1202 // Reset ring size for kernel pipe nexus to limit memory usage
cb323159
A
1203 uint64_t ring_size =
1204 pcb->utun_kpipe_tx_ring_size != 0 ? pcb->utun_kpipe_tx_ring_size :
1205 if_utun_ring_size;
5ba3f43e
A
1206 result = kern_nexus_attr_set(nxa, NEXUS_ATTR_TX_SLOTS, ring_size);
1207 VERIFY(result == 0);
cb323159
A
1208
1209 ring_size =
1210 pcb->utun_kpipe_rx_ring_size != 0 ? pcb->utun_kpipe_rx_ring_size :
1211 if_utun_ring_size;
5ba3f43e
A
1212 result = kern_nexus_attr_set(nxa, NEXUS_ATTR_RX_SLOTS, ring_size);
1213 VERIFY(result == 0);
1214
1215 result = kern_nexus_controller_register_provider(utun_ncd,
0a7de745
A
1216 dom_prov,
1217 (const uint8_t *)"com.apple.nexus.utun.kpipe",
1218 &prov_init,
1219 sizeof(prov_init),
1220 nxa,
1221 &utun_kpipe_uuid);
5ba3f43e 1222 if (result) {
cb323159 1223 os_log_error(OS_LOG_DEFAULT, "%s: kern_nexus_controller_register_provider failed: %d\n",
0a7de745 1224 __FUNCTION__, result);
5ba3f43e
A
1225 goto done;
1226 }
1227
1228done:
1229 if (nxa) {
1230 kern_nexus_attr_destroy(nxa);
1231 }
1232
1233 if (result) {
1234 if (utun_ncd) {
1235 kern_nexus_controller_destroy(utun_ncd);
1236 utun_ncd = NULL;
1237 }
1238 utun_ncd_refcount = 0;
1239 }
1240
1241 lck_mtx_unlock(&utun_lock);
1242
1243 return result;
1244}
1245
1246static void
1247utun_unregister_kernel_pipe_nexus(void)
1248{
1249 lck_mtx_lock(&utun_lock);
1250
1251 VERIFY(utun_ncd_refcount > 0);
1252
1253 if (--utun_ncd_refcount == 0) {
1254 kern_nexus_controller_destroy(utun_ncd);
1255 utun_ncd = NULL;
1256 }
1257
1258 lck_mtx_unlock(&utun_lock);
1259}
1260
1261// For use by socket option, not internally
1262static errno_t
1263utun_disable_channel(struct utun_pcb *pcb)
1264{
1265 errno_t result;
1266 int enabled;
1267 uuid_t uuid;
1268
1269 lck_rw_lock_exclusive(&pcb->utun_pcb_lock);
1270
1271 enabled = pcb->utun_kpipe_enabled;
1272 uuid_copy(uuid, pcb->utun_kpipe_uuid);
1273
1274 VERIFY(uuid_is_null(pcb->utun_kpipe_uuid) == !enabled);
1275
1276 pcb->utun_kpipe_enabled = 0;
1277 uuid_clear(pcb->utun_kpipe_uuid);
1278
1279 lck_rw_unlock_exclusive(&pcb->utun_pcb_lock);
1280
1281 if (enabled) {
1282 result = kern_nexus_controller_free_provider_instance(utun_ncd, uuid);
1283 } else {
1284 result = ENXIO;
1285 }
1286
1287 if (!result) {
a39ff7e2
A
1288 if (pcb->utun_kpipe_pp != NULL) {
1289 kern_pbufpool_destroy(pcb->utun_kpipe_pp);
1290 pcb->utun_kpipe_pp = NULL;
1291 }
5ba3f43e
A
1292 utun_unregister_kernel_pipe_nexus();
1293 }
1294
1295 return result;
1296}
1297
1298static errno_t
1299utun_enable_channel(struct utun_pcb *pcb, struct proc *proc)
1300{
1301 struct kern_nexus_init init;
a39ff7e2 1302 struct kern_pbufpool_init pp_init;
5ba3f43e
A
1303 errno_t result;
1304
d9a64523
A
1305 kauth_cred_t cred = kauth_cred_get();
1306 result = priv_check_cred(cred, PRIV_SKYWALK_REGISTER_KERNEL_PIPE, 0);
1307 if (result) {
1308 return result;
1309 }
1310
cb323159 1311 result = utun_register_kernel_pipe_nexus(pcb);
5ba3f43e
A
1312 if (result) {
1313 return result;
1314 }
1315
1316 VERIFY(utun_ncd);
1317
1318 lck_rw_lock_exclusive(&pcb->utun_pcb_lock);
1319
1320 if (pcb->utun_kpipe_enabled) {
1321 result = EEXIST; // return success instead?
1322 goto done;
1323 }
1324
1325 /*
1326 * Make sure we can fit packets in the channel buffers and
1327 * Allow an extra 4 bytes for the protocol number header in the channel
1328 */
5c9f4661 1329 if (pcb->utun_ifp->if_mtu + UTUN_HEADER_SIZE(pcb) > pcb->utun_slot_size) {
5ba3f43e
A
1330 result = EOPNOTSUPP;
1331 goto done;
1332 }
1333
0a7de745 1334 bzero(&pp_init, sizeof(pp_init));
a39ff7e2 1335 pp_init.kbi_version = KERN_PBUFPOOL_CURRENT_VERSION;
cb323159 1336 pp_init.kbi_flags |= KBIF_VIRTUAL_DEVICE;
a39ff7e2
A
1337 pp_init.kbi_packets = pcb->utun_netif_ring_size * 2;
1338 pp_init.kbi_bufsize = pcb->utun_slot_size;
1339 pp_init.kbi_buf_seg_size = UTUN_IF_DEFAULT_BUF_SEG_SIZE;
1340 pp_init.kbi_max_frags = 1;
1341 pp_init.kbi_flags |= KBIF_QUANTUM;
0a7de745 1342 (void) snprintf((char *)pp_init.kbi_name, sizeof(pp_init.kbi_name),
a39ff7e2 1343 "com.apple.kpipe.%s", pcb->utun_if_xname);
cb323159
A
1344 pp_init.kbi_ctx = NULL;
1345 pp_init.kbi_ctx_retain = NULL;
1346 pp_init.kbi_ctx_release = NULL;
a39ff7e2 1347
cb323159 1348 result = kern_pbufpool_create(&pp_init, &pcb->utun_kpipe_pp,
a39ff7e2
A
1349 NULL);
1350 if (result != 0) {
cb323159 1351 os_log_error(OS_LOG_DEFAULT, "%s pbufbool create failed, error %d\n", __func__, result);
a39ff7e2
A
1352 goto done;
1353 }
1354
5ba3f43e 1355 VERIFY(uuid_is_null(pcb->utun_kpipe_uuid));
0a7de745 1356 bzero(&init, sizeof(init));
5ba3f43e 1357 init.nxi_version = KERN_NEXUS_CURRENT_VERSION;
a39ff7e2 1358 init.nxi_tx_pbufpool = pcb->utun_kpipe_pp;
5ba3f43e 1359 result = kern_nexus_controller_alloc_provider_instance(utun_ncd,
0a7de745 1360 utun_kpipe_uuid, pcb, &pcb->utun_kpipe_uuid, &init);
5ba3f43e
A
1361 if (result) {
1362 goto done;
1363 }
1364
1365 nexus_port_t port = NEXUS_PORT_KERNEL_PIPE_CLIENT;
1366 result = kern_nexus_controller_bind_provider_instance(utun_ncd,
0a7de745
A
1367 pcb->utun_kpipe_uuid, &port,
1368 proc_pid(proc), NULL, NULL, 0, NEXUS_BIND_PID);
5ba3f43e
A
1369 if (result) {
1370 kern_nexus_controller_free_provider_instance(utun_ncd,
0a7de745 1371 pcb->utun_kpipe_uuid);
5ba3f43e
A
1372 uuid_clear(pcb->utun_kpipe_uuid);
1373 goto done;
1374 }
1375
1376 pcb->utun_kpipe_enabled = 1;
1377
1378done:
1379 lck_rw_unlock_exclusive(&pcb->utun_pcb_lock);
1380
1381 if (result) {
a39ff7e2
A
1382 if (pcb->utun_kpipe_pp != NULL) {
1383 kern_pbufpool_destroy(pcb->utun_kpipe_pp);
1384 pcb->utun_kpipe_pp = NULL;
1385 }
5ba3f43e
A
1386 utun_unregister_kernel_pipe_nexus();
1387 }
1388
1389 return result;
1390}
1391
1392#endif // UTUN_NEXUS
b0d623f7
A
1393
1394errno_t
1395utun_register_control(void)
1396{
5ba3f43e
A
1397 struct kern_ctl_reg kern_ctl;
1398 errno_t result = 0;
0a7de745 1399
5ba3f43e
A
1400#if UTUN_NEXUS
1401 utun_register_nexus();
1402#endif // UTUN_NEXUS
1403
1404 TAILQ_INIT(&utun_head);
0a7de745 1405
b0d623f7 1406 bzero(&kern_ctl, sizeof(kern_ctl));
fe8ab488 1407 strlcpy(kern_ctl.ctl_name, UTUN_CONTROL_NAME, sizeof(kern_ctl.ctl_name));
b0d623f7 1408 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0;
f427ee49 1409 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED | CTL_FLAG_REG_SETUP | CTL_FLAG_REG_EXTENDED; /* Require root */
39236c6e
A
1410 kern_ctl.ctl_sendsize = 512 * 1024;
1411 kern_ctl.ctl_recvsize = 512 * 1024;
f427ee49 1412 kern_ctl.ctl_setup = utun_ctl_setup;
5c9f4661 1413 kern_ctl.ctl_bind = utun_ctl_bind;
b0d623f7
A
1414 kern_ctl.ctl_connect = utun_ctl_connect;
1415 kern_ctl.ctl_disconnect = utun_ctl_disconnect;
1416 kern_ctl.ctl_send = utun_ctl_send;
1417 kern_ctl.ctl_setopt = utun_ctl_setopt;
1418 kern_ctl.ctl_getopt = utun_ctl_getopt;
fe8ab488 1419 kern_ctl.ctl_rcvd = utun_ctl_rcvd;
39236c6e 1420
b0d623f7
A
1421 result = ctl_register(&kern_ctl, &utun_kctlref);
1422 if (result != 0) {
cb323159 1423 os_log_error(OS_LOG_DEFAULT, "utun_register_control - ctl_register failed: %d\n", result);
b0d623f7
A
1424 return result;
1425 }
0a7de745 1426
b0d623f7 1427 /* Register the protocol plumbers */
cb323159 1428 if ((result = proto_register_plumber(PF_INET, IFNET_FAMILY_UTUN,
0a7de745 1429 utun_attach_proto, NULL)) != 0) {
cb323159
A
1430 os_log_error(OS_LOG_DEFAULT, "utun_register_control - proto_register_plumber(PF_INET, IFNET_FAMILY_UTUN) failed: %d\n",
1431 result);
b0d623f7
A
1432 ctl_deregister(utun_kctlref);
1433 return result;
1434 }
0a7de745 1435
b0d623f7 1436 /* Register the protocol plumbers */
cb323159 1437 if ((result = proto_register_plumber(PF_INET6, IFNET_FAMILY_UTUN,
0a7de745 1438 utun_attach_proto, NULL)) != 0) {
cb323159 1439 proto_unregister_plumber(PF_INET, IFNET_FAMILY_UTUN);
b0d623f7 1440 ctl_deregister(utun_kctlref);
cb323159
A
1441 os_log_error(OS_LOG_DEFAULT, "utun_register_control - proto_register_plumber(PF_INET6, IFNET_FAMILY_UTUN) failed: %d\n",
1442 result);
b0d623f7
A
1443 return result;
1444 }
39037602 1445
5ba3f43e
A
1446 utun_lck_attr = lck_attr_alloc_init();
1447 utun_lck_grp_attr = lck_grp_attr_alloc_init();
0a7de745 1448 utun_lck_grp = lck_grp_alloc_init("utun", utun_lck_grp_attr);
5ba3f43e 1449
5ba3f43e 1450 lck_mtx_init(&utun_lock, utun_lck_grp, utun_lck_attr);
5ba3f43e 1451
b0d623f7
A
1452 return 0;
1453}
1454
1455/* Kernel control functions */
1456
f427ee49
A
1457static inline int
1458utun_find_by_unit(u_int32_t unit)
1459{
1460 struct utun_pcb *next_pcb = NULL;
1461 int found = 0;
1462
1463 TAILQ_FOREACH(next_pcb, &utun_head, utun_chain) {
1464 if (next_pcb->utun_unit == unit) {
1465 found = 1;
1466 break;
1467 }
1468 }
1469
1470 return found;
1471}
1472
5ba3f43e 1473static inline void
f427ee49 1474utun_free_pcb(struct utun_pcb *pcb, bool locked)
5ba3f43e 1475{
f427ee49 1476#if UTUN_NEXUS
5ba3f43e 1477 mbuf_freem_list(pcb->utun_input_chain);
cb323159 1478 pcb->utun_input_chain_count = 0;
5ba3f43e
A
1479 lck_mtx_destroy(&pcb->utun_input_chain_lock, utun_lck_grp);
1480#endif // UTUN_NEXUS
1481 lck_rw_destroy(&pcb->utun_pcb_lock, utun_lck_grp);
f427ee49 1482 if (!locked) {
5c9f4661 1483 lck_mtx_lock(&utun_lock);
f427ee49
A
1484 }
1485 TAILQ_REMOVE(&utun_head, pcb, utun_chain);
1486 if (!locked) {
5c9f4661
A
1487 lck_mtx_unlock(&utun_lock);
1488 }
5ba3f43e
A
1489 zfree(utun_pcb_zone, pcb);
1490}
1491
f427ee49
A
1492static errno_t
1493utun_ctl_setup(u_int32_t *unit, void **unitinfo)
1494{
1495 if (unit == NULL || unitinfo == NULL) {
1496 return EINVAL;
1497 }
1498
1499 lck_mtx_lock(&utun_lock);
1500
1501 /* Find next available unit */
1502 if (*unit == 0) {
1503 *unit = 1;
1504 while (*unit != ctl_maxunit) {
1505 if (utun_find_by_unit(*unit)) {
1506 (*unit)++;
1507 } else {
1508 break;
1509 }
1510 }
1511 if (*unit == ctl_maxunit) {
1512 lck_mtx_unlock(&utun_lock);
1513 return EBUSY;
1514 }
1515 } else if (utun_find_by_unit(*unit)) {
1516 lck_mtx_unlock(&utun_lock);
1517 return EBUSY;
1518 }
1519
1520 /* Find some open interface id */
1521 u_int32_t chosen_unique_id = 1;
1522 struct utun_pcb *next_pcb = TAILQ_LAST(&utun_head, utun_list);
1523 if (next_pcb != NULL) {
1524 /* List was not empty, add one to the last item */
1525 chosen_unique_id = next_pcb->utun_unique_id + 1;
1526 next_pcb = NULL;
1527
1528 /*
1529 * If this wrapped the id number, start looking at
1530 * the front of the list for an unused id.
1531 */
1532 if (chosen_unique_id == 0) {
1533 /* Find the next unused ID */
1534 chosen_unique_id = 1;
1535 TAILQ_FOREACH(next_pcb, &utun_head, utun_chain) {
1536 if (next_pcb->utun_unique_id > chosen_unique_id) {
1537 /* We found a gap */
1538 break;
1539 }
1540
1541 chosen_unique_id = next_pcb->utun_unique_id + 1;
1542 }
1543 }
1544 }
1545
1546 struct utun_pcb *pcb = zalloc_flags(utun_pcb_zone, Z_WAITOK | Z_ZERO);
1547
1548 *unitinfo = pcb;
1549 pcb->utun_unit = *unit;
1550 pcb->utun_unique_id = chosen_unique_id;
1551
1552 if (next_pcb != NULL) {
1553 TAILQ_INSERT_BEFORE(next_pcb, pcb, utun_chain);
1554 } else {
1555 TAILQ_INSERT_TAIL(&utun_head, pcb, utun_chain);
1556 }
1557
1558 lck_mtx_unlock(&utun_lock);
1559
1560 return 0;
1561}
1562
b0d623f7 1563static errno_t
5c9f4661 1564utun_ctl_bind(kern_ctl_ref kctlref,
0a7de745
A
1565 struct sockaddr_ctl *sac,
1566 void **unitinfo)
b0d623f7 1567{
f427ee49
A
1568 if (*unitinfo == NULL) {
1569 u_int32_t unit = 0;
1570 (void)utun_ctl_setup(&unit, unitinfo);
1571 }
1572
1573 struct utun_pcb *pcb = (struct utun_pcb *)*unitinfo;
1574 if (pcb == NULL) {
1575 return EINVAL;
1576 }
39037602 1577
d1ecb069
A
1578 pcb->utun_ctlref = kctlref;
1579 pcb->utun_unit = sac->sc_unit;
fe8ab488 1580 pcb->utun_max_pending_packets = 1;
5ba3f43e 1581
5c9f4661
A
1582#if UTUN_NEXUS
1583 pcb->utun_use_netif = false;
cb323159
A
1584 pcb->utun_attach_fsw = true;
1585 pcb->utun_netif_connected = false;
5c9f4661 1586 pcb->utun_slot_size = UTUN_IF_DEFAULT_SLOT_SIZE;
cb323159
A
1587 pcb->utun_netif_ring_size = if_utun_ring_size;
1588 pcb->utun_tx_fsw_ring_size = if_utun_tx_fsw_ring_size;
1589 pcb->utun_rx_fsw_ring_size = if_utun_rx_fsw_ring_size;
1590 pcb->utun_input_chain_count = 0;
1591 lck_mtx_init(&pcb->utun_input_chain_lock, utun_lck_grp, utun_lck_attr);
5c9f4661
A
1592#endif // UTUN_NEXUS
1593
5ba3f43e
A
1594 lck_rw_init(&pcb->utun_pcb_lock, utun_lck_grp, utun_lck_attr);
1595
0a7de745 1596 return 0;
5c9f4661
A
1597}
1598
1599static errno_t
1600utun_ctl_connect(kern_ctl_ref kctlref,
0a7de745
A
1601 struct sockaddr_ctl *sac,
1602 void **unitinfo)
5c9f4661
A
1603{
1604 struct ifnet_init_eparams utun_init = {};
1605 errno_t result = 0;
1606
1607 if (*unitinfo == NULL) {
1608 (void)utun_ctl_bind(kctlref, sac, unitinfo);
1609 }
0a7de745 1610
5c9f4661 1611 struct utun_pcb *pcb = *unitinfo;
f427ee49
A
1612 if (pcb == NULL) {
1613 return EINVAL;
5ba3f43e
A
1614 }
1615
f427ee49
A
1616 /* Handle case where utun_ctl_setup() was called, but ipsec_ctl_bind() was not */
1617 if (pcb->utun_ctlref == NULL) {
1618 (void)utun_ctl_bind(kctlref, sac, unitinfo);
5ba3f43e 1619 }
5ba3f43e
A
1620
1621 snprintf(pcb->utun_if_xname, sizeof(pcb->utun_if_xname), "utun%d", pcb->utun_unit - 1);
1622 snprintf(pcb->utun_unique_name, sizeof(pcb->utun_unique_name), "utunid%d", pcb->utun_unique_id - 1);
b0d623f7
A
1623
1624 /* Create the interface */
1625 bzero(&utun_init, sizeof(utun_init));
39236c6e 1626 utun_init.ver = IFNET_INIT_CURRENT_VERSION;
0a7de745 1627 utun_init.len = sizeof(utun_init);
5ba3f43e
A
1628
1629#if UTUN_NEXUS
5c9f4661
A
1630 if (pcb->utun_use_netif) {
1631 utun_init.flags = (IFNET_INIT_SKYWALK_NATIVE | IFNET_INIT_NX_NOAUTO);
1632 utun_init.tx_headroom = UTUN_IF_HEADROOM_SIZE;
1633 } else
5ba3f43e 1634#endif // UTUN_NEXUS
5c9f4661
A
1635 {
1636 utun_init.flags = IFNET_INIT_NX_NOAUTO;
1637 utun_init.start = utun_start;
1638 utun_init.framer_extended = utun_framer;
1639 }
5ba3f43e 1640 utun_init.name = "utun";
d1ecb069 1641 utun_init.unit = pcb->utun_unit - 1;
5ba3f43e
A
1642 utun_init.uniqueid = pcb->utun_unique_name;
1643 utun_init.uniqueid_len = strlen(pcb->utun_unique_name);
cb323159 1644 utun_init.family = IFNET_FAMILY_UTUN;
b0d623f7 1645 utun_init.type = IFT_OTHER;
b0d623f7 1646 utun_init.demux = utun_demux;
b0d623f7
A
1647 utun_init.add_proto = utun_add_proto;
1648 utun_init.del_proto = utun_del_proto;
1649 utun_init.softc = pcb;
1650 utun_init.ioctl = utun_ioctl;
f427ee49 1651 utun_init.free = utun_detached;
39037602 1652
5ba3f43e 1653#if UTUN_NEXUS
5c9f4661
A
1654 if (pcb->utun_use_netif) {
1655 result = utun_nexus_ifattach(pcb, &utun_init, &pcb->utun_ifp);
1656 if (result != 0) {
cb323159 1657 os_log_error(OS_LOG_DEFAULT, "utun_ctl_connect - utun_nexus_ifattach failed: %d\n", result);
f427ee49 1658 utun_free_pcb(pcb, false);
5c9f4661
A
1659 *unitinfo = NULL;
1660 return result;
1661 }
5ba3f43e 1662
cb323159
A
1663 if (pcb->utun_attach_fsw) {
1664 result = utun_flowswitch_attach(pcb);
1665 if (result != 0) {
1666 os_log_error(OS_LOG_DEFAULT, "utun_ctl_connect - utun_flowswitch_attach failed: %d\n", result);
f427ee49
A
1667 // Do not call utun_free_pcb(). We will be attached already, and will be freed later
1668 // in utun_detached().
cb323159
A
1669 *unitinfo = NULL;
1670 return result;
1671 }
5c9f4661 1672 }
5ba3f43e 1673
5c9f4661
A
1674 /* Attach to bpf */
1675 bpfattach(pcb->utun_ifp, DLT_RAW, 0);
1676 } else
1677#endif // UTUN_NEXUS
1678 {
1679 /*
1680 * Upon success, this holds an ifnet reference which we will
1681 * release via ifnet_release() at final detach time.
1682 */
1683 result = ifnet_allocate_extended(&utun_init, &pcb->utun_ifp);
1684 if (result != 0) {
cb323159 1685 os_log_error(OS_LOG_DEFAULT, "utun_ctl_connect - ifnet_allocate failed: %d\n", result);
f427ee49 1686 utun_free_pcb(pcb, false);
5c9f4661
A
1687 *unitinfo = NULL;
1688 return result;
1689 }
b0d623f7 1690
5c9f4661
A
1691 /* Set flags and additional information. */
1692 ifnet_set_mtu(pcb->utun_ifp, UTUN_DEFAULT_MTU);
1693 ifnet_set_flags(pcb->utun_ifp, IFF_UP | IFF_MULTICAST | IFF_POINTOPOINT, 0xffff);
d1ecb069 1694
5c9f4661
A
1695 /* The interface must generate its own IPv6 LinkLocal address,
1696 * if possible following the recommendation of RFC2472 to the 64bit interface ID
1697 */
1698 ifnet_set_eflags(pcb->utun_ifp, IFEF_NOAUTOIPV6LL, IFEF_NOAUTOIPV6LL);
1699
1700 /* Reset the stats in case as the interface may have been recycled */
1701 struct ifnet_stats_param stats;
1702 bzero(&stats, sizeof(struct ifnet_stats_param));
1703 ifnet_set_stat(pcb->utun_ifp, &stats);
1704
1705 /* Attach the interface */
1706 result = ifnet_attach(pcb->utun_ifp, NULL);
1707 if (result != 0) {
cb323159 1708 os_log_error(OS_LOG_DEFAULT, "utun_ctl_connect - ifnet_attach failed: %d\n", result);
5c9f4661
A
1709 /* Release reference now since attach failed */
1710 ifnet_release(pcb->utun_ifp);
f427ee49 1711 utun_free_pcb(pcb, false);
5c9f4661 1712 *unitinfo = NULL;
0a7de745 1713 return result;
5c9f4661
A
1714 }
1715
1716 /* Attach to bpf */
1717 bpfattach(pcb->utun_ifp, DLT_NULL, UTUN_HEADER_SIZE(pcb));
39037602 1718 }
5ba3f43e 1719
5ba3f43e
A
1720 /* The interfaces resoures allocated, mark it as running */
1721 ifnet_set_flags(pcb->utun_ifp, IFF_RUNNING, IFF_RUNNING);
1722
b0d623f7
A
1723 return result;
1724}
1725
1726static errno_t
5ba3f43e 1727utun_detach_ip(ifnet_t interface,
0a7de745
A
1728 protocol_family_t protocol,
1729 socket_t pf_socket)
b0d623f7
A
1730{
1731 errno_t result = EPROTONOSUPPORT;
0a7de745 1732
b0d623f7
A
1733 /* Attempt a detach */
1734 if (protocol == PF_INET) {
0a7de745
A
1735 struct ifreq ifr;
1736
b0d623f7
A
1737 bzero(&ifr, sizeof(ifr));
1738 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d",
0a7de745
A
1739 ifnet_name(interface), ifnet_unit(interface));
1740
b0d623f7 1741 result = sock_ioctl(pf_socket, SIOCPROTODETACH, &ifr);
5ba3f43e 1742 } else if (protocol == PF_INET6) {
0a7de745
A
1743 struct in6_ifreq ifr6;
1744
b0d623f7
A
1745 bzero(&ifr6, sizeof(ifr6));
1746 snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d",
0a7de745
A
1747 ifnet_name(interface), ifnet_unit(interface));
1748
b0d623f7
A
1749 result = sock_ioctl(pf_socket, SIOCPROTODETACH_IN6, &ifr6);
1750 }
0a7de745 1751
b0d623f7
A
1752 return result;
1753}
1754
1755static void
5ba3f43e 1756utun_remove_address(ifnet_t interface,
0a7de745
A
1757 protocol_family_t protocol,
1758 ifaddr_t address,
1759 socket_t pf_socket)
b0d623f7
A
1760{
1761 errno_t result = 0;
0a7de745 1762
b0d623f7
A
1763 /* Attempt a detach */
1764 if (protocol == PF_INET) {
5ba3f43e 1765 struct ifreq ifr;
0a7de745 1766
b0d623f7
A
1767 bzero(&ifr, sizeof(ifr));
1768 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d",
0a7de745 1769 ifnet_name(interface), ifnet_unit(interface));
b0d623f7
A
1770 result = ifaddr_address(address, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
1771 if (result != 0) {
cb323159 1772 os_log_error(OS_LOG_DEFAULT, "utun_remove_address - ifaddr_address failed: %d", result);
5ba3f43e 1773 } else {
b0d623f7
A
1774 result = sock_ioctl(pf_socket, SIOCDIFADDR, &ifr);
1775 if (result != 0) {
cb323159 1776 os_log_error(OS_LOG_DEFAULT, "utun_remove_address - SIOCDIFADDR failed: %d", result);
b0d623f7
A
1777 }
1778 }
5ba3f43e
A
1779 } else if (protocol == PF_INET6) {
1780 struct in6_ifreq ifr6;
0a7de745 1781
b0d623f7
A
1782 bzero(&ifr6, sizeof(ifr6));
1783 snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d",
0a7de745 1784 ifnet_name(interface), ifnet_unit(interface));
b0d623f7 1785 result = ifaddr_address(address, (struct sockaddr*)&ifr6.ifr_addr,
0a7de745 1786 sizeof(ifr6.ifr_addr));
b0d623f7 1787 if (result != 0) {
cb323159 1788 os_log_error(OS_LOG_DEFAULT, "utun_remove_address - ifaddr_address failed (v6): %d",
0a7de745 1789 result);
5ba3f43e 1790 } else {
b0d623f7
A
1791 result = sock_ioctl(pf_socket, SIOCDIFADDR_IN6, &ifr6);
1792 if (result != 0) {
cb323159 1793 os_log_error(OS_LOG_DEFAULT, "utun_remove_address - SIOCDIFADDR_IN6 failed: %d",
0a7de745 1794 result);
b0d623f7
A
1795 }
1796 }
1797 }
1798}
1799
1800static void
5ba3f43e 1801utun_cleanup_family(ifnet_t interface,
0a7de745 1802 protocol_family_t protocol)
5ba3f43e
A
1803{
1804 errno_t result = 0;
1805 socket_t pf_socket = NULL;
1806 ifaddr_t *addresses = NULL;
1807 int i;
0a7de745 1808
b0d623f7 1809 if (protocol != PF_INET && protocol != PF_INET6) {
cb323159 1810 os_log_error(OS_LOG_DEFAULT, "utun_cleanup_family - invalid protocol family %d\n", protocol);
b0d623f7
A
1811 return;
1812 }
0a7de745 1813
b0d623f7
A
1814 /* Create a socket for removing addresses and detaching the protocol */
1815 result = sock_socket(protocol, SOCK_DGRAM, 0, NULL, NULL, &pf_socket);
1816 if (result != 0) {
0a7de745 1817 if (result != EAFNOSUPPORT) {
cb323159 1818 os_log_error(OS_LOG_DEFAULT, "utun_cleanup_family - failed to create %s socket: %d\n",
0a7de745
A
1819 protocol == PF_INET ? "IP" : "IPv6", result);
1820 }
b0d623f7
A
1821 goto cleanup;
1822 }
0a7de745
A
1823
1824 /* always set SS_PRIV, we want to close and detach regardless */
1825 sock_setpriv(pf_socket, 1);
6d2010ae 1826
b0d623f7
A
1827 result = utun_detach_ip(interface, protocol, pf_socket);
1828 if (result == 0 || result == ENXIO) {
1829 /* We are done! We either detached or weren't attached. */
1830 goto cleanup;
5ba3f43e 1831 } else if (result != EBUSY) {
b0d623f7 1832 /* Uh, not really sure what happened here... */
cb323159 1833 os_log_error(OS_LOG_DEFAULT, "utun_cleanup_family - utun_detach_ip failed: %d\n", result);
b0d623f7
A
1834 goto cleanup;
1835 }
0a7de745 1836
b0d623f7
A
1837 /*
1838 * At this point, we received an EBUSY error. This means there are
1839 * addresses attached. We should detach them and then try again.
1840 */
1841 result = ifnet_get_address_list_family(interface, &addresses, protocol);
1842 if (result != 0) {
cb323159 1843 os_log_error(OS_LOG_DEFAULT, "fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
0a7de745
A
1844 ifnet_name(interface), ifnet_unit(interface),
1845 protocol == PF_INET ? "PF_INET" : "PF_INET6", result);
b0d623f7
A
1846 goto cleanup;
1847 }
0a7de745 1848
b0d623f7
A
1849 for (i = 0; addresses[i] != 0; i++) {
1850 utun_remove_address(interface, protocol, addresses[i], pf_socket);
1851 }
1852 ifnet_free_address_list(addresses);
1853 addresses = NULL;
0a7de745 1854
b0d623f7
A
1855 /*
1856 * The addresses should be gone, we should try the remove again.
1857 */
1858 result = utun_detach_ip(interface, protocol, pf_socket);
1859 if (result != 0 && result != ENXIO) {
cb323159 1860 os_log_error(OS_LOG_DEFAULT, "utun_cleanup_family - utun_detach_ip failed: %d\n", result);
b0d623f7 1861 }
0a7de745 1862
b0d623f7 1863cleanup:
5ba3f43e 1864 if (pf_socket != NULL) {
b0d623f7 1865 sock_close(pf_socket);
5ba3f43e 1866 }
0a7de745 1867
5ba3f43e 1868 if (addresses != NULL) {
b0d623f7 1869 ifnet_free_address_list(addresses);
5ba3f43e 1870 }
b0d623f7
A
1871}
1872
1873static errno_t
5ba3f43e 1874utun_ctl_disconnect(__unused kern_ctl_ref kctlref,
0a7de745
A
1875 __unused u_int32_t unit,
1876 void *unitinfo)
b0d623f7 1877{
0a7de745 1878 struct utun_pcb *pcb = unitinfo;
5ba3f43e
A
1879 ifnet_t ifp = NULL;
1880 errno_t result = 0;
1881
1882 if (pcb == NULL) {
1883 return EINVAL;
1884 }
1885
1886#if UTUN_NEXUS
1887 // Tell the nexus to stop all rings
cb323159 1888 if (pcb->utun_netif_nexus != NULL && pcb->utun_netif_connected) {
5ba3f43e
A
1889 kern_nexus_stop(pcb->utun_netif_nexus);
1890 }
1891#endif // UTUN_NEXUS
316670eb 1892
5ba3f43e 1893 lck_rw_lock_exclusive(&pcb->utun_pcb_lock);
316670eb 1894
5ba3f43e
A
1895#if UTUN_NEXUS
1896 uuid_t kpipe_uuid;
1897 uuid_copy(kpipe_uuid, pcb->utun_kpipe_uuid);
1898 uuid_clear(pcb->utun_kpipe_uuid);
1899 pcb->utun_kpipe_enabled = FALSE;
1900#endif // UTUN_NEXUS
39037602 1901
d1ecb069 1902 pcb->utun_ctlref = NULL;
5ba3f43e 1903
5c9f4661
A
1904 ifp = pcb->utun_ifp;
1905 if (ifp != NULL) {
1906#if UTUN_NEXUS
1907 // Tell the nexus to stop all rings
1908 if (pcb->utun_netif_nexus != NULL) {
1909 /*
1910 * Quiesce the interface and flush any pending outbound packets.
1911 */
1912 if_down(ifp);
1913
1914 /* Increment refcnt, but detach interface */
1915 ifnet_incr_iorefcnt(ifp);
1916 if ((result = ifnet_detach(ifp)) != 0) {
1917 panic("utun_ctl_disconnect - ifnet_detach failed: %d\n", result);
1918 }
5ba3f43e 1919
5c9f4661
A
1920 /*
1921 * We want to do everything in our power to ensure that the interface
1922 * really goes away when the socket is closed. We must remove IP/IPv6
1923 * addresses and detach the protocols. Finally, we can remove and
1924 * release the interface.
1925 */
1926 utun_cleanup_family(ifp, AF_INET);
1927 utun_cleanup_family(ifp, AF_INET6);
39037602 1928
5c9f4661 1929 lck_rw_unlock_exclusive(&pcb->utun_pcb_lock);
39037602 1930
5c9f4661
A
1931 if (!uuid_is_null(kpipe_uuid)) {
1932 if (kern_nexus_controller_free_provider_instance(utun_ncd, kpipe_uuid) == 0) {
a39ff7e2
A
1933 if (pcb->utun_kpipe_pp != NULL) {
1934 kern_pbufpool_destroy(pcb->utun_kpipe_pp);
1935 pcb->utun_kpipe_pp = NULL;
1936 }
5c9f4661
A
1937 utun_unregister_kernel_pipe_nexus();
1938 }
1939 }
a39ff7e2 1940 utun_nexus_detach(pcb);
5c9f4661
A
1941
1942 /* Decrement refcnt to finish detaching and freeing */
1943 ifnet_decr_iorefcnt(ifp);
1944 } else
1945#endif // UTUN_NEXUS
1946 {
1947 lck_rw_unlock_exclusive(&pcb->utun_pcb_lock);
5ba3f43e
A
1948
1949#if UTUN_NEXUS
5c9f4661
A
1950 if (!uuid_is_null(kpipe_uuid)) {
1951 if (kern_nexus_controller_free_provider_instance(utun_ncd, kpipe_uuid) == 0) {
a39ff7e2
A
1952 if (pcb->utun_kpipe_pp != NULL) {
1953 kern_pbufpool_destroy(pcb->utun_kpipe_pp);
1954 pcb->utun_kpipe_pp = NULL;
1955 }
5c9f4661
A
1956 utun_unregister_kernel_pipe_nexus();
1957 }
1958 }
5ba3f43e
A
1959#endif // UTUN_NEXUS
1960
5c9f4661
A
1961 /*
1962 * We want to do everything in our power to ensure that the interface
1963 * really goes away when the socket is closed. We must remove IP/IPv6
1964 * addresses and detach the protocols. Finally, we can remove and
1965 * release the interface.
1966 */
1967 utun_cleanup_family(ifp, AF_INET);
1968 utun_cleanup_family(ifp, AF_INET6);
1969
1970 /*
1971 * Detach now; utun_detach() will be called asynchronously once
1972 * the I/O reference count drops to 0. There we will invoke
1973 * ifnet_release().
1974 */
1975 if ((result = ifnet_detach(ifp)) != 0) {
cb323159 1976 os_log_error(OS_LOG_DEFAULT, "utun_ctl_disconnect - ifnet_detach failed: %d\n", result);
5c9f4661
A
1977 }
1978 }
1979 } else {
1980 // Bound, but not connected
1981 lck_rw_unlock_exclusive(&pcb->utun_pcb_lock);
1982 utun_free_pcb(pcb, false);
1983 }
0a7de745 1984
b0d623f7 1985 return 0;
39037602 1986}
b0d623f7
A
1987
1988static errno_t
5ba3f43e 1989utun_ctl_send(__unused kern_ctl_ref kctlref,
0a7de745
A
1990 __unused u_int32_t unit,
1991 void *unitinfo,
1992 mbuf_t m,
1993 __unused int flags)
b0d623f7 1994{
39236c6e 1995 /*
0a7de745 1996 * The userland ABI requires the first four bytes have the protocol family
39236c6e
A
1997 * in network byte order: swap them
1998 */
39037602 1999 if (m_pktlen(m) >= (int32_t)UTUN_HEADER_SIZE((struct utun_pcb *)unitinfo)) {
39236c6e 2000 *(protocol_family_t *)mbuf_data(m) = ntohl(*(protocol_family_t *)mbuf_data(m));
39037602 2001 } else {
cb323159 2002 os_log_error(OS_LOG_DEFAULT, "%s - unexpected short mbuf pkt len %d\n", __func__, m_pktlen(m));
39037602 2003 }
39236c6e 2004
316670eb 2005 return utun_pkt_input((struct utun_pcb *)unitinfo, m);
b0d623f7
A
2006}
2007
2008static errno_t
5ba3f43e 2009utun_ctl_setopt(__unused kern_ctl_ref kctlref,
0a7de745
A
2010 __unused u_int32_t unit,
2011 void *unitinfo,
2012 int opt,
2013 void *data,
2014 size_t len)
b0d623f7 2015{
5ba3f43e
A
2016 struct utun_pcb *pcb = unitinfo;
2017 errno_t result = 0;
b0d623f7
A
2018 /* check for privileges for privileged options */
2019 switch (opt) {
0a7de745
A
2020 case UTUN_OPT_FLAGS:
2021 case UTUN_OPT_EXT_IFDATA_STATS:
2022 case UTUN_OPT_SET_DELEGATE_INTERFACE:
2023 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
2024 return EPERM;
2025 }
2026 break;
b0d623f7
A
2027 }
2028
2029 switch (opt) {
0a7de745
A
2030 case UTUN_OPT_FLAGS:
2031 if (len != sizeof(u_int32_t)) {
2032 result = EMSGSIZE;
f427ee49
A
2033 break;
2034 }
2035 if (pcb->utun_ifp != NULL) {
2036 // Only can set before connecting
2037 result = EINVAL;
2038 break;
0a7de745 2039 }
f427ee49 2040 pcb->utun_flags = *(u_int32_t *)data;
0a7de745
A
2041 break;
2042
2043 case UTUN_OPT_EXT_IFDATA_STATS:
2044 if (len != sizeof(int)) {
2045 result = EMSGSIZE;
2046 break;
2047 }
2048 if (pcb->utun_ifp == NULL) {
2049 // Only can set after connecting
2050 result = EINVAL;
39236c6e 2051 break;
0a7de745
A
2052 }
2053 pcb->utun_ext_ifdata_stats = (*(int *)data) ? 1 : 0;
2054 break;
39236c6e 2055
0a7de745
A
2056 case UTUN_OPT_INC_IFDATA_STATS_IN:
2057 case UTUN_OPT_INC_IFDATA_STATS_OUT: {
2058 struct utun_stats_param *utsp = (struct utun_stats_param *)data;
2059
2060 if (utsp == NULL || len < sizeof(struct utun_stats_param)) {
2061 result = EINVAL;
d1ecb069 2062 break;
0a7de745
A
2063 }
2064 if (pcb->utun_ifp == NULL) {
2065 // Only can set after connecting
2066 result = EINVAL;
2067 break;
2068 }
2069 if (!pcb->utun_ext_ifdata_stats) {
2070 result = EINVAL;
b0d623f7 2071 break;
d1ecb069 2072 }
0a7de745
A
2073 if (opt == UTUN_OPT_INC_IFDATA_STATS_IN) {
2074 ifnet_stat_increment_in(pcb->utun_ifp, utsp->utsp_packets,
2075 utsp->utsp_bytes, utsp->utsp_errors);
2076 } else {
2077 ifnet_stat_increment_out(pcb->utun_ifp, utsp->utsp_packets,
2078 utsp->utsp_bytes, utsp->utsp_errors);
2079 }
2080 break;
2081 }
2082 case UTUN_OPT_SET_DELEGATE_INTERFACE: {
2083 ifnet_t del_ifp = NULL;
2084 char name[IFNAMSIZ];
39236c6e 2085
0a7de745
A
2086 if (len > IFNAMSIZ - 1) {
2087 result = EMSGSIZE;
39236c6e
A
2088 break;
2089 }
0a7de745
A
2090 if (pcb->utun_ifp == NULL) {
2091 // Only can set after connecting
2092 result = EINVAL;
2093 break;
2094 }
2095 if (len != 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */
2096 bcopy(data, name, len);
2097 name[len] = 0;
2098 result = ifnet_find_by_name(name, &del_ifp);
2099 }
2100 if (result == 0) {
2101 result = ifnet_set_delegate(pcb->utun_ifp, del_ifp);
2102 if (del_ifp) {
2103 ifnet_release(del_ifp);
fe8ab488 2104 }
0a7de745
A
2105 }
2106 break;
2107 }
2108 case UTUN_OPT_MAX_PENDING_PACKETS: {
2109 u_int32_t max_pending_packets = 0;
2110 if (len != sizeof(u_int32_t)) {
2111 result = EMSGSIZE;
2112 break;
2113 }
2114 max_pending_packets = *(u_int32_t *)data;
2115 if (max_pending_packets == 0) {
2116 result = EINVAL;
fe8ab488
A
2117 break;
2118 }
0a7de745
A
2119 pcb->utun_max_pending_packets = max_pending_packets;
2120 break;
2121 }
5ba3f43e 2122#if UTUN_NEXUS
0a7de745
A
2123 case UTUN_OPT_ENABLE_CHANNEL: {
2124 if (len != sizeof(int)) {
2125 result = EMSGSIZE;
2126 break;
2127 }
2128 if (pcb->utun_ifp == NULL) {
2129 // Only can set after connecting
2130 result = EINVAL;
2131 break;
2132 }
2133 if (*(int *)data) {
2134 result = utun_enable_channel(pcb, current_proc());
2135 } else {
2136 result = utun_disable_channel(pcb);
2137 }
2138 break;
2139 }
2140 case UTUN_OPT_ENABLE_FLOWSWITCH: {
2141 if (len != sizeof(int)) {
2142 result = EMSGSIZE;
2143 break;
2144 }
2145 if (pcb->utun_ifp == NULL) {
2146 // Only can set after connecting
2147 result = EINVAL;
2148 break;
2149 }
cb323159 2150 if (!if_is_fsw_transport_netagent_enabled()) {
0a7de745
A
2151 result = ENOTSUP;
2152 break;
2153 }
cb323159 2154 if (uuid_is_null(pcb->utun_nx.fsw_agent)) {
0a7de745 2155 result = ENOENT;
5ba3f43e
A
2156 break;
2157 }
5ba3f43e 2158
cb323159
A
2159 uint32_t flags = netagent_get_flags(pcb->utun_nx.fsw_agent);
2160
0a7de745 2161 if (*(int *)data) {
0a7de745 2162 pcb->utun_needs_netagent = true;
cb323159
A
2163 flags |= (NETAGENT_FLAG_NEXUS_PROVIDER |
2164 NETAGENT_FLAG_NEXUS_LISTENER);
2165 result = netagent_set_flags(pcb->utun_nx.fsw_agent, flags);
0a7de745 2166 } else {
cb323159
A
2167 flags &= ~(NETAGENT_FLAG_NEXUS_PROVIDER |
2168 NETAGENT_FLAG_NEXUS_LISTENER);
2169 result = netagent_set_flags(pcb->utun_nx.fsw_agent, flags);
0a7de745 2170 pcb->utun_needs_netagent = false;
0a7de745
A
2171 }
2172 break;
2173 }
cb323159
A
2174 case UTUN_OPT_ATTACH_FLOWSWITCH: {
2175 if (len != sizeof(int)) {
2176 result = EMSGSIZE;
2177 break;
2178 }
2179 if (pcb->utun_ifp != NULL) {
2180 // Only can set before connecting
2181 result = EINVAL;
2182 break;
2183 }
2184 lck_rw_lock_exclusive(&pcb->utun_pcb_lock);
2185 pcb->utun_attach_fsw = !!(*(int *)data);
2186 lck_rw_unlock_exclusive(&pcb->utun_pcb_lock);
2187 break;
2188 }
0a7de745
A
2189 case UTUN_OPT_ENABLE_NETIF: {
2190 if (len != sizeof(int)) {
2191 result = EMSGSIZE;
5ba3f43e
A
2192 break;
2193 }
0a7de745
A
2194 if (pcb->utun_ifp != NULL) {
2195 // Only can set before connecting
2196 result = EINVAL;
5c9f4661
A
2197 break;
2198 }
0a7de745
A
2199 lck_rw_lock_exclusive(&pcb->utun_pcb_lock);
2200 pcb->utun_use_netif = !!(*(int *)data);
2201 lck_rw_unlock_exclusive(&pcb->utun_pcb_lock);
2202 break;
2203 }
2204 case UTUN_OPT_SLOT_SIZE: {
2205 if (len != sizeof(u_int32_t)) {
2206 result = EMSGSIZE;
5c9f4661
A
2207 break;
2208 }
0a7de745
A
2209 if (pcb->utun_ifp != NULL) {
2210 // Only can set before connecting
2211 result = EINVAL;
5c9f4661
A
2212 break;
2213 }
0a7de745
A
2214 u_int32_t slot_size = *(u_int32_t *)data;
2215 if (slot_size < UTUN_IF_MIN_SLOT_SIZE ||
2216 slot_size > UTUN_IF_MAX_SLOT_SIZE) {
2217 return EINVAL;
2218 }
2219 pcb->utun_slot_size = slot_size;
2220 break;
2221 }
2222 case UTUN_OPT_NETIF_RING_SIZE: {
2223 if (len != sizeof(u_int32_t)) {
2224 result = EMSGSIZE;
5c9f4661
A
2225 break;
2226 }
0a7de745
A
2227 if (pcb->utun_ifp != NULL) {
2228 // Only can set before connecting
2229 result = EINVAL;
5c9f4661
A
2230 break;
2231 }
0a7de745
A
2232 u_int32_t ring_size = *(u_int32_t *)data;
2233 if (ring_size < UTUN_IF_MIN_RING_SIZE ||
2234 ring_size > UTUN_IF_MAX_RING_SIZE) {
2235 return EINVAL;
2236 }
2237 pcb->utun_netif_ring_size = ring_size;
2238 break;
2239 }
2240 case UTUN_OPT_TX_FSW_RING_SIZE: {
2241 if (len != sizeof(u_int32_t)) {
2242 result = EMSGSIZE;
2243 break;
2244 }
2245 if (pcb->utun_ifp != NULL) {
2246 // Only can set before connecting
2247 result = EINVAL;
b0d623f7 2248 break;
fe8ab488 2249 }
0a7de745
A
2250 u_int32_t ring_size = *(u_int32_t *)data;
2251 if (ring_size < UTUN_IF_MIN_RING_SIZE ||
2252 ring_size > UTUN_IF_MAX_RING_SIZE) {
2253 return EINVAL;
2254 }
2255 pcb->utun_tx_fsw_ring_size = ring_size;
2256 break;
2257 }
2258 case UTUN_OPT_RX_FSW_RING_SIZE: {
2259 if (len != sizeof(u_int32_t)) {
2260 result = EMSGSIZE;
2261 break;
2262 }
2263 if (pcb->utun_ifp != NULL) {
2264 // Only can set before connecting
2265 result = EINVAL;
2266 break;
2267 }
2268 u_int32_t ring_size = *(u_int32_t *)data;
2269 if (ring_size < UTUN_IF_MIN_RING_SIZE ||
2270 ring_size > UTUN_IF_MAX_RING_SIZE) {
2271 return EINVAL;
2272 }
2273 pcb->utun_rx_fsw_ring_size = ring_size;
2274 break;
2275 }
cb323159
A
2276 case UTUN_OPT_KPIPE_TX_RING_SIZE: {
2277 if (len != sizeof(u_int32_t)) {
2278 result = EMSGSIZE;
2279 break;
2280 }
2281 if (pcb->utun_ifp != NULL) {
2282 // Only can set before connecting
2283 result = EINVAL;
2284 break;
2285 }
2286 u_int32_t ring_size = *(u_int32_t *)data;
2287 if (ring_size < UTUN_IF_MIN_RING_SIZE ||
2288 ring_size > UTUN_IF_MAX_RING_SIZE) {
2289 return EINVAL;
2290 }
2291 pcb->utun_kpipe_tx_ring_size = ring_size;
2292 break;
2293 }
2294 case UTUN_OPT_KPIPE_RX_RING_SIZE: {
2295 if (len != sizeof(u_int32_t)) {
2296 result = EMSGSIZE;
2297 break;
2298 }
2299 if (pcb->utun_ifp != NULL) {
2300 // Only can set before connecting
2301 result = EINVAL;
2302 break;
2303 }
2304 u_int32_t ring_size = *(u_int32_t *)data;
2305 if (ring_size < UTUN_IF_MIN_RING_SIZE ||
2306 ring_size > UTUN_IF_MAX_RING_SIZE) {
2307 return EINVAL;
2308 }
2309 pcb->utun_kpipe_rx_ring_size = ring_size;
2310 break;
2311 }
0a7de745
A
2312#endif // UTUN_NEXUS
2313 default: {
2314 result = ENOPROTOOPT;
2315 break;
2316 }
b0d623f7
A
2317 }
2318
2319 return result;
2320}
2321
2322static errno_t
5ba3f43e 2323utun_ctl_getopt(__unused kern_ctl_ref kctlref,
0a7de745
A
2324 __unused u_int32_t unit,
2325 void *unitinfo,
2326 int opt,
2327 void *data,
2328 size_t *len)
b0d623f7 2329{
5ba3f43e
A
2330 struct utun_pcb *pcb = unitinfo;
2331 errno_t result = 0;
0a7de745 2332
b0d623f7 2333 switch (opt) {
0a7de745
A
2334 case UTUN_OPT_FLAGS:
2335 if (*len != sizeof(u_int32_t)) {
2336 result = EMSGSIZE;
2337 } else {
2338 *(u_int32_t *)data = pcb->utun_flags;
2339 }
2340 break;
d1ecb069 2341
0a7de745
A
2342 case UTUN_OPT_EXT_IFDATA_STATS:
2343 if (*len != sizeof(int)) {
2344 result = EMSGSIZE;
2345 } else {
2346 *(int *)data = (pcb->utun_ext_ifdata_stats) ? 1 : 0;
2347 }
2348 break;
d1ecb069 2349
0a7de745
A
2350 case UTUN_OPT_IFNAME:
2351 if (*len < MIN(strlen(pcb->utun_if_xname) + 1, sizeof(pcb->utun_if_xname))) {
2352 result = EMSGSIZE;
2353 } else {
2354 if (pcb->utun_ifp == NULL) {
2355 // Only can get after connecting
2356 result = EINVAL;
2357 break;
5ba3f43e 2358 }
4ba76501 2359 *len = scnprintf(data, *len, "%s", pcb->utun_if_xname) + 1;
fe8ab488 2360 }
0a7de745 2361 break;
39037602 2362
0a7de745
A
2363 case UTUN_OPT_MAX_PENDING_PACKETS: {
2364 if (*len != sizeof(u_int32_t)) {
2365 result = EMSGSIZE;
2366 } else {
2367 *((u_int32_t *)data) = pcb->utun_max_pending_packets;
a39ff7e2 2368 }
0a7de745
A
2369 break;
2370 }
a39ff7e2 2371
0a7de745
A
2372#if UTUN_NEXUS
2373 case UTUN_OPT_ENABLE_CHANNEL: {
2374 if (*len != sizeof(int)) {
2375 result = EMSGSIZE;
2376 } else {
2377 lck_rw_lock_shared(&pcb->utun_pcb_lock);
2378 *(int *)data = pcb->utun_kpipe_enabled;
2379 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
a39ff7e2 2380 }
0a7de745
A
2381 break;
2382 }
a39ff7e2 2383
0a7de745
A
2384 case UTUN_OPT_ENABLE_FLOWSWITCH: {
2385 if (*len != sizeof(int)) {
2386 result = EMSGSIZE;
2387 } else {
cb323159 2388 *(int *)data = if_check_netagent(pcb->utun_ifp, pcb->utun_nx.fsw_agent);
a39ff7e2 2389 }
0a7de745
A
2390 break;
2391 }
a39ff7e2 2392
0a7de745
A
2393 case UTUN_OPT_ENABLE_NETIF: {
2394 if (*len != sizeof(int)) {
2395 result = EMSGSIZE;
2396 } else {
5ba3f43e 2397 lck_rw_lock_shared(&pcb->utun_pcb_lock);
0a7de745 2398 *(int *)data = !!pcb->utun_use_netif;
5ba3f43e 2399 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
5c9f4661 2400 }
0a7de745
A
2401 break;
2402 }
2403
2404 case UTUN_OPT_GET_CHANNEL_UUID: {
2405 lck_rw_lock_shared(&pcb->utun_pcb_lock);
2406 if (uuid_is_null(pcb->utun_kpipe_uuid)) {
2407 result = ENXIO;
2408 } else if (*len != sizeof(uuid_t)) {
2409 result = EMSGSIZE;
2410 } else {
2411 uuid_copy(data, pcb->utun_kpipe_uuid);
5c9f4661 2412 }
0a7de745
A
2413 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
2414 break;
2415 }
2416 case UTUN_OPT_SLOT_SIZE: {
2417 if (*len != sizeof(u_int32_t)) {
2418 result = EMSGSIZE;
2419 } else {
2420 *(u_int32_t *)data = pcb->utun_slot_size;
5c9f4661 2421 }
0a7de745
A
2422 break;
2423 }
2424 case UTUN_OPT_NETIF_RING_SIZE: {
2425 if (*len != sizeof(u_int32_t)) {
2426 result = EMSGSIZE;
2427 } else {
2428 *(u_int32_t *)data = pcb->utun_netif_ring_size;
5c9f4661 2429 }
0a7de745
A
2430 break;
2431 }
2432 case UTUN_OPT_TX_FSW_RING_SIZE: {
2433 if (*len != sizeof(u_int32_t)) {
2434 result = EMSGSIZE;
2435 } else {
2436 *(u_int32_t *)data = pcb->utun_tx_fsw_ring_size;
2437 }
2438 break;
2439 }
2440 case UTUN_OPT_RX_FSW_RING_SIZE: {
2441 if (*len != sizeof(u_int32_t)) {
2442 result = EMSGSIZE;
2443 } else {
2444 *(u_int32_t *)data = pcb->utun_rx_fsw_ring_size;
5c9f4661 2445 }
0a7de745
A
2446 break;
2447 }
cb323159
A
2448 case UTUN_OPT_KPIPE_TX_RING_SIZE: {
2449 if (*len != sizeof(u_int32_t)) {
2450 result = EMSGSIZE;
2451 } else {
2452 *(u_int32_t *)data = pcb->utun_kpipe_tx_ring_size;
2453 }
2454 break;
2455 }
2456 case UTUN_OPT_KPIPE_RX_RING_SIZE: {
2457 if (*len != sizeof(u_int32_t)) {
2458 result = EMSGSIZE;
2459 } else {
2460 *(u_int32_t *)data = pcb->utun_kpipe_rx_ring_size;
2461 }
2462 break;
2463 }
5ba3f43e 2464#endif // UTUN_NEXUS
39037602 2465
0a7de745
A
2466 default:
2467 result = ENOPROTOOPT;
2468 break;
b0d623f7 2469 }
0a7de745 2470
b0d623f7
A
2471 return result;
2472}
2473
fe8ab488
A
2474static void
2475utun_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags)
2476{
3e170ce0 2477#pragma unused(flags)
fe8ab488
A
2478 bool reenable_output = false;
2479 struct utun_pcb *pcb = unitinfo;
2480 if (pcb == NULL) {
2481 return;
2482 }
2483 ifnet_lock_exclusive(pcb->utun_ifp);
3e170ce0
A
2484
2485 u_int32_t utun_packet_cnt;
2486 errno_t error_pc = ctl_getenqueuepacketcount(kctlref, unit, &utun_packet_cnt);
2487 if (error_pc != 0) {
cb323159 2488 os_log_error(OS_LOG_DEFAULT, "utun_ctl_rcvd: ctl_getenqueuepacketcount returned error %d\n", error_pc);
3e170ce0 2489 utun_packet_cnt = 0;
fe8ab488 2490 }
3e170ce0
A
2491
2492 if (utun_packet_cnt < pcb->utun_max_pending_packets) {
2493 reenable_output = true;
2494 }
2495
fe8ab488
A
2496 if (reenable_output) {
2497 errno_t error = ifnet_enable_output(pcb->utun_ifp);
2498 if (error != 0) {
cb323159 2499 os_log_error(OS_LOG_DEFAULT, "utun_ctl_rcvd: ifnet_enable_output returned error %d\n", error);
fe8ab488
A
2500 }
2501 }
2502 ifnet_lock_done(pcb->utun_ifp);
2503}
2504
b0d623f7 2505/* Network Interface functions */
fe8ab488
A
2506static void
2507utun_start(ifnet_t interface)
2508{
2509 mbuf_t data;
39037602
A
2510 struct utun_pcb *pcb = ifnet_softc(interface);
2511
2512 VERIFY(pcb != NULL);
2513
5ba3f43e
A
2514#if UTUN_NEXUS
2515 lck_rw_lock_shared(&pcb->utun_pcb_lock);
2516 if (pcb->utun_kpipe_enabled) {
2517 /* It's possible to have channels enabled, but not yet have the channel opened,
2518 * in which case the rxring will not be set
2519 */
2520 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
2521 if (pcb->utun_kpipe_rxring != NULL) {
2522 kern_channel_notify(pcb->utun_kpipe_rxring, 0);
2523 }
2524 return;
2525 }
2526 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
2527#endif // UTUN_NEXUS
39037602 2528
fe8ab488
A
2529 for (;;) {
2530 bool can_accept_packets = true;
2531 ifnet_lock_shared(pcb->utun_ifp);
3e170ce0
A
2532
2533 u_int32_t utun_packet_cnt;
2534 errno_t error_pc = ctl_getenqueuepacketcount(pcb->utun_ctlref, pcb->utun_unit, &utun_packet_cnt);
2535 if (error_pc != 0) {
cb323159 2536 os_log_error(OS_LOG_DEFAULT, "utun_start: ctl_getenqueuepacketcount returned error %d\n", error_pc);
3e170ce0
A
2537 utun_packet_cnt = 0;
2538 }
2539
2540 can_accept_packets = (utun_packet_cnt < pcb->utun_max_pending_packets);
fe8ab488
A
2541 if (!can_accept_packets && pcb->utun_ctlref) {
2542 u_int32_t difference = 0;
2543 if (ctl_getenqueuereadable(pcb->utun_ctlref, pcb->utun_unit, &difference) == 0) {
2544 if (difference > 0) {
2545 // If the low-water mark has not yet been reached, we still need to enqueue data
2546 // into the buffer
2547 can_accept_packets = true;
2548 }
2549 }
2550 }
2551 if (!can_accept_packets) {
2552 errno_t error = ifnet_disable_output(interface);
2553 if (error != 0) {
cb323159 2554 os_log_error(OS_LOG_DEFAULT, "utun_start: ifnet_disable_output returned error %d\n", error);
fe8ab488
A
2555 }
2556 ifnet_lock_done(pcb->utun_ifp);
2557 break;
2558 }
2559 ifnet_lock_done(pcb->utun_ifp);
5ba3f43e 2560 if (ifnet_dequeue(interface, &data) != 0) {
fe8ab488 2561 break;
5ba3f43e
A
2562 }
2563 if (utun_output(interface, data) != 0) {
fe8ab488 2564 break;
5ba3f43e 2565 }
fe8ab488
A
2566 }
2567}
2568
b0d623f7 2569static errno_t
0a7de745
A
2570utun_output(ifnet_t interface,
2571 mbuf_t data)
b0d623f7 2572{
0a7de745 2573 struct utun_pcb *pcb = ifnet_softc(interface);
5ba3f43e 2574 errno_t result;
39037602
A
2575
2576 VERIFY(interface == pcb->utun_ifp);
5ba3f43e 2577
5c9f4661
A
2578#if UTUN_NEXUS
2579 if (!pcb->utun_use_netif)
2580#endif // UTUN_NEXUS
2581 {
2582 if (m_pktlen(data) >= (int32_t)UTUN_HEADER_SIZE(pcb)) {
2583 bpf_tap_out(pcb->utun_ifp, DLT_NULL, data, 0, 0);
2584 }
2585 }
2586
d1ecb069 2587 if (pcb->utun_flags & UTUN_FLAGS_NO_OUTPUT) {
b0d623f7
A
2588 /* flush data */
2589 mbuf_freem(data);
2590 return 0;
2591 }
2592
316670eb 2593 // otherwise, fall thru to ctl_enqueumbuf
d1ecb069 2594 if (pcb->utun_ctlref) {
0a7de745 2595 int length;
316670eb 2596
39236c6e
A
2597 /*
2598 * The ABI requires the protocol in network byte order
2599 */
39037602 2600 if (m_pktlen(data) >= (int32_t)UTUN_HEADER_SIZE(pcb)) {
39236c6e 2601 *(u_int32_t *)mbuf_data(data) = htonl(*(u_int32_t *)mbuf_data(data));
39037602 2602 }
39236c6e 2603
316670eb 2604 length = mbuf_pkthdr_len(data);
d1ecb069 2605 result = ctl_enqueuembuf(pcb->utun_ctlref, pcb->utun_unit, data, CTL_DATA_EOR);
b0d623f7
A
2606 if (result != 0) {
2607 mbuf_freem(data);
cb323159 2608 os_log_error(OS_LOG_DEFAULT, "utun_output - ctl_enqueuembuf failed: %d\n", result);
5c9f4661
A
2609#if UTUN_NEXUS
2610 if (!pcb->utun_use_netif)
2611#endif // UTUN_NEXUS
2612 {
2613 ifnet_stat_increment_out(interface, 0, 0, 1);
2614 }
5ba3f43e 2615 } else {
5c9f4661
A
2616#if UTUN_NEXUS
2617 if (!pcb->utun_use_netif)
2618#endif // UTUN_NEXUS
2619 {
2620 if (!pcb->utun_ext_ifdata_stats) {
2621 ifnet_stat_increment_out(interface, 1, length, 0);
2622 }
5ba3f43e 2623 }
b0d623f7 2624 }
5ba3f43e 2625 } else {
b0d623f7 2626 mbuf_freem(data);
5ba3f43e 2627 }
0a7de745 2628
b0d623f7
A
2629 return 0;
2630}
2631
b0d623f7 2632static errno_t
5ba3f43e 2633utun_demux(__unused ifnet_t interface,
0a7de745
A
2634 mbuf_t data,
2635 __unused char *frame_header,
2636 protocol_family_t *protocol)
b0d623f7 2637{
d9a64523 2638#if UTUN_NEXUS
0a7de745 2639 struct utun_pcb *pcb = ifnet_softc(interface);
d9a64523
A
2640 struct ip *ip;
2641 u_int ip_version;
2642#endif
2643
b0d623f7
A
2644 while (data != NULL && mbuf_len(data) < 1) {
2645 data = mbuf_next(data);
2646 }
5ba3f43e 2647
5c9f4661 2648 if (data == NULL) {
b0d623f7 2649 return ENOENT;
5c9f4661 2650 }
5ba3f43e 2651
5c9f4661
A
2652#if UTUN_NEXUS
2653 if (pcb->utun_use_netif) {
2654 ip = mtod(data, struct ip *);
2655 ip_version = ip->ip_v;
2656
0a7de745
A
2657 switch (ip_version) {
2658 case 4:
2659 *protocol = PF_INET;
2660 return 0;
2661 case 6:
2662 *protocol = PF_INET6;
2663 return 0;
2664 default:
2665 *protocol = 0;
2666 break;
5c9f4661
A
2667 }
2668 } else
2669#endif // UTUN_NEXUS
2670 {
2671 *protocol = *(u_int32_t *)mbuf_data(data);
5ba3f43e
A
2672 }
2673
b0d623f7
A
2674 return 0;
2675}
2676
2677static errno_t
5ba3f43e 2678utun_framer(ifnet_t interface,
0a7de745
A
2679 mbuf_t *packet,
2680 __unused const struct sockaddr *dest,
2681 __unused const char *desk_linkaddr,
2682 const char *frame_type,
2683 u_int32_t *prepend_len,
2684 u_int32_t *postpend_len)
b0d623f7 2685{
0a7de745 2686 struct utun_pcb *pcb = ifnet_softc(interface);
39037602
A
2687 VERIFY(interface == pcb->utun_ifp);
2688
2689 u_int32_t header_length = UTUN_HEADER_SIZE(pcb);
d9a64523 2690 if (mbuf_prepend(packet, header_length, MBUF_DONTWAIT) != 0) {
cb323159 2691 os_log_error(OS_LOG_DEFAULT, "utun_framer - ifnet_output prepend failed\n");
d1ecb069 2692
b0d623f7 2693 ifnet_stat_increment_out(interface, 0, 0, 1);
d1ecb069 2694
b0d623f7 2695 // just return, because the buffer was freed in mbuf_prepend
0a7de745 2696 return EJUSTRETURN;
d9a64523 2697 }
5ba3f43e 2698 if (prepend_len != NULL) {
39037602 2699 *prepend_len = header_length;
5ba3f43e
A
2700 }
2701 if (postpend_len != NULL) {
39236c6e 2702 *postpend_len = 0;
5ba3f43e 2703 }
0a7de745 2704
d9a64523
A
2705 // place protocol number at the beginning of the mbuf
2706 *(protocol_family_t *)mbuf_data(*packet) = *(protocol_family_t *)(uintptr_t)(size_t)frame_type;
39037602
A
2707
2708
0a7de745 2709 return 0;
b0d623f7
A
2710}
2711
2712static errno_t
5ba3f43e 2713utun_add_proto(__unused ifnet_t interface,
0a7de745
A
2714 protocol_family_t protocol,
2715 __unused const struct ifnet_demux_desc *demux_array,
2716 __unused u_int32_t demux_count)
b0d623f7 2717{
0a7de745
A
2718 switch (protocol) {
2719 case PF_INET:
2720 return 0;
2721 case PF_INET6:
2722 return 0;
2723 default:
2724 break;
b0d623f7 2725 }
0a7de745 2726
b0d623f7
A
2727 return ENOPROTOOPT;
2728}
2729
2730static errno_t
5ba3f43e 2731utun_del_proto(__unused ifnet_t interface,
0a7de745 2732 __unused protocol_family_t protocol)
b0d623f7
A
2733{
2734 return 0;
2735}
2736
2737static errno_t
5ba3f43e 2738utun_ioctl(ifnet_t interface,
0a7de745
A
2739 u_long command,
2740 void *data)
b0d623f7 2741{
d9a64523 2742#if UTUN_NEXUS
0a7de745 2743 struct utun_pcb *pcb = ifnet_softc(interface);
d9a64523 2744#endif
0a7de745
A
2745 errno_t result = 0;
2746
2747 switch (command) {
2748 case SIOCSIFMTU: {
5ba3f43e 2749#if UTUN_NEXUS
0a7de745
A
2750 if (pcb->utun_use_netif) {
2751 // Make sure we can fit packets in the channel buffers
2752 // Allow for the headroom in the slot
2753 if (((uint64_t)((struct ifreq*)data)->ifr_mtu) + UTUN_IF_HEADROOM_SIZE > pcb->utun_slot_size) {
2754 result = EINVAL;
2755 } else {
2756 ifnet_set_mtu(interface, (uint32_t)((struct ifreq*)data)->ifr_mtu);
5c9f4661 2757 }
0a7de745
A
2758 } else
2759#endif // UTUN_NEXUS
2760 {
2761 ifnet_set_mtu(interface, ((struct ifreq*)data)->ifr_mtu);
5c9f4661 2762 }
0a7de745 2763 break;
b0d623f7 2764 }
0a7de745
A
2765
2766 case SIOCSIFFLAGS:
2767 /* ifioctl() takes care of it */
2768 break;
2769
2770 default:
2771 result = EOPNOTSUPP;
2772 }
2773
b0d623f7
A
2774 return result;
2775}
2776
2777static void
5ba3f43e 2778utun_detached(ifnet_t interface)
b0d623f7 2779{
0a7de745 2780 struct utun_pcb *pcb = ifnet_softc(interface);
5ba3f43e 2781 (void)ifnet_release(interface);
f427ee49 2782 lck_mtx_lock(&utun_lock);
5c9f4661 2783 utun_free_pcb(pcb, true);
f427ee49
A
2784 (void)ifnet_dispose(interface);
2785 lck_mtx_unlock(&utun_lock);
b0d623f7
A
2786}
2787
2788/* Protocol Handlers */
2789
2790static errno_t
5ba3f43e 2791utun_proto_input(__unused ifnet_t interface,
0a7de745
A
2792 protocol_family_t protocol,
2793 mbuf_t m,
2794 __unused char *frame_header)
b0d623f7 2795{
0a7de745 2796 struct utun_pcb *pcb = ifnet_softc(interface);
5c9f4661
A
2797#if UTUN_NEXUS
2798 if (!pcb->utun_use_netif)
2799#endif // UTUN_NEXUS
2800 {
2801 mbuf_adj(m, UTUN_HEADER_SIZE(pcb));
2802 }
0a7de745 2803 int32_t pktlen = m->m_pkthdr.len;
39037602 2804 if (proto_input(protocol, m) != 0) {
6d2010ae 2805 m_freem(m);
5c9f4661
A
2806#if UTUN_NEXUS
2807 if (!pcb->utun_use_netif)
2808#endif // UTUN_NEXUS
2809 {
2810 ifnet_stat_increment_in(interface, 0, 0, 1);
2811 }
5ba3f43e 2812 } else {
5c9f4661
A
2813#if UTUN_NEXUS
2814 if (!pcb->utun_use_netif)
5ba3f43e 2815#endif // UTUN_NEXUS
5c9f4661 2816 {
a39ff7e2 2817 ifnet_stat_increment_in(interface, 1, pktlen, 0);
5c9f4661 2818 }
39037602 2819 }
0a7de745 2820
b0d623f7
A
2821 return 0;
2822}
2823
2824static errno_t
5ba3f43e 2825utun_proto_pre_output(__unused ifnet_t interface,
0a7de745
A
2826 protocol_family_t protocol,
2827 __unused mbuf_t *packet,
2828 __unused const struct sockaddr *dest,
2829 __unused void *route,
2830 char *frame_type,
2831 __unused char *link_layer_dest)
b0d623f7 2832{
6d2010ae 2833 *(protocol_family_t *)(void *)frame_type = protocol;
39037602 2834 return 0;
b0d623f7
A
2835}
2836
2837static errno_t
5ba3f43e 2838utun_attach_proto(ifnet_t interface,
0a7de745 2839 protocol_family_t protocol)
b0d623f7 2840{
0a7de745
A
2841 struct ifnet_attach_proto_param proto;
2842
b0d623f7
A
2843 bzero(&proto, sizeof(proto));
2844 proto.input = utun_proto_input;
2845 proto.pre_output = utun_proto_pre_output;
2846
5ba3f43e 2847 errno_t result = ifnet_attach_protocol(interface, protocol, &proto);
b0d623f7 2848 if (result != 0 && result != EEXIST) {
cb323159 2849 os_log_error(OS_LOG_DEFAULT, "utun_attach_inet - ifnet_attach_protocol %d failed: %d\n",
0a7de745 2850 protocol, result);
b0d623f7 2851 }
0a7de745 2852
b0d623f7
A
2853 return result;
2854}
2855
5ba3f43e
A
2856static errno_t
2857utun_pkt_input(struct utun_pcb *pcb, mbuf_t packet)
2858{
5c9f4661
A
2859#if UTUN_NEXUS
2860 if (pcb->utun_use_netif) {
2861 lck_rw_lock_shared(&pcb->utun_pcb_lock);
5ba3f43e 2862
5c9f4661 2863 lck_mtx_lock(&pcb->utun_input_chain_lock);
cb323159
A
2864
2865 if (pcb->utun_input_chain_count > (u_int32_t)if_utun_max_pending_input) {
2866 lck_mtx_unlock(&pcb->utun_input_chain_lock);
2867 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
2868 return ENOSPC;
2869 }
2870
5c9f4661
A
2871 if (pcb->utun_input_chain != NULL) {
2872 pcb->utun_input_chain_last->m_nextpkt = packet;
2873 } else {
2874 pcb->utun_input_chain = packet;
2875 }
cb323159 2876 pcb->utun_input_chain_count++;
5c9f4661
A
2877 while (packet->m_nextpkt) {
2878 VERIFY(packet != packet->m_nextpkt);
2879 packet = packet->m_nextpkt;
cb323159 2880 pcb->utun_input_chain_count++;
5c9f4661
A
2881 }
2882 pcb->utun_input_chain_last = packet;
2883 lck_mtx_unlock(&pcb->utun_input_chain_lock);
5ba3f43e 2884
5c9f4661
A
2885 kern_channel_ring_t rx_ring = pcb->utun_netif_rxring;
2886 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
316670eb 2887
5c9f4661
A
2888 if (rx_ring != NULL) {
2889 kern_channel_notify(rx_ring, 0);
2890 }
316670eb 2891
0a7de745 2892 return 0;
5c9f4661 2893 } else
cb323159 2894#endif // UTUN_NEXUS
5c9f4661
A
2895 {
2896 mbuf_pkthdr_setrcvif(packet, pcb->utun_ifp);
5ba3f43e 2897
0a7de745 2898 if (m_pktlen(packet) >= (int32_t)UTUN_HEADER_SIZE(pcb)) {
5c9f4661
A
2899 bpf_tap_in(pcb->utun_ifp, DLT_NULL, packet, 0, 0);
2900 }
2901 if (pcb->utun_flags & UTUN_FLAGS_NO_INPUT) {
2902 /* flush data */
2903 mbuf_freem(packet);
2904 return 0;
2905 }
316670eb 2906
0a7de745 2907 errno_t result = 0;
5c9f4661
A
2908 if (!pcb->utun_ext_ifdata_stats) {
2909 struct ifnet_stat_increment_param incs = {};
2910 incs.packets_in = 1;
2911 incs.bytes_in = mbuf_pkthdr_len(packet);
2912 result = ifnet_input(pcb->utun_ifp, packet, &incs);
2913 } else {
2914 result = ifnet_input(pcb->utun_ifp, packet, NULL);
2915 }
2916 if (result != 0) {
2917 ifnet_stat_increment_in(pcb->utun_ifp, 0, 0, 1);
5ba3f43e 2918
cb323159 2919 os_log_error(OS_LOG_DEFAULT, "%s - ifnet_input failed: %d\n", __FUNCTION__, result);
5c9f4661
A
2920 mbuf_freem(packet);
2921 }
5ba3f43e 2922
0a7de745 2923 return 0;
316670eb 2924 }
316670eb 2925}
5ba3f43e
A
2926
2927#if UTUN_NEXUS
2928
2929static errno_t
2930utun_nxdp_init(__unused kern_nexus_domain_provider_t domprov)
2931{
2932 return 0;
2933}
2934
2935static void
2936utun_nxdp_fini(__unused kern_nexus_domain_provider_t domprov)
2937{
2938 // Ignore
2939}
2940
2941static errno_t
2942utun_register_nexus(void)
2943{
2944 const struct kern_nexus_domain_provider_init dp_init = {
2945 .nxdpi_version = KERN_NEXUS_DOMAIN_PROVIDER_CURRENT_VERSION,
2946 .nxdpi_flags = 0,
2947 .nxdpi_init = utun_nxdp_init,
2948 .nxdpi_fini = utun_nxdp_fini
2949 };
2950 errno_t err = 0;
2951
2952 /* utun_nxdp_init() is called before this function returns */
2953 err = kern_nexus_register_domain_provider(NEXUS_TYPE_NET_IF,
0a7de745
A
2954 (const uint8_t *) "com.apple.utun",
2955 &dp_init, sizeof(dp_init),
2956 &utun_nx_dom_prov);
5ba3f43e 2957 if (err != 0) {
cb323159 2958 os_log_error(OS_LOG_DEFAULT, "%s: failed to register domain provider\n", __func__);
0a7de745 2959 return err;
5ba3f43e 2960 }
0a7de745 2961 return 0;
5ba3f43e 2962}
9d749ea3
A
2963boolean_t
2964utun_interface_needs_netagent(ifnet_t interface)
2965{
2966 struct utun_pcb *pcb = NULL;
2967
2968 if (interface == NULL) {
0a7de745 2969 return FALSE;
9d749ea3
A
2970 }
2971
2972 pcb = ifnet_softc(interface);
2973
2974 if (pcb == NULL) {
0a7de745 2975 return FALSE;
9d749ea3
A
2976 }
2977
0a7de745 2978 return pcb->utun_needs_netagent == true;
9d749ea3 2979}
5ba3f43e
A
2980
2981static errno_t
2982utun_ifnet_set_attrs(ifnet_t ifp)
2983{
2984 /* Set flags and additional information. */
2985 ifnet_set_mtu(ifp, 1500);
2986 ifnet_set_flags(ifp, IFF_UP | IFF_MULTICAST | IFF_POINTOPOINT, 0xffff);
2987
2988 /* The interface must generate its own IPv6 LinkLocal address,
2989 * if possible following the recommendation of RFC2472 to the 64bit interface ID
2990 */
2991 ifnet_set_eflags(ifp, IFEF_NOAUTOIPV6LL, IFEF_NOAUTOIPV6LL);
2992
0a7de745 2993 return 0;
5ba3f43e
A
2994}
2995
2996static errno_t
2997utun_netif_prepare(kern_nexus_t nexus, ifnet_t ifp)
2998{
2999 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
3000 pcb->utun_netif_nexus = nexus;
0a7de745 3001 return utun_ifnet_set_attrs(ifp);
5ba3f43e
A
3002}
3003
3004static errno_t
3005utun_nexus_pre_connect(kern_nexus_provider_t nxprov,
3006 proc_t p, kern_nexus_t nexus,
3007 nexus_port_t nexus_port, kern_channel_t channel, void **ch_ctx)
3008{
3009#pragma unused(nxprov, p)
3010#pragma unused(nexus, nexus_port, channel, ch_ctx)
0a7de745 3011 return 0;
5ba3f43e
A
3012}
3013
3014static errno_t
3015utun_nexus_connected(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
3016 kern_channel_t channel)
3017{
3018#pragma unused(nxprov, channel)
3019 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
3020 boolean_t ok = ifnet_is_attached(pcb->utun_ifp, 1);
cb323159
A
3021 if (pcb->utun_netif_nexus == nexus) {
3022 pcb->utun_netif_connected = true;
3023 }
0a7de745 3024 return ok ? 0 : ENXIO;
5ba3f43e
A
3025}
3026
3027static void
3028utun_nexus_pre_disconnect(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
3029 kern_channel_t channel)
3030{
3031#pragma unused(nxprov, nexus, channel)
3032}
3033
3034static void
3035utun_netif_pre_disconnect(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745 3036 kern_channel_t channel)
5ba3f43e
A
3037{
3038#pragma unused(nxprov, nexus, channel)
3039}
3040
3041static void
3042utun_nexus_disconnected(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
3043 kern_channel_t channel)
3044{
3045#pragma unused(nxprov, channel)
3046 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
3047 if (pcb->utun_netif_nexus == nexus) {
cb323159
A
3048 pcb->utun_netif_connected = false;
3049 if (pcb->utun_attach_fsw) {
3050 // disconnected by flowswitch that was attached by us
3051 pcb->utun_netif_nexus = NULL;
3052 }
5ba3f43e
A
3053 }
3054 ifnet_decr_iorefcnt(pcb->utun_ifp);
3055}
3056
3057static errno_t
3058utun_kpipe_ring_init(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745
A
3059 kern_channel_t channel, kern_channel_ring_t ring,
3060 boolean_t is_tx_ring, void **ring_ctx)
5ba3f43e
A
3061{
3062#pragma unused(nxprov)
3063#pragma unused(channel)
3064#pragma unused(ring_ctx)
3065 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
3066 if (!is_tx_ring) {
3067 VERIFY(pcb->utun_kpipe_rxring == NULL);
3068 pcb->utun_kpipe_rxring = ring;
3069 } else {
3070 VERIFY(pcb->utun_kpipe_txring == NULL);
3071 pcb->utun_kpipe_txring = ring;
3072 }
3073 return 0;
3074}
3075
3076static void
3077utun_kpipe_ring_fini(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745 3078 kern_channel_ring_t ring)
5ba3f43e
A
3079{
3080#pragma unused(nxprov)
3081 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
3082 if (pcb->utun_kpipe_rxring == ring) {
3083 pcb->utun_kpipe_rxring = NULL;
3084 } else if (pcb->utun_kpipe_txring == ring) {
3085 pcb->utun_kpipe_txring = NULL;
3086 }
3087}
3088
3089static errno_t
3090utun_kpipe_sync_tx(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745 3091 kern_channel_ring_t tx_ring, uint32_t flags)
5ba3f43e
A
3092{
3093#pragma unused(nxprov)
3094#pragma unused(flags)
3095 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
3096
3097 lck_rw_lock_shared(&pcb->utun_pcb_lock);
3098 int channel_enabled = pcb->utun_kpipe_enabled;
3099 if (!channel_enabled) {
3100 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
3101 return 0;
3102 }
3103
5c9f4661
A
3104 if (pcb->utun_use_netif) {
3105 kern_channel_slot_t tx_slot = kern_channel_get_next_slot(tx_ring, NULL, NULL);
3106 if (tx_slot == NULL) {
3107 // Nothing to write, bail
3108 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
3109 return 0;
3110 }
3111
3112 // Signal the netif ring to read
3113 kern_channel_ring_t rx_ring = pcb->utun_netif_rxring;
3114 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
3115 if (rx_ring != NULL) {
3116 kern_channel_notify(rx_ring, 0);
3117 }
3118 } else {
5ba3f43e 3119 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
5ba3f43e 3120
5c9f4661
A
3121 struct ifnet_stat_increment_param incs = {};
3122 struct kern_channel_ring_stat_increment tx_ring_stats = {};
3123 MBUFQ_HEAD(mbufq) mbq;
3124 MBUFQ_INIT(&mbq);
3125 kern_channel_slot_t tx_pslot = NULL;
3126 kern_channel_slot_t tx_slot = kern_channel_get_next_slot(tx_ring, NULL, NULL);
3127 while (tx_slot != NULL) {
3128 kern_packet_t tx_ph = kern_channel_slot_get_packet(tx_ring, tx_slot);
3129
3130 // Advance TX ring
3131 tx_pslot = tx_slot;
3132 tx_slot = kern_channel_get_next_slot(tx_ring, tx_slot, NULL);
3133
3134 if (tx_ph == 0) {
3135 continue;
3136 }
3137
3138 kern_buflet_t tx_buf = kern_packet_get_next_buflet(tx_ph, NULL);
3139 VERIFY(tx_buf != NULL);
f427ee49 3140 uint8_t *tx_baddr = kern_buflet_get_data_address(tx_buf);
5c9f4661
A
3141 VERIFY(tx_baddr != 0);
3142 tx_baddr += kern_buflet_get_data_offset(tx_buf);
3143
3144 size_t length = MIN(kern_packet_get_data_length(tx_ph),
0a7de745 3145 pcb->utun_slot_size);
5c9f4661
A
3146
3147 mbuf_t data = NULL;
3148 if (length >= UTUN_HEADER_SIZE(pcb) &&
0a7de745 3149 !(pcb->utun_flags & UTUN_FLAGS_NO_INPUT)) {
5c9f4661
A
3150 errno_t error = mbuf_gethdr(MBUF_WAITOK, MBUF_TYPE_HEADER, &data);
3151 VERIFY(0 == error);
3152 error = mbuf_copyback(data, 0, length, tx_baddr, MBUF_WAITOK);
3153 VERIFY(0 == error);
3154 /*
3155 * The userland ABI requires the first four bytes have
3156 * the protocol family in network byte order: swap them
3157 */
3158 *(uint32_t *)mbuf_data(data) = ntohl(*(uint32_t *)mbuf_data(data));
3159 mbuf_pkthdr_setrcvif(data, pcb->utun_ifp);
3160 bpf_tap_in(pcb->utun_ifp, DLT_NULL, data, 0, 0);
3161 incs.packets_in++;
3162 incs.bytes_in += length;
3163 MBUFQ_ENQUEUE(&mbq, data);
3164 }
3165 }
3166 if (tx_pslot) {
3167 kern_channel_advance_slot(tx_ring, tx_pslot);
3168 tx_ring_stats.kcrsi_slots_transferred = incs.packets_in;
3169 tx_ring_stats.kcrsi_bytes_transferred = incs.bytes_in;
3170 kern_channel_increment_ring_net_stats(tx_ring, pcb->utun_ifp, &tx_ring_stats);
3171 (void) kern_channel_reclaim(tx_ring);
3172 }
3173 if (!MBUFQ_EMPTY(&mbq)) {
3174 (void) ifnet_input_extended(pcb->utun_ifp, MBUFQ_FIRST(&mbq),
0a7de745 3175 MBUFQ_LAST(&mbq), &incs);
5c9f4661
A
3176 MBUFQ_INIT(&mbq);
3177 }
5ba3f43e
A
3178 }
3179
3180 return 0;
3181}
3182
3183static errno_t
3184utun_kpipe_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus,
0a7de745 3185 kern_channel_ring_t rx_ring, uint32_t flags)
5ba3f43e
A
3186{
3187#pragma unused(nxprov)
3188#pragma unused(flags)
3189 struct utun_pcb *pcb = kern_nexus_get_context(nexus);
5c9f4661 3190 struct kern_channel_ring_stat_increment rx_ring_stats = {};
5ba3f43e
A
3191
3192 lck_rw_lock_shared(&pcb->utun_pcb_lock);
3193
3194 int channel_enabled = pcb->utun_kpipe_enabled;
3195 if (!channel_enabled) {
3196 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
3197 return 0;
3198 }
3199
3200 /* reclaim user-released slots */
3201 (void) kern_channel_reclaim(rx_ring);
3202
3203 uint32_t avail = kern_channel_available_slot_count(rx_ring);
3204 if (avail == 0) {
3205 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
3206 return 0;
3207 }
3208
5c9f4661
A
3209 if (pcb->utun_use_netif) {
3210 kern_channel_ring_t tx_ring = pcb->utun_netif_txring;
3211 if (tx_ring == NULL ||
0a7de745 3212 pcb->utun_netif_nexus == NULL) {
5c9f4661
A
3213 // Net-If TX ring not set up yet, nothing to read
3214 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
3215 return 0;
3216 }
5ba3f43e 3217
5c9f4661 3218 struct netif_stats *nifs = &NX_NETIF_PRIVATE(pcb->utun_netif_nexus)->nif_stats;
5ba3f43e 3219
5c9f4661 3220 // Unlock utun before entering ring
5ba3f43e 3221 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
5ba3f43e 3222
5c9f4661 3223 (void)kr_enter(tx_ring, TRUE);
5ba3f43e 3224
5c9f4661
A
3225 // Lock again after entering and validate
3226 lck_rw_lock_shared(&pcb->utun_pcb_lock);
3227 if (tx_ring != pcb->utun_netif_txring) {
3228 // Ring no longer valid
3229 // Unlock first, then exit ring
3230 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
3231 kr_exit(tx_ring);
3232 return 0;
5ba3f43e
A
3233 }
3234
5c9f4661
A
3235 struct kern_channel_ring_stat_increment tx_ring_stats;
3236 bzero(&tx_ring_stats, sizeof(tx_ring_stats));
3237 kern_channel_slot_t tx_pslot = NULL;
3238 kern_channel_slot_t tx_slot = kern_channel_get_next_slot(tx_ring, NULL, NULL);
3239 if (tx_slot == NULL) {
3240 // Nothing to read, don't bother signalling
3241 // Unlock first, then exit ring
3242 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
3243 kr_exit(tx_ring);
3244 return 0;
5ba3f43e
A
3245 }
3246
5c9f4661
A
3247 struct kern_pbufpool *rx_pp = rx_ring->ckr_pp;
3248 VERIFY(rx_pp != NULL);
3249 kern_channel_slot_t rx_pslot = NULL;
3250 kern_channel_slot_t rx_slot = kern_channel_get_next_slot(rx_ring, NULL, NULL);
5ba3f43e 3251
5c9f4661
A
3252 while (rx_slot != NULL && tx_slot != NULL) {
3253 size_t length;
3254 kern_buflet_t rx_buf;
3255 void *rx_baddr;
5ba3f43e 3256
5c9f4661 3257 kern_packet_t tx_ph = kern_channel_slot_get_packet(tx_ring, tx_slot);
5ba3f43e 3258
5c9f4661
A
3259 // Advance TX ring
3260 tx_pslot = tx_slot;
3261 tx_slot = kern_channel_get_next_slot(tx_ring, tx_slot, NULL);
5ba3f43e 3262
5c9f4661
A
3263 /* Skip slot if packet is zero-length or marked as dropped (QUMF_DROPPED) */
3264 if (tx_ph == 0) {
3265 continue;
3266 }
5ba3f43e 3267
5c9f4661
A
3268 // Allocate rx packet
3269 kern_packet_t rx_ph = 0;
3270 errno_t error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph);
a39ff7e2 3271 if (__improbable(error != 0)) {
cb323159 3272 os_log_error(OS_LOG_DEFAULT, "utun_kpipe_sync_rx %s: failed to allocate packet\n",
0a7de745 3273 pcb->utun_ifp->if_xname);
5ba3f43e
A
3274 break;
3275 }
5c9f4661
A
3276
3277 kern_buflet_t tx_buf = kern_packet_get_next_buflet(tx_ph, NULL);
3278 VERIFY(tx_buf != NULL);
f427ee49 3279 uint8_t *tx_baddr = kern_buflet_get_data_address(tx_buf);
5c9f4661
A
3280 VERIFY(tx_baddr != NULL);
3281 tx_baddr += kern_buflet_get_data_offset(tx_buf);
3282
3283 bpf_tap_packet_out(pcb->utun_ifp, DLT_RAW, tx_ph, NULL, 0);
3284
3285 length = MIN(kern_packet_get_data_length(tx_ph) + UTUN_HEADER_SIZE(pcb),
0a7de745 3286 pcb->utun_slot_size);
5c9f4661
A
3287
3288 tx_ring_stats.kcrsi_slots_transferred++;
3289 tx_ring_stats.kcrsi_bytes_transferred += length;
3290
3291 if (length < UTUN_HEADER_SIZE(pcb) ||
0a7de745
A
3292 length > pcb->utun_slot_size ||
3293 length > rx_pp->pp_buflet_size ||
3294 (pcb->utun_flags & UTUN_FLAGS_NO_OUTPUT)) {
5c9f4661
A
3295 /* flush data */
3296 kern_pbufpool_free(rx_pp, rx_ph);
cb323159 3297 os_log_error(OS_LOG_DEFAULT, "utun_kpipe_sync_rx %s: invalid length %zu header_size %zu\n",
0a7de745 3298 pcb->utun_ifp->if_xname, length, UTUN_HEADER_SIZE(pcb));
cb323159
A
3299 STATS_INC(nifs, NETIF_STATS_DROP_BADLEN);
3300 STATS_INC(nifs, NETIF_STATS_DROP);
5c9f4661 3301 continue;
5ba3f43e 3302 }
5c9f4661
A
3303
3304 /* fillout packet */
3305 rx_buf = kern_packet_get_next_buflet(rx_ph, NULL);
3306 VERIFY(rx_buf != NULL);
f427ee49 3307 rx_baddr = kern_buflet_get_data_address(rx_buf);
5c9f4661
A
3308 VERIFY(rx_baddr != NULL);
3309
3310 // Find family
3311 uint32_t af = 0;
3312 uint8_t vhl = *(uint8_t *)(tx_baddr);
3313 u_int ip_version = (vhl >> 4);
3314 switch (ip_version) {
0a7de745
A
3315 case 4: {
3316 af = AF_INET;
3317 break;
3318 }
3319 case 6: {
3320 af = AF_INET6;
3321 break;
3322 }
3323 default: {
cb323159 3324 os_log_error(OS_LOG_DEFAULT, "utun_kpipe_sync_rx %s: unknown ip version %u vhl %u header_size %zu\n",
0a7de745
A
3325 pcb->utun_ifp->if_xname, ip_version, vhl, UTUN_HEADER_SIZE(pcb));
3326 break;
3327 }
5ba3f43e 3328 }
5ba3f43e 3329
5c9f4661
A
3330 // Copy header
3331 af = htonl(af);
3332 memcpy((void *)rx_baddr, &af, sizeof(af));
3333 if (pcb->utun_flags & UTUN_FLAGS_ENABLE_PROC_UUID) {
3334 kern_packet_get_euuid(tx_ph, (void *)(rx_baddr + sizeof(af)));
3335 }
5ba3f43e 3336
5c9f4661
A
3337 // Copy data from tx to rx
3338 memcpy((void *)(rx_baddr + UTUN_HEADER_SIZE(pcb)), (void *)tx_baddr, length - UTUN_HEADER_SIZE(pcb));
3339 kern_packet_clear_flow_uuid(rx_ph); // zero flow id
5ba3f43e 3340
5c9f4661
A
3341 /* finalize and attach the packet */
3342 error = kern_buflet_set_data_offset(rx_buf, 0);
3343 VERIFY(error == 0);
3344 error = kern_buflet_set_data_length(rx_buf, length);
3345 VERIFY(error == 0);
3346 error = kern_packet_finalize(rx_ph);
3347 VERIFY(error == 0);
3348 error = kern_channel_slot_attach_packet(rx_ring, rx_slot, rx_ph);
3349 VERIFY(error == 0);
5ba3f43e 3350
cb323159
A
3351 STATS_INC(nifs, NETIF_STATS_TX_PACKETS);
3352 STATS_INC(nifs, NETIF_STATS_TX_COPY_DIRECT);
5ba3f43e 3353
5c9f4661
A
3354 rx_ring_stats.kcrsi_slots_transferred++;
3355 rx_ring_stats.kcrsi_bytes_transferred += length;
5ba3f43e 3356
5c9f4661
A
3357 rx_pslot = rx_slot;
3358 rx_slot = kern_channel_get_next_slot(rx_ring, rx_slot, NULL);
3359 }
5ba3f43e 3360
5c9f4661
A
3361 if (rx_pslot) {
3362 kern_channel_advance_slot(rx_ring, rx_pslot);
3363 kern_channel_increment_ring_net_stats(rx_ring, pcb->utun_ifp, &rx_ring_stats);
3364 }
5ba3f43e 3365
5c9f4661
A
3366 if (tx_pslot) {
3367 kern_channel_advance_slot(tx_ring, tx_pslot);
3368 kern_channel_increment_ring_net_stats(tx_ring, pcb->utun_ifp, &tx_ring_stats);
3369 (void)kern_channel_reclaim(tx_ring);
3370 }
5ba3f43e 3371
5c9f4661 3372 /* just like utun_ctl_rcvd(), always reenable output */
5ba3f43e
A
3373 errno_t error = ifnet_enable_output(pcb->utun_ifp);
3374 if (error != 0) {
cb323159 3375 os_log_error(OS_LOG_DEFAULT, "utun_kpipe_sync_rx: ifnet_enable_output returned error %d\n", error);
5ba3f43e 3376 }
5ba3f43e 3377
5c9f4661
A
3378 // Unlock first, then exit ring
3379 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
5ba3f43e 3380
5c9f4661
A
3381 if (tx_pslot != NULL) {
3382 kern_channel_notify(tx_ring, 0);
3383 }
3384 kr_exit(tx_ring);
3385 } else {
3386 lck_rw_unlock_shared(&pcb->utun_pcb_lock);
3387
3388 uint32_t mb_cnt = 0;
3389 uint32_t mb_len = 0;
3390 struct mbuf *mb_head = NULL;
3391 struct mbuf *mb_tail = NULL;
3392
3393 if (ifnet_dequeue_multi(pcb->utun_ifp, avail, &mb_head,
0a7de745 3394 &mb_tail, &mb_cnt, &mb_len) != 0) {
5c9f4661
A
3395 return 0;
3396 }
3397 VERIFY(mb_cnt <= avail);
3398
3399 struct kern_pbufpool *rx_pp = rx_ring->ckr_pp;
3400 VERIFY(rx_pp != NULL);
3401 kern_channel_slot_t rx_pslot = NULL;
3402 kern_channel_slot_t rx_slot = kern_channel_get_next_slot(rx_ring, NULL, NULL);
3403 while (rx_slot) {
3404 size_t length = 0;
3405 mbuf_t data = NULL;
3406 if ((data = mb_head) == NULL) {
3407 VERIFY(mb_cnt == 0);
3408 break;
3409 }
3410 mb_head = mbuf_nextpkt(mb_head);
3411 mbuf_setnextpkt(data, NULL);
3412 VERIFY(mb_cnt != 0);
3413 --mb_cnt;
3414 length = mbuf_pkthdr_len(data);
3415 if (length < UTUN_HEADER_SIZE(pcb) ||
0a7de745
A
3416 length > pcb->utun_slot_size ||
3417 (pcb->utun_flags & UTUN_FLAGS_NO_OUTPUT)) {
5c9f4661
A
3418 /* flush data */
3419 mbuf_freem(data);
3420 continue;
3421 }
3422 bpf_tap_out(pcb->utun_ifp, DLT_NULL, data, 0, 0);
3423
3424 // Allocate rx packet
3425 kern_packet_t rx_ph = 0;
3426 errno_t error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph);
a39ff7e2 3427 if (__improbable(error != 0)) {
cb323159 3428 os_log_error(OS_LOG_DEFAULT, "utun_kpipe_sync_rx %s: failed to allocate packet\n",
0a7de745 3429 pcb->utun_ifp->if_xname);
5c9f4661
A
3430 break;
3431 }
3432
3433 /*
3434 * The ABI requires the protocol in network byte order
3435 */
3436 *(u_int32_t *)mbuf_data(data) = htonl(*(u_int32_t *)mbuf_data(data));
3437
3438 // Fillout rx packet
3439 kern_buflet_t rx_buf = kern_packet_get_next_buflet(rx_ph, NULL);
3440 VERIFY(rx_buf != NULL);
f427ee49 3441 void *rx_baddr = kern_buflet_get_data_address(rx_buf);
5c9f4661
A
3442 VERIFY(rx_baddr != NULL);
3443
3444 // Copy-in data from mbuf to buflet
3445 mbuf_copydata(data, 0, length, (void *)rx_baddr);
0a7de745 3446 kern_packet_clear_flow_uuid(rx_ph); // Zero flow id
5c9f4661
A
3447
3448 // Finalize and attach the packet
3449 error = kern_buflet_set_data_offset(rx_buf, 0);
3450 VERIFY(error == 0);
3451 error = kern_buflet_set_data_length(rx_buf, length);
3452 VERIFY(error == 0);
3453 error = kern_packet_finalize(rx_ph);
3454 VERIFY(error == 0);
3455 error = kern_channel_slot_attach_packet(rx_ring, rx_slot, rx_ph);
3456 VERIFY(error == 0);
3457
3458 rx_ring_stats.kcrsi_slots_transferred++;
3459 rx_ring_stats.kcrsi_bytes_transferred += length;
3460
3461 if (!pcb->utun_ext_ifdata_stats) {
3462 ifnet_stat_increment_out(pcb->utun_ifp, 1, length, 0);
3463 }
3464
3465 mbuf_freem(data);
3466
3467 rx_pslot = rx_slot;
3468 rx_slot = kern_channel_get_next_slot(rx_ring, rx_slot, NULL);
3469 }
3470 if (rx_pslot) {
3471 kern_channel_advance_slot(rx_ring, rx_pslot);
3472 kern_channel_increment_ring_stats(rx_ring, &rx_ring_stats);
3473 }
3474 if (mb_head != NULL) {
3475 VERIFY(mb_cnt != 0);
3476 mbuf_freem_list(mb_head);
3477 }
5ba3f43e 3478 }
5ba3f43e
A
3479
3480 return 0;
3481}
39037602 3482
5ba3f43e 3483#endif // UTUN_NEXUS
39037602
A
3484
3485
3486/*
5ba3f43e 3487 * These are place holders until coreTLS kext stops calling them
39037602 3488 */
0a7de745 3489errno_t utun_ctl_register_dtls(void *reg);
39037602
A
3490int utun_pkt_dtls_input(struct utun_pcb *pcb, mbuf_t *pkt, protocol_family_t family);
3491void utun_ctl_disable_crypto_dtls(struct utun_pcb *pcb);
3492
3493errno_t
0a7de745 3494utun_ctl_register_dtls(void *reg)
39037602
A
3495{
3496#pragma unused(reg)
3497 return 0;
3498}
3499
3500int
3501utun_pkt_dtls_input(struct utun_pcb *pcb, mbuf_t *pkt, protocol_family_t family)
3502{
3503#pragma unused(pcb)
3504#pragma unused(pkt)
3505#pragma unused(family)
3506 return 0;
3507}
3508
3509void
3510utun_ctl_disable_crypto_dtls(struct utun_pcb *pcb)
3511{
3512#pragma unused(pcb)
3513}