+ return 0;
+}
+
+static errno_t
+utun_ctl_bind(kern_ctl_ref kctlref,
+ struct sockaddr_ctl *sac,
+ void **unitinfo)
+{
+ if (*unitinfo == NULL) {
+ u_int32_t unit = 0;
+ (void)utun_ctl_setup(&unit, unitinfo);
+ }
+
+ struct utun_pcb *pcb = (struct utun_pcb *)*unitinfo;
+ if (pcb == NULL) {
+ return EINVAL;
+ }
+
+ pcb->utun_ctlref = kctlref;
+ pcb->utun_unit = sac->sc_unit;
+ pcb->utun_max_pending_packets = 1;
+
+#if UTUN_NEXUS
+ pcb->utun_use_netif = false;
+ pcb->utun_attach_fsw = true;
+ pcb->utun_netif_connected = false;
+ pcb->utun_slot_size = UTUN_IF_DEFAULT_SLOT_SIZE;
+ pcb->utun_netif_ring_size = if_utun_ring_size;
+ pcb->utun_tx_fsw_ring_size = if_utun_tx_fsw_ring_size;
+ pcb->utun_rx_fsw_ring_size = if_utun_rx_fsw_ring_size;
+ pcb->utun_input_chain_count = 0;
+ lck_mtx_init(&pcb->utun_input_chain_lock, utun_lck_grp, utun_lck_attr);
+#endif // UTUN_NEXUS
+
+ lck_rw_init(&pcb->utun_pcb_lock, utun_lck_grp, utun_lck_attr);
+
+ return 0;
+}
+
+static errno_t
+utun_ctl_connect(kern_ctl_ref kctlref,
+ struct sockaddr_ctl *sac,
+ void **unitinfo)
+{
+ struct ifnet_init_eparams utun_init = {};
+ errno_t result = 0;
+
+ if (*unitinfo == NULL) {
+ (void)utun_ctl_bind(kctlref, sac, unitinfo);
+ }
+
+ struct utun_pcb *pcb = *unitinfo;
+ if (pcb == NULL) {
+ return EINVAL;
+ }
+
+ /* Handle case where utun_ctl_setup() was called, but ipsec_ctl_bind() was not */
+ if (pcb->utun_ctlref == NULL) {
+ (void)utun_ctl_bind(kctlref, sac, unitinfo);
+ }
+