In the previous part we made a simple sniffer which created a raw socket and started receiving on it. But it had few drawbacks :
1. Could sniff only incoming data.
2. Could sniff only TCP or UDP or ICMP or any one protocol packets at a time.
3. Ethernet headers were not available.
In this article we are going to modify the same code to fix the above 3 drawbacks. We shall be using just linux sockets for sniffing.
Sniffing Ethernet headers
The sniffer program shown in this article will sniff the whole packet, such that the ethernet headers will also be available.
To sniff the ethernet headers we just need to create a socket with some special parameters as shown below.
Instead of :
sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
We do :
sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ; //Optional //setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , "eth0" , strlen("eth0")+ 1 );
The third parameter htons(ETH_P_ALL) enables the socket to read full packet content including the ethernet headers.
Now it will :
1. Sniff both incoming and outgoing traffic. 2. Sniff ALL ETHERNET FRAMES , which includes all kinds of IP packets and even more if there are any. 3. Provides the Ethernet headers too , which contain the mac addresses.
The setsockopt line is optional.
Its important to provide the correct interface name to setsockopt , eth0 in this case and in most cases.
So may be you would like to present the user with a list of interfaces available and allow him to choose the one to be sniffed.
Full Code
#include<netinet/in.h> #include<errno.h> #include<netdb.h> #include<stdio.h> //For standard things #include<stdlib.h> //malloc #include<string.h> //strlen #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<netinet/if_ether.h> //For ETH_P_ALL #include<net/ethernet.h> //For ether_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_packet(unsigned char * , int ); void print_udp_packet(unsigned char * , int ); void print_icmp_packet(unsigned char* , int ); void PrintData (unsigned char* , int); FILE *logfile; struct sockaddr_in source,dest; int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0,i,j; int main() { int saddr_size , data_size; struct sockaddr saddr; unsigned char *buffer = (unsigned char *) malloc(65536); //Its Big! logfile=fopen("log.txt","w"); if(logfile==NULL) { printf("Unable to create log.txt file."); } printf("Starting...\n"); int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ; //setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , "eth0" , strlen("eth0")+ 1 ); if(sock_raw < 0) { //Print the error with proper message perror("Socket Error"); return 1; } while(1) { saddr_size = sizeof saddr; //Receive a packet data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size); if(data_size <0 ) { printf("Recvfrom error , failed to get packets\n"); 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 , excluding the ethernet header struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr)); ++total; switch (iph->protocol) //Check the Protocol and do accordingly... { case 1: //ICMP Protocol ++icmp; print_icmp_packet( 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 : %d\r", tcp , udp , icmp , igmp , others , total); } void print_ethernet_header(unsigned char* Buffer, int Size) { struct ethhdr *eth = (struct ethhdr *)Buffer; fprintf(logfile , "\n"); fprintf(logfile , "Ethernet Header\n"); fprintf(logfile , " |-Destination Address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X \n", eth->h_dest[0] , eth->h_dest[1] , eth->h_dest[2] , eth->h_dest[3] , eth->h_dest[4] , eth->h_dest[5] ); fprintf(logfile , " |-Source Address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X \n", eth->h_source[0] , eth->h_source[1] , eth->h_source[2] , eth->h_source[3] , eth->h_source[4] , eth->h_source[5] ); fprintf(logfile , " |-Protocol : %u \n",(unsigned short)eth->h_proto); } void print_ip_header(unsigned char* Buffer, int Size) { print_ethernet_header(Buffer , Size); unsigned short iphdrlen; struct iphdr *iph = (struct iphdr *)(Buffer + sizeof(struct ethhdr) ); 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 Header\n"); fprintf(logfile , " |-IP Version : %d\n",(unsigned int)iph->version); fprintf(logfile , " |-IP Header Length : %d DWORDS or %d Bytes\n",(unsigned int)iph->ihl,((unsigned int)(iph->ihl))*4); fprintf(logfile , " |-Type Of Service : %d\n",(unsigned int)iph->tos); fprintf(logfile , " |-IP Total Length : %d Bytes(Size of Packet)\n",ntohs(iph->tot_len)); fprintf(logfile , " |-Identification : %d\n",ntohs(iph->id)); //fprintf(logfile , " |-Reserved ZERO Field : %d\n",(unsigned int)iphdr->ip_reserved_zero); //fprintf(logfile , " |-Dont Fragment Field : %d\n",(unsigned int)iphdr->ip_dont_fragment); //fprintf(logfile , " |-More Fragment Field : %d\n",(unsigned int)iphdr->ip_more_fragment); fprintf(logfile , " |-TTL : %d\n",(unsigned int)iph->ttl); fprintf(logfile , " |-Protocol : %d\n",(unsigned int)iph->protocol); fprintf(logfile , " |-Checksum : %d\n",ntohs(iph->check)); fprintf(logfile , " |-Source IP : %s\n",inet_ntoa(source.sin_addr)); fprintf(logfile , " |-Destination IP : %s\n",inet_ntoa(dest.sin_addr)); } void print_tcp_packet(unsigned char* Buffer, int Size) { unsigned short iphdrlen; struct iphdr *iph = (struct iphdr *)( Buffer + sizeof(struct ethhdr) ); iphdrlen = iph->ihl*4; struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr)); int header_size = sizeof(struct ethhdr) + iphdrlen + tcph->doff*4; fprintf(logfile , "\n\n***********************TCP Packet*************************\n"); print_ip_header(Buffer,Size); fprintf(logfile , "\n"); fprintf(logfile , "TCP Header\n"); fprintf(logfile , " |-Source Port : %u\n",ntohs(tcph->source)); fprintf(logfile , " |-Destination Port : %u\n",ntohs(tcph->dest)); fprintf(logfile , " |-Sequence Number : %u\n",ntohl(tcph->seq)); fprintf(logfile , " |-Acknowledge Number : %u\n",ntohl(tcph->ack_seq)); fprintf(logfile , " |-Header Length : %d DWORDS or %d BYTES\n" ,(unsigned int)tcph->doff,(unsigned int)tcph->doff*4); //fprintf(logfile , " |-CWR Flag : %d\n",(unsigned int)tcph->cwr); //fprintf(logfile , " |-ECN Flag : %d\n",(unsigned int)tcph->ece); fprintf(logfile , " |-Urgent Flag : %d\n",(unsigned int)tcph->urg); fprintf(logfile , " |-Acknowledgement Flag : %d\n",(unsigned int)tcph->ack); fprintf(logfile , " |-Push Flag : %d\n",(unsigned int)tcph->psh); fprintf(logfile , " |-Reset Flag : %d\n",(unsigned int)tcph->rst); fprintf(logfile , " |-Synchronise Flag : %d\n",(unsigned int)tcph->syn); fprintf(logfile , " |-Finish Flag : %d\n",(unsigned int)tcph->fin); fprintf(logfile , " |-Window : %d\n",ntohs(tcph->window)); fprintf(logfile , " |-Checksum : %d\n",ntohs(tcph->check)); fprintf(logfile , " |-Urgent Pointer : %d\n",tcph->urg_ptr); fprintf(logfile , "\n"); fprintf(logfile , " DATA Dump "); fprintf(logfile , "\n"); fprintf(logfile , "IP Header\n"); PrintData(Buffer,iphdrlen); fprintf(logfile , "TCP Header\n"); PrintData(Buffer+iphdrlen,tcph->doff*4); fprintf(logfile , "Data Payload\n"); PrintData(Buffer + header_size , Size - header_size ); fprintf(logfile , "\n###########################################################"); } void print_udp_packet(unsigned char *Buffer , int Size) { unsigned short iphdrlen; struct iphdr *iph = (struct iphdr *)(Buffer + sizeof(struct ethhdr)); iphdrlen = iph->ihl*4; struct udphdr *udph = (struct udphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr)); int header_size = sizeof(struct ethhdr) + iphdrlen + sizeof udph; fprintf(logfile , "\n\n***********************UDP Packet*************************\n"); print_ip_header(Buffer,Size); fprintf(logfile , "\nUDP Header\n"); fprintf(logfile , " |-Source Port : %d\n" , ntohs(udph->source)); fprintf(logfile , " |-Destination Port : %d\n" , ntohs(udph->dest)); fprintf(logfile , " |-UDP Length : %d\n" , ntohs(udph->len)); fprintf(logfile , " |-UDP Checksum : %d\n" , ntohs(udph->check)); fprintf(logfile , "\n"); fprintf(logfile , "IP Header\n"); PrintData(Buffer , iphdrlen); fprintf(logfile , "UDP Header\n"); PrintData(Buffer+iphdrlen , sizeof udph); fprintf(logfile , "Data Payload\n"); //Move the pointer ahead and reduce the size of string PrintData(Buffer + header_size , Size - header_size); fprintf(logfile , "\n###########################################################"); } void print_icmp_packet(unsigned char* Buffer , int Size) { unsigned short iphdrlen; struct iphdr *iph = (struct iphdr *)(Buffer + sizeof(struct ethhdr)); iphdrlen = iph->ihl * 4; struct icmphdr *icmph = (struct icmphdr *)(Buffer + iphdrlen + sizeof(struct ethhdr)); int header_size = sizeof(struct ethhdr) + iphdrlen + sizeof icmph; fprintf(logfile , "\n\n***********************ICMP Packet*************************\n"); print_ip_header(Buffer , Size); fprintf(logfile , "\n"); fprintf(logfile , "ICMP Header\n"); 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 : %d\n",(unsigned int)(icmph->code)); fprintf(logfile , " |-Checksum : %d\n",ntohs(icmph->checksum)); //fprintf(logfile , " |-ID : %d\n",ntohs(icmph->id)); //fprintf(logfile , " |-Sequence : %d\n",ntohs(icmph->sequence)); fprintf(logfile , "\n"); fprintf(logfile , "IP Header\n"); PrintData(Buffer,iphdrlen); fprintf(logfile , "UDP Header\n"); PrintData(Buffer + iphdrlen , sizeof icmph); fprintf(logfile , "Data Payload\n"); //Move the pointer ahead and reduce the size of string PrintData(Buffer + header_size , (Size - header_size) ); 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" ); } } }
The log file will looks somewhat like this :
***********************TCP Packet************************* Ethernet Header |-Destination Address : 00-25-5E-1A-3D-F1 |-Source Address : 00-1C-C0-F8-79-EE |-Protocol : 8 IP Header |-IP Version : 4 |-IP Header Length : 5 DWORDS or 20 Bytes |-Type Of Service : 0 |-IP Total Length : 141 Bytes(Size of Packet) |-Identification : 13122 |-TTL : 64 |-Protocol : 6 |-Checksum : 45952 |-Source IP : 192.168.1.6 |-Destination IP : 74.125.71.125 TCP Header |-Source Port : 33655 |-Destination Port : 5222 |-Sequence Number : 78458457 |-Acknowledge Number : 2427066746 |-Header Length : 5 DWORDS or 20 BYTES |-Urgent Flag : 0 |-Acknowledgement Flag : 1 |-Push Flag : 1 |-Reset Flag : 0 |-Synchronise Flag : 0 |-Finish Flag : 0 |-Window : 62920 |-Checksum : 21544 |-Urgent Pointer : 0 DATA Dump IP Header 00 25 5E 1A 3D F1 00 1C C0 F8 79 EE 08 00 45 00 .%^.=.....y...E. 00 8D 33 42 ..3B TCP Header 40 00 40 06 B3 80 C0 A8 01 06 4A 7D 47 7D 83 77 @.@..?....J}G}.w 14 66 04 AD .f.. Data Payload 17 03 01 00 60 A0 9C 5D 14 A1 25 AB CE 8B 7C EB ....`..]..%...|. 1A A4 43 A6 60 DD E8 6B 6E 43 C1 94 6A D2 25 23 ..C.`..knC..j.%# 03 98 59 67 1A 2C 07 D3 7E B2 B8 9F 83 38 4C 69 ..Yg.,..~....8Li D3 3A 8E 0D 9E F0 6B CE 9E 6B F4 E1 BD 9E 50 53 .:....k..k....PS 6D F6 AB 11 05 D6 41 82 F0 03 0C A6 E2 48 2B 71 m.....A......H+q 16 81 FF 5B DF 50 D4 5B AD 90 04 5E 4C 94 E7 9B ...[.P.[...^L... 0B 72 7E 32 88 .r~2. ###########################################################
In the above log we can see the ethernet headers being printed. They show the source and destination mac address along with the packet protocol. 8 means IP protocol
Note :
1. If you want to sniff only IP and ARP packets for example then you can try this :
sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_IP|ETH_P_ARP)) ;
The complete list of protocols is found in /usr/include/linux/if_ether.h
/* * These are the defined Ethernet Protocol ID's. */ #define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ #define ETH_P_PUP 0x0200 /* Xerox PUP packet */ #define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */ #define ETH_P_IP 0x0800 /* Internet Protocol packet */ #define ETH_P_X25 0x0805 /* CCITT X.25 */ #define ETH_P_ARP 0x0806 /* Address Resolution packet */ #define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */ #define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */ #define ETH_P_DEC 0x6000 /* DEC Assigned proto */ #define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */ #define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */ #define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */ #define ETH_P_LAT 0x6004 /* DEC LAT */ #define ETH_P_DIAG 0x6005 /* DEC Diagnostics */ #define ETH_P_CUST 0x6006 /* DEC Customer use */ #define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */ #define ETH_P_TEB 0x6558 /* Trans Ether Bridging */ #define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ #define ETH_P_ATALK 0x809B /* Appletalk DDP */ #define ETH_P_AARP 0x80F3 /* Appletalk AARP */ #define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ #define ETH_P_IPX 0x8137 /* IPX over DIX */ #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ #define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */ #define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ #define ETH_P_WCCP 0x883E /* Web-cache coordination protocol * defined in draft-wilson-wrec-wccp-v2-00.txt */ #define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ #define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ #define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */ #define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */ #define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ #define ETH_P_LINK_CTL 0x886c /* HPNA, wlan link local tunnel */ #define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport * over Ethernet */ #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ #define ETH_P_TIPC 0x88CA /* TIPC */ #define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ #define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ #define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ #define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ /* * Non DIX types. Won't clash for 1500 types. */ #define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */ #define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */ #define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ #define ETH_P_802_2 0x0004 /* 802.2 frames */ #define ETH_P_SNAP 0x0005 /* Internal only */ #define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */ #define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/ #define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */ #define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */ #define ETH_P_CAN 0x000C /* Controller Area Network */ #define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/ #define ETH_P_TR_802_2 0x0011 /* 802.2 frames */ #define ETH_P_MOBITEX 0x0015 /* Mobitex ([email protected]) */ #define ETH_P_CONTROL 0x0016 /* Card specific control frames */ #define ETH_P_IRDA 0x0017 /* Linux-IrDA */ #define ETH_P_ECONET 0x0018 /* Acorn Econet */ #define ETH_P_HDLC 0x0019 /* HDLC frames */ #define ETH_P_ARCNET 0x001A /* 1A for ArcNet :-) */ #define ETH_P_DSA 0x001B /* Distributed Switch Arch. */ #define ETH_P_TRAILER 0x001C /* Trailer switch tagging */ #define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */ #define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */ #define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */
Enjoy!!
Hi… Thank you for the Excellent Tutorials and practical program examples.
I was trying to sniff only ARP/RARP and DHCP (or if needed BootP) packets on my network, because it is a mix of DHCP and static IP configurations. I was wondering what would be the values in the third option of the socket(…,…,???) function?
Help would be greatly appreciated.
Thanks..
“1. Sniff both incoming and outgoing traffic.”
Outgoing is only in ETH_P_ALL option? or can i set custom protocol and filter outgoing traffic ?
Hey there !
First up: Thank you mate, you helped me alot.
But I got one question: Are you sure:
sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_IP|ETH_P_ARP)) ;
works this way ? I Tried to filter IPV4 (0x8000) and a fieldbus protocol (0x8892) but I cant seem to make it work. For some reason it only detects the fieldbus protocol. I tested each protocol seperatly and it works fine. My line of code looks like this:
sock_raw = socket( AF_PACKET , SOCK_RAW , htons(0x8000|0x8892)) ;
Maybe you got an idea.
you deserve a medal for this! Thank you!
thanks for the comment.
glad that you liked the post.
Hi
I am struggling to use source code (part 2). Unfortunately I don’t have experience how to use source code, so what I did was copied the code into a file using
vi capture-
then saved the file and issued
chmod u+x capture-
[root@server ~]# ./capture-
./capture-code: line 21: syntax error near unexpected token `(‘
./capture-code: line 21: `void ProcessPacket(unsigned char* , int);’
Please advise how to get this working. More over can I save the captured data in a format to be opened with Wireshark ?
Thanks
good example, learned!
i come here as libpcap drop udp packet, after some google, they tell me the pcap_setuserbuf not implement for linux, so I have to use raw sock, you showed a good sample code.
thank you.
my website is http://www.crobsoft.com
can someone please explain me more details about this code
Hi, I think the hyperlink “previous part” is not working! I wanted to write a C/C++ program that make use of divert sockets (FreeBSD) which will block all incoming icmp packets. Any clue on how to do that ? Thanks in advance.
Hi,
I want to capture a random tcp packet.
The program has to run as an ordinary user.
Any idea, how this can be done?
If it is not possible to capture tcp packet, is it possible to capture a http packet or any other protocol packet?
Please suggest.
Thanks,
Narendra
this code works on my centos 6.8 i386, but I also did some fixes.
if you just copy & paste on your platform, it may show compile error.
you have to refer to your include files to fix those issues.
there are a lot of different in the struct.
Will this work on other distributions? I’m about to install kali and I use this as a guide for my project so that information will be helpful to me a lot
this program is not displaying apllication layer headers.
can you help me with this please
how to display apllcation layer prtocol headers in this program?
If I want the program to show MAC address . Could you tell me about that . Thanks.
just to tell i notice an error in your code for all Print functions you forgot to shift before writting data.
fprintf(stdout,”IP Header\n”);
Print_data((pkt + sizeof(struct ethhdr)),s_iph);
fprintf(stdout,”TCP Header\n”);
Print_data(pkt + sizeof(struct ethhdr) + s_iph,tcph->doff * 4);
fprintf(stdout,”Data Payload\n”);
Print_data(pkt + sizeof(struct ethhdr) + s_iph + tcph->doff * 4, (s_pkt – tcph->doff * 4 – s_iph – sizeof(struct ethhdr)));
Very nice piece of code. One question – If I want to read UDP only from a single interface (eth1), but I want the full ethernet frame passed along, is that possible?
thank you for this.
when i compile your code in my mac book early pro it will show these errors
sniff.c:44:28: error: use of undeclared identifier ‘AF_PACKET’
int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;
^
sniff.c:44:57: error: use of undeclared identifier ‘ETH_P_ALL’
int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;
is there any way to block packet. i mean listen incoming traffic and block them if its http protocol
Hi… Is it possible to capture wireless packets using the above code?? How to specify the interface in which the packets captured??
I changed the piece of code as below, but it is not capturing the packets coming from wireless interface.
It is capturing the packets from other interfaces, but not specifically on wlan0
setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , “wlan0” , strlen(“wlan0”)+ 1 );
Good example!!! It is helpful for me. Thank you.
Hi dude, first, thank you so much for this very clean, elegant and simple approach. I have a question, how can filter LLC packets? Yes, I’ve read that the ETH_P_802_2 variable aids to do this work, but I want to know, if existe a type (like 0x0800) for this type of protocol. Merci beaucoup!
Is it possible to capture all the packets in the network through raw sockets like libpcap.
With this code able to capture all the packets with source/destination as our IP, but not capturing packets with out our Ip. please help.
Thanks so much for this! I’ve been hassling with Python to get raw packets for weeks now. This is more my element.
how can I display the IP address of the system who is sending the packet??
Hello,
How to capture ARP packets?
What should I implement the code?
Thank you!
the code actually captures all ethernet packets including arp packets.
In case of ARP packets the protocol field of the ethernet header would contain the value 0x0806
So you can check like this
if( ntohs(eth->h_proto) == 0x0806 ) { // arp packet, process }
thats the basic idea, you would need to parse the arp packet according to its packet structure, details of which can found on google.
Hello,
Thank you for the code.
In my application I try to sniff all the incoming data.
My application run correctly only if wireshark run in the same time !
Could you help me to find some clues ?
thank you for the code which will help me a lot. My question is These received packets are saved in a text file. but i want to know infact my project is about saving the captured packets in a binary file. how do i do this ? i checked with your code and replaced fprintf to ‘fwrite’ . but i am not able to find the solution sir
Dear Moon,
As part of academic lab program , I had a lab content “Working with sniffer for monitoring network communication(Ethereal)” . Tell me , your code will work on Windows Turbo C environment ? Is that code satisfy
our requirement . please advise fast
Thanks,
Anes
Thanks for providing this code. This helps to me a lot. I have a one question? How to extract and print vlan_id and vlan_tag from the vlan tagged packets? or which modification in this code are needed to do the same? Please help me for providing proper answer.
Thanks in advance.
Based on my understanding reading the raw socket document, basically all the known type of packets for example (TCP/IP) will be passed to the kernel stack and a copy is sent to the raw socket. Is there a way not to send any packets to the kernel stack and only send to the raw socket? I want to controll all the incoming and out going packet through the raw socket application. Thank in advance. Anuar.
void convrt(const u_char * Buffer, int Size)
{
unsigned short iphdrlen;
struct iphdr *iph = (struct iphdr *)( Buffer + sizeof(struct ethhdr) );
iphdrlen = iph->ihl*4;
struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr));
int header_size = sizeof(struct ethhdr) + iphdrlen + tcph->doff*4;
char typ[65536];
//typ = Buffer + header_size;
//strncpy(typ, Buffer + header_size, Size – header_size);
int i,j;
for(i=0;i <= Size – header_size; i++)
{
typ[i] = *(Buffer+header_size+i);
}
for(j=0;j<= Size-header_size; j++)
{
printf("%c",(unsigned int)typ[j]);
}
}
i wrote this additional function and i call it in the program, want to return whatever the printf() is diplaying as a char* but whenever i try to do that i guess there is some UB and the program just closes. how can i acomplish that?? plz. or how can i make this function return a string??
Hello, i’m trying to adapt your code to analyze an IP packet captured with a breakout on a serial port. I capture a PPP packet and after analyze it i extract the IP packet i need to obtain the data into it.
For example, this is a PPP packet: ff 03 21 45 00 00 3d 04 46 40 00 7c 06 f7 6b 0a 1f ed ce 0a 08 01 14 10 14 42 69 92 a2 cd 08 9a 49 56 38 50 18 44 70 10 80 00 00 68 0f 0f 68 c4 14 01 c9 01 06 00 14 01 fc f8 c7 51 01 14 df 16 ca 4e
After analyze it i have the TCP: 45 00 00 3d 04 46 40 00 7c 06 f7 6b 0a 1f ed ce 0a 08 01 14 10 14 42 69 92 a2 cd 08 9a 49 56 38 50 18 44 70 10 80 00 00 68 0f 0f 68 c4 14 01 c9 01 06 00 14 01 fc f8 c7 51 01 14 df 16
And thats the buffer that i want to use with your code. But with out modification, when i try to compile your original code i got this errors: http://pastebin.com/SQKxMEUH.
Please if you can help me.
Thanks and sorry for my bad english.
On what OS are you compiling the program ?
Is it linux ?
Yes ubuntu 12.10 to be exact. i am using gcc -lpcap to compile
okay i am capturing the packets using this code i ahve made specific changes suitable for my use, i wanted to ask in the first response packet that contains the headers of the response i want to extract the values of Content-Length and the Content-type fields from the buffer. i tried strstr but it is no use because of nulls. any suggestions. i will be very grateful if somone can share a small function to do so.
what can i do if i want to handle session in this code
what kind of session ? http stream ?
You need to reconstruct http request/response data from the captured packets.
For this you have to read individual tcp packets check their sequence numbers and join their data together.
There is a program called tcpflow that does this. Check it out at
https://github.com/simsong/tcpflow
sir i am electronic & communication student, i have to carry out work on payload data. but i dont know how to extract payload data. could you help me?
thank you.
in the functions print_icmp_packet, print_tcp_packet and print_udp_packet the payload can be extracted as follows
char *payload = Buffer + header_size;
int payload_size = Size – header_size;
buffer is the full packet content. removing the headers from the buffer will give the payload.
Ah, I forgot. Also in processing UDP you’ve made a subtle mistake of using sizeof(udph) instead of sizeof(udphdr).
udph is of pointer type so the sizeof is 4 on 32bit OSes and 8 on 64bit OSes
The size of the UDP header is 8 bytes. So by pure mistake people who compile and use this as 64 bit code won’t be surprised. On 32 bits – they might be ;)
I didn’t read all the comments so maybe someone has pointed this out already but there’s a mistake in the raw data dumping part. There’s no place where buffer is incremented so it points to the Ethernet header. But you dump it as the IP header – you directly pass Buffer instead of Buffer+sizeof(ethhdr). And it’s wrong all the way up/down the stack.
Please fix it as this is the most popular sniffer example and people will get confused :)
Look’s like he let it like this on purpose to be useful only to those who are not just copying the code.
If you wrote it yourself you will notice and correct it.
Hello,
How can we get all the packets from a single download and get the total byte count and reassemble these packets?
it is really great code!!!
I want to what is benefit by using pure linux socket not pcap libray
and the important one
how to output .pcap with this code
thanks~
not using pcap library means that the program does not depend on an external library
and can compile and run directly.
if you need to output to pcap file format then a better solution is to use pcap library directly.
the following post discusses how to code sniffer using pcap library on linux
https://www.binarytides.com/c-packet-sniffer-code-with-libpcap-and-linux-sockets-bsd/
thanks!!!!
so not using pcap library will make program
run faster?
speed difference might not be that noticeable, and I am not sure of how it effects.
But using pcap makes the program more portable and removes the need to use sockets in the code.
Can u please explain the below part clearly???
struct iphdr *iph = (struct iphdr *)( Buffer + sizeof(struct ethhdr) );
iphdrlen = iph->ihl*4
struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr));
struct iphdr *iph = (struct iphdr *)( Buffer + sizeof(struct ethhdr) );
— the above line gets the pointer to the ip header in the structure ‘iphdr’ which can be used to access individual fields of the header
iphdrlen = iph->ihl*4
— the above computes the length of the ip header using the ‘ihl’ field of the ip header. the ihl field contains the ip header length in total bytes/4.
struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr));
— the above line gets the pointer to the tcp header in the structure ‘tcphdr’ which can be used to access the individual fields of the tcp header.
Its all pointers and structures.
Hi thanks for your quick reply.. But why are you adding buffer also.. The whole packet including all layer headers will be there in the buffer rite.. am i right??? if it is so, adding buffer(65536) will move the pointer away from buffer right?
Buffer is the pointer to the first character of the whole packet, so adding to it moves inside the buffer.
nice nice.. got it.. Am new to socket programming. Asking silly questions. Can we further go beyond and find what is the corresponding application layer protocol of the packet
To find the application layer protocol (like wireshark does) will require studying various applications and find what rules they have.
For example a udp packet with destination port 53 is a dns query packet. And a packet with destination port 80 is very likely an “http” packet.
So properties like port number and protocol combinations have to be checked and then the application layer protocol can be detected.
how can we check the HTTP packet type (GET and POST) of application layer
Can we have the same for sniffing 802.11 WLAN PACKETS?
Yes, the same code should work when sniffing packets over wi-fi.
I wish to know the SSID , association request / reply frames and other MAC layer frames. This deals mostly with the network layer.
Very nice !
But is it normal that I can’t reveive ARP broadcast packet when the ARP request is for my PC ?
Ex :
Linux Server : 192.168.0.100
MyLaptop : 192.168.0.150
When I’m doing an ARP request to 192.168.0. with arping on my server, I reveive the packet on my laptop with your exemple but when I’m doing an arping 192.168.0.150, your exemple don’t catch it .. why ?
Both exemple send an arp packet to broadcast so why i’m not getting it when the request is for the computer running the code ?
When i’m using Wireshark, i’m seeing the arp request and the arp response packet.
Thanks
Hello Sir, Can u provide the client program for this
Thanks for this really useful article! Nicely explained but I have still one question regarding the binding to an interface. I want only to sniff the packets from my fixed network interface, but not from my WLAN interface. So I uncommented the setsockopt line and changed the name of the interface to eth0. But still I see packets from both network interfaces (I used wireshark to compare the results).
I also tried the following code, but it seems not to work too.
struct ifreq Interface;
memset(&Interface, 0, sizeof(Interface));
strncpy(Interface.ifr_ifrn.ifrn_name, “eth1”, IFNAMSIZ);
setsockopt(sock_raw, SOL_SOCKET, SO_BINDTODEVICE, &Interface,sizeof(Interface))
Any ideas what I’m doing wrong?
hello…can u please provide code to implement IP spoofing in UDP packet
hello Sir,
thank you for the post and it is clear to understand the steps. is it possible to create some sort of GUI for the code so that users can initiate the sniffing by clicking instead of writing a command and also so that users can see easily what is being captured? if possible where should i get started?
Best Regards,
Adane
Yes , its possible to write a gui application that uses the above code to sniff data.
You need to choose a gui library. I would suggest wxwidgets.
It is a cross platform c/c++ library for creating gui apps.
Dear Binary Tides, it’s so simple and easy to understand. Thanks for the code. I compiled and run fine. Just one confusion. In the `printData( )` function, line number 292 baffles me. If you have already progressed upto say i = x, then printing data[j] prints a character which is already printed since you are taking j = i – 16.
Can you please help me to explain me the alphanumeric printing of code? Rest of the parts are clear.
Thanks in advance.
Hello Sir,
I try to run the code in ubuntu 11.04 terminal and i am getting an error as follows:
~$ gcc packetsniffr2c.c
packetsniffr2c.c: In function ‘main’:
packetsniffr2c.c:59:3: warning: passing argument 5 of ‘recvfrom’ from incompatible pointer type
/usr/include/sys/socket.h:166:16: note: expected ‘struct sockaddr * __restrict__’ but argument is of type ‘struct sockaddr_in *’
So, please help me out to correct this error. I will be thank full to you.
Regrads,
Raj
the code has been fixed. should compile without any errors or warnings.
thank you sooooo much for this, starting out with sniffing and this is beautiful!!
socket error : operation failed