示例#1
0
int main()
{
  // TEST PACKET TYPES
  // TRN
  char *testData = "hello world!";
  Packet trn;
  trn.isAck = false;
  trn.isFin = false;
  trn.seq = 118;
  trn.data = (uint8_t*)testData;
  trn.length = 13;
  // Don't need to free 'trn' packet because the data wasn't malloc'd
  // However, usually will need to free it

  pretendSend(&trn);
  // ACK
  Packet ack = makeAck(118);
  pretendSend(&ack);
  freePacket(&ack);

  // FIN
  Packet fin = makeFin();
  pretendSend(&fin);
  freePacket(&fin);

  // FINACK
  Packet finAck = makeFinAck();
  pretendSend(&finAck);
  freePacket(&finAck);
}
示例#2
0
UInt32
MolEnet::outputPacket( struct mbuf *pkt, void *param )
{
	struct IOPhysicalSegment segVector[2];
	int n;

	assert( pkt && netifEnabled );

	//printm("outputPacket %d\n", tx_tail );

	if( tx_ring[tx_tail].psize ) {
		/* Ring full. The txIRQ should call transmitQueue->service to unstall 
		 * the queue. At the moment we transmit each packet synchronously
		 * to the linux side. Thus the ring will never be full...
		 */ 
		printm("output stalled\n");
		return kIOReturnOutputStall;
	}

	n = txMBufCursor->getPhysicalSegmentsWithCoalesce( pkt, segVector );
	if( n < 0 || n > 2 ) {
		printm("getPhysicalSegments returned an error (%d)\n", n );
		freePacket(pkt);
		return kIOReturnOutputDropped;
	}

	tx_ring[tx_tail].flags = 0;
	if( n == 2 ) {
		tx_of_ring[tx_tail].buf = segVector[1].location;
		tx_of_ring[tx_tail].bsize = segVector[1].length;
		tx_of_ring[tx_tail].psize = segVector[1].length;
		tx_of_ring[tx_tail].flags = 0;
		tx_ring[tx_tail].flags = kEnet2SplitBufferFlag;
	}
	tx_ring[tx_tail].buf = segVector[0].location;
	tx_ring[tx_tail].bsize = segVector[0].length;
	eieio(); // gcc scheduling barrier
	tx_ring[tx_tail].psize = segVector[0].length;

	// Increase tail marker
	tx_tail = (tx_tail + 1) & TX_MASK;

	if( OSI_Enet2Kick() )
		printm("transmission error\n");

	freePacket( pkt );

	return kIOReturnOutputSuccess;
}
示例#3
0
void CLASS::free( void )
{
#define RELEASE(x) do { if(x) { (x)->release(); (x) = 0; } } while(0)

    DEBUG_LOG("%s::free\n", getName());

    assert(fEnabledForKDP == false);
    assert(fEnabledForBSD == false);

    if (fInterruptSource && fWorkLoop)
    {
        fWorkLoop->removeEventSource(fInterruptSource);
    }

    RELEASE( fInterruptSource );
    RELEASE( fKDPNub          );
    RELEASE( fNetif           );
    RELEASE( fRxMbufCursor    );
    RELEASE( fTxMbufCursor    );
    RELEASE( fPCINub          );
    RELEASE( fWorkLoop        );
    RELEASE( fRegMap          );
    RELEASE( fMediumDict      );
    RELEASE( fWatchdogTimer   );
    RELEASE( fKDPQueue        );

    if (fKDPMbuf)
    {
        freePacket(fKDPMbuf);
        fKDPMbuf = 0;
        fKDPMbufSeg.location = 0;
    }

    super::free();
}
示例#4
0
Packet *newPacketIHAVE(Packet *pktWHOHAS)
{
    uint8_t numHash = getPacketNumHash(pktWHOHAS);
    int i = 0;
    int idx;
    uint8_t *hash;
    Packet *thisObj = newPacketDefault();
    incPacketSize(thisObj, 4);
    setPacketType(thisObj, "IHAVE");
    for(i = 0; i < numHash; i++) {
        hash = getPacketHash(pktWHOHAS, i);
        idx = searchHash(hash, &hasChunk, -1);
        if(idx >= 0) {
            printf("Has[%d]", i);
            insertPacketHash(thisObj, hash);
        }
    }

    if(i == 0 || getPacketSize(thisObj) == 20) {
        freePacket(thisObj);
        return NULL;
    } else {
      setPacketDest(thisObj, &(pktWHOHAS->src), sizeof(pktWHOHAS->src));
      return thisObj;
    }
}
示例#5
0
void FilesManager::ProcessPacket(PACKET * packet)
{
	switch (packet->_header.subCommand)
	{
		case drivesList:
		{
			SendDrivesList();
			break;
		}
		case browsePath:
		{
			SendBrowsePath((char*)packet->data);
			break;
		}
		case renameFile:
		{
			RenameFileFromPath((char*)packet->data);
			break;
		}
		case deleteFile:
		{
			DeleteFileFromPath((char*)packet->data);
			break;
		}
		default:
		{
			break;
		}
	}
	freePacket(packet);
}
示例#6
0
void HoRNDIS::receivePacket(void *packet, UInt32 size) {
	mbuf_t m;
	UInt32 submit;
	IOReturn rv;
	
	LOG(V_DEBUG, "sz %d", (int)size);
	
	if (size > MAX_BLOCK_SIZE) {
		LOG(V_ERROR, "packet size error, packet dropped");
		fpNetStats->inputErrors++;
		return;
	}
	
	while (size) {
		struct rndis_data_hdr *hdr = (struct rndis_data_hdr *)packet;
		uint32_t msg_len, data_ofs, data_len;
		
		msg_len = le32_to_cpu(hdr->msg_len);
		data_ofs = le32_to_cpu(hdr->data_offset);
		data_len = le32_to_cpu(hdr->data_len);
		
		if (hdr->msg_type != RNDIS_MSG_PACKET) {
			LOG(V_ERROR, "non-PACKET over data channel? (msg_type %08x)", hdr->msg_type);
			return;
		}
		
		if (hdr->msg_len > size) {
			LOG(V_ERROR, "msg_len too big?");
			return;
		}
		
		if ((data_ofs + data_len + 8) > msg_len) {
			LOG(V_ERROR, "data bigger than msg?");
			return;
		}
	
		m = allocatePacket(data_len);
		if (!m) {
			LOG(V_ERROR, "allocatePacket for data_len %d failed", data_len);
			fpNetStats->inputErrors++;
			return;
		}
		
		rv = mbuf_copyback(m, 0, data_len, (char *)packet + data_ofs + 8, MBUF_WAITOK);
		if (rv) {
			LOG(V_ERROR, "mbuf_copyback failed, rv %08x", rv);
			fpNetStats->inputErrors++;
			freePacket(m);
			return;
		}

		submit = fNetworkInterface->inputPacket(m, data_len);
		LOG(V_DEBUG, "submitted pkt sz %d", data_len);
		fpNetStats->inputPackets++;
		
		size -= hdr->msg_len;
		packet = (char *)packet + hdr->msg_len;
	}
}
UInt32 AgereET131x::outputPacket(mbuf_t m, void * param)
{
	int status = 0;

    /**************************************************************************
	 Queue is not empty or TCB is not available
     *************************************************************************/
    if( MP_TCB_RESOURCES_NOT_AVAILABLE( &adapter )) {
        /**********************************************************************
		 NOTE - If there's an error on send, no need to queue the
		 packet under Linux; if we just send an error up to the netif
		 layer, it will resend the skb to us.
         *********************************************************************/
       // IOLog("TCB Resources Not Available\n" );
		freePacket(m);
		netStats->outputErrors += 1;
		return kIOReturnOutputDropped;
    }

	/**********************************************************************
	 We need to see if the link is up; if it's not, make the netif layer
	 think we're good and drop the packet
	 *********************************************************************/
	if( MP_SHOULD_FAIL_SEND( &adapter ) ){
		freePacket( m );
		netStats->outputErrors += 1;
		return kIOReturnOutputDropped;
	}

	status = send_packet( m );
	if( status != 0 ){
		IOLog( "General error, drop packet(%d)\n", status );
		freePacket( m );
		netStats->outputErrors += 1;
		return kIOReturnOutputDropped;
	}

	return kIOReturnSuccess;
}
UInt32 VoodooIntel3945::outputPacket( mbuf_t m, void* param ) {
	struct wpi_softc* sc = &fSelfData;
	struct ieee80211com* ic = &sc->sc_ic;
	struct ieee80211_node *ni;
	
	DPRINTF(("TX: mbuf len=%u\n", mbuf_len(m)));
	
	if (m == 0)
		return kIOReturnOutputDropped; // ???
	
	ExtraMbufParams* p = (ExtraMbufParams*)param;
	if (p->is80211ManagementFrame) {
		ni = (struct ieee80211_node *)mbuf_pkthdr_rcvif(m);
	} else {
		if (sc->qfullmsk != 0) {
			freePacket(m);
			return kIOReturnOutputDropped;
		}
		
		if (ic->ic_state != IEEE80211_S_RUN) {
			freePacket(m);
			return kIOReturnOutputDropped;
		}
		
		/* Encapsulate and send data frames. */
		if ((m = ieee80211_encap(ic, m, &ni)) == NULL)
			return kIOReturnOutputDropped;
	}
				
	if (wpi_tx(sc, m, ni) != 0) {
		ieee80211_release_node(ic, ni);
		if (m) freePacket(m);
		return kIOReturnOutputDropped;
	} else {
		DPRINTF(("(prev tx success)\n"));
		sc->sc_tx_timer = 5;
		return kIOReturnOutputSuccess;
	}
}
void ReorderingPacketBuffer::releaseUsedPacket(BufferedPacket* packet) {
  // ASSERT: packet == fHeadPacket
  // ASSERT: fNextExpectedSeqNo == packet->rtpSeqNo()
  ++fNextExpectedSeqNo; // because we're finished with this packet now

  fHeadPacket = fHeadPacket->nextPacket();
  if (!fHeadPacket) {
    fTailPacket = NULL;
  }
  packet->nextPacket() = NULL;

  freePacket(packet);
}
示例#10
0
void CLASS::releaseTxMemory( void )
{
    if (fTxDescMemory)
    {
        for (UInt32 i = 0; i < kTxDescCount; i++)
        {
            if (fTxDescBase[i].packet)
                freePacket(fTxDescBase[i].packet);
        }

        memset(fTxDescBase, 0, kTxDescCount * sizeof(TxDesc));
        fTxDescMemory->complete();
        fTxDescMemory->release();
        fTxDescMemory = 0;
        fTxDescBase   = 0;
    }
}
示例#11
0
/*! Vett keret feldolgozása */
void processReceive() {
    Packet *packet = getNextPacket(); // az aktualis vett keret lekerese
    if (!packet)                      // valaki szorakozik NULL ertek
        return;

    if (packet->address == clientAddress) { // jo a cim, fel kell dolgozni
        switch (packet->cmd) {
            case cmPing : replyPing();   // ping parancs jott
                break;
            case cmGetTerm : replyTerm();  // homerseklet lekerdezes parancs jott
                break;
            case cmGetPressure : replyPressure();  // nyomas lekerdezes parancs jott
                break;
        }
    }
    freePacket();  // jelzes, hogy fel van dolgozva, johet a kovetkezo keret
}
示例#12
0
void
MolEnet::free()
{
	int i;
	
	if( is_open ) {
		OSI_Enet2Cntrl( kEnet2Reset );
		OSI_Enet2Close();
	}

	if( getWorkLoop() )
		getWorkLoop()->disableAllEventSources();

	if( _irq )
		_irq->release();

	if( transmitQueue )
		transmitQueue->release();

	if( networkInterface )
		networkInterface->release();

	if( rxMBufCursor )
		rxMBufCursor->release();
	if( txMBufCursor )
		txMBufCursor->release();

	if( mediumDict )
		mediumDict->release();

	if( rx_ring )
		IOFreeContiguous( rx_ring, sizeof(enet2_ring_t) * RX_NUM_EL );
	if( tx_ring )
		IOFreeContiguous( tx_ring, sizeof(enet2_ring_t) * TX_NUM_EL );

	if( workLoop ) {
		workLoop->release();
		workLoop = 0;
	}
	for( i=0; i<RX_NUM_EL; i++ )
		if( rxMBuf[i] )
			freePacket( rxMBuf[i] );

	// free packets in progress
	super::free();
}
示例#13
0
void CLASS::serviceTxInterrupt( void )
{
    TxDesc * descPtr;
    UInt32   headIndex = fTxHeadIndex;
    UInt32   busyCount = TX_RING_BUSY(headIndex, fTxTailIndex);
    UInt32   doneCount = 0;
    UInt32   txStatus;

    while (doneCount < busyCount)
    {
        descPtr = &fTxDescBase[ headIndex ];
        assert(descPtr->descLast);
        assert(descPtr->descCount);

        // Examine ownership bit in the last descriptor for this chain.

        txStatus = OSReadLittleInt32(&descPtr->descLast->cmdStatus, 0);
        if (txStatus & kDescOwn)
            break;  // transmit not done yet

        if (txStatus & kDescTxAbnormalMask)
        {
            recordTxDescriptorErrors(txStatus);
        }

        if (descPtr->packet)
        {
            freePacket(descPtr->packet, kDelayFree);
            descPtr->packet = 0;
        }

        // Skip to the start of the next transmit slot.

        headIndex  = descPtr->nextIndex;
        doneCount += descPtr->descCount;
    }

    if (doneCount)
    {
        fTxHeadIndex = headIndex;
        fTransmitQueue->service();
        releaseFreePackets();
        DEBUG_LOG("TX ISR: retired %lu\n", doneCount);
    }
}
示例#14
0
void pretendSend(Packet *p) {
  uint8_t *buffer;
  size_t length = serializePacket(p, &buffer);

  Packet rec;
  parsePacket(buffer, length, &rec);
  printf("\nSent:\n");
  printPacket(p);
  printf("Received:\n");
  printPacket(p);
  printf("\n");

  // Fail the test if the packets are different after being serialized
  assert(comparePackets(p, &rec));

  freePacket(&rec);
  free(buffer);
}
示例#15
0
void CLASS::releaseRxMemory( void )
{
    if (fRxDescMemory)
    {
        for (UInt32 i = 0; i < kRxDescCount; i++)
        {
            if (fRxDescBase[i].packet)
                freePacket(fRxDescBase[i].packet);
        }

        memset(fRxDescBase, 0, kRxDescCount * sizeof(RxDesc));
        fRxDescMemory->complete();
        fRxDescMemory->release();
        fRxDescMemory   = 0;
        fRxDescBase     = 0;
        fRxDescPhysAddr = 0;
    }
}
示例#16
0
void updateACKQueue(Packet *pkt, int peerID)
{
  sendWindow *sw = &(uploadPool[peerID].sw);
  uint32_t ack = getPacketAck(pkt);
  queue *ackWaitQueue = uploadPool[peerID].ackWaitQueue;
  queue *dataQueue = uploadPool[peerID].dataQueue;
  Packet *ackWait = peek(ackWaitQueue);
  struct timeval cur_time;
  gettimeofday(&cur_time, NULL);
  logger(peerID, uploadPool[peerID].connID, diffTimevalMilli(&cur_time, &(uploadPool[peerID].startTime)), sw->ctrl.windowSize);
  expandWindow(&(sw->ctrl));
  uploadPool[peerID].timeoutCount = 0;
  fprintf(stderr,"Received ACK %d. Last ACK: %d. Next up: %d\n", ack, sw->lastPacketAcked, ackWait == NULL ? 65535 : getPacketSeq(ackWait));
  if(ackWait != NULL) {
    if(ack >= getPacketSeq(ackWait)) {
      sw->dupCount = 0;
      while(ackWait != NULL && ack >= getPacketSeq(ackWait)) {
	dequeue(ackWaitQueue);
	freePacket(ackWait);
	ackWait = peek(ackWaitQueue);
      }
      sw->lastPacketAcked = ack;
      updateSendWindow(sw);

      if(ack == BT_CHUNK_SIZE / PACKET_DATA_SIZE + 1) {
	fprintf(stderr,"Finished sending current chunk!");
	numConnUp--;
	initWindows(&(downloadPool[peerID].rw), &(uploadPool[peerID].sw));
	assert(dequeue(ackWaitQueue) == NULL);
      }
    } else { // Unexpected ACK number
      if(ack == sw->lastPacketAcked) { // Dupliate ACK
	sw->dupCount++;
	fprintf(stderr,"Received duplicate packets %d\n", ack);
	if(sw->dupCount == MAX_DUPLICATE) { // Trigger a fast retransmit
	  fprintf(stderr,"Received 3 duplicates acks %d retransmitting\n", ack);
	  sw->dupCount = 0;
	  mergeAtFront(ackWaitQueue, dataQueue);
	  shrinkWindow(&(sw->ctrl));
	}
      }
    }
  }
}
示例#17
0
void flushQueue(int sock, queue *sendQueue)
{
  int i = 0;
  int retVal = -1;
  int count = sendQueue->size;
  int noLoss = 0;
  Packet *pkt = dequeue(sendQueue);
  if(pkt == NULL) {
    return;
  }
  peerList_t *list = peerInfo.peerList;
  while(count > 0) {
    if(pkt->dest != NULL) { // IHAVE
      retVal = spiffy_sendto(sock,
			     pkt->payload,
			     getPacketSize(pkt),
			     0,
			     (struct sockaddr *) (pkt->dest),
			     sizeof(*(pkt->dest)));
    } else { // WHOHAS  
      for(i = 0; i < peerInfo.numPeer; i++) {
	if(list[i].isMe == 0) {
	  retVal = spiffy_sendto(sock,
				 pkt->payload,
				 getPacketSize(pkt),
				 0,
				 (struct sockaddr *) & (list[i].addr),
				 sizeof(list[i].addr));
	  if(retVal == -1) {
	    enqueue(sendQueue, pkt);
	    noLoss = 1;
	  }
	}
      }
    }
    if(noLoss == 0) {
      fprintf(stderr,"spiffy_sendto() returned -1. This is broken!");
    } 
    freePacket(pkt);
    pkt = dequeue(sendQueue);
    count--;
  }
}
示例#18
0
Packet *newPacketSingleDATA(int seqNo, int seqChunk, size_t size)
{
    size_t retSize;
    long offset = seqChunk * BT_CHUNK_SIZE + (seqNo - 1) * PACKET_DATA_SIZE;
    Packet *pkt = newPacketDefault();

    setPacketType(pkt, "DATA");
    incPacketSize(pkt, size);
    setPacketSeq(pkt, seqNo);

    FILE *mf = masterChunk.filePtr;

    rewind(mf);
    fseek(mf, offset, SEEK_SET);
    retSize = fread(pkt->payload + 16, sizeof(uint8_t), size, mf);
    if(retSize != size) {
      printf("IO Error reading chunk\n");
      freePacket(pkt);
      return NULL;
    } else {
      return pkt;
    }
}
示例#19
0
UInt32 HoRNDIS::outputPacket(mbuf_t packet, void *param) {
	mbuf_t m;
	size_t pktlen = 0;
	IOReturn ior = kIOReturnSuccess;
	UInt32 poolIndx;
	int i;

	LOG(V_DEBUG, "");
	
	/* Count the total size of this packet */
	m = packet;
	while (m) {
		pktlen += mbuf_len(m);
		m = mbuf_next(m);
	}
	
	LOG(V_DEBUG, "%ld bytes", pktlen);
	
	if (pktlen > (mtu + 14)) {
		LOG(V_ERROR, "packet too large (%ld bytes, but I told you you could have %d!)", pktlen, mtu);
		fpNetStats->outputErrors++;
		return false;
	}
	
	/* Find an output buffer in the pool */
	IOLockLock(outbuf_lock);
	for (i = 0; i < OUT_BUF_MAX_TRIES; i++) {
		AbsoluteTime ivl, deadl;
		
		for (poolIndx = 0; poolIndx < N_OUT_BUFS; poolIndx++)
			if (!outbufs[poolIndx].inuse) {
				outbufs[poolIndx].inuse = true;
				break;
			}
		if (poolIndx != N_OUT_BUFS)
			break;
		
		/* "while", not "if".  See Symphony X's seminal work on this topic, /Paradise Lost/ (2007). */
		nanoseconds_to_absolutetime(OUT_BUF_WAIT_TIME, &ivl);
		clock_absolutetime_interval_to_deadline(ivl, &deadl);
		LOG(V_NOTE, "waiting for buffer...");
		IOLockSleepDeadline(outbuf_lock, outbufs, deadl, THREAD_INTERRUPTIBLE);
	}
	IOLockUnlock(outbuf_lock);
	
	if (poolIndx == N_OUT_BUFS) {
		LOG(V_ERROR, "timed out waiting for buffer");
		return kIOReturnTimeout;
	}
	
	/* Start filling in the send buffer */
	struct rndis_data_hdr *hdr;
	hdr = (struct rndis_data_hdr *)outbufs[poolIndx].buf;
	
	outbufs[poolIndx].inuse = true;
	
	outbufs[poolIndx].mdp->setLength(pktlen + sizeof *hdr);
	
	memset(hdr, 0, sizeof *hdr);
	hdr->msg_type = RNDIS_MSG_PACKET;
	hdr->msg_len = cpu_to_le32(pktlen + sizeof *hdr);
	hdr->data_offset = cpu_to_le32(sizeof(*hdr) - 8);
	hdr->data_len = cpu_to_le32(pktlen);
	mbuf_copydata(packet, 0, pktlen, hdr + 1);
	
	freePacket(packet);
	
	/* Now, fire it off! */
	outbufs[poolIndx].comp.target    = this;
	outbufs[poolIndx].comp.parameter = (void *)poolIndx;
	outbufs[poolIndx].comp.action    = dataWriteComplete;
	
	ior = fOutPipe->Write(outbufs[poolIndx].mdp, &outbufs[poolIndx].comp);
	if (ior != kIOReturnSuccess) {
		LOG(V_ERROR, "write failed");
		if (ior == kIOUSBPipeStalled) {
			fOutPipe->Reset();
			ior = fOutPipe->Write(outbufs[poolIndx].mdp, &outbufs[poolIndx].comp);
			if (ior != kIOReturnSuccess) {
				LOG(V_ERROR, "write really failed");
				fpNetStats->outputErrors++;
				return ior;
			}
		}
	}
	fpNetStats->outputPackets++;
	
	return kIOReturnOutputSuccess;
}
示例#20
0
UInt32 darwin_iwi3945::outputPacket(mbuf_t m, void * param)
{
	//IOLog("outputPacket\n");
	if((fNetif->getFlags() & IFF_RUNNING)!=0 || m==NULL)
	{
		if (m)
		if (!(mbuf_type(m) == MBUF_TYPE_FREE) ) freePacket(m);
		m=NULL;
		netStats->outputErrors++;
		return kIOReturnOutputDropped;
	}
	
	
	mbuf_t nm;
	int ret = kIOReturnOutputDropped;

	//checking supported packet
	
	IWI_DEBUG("outputPacket t: %d f:%04x\n",mbuf_type(m),mbuf_flags(m));
	
	//drop mbuf is not PKTHDR
	if (!(mbuf_flags(m) & MBUF_PKTHDR) ){
		IWI_ERR("BUG: dont support mbuf without pkthdr and dropped \n");
		netStats->outputErrors++;
		goto finish;
	}
	
	if(mbuf_type(m) == MBUF_TYPE_FREE){
		IWI_ERR("BUG: this is freed packet and dropped \n");
		netStats->outputErrors++;
		goto finish;
	}
	
	nm = mergePacket(m);
	
	if (nm==NULL) 
	{
		netStats->outputErrors++;
		goto finish;
	}
	
	if(mbuf_next(nm)){
		IWI_ERR("BUG: dont support chains mbuf\n");
		IWI_ERR("BUG: tx packet is not single mbuf mbuf_len(%d) mbuf_pkthdr_len(%d)\n",mbuf_len(nm) , mbuf_pkthdr_len(nm) );
		IWI_ERR("BUG: next mbuf size %d\n",mbuf_len(mbuf_next(nm)));
	}
	
	IWI_DEBUG_FULL("call ieee80211_xmit - not done yet\n");
	//ret  = ieee80211_xmit(nm,priv->net_dev);
	//struct ieee80211_tx_control ctrl;
	//ret=ipw_tx_skb(priv, nm, &ctrl);

finish:	
	
	/* free finished packet */
	//freePacket(m);
	//m=NULL;
	if (ret ==  kIOReturnOutputDropped) { 
		//if (nm)
		//if (!(mbuf_type(nm) == MBUF_TYPE_FREE) ) freePacket(nm);
		//nm=NULL;
	}
	return ret;	
}
示例#21
0
void handlePacket(Packet *pkt)
{
  if(verifyPacket(pkt)) {
    int type = getPacketType(pkt);
    switch(type) {
    case 0: { // WHOHAS
      fprintf(stderr,"->WHOHAS\n");
      Packet *pktIHAVE = newPacketIHAVE(pkt);
      enqueue(nonCongestQueue, (void *)pktIHAVE);
      break;
    }
    case 1: { // IHAVE
      fprintf(stderr,"->IHAVE\n");
      int peerIndex = searchPeer(&(pkt->src));
      int peerID = peerInfo.peerList[peerIndex].peerID;
      newPacketGET(pkt, downloadPool[peerID].getQueue);
      idle = 0;
      break;
    }
    case 2: { // GET
      fprintf(stderr,"->GET\n");
      if(numConnUp == maxConn){
	fprintf(stderr,"->GET request denied.\n");
	freePacket(pkt);
	break;
      }
      numConnUp++;
      int peerIndex = searchPeer(&(pkt->src));
      int peerID = peerInfo.peerList[peerIndex].peerID;

      if(downloadPool[peerID].connected == 0){
	clearQueue(uploadPool[peerID].ackWaitQueue);
	initWindows(&(downloadPool[peerID].rw), &(uploadPool[peerID].sw));
	newPacketDATA(pkt, uploadPool[peerID].dataQueue);
	uploadPool[peerID].connID++;
	gettimeofday(&(uploadPool[peerID].startTime), NULL);
      } else {    
	fprintf(stderr,"Only one-way connection is allowed.\n");
	freePacket(pkt);
      }
      break;
    }
    case 3: { // DATA
      fprintf(stderr,"->DATA");
      int peerIndex = searchPeer(&(pkt->src));
      int peerID = peerInfo.peerList[peerIndex].peerID;
      if(1 == updateGetSingleChunk(pkt, peerID)) {
	downloadPool[peerID].connected = 0;
	numConnDown--;
	updateGetChunk();
      }
      break;
    }
    case 4: { // ACK
      fprintf(stderr,"->ACK\n");
      int peerIndex = searchPeer(&(pkt->src));
      int peerID = peerInfo.peerList[peerIndex].peerID;
      updateACKQueue(pkt, peerID);
      break;
    }
    case 5: // DENIED
    default:
      fprintf(stderr,"DENIED\n");
    }
  } else {
    fprintf(stderr,"Invalid packet!\n");
  }
  freePacket(pkt);
  return;
}
示例#22
0
DecoderData::~DecoderData()
{
	freePacket();
	pthread_mutex_destroy(&m_pktMutex);
}
示例#23
0
mbuf_t darwin_iwi3945::mergePacket(mbuf_t m)
{
	mbuf_t nm,nm2;
	int offset;
	if(!mbuf_next(m))
	{
		offset = (4 - ((int)(mbuf_data(m)) & 3)) % 4;    //packet needs to be 4 byte aligned
		if (offset==0) return m;
		IWI_DEBUG_FULL("this packet dont have mbuf_next, merge  is not required\n");
		goto copy_packet;
	}

	/* allocate and Initialize New mbuf */
	nm = allocatePacket(mbuf_pkthdr_len(m));
	if (nm==0) return NULL;
	//if (mbuf_getpacket(MBUF_WAITOK, &nm)!=0) return NULL;
	mbuf_setlen(nm,0);
	mbuf_pkthdr_setlen(nm,0);
	if( mbuf_next(nm)) IWI_ERR("merged mbuf_next\n");
	
	/* merging chains to single mbuf */
	for (nm2 = m; nm2;  nm2 = mbuf_next(nm2)) {
		memcpy (skb_put (nm, mbuf_len(nm2)), (UInt8*)mbuf_data(nm2), mbuf_len(nm2));
	}

	/* checking if merged or not. */
	if( mbuf_len(nm) == mbuf_pkthdr_len(m) ) 
	{
		if (m!=NULL)
		if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m);
		m=NULL;
		return nm;
	}
	/* merging is not completed. */
	IWI_LOG("mergePacket is failed: data copy dont work collectly\n");
	//IWI_LOG("orig_len %d orig_pktlen %d new_len  %d new_pktlen  %d\n",
	//				mbuf_len(m),mbuf_pkthdr_len(m),
	//				mbuf_len(nm),mbuf_pkthdr_len(nm) );
	if (m!=NULL)
	if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m);
	m=NULL;
	if (nm!=NULL)
	if (!(mbuf_type(nm) == MBUF_TYPE_FREE) ) freePacket(nm);
	nm=NULL;
	return NULL;

