Ejemplo n.º 1
0
bool cPcapNet::sendFile (const char* file, bool sync, int loops)
{
	struct pcap_pkthdr *header;
	const u_char *pkt_data;
	bpf_u_int32 len = 0;
	bool error = false;

 // FIXME close interface on error
	uint32_t count = getFileSize(file);

	if (!openInterface ())
		return false;

	pcap_send_queue* q = pcap_sendqueue_alloc (count);
	if (!q)
	{
		fprintf (stderr, "can't allocate sendqueue\n");
		return false;
	}

	cPcapFileIO pcapfile;

	if (!pcapfile.open (file))
		return false;

	// Retrieve the packets from the file
	while (pcapfile.read (&header, &pkt_data))
	{
		int r = pcap_sendqueue_queue (q, header, pkt_data);
		// pcap_sendqueue_queue can only fail, if we have'n allocated enough memory
		assert (!r);

		len += (header->len + sizeof (*header));
	}

	error = pcapfile.error ();
	if (error)
		fprintf (stderr, "File error while reading %s\n", file);

	pcapfile.close ();

	while (!error && loops--)
	{
		error = pcap_sendqueue_transmit (ifcHandle, q, sync) != len;
		if (error)
			fprintf (stderr, "PCAP could not send transmit buffer\n");
	}
	pcap_sendqueue_destroy (q);
	pcap_close(ifcHandle);

	return !error;
}
Ejemplo n.º 2
0
/***************************************************************************
 * Some methods of transmit queue multiple packets in a buffer then
 * send all queued packets at once. At the end of a scan, we might have
 * some pending packets that haven't been transmitted yet. Therefore,
 * we'll have to flush them.
 ***************************************************************************/
void
rawsock_flush(struct Adapter *adapter)
{
    if (adapter->sendq) {
        pcap_sendqueue_transmit(adapter->pcap, adapter->sendq, 0);

        /* Dude, I totally forget why this step is necessary. I vaguely
         * remember there's a good reason for it though */
        pcap_sendqueue_destroy(adapter->sendq);
        adapter->sendq =  pcap_sendqueue_alloc(SENDQ_SIZE);
    }

}
Ejemplo n.º 3
0
/***************************************************************************
 * wrapper for libpcap's sendpacket
 *
 * PORTABILITY: WINDOWS and PF_RING
 * For performance, Windows and PF_RING can queue up multiple packets, then
 * transmit them all in a chunk. If we stop and wait for a bit, we need
 * to flush the queue to force packets to be transmitted immediately.
 ***************************************************************************/
