Thread: packet analyzer in c

  1. #1
    Registered User
    Join Date
    Jul 2004
    Posts
    14

    packet analyzer in c

    Hi there,

    I am in a need of some network programming expereince, in particuar with packet sniffing.

    I am working on building a Net. Analyzer and 50% is ready, I need some help in building several functions to extract the protocols from the packet and print them in order.

    so what I need exactly is functions that have the following parameters ( a pointer to the head of the packet), and lenght (the lenght of the packet), then they extract each protocol and print it.

    The ethernet header comes first, then the IP or /ARP, then TCP or UDP.

    Hope Imake it clear for others to help.


    Thank you in advance

    Ahmed.

  2. #2
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    How can you have a 50% completed network analyzer without any of those functions? (Sorry, couldn't resist...)

    Well, I don't have time to write any of those functions for you, but I'll post the source of a function I've already written. It checks if an ethernet package is an ARP response from a specific host to a specific host.

    It is vital that you get good documentation of Ethernet frames and the TCP protocol stack.

    Here's the function:
    Code:
    bool isARPRespone(uchar* packetBuffer, DWORD packetSize, uchar fromIP[4], uchar toIP[4])
    {
    	 //Check that the packet has sufficient size
    	//ARP packets are 42 bytes
    	if (packetSize != 42)
    		return false;
    	//Is it as ARP package?
    	//Ethertype for ARP is 0x0806
    	if (packetBuffer[12] != 0x08 ||
    		packetBuffer[13] != 0x06)
    			return false; 
    	//Does it specify the source IP address?
    	uchar packetSourceIP[4];
    	memcpy(packetSourceIP, packetBuffer + 28, 4);
    	if (fromIP[0] != packetSourceIP[0] ||
    		fromIP[1] != packetSourceIP[1] ||
    		fromIP[2] != packetSourceIP[2] ||
    		fromIP[3] != packetSourceIP[3])
    			return false;
    	//Does it specify the destination IP address?
    	uchar packetDestIP[4];
    	memcpy(packetDestIP, packetBuffer + 38, 4);
    	if (toIP[0] != packetDestIP[0] ||
    		toIP[1] != packetDestIP[1] ||
    		toIP[2] != packetDestIP[2] ||
    		toIP[3] != packetDestIP[3])
    			return false;
    	return true;
    }
    If you have more specific questions, I'll be glad to help.
    I'm actually teaching data communication at the Swedish Army Technícal School during this summer, so this is exactly what I'm busy with for the moment.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    How will yours differ from say http://www.ethereal.com/
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Jul 2004
    Posts
    14
    Sang-drax, Thanx alot.


    Well, your code is good enough to start with, but I need your help in explaining this source code that I got from the interent.
    considering my main function call to the other functions by passing 2 parameters (*p) and (length).
    This is a sample of one of the functions :

    void print_ether_header(register const u_char *bp, register u_int length)
    {
    register u_short dest_eth1, dest_eth2, dest_eth3;
    register u_short temp1 = 0x0, temp2 = 0x0;
    register u_short src_eth1, src_eth2, src_eth3;
    register u_short type1;

    temp1 = *bp << 8;
    *bp++;
    temp1 = temp1 | *bp;
    *bp++;
    dest_eth1 = temp1;

    temp1 = *bp << 8;
    *bp++;
    temp1 = temp1 | *bp;
    *bp++;
    dest_eth2 = temp1;

    temp1 = *bp << 8;
    *bp++;
    temp1 = temp1 | *bp;
    *bp++;
    dest_eth3 = temp1;

    temp1 = *bp << 8;
    *bp++;
    temp1 = temp1 | *bp;
    *bp++;
    src_eth1 = temp1;

    temp1 = *bp << 8;
    *bp++;
    temp1 = temp1 | *bp;
    *bp++;
    src_eth2 = temp1;

    temp1 = *bp << 8;
    *bp++;
    temp1 = temp1 | *bp;
    *bp++;
    src_eth3 = temp1;
    ..
    ...
    ...

    ---------------------------------
    What is he trying to do here by *bp<<8, then temp |=*bp ant so on ?
    in other words, How could he extract the header fields from the packet ? what is the mechanism he is using ? !!



    To Salem,

    I am studying network anlaysis, my Net. Analyzer is nothing comparing ethereal, but a way of learning.

  5. #5
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Quote Originally Posted by althagafi
    What is he trying to do here by *bp<<8, then temp |=*bp ant so on ?
    He is extracting the source and destination MAC addresses of the Ethernet package. He is reading one byte at a time and combining them to 16-bit words using bitwise operators.

    MAC addresses are 48 bits, so he has chosen to represent a MAC address with three 16-bit words, called dest_eth1, dest_eth2, dest_eth3 (this is not a good way if you ask me).
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  6. #6
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Hey, I found a bug in my code!

    Code:
    //Is it as ARP package?
    //Ethertype for ARP is 0x0806
    if (packetBuffer[12] != 0x08 ||
    packetBuffer[13] != 0x06)
    	return false;
    The || should of course be a &&

    EDIT: I really, really hate this editor.
    Last edited by Sang-drax; 07-30-2004 at 05:16 AM. Reason: Stupid, stupid, STUPID editor!!
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  7. #7
    Registered User
    Join Date
    Jul 2004
    Posts
    14
    Quote Originally Posted by Sang-drax
    He is extracting the source and destination MAC addresses of the Ethernet package. He is reading one byte at a time and combining them to 16-bit words using bitwise operators.

    MAC addresses are 48 bits, so he has chosen to represent a MAC address with three 16-bit words, called dest_eth1, dest_eth2, dest_eth3 (this is not a good way if you ask me).
    He is trying to be simple and clear in his representation of the fields.
    I do think that this is an easy way ! hope you have something more easier or advantigous.

    what's your take on that way ? so that I should avoid using it.
    and what's your recommend way and why ?



    Thank you for your great help.

  8. #8
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    A MAC address should be represented with a single variable. There's no reason to separate one thing into several variables.
    Like:

    char destMAC[6];
    or
    class MACAddress
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  9. #9
    Registered User
    Join Date
    Jul 2004
    Posts
    14
    Quote Originally Posted by Sang-drax
    A MAC address should be represented with a single variable. There's no reason to separate one thing into several variables.
    Like:

    char destMAC[6];
    or
    class MACAddress
    ============================================
    To extract the Des. Mac , can I do it in this way?

    Register u_char dts_mac[6];


    dst_mac[6]=*p <<48; // pp is a pointer to the packet header.
    then
    *p +6 ; // to move to next 6 bytes

    src_mac[6]=*p<<48;
    then *p+6

    your advice.

    appreciated, the your help you offer.

  10. #10
    Registered User
    Join Date
    Jul 2004
    Posts
    14
    Quote Originally Posted by althagafi
    ============================================
    To extract the Des. Mac , can I do it in this way?

    Register u_char dts_mac[6];


    dst_mac[6]=*p <<48; // pp is a pointer to the packet header.
    then
    *p +6 ; // to move to next 6 bytes

    src_mac[6]=*p<<48;
    then *p+6

    your advice.

    appreciated, the your help you offer.


    Look at this code and tell me why is not giving me the right result:

    Code:
       int print_ether_hdr(const unsigned char *pkt_ptr,unsigned int length)
       {
                 unsigned  char DST_MAC[6];
                 unsigned  char SRC_MAC[6];
                 register unsigned short  buffer=0x00;
                 register unsigned short  PKT_TYPE;
                 register const unsigned short IP=0x800;
                 register const unsigned short ARP=0x806;
                 int i=0;
                 int j=0;  
                 printf     ("\t========================================\n");
                 printf("----------Ethernet Header---------------\n");
                 printf("Des. Mac :");
                 for (i==0;i<6;i++)
                  {               DST_MAC[i]=*pkt_ptr <<8;
        	               printf("%2x",DST_MAC[i]);
        	               *pkt_ptr++;
                  }
                printf("\nSrc. Mac :");   
                for (j==0;j<6;j++)
                  { 	SRC_MAC[j]=*pkt_ptr <<8;
                    	printf("%2x",SRC_MAC[j]);
        	                *pkt_ptr++;
                  }
       }
    I'm getting :
    ----------Ethernet Header---------------
    Des. Mac : 0 0 0 0 0 0
    Src. Mac : 0 0 0 0 0 0
    ========================================
    ----------Ethernet Header---------------
    Des. Mac : 0 0 0 0 0 0
    Src. Mac : 0 0 0 0 0 0
    ========================================
    ----------Ethernet Header---------------
    Des. Mac : 0 0 0 0 0 0
    Src. Mac : 0 0 0 0 0 0
    Last edited by althagafi; 07-31-2004 at 01:52 PM. Reason: Reformating

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    When you are using << 8, yuo are effectively setting the last 8 bits to zero, which you then store in a byte. No wonder the byte is always zero.

    Remove the << 8 and see what happens.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  13. #13
    Registered User
    Join Date
    Jul 2004
    Posts
    14
    Ok, never mind about the prev. code, I have changed it to this code and is working almost fine, but I'm not getting any Proto Type except IP (0800) or something like 9000 that I have no clue of.
    I am wondering why I could not see any ARP packets.
    Any advice.


    Code:
    int print_ether_hdr(const unsigned char *pkt_ptr,unsigned int length)
    {
       unsigned  short DST_MAC[3];
       unsigned  short SRC_MAC[3];
       register unsigned short  buffer=0x00;
       register unsigned short  PKT_TYPE;
       register const unsigned short IP=0x800;
       register const unsigned short ARP=0x806;
       int i;
      
       
       printf("\n========New Etherenet Packet===========\n");
       printf(".........(Ethernet Header)..............\n");
       
       //Extract the Dest. MAC Address
       
         for (i=0;i<3;i++)
       	  {
    	   buffer=*pkt_ptr << 8;
    	   *pkt_ptr++;
    	   buffer |=*pkt_ptr;
    	   *pkt_ptr++;
    	   DST_MAC[i]=buffer;
    	  }
    	   
       // Print the Dest. MAC
       printf("Dest. MAC Addr : %04x%04x%04x\n",DST_MAC[0],DST_MAC[2],DST_MAC[2]);
       //Extract the Src. MAC Address
       
       for (i=0;i<3;i++)
       	  {
    	   buffer=*pkt_ptr << 8;
    	   *pkt_ptr++;
    	   buffer |=*pkt_ptr;
    	   *pkt_ptr++;
    	   SRC_MAC[i]=buffer;
    	  }
       // Print the Src. MAC
       printf("Source MAC Addr: %04x%04x%04x\n",SRC_MAC[0],SRC_MAC[1],SRC_MAC[2]);
       
       //Extract the Ethernet Type
       buffer=*pkt_ptr<<8;   
       *pkt_ptr++;
       buffer =buffer | *pkt_ptr;
       PKT_TYPE=buffer;
       *pkt_ptr++;
       // Print Ethernet packet Type.
      // if (PKT_TYPE>0x5ee)
          printf("Packet Type/Len : %04x\n",PKT_TYPE);
      //   else 
    //     printf("	Data Packet Lengeth  : %04x\n",PKT_TYPE);
       printf("----------------------------------------\n");
       
       // Decide if the packet is IP or ARP, then print it.
       switch (PKT_TYPE)
       	case IP: print_ip_pkt(pkt_ptr,length);
       	case ARP:print_ip_pkt(pkt_ptr,length);
       	default :printf("Unknown packet type");   	
         
    return 0;
    
    
    };
    Last edited by althagafi; 08-01-2004 at 10:11 AM. Reason: Reformating

  14. #14
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    You need to change your switch-statement a little:
    Code:
    // Decide if the packet is IP or ARP, then print it.
    switch (PKT_TYPE)
    	case IP: print_ip_pkt(pkt_ptr,length);
    	 break;
    	case ARP: print_arp_pkt(pkt_ptr,length);
    	 break;
    	default: printf("Unknown packet type");	 
     
    };
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  15. #15
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Also here are more thoughts:
    Code:
    printf("Dest. MAC Addr : %04x%04x%04x\n",DST_MAC[0],DST_MAC[2],DST_MAC[2]);
    The middle should be DST_MAC[1]

    Code:
    *pkt_ptr++;
    Can be changed into:
    Code:
    pkt_ptr++; //Same effect

    Finally are you sure you are actually parsing some ARP packages?
    Here's an ARP package that you can pass to your function to test it:
    Code:
    FF FF FF FF FF FF 00 D0-95 53 97 80 08 06 00 01   
    08 00 06 04 00 01 00 D0-95 53 97 80 0A F9 0A C8   
    00 00 00 00 00 00 0A F9-00 FE 10 37 83 1B 75 A4   
    3D 57 A7 52 B5 45 3B A2-D3 DF 52 3E
    Last edited by Sang-drax; 08-01-2004 at 10:41 AM.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Packet processing in Socket programming, please help
    By pumpkin in forum Networking/Device Communication
    Replies: 5
    Last Post: 05-28-2009, 01:33 AM
  2. Replies: 4
    Last Post: 05-05-2009, 05:35 AM
  3. Global Variables
    By Taka in forum C Programming
    Replies: 34
    Last Post: 11-02-2007, 03:25 AM
  4. Raw Packet (sorry tripple weird Post)
    By Coder87C in forum Networking/Device Communication
    Replies: 6
    Last Post: 03-04-2006, 11:34 AM
  5. packet analyzer in c
    By althagafi in forum C Programming
    Replies: 1
    Last Post: 07-26-2004, 11:46 PM