Exemple #1
0
int  vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
{
    NOREF(pvIfData);

    int rc = VINF_SUCCESS;
    ifnet_t pIfNet = vboxNetFltDarwinRetainIfNet(pThis);
    if (pIfNet)
    {
        /*
         * Create a mbuf for the gather list and push it onto the wire.
         *
         * Note! If the interface is in the promiscuous mode we need to send the
         *       packet down the stack so it reaches the driver and Berkeley
         *       Packet Filter (see @bugref{5817}).
         */
        if ((fDst & INTNETTRUNKDIR_WIRE) || vboxNetFltDarwinIsPromiscuous(pThis))
        {
            mbuf_t pMBuf = vboxNetFltDarwinMBufFromSG(pThis, pSG);
            if (pMBuf)
            {
                errno_t err = ifnet_output_raw(pIfNet, PF_LINK, pMBuf);
                if (err)
                    rc = RTErrConvertFromErrno(err);
            }
            else
                rc = VERR_NO_MEMORY;
        }

        /*
         * Create a mbuf for the gather list and push it onto the host stack.
         */
        if (fDst & INTNETTRUNKDIR_HOST)
        {
            mbuf_t pMBuf = vboxNetFltDarwinMBufFromSG(pThis, pSG);
            if (pMBuf)
            {
                /* This is what IONetworkInterface::inputPacket does. */
                unsigned const cbEthHdr = 14;
                mbuf_pkthdr_setheader(pMBuf, mbuf_data(pMBuf));
                mbuf_pkthdr_setlen(pMBuf, mbuf_pkthdr_len(pMBuf) - cbEthHdr);
                mbuf_setdata(pMBuf, (uint8_t *)mbuf_data(pMBuf) + cbEthHdr, mbuf_len(pMBuf) - cbEthHdr);
                mbuf_pkthdr_setrcvif(pMBuf, pIfNet); /* will crash without this. */

                errno_t err = ifnet_input(pIfNet, pMBuf, NULL);
                if (err)
                    rc = RTErrConvertFromErrno(err);
            }
            else
                rc = VERR_NO_MEMORY;
        }

        vboxNetFltDarwinReleaseIfNet(pThis, pIfNet);
    }

    return rc;
}
IOReturn REACConnection::sendSplitAnnouncementPacket() {
    const UInt32 fillerSize = 288;
    const UInt32 fillerOffset = sizeof(EthernetHeader)+sizeof(REACPacketHeader);
    const UInt32 endingOffset = fillerOffset+fillerSize;
    const UInt32 packetLen = endingOffset+sizeof(REACConstants::ENDING);
    REACSplitDataStream *splitDataStream;
    REACPacketHeader rph;
    mbuf_t mbuf = NULL;
    int result = kIOReturnError;

    /// Do some argument checks
    if (!REAC_SPLIT == mode) {
        result = kIOReturnInvalid;
        goto Done;
    }

    /// Prepare REAC packet header
    splitDataStream = OSDynamicCast(REACSplitDataStream, dataStream);
    if (NULL == splitDataStream) {
        IOLog("REACConnection::sendSplitAnnouncementPacket(): Internal error!\n");
        result = kIOReturnInternalError;
        goto Done;
    }
    rph.setCounter(splitAnnouncementCounter++);
    if (!splitDataStream->prepareSplitAnnounce(&rph)) {
        goto Done;
    }

    /// Allocate mbuf
    if (0 != mbuf_allocpacket(MBUF_DONTWAIT, packetLen, NULL, &mbuf) ||
            kIOReturnSuccess != MbufUtils::setChainLength(mbuf, packetLen)) {
        IOLog("REACConnection::sendSplitAnnouncementPacket() - Error: Failed to allocate packet mbuf.\n");
        goto Done;
    }

    /// Copy ethernet header
    EthernetHeader header;
    memcpy(header.shost, interfaceAddr, sizeof(header.shost));
    memcpy(header.dhost, deviceInfo->addr, sizeof(header.dhost));
    memcpy(&header.type, REACConstants::PROTOCOL, sizeof(REACConstants::PROTOCOL));
    if (kIOReturnSuccess != MbufUtils::copyFromBufferToMbuf(mbuf, 0, sizeof(EthernetHeader), &header)) {
        IOLog("REACConnection::sendSplitAnnouncementPacket() - Error: Failed to copy REAC header to packet mbuf.\n");
        goto Done;
    }

    /// Copy REAC header
    if (kIOReturnSuccess != MbufUtils::copyFromBufferToMbuf(mbuf, sizeof(EthernetHeader), sizeof(REACPacketHeader), &rph)) {
        IOLog("REACConnection::sendSplitAnnouncementPacket() - Error: Failed to copy REAC header to packet mbuf.\n");
        goto Done;
    }

    /// Copy filler
    if (kIOReturnSuccess != MbufUtils::zeroMbuf(mbuf, fillerOffset, fillerSize)) {
        IOLog("REACConnection::sendSplitAnnouncementPacket() - Error: Failed to zero filler data in mbuf.\n");
        goto Done;
    }

    /// Copy packet ending
    if (kIOReturnSuccess != MbufUtils::copyFromBufferToMbuf(mbuf, endingOffset,
            sizeof(REACConstants::ENDING), (void *)REACConstants::ENDING)) {
        IOLog("REACConnection::sendSplitAnnouncementPacket() - Error: Failed to copy ending to packet mbuf.\n");
        goto Done;
    }

    /// Send packet
    if (0 != ifnet_output_raw(interface, 0, mbuf)) {
        mbuf = NULL; // ifnet_output_raw always frees the mbuf
        IOLog("REACConnection::sendSplitAnnouncementPacket() - Error: Failed to send packet.\n");
        goto Done;
    }

    mbuf = NULL; // ifnet_output_raw always frees the mbuf
    result = kIOReturnSuccess;
Done:
    if (NULL != mbuf) {
        mbuf_freem(mbuf);
        mbuf = NULL;
    }
    return result;
}
IOReturn REACConnection::sendSamples(UInt32 bufSize, UInt8 *sampleBuffer) {
    REACMasterDataStream *masterDataStream = OSDynamicCast(REACMasterDataStream, dataStream);
    const UInt32 ourSamplesSize = REAC_SAMPLES_PER_PACKET*REAC_RESOLUTION*
                                  (NULL != masterDataStream ?
                                   inChannels : deviceInfo->out_channels);
    // TODO This is not complete
    const UInt32 slaveSamplesSize = (NULL != masterDataStream && masterDataStream->isConnectedToSlave()) ? ourSamplesSize : 0;
    const UInt32 sentSamplesSize = ourSamplesSize+slaveSamplesSize;
    const UInt32 sampleOffset = sizeof(EthernetHeader)+sizeof(REACPacketHeader);
    const UInt32 endingOffset = sampleOffset+sentSamplesSize;
    const UInt32 packetLen = endingOffset+sizeof(REACConstants::ENDING);
    REACPacketHeader rph;
    mbuf_t mbuf = NULL;
    IOReturn result = kIOReturnError;
    IOReturn processPacketRet;

    /// Do some argument checks
    if (!(REAC_SLAVE == mode || REAC_MASTER == mode)) {
        result = kIOReturnInvalid;
        goto Done;
    }
    if (ourSamplesSize != bufSize && NULL != sampleBuffer) { // bufSize is ignored when sampleBuffer is NULL
        result = kIOReturnBadArgument;
        goto Done;
    }

    /// Prepare ethernet header
    EthernetHeader header;
    memcpy(header.shost, interfaceAddr, sizeof(header.shost));
    // Don't initialize header.dhost; that's the responsibility of dataStream->processPacket
    memcpy(&header.type, REACConstants::PROTOCOL, sizeof(REACConstants::PROTOCOL));

    /// Do REAC data stream processing
    processPacketRet = dataStream->processPacket(&rph, sizeof(header.dhost), header.dhost);
    if (kIOReturnAborted == processPacketRet) {
        // The REACDataStream indicates to us that it doesn't want us to send a packet.
        goto Done;
    }
    else if (kIOReturnSuccess != processPacketRet) {
        IOLog("REACConnection::sendSamples() - Error: Failed to process packet data stream.\n");
        goto Done;
    }

    /// Allocate mbuf
    if (0 != mbuf_allocpacket(MBUF_DONTWAIT, packetLen, NULL, &mbuf) ||
            kIOReturnSuccess != MbufUtils::setChainLength(mbuf, packetLen)) {
        IOLog("REACConnection::sendSamples() - Error: Failed to allocate packet mbuf.\n");
        goto Done;
    }

    /// Copy ethernet header
    if (kIOReturnSuccess != MbufUtils::copyFromBufferToMbuf(mbuf, 0, sizeof(EthernetHeader), &header)) {
        IOLog("REACConnection::sendSamples() - Error: Failed to copy REAC header to packet mbuf.\n");
        goto Done;
    }

    /// Copy REAC header
    if (kIOReturnSuccess != MbufUtils::copyFromBufferToMbuf(mbuf, sizeof(EthernetHeader), sizeof(REACPacketHeader), &rph)) {
        IOLog("REACConnection::sendSamples() - Error: Failed to copy REAC header to packet mbuf.\n");
        goto Done;
    }

    /// Copy sample data
    if (NULL != sampleBuffer) {
        if (kIOReturnSuccess != MbufUtils::copyAudioFromBufferToMbuf(mbuf, sampleOffset, bufSize, sampleBuffer)) {
            IOLog("REACConnection::sendSamples() - Error: Failed to copy sample data to packet mbuf.\n");
            goto Done;
        }
    }
    else {
        if (kIOReturnSuccess != MbufUtils::zeroMbuf(mbuf, sampleOffset, ourSamplesSize)) {
            IOLog("REACConnection::sendSamples() - Error: Failed to zero sample data in mbuf.\n");
            goto Done;
        }
    }
    if (NULL != masterDataStream && masterDataStream->isConnectedToSlave()) {
        // TODO This is very incorrect: It doesn't send the slave data, and even if it would, the order of the
        // data would be jumbled, because it has to send the whole first sample first and so on.
        if (kIOReturnSuccess != MbufUtils::zeroMbuf(mbuf, sampleOffset+ourSamplesSize, slaveSamplesSize)) {
            IOLog("REACConnection::sendSamples() - Error: Failed to zero slave sample data in mbuf.\n");
            goto Done;
        }
    }

    /// Copy packet ending
    if (kIOReturnSuccess != MbufUtils::copyFromBufferToMbuf(mbuf, endingOffset,
            sizeof(REACConstants::ENDING), (void *)REACConstants::ENDING)) {
        IOLog("REACConnection::sendSamples() - Error: Failed to copy ending to packet mbuf.\n");
        goto Done;
    }

    /// Send packet
    if (0 != ifnet_output_raw(interface, 0, mbuf)) {
        mbuf = NULL; // ifnet_output_raw always frees the mbuf
        IOLog("REACConnection::sendSamples() - Error: Failed to send packet.\n");
        goto Done;
    }

    mbuf = NULL; // ifnet_output_raw always frees the mbuf
    result = kIOReturnSuccess;
Done:
    if (NULL != mbuf) {
        mbuf_freem(mbuf);
        mbuf = NULL;
    }
    return result;
}
Exemple #4
0
errno_t
firewire_inet_arp(
    ifnet_t								ifp,
    u_short								arpop,
    const struct sockaddr_dl*			sender_hw,
    const struct sockaddr*				sender_proto,
    const struct sockaddr_dl*			target_hw,
    const struct sockaddr*				target_proto)
{
    mbuf_t	m;
    errno_t	result;
    register struct firewire_header *fwh;
    register IP1394_ARP *fwa;
    const struct sockaddr_in* sender_ip = (const struct sockaddr_in*)sender_proto;
    const struct sockaddr_in* target_ip = (const struct sockaddr_in*)target_proto;
    char *datap;

    IOFWInterface *fwIf	   = (IOFWInterface*)ifnet_softc(ifp);

    if(fwIf == NULL)
        return EINVAL;

    IOFireWireIP  *fwIpObj = (IOFireWireIP*)fwIf->getController();

    if(fwIpObj == NULL)
        return EINVAL;

    LCB	*lcb = fwIpObj->getLcb();

    if (target_ip == NULL)
        return EINVAL;

    if ((sender_ip && sender_ip->sin_family != AF_INET) ||
            (target_ip && target_ip->sin_family != AF_INET))
        return EAFNOSUPPORT;

    result = mbuf_gethdr(MBUF_DONTWAIT, MBUF_TYPE_DATA, &m);
    if (result != 0)
        return result;

    mbuf_setlen(m, sizeof(*fwa));
    mbuf_pkthdr_setlen(m, sizeof(*fwa));

    /* Move the data pointer in the mbuf to the end, aligned to 4 bytes */
    datap = (char*)mbuf_datastart(m);
    datap += mbuf_trailingspace(m);
    datap -= (((u_long)datap) & 0x3);
    mbuf_setdata(m, datap, sizeof(*fwa));
    fwa = (IP1394_ARP*)mbuf_data(m);
    bzero((caddr_t)fwa, sizeof(*fwa));

    /* Prepend the ethernet header, we will send the raw frame */
    result = mbuf_prepend(&m, sizeof(*fwh), MBUF_DONTWAIT);
    if(result != 0)
        return result;

    fwh = (struct firewire_header*)mbuf_data(m);
    fwh->fw_type = htons(FWTYPE_ARP);

    /* Fill out the arp packet */
    fwa->hardwareType = htons(ARP_HDW_TYPE);
    fwa->protocolType = htons(FWTYPE_IP);
    fwa->hwAddrLen = sizeof(IP1394_HDW_ADDR);
    fwa->ipAddrLen = IPV4_ADDR_SIZE;
    fwa->opcode = htons(arpop);
    fwa->senderMaxRec = lcb->ownHardwareAddress.maxRec;
    fwa->sspd = lcb->ownHardwareAddress.spd;
    fwa->senderUnicastFifoHi = htons(lcb->ownHardwareAddress.unicastFifoHi);
    fwa->senderUnicastFifoLo = htonl(lcb->ownHardwareAddress.unicastFifoLo);

    /* Sender Hardware */
    if (sender_hw != NULL)
        bcopy(CONST_LLADDR(sender_hw), &fwa->senderUniqueID, sizeof(fwa->senderUniqueID));
    else
        ifnet_lladdr_copy_bytes(ifp, &fwa->senderUniqueID, FIREWIRE_ADDR_LEN);

    ifnet_lladdr_copy_bytes(ifp, fwh->fw_shost, sizeof(fwh->fw_shost));

    /* Sender IP */
    if (sender_ip != NULL)
        fwa->senderIpAddress = sender_ip->sin_addr.s_addr;
    else
    {
        ifaddr_t	*addresses;
        struct sockaddr sa;

        if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0)
        {
            ifaddr_address( addresses[0], &sa, 16 );
            fwa->senderIpAddress  = ((UInt32)(sa.sa_data[5] & 0xFF)) << 24;
            fwa->senderIpAddress |= ((UInt32)(sa.sa_data[4] & 0xFF)) << 16;
            fwa->senderIpAddress |= ((UInt32)(sa.sa_data[3] & 0xFF)) << 8;
            fwa->senderIpAddress |= ((UInt32)(sa.sa_data[2] & 0xFF));

            ifnet_free_address_list(addresses);
        }
        else
        {
            mbuf_free(m);
            return ENXIO;
        }
    }

    /* Target Hardware */
    if (target_hw == 0)
        bcopy(fwbroadcastaddr, fwh->fw_dhost, sizeof(fwh->fw_dhost));
    else
        bcopy(CONST_LLADDR(target_hw), fwh->fw_dhost, sizeof(fwh->fw_dhost));

    /* Target IP */
    fwa->targetIpAddress = target_ip->sin_addr.s_addr;

    ifnet_output_raw(ifp, PF_INET, m);

    return 0;
}