Packet Sniffer Code in C using Linux Sockets (BSD)

To code a sniffer in C (Linux) the steps would be :

1. Create a Raw Socket.
2. Put it in a recvfrom loop.

A raw socket when put in recvfrom receives all incoming packets. The following code shows an example of such a sniffer. Note that it sniffs only incoming packets. For sniffing all traffic on a network a packet capture library like libpcap can be used.

Code : sniffer.c

#include<netinet/in.h>
#include<errno.h>
#include<netdb.h>
#include<stdio.h>	//For standard things
#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
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>

void ProcessPacket(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);

int sock_raw;
FILE *logfile;
int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0,i,j;
struct sockaddr_in source,dest;

int main()
{
	int saddr_size , data_size;
	struct sockaddr_in saddr;
	struct in_addr in;

	unsigned char *buffer = (unsigned char *)malloc(65536); //Its Big!

	logfile=fopen("log.txt","w");
	if(logfile==NULL) printf("Unable to create file.");
	printf("Starting...n");
	//Create a raw socket that shall sniff
	sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
	if(sock_raw < 0)
	{
		printf("Socket Errorn");
		return 1;
	}
	while(1)
	{
		saddr_size = sizeof saddr;
		//Receive a packet
		data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , &saddr_size);
		if(data_size <0 )
		{
			printf("Recvfrom error , failed to get packetsn");
			return 1;
		}
		//Now process the packet
		ProcessPacket(buffer , data_size);
	}
	close(sock_raw);
	printf("Finished");
	return 0;
}

void ProcessPacket(unsigned char* buffer, int size)
{
	//Get the IP Header part of this packet
	struct iphdr *iph = (struct iphdr*)buffer;
	++total;
	switch (iph->protocol) //Check the Protocol and do accordingly...
	{
		case 1:  //ICMP Protocol
			++icmp;
			//PrintIcmpPacket(Buffer,Size);
			break;

		case 2:  //IGMP Protocol
			++igmp;
			break;

		case 6:  //TCP Protocol
			++tcp;
			print_tcp_packet(buffer , size);
			break;

		case 17: //UDP Protocol
			++udp;
			print_udp_packet(buffer , size);
			break;

		default: //Some Other Protocol like ARP etc.
			++others;
			break;
	}
	printf("TCP : %d   UDP : %d   ICMP : %d   IGMP : %d   Others : %d   Total : %dr",tcp,udp,icmp,igmp,others,total);
}

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)
{

	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

The program must be run as root user or superuser privileges. e.g. sudo ./a.out in ubuntu
The program creates raw sockets which require root access.

Popularity: 31% [?]

3 Responses to “Packet Sniffer Code in C using Linux Sockets (BSD)”

  1. pleas have you a windows version of sniffer

    badr-bari@hotmail.com

  2. hi
    i have bee trying to run the above c program in my system but its not working. Though the compilation is done with some warnings but the execution gets stuck.Log file is created but its blank.
    i want to know if i am doing it right way or some other steps are involved.
    the program doesn’t ask any port address to sniff data from.

    Please help
    Thank you

  3. @sumit

    The above program will work if you edit the statement
    sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP); to
    sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_UDP);

    (atleast in my case it was working)
    but there’s still a bug
    it just filters out the UDP Packets.
    also if anyone can help me with how to enable timestamp option in IP packets

Leave a Reply