int
rawsock_send_packet(
    struct Adapter *adapter,
    const unsigned char *packet,
    unsigned length,
    unsigned flush)
{
    if (adapter == 0)
        return 0;
    
    /* Print --packet-trace if debugging */
    if (adapter->is_packet_trace) {
        packet_trace(stdout, packet, length, 1);
    }

    /* PF_RING */
    if (adapter->ring) {
        int err = PF_RING_ERROR_NO_TX_SLOT_AVAILABLE;

        while (err == PF_RING_ERROR_NO_TX_SLOT_AVAILABLE) {
            err = PFRING.send(adapter->ring, packet, length, (unsigned char)flush);
        }
        if (err < 0)
            LOG(1, "pfring:xmit: ERROR %d\n", err);
        return err;
    }

    /* WINDOWS PCAP */
    if (adapter->sendq) {
        int err;
        struct pcap_pkthdr hdr;
        hdr.len = length;
        hdr.caplen = length;

        err = pcap_sendqueue_queue(adapter->sendq, &hdr, packet);
        if (err) {
            //printf("sendpacket() failed %d\n", x);
            //for (;;)
            pcap_sendqueue_transmit(adapter->pcap, adapter->sendq, 0);
            //printf("pcap_send_queue)() returned %u\n", x);
            pcap_sendqueue_destroy(adapter->sendq);
            adapter->sendq =  pcap_sendqueue_alloc(SENDQ_SIZE);
            pcap_sendqueue_queue(adapter->sendq, &hdr, packet);
            //("sendpacket() returned %d\n", x);
            //exit(1);
        } else
            ; //printf("+%u\n", count++);
        if (flush) {
            pcap_sendqueue_transmit(adapter->pcap, adapter->sendq, 0);

            /* Dude, I totally forget why this step is necessary. I vaguely
             * remember there's a good reason for it though */
            pcap_sendqueue_destroy(adapter->sendq);
            adapter->sendq =  pcap_sendqueue_alloc(SENDQ_SIZE);
        }
        return 0;
    }

    /* LIBPCAP */
    if (adapter->pcap)
        return pcap_sendpacket(adapter->pcap, packet, length);

    return 0;
}
Ejemplo n.º 4
0
void main(int argc, char **argv)
{
	pcap_t *indesc,*outdesc;
	char errbuf[PCAP_ERRBUF_SIZE];
	char source[PCAP_BUF_SIZE];
	FILE *capfile;
	int caplen, sync;
	u_int res;
	pcap_send_queue *squeue;
	struct pcap_pkthdr *pktheader;
	u_char *pktdata;
	float cpu_time;
	u_int npacks = 0;
	
	/* Check the validity of the command line */
	if (argc <= 2 || argc >= 5)
	{
		usage();
		return;
	}
		
	/* Retrieve the length of the capture file */
	capfile=fopen(argv[1],"rb");
	if(!capfile){
		printf("Capture file not found!\n");
		return;
	}
	
	fseek(capfile , 0, SEEK_END);
	caplen= ftell(capfile)- sizeof(struct pcap_file_header);
	fclose(capfile);
			
	/* Chek if the timestamps must be respected */
	if(argc == 4 && argv[3][0] == 's')
		sync = TRUE;
	else
		sync = FALSE;

	/* Open the capture */
	/* Create the source string according to the new WinPcap syntax */
	if ( pcap_createsrcstr(	source,			// variable that will keep the source string
							PCAP_SRC_FILE,	// we want to open a file
							NULL,			// remote host
							NULL,			// port on the remote host
							argv[1],		// name of the file we want to open
							errbuf			// error buffer
							) != 0)
	{
		fprintf(stderr,"\nError creating a source string\n");
		return;
	}
	
	/* Open the capture file */
	if ( (indesc= pcap_open(source, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf) ) == NULL)
	{
		fprintf(stderr,"\nUnable to open the file %s.\n", source);
		return;
	}

	/* Open the output adapter */
	if ( (outdesc= pcap_open(argv[2], 100, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf) ) == NULL)
	{
		fprintf(stderr,"\nUnable to open adapter %s.\n", source);
		return;
	}

	/* Check the MAC type */
	if (pcap_datalink(indesc) != pcap_datalink(outdesc))
	{
		printf("Warning: the datalink of the capture differs from the one of the selected interface.\n");
		printf("Press a key to continue, or CTRL+C to stop.\n");
		getchar();
	}

	/* Allocate a send queue */
	squeue = pcap_sendqueue_alloc(caplen);

	/* Fill the queue with the packets from the file */
	while ((res = pcap_next_ex( indesc, &pktheader, &pktdata)) == 1)
	{
		if (pcap_sendqueue_queue(squeue, pktheader, pktdata) == -1)
		{
			printf("Warning: packet buffer too small, not all the packets will be sent.\n");
			break;
		}

		npacks++;
	}

	if (res == -1)
	{
		printf("Corrupted input file.\n");
		pcap_sendqueue_destroy(squeue);
		return;
	}

	/* Transmit the queue */
	
	cpu_time = (float)clock ();

	if ((res = pcap_sendqueue_transmit(outdesc, squeue, sync)) < squeue->len)
	{
		printf("An error occurred sending the packets: %s. Only %d bytes were sent\n", pcap_geterr(outdesc), res);
	}
	
	cpu_time = (clock() - cpu_time)/CLK_TCK;
	
	printf ("\n\nElapsed time: %5.3f\n", cpu_time);
	printf ("\nTotal packets generated = %d", npacks);
	printf ("\nAverage packets per second = %d", (int)((double)npacks/cpu_time));
	printf ("\n");

	/* free the send queue */
	pcap_sendqueue_destroy(squeue);

	/* Close the input file */
	pcap_close(indesc);

	/* 
	 * lose the output adapter 
	 * IMPORTANT: remember to close the adapter, otherwise there will be no guarantee that all the 
	 * packets will be sent!
	 */
	pcap_close(outdesc);


	return;
}
Ejemplo n.º 5
0
void PcapPort::PortTransmitter::run()
{
    //! \todo (MED) Stream Mode - continuous: define before implement

    // NOTE1: We can't use pcap_sendqueue_transmit() directly even on Win32
    // 'coz of 2 reasons - there's no way of stopping it before all packets
    // in the sendQueue are sent out and secondly, stats are available only
    // when all packets have been sent - no periodic updates
    // 
    // NOTE2: Transmit on the Rx Handle so that we can receive it back
    // on the Tx Handle to do stats
    //
    // NOTE3: Update pcapExtra counters - port TxStats will be updated in the
    // 'stats callback' function so that both Rx and Tx stats are updated
    // together

    const int kSyncTransmit = 1;
    int i;
    long overHead = 0; // overHead should be negative or zero

    qDebug("packetSequenceList_.size = %d", packetSequenceList_.size());
    if (packetSequenceList_.size() <= 0)
        goto _exit;

    for(i = 0; i < packetSequenceList_.size(); i++) {
        qDebug("sendQ[%d]: rptCnt = %d, rptSz = %d, usecDelay = %ld", i, 
                packetSequenceList_.at(i)->repeatCount_, 
                packetSequenceList_.at(i)->repeatSize_,
                packetSequenceList_.at(i)->usecDelay_);
        qDebug("sendQ[%d]: pkts = %ld, usecDuration = %ld", i, 
                packetSequenceList_.at(i)->packets_, 
                packetSequenceList_.at(i)->usecDuration_);
    }

    state_ = kRunning;
    i = 0;
    while (i < packetSequenceList_.size())
    {

_restart:
        int rptSz  = packetSequenceList_.at(i)->repeatSize_;
        int rptCnt = packetSequenceList_.at(i)->repeatCount_;

        for (int j = 0; j < rptCnt; j++)
        {
            for (int k = 0; k < rptSz; k++)
            {
                int ret;
                PacketSequence *seq = packetSequenceList_.at(i+k);
#ifdef Q_OS_WIN32
                TimeStamp ovrStart, ovrEnd;

                if (seq->usecDuration_ <= long(1e6)) // 1s
                {
                    getTimeStamp(&ovrStart);
                    ret = pcap_sendqueue_transmit(handle_, 
                            seq->sendQueue_, kSyncTransmit);
                    if (ret >= 0)
                    {
                        stats_->txPkts += seq->packets_;
                        stats_->txBytes += seq->bytes_;

                        getTimeStamp(&ovrEnd);
                        overHead += seq->usecDuration_ 
                            - udiffTimeStamp(&ovrStart, &ovrEnd);
                        Q_ASSERT(overHead <= 0);
                    }
                    if (stop_)
                        ret = -2;
                }
                else
                {
                    ret = sendQueueTransmit(handle_, seq->sendQueue_, 
                            overHead, kSyncTransmit);
                }
#else
                ret = sendQueueTransmit(handle_, seq->sendQueue_, 
                            overHead, kSyncTransmit);
#endif

                if (ret >= 0)
                {
                    long usecs = seq->usecDelay_ + overHead; 
                    if (usecs > 0) 
                    {
                        udelay(usecs);
                        overHead = 0;
                    }
                    else
                        overHead = usecs;
                }
                else
                {
                    qDebug("error %d in sendQueueTransmit()", ret);
                    qDebug("overHead = %ld", overHead);
                    stop_ = false;
                    goto _exit;
                }
            }
        }

        // Move to the next Packet Set
        i += rptSz;
    }

    if (returnToQIdx_ >= 0)
    {
        long usecs = loopDelay_ + overHead;

        if (usecs > 0)
        {
            udelay(usecs);
            overHead = 0;
        }
        else
            overHead = usecs;

        i = returnToQIdx_;
        goto _restart;
    }

_exit:
    state_ = kFinished;
}