copy_packet: 
		if (mbuf_dup(m, MBUF_WAITOK , &nm)!=0)
		{
			if (m!=NULL)
			if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m);
			m=NULL;
			return NULL;
		}
		if (m!=NULL)
		if (!(mbuf_type(m) == MBUF_TYPE_FREE) ) freePacket(m);
		m=NULL;
		return nm;
		//return copyPacket(m, 0); 

}
示例#24
0
UInt32 CLASS::outputPacket( mbuf_t packet, void * param )
{
    TxDesc *            descNext;
    TxDesc *            descHead;
    TxDesc *            descLast;
    UInt                segCount;
    UInt32              cmdStatus;
    UInt32              tailIndex;
    IOPhysicalSegment   vectors[ kTxMaxSegmentCount ];
    IODebuggerLockState state;

    state = IOKernelDebugger::lock(this);   

    tailIndex = fTxTailIndex;

    // Check if there are enough descriptors to describe the packet
    // buffers. kTxMaxSegmentCount should be large enough to reduce
    // the need to coalesce mbufs.

    if (TX_RING_FREE(fTxHeadIndex, tailIndex) < kTxMaxSegmentCount)
    {
        IOKernelDebugger::unlock(state);
        return kIOReturnOutputStall;
    }

    // Get the next transmit descriptor owned by the driver.

    descHead = &fTxDescBase[tailIndex];
    descNext = descHead;

    // Use the mbuf cursor to generate a list of physical address and
    // length vectors for the network buffers.

    segCount = fTxMbufCursor->getPhysicalSegmentsWithCoalesce(
                              packet, vectors, kTxMaxSegmentCount);
    if (segCount == 0)
    {
        DEBUG_LOG("TX Cursor returned 0 segments\n");
        goto drop_packet;
    }
    assert(segCount <= kTxMaxSegmentCount);

    // Update the first (head) descriptor.
    // Do not set the OWN bit until the rest of the descriptors are done.

    OSWriteLittleInt32(&descHead->bufferPtr, 0, vectors[0].location);
    cmdStatus = (vectors[0].length & kDescBufferSizeMask);
    tailIndex = (tailIndex + 1) & (kTxDescCount - 1);
    descLast  = descHead;
    descNext  = &fTxDescBase[tailIndex];

    for (UInt seg = 1; seg < segCount; seg++)
    {
        // Write cmdStatus for previous descriptor with MORE bit set.

        OSWriteLittleInt32(&descLast->cmdStatus, 0, cmdStatus | kDescMore);

        // Update current descriptor.

        OSWriteLittleInt32(&descNext->bufferPtr, 0, vectors[seg].location);
        cmdStatus = (vectors[seg].length & kDescBufferSizeMask) | kDescOwn;

        tailIndex = (tailIndex + 1) & (kTxDescCount - 1);
        descLast  = descNext;
        descNext  = &fTxDescBase[tailIndex];
    }

    // Last descriptor must have MORE bit cleared.

    if (++fTxInterruptInterval >= (kTxDescCount/kTxMaxSegmentCount/4))
    {
        cmdStatus |= kDescInterrupt;
        fTxInterruptInterval = 0;
    }

    OSWriteLittleInt32(&descLast->cmdStatus, 0, cmdStatus);
    
    // Set OWN bit on head descriptor after all descriptors following it
    // have been prepared.

    descHead->cmdStatus |= OSSwapHostToLittleConstInt32(kDescOwn);

    // Update Head Descriptor.

    descHead->packet    = packet;
    descHead->descLast  = descLast;
    descHead->descCount = segCount;
    descHead->nextIndex = tailIndex;

    // Update free descriptor count after completing the descriptor chain.
    // The order is important otherwise we may race with interrupt handler.

    fTxTailIndex = tailIndex;
    DEBUG_LOG("TX DESC:%d-%ld (size %d)\n",
              descHead-fTxDescBase, fTxTailIndex, mbuf_pkthdr_len(packet));

    // Enable transmitter in case its in txIdle state.

    WriteReg(CR, CR_TXE);

    IOKernelDebugger::unlock(state);
    NET_STAT(outputPackets, 1);
    return kIOReturnOutputSuccess;

drop_packet:
    IOKernelDebugger::unlock(state);
    freePacket(packet);
    ETH_STAT(dot3TxExtraEntry.resourceErrors, 1);
    return kIOReturnOutputDropped;
}
示例#25
0
void ClientUDP::run()
{
	//init();
	assert(init());

	//open();
	assert(open());

	//resolveHost();
	assert(resolveHost());

	//allocatePacket();
	assert(allocatePacket());

	//SDL_CreateWindow("Client Window", 0, 0, 100, 100, SDL_WINDOW_OPENGL);

	/* Main loop */
	m_quit = 0;
	while (!m_quit)
	{
		//while (SDL_PollEvent(&m_evt))
		//{
		//	m_clientPackage->e = m_evt;

		//	switch (m_clientPackage->e.type)
		//	{
		//	case SDL_KEYDOWN:
		//		printf("Key press detected\n");
		//		break;

		//	case SDL_KEYUP:
		//		printf("Key release detected\n");
		//		break;

		//	case SDL_MOUSEMOTION:
		//		printf("Mouse Moved\n");
		//		break;

		//	default:
		//		break;
		//	}
		//}

		//m_packet->len = (sizeof(Package));
		//m_packet->address.host = m_srvadd.host;	/* Set the destination host */
		//m_packet->address.port = m_srvadd.port;	/* And destination port */

		printf("Type Message: \n>");
		//scanf("%s", (char *)m_packet->data);

		std::getline(std::cin, m_input);

		m_packet->address.host = m_srvadd.host;	/* Set the destination host */
		m_packet->address.port = m_srvadd.port;	/* And destination port */

		m_packet->len = m_input.length() + 256;
		
		memcpy(m_packet->data, m_input.c_str(), m_packet->len);

		//memcpy(m_packet->data, m_clientPackage->data, sizeof(Package));

		if (!(SDLNet_UDP_Send(m_socketDescriptor, -1, m_packet) > 0))
		{
			printf("SDLNet_UDP_Send failed...\n");
		}
	}

	freePacket(*m_packet);
	SDLNet_Quit();
}
示例#26
0
UInt32 AtherosL1Ethernet::outputPacket(mbuf_t m, void *prm)
{
    u32 buf_len;
    at_adapter *adapter=&adapter_;

    u16 next_to_use;
    u16 tpd_req = 1;
    TpdDescr *pTpd ;
    struct at_buffer *buffer_info;

     if(tpd_avail(&adapter->tpd_ring) < tpd_req) {
        // no enough descriptor
        DbgPrint("no enough resource!!\n");
        freePacket(m);
        return kIOReturnOutputDropped;
    }
    

    // init tpd flags
    struct at_tpd_ring* tpd_ring = &adapter->tpd_ring;
    pTpd = AT_TPD_DESC(tpd_ring,
                       ((u16)atomic_read(&tpd_ring->next_to_use)));
    //memset(pTpd, 0, sizeof(TpdDescr));
    memset(((u8*)pTpd + sizeof(pTpd->addr)), 0, (sizeof(TpdDescr) - sizeof(pTpd->addr))); //addr don't clear

    next_to_use = (u16)atomic_read(&tpd_ring->next_to_use);
    buffer_info = tpd_ring->buffer_info+next_to_use; 
    
    if (!buffer_info->memDesc)
    {
        DbgPrint("Tx buffer is null!!\n");
        freePacket(m);
        return kIOReturnOutputDropped;
    }
    
    if (mbuf_pkthdr_len(m) <= AT_TX_BUF_LEN) buf_len = mbuf_pkthdr_len(m);
    else
    {
        DbgPrint("Tx Packet size is too big, droping\n");
        freePacket(m);
        return kIOReturnOutputDropped;
    }
    
    DbgPrint("outputPacket() length %d next_to_use=%d\n", buf_len, next_to_use);
    
    UInt8 *data_ptr = (UInt8 *)buffer_info->memDesc->getBytesNoCopy();
    UInt32 pkt_snd_len = 0;
    mbuf_t cur_buf = m;

    do
    {
        if (mbuf_data(cur_buf)) bcopy(mbuf_data(cur_buf), data_ptr, mbuf_len(cur_buf));
        data_ptr += mbuf_len(cur_buf);
        pkt_snd_len += mbuf_len(cur_buf);
    }
    while(((cur_buf = mbuf_next(cur_buf)) != NULL) && ((pkt_snd_len + mbuf_len(cur_buf)) <= buf_len));
    
    
    buf_len = pkt_snd_len;
    buffer_info->length = (UInt16)buf_len;
    pTpd->buf_len= OSSwapHostToLittleInt16((UInt16)buf_len);
    pTpd->eop = 1;
    
    if(++next_to_use == tpd_ring->count) next_to_use = 0; 
    
    atomic_set(&tpd_ring->next_to_use, next_to_use);
    
    // update mailbox
    at_update_mailbox(adapter);
    
    OSSynchronizeIO();

    freePacket(m);
    return kIOReturnOutputSuccess;
}
示例#27
0
void flushDownload(int sock)
{
  int i = 0;
  int idx;
  uint8_t *hash;
  Packet *pkt;
  connDown *pool = downloadPool;
  for(i = 0; i < peerInfo.numPeer; i++) {
    int peerID = peerInfo.peerList[i].peerID;
    Packet *ack = peek(pool[peerID].ackSendQueue);

    while(ack != NULL) {
      peerList_t *p = &(peerInfo.peerList[i]);
      fprintf(stderr,"Sending ACK %d\n", getPacketAck(ack));
      int retVal = spiffy_sendto(sock,
				 ack->payload,
				 getPacketSize(ack),
				 0,
				 (struct sockaddr *) & (p->addr),
				 sizeof(p->addr));
      fprintf(stderr,"Sent ACK %d\n", getPacketAck(ack));
      if(retVal == -1) { // spiffy_sendto() does not work!!
	fprintf(stderr,"spiffy_sendto() returned -1.\n");
	enqueue(pool[peerID].ackSendQueue, dequeue(pool[peerID].ackSendQueue));
      } else {
	dequeue(pool[peerID].ackSendQueue);
	freePacket(ack);
	ack = dequeue(pool[peerID].ackSendQueue);
      }
    }

    switch(pool[peerID].state) {
    case 0: // Ready
      pkt = dequeue(pool[peerID].getQueue);
      while(pkt != NULL) {
	hash = getPacketHash(pkt, 0);
	printHash(hash);
	idx = searchHash(hash, &getChunk, 0);
	if(idx == -1) { // Someone else is sending or has sent this chunk
	  freePacket(pkt);
	  pkt = dequeue(pool[peerID].getQueue);
	} else if(numConnDown < maxConn){
	  getChunk.list[idx].fetchState = 2;
	  if(downloadPool[peerID].connected == 1)
	    fprintf(stderr,"NOT SUPPOSED TO BE CONNECTEED! \n\n\n\n\n\n");
	  downloadPool[peerID].connected = 1;
	  numConnDown++;
	  break;
	} else { // Cannot allow more download connections
	  fprintf(stderr,"->No more download connection allowed!\n");
	  pool[peerID].state = 2;
	  break;
	}
      }
      if(pool[peerID].state == 2)
	break;
      
      if(pkt != NULL) {
	fprintf(stderr,"Sending a GET\n");
	peerList_t *p = &(peerInfo.peerList[i]);
	hash = pkt->payload + 16;
	char buf[50];
	bzero(buf, 50);
	binary2hex(hash, 20, buf);
	fprintf(stderr,"GET hash:%s\n", buf);
	pool[peerID].curChunkID = searchHash(hash, &getChunk, -1);
	
	int retVal = spiffy_sendto(sock,
				   pkt->payload,
				   getPacketSize(pkt),
				   0,
				   (struct sockaddr *) & (p->addr),
				   sizeof(p->addr));

	if(retVal == -1) { // Spiffy is broken!
	  fprintf(stderr,"spiffy_snetto() returned -1.\n");
	  newPacketWHOHAS(nonCongestQueue);
	  freePacket(pkt);
	  cleanUpConnDown(&(pool[peerID]));
	  numConnDown--;
	  return;
	}

	setPacketTime(pkt);

	enqueue(pool[peerID].timeoutQueue, pkt);
	pool[peerID].state = 1;
      }
      break;
    case 1: { // Downloading
      pkt = peek(pool[peerID].timeoutQueue);
      struct timeval curTime;
      gettimeofday(&curTime, NULL);
      long dt = diffTimeval(&curTime, &(pkt->timestamp));
      if(dt > GET_TIMEOUT_SEC) {
	pool[peerID].timeoutCount++;
	fprintf(stderr,"GET request timed out %d times!\n", pool[peerID].timeoutCount);
	setPacketTime(pkt);
	if(pool[peerID].timeoutCount == 3) {
	  getChunk.list[pool[peerID].curChunkID].fetchState = 0;
	  pool[peerID].state = 0;
	  newPacketWHOHAS(nonCongestQueue);
	  freePacket(pkt);
	  cleanUpConnDown(&(pool[peerID]));
	  numConnDown--;
	}
      }
      break;
    }
    case 2: {
      break;
    }
    default:
      break;
    }

  }
}
示例#28
0
/* returns 0 on success, error message on failure */
char*
secureidcheck(char *user, char *response)
{
	Packet *req = nil, *resp = nil;
	ulong u[4];
	uchar x[16];
	char *radiussecret;
	char ruser[ 64];
	char dest[3*IPaddrlen+20];
	Secret shared, pass;
	char *rv = "authentication failed";
	Ndbs s;
	Ndbtuple *t, *nt, *tt;
	uchar *ip;
	static Ndb *netdb;

	if(netdb == nil)
		netdb = ndbopen(0);

	/* bad responses make them disable the fob, avoid silly checks */
	if(strlen(response) < 4 || strpbrk(response,"abcdefABCDEF") != nil)
		goto out;

	/* get radius secret */
	radiussecret = ndbgetvalue(db, &s, "radius", "lra-radius", "secret", &t);
	if(radiussecret == nil){
		syslog(0, AUTHLOG, "secureidcheck: nil radius secret: %r");
		goto out;
	}

	/* translate user name if we have to */
	strcpy(ruser, user);
	for(nt = t; nt; nt = nt->entry){
		if(strcmp(nt->attr, "uid") == 0 && strcmp(nt->val, user) == 0)
			for(tt = nt->line; tt != nt; tt = tt->line)
				if(strcmp(tt->attr, "rid") == 0){
					strcpy(ruser, tt->val);
					break;
				}
	}
	ndbfree(t);

	u[0] = fastrand();
	u[1] = fastrand();
	u[2] = fastrand();
	u[3] = fastrand();
	req = newRequest((uchar*)u);
	if(req == nil)
		goto out;
	shared.s = (uchar*)radiussecret;
	shared.len = strlen(radiussecret);
	ip = getipv4addr();
	if(ip == nil){
		syslog(0, AUTHLOG, "no interfaces: %r\n");
		goto out;
	}
	if(setAttribute(req, R_NASIPAddress, ip + IPv4off, 4) < 0)
		goto out;

	if(setAttribute(req, R_UserName, (uchar*)ruser, strlen(ruser)) < 0)
		goto out;
	pass.s = (uchar*)response;
	pass.len = strlen(response);
	hide(&shared, req->authenticator, &pass, x);
	if(setAttribute(req, R_UserPassword, x, 16) < 0)
		goto out;

	t = ndbsearch(netdb, &s, "sys", "lra-radius");
	if(t == nil){
		syslog(0, AUTHLOG, "secureidcheck: nil radius sys search: %r\n");
		goto out;
	}
	for(nt = t; nt; nt = nt->entry){
		if(strcmp(nt->attr, "ip") != 0)
			continue;

		snprint(dest,sizeof dest,"udp!%s!oradius", nt->val);
		resp = rpc(dest, &shared, req);
		if(resp == nil){
			syslog(0, AUTHLOG, "%s nil response", dest);
			continue;
		}
		if(resp->ID != req->ID){
			syslog(0, AUTHLOG, "%s mismatched ID  req=%d resp=%d",
				dest, req->ID, resp->ID);
			freePacket(resp);
			resp = nil;
			continue;
		}
	
		switch(resp->code){
		case R_AccessAccept:
			syslog(0, AUTHLOG, "%s accepted ruser=%s", dest, ruser);
			rv = nil;
			break;
		case R_AccessReject:
			syslog(0, AUTHLOG, "%s rejected ruser=%s %s", dest, ruser, replymsg(resp));
			rv = "secureid failed";
			break;
		case R_AccessChallenge:
			syslog(0, AUTHLOG, "%s challenge ruser=%s %s", dest, ruser, replymsg(resp));
			rv = "secureid out of sync";
			break;
		default:
			syslog(0, AUTHLOG, "%s code=%d ruser=%s %s", dest, resp->code, ruser, replymsg(resp));
			break;
		}
		break; /* we have a proper reply, no need to ask again */
	}
	ndbfree(t);
	free(radiussecret);
out:
	freePacket(req);
	freePacket(resp);
	return rv;
}
示例#29
0
Packet *
rpc(char *dest, Secret *shared, Packet *req)
{
	uchar buf[4096], buf2[4096], *b, *e;
	Packet *resp;
	Attribute *a;
	int m, n, fd, try;

	/* marshal request */
	e = buf + sizeof buf;
	buf[0] = req->code;
	buf[1] = req->ID;
	memmove(buf+4, req->authenticator, 16);
	b = buf+20;
	for(a = &req->first; a; a = a->next){
		if(b + 2 + a->len > e)
			return nil;
		*b++ = a->type;
		*b++ = 2 + a->len;
		memmove(b, a->val, a->len);
		b += a->len;
	}
	n = b-buf;
	buf[2] = n>>8;
	buf[3] = n;

	/* send request, wait for reply */
	fd = dial(dest, 0, 0, 0);
	if(fd < 0){
		syslog(0, AUTHLOG, "%s: rpc can't get udp channel", dest);
		return nil;
	}
	atnotify(ding, 1);
	m = -1;
	for(try = 0; try < 2; try++){
		alarm(4000);
		m = write(fd, buf, n);
		if(m != n){
			syslog(0, AUTHLOG, "%s: rpc write err %d %d: %r", dest, m, n);
			m = -1;
			break;
		}
		m = read(fd, buf2, sizeof buf2);
		alarm(0);
		if(m < 0){
			syslog(0, AUTHLOG, "%s rpc read err %d: %r", dest, m);
			break; /* failure */
		}
		if(m == 0 || buf2[1] != buf[1]){  /* need matching ID */
			syslog(0, AUTHLOG, "%s unmatched reply %d", dest, m);
			continue;
		}
		if(authcmp(shared, buf2, m, buf+4) == 0)
			break;
		syslog(0, AUTHLOG, "%s bad rpc chksum", dest);
	}
	close(fd);
	if(m <= 0)
		return nil;

	/* unmarshal reply */
	b = buf2;
	e = buf2+m;
	resp = (Packet*)malloc(sizeof(*resp));
	if(resp == nil)
		return nil;
	resp->code = *b++;
	resp->ID = *b++;
	n = *b++;
	n = (n<<8) | *b++;
	if(m != n){
		syslog(0, AUTHLOG, "rpc got %d bytes, length said %d", m, n);
		if(m > n)
			e = buf2+n;
	}
	memmove(resp->authenticator, b, 16);
	b += 16;
	a = &resp->first;
	a->type = 0;
	while(1){
		if(b >= e){
			a->next = nil;
			break;			/* exit loop */
		}
		a->type = *b++;
		a->len = (*b++) - 2;
		if(b + a->len > e){ /* corrupt packet */
			a->next = nil;
			freePacket(resp);
			return nil;
		}
		memmove(a->val, b, a->len);
		b += a->len;
		if(b < e){  /* any more attributes? */
			a->next = (Attribute*)malloc(sizeof(*a));
			if(a->next == nil){
				free(req);
				return nil;
			}
			a = a->next;
		}
	}
	return resp;
}

