0

I am trying to capture the UDP sflow data from port 6343. I am trying to capture the UDP header information which provides source port, destination port, UDP header length and checksum. I am able to see the ports capturing, but the UDP and checksum fields are 0 and 1 respectively which means the UDP length is not calculated and checksum is also not calculated. Am I missing something here for UDP header length and checksum calculation ?? The following is my code which I use:

#include<stdio.h> //For standard things
#include<stdlib.h>    //malloc
#include<string.h>    //memset
#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>
#define PORT 6343
#define PCKT_LEN 65536

void handlepacket(unsigned char *, int);
int sockt;
int i,j;
struct sockaddr_in source,dest; 

int main()
{
    int saddr_size,data_size;
    struct sockaddr_in daddr;
    struct sockaddr_in saddr;
    //struct in_addr in;
    unsigned char *buffer = (unsigned char *)malloc(65536); // Its Big !     Malloc allocates a block of size bytes of memory,returning a pointer to the begining of the block

    struct udphdr *udph = (struct udphdr*)(buffer + sizeof(struct iphdr));


    printf("Starting...\n");
    //Create a raw socket that shall sniff
    sockt = socket(AF_INET ,SOCK_DGRAM ,0);
    if(sockt < 0)
    {
        printf("Socket Error\n");
        return 1;
    }
    memset((char *)&daddr,0,sizeof(daddr));

    //prepare the sockaddr_in structure
    daddr.sin_family = AF_INET;
    daddr.sin_addr.s_addr = INADDR_ANY;
    daddr.sin_port = htons(PORT);

    //Bind
    if(bind(sockt,(struct sockaddr *)&daddr, sizeof(daddr))<0)
    {
      printf("bind failed");
      return 1;
    }
    printf("bind done");

    while(1)
    {
        saddr_size = sizeof saddr;
        printf("waiting for data...");

        //Receive a packet
        data_size = recvfrom(sockt , buffer ,65536 , 0 , (struct sockaddr*)  &saddr , (socklen_t*)&saddr_size);
        if(data_size <0)
        {
            printf("Packets not recieved \n");
            return 1;
        }
        //Now process the packet
        handlepacket(buffer , data_size);


        printf("Packets arrived from %d \n",ntohs(daddr.sin_port));
        printf("Source Port : %d , Destination Port : %d \n", ntohs(udph->source), ntohs(udph->dest)); 

    }
    close(sockt);
    printf("Finished");
    return 0;
}

void handlepacket(unsigned char *buffer, int data_size)
{ 
    //IP header length
    struct iphdr *iph = (struct iphdr *)buffer;
    unsigned short iphdrlen = iph->ihl*4;
    // UDP header length
    struct udphdr *udph = (struct udphdr*)(buffer + iphdrlen);

    memset(&source,0,sizeof(source));
    source.sin_addr.s_addr = iph ->saddr;
    memset(&dest,0,sizeof(dest));
    dest.sin_addr.s_addr = iph->daddr;



    printf("UDP Length : %d , UDP checksum : %d \n",ntohs(udph->len), ntohs(udph->check));


}
dbush
  • 205,898
  • 23
  • 218
  • 273
Kishore
  • 21
  • 2
  • 7

1 Answers1

0

When use create a socket of type AF_INET / SOCK_DGRAM, the operating system processes and IP and UDP headers and strips them off before passing them to you. What you see in buffer is what immediately follows the UDP header.

You're passed back the source IP and port via fifth parameter to the recvfrom function, and the payload length is passed back as the return value. If there is a problem with the UDP checksum, the OS would discard the packet and your application code would never see it, so it's not something you typically need to worry about on the application level.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Thank you for your comment. as you mentioned about AF_INET, what should I use to avoid stripping of UDP header information? should I use RAW socket type to get the UDP header. In that case is it possible for me to fetch data from the specified port since RAW socket type ? – Kishore Jul 27 '15 at 13:16
  • Also should I use any function to calculate the header length and checksum separately? I – Kishore Jul 27 '15 at 13:18
  • If you want to get the full UDP (and IP) headers, you need to use a library that can capture full packets like libpcap. I haven't used it much myself, so you'll need to read the man pages for it. The question however is why do you need this information? What exactly do you intend on doing with it? – dbush Jul 27 '15 at 13:19
  • I am actually trying to capture the sflow data from port 6343 which is sending UDP data. I have to capture these packets ( the information like src port, dest port, packet length etc...) and create a graphical representation of this detail. – Kishore Jul 27 '15 at 14:04
  • For UDP, you can get everything except for the checksum from `recvfrom`. If the checksum is invalid the packet should be thrown out, so I don't see much value in trying to capture it. – dbush Jul 27 '15 at 14:35
  • I am receiving the src port and dest port information but the UDP length is always zero. The following is the output I am receiving when I run the above code : Packets arrived from 6343 Source Port : 54109 , Destination Port : 15798 waiting for data...UDP Length : 0 – Kishore Jul 27 '15 at 14:45
  • I am confused when I am receiving port information from recvfrom, why I am not getting length value..that's where I am struck in my code.. – Kishore Jul 27 '15 at 14:46
  • That's because you're expecting the returned buffer to contain the UDP header. It doesn't. The return value of `recvfrom` i.e. `data_size` IS the length. That's all you need. – dbush Jul 27 '15 at 14:47
  • I tried to read from the data_size where recvfrom is storing the value. I got the following output. waiting for data...UDP Length : -1913977900 Packets arrived from 6343 Source Port : 54325 , Destination Port : 23702 The UDP length value is a negative number. I don't understand from where this value came from...can you please help me in this. – Kishore Jul 27 '15 at 16:49
  • I fixed it. The change I made was only in this place " printf("UDP Length : %d \n",ntohs(data_size));". – Kishore Jul 27 '15 at 17:06
  • Thank you for your great help. – Kishore Jul 27 '15 at 17:06