Ejemplo n.º 1
0
void net_habitue_device_SC101::resolve()
{
  KDEBUG("resolving");
  clock_get_uptime(&_lastResolve);
  
  sockaddr_in addr;
  bzero(&addr, sizeof(addr));
  addr.sin_len = sizeof(addr);
  addr.sin_family = AF_INET;
  addr.sin_port = htons(PSAN_PORT);
  addr.sin_addr.s_addr = INADDR_BROADCAST;

  psan_resolve_t req;
  bzero(&req, sizeof(req));
  req.ctrl.cmd = PSAN_RESOLVE;
  req.ctrl.seq = ((net_habitue_driver_SC101 *)getProvider())->getSequenceNumber();
  strncpy(req.id, getID()->getCStringNoCopy(), sizeof(req.id));
  
  outstanding *out = IONewZero(outstanding, 1);
  out->seq = ntohs(req.ctrl.seq);
  out->len = sizeof(psan_resolve_response_t);
  out->cmd = PSAN_RESOLVE_RESPONSE;
  out->packetHandler = OSMemberFunctionCast(PacketHandler, this, &net_habitue_device_SC101::handleResolvePacket);
  out->timeoutHandler = OSMemberFunctionCast(TimeoutHandler, this, &net_habitue_device_SC101::handleResolveTimeout);
  out->target = this;
  out->timeout_ms = RESOLVE_TIMEOUT_MS;
  
  mbuf_t m;

  if (mbuf_allocpacket(MBUF_WAITOK, sizeof(psan_resolve_t), NULL, &m) != 0)
    KINFO("mbuf_allocpacket failed!"); // TODO(iwade) handle

  if (mbuf_copyback(m, 0, sizeof(req), &req, MBUF_WAITOK) != 0)
    KINFO("mbuf_copyback failed!"); // TODO(iwade) handle
  
  ((net_habitue_driver_SC101 *)getProvider())->sendPacket(&addr, m, out);
}
Ejemplo n.º 2
0
void net_habitue_device_SC101::doSubmitIO(outstanding_io *io)
{
  bool isWrite = (io->buffer->getDirection() == kIODirectionOut);
  UInt32 ioLen = (io->nblks * SECTOR_SIZE);
  mbuf_t m;

  retryResolve();
  
  if (isWrite)
  {
    KDEBUG("%p write %d %d (%d)", io, io->block, io->nblks, _outstandingCount);
    
    psan_put_t req;
    bzero(&req, sizeof(req));
    req.ctrl.cmd = PSAN_PUT;
    req.ctrl.seq = ((net_habitue_driver_SC101 *)getProvider())->getSequenceNumber();
    req.ctrl.len_power = POWER_OF_2(ioLen);
    req.sector = htonl(io->block);
    
    if (mbuf_allocpacket(MBUF_WAITOK, sizeof(req) + ioLen, NULL, &m) != 0)
      KINFO("mbuf_allocpacket failed!"); // TODO(iwade) handle

    if (mbuf_copyback(m, 0, sizeof(req), &req, MBUF_WAITOK) != 0)
      KINFO("mbuf_copyback failed!"); // TODO(iwade) handle
    
    if (!mbuf_buffer(io->buffer, 0, m, sizeof(req), ioLen))
      KINFO("mbuf_buffer failed"); // TODO(iwade) handle

    io->outstanding.seq = ntohs(req.ctrl.seq);
    io->outstanding.len = sizeof(psan_put_response_t);
    io->outstanding.cmd = PSAN_PUT_RESPONSE;
  }
  else
  {
    KDEBUG("%p read %d %d (%d)", io, io->block, io->nblks, _outstandingCount);
    
    psan_get_t req;
    bzero(&req, sizeof(req));
    req.ctrl.cmd = PSAN_GET;
    req.ctrl.seq = ((net_habitue_driver_SC101 *)getProvider())->getSequenceNumber();
    req.ctrl.len_power = POWER_OF_2(ioLen);
    req.sector = htonl(io->block);
    
    if (mbuf_allocpacket(MBUF_WAITOK, sizeof(req), NULL, &m) != 0)
      KINFO("mbuf_allocpacket failed!"); // TODO(iwade) handle

    if (mbuf_copyback(m, 0, sizeof(req), &req, MBUF_WAITOK) != 0)
      KINFO("mbuf_copyback failed!"); // TODO(iwade) handle
    
    io->outstanding.seq = ntohs(req.ctrl.seq);
    io->outstanding.len = sizeof(psan_get_response_t) + ioLen;
    io->outstanding.cmd = PSAN_GET_RESPONSE;
  }
  
  io->outstanding.packetHandler = OSMemberFunctionCast(PacketHandler, this, &net_habitue_device_SC101::handleAsyncIOPacket);
  io->outstanding.timeoutHandler = OSMemberFunctionCast(TimeoutHandler, this, &net_habitue_device_SC101::handleAsyncIOTimeout);
  io->outstanding.target = this;
  io->outstanding.ctx = io;
  io->outstanding.timeout_ms = io->timeout_ms;

  ((net_habitue_driver_SC101 *)getProvider())->sendPacket((sockaddr_in *)io->addr->getBytesNoCopy(), m, &io->outstanding);
}
Ejemplo n.º 3
0
errno_t kn_tcp_pkt_from_params(mbuf_t *data, u_int8_t tcph_flags, u_int32_t iph_saddr, u_int32_t iph_daddr, u_int16_t tcph_sport, u_int16_t tcph_dport, u_int32_t tcph_seq, u_int32_t tcph_ack, const char* payload, size_t payload_len) 
{
    int retval = 0;
	size_t tot_data_len, tot_buf_len, max_len; // mac osx thing.. to be safe, leave out 14 bytes for ethernet header. 
	void *buf = NULL;
    struct ip* o_iph;
	struct tcphdr* o_tcph;
	u_int16_t csum;
	mbuf_csum_request_flags_t csum_flags = 0;
    boolean_t pkt_allocated = FALSE;
	
	tot_data_len = sizeof(struct ip) + sizeof(struct tcphdr) + payload_len;
	tot_buf_len = tot_data_len + ETHHDR_LEN;
	
	// allocate the packet
	retval = mbuf_allocpacket(MBUF_DONTWAIT, tot_buf_len, NULL, data);
	if (retval != 0) {
		kn_debug("mbuf_allocpacket returned error %d\n", retval);
		goto FAILURE;
	}
    else {
        pkt_allocated = TRUE;
    }
	
	max_len = mbuf_maxlen(*data);
	if (max_len < tot_buf_len) {
		kn_debug("no enough buffer space, try to request more.\n");
		retval = mbuf_prepend(data, tot_buf_len - max_len, MBUF_DONTWAIT);
		if (retval != 0) {
			kn_debug("mbuf_prepend returned error %d\n", retval);
			goto FAILURE;
		}
	}
	
	mbuf_pkthdr_setlen(*data, tot_data_len);
	retval = mbuf_pkthdr_setrcvif(*data, NULL);
	if (retval != 0) {
		kn_debug("mbuf_pkthdr_setrcvif returned error %d\n", retval);
        goto FAILURE;
	}
	
	mbuf_setlen(*data, tot_data_len);
	
	retval = mbuf_setdata(*data, (mbuf_datastart(*data) + ETHHDR_LEN), tot_data_len);
	if (retval != 0) {
		kn_debug("mbuf_setdata returned error %d\n", retval);
        goto FAILURE;
	}	
	
	buf = mbuf_data(*data);
	mbuf_pkthdr_setheader(*data, buf);
	
	o_iph = (struct ip*)buf;
	
	memset(o_iph, 0, sizeof(struct ip));
	
	// setup IPv4 header
	o_iph->ip_hl			=	sizeof(struct ip) / 4;
	o_iph->ip_v				=	4;
	o_iph->ip_tos			=	0;
	o_iph->ip_id			=	0;
	o_iph->ip_off			=	htons(IP_DF);
	o_iph->ip_p				=	IPPROTO_TCP;
	o_iph->ip_len			=	htons(tot_data_len);
	o_iph->ip_sum			=	0;
	o_iph->ip_ttl			=	64;
	o_iph->ip_src.s_addr	=	iph_saddr;
	o_iph->ip_dst.s_addr	=	iph_daddr;
	
	o_tcph = (struct tcphdr*)((char*)o_iph + sizeof(struct ip));
	
	memset(o_tcph, 0, sizeof(struct tcphdr));
    
	o_tcph->th_sport		=	tcph_sport;
	o_tcph->th_dport		=	tcph_dport;
	o_tcph->th_seq			=	tcph_seq;
	o_tcph->th_ack			=	tcph_ack;
	o_tcph->th_flags		=	tcph_flags;
	o_tcph->th_win			=	0xffffU;
	o_tcph->th_off			=	sizeof(struct tcphdr) / 4;
	o_tcph->th_sum			=	0;
	o_tcph->th_urp			=	0;
	
	if (payload_len > 0) {
		memcpy((char*)o_tcph + sizeof(struct tcphdr), payload, payload_len);
	}
	
	mbuf_clear_csum_performed(*data);
	
	csum_flags |= MBUF_CSUM_REQ_IP;
	retval = mbuf_get_csum_requested(*data, &csum_flags, NULL);
	if (retval != 0) {
		kn_debug("mbuf_get_csum_requested returned error %d\n", retval);
        goto FAILURE;
	}
	
	/* calculate TCP checksum */
	
	csum = kn_tcp_sum_calc(sizeof(struct tcphdr) + payload_len, (u_int16_t*)&o_iph->ip_src.s_addr, (u_int16_t*)&o_iph->ip_dst.s_addr, (u_int16_t*)o_tcph);
	o_tcph->th_sum			=	csum;
    
    return 0;
    
FAILURE:
    if (pkt_allocated == TRUE) {
        mbuf_free(*data);
    }
    
	return retval;
    
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
/**
 * Internal worker that create a darwin mbuf for a (scatter/)gather list.
 *
 * @returns Pointer to the mbuf.
 * @param   pThis           The instance.
 * @param   pSG             The (scatter/)gather list.
 */
static mbuf_t vboxNetFltDarwinMBufFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG)
{
    /// @todo future? mbuf_how_t How = preemption enabled ? MBUF_DONTWAIT : MBUF_WAITOK;
    mbuf_how_t How = MBUF_WAITOK;

    /*
     * We need some way of getting back to our instance data when
     * the mbuf is freed, so use pvUserData for this.
     *  -- this is not relevant anylonger! --
     */
    Assert(!pSG->pvUserData || pSG->pvUserData == pThis);
    Assert(!pSG->pvUserData2);
    pSG->pvUserData = pThis;

    /*
     * Allocate a packet and copy over the data.
     *
     * Using mbuf_attachcluster() here would've been nice but there are two
     * issues with it: (1) it's 10.5.x only, and (2) the documentation indicates
     * that it's not supposed to be used for really external buffers. The 2nd
     * point might be argued against considering that the only m_clattach user
     * is mallocs memory for the ext mbuf and not doing what's stated in the docs.
     * However, it's hard to tell if these m_clattach buffers actually makes it
     * to the NICs or not, and even if they did, the NIC would need the physical
     * addresses for the pages they contain and might end up copying the data
     * to a new mbuf anyway.
     *
     * So, in the end it's better to just do it the simple way that will work
     * 100%, even if it involves some extra work (alloc + copy) we really wished
     * to avoid.
     *
     * Note. We can't make use of the physical addresses on darwin because the
     *       way the mbuf / cluster stuff works (see mbuf_data_to_physical and
     *       mcl_to_paddr).
     */
    mbuf_t pPkt = NULL;
    errno_t err = mbuf_allocpacket(How, pSG->cbTotal, NULL, &pPkt);
    if (!err)
    {
        /* Skip zero sized memory buffers (paranoia). */
        mbuf_t pCur = pPkt;
        while (pCur && !mbuf_maxlen(pCur))
            pCur = mbuf_next(pCur);
        Assert(pCur);

        /* Set the required packet header attributes. */
        mbuf_pkthdr_setlen(pPkt, pSG->cbTotal);
        mbuf_pkthdr_setheader(pPkt, mbuf_data(pCur));

        /* Special case the single buffer copy. */
        if (    mbuf_next(pCur)
            &&  mbuf_maxlen(pCur) >= pSG->cbTotal)
        {
            mbuf_setlen(pCur, pSG->cbTotal);
            IntNetSgRead(pSG, mbuf_data(pCur));
        }
        else
        {
            /* Multi buffer copying. */
            size_t  cbLeft = pSG->cbTotal;
            size_t  offSrc = 0;
            while (cbLeft > 0 && pCur)
            {
                size_t cb = mbuf_maxlen(pCur);
                if (cb > cbLeft)
                    cb = cbLeft;
                mbuf_setlen(pCur, cb);
                IntNetSgReadEx(pSG, offSrc, cb, mbuf_data(pCur));

                /* advance */
                offSrc += cb;
                cbLeft -= cb;
                pCur = mbuf_next(pCur);
            }
            Assert(cbLeft == 0);
        }
        if (!err)
        {
            /*
             * Tag the packet and return successfully.
             */
            PVBOXNETFLTTAG pTagData;
            err = mbuf_tag_allocate(pPkt, g_idTag, 0 /* type */, sizeof(VBOXNETFLTTAG) /* tag len */, How, (void **)&pTagData);
            if (!err)
            {
                Assert(pSG->aSegs[0].cb >= sizeof(pTagData->EthHdr));
                memcpy(&pTagData->EthHdr, pSG->aSegs[0].pv, sizeof(pTagData->EthHdr));
                return pPkt;
            }

            /* bailout: */
            AssertMsg(err == ENOMEM || err == EWOULDBLOCK, ("err=%d\n", err));
        }

        mbuf_freem(pPkt);
    }
    else
        AssertMsg(err == ENOMEM || err == EWOULDBLOCK, ("err=%d\n", err));
    pSG->pvUserData = NULL;

    return NULL;
}