Пример #1
0
IOReturn darwin_iwi3945::disable( IONetworkInterface * netif )
{
	IWI_DEBUG("ifconfig down\n");
	if ((fNetif->getFlags() & IFF_RUNNING)!=0)
	{
		IWI_DEBUG("ifconfig going down\n");
		//super::disable(fNetif);
		//fNetif->setPoweredOnByUser(false);
		fTransmitQueue->stop();
		setLinkStatus(kIONetworkLinkValid);
		//fNetif->setLinkState(kIO80211NetworkLinkDown);
		//fNetif->syncSIOCSIFFLAGS( /*IONetworkController * */this);
		//(if_flags & ~mask) | (new_flags & mask) if mask has IFF_UP if_updown fires up (kpi_interface.c in xnu)
		ifnet_set_flags(fifnet, 0 , IFF_RUNNING );
		
		
		fTransmitQueue->setCapacity(0);
		fTransmitQueue->flush();
				
		//if ((priv->status & STATUS_AUTH)) enable(fNetif);
		
		return kIOReturnSuccess;
		
	}
	else
	{
		IWI_DEBUG("ifconfig already down\n");
		return -1;
	}

}
Пример #2
0
static errno_t
ether_inet6_prmod_ioctl(ifnet_t ifp, protocol_family_t protocol_family,
    u_long command, void *data)
{
#pragma unused(protocol_family)
	int error = 0;

	switch (command) {
	case SIOCSIFADDR:		/* struct ifaddr pointer */
		/*
		 * Note: caller of ifnet_ioctl() passes in pointer to
		 * struct ifaddr as parameter to SIOCSIFADDR, for legacy
		 * reasons.
		 */
		if ((ifp->if_flags & IFF_RUNNING) == 0) {
			ifnet_set_flags(ifp, IFF_UP, IFF_UP);
			ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
		}
		break;

	case SIOCGIFADDR: {		/* struct ifreq */
		struct ifreq *ifr = (struct ifreq *)(void *)data;
		(void) ifnet_guarded_lladdr_copy_bytes(ifp,
		    ifr->ifr_addr.sa_data, ETHER_ADDR_LEN);
		break;
	}

	default:
		error = EOPNOTSUPP;
		break;
	}
	return (error);
}
Пример #3
0
void vboxNetAdpOsDestroy(PVBOXNETADP pThis)
{
    u_int32_t i;
    /* Bring down the interface */
    int rc = VINF_SUCCESS;
    errno_t err;

    AssertPtr(pThis->u.s.pIface);
    Assert(pThis->u.s.hEvtDetached != NIL_RTSEMEVENT);

    err = ifnet_set_flags(pThis->u.s.pIface, 0, IFF_UP | IFF_RUNNING);
    if (err)
        Log(("vboxNetAdpDarwinUnregisterDevice: Failed to bring down interface "
             "(err=%d).\n", err));
    /* Detach all protocols. */
    for (i = 0; i < VBOXNETADP_MAX_FAMILIES; i++)
        if (pThis->u.s.aAttachedFamilies[i])
            ifnet_detach_protocol(pThis->u.s.pIface, pThis->u.s.aAttachedFamilies[i]);
    err = ifnet_detach(pThis->u.s.pIface);
    if (err)
        Log(("vboxNetAdpDarwinUnregisterDevice: Failed to detach interface "
             "(err=%d).\n", err));
    Log2(("vboxNetAdpDarwinUnregisterDevice: Waiting for 'detached' event...\n"));
    /* Wait until we get a signal from detach callback. */
    rc = RTSemEventWait(pThis->u.s.hEvtDetached, VBOXNETADP_DETACH_TIMEOUT);
    if (rc == VERR_TIMEOUT)
        LogRel(("VBoxAdpDrv: Failed to detach interface %s%d\n.",
                VBOXNETADP_NAME, pThis->iUnit));
    err = ifnet_release(pThis->u.s.pIface);
    if (err)
        Log(("vboxNetAdpUnregisterDevice: Failed to release interface (err=%d).\n", err));

    RTSemEventDestroy(pThis->u.s.hEvtDetached);
    pThis->u.s.hEvtDetached = NIL_RTSEMEVENT;
}
Пример #4
0
static errno_t
pflogioctl(struct ifnet *ifp, unsigned long cmd, void *data)
{
#pragma unused(data)
	switch (cmd) {
	case SIOCSIFADDR:
	case SIOCAIFADDR:
	case SIOCSIFDSTADDR:
	case SIOCSIFFLAGS:
		if (ifnet_flags(ifp) & IFF_UP)
			ifnet_set_flags(ifp, IFF_RUNNING, IFF_RUNNING);
		else
			ifnet_set_flags(ifp, 0, IFF_RUNNING);
		break;
	default:
		return (ENOTTY);
	}

	return (0);
}
Пример #5
0
IOReturn darwin_iwi3945::enable( IONetworkInterface * netif ) 
{
	if (!fifnet)
	{
		char ii[4];
		sprintf(ii,"%s%d" ,fNetif->getNamePrefix(), fNetif->getUnitNumber());
		ifnet_find_by_name(ii,&fifnet);
		IWI_DEBUG("ifnet_t %s%d = %x\n",ifnet_name(fifnet),ifnet_unit(fifnet),fifnet);
		struct ieee80211_local* loc=hw_to_local(priv->hw);
		memcpy(&loc->mdev->name,ii,sizeof(ii));
		loc->mdev->ifindex=fNetif->getUnitNumber();
		priv->interface_id=fNetif->getUnitNumber();
	}
	if (firstifup==0)
	{
		firstifup=1;
		return -1;
	}
	
	IWI_DEBUG("ifconfig up\n");
	if ((fNetif->getFlags() & IFF_RUNNING)==0)
	{
		IWI_DEBUG("ifconfig going up\n ");
		
		//super::enable(fNetif);
		//fNetif->setPoweredOnByUser(true);
		//fNetif->setLinkState(kIO80211NetworkLinkUp);

		//(if_flags & ~mask) | (new_flags & mask) if mask has IFF_UP if_updown fires up (kpi_interface.c in xnu)	
		if (priv->status & STATUS_AUTH) ifnet_set_flags(fifnet, IFF_RUNNING, IFF_RUNNING );
		//fNetif->inputEvent(kIONetworkEventTypeLinkUp,NULL);
		fTransmitQueue->setCapacity(1024);
		fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync);
		fTransmitQueue->start();
		return kIOReturnSuccess;
	}
	else
	{
		IWI_DEBUG("ifconfig already up\n");
		return kIOReturnExclusiveAccess;

	}

}
Пример #6
0
static int
pflog_clone_create(struct if_clone *ifc, u_int32_t unit, __unused void *params)
{
	struct pflog_softc *pflogif;
	struct ifnet_init_eparams pf_init;
	int error = 0;

	if (unit >= PFLOGIFS_MAX) {
		/* Either the interface cloner or our initializer is broken */
		panic("%s: unit (%d) exceeds max (%d)", __func__, unit,
		    PFLOGIFS_MAX);
		/* NOTREACHED */
	}

	if ((pflogif = if_clone_softc_allocate(&pflog_cloner)) == NULL) {
		error = ENOMEM;
		goto done;
	}

	bzero(&pf_init, sizeof (pf_init));
	pf_init.ver = IFNET_INIT_CURRENT_VERSION;
	pf_init.len = sizeof (pf_init);
	pf_init.flags = IFNET_INIT_LEGACY;
	pf_init.name = ifc->ifc_name;
	pf_init.unit = unit;
	pf_init.type = IFT_PFLOG;
	pf_init.family = IFNET_FAMILY_LOOPBACK;
	pf_init.output = pflogoutput;
	pf_init.demux = pflogdemux;
	pf_init.add_proto = pflogaddproto;
	pf_init.del_proto = pflogdelproto;
	pf_init.softc = pflogif;
	pf_init.ioctl = pflogioctl;
	pf_init.detach = pflogfree;

	bzero(pflogif, sizeof (*pflogif));
	pflogif->sc_unit = unit;
	pflogif->sc_flags |= IFPFLF_DETACHING;

	error = ifnet_allocate_extended(&pf_init, &pflogif->sc_if);
	if (error != 0) {
		printf("%s: ifnet_allocate failed - %d\n", __func__, error);
		if_clone_softc_deallocate(&pflog_cloner, pflogif);
		goto done;
	}

	ifnet_set_mtu(pflogif->sc_if, PFLOGMTU);
	ifnet_set_flags(pflogif->sc_if, IFF_UP, IFF_UP);

	error = ifnet_attach(pflogif->sc_if, NULL);
	if (error != 0) {
		printf("%s: ifnet_attach failed - %d\n", __func__, error);
		ifnet_release(pflogif->sc_if);
		if_clone_softc_deallocate(&pflog_cloner, pflogif);
		goto done;
	}

#if NBPFILTER > 0
	bpfattach(pflogif->sc_if, DLT_PFLOG, PFLOG_HDRLEN);
#endif

	lck_rw_lock_shared(pf_perim_lock);
	lck_mtx_lock(pf_lock);
	LIST_INSERT_HEAD(&pflogif_list, pflogif, sc_list);
	pflogifs[unit] = pflogif->sc_if;
	pflogif->sc_flags &= ~IFPFLF_DETACHING;
	lck_mtx_unlock(pf_lock);
	lck_rw_done(pf_perim_lock);

done:
	return (error);
}
Пример #7
0
int vboxNetAdpOsCreate(PVBOXNETADP pThis, PCRTMAC pMACAddress)
{
    int rc;
    struct ifnet_init_params Params;
    RTUUID uuid;
    struct sockaddr_dl mac;

    pThis->u.s.hEvtDetached = NIL_RTSEMEVENT;
    rc = RTSemEventCreate(&pThis->u.s.hEvtDetached);
    if (RT_FAILURE(rc))
    {
        printf("vboxNetAdpOsCreate: failed to create semaphore (rc=%d).\n", rc);
        return rc;
    }

    pThis->u.s.nTapMode = BPF_MODE_DISABLED;

    mac.sdl_len = sizeof(mac);
    mac.sdl_family = AF_LINK;
    mac.sdl_alen = ETHER_ADDR_LEN;
    mac.sdl_nlen = 0;
    mac.sdl_slen = 0;
    memcpy(LLADDR(&mac), pMACAddress->au8, mac.sdl_alen);

    RTStrPrintf(pThis->szName, VBOXNETADP_MAX_NAME_LEN, "%s%d", VBOXNETADP_NAME, pThis->iUnit);
    vboxNetAdpDarwinComposeUUID(pThis, &uuid);
    Params.uniqueid = uuid.au8;
    Params.uniqueid_len = sizeof(uuid);
    Params.name = VBOXNETADP_NAME;
    Params.unit = pThis->iUnit;
    Params.family = IFNET_FAMILY_ETHERNET;
    Params.type = IFT_ETHER;
    Params.output = vboxNetAdpDarwinOutput;
    Params.demux = vboxNetAdpDarwinDemux;
    Params.add_proto = vboxNetAdpDarwinAddProto;
    Params.del_proto = vboxNetAdpDarwinDelProto;
    Params.check_multi = ether_check_multi;
    Params.framer = ether_frameout;
    Params.softc = pThis;
    Params.ioctl = (ifnet_ioctl_func)ether_ioctl;
    Params.set_bpf_tap = NULL;
    Params.detach = vboxNetAdpDarwinDetach;
    Params.event = NULL;
    Params.broadcast_addr = "\xFF\xFF\xFF\xFF\xFF\xFF";
    Params.broadcast_len = ETHER_ADDR_LEN;

    errno_t err = ifnet_allocate(&Params, &pThis->u.s.pIface);
    if (!err)
    {
        err = ifnet_attach(pThis->u.s.pIface, &mac);
        if (!err)
        {
            err = bpf_attach(pThis->u.s.pIface, DLT_EN10MB, ETHER_HDR_LEN,
                      vboxNetAdpDarwinBpfSend, vboxNetAdpDarwinBpfTap);
            if (err)
            {
                LogRel(("vboxnetadp: bpf_attach failed with %d\n", err));
            }
            err = ifnet_set_flags(pThis->u.s.pIface, IFF_RUNNING | IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST, 0xFFFF);
            if (!err)
            {
                ifnet_set_mtu(pThis->u.s.pIface, VBOXNETADP_MTU);
                return VINF_SUCCESS;
            }
            else
                Log(("vboxNetAdpDarwinRegisterDevice: Failed to set flags (err=%d).\n", err));
            ifnet_detach(pThis->u.s.pIface);
        }
        else
            Log(("vboxNetAdpDarwinRegisterDevice: Failed to attach to interface (err=%d).\n", err));
        ifnet_release(pThis->u.s.pIface);
    }
    else
        Log(("vboxNetAdpDarwinRegisterDevice: Failed to allocate interface (err=%d).\n", err));

    RTSemEventDestroy(pThis->u.s.hEvtDetached);
    pThis->u.s.hEvtDetached = NIL_RTSEMEVENT;

    return RTErrConvertFromErrno(err);
}
Пример #8
0
static errno_t
utun_ctl_connect(
	kern_ctl_ref		kctlref,
	struct sockaddr_ctl	*sac, 
	void				**unitinfo)
{
	struct ifnet_init_eparams	utun_init;
	struct utun_pcb				*pcb;
	errno_t						result;
	struct ifnet_stats_param 	stats;
	
	/* kernel control allocates, interface frees */
	pcb = utun_alloc(sizeof(*pcb));
	if (pcb == NULL)
		return ENOMEM;
	
	/* Setup the protocol control block */
	bzero(pcb, sizeof(*pcb));
	*unitinfo = pcb;
	pcb->utun_ctlref = kctlref;
	pcb->utun_unit = sac->sc_unit;
	
	printf("utun_ctl_connect: creating interface utun%d\n", pcb->utun_unit - 1);

	/* Create the interface */
	bzero(&utun_init, sizeof(utun_init));
	utun_init.ver = IFNET_INIT_CURRENT_VERSION;
	utun_init.len = sizeof (utun_init);
	utun_init.flags = IFNET_INIT_LEGACY;
	utun_init.name = "utun";
	utun_init.unit = pcb->utun_unit - 1;
	utun_init.family = utun_family;
	utun_init.type = IFT_OTHER;
	utun_init.output = utun_output;
	utun_init.demux = utun_demux;
	utun_init.framer_extended = utun_framer;
	utun_init.add_proto = utun_add_proto;
	utun_init.del_proto = utun_del_proto;
	utun_init.softc = pcb;
	utun_init.ioctl = utun_ioctl;
	utun_init.detach = utun_detached;
	
	result = ifnet_allocate_extended(&utun_init, &pcb->utun_ifp);
	if (result != 0) {
		printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result);
		utun_free(pcb);
		return result;
	}
	OSIncrementAtomic(&utun_ifcount);
	
	/* Set flags and additional information. */
	ifnet_set_mtu(pcb->utun_ifp, 1500);
	ifnet_set_flags(pcb->utun_ifp, IFF_UP | IFF_MULTICAST | IFF_POINTOPOINT, 0xffff);

	/* The interface must generate its own IPv6 LinkLocal address,
	 * if possible following the recommendation of RFC2472 to the 64bit interface ID
	 */
	ifnet_set_eflags(pcb->utun_ifp, IFEF_NOAUTOIPV6LL, IFEF_NOAUTOIPV6LL);
	
	/* Reset the stats in case as the interface may have been recycled */
	bzero(&stats, sizeof(struct ifnet_stats_param));
	ifnet_set_stat(pcb->utun_ifp, &stats);

	/* Attach the interface */
	result = ifnet_attach(pcb->utun_ifp, NULL);
	if (result != 0) {
		printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result);
		ifnet_release(pcb->utun_ifp);
		utun_free(pcb);
	}
	
	/* Attach to bpf */
	if (result == 0)
		bpfattach(pcb->utun_ifp, DLT_NULL, 4);
	
	/* The interfaces resoures allocated, mark it as running */
	if (result == 0)
		ifnet_set_flags(pcb->utun_ifp, IFF_RUNNING, IFF_RUNNING);
	
	return result;
}
Пример #9
0
static errno_t
utun_ctl_connect(
	kern_ctl_ref		kctlref,
	struct sockaddr_ctl	*sac, 
	void				**unitinfo)
{
	struct ifnet_init_eparams	utun_init;
	struct utun_pcb				*pcb;
	errno_t						result;
	struct ifnet_stats_param 	stats;
	
	/* kernel control allocates, interface frees */
	MALLOC(pcb, struct utun_pcb *, sizeof(*pcb), M_DEVBUF, M_WAITOK | M_ZERO);

	*unitinfo = pcb;
	pcb->utun_ctlref = kctlref;
	pcb->utun_unit = sac->sc_unit;
	pcb->utun_max_pending_packets = 1;
	
	printf("utun_ctl_connect: creating interface utun%d\n", pcb->utun_unit - 1);

	/* Create the interface */
	bzero(&utun_init, sizeof(utun_init));
	utun_init.ver = IFNET_INIT_CURRENT_VERSION;
	utun_init.len = sizeof (utun_init);
	utun_init.name = "utun";
	utun_init.start = utun_start;
	utun_init.unit = pcb->utun_unit - 1;
	utun_init.family = utun_family;
	utun_init.subfamily = IFNET_SUBFAMILY_UTUN;
	utun_init.type = IFT_OTHER;
	utun_init.demux = utun_demux;
	utun_init.framer_extended = utun_framer;
	utun_init.add_proto = utun_add_proto;
	utun_init.del_proto = utun_del_proto;
	utun_init.softc = pcb;
	utun_init.ioctl = utun_ioctl;
	utun_init.detach = utun_detached;

	/*
	 * Upon success, this holds an ifnet reference which we will
	 * release via ifnet_release() at final detach time.
	 */
	result = ifnet_allocate_extended(&utun_init, &pcb->utun_ifp);
	if (result != 0) {
		printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result);
		*unitinfo = NULL;
		FREE(pcb, M_DEVBUF);
		return result;
	}
	
	/* Set flags and additional information. */
	ifnet_set_mtu(pcb->utun_ifp, UTUN_DEFAULT_MTU);
	ifnet_set_flags(pcb->utun_ifp, IFF_UP | IFF_MULTICAST | IFF_POINTOPOINT, 0xffff);

	/* The interface must generate its own IPv6 LinkLocal address,
	 * if possible following the recommendation of RFC2472 to the 64bit interface ID
	 */
	ifnet_set_eflags(pcb->utun_ifp, IFEF_NOAUTOIPV6LL, IFEF_NOAUTOIPV6LL);
	
	/* Reset the stats in case as the interface may have been recycled */
	bzero(&stats, sizeof(struct ifnet_stats_param));
	ifnet_set_stat(pcb->utun_ifp, &stats);

	/* Attach the interface */
	result = ifnet_attach(pcb->utun_ifp, NULL);
	if (result != 0) {
		printf("utun_ctl_connect - ifnet_allocate failed: %d\n", result);
		/* Release reference now since attach failed */
		ifnet_release(pcb->utun_ifp);
		*unitinfo = NULL;
		FREE(pcb, M_DEVBUF);
	} else {
		/* Attach to bpf */
		bpfattach(pcb->utun_ifp, DLT_NULL, UTUN_HEADER_SIZE(pcb));
		/* The interfaces resoures allocated, mark it as running */
		ifnet_set_flags(pcb->utun_ifp, IFF_RUNNING, IFF_RUNNING);
	}
	return result;
}
Пример #10
0
/**
 *
 * @see iff_event_func in the darwin kpi.
 */
