C Packet Sniffer Code with Libpcap and Linux Sockets (BSD)
Libpcap is a packe capture library which can be used to sniff packets or network traffic over a network interface. Pcap Documentation gives a description of the methods and data structures available in the libpcap library.
To install libpcap on your linux distro you can either download the source from the website and compile it and install. Or if you are on a distro like ubuntu then it can be installed from synaptic package manager. In the list of packages in Synaptic Package Manager look for 2 packages named as libpcap0.8 and libpcap0.8-dev. Install both of them.
To start with the C program the simple steps would be :
1. Find all available devices – find_alldevs()
find_alldevs() is the function which can be used to get a list of all available network devices or interfaces present on the machine or which can be opened by pcap_open_live() for sniffing purpose.
The prototype is as :
int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
where alldevsp is a pointer to an array of of pcap_if_t structures and errbuf is a character pointer and will contain any error message that occured during the function call.
2. Select a device for sniffing data – pcap_open_live()
pcap_open_live() is the function to get a packet capture descriptor or a handle to a device which has been opened up for sniffing. The protoype is as :
pcap_t *pcap_open_live(const char *device, int snaplen,int promisc, int to_ms, char *errbuf)
device – is the name of the device as obtained from the call to pcap_findalldevs.
snaplen – is the maximum amount of data to be captured. 65536 should be sufficient length.
promisc – 0 or 1 to indicate whether to open the device in promiscuous mode.
to_ms – the timeout in milliseconds , 0 for no timeout
errbuf – buffer to contain any error message
It returns a device handler in the form of the structure pcap_t which can be used by pcap_loop() to capture data from.
3. Start sniffing the device – pcap_loop()
4. Process the sniffed packet – user defined callback method
Code :
/*
Packet sniffer using libpcap library
*/
#include<pcap.h>
#include<stdio.h>
#include<net/ethernet.h>
#include<netinet/ip_icmp.h> //Provides declarations for icmp header
#include<netinet/udp.h> //Provides declarations for udp header
#include<netinet/tcp.h> //Provides declarations for tcp header
#include<netinet/ip.h> //Provides declarations for ip header
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
void process_ip_packet(unsigned char* , int);
void print_ip_header(unsigned char* , int);
void print_tcp_header(unsigned char* buffer , int size);
void print_udp_header(unsigned char* , int);
FILE *logfile;
struct sockaddr_in source,dest;
int main()
{
pcap_if_t alldevsp[100] , *device;
pcap_t *handle; //Handle of the device that shall be sniffed
char errbuf[100] , *devname , **devs;
int count = 1 , n;
//First get the list of available devices
printf("Finding available devices ... ");
if(pcap_findalldevs(&alldevsp, errbuf))
{
printf("Error finding devices : %s" , errbuf);
exit(1);
}
printf("Done");
//Print the available devices
printf("nAvailable Devices are :n");
device = alldevsp;
while(device != NULL)
{
*(devs + count) = device->name;
printf("%d. %s - %sn", count++ , device->name , device->description);
device = device->next;
}
//Ask user which device to sniff
printf("Enter the number of the device you want to sniff : ");
scanf("%d" , &n);
devname = *(devs + count - 1);
//Open the device for sniffing
printf("Opening device for sniffing ... ");
handle = pcap_open_live("eth0" , 65536 , 1 , 0 , errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device eth0 : %sn" , errbuf);
exit(1);
}
printf("Donen");
logfile=fopen("log.txt","w");
if(logfile==NULL) printf("Unable to create file.");
//Put the device in sniff loop
pcap_loop(handle , -1 , process_packet , NULL);
return 0;
}
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
int size = header->len;
struct ether_header *ethh;
ethh = (struct ether_header *)packet;
//Print the ethernet header in the log file
if(ntohs(ethh->ether_type) == ETHERTYPE_IP)
{
process_ip_packet(packet + sizeof *ethh , size - sizeof ethh);
printf("%d" , sizeof *ethh);
fflush(stdout);
}
return 0;
}
void process_ip_packet(unsigned char* buffer, int size)
{
//Get the IP Header part of this packet
struct iphdr *iph = (struct iphdr*)buffer;
switch (iph->protocol) //Check the Protocol and do accordingly...
{
case 1: //ICMP Protocol
//PrintIcmpPacket(Buffer,Size);
break;
case 2: //IGMP Protocol
break;
case 6: //TCP Protocol
print_tcp_packet(buffer , size);
break;
case 17: //UDP Protocol
print_udp_packet(buffer , size);
break;
default: //Some Other Protocol like ARP etc.
break;
}
}
void print_ip_header(unsigned char* Buffer, int Size)
{
unsigned short iphdrlen;
struct iphdr *iph = (struct iphdr *)Buffer;
iphdrlen =iph->ihl*4;
memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = iph->saddr;
memset(&dest, 0, sizeof(dest));
dest.sin_addr.s_addr = iph->daddr;
fprintf(logfile,"n");
fprintf(logfile,"IP Headern");
fprintf(logfile," |-IP Version : %dn",(unsigned int)iph->version);
fprintf(logfile," |-IP Header Length : %d DWORDS or %d Bytesn",(unsigned int)iph->ihl,((unsigned int)(iph->ihl))*4);
fprintf(logfile," |-Type Of Service : %dn",(unsigned int)iph->tos);
fprintf(logfile," |-IP Total Length : %d Bytes(Size of Packet)n",ntohs(iph->tot_len));
fprintf(logfile," |-Identification : %dn",ntohs(iph->id));
//fprintf(logfile," |-Reserved ZERO Field : %dn",(unsigned int)iphdr->ip_reserved_zero);
//fprintf(logfile," |-Dont Fragment Field : %dn",(unsigned int)iphdr->ip_dont_fragment);
//fprintf(logfile," |-More Fragment Field : %dn",(unsigned int)iphdr->ip_more_fragment);
fprintf(logfile," |-TTL : %dn",(unsigned int)iph->ttl);
fprintf(logfile," |-Protocol : %dn",(unsigned int)iph->protocol);
fprintf(logfile," |-Checksum : %dn",ntohs(iph->check));
fprintf(logfile," |-Source IP : %sn",inet_ntoa(source.sin_addr));
fprintf(logfile," |-Destination IP : %sn",inet_ntoa(dest.sin_addr));
}
void print_tcp_packet(unsigned char* Buffer, int Size)
{
unsigned short iphdrlen;
struct iphdr *iph = (struct iphdr *)Buffer;
iphdrlen = iph->ihl*4;
struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen);
fprintf(logfile,"nn***********************TCP Packet*************************n");
print_ip_header(Buffer,Size);
fprintf(logfile,"n");
fprintf(logfile,"TCP Headern");
fprintf(logfile," |-Source Port : %un",ntohs(tcph->source));
fprintf(logfile," |-Destination Port : %un",ntohs(tcph->dest));
fprintf(logfile," |-Sequence Number : %un",ntohl(tcph->seq));
fprintf(logfile," |-Acknowledge Number : %un",ntohl(tcph->ack_seq));
fprintf(logfile," |-Header Length : %d DWORDS or %d BYTESn" ,(unsigned int)tcph->doff,(unsigned int)tcph->doff*4);
//fprintf(logfile," |-CWR Flag : %dn",(unsigned int)tcph->cwr);
//fprintf(logfile," |-ECN Flag : %dn",(unsigned int)tcph->ece);
fprintf(logfile," |-Urgent Flag : %dn",(unsigned int)tcph->urg);
fprintf(logfile," |-Acknowledgement Flag : %dn",(unsigned int)tcph->ack);
fprintf(logfile," |-Push Flag : %dn",(unsigned int)tcph->psh);
fprintf(logfile," |-Reset Flag : %dn",(unsigned int)tcph->rst);
fprintf(logfile," |-Synchronise Flag : %dn",(unsigned int)tcph->syn);
fprintf(logfile," |-Finish Flag : %dn",(unsigned int)tcph->fin);
fprintf(logfile," |-Window : %dn",ntohs(tcph->window));
fprintf(logfile," |-Checksum : %dn",ntohs(tcph->check));
fprintf(logfile," |-Urgent Pointer : %dn",tcph->urg_ptr);
fprintf(logfile,"n");
fprintf(logfile," DATA Dump ");
fprintf(logfile,"n");
fprintf(logfile,"IP Headern");
PrintData(Buffer,iphdrlen);
fprintf(logfile,"TCP Headern");
PrintData(Buffer+iphdrlen,tcph->doff*4);
fprintf(logfile,"Data Payloadn");
PrintData(Buffer + iphdrlen + tcph->doff*4 , (Size - tcph->doff*4-iph->ihl*4) );
fprintf(logfile,"n###########################################################");
}
void print_udp_packet(unsigned char *Buffer , int Size)
{
unsigned short iphdrlen;
struct iphdr *iph = (struct iphdr *)Buffer;
iphdrlen = iph->ihl*4;
struct udphdr *udph = (struct udphdr*)(Buffer + iphdrlen);
fprintf(logfile,"nn***********************UDP Packet*************************n");
print_ip_header(Buffer,Size);
fprintf(logfile,"nUDP Headern");
fprintf(logfile," |-Source Port : %dn" , ntohs(udph->source));
fprintf(logfile," |-Destination Port : %dn" , ntohs(udph->dest));
fprintf(logfile," |-UDP Length : %dn" , ntohs(udph->len));
fprintf(logfile," |-UDP Checksum : %dn" , ntohs(udph->check));
fprintf(logfile,"n");
fprintf(logfile,"IP Headern");
PrintData(Buffer , iphdrlen);
fprintf(logfile,"UDP Headern");
PrintData(Buffer+iphdrlen , sizeof udph);
fprintf(logfile,"Data Payloadn");
PrintData(Buffer + iphdrlen + sizeof udph ,( Size - sizeof udph - iph->ihl * 4 ));
fprintf(logfile,"n###########################################################");
}
void print_icmp_packet(unsigned char* Buffer , int Size)
{
unsigned short iphdrlen;
struct iphdr *iph = (struct iphdr *)Buffer;
iphdrlen = iph->ihl*4;
struct icmphdr *icmph = (struct icmphdr *)(Buffer + iphdrlen);
fprintf(logfile,"nn***********************ICMP Packet*************************n");
print_ip_header(Buffer , Size);
fprintf(logfile,"n");
fprintf(logfile,"ICMP Headern");
fprintf(logfile," |-Type : %d",(unsigned int)(icmph->type));
if((unsigned int)(icmph->type) == 11)
fprintf(logfile," (TTL Expired)n");
else if((unsigned int)(icmph->type) == ICMP_ECHOREPLY)
fprintf(logfile," (ICMP Echo Reply)n");
fprintf(logfile," |-Code : %dn",(unsigned int)(icmph->code));
fprintf(logfile," |-Checksum : %dn",ntohs(icmph->checksum));
//fprintf(logfile," |-ID : %dn",ntohs(icmph->id));
//fprintf(logfile," |-Sequence : %dn",ntohs(icmph->sequence));
fprintf(logfile,"n");
fprintf(logfile,"IP Headern");
PrintData(Buffer,iphdrlen);
fprintf(logfile,"UDP Headern");
PrintData(Buffer + iphdrlen , sizeof icmph);
fprintf(logfile,"Data Payloadn");
PrintData(Buffer + iphdrlen + sizeof icmph , (Size - sizeof icmph - iph->ihl * 4));
fprintf(logfile,"n###########################################################");
}
void PrintData (unsigned char* data , int Size)
{
int i,j;
for(i=0 ; i < Size ; i++)
{
if( i!=0 && i%16==0) //if one line of hex printing is complete...
{
fprintf(logfile," ");
for(j=i-16 ; j<i ; j++)
{
if(data[j]>=32 && data[j]<=128)
fprintf(logfile,"%c",(unsigned char)data[j]); //if its a number or alphabet
else fprintf(logfile,"."); //otherwise print a dot
}
fprintf(logfile,"n");
}
if(i%16==0) fprintf(logfile," ");
fprintf(logfile," %02X",(unsigned int)data[i]);
if( i==Size-1) //print the last spaces
{
for(j=0;j<15-i%16;j++) fprintf(logfile," "); //extra spaces
fprintf(logfile," ");
for(j=i-i%16 ; j<=i ; j++)
{
if(data[j]>=32 && data[j]<=128) fprintf(logfile,"%c",(unsigned char)data[j]);
else fprintf(logfile,".");
}
fprintf(logfile,"n");
}
}
}
Compile : gcc sniffer.c -lpcap -o sniffer
Run : sudo ./sniffer
The program requires superuser or root privileges to be able to sniff the packets.
Wireshark(previously ethereal) and tcpdump are examples of applications which use the libpcap library on linux to capture packet data.
Popularity: 9% [?]
















Thanks a lot. I’ve just started out with libpcap, so this serves as a good intro.