Exemple 3: Lecture des données de paquet précédemment capturées à partir d'un fichier de sauvegarde et traitement
L'exemple de code suivant illustre la lecture des données de paquet précédemment capturées à partir d'un fichier de sauvegarde et leur traitement.
Cet exemple est uniquement destiné à illustrer l'utilisation des API de la bibliothèque Packet Capture. Il est recommandé d'écrire votre propre application pour une fonction optimale dans un environnement de production.
/*
* Use pcap_open_offline() to open a savefile, containing packet capture data,
* and use the print_addrs() routine to print the source and destination IP
* addresses from the packet capture data to stdout.
*/
#include <stdio.h>
#include <pcap.h>
#define IFSZ 16
#define FLTRSZ 120
#define MAXHOSTSZ 256
#define PCAP_SAVEFILE "./pcap_savefile"
int packets = 0; /* running count of packets read in */
int
usage(char *progname)
{
printf("Usage: %s <interface> [<savefile name>]\n", basename(progname));
exit(7);
}
/*
* Function: print_addrs()
*
* Description: Write source and destination IP addresses from packet data
* out to stdout.
* For simplification, in this sample, assume the
* following about the captured packet data:
* - the addresses are IPv4 addresses
* - the data link type is ethernet
* - ethernet encapsulation, according to RFC 894, is used.
*
* Return: 0 upon success
* -1 on failure (if packet data was cut off before IP addresses).
*/
void
print_addrs(u_char *user, const struct pcap_pkthdr *hdr, const u_char *data)
{
int offset = 26; /* 14 bytes for MAC header +
* 12 byte offset into IP header for IP addresses
*/
if (hdr->caplen < 30) {
/* captured data is not long enough to extract IP address */
fprintf(stderr,
"Error: not enough captured packet data present to extract IP addresses.\n");
return;
}
printf("Packet received from source address %d.%d.%d.%d\n",
data[offset], data[offset+1], data[offset+2], data[offset+3]);
if (hdr->caplen >= 34) {
printf("and destined for %d.%d.%d.%d\n",
data[offset+4], data[offset+5],
data[offset+6], data[offset+7]);
}
packets++; /* keep a running total of number of packets read in */
}
int
main(int argc, char **argv)
{
pcap_t *p; /* packet capture descriptor */
char ifname[IFSZ]; /* interface name (such as "en0") */
char filename[80]; /* name of savefile to read packet data from */
char errbuf[PCAP_ERRBUF_SIZE]; /* buffer to hold error text */
char prestr[80]; /* prefix string for errors from pcap_perror */
int majver = 0, minver = 0; /* major and minor numbers for the */
/* current Pcap library version */
/*
* For this program, the interface name must be passed to it on the
* command line. The savefile name may optionally be passed in
* as well. If no savefile name is passed in, "./pcap_savefile" is
* assumed. If there are no arguments, program has been invoked
* incorrectly.
*/
if (argc < 2)
usage(argv[0]);
if (strlen(argv[1]) > IFSZ) {
fprintf(stderr, "Invalid interface name.\n");
exit(1);
}
strcpy(ifname, argv[1]);
/*
* If there is a second argument (the name of the savefile), save it in
* filename. Otherwise, use the default name.
*/
if (argc >= 3)
strcpy(filename,argv[2]);
else
strcpy(filename, PCAP_SAVEFILE);
/*
* Open a file containing packet capture data. This must be called
* before processing any of the packet capture data. The file
* containing pcaket capture data should have been generated by a
* previous call to pcap_open_live().
*/
if (!(p = pcap_open_offline(filename, errbuf))) {
fprintf(stderr,
"Error in opening savefile, %s, for reading: %s\n",
filename, errbuf);
exit(2);
}
/*
* Call pcap_dispatch() with a count of 0 which will cause
* pcap_dispatch() to read and process packets until an error or EOF
* occurs. For each packet read from the savefile, the output routine,
* print_addrs(), will be called to print the source and destinations
* addresses from the IP header in the packet capture data.
* Note that packet in this case may not be a complete packet. The
* amount of data captured per packet is determined by the snaplen
* variable which was passed into pcap_open_live() when the savefile
* was created.
*/
if (pcap_dispatch(p, 0, &print_addrs, (char *)0) < 0) {
/*
* Print out appropriate text, followed by the error message
* generated by the packet capture library.
*/
sprintf(prestr,"Error reading packets from interface %s",
ifname);
pcap_perror(p,prestr);
exit(4);
}
printf("\nPackets read in: %d\n", packets);
/*
* Print out the major and minor version numbers. These are the version
* numbers associated with this revision of the packet capture library.
* The major and minor version numbers can be used to help determine
* what revision of libpcap created the savefile, and, therefore, what
* format was used when it was written.
*/
if (!(majver = pcap_major_version(p))) {
fprintf(stderr,
"Error getting major version number from interface %s",
ifname);
exit(5);
}
printf("The major version number used to create the savefile was: %d.\n", majver);
if (!(minver = pcap_minor_version(p))) {
fprintf(stderr,
"Error getting minor version number from interface %s",
ifname);
exit(6);
}
printf("The minor version number used to create the savefile was: %d.\n", minver);
/*
* Close the packet capture device and free the memory used by the
* packet capture descriptor.
*/
pcap_close(p);
}