static void vboxNetFltDarwinIffEvent(void *pvThis, ifnet_t pIfNet, protocol_family_t eProtocol, const struct kev_msg *pEvMsg)
{
    PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)pvThis;
    LogFlow(("vboxNetFltDarwinIffEvent: pThis=%p\n", pThis));

    NOREF(pThis);
    NOREF(pIfNet);
    NOREF(eProtocol);
    NOREF(pEvMsg);

    /*
     * Watch out for the interface going online / offline.
     */
    if (    VALID_PTR(pThis)
        &&  VALID_PTR(pEvMsg)
        &&  pEvMsg->vendor_code  == KEV_VENDOR_APPLE
        &&  pEvMsg->kev_class    == KEV_NETWORK_CLASS
        &&  pEvMsg->kev_subclass == KEV_DL_SUBCLASS)
    {
        if (pThis->u.s.pIfNet    == pIfNet)
        {
            if (pEvMsg->event_code == KEV_DL_LINK_ON)
            {
                if (ASMAtomicUoReadBool(&pThis->u.s.fNeedSetPromiscuous))
                {
                    /* failed to bring it online. */
                    errno_t err = ifnet_set_promiscuous(pIfNet, 1);
                    if (!err)
                    {
                        ASMAtomicWriteBool(&pThis->u.s.fSetPromiscuous, true);
                        ASMAtomicWriteBool(&pThis->u.s.fNeedSetPromiscuous, false);
                        Log(("vboxNetFltDarwinIffEvent: enabled promiscuous mode on %s (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pIfNet)));
                    }
                    else
                        Log(("vboxNetFltDarwinIffEvent: ifnet_set_promiscuous failed on %s, err=%d (%d)\n", pThis->szName, err, VBOX_GET_PCOUNT(pIfNet)));
                }
                else if (   ASMAtomicUoReadBool(&pThis->u.s.fSetPromiscuous)
                         && !(ifnet_flags(pIfNet) & IFF_PROMISC))
                {
                    /* Try fix the inconsistency. */
                    errno_t err = ifnet_set_flags(pIfNet, IFF_PROMISC, IFF_PROMISC);
                    if (!err)
                        err = ifnet_ioctl(pIfNet, 0, SIOCSIFFLAGS, NULL);
                    if (!err && (ifnet_flags(pIfNet) & IFF_PROMISC))
                        Log(("vboxNetFltDarwinIffEvent: fixed IFF_PROMISC on %s (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pIfNet)));
                    else
                        Log(("vboxNetFltDarwinIffEvent: failed to fix IFF_PROMISC on %s, err=%d flags=%#x (%d)\n",
                             pThis->szName, err, ifnet_flags(pIfNet), VBOX_GET_PCOUNT(pIfNet)));
                }
                else
                    Log(("vboxNetFltDarwinIffEvent: online, '%s'. flags=%#x (%d)\n", pThis->szName, ifnet_flags(pIfNet), VBOX_GET_PCOUNT(pIfNet)));
            }
            else if (pEvMsg->event_code == KEV_DL_LINK_OFF)
                Log(("vboxNetFltDarwinIffEvent: %s goes down (%d)\n", pThis->szName, VBOX_GET_PCOUNT(pIfNet)));
/** @todo KEV_DL_LINK_ADDRESS_CHANGED  -> pfnReportMacAddress */
/** @todo KEV_DL_SIFFLAGS              -> pfnReportPromiscuousMode */
        }
        else
            Log(("vboxNetFltDarwinIffEvent: pThis->u.s.pIfNet=%p pIfNet=%p (%d)\n", pThis->u.s.pIfNet, pIfNet, VALID_PTR(pIfNet) ? VBOX_GET_PCOUNT(pIfNet) : -1));
    }
    else if (VALID_PTR(pEvMsg))
        Log(("vboxNetFltDarwinIffEvent: vendor_code=%#x kev_class=%#x kev_subclass=%#x event_code=%#x\n",
             pEvMsg->vendor_code, pEvMsg->kev_class, pEvMsg->kev_subclass, pEvMsg->event_code));
}
Пример #11
0
void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
{
    ifnet_t pIfNet = vboxNetFltDarwinRetainIfNet(pThis);
    if (pIfNet)
    {
        if (pThis->fDisablePromiscuous)
        {
            /*
             * Promiscuous mode should not be used (wireless), we just need to
             * make sure the interface is up.
             */
            if (fActive)
            {
                u_int16_t fIf = ifnet_flags(pIfNet);
                if ((fIf & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING))
                {
                    ifnet_set_flags(pIfNet, IFF_UP, IFF_UP);
                    ifnet_ioctl(pIfNet, 0, SIOCSIFFLAGS, NULL);
                }
            }
        }
        else
        {
            /*
             * This api is a bit weird, the best reference is the code.
             *
             * Also, we have a bit or race conditions wrt the maintenance of
             * host the interface promiscuity for vboxNetFltPortOsIsPromiscuous.
             */
            unsigned const cPromiscBefore = VBOX_GET_PCOUNT(pIfNet);
            u_int16_t fIf;
            if (fActive)
            {
                Assert(!pThis->u.s.fSetPromiscuous);
                errno_t err = ENETDOWN;
                ASMAtomicWriteBool(&pThis->u.s.fNeedSetPromiscuous, true);

                /*
                 * Try bring the interface up and running if it's down.
                 */
                fIf = ifnet_flags(pIfNet);
                if ((fIf & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING))
                {
                    err = ifnet_set_flags(pIfNet, IFF_UP, IFF_UP);
                    errno_t err2 = ifnet_ioctl(pIfNet, 0, SIOCSIFFLAGS, NULL);
                    if (!err)
                        err = err2;
                    fIf = ifnet_flags(pIfNet);
                }

                /*
                 * Is it already up?  If it isn't, leave it to the link event or
                 * we'll upset if_pcount (as stated above, ifnet_set_promiscuous is weird).
                 */
                if ((fIf & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
                {
                    err = ifnet_set_promiscuous(pIfNet, 1);
                    pThis->u.s.fSetPromiscuous = err == 0;
                    if (!err)
                    {
                        ASMAtomicWriteBool(&pThis->u.s.fNeedSetPromiscuous, false);

                        /* check if it actually worked, this stuff is not always behaving well. */
                        if (!(ifnet_flags(pIfNet) & IFF_PROMISC))
                        {
                            err = ifnet_set_flags(pIfNet, IFF_PROMISC, IFF_PROMISC);
                            if (!err)
                                err = ifnet_ioctl(pIfNet, 0, SIOCSIFFLAGS, NULL);
                            if (!err)
                                Log(("vboxNetFlt: fixed IFF_PROMISC on %s (%d->%d)\n", pThis->szName, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet)));
                            else
                                Log(("VBoxNetFlt: failed to fix IFF_PROMISC on %s, err=%d (%d->%d)\n",
                                     pThis->szName, err, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet)));
                        }
                    }
                    else
                        Log(("VBoxNetFlt: ifnet_set_promiscuous -> err=%d grr! (%d->%d)\n", err, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet)));
                }
                else if (!err)
                    Log(("VBoxNetFlt: Waiting for the link to come up... (%d->%d)\n", cPromiscBefore, VBOX_GET_PCOUNT(pIfNet)));
                if (err)
                    LogRel(("VBoxNetFlt: Failed to put '%s' into promiscuous mode, err=%d (%d->%d)\n", pThis->szName, err, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet)));
            }
            else
            {
                ASMAtomicWriteBool(&pThis->u.s.fNeedSetPromiscuous, false);
                if (pThis->u.s.fSetPromiscuous)
                {
                    errno_t err = ifnet_set_promiscuous(pIfNet, 0);
                    AssertMsg(!err, ("%d\n", err)); NOREF(err);
                }
                pThis->u.s.fSetPromiscuous = false;

                fIf = ifnet_flags(pIfNet);
                Log(("VBoxNetFlt: fIf=%#x; %d->%d\n", fIf, cPromiscBefore, VBOX_GET_PCOUNT(pIfNet)));
            }
        }

        vboxNetFltDarwinReleaseIfNet(pThis, pIfNet);
    }
}