Install libpcap library
First, install the associated support environment
sudo apt get install flex
sudo apt get install bison
Then download the latest version of libpcap, Download:http://www.tcpdump.org/。
Decompression, enter the following command in the unzipped folder
./configure
make
make install
Single card capture DEMO
Single card packet capture library libpcap is very basic functions, here released a demo as a reference to facilitate comparison with the multi-card expansion.
The main function of a single card demo is input card heard by the user. When the user does not enter the card, the program will print all device names can listen, to be selected by the user monitor card, when (10000) monitor a certain number of the card, the program terminates.
//demo=single
#include "pcap.h"
#include "stdlib.h"
#include <time.h>
#include <arpa/inet.h>
#define SNAP_LEN 65536
//prototype of the packet handler
void dispatcher_handler(u_char *temp1,
const struct pcap_pkthdr *header, const u_char *pkt_data);
int main(int argc, char **argv)
{
char *dev = NULL; /* capture device name */
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
pcap_t *handle; /* packet capture handle */
pcap_if_t *alldev, *p;
char filter_exp[] = "tcp"; /* filter expression [3] */
struct bpf_program fp; /* compiled filter program (expression) */
bpf_u_int32 mask; /* subnet mask */
bpf_u_int32 net; /* ip */
int num_packets = 10000; /* number of packets to capture */
/* check for capture device name on command-line */
if (argc == 2) {
dev = argv[1];
}
else if (argc > 2) {
fprintf(stderr, "error: unrecognized command-line options\n\n");
exit(EXIT_FAILURE);
}
else {
/* find a capture device if not specified on command-line */
int i=0,num;
if(pcap_findalldevs(&alldev,errbuf)==-1)
{
printf("find all devices is error\n");
return 0;
}
for(p=alldev;p;p=p->next)
{
printf("%d:%s\n",++i,p->name);
if(p->description)
{
printf("%s\n",p->description);
}
}
printf("please input which interface you want to use\n");
scanf("%d",&num);
if(num<1||num>i)
{
printf("interface is unavillible\n");
return 0;
}
for(p=alldev,i=1;i<=num;p=p->next,i++)
dev=p->name;
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n",
errbuf);
exit(EXIT_FAILURE);
}
}
/* print capture info */
printf("Device: %s\n", dev);
printf("Number of packets: %d\n", num_packets);
printf("Filter expression: %s\n", filter_exp);
/* open capture device */
handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
exit(EXIT_FAILURE);
}
/* make sure we're capturing on an Ethernet device [2] */
if (pcap_datalink(handle) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", dev);
exit(EXIT_FAILURE);
}
/* compile the filter expression */
if (pcap_compile(handle, &fp, filter_exp, 0, 24) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
/* apply the compiled filter */
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
/* now we can set our callback function */
pcap_loop(handle, num_packets, dispatcher_handler, NULL);
/* cleanup */
pcap_freecode(&fp);
pcap_close(handle);
printf("\nCapture complete.\n");
return 0;
}
void dispatcher_handler(u_char *temp1,
const struct pcap_pkthdr *header, const u_char *pkt_data)
{
printf("I get one packet!\n");
}
Multi-card expansion
Since no libpcap library card can monitor multiple functions at the same time, according to the recommendations of friends, I decided to use a multi-threaded approach to open multiple threads are listening more than one card to resolve this problem. Here, for example to monitor dual-card will be given solutions, inadequacies also please the reader pointed out:
- Similarly, the user can enter the name of the first two cards is to listen,
sudo ./demo eth0 wlan0 - When the user does not input parameters to listen on the card, the program name can be given to all listening devices, sequentially input by the user, to the two parameters are two processes used to monitor packets.
- Termination condition regarding the program, the number of packets to the original decision is clearly unreasonable for the multi-card scene, listening instead to time decision: On the third execution threads sleep () function, the end of the third process, the front end of two a packet capture process.
code show as below:
//demo
#include "pcap.h"
#include <pthread.h>
#include "stdlib.h"
#include <time.h>
#include <arpa/inet.h>
#include "unistd.h"
#define SNAP_LEN 65535
/* prototype of the packet handler */
void dispatcher_handler(u_char *temp1,
const struct pcap_pkthdr *header, const u_char *pkt_data);
void *thr_fn1(void *arg);
void *thr_fn2(void *arg);
void *thr_fn3(void *arg);
pcap_t *handle1, *handle2; /* packet capture handle */
int CAP_TIME = 600;
pthread_t t1, t2, t3;
int main(int argc, char **argv)
{
char *dev1 = NULL;
char *dev2 = NULL;
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
pcap_if_t *alldev, *p;
char filter_exp[] = "tcp"; /* filter expression [3] */
struct bpf_program fp1,fp2; /* compiled filter program (expression) */
bpf_u_int32 mask; /* subnet mask */
bpf_u_int32 net; /* ip */
/* check for capture device name on command-line */
if (argc == 3) { //pre-define the two device's names to be captured
dev1 = argv[1];
dev2 = argv[2];
}
else if (argc > 3 || argc == 2) {
fprintf(stderr, "error: unrecognized command-line options\n\n");
exit(EXIT_FAILURE);
}
else {
/* find all capture device and tell the users to choose 2 if not specified on command-line */
int i=0,num1,num2;
if(pcap_findalldevs(&alldev,errbuf)==-1)
{
printf("find all devices is error\n");
return 0;
}
for(p=alldev;p;p=p->next)
{
printf("%d:%s\n",++i,p->name);
if(p->description)
{
printf("%s\n",p->description);
}
}
printf("please input the 1st interface you want to use\n");
scanf("%d",&num1);
if(num1<1||num1>i)
{
printf("interface is unavillible\n");
return 0;
}
for(p=alldev,i=1;i<=num1;p=p->next,i++)
dev1=p->name;
printf("please input the 2nd interface you want to use\n");
scanf("%d",&num2);
if(num2<1 || num2>i || num2==num1)
{
printf("interface is unavillible\n");
return 0;
}
for(p=alldev,i=1;i<=num2;p=p->next,i++)
dev2=p->name;
}
printf("please input the capture time\n");
scanf("%d",&CAP_TIME);
/* print capture info */
printf("1st device: %s\n", dev1);
/* open capture device */
handle1 = pcap_open_live(dev1, SNAP_LEN, 1, 1000, errbuf);
if (handle1 == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev1, errbuf);
exit(EXIT_FAILURE);
}
/* make sure we're capturing on an Ethernet device [2] */
if (pcap_datalink(handle1) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", dev1);
exit(EXIT_FAILURE);
}
/* compile the filter expression */
if (pcap_compile(handle1, &fp1, filter_exp, 0, 24) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n",
filter_exp, pcap_geterr(handle1));
exit(EXIT_FAILURE);
}
/* apply the compiled filter */
if (pcap_setfilter(handle1, &fp1) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
filter_exp, pcap_geterr(handle1));
exit(EXIT_FAILURE);
}
/* print capture info */
printf("2nd device: %s\n", dev2);
printf("Filter expression: %s\n", filter_exp);
printf("Caputre time: %d\n", CAP_TIME);
/* open capture device */
handle2 = pcap_open_live(dev2, SNAP_LEN, 1, 1000, errbuf);
if (handle2 == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev2, errbuf);
exit(EXIT_FAILURE);
}
/* make sure we're capturing on an Ethernet device [2] */
if (pcap_datalink(handle2) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", dev2);
exit(EXIT_FAILURE);
}
/* compile the filter expression */
if (pcap_compile(handle2, &fp2, filter_exp, 0, 24) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n",
filter_exp, pcap_geterr(handle2));
exit(EXIT_FAILURE);
}
/* apply the compiled filter */
if (pcap_setfilter(handle2, &fp2) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
filter_exp, pcap_geterr(handle2));
exit(EXIT_FAILURE);
}
pthread_create(&t1, NULL, thr_fn1, NULL);
pthread_create(&t2, NULL, thr_fn2, NULL);
pthread_create(&t3, NULL, thr_fn3, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
pcap_freecode(&fp1);
pcap_freecode(&fp2);
pcap_close(handle1);
pcap_close(handle2);
printf("\nCapture complete.\n");
return 0;
}
void dispatcher_handler(u_char *temp1,
const struct pcap_pkthdr *header, const u_char *pkt_data)
{
printf("I get one packet!\n");
}
void *thr_fn1(void *arg)
{
pcap_loop(handle1, 0, dispatcher_handler, NULL);
//pthread_cancel( t2 );
}
void *thr_fn2(void *arg)
{
pcap_loop(handle2, 0, dispatcher_handler, NULL);
//pthread_cancel( t1 );
}
void *thr_fn3(void *arg)
{
sleep(CAP_TIME);
pthread_cancel( t1 );
pthread_cancel( t2 );
}
Compiling program needs to connect libpcap library and pthread library, use the commandgcc -g -w demo.cpp -o demo -lpcap -lpthread
Note: the sake of space, only the main loop a print instruction, different functions can be used alternatively other network resources.