Created
December 21, 2012 02:49
-
-
Save isayme/4350346 to your computer and use it in GitHub Desktop.
use libpcap to capture pkts in linux. Add filter 'tcp or udp'.
gcc -g -o cappkt cappkt.c -lpcap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <time.h> | |
#include <netinet/in.h> | |
#include <pcap/pcap.h> | |
// thread unsafe | |
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) | |
{ | |
struct tm *ltime; | |
char timestr[16]; | |
time_t local_tv_sec; | |
local_tv_sec = header->ts.tv_sec; | |
ltime = localtime(&local_tv_sec); | |
strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime); | |
printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len); | |
} | |
int main(int argc, char **argv) | |
{ | |
int ret; | |
int i; | |
int inum; | |
pcap_if_t *alldevs; | |
pcap_if_t *dev; | |
pcap_t *fp; | |
char errbuf[PCAP_ERRBUF_SIZE]; | |
u_int netmask; | |
char packet_filter[] = "tcp or udp"; | |
struct bpf_program fcode; | |
// print the version of current libpcap | |
printf("%s\n", pcap_lib_version()); | |
// get all local network devs | |
if (pcap_findalldevs(&alldevs, errbuf) == -1) | |
{ | |
fprintf(stderr,"pcap_findalldevs_ex error : %s\n", errbuf); | |
return -1; | |
} | |
// print network devs infomation | |
i = 0; | |
for(dev = alldevs; dev != NULL; dev = dev->next) | |
{ | |
printf("%d. %s", ++i, dev->name); | |
if (dev->description) | |
printf(" (%s)\n", dev->description); | |
else | |
printf("\n");// (no description available)\n"); | |
} | |
// select a network device to capture pkts | |
printf("which interface to capture (1-%d):",i); | |
scanf("%d", &inum); | |
if(inum < 1 || inum > i) | |
{ | |
fprintf(stderr, "\nInterface number out of range.\n"); | |
pcap_freealldevs(alldevs); | |
return -1; | |
} | |
// skip to selected device | |
for(dev = alldevs, i = 0; i < (inum - 1) ; dev = dev->next, i++); | |
// open the selected device | |
if (NULL == (fp = pcap_open_live(dev->name, 65536, 1, 1000, errbuf))) | |
{ | |
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", dev->name); | |
pcap_freealldevs(alldevs); | |
return -1; | |
} | |
// only deal with Ethernet device | |
if(pcap_datalink(fp) != DLT_EN10MB) | |
{ | |
fprintf(stderr,"\nThis program works only on Ethernet networks.\n"); | |
pcap_freealldevs(alldevs); | |
return -1; | |
} | |
if(NULL != dev->addresses && NULL != dev->addresses->netmask) | |
// get address mask | |
netmask = ((struct sockaddr_in *)(dev->addresses->netmask))->sin_addr.s_addr; | |
else | |
// set default net mask as a C class net | |
netmask = 0xffffff; | |
// compile filter argument | |
if (pcap_compile(fp, &fcode, packet_filter, 1, netmask) < 0) | |
{ | |
fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n"); | |
// if err, release infomation and exit | |
pcap_freealldevs(alldevs); | |
return -1; | |
} | |
// set filter to device | |
if (pcap_setfilter(fp, &fcode) < 0) | |
{ | |
fprintf(stderr,"\nError setting the filter.\n"); | |
// if err, release infomation and exit | |
pcap_freealldevs(alldevs); | |
return -1; | |
} | |
printf("\nlistening on %s...\n", dev->name); | |
// release all devices information | |
pcap_freealldevs(alldevs); | |
// capture pkt with callback `packet_handler` | |
pcap_loop(fp, 0, packet_handler, NULL); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment