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; }
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; }