static errno_t utun_ctl_disconnect( __unused kern_ctl_ref kctlref, __unused u_int32_t unit, void *unitinfo) { struct utun_pcb *pcb = unitinfo; ifnet_t ifp = pcb->utun_ifp; errno_t result = 0; utun_cleanup_crypto(pcb); pcb->utun_ctlref = NULL; pcb->utun_unit = 0; /* * We want to do everything in our power to ensure that the interface * really goes away when the socket is closed. We must remove IP/IPv6 * addresses and detach the protocols. Finally, we can remove and * release the interface. */ utun_cleanup_family(ifp, AF_INET); utun_cleanup_family(ifp, AF_INET6); if ((result = ifnet_detach(ifp)) != 0) { printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result); } if ((result = ifnet_release(ifp)) != 0) { printf("utun_ctl_disconnect - ifnet_release failed: %d\n", result); } return 0; }
static errno_t utun_ctl_disconnect( __unused kern_ctl_ref kctlref, __unused u_int32_t unit, void *unitinfo) { struct utun_pcb *pcb = unitinfo; ifnet_t ifp = NULL; errno_t result = 0; if (pcb == NULL) return EINVAL; ifp = pcb->utun_ifp; VERIFY(ifp != NULL); pcb->utun_ctlref = NULL; pcb->utun_unit = 0; /* * We want to do everything in our power to ensure that the interface * really goes away when the socket is closed. We must remove IP/IPv6 * addresses and detach the protocols. Finally, we can remove and * release the interface. */ utun_cleanup_family(ifp, AF_INET); utun_cleanup_family(ifp, AF_INET6); /* * Detach now; utun_detach() will be called asynchronously once * the I/O reference count drops to 0. There we will invoke * ifnet_release(). */ if ((result = ifnet_detach(ifp)) != 0) { printf("utun_ctl_disconnect - ifnet_detach failed: %d\n", result); } return 0; }