int
setAttribute(Packet *p, uchar type, uchar *s, int n)
{
	Attribute *a;

	a = &p->first;
	if(a->type != 0){
		a = (Attribute*)malloc(sizeof(*a));
		if(a == nil)
			return -1;
		a->next = p->first.next;
		p->first.next = a;
	}
	a->type = type;
	a->len = n;
	if(a->len > 253 )  /* RFC2138, section 5 */
		a->len = 253;
	memmove(a->val, s, a->len);
	return 0;
}
示例#30
0
UInt32 AttansicL2Ethernet::outputPacket(mbuf_t m, void *prm)
{
    at_adapter *adapter=&adapter_;
    tx_pkt_header_t* txph;
    u32 offset, copy_len;
    int txs_unused;
    int txbuf_unused;

    u32 buf_len;

	if (mbuf_pkthdr_len(m) <= MAX_TX_BUF_LEN) buf_len = mbuf_pkthdr_len(m);
	else
	{
		DbgPrint("Tx Packet size is too big, droping\n");
		freePacket(m);
		return kIOReturnOutputDropped;
	}

	txs_unused = TxsFreeUnit(adapter);
	txbuf_unused = TxdFreeBytes(adapter);

	if (txs_unused < 1  || buf_len  > txbuf_unused) {
		// no enough resource
		DbgPrint("no enough resource!!\n");
		freePacket(m);
		return kIOReturnOutputDropped;
	}

	offset = adapter->txd_write_ptr;
DbgPrint("outputPacket() begin, txd_write_ptr %d txs_next_clear %d length %d \n" , adapter->txd_write_ptr,adapter->txs_next_clear,buf_len);

    txph = (tx_pkt_header_t*) 
            (((u8*)adapter->txd_ring)+offset);

	offset += 4;
	if (offset >= adapter->txd_ring_size)
		offset -= adapter->txd_ring_size;

	u32 pkt_snd_len = 0;
	mbuf_t cur_buf = m;

	do
	{
		if (mbuf_data(cur_buf)){
			copy_len = adapter->txd_ring_size - offset;
			if (copy_len >=mbuf_len(cur_buf)) {
				memcpy((u8*)adapter->txd_ring+offset, mbuf_data(cur_buf), mbuf_len(cur_buf));

			} else {
				memcpy((u8*)adapter->txd_ring+offset, mbuf_data(cur_buf), copy_len);
				memcpy((u8*)adapter->txd_ring,  ((u8*)mbuf_data(cur_buf))+copy_len, mbuf_len(cur_buf)-copy_len);
			}
			offset += mbuf_len(cur_buf);
			if (offset >= adapter->txd_ring_size)
				offset -= adapter->txd_ring_size;
			pkt_snd_len += mbuf_len(cur_buf);
		}
	}
	while(((cur_buf = mbuf_next(cur_buf)) != NULL) && ((pkt_snd_len + mbuf_len(cur_buf)) <= buf_len));
	buf_len = pkt_snd_len;
	
	*(u32*)txph = 0;
	txph->pkt_size = buf_len;
	
    offset =  ((offset+3)&~3);
	
	if (offset >= adapter->txd_ring_size)
		offset -= adapter->txd_ring_size;
	adapter->txd_write_ptr = offset;

	// clear txs before send
	adapter->txs_ring[adapter->txs_next_clear].update = 0;
	if (++adapter->txs_next_clear == adapter->txs_ring_size)
		adapter->txs_next_clear = 0;

	AT_WRITE_REGW(  &adapter->hw, 
             REG_MB_TXD_WR_IDX, 
             (adapter->txd_write_ptr>>2));

	OSSynchronizeIO();
	freePacket(m);
	return kIOReturnOutputSuccess;
}