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; }
/*************************************************************************** * 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); } }
static void rawsock_close_adapter(struct Adapter *adapter) { if (adapter->ring) { PFRING.close(adapter->ring); } if (adapter->pcap) { pcap_close(adapter->pcap); } if (adapter->sendq) { pcap_sendqueue_destroy(adapter->sendq); } free(adapter); }
/*************************************************************************** * 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; }
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; }