-2

I am trying to collect UDP data payload information using C program by capturing the packet from port 6343. The code I am using is as follows:

#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>
#include<net/ethernet.h>
#include<netinet/if_ether.h>
#define PORT 6343             // define the port to connect
#define ETH_P_IP 0x0800

void ProcessPacket(unsigned char*, int);
void print_ethernet_header(unsigned char*, int);
void print_ip_header(unsigned char* , int);
void print_udp_packet(unsigned char*, int);
void Dataint (unsigned char* , int);
void print(const int *, const int);
int sockt;
int i,j;
struct sockaddr_in source,dest; 

const MAX_HEADER_SIZE = 256;   /* The maximum sampled header size. */

struct sampled_header {
header_protocol protocol;       /* Format of sampled header */
unsigned int frame_length;      /* Original length of packet before
                                  sampling */
opaque header{MAX_HEADER_SIZE}; /* Header bytes */
}

/* Packet IP version 4 data */

struct sampled_ipv4 {
unsigned int length;     /* The length of the IP packet excluding
                           lower layer encapsulations */
unsigned int protocol;   /* IP Protocol type
                           (for example, TCP = 6, UDP = 17) */
ip_v4 src_ip;            /* Source IP Address */
ip_v4 dst_ip;            /* Destination IP Address */
unsigned int src_port;   /* TCP/UDP source port number or
                           equivalent */
unsigned int dst_port;   /* TCP/UDP destination port number or
                           equivalent */
unsigned int tcp_flags;  /* TCP flags */
unsigned int tos;        /* IP type of service */
}
/* Packet IP version 6 data */

struct sampled_ipv6 {
unsigned int length;     /* The length of the IP packet excluding
                           lower layer encapsulations */
unsigned int protocol;   /* IP next header
                           (for example, TCP = 6, UDP = 17) */
ip_v6 src_ip;            /* Source IP Address */
ip_v6 dst_ip;            /* Destination IP Address */
unsigned int src_port;   /* TCP/UDP source port number or
                           equivalent */
unsigned int dst_port;   /* TCP/UDP destination port number or
                           equivalent */
unsigned int tcp_flags;  /* TCP flags */
unsigned int priority;   /* IP priority */
}

struct extended_switch {
unsigned int src_vlan;     /* The 802.1Q VLAN id of incoming frame */
unsigned int src_priority; /* The 802.1p priority of incoming
                             frame */
unsigned int dst_vlan;     /* The 802.1Q VLAN id of outgoing frame */
unsigned int dst_priority; /* The 802.1p priority of outgoing
                             frame */
}

 int main()
 {

int saddr_size,data_size, datasize; 
struct sockaddr_in saddr;
struct sockaddr_in daddr;
struct in_addr addr;
int protocol=17;
unsigned char* buffer = (unsigned char *)malloc(65535); // Its Big ! Malloc allocates a block of size bytes of memory,returning a pointer to the begining of the block

//Create a socket

sockt = socket(AF_INET ,SOCK_DGRAM ,IPPROTO_UDP);
if(sockt < 0)
{
    printf("Socket Error\n");
    return 1;
}
memset((char *)&daddr,0,sizeof(daddr));

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

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...\n");

//Receive a packet

datasize = recvfrom(sockt , buffer ,65535 , 0 , (struct sockaddr*) &saddr , (socklen_t*)&saddr_size);
data_size = recvfrom(sockt , buffer ,65535 , 0 , NULL , NULL);
if(data_size <0)
{
  printf("Packets not recieved \n");
  return 1;
}
printf("Packets arrived from %d \n",ntohs(daddr.sin_port));
printf("packet recieved : %lu bytes\n", datasize);

ProcessPacket(buffer , data_size);

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


void ProcessPacket(unsigned char* buffer, int len)
{
  print_udp_packet(buffer , len);

}

void print_ethernet_header(unsigned char* buffer, int len)
{
  struct ethhdr *eth = (struct ethhdr *)buffer;
  printf("Ethernet Header\n");
  printf("---------------------------------------\n");
  printf("Ethernet Header Length   : %u bytes \n",sizeof(eth));
  printf("Destination MAC : %.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] );
  printf("Source MAC      : %.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] );
  printf("Ethernet Type   : %u \n",eth->h_proto);
  printf("---------------------------------------\n");
  }

  void print_ip_header(unsigned char* buffer, int len)
  {
  //print_ethernet_header(buffer , len);

  struct iphdr *iph = (struct iphdr *)(buffer + sizeof(struct ethhdr));
  unsigned short 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;

  printf("IP Header\n");
  printf("---------------------------------------\n");
  printf("IP Length        : %d\n", ntohs(iph->tot_len));
  printf("Source IP        : %s\n",inet_ntoa(source.sin_addr));
  printf("Destination IP   : %s\n",inet_ntoa(dest.sin_addr));
  printf("Protocol         : %d\n", iph->protocol);
  printf("Type Of Service  : %d\n",htons(iph->tos));
  printf("---------------------------------------\n");
  }


  void print_udp_packet(unsigned char* buffer , int len)
  {
  struct sockaddr_in saddr;
  struct sockaddr_in daddr;
  unsigned short iphdrlen;
  unsigned char* payload = (unsigned char *)malloc(1024);
  struct iphdr *iph = (struct iphdr *)(buffer+ sizeof(struct ethhdr));
  iphdrlen = iph->ihl*4;

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

   int header_size =  sizeof(struct ethhdr) + iphdrlen + sizeof udph;

   print_ip_header(buffer,len);

   printf("UDP Header\n");
   printf("---------------------------------------\n");
   printf("UDP Length       : %d\n", ntohs(udph->len));
   //printf("UDP Length       : %d\n", ntohs(sizeof (struct udphdr))); 
   printf("Source Port      : %d\n ",ntohs(udph->source));
   printf("Destination Port : %d\n ",ntohs(udph->dest));
   printf("Source Port      : %d\n ",ntohs(saddr.sin_port));
   printf("Destination Port : %d\n ",ntohs(daddr.sin_port)); 
   printf("---------------------------------------\n");

   printf("Data Payload\n");  
   //PrintData(buffer + header_size , len - header_size);
   Dataint(buffer ,len);
   printf("--------------------------------------------\n"); 


   }

  void Dataint (unsigned char* buffer , int len)
  {

  int i,j;
  i=0;
  for(i=0 ; i <= len ; i++)
  {
    if( i!=0 && i%16==0)   // prints every hex line with a space
    {
        printf("  ");
    } 

     // prints entire data in integer
      if(i%16==0) 
        printf("   ");                           // prints the first element of hex line                      
        printf(" %d",(unsigned int)buffer[i]);  

    //print the last spaces         
    if( i==len-1)  
    {
        for(j=0;j<16-i%16;j++) 
        printf("   ");

    }
   }
  } 

I have the payload converted to integer form as shown below:

0 0 0 5 0 0 0 1 147 188 192 6 0 0 0 0      0 50 170 143 37 107 3 154 0 0 0 6 0 0 0 1      0 0 0 208 1 30 136 36 0 0 0 29 0 0 1 0      236 205 212 188 0 22 44 215 0 0 0 29 0 0 0 40      0 0 0 2 0 0 0 1 0 0 0 144 0 0 0 1      0 0 5 238 0 0 0 4 0 0 0 128 240 146 28 72      194 0 0 14 12 48 199 199 8 0 69 0 5 220 65 28      64 0 47 6 24 125 193 104 215 69 147 188 192 24 0 80      142 152 237 55 211 205 114 104 162 142 128 16 0 54 188 178      0 0 1 1 8 10 139 71 198 30 37 2 188 177 205 144      135 164 154 194 155 33 30 238 48 113 112 179 62 180 223 221      169 24 234 48 163 41 188 139 148 98 130 255 16 229 123 58      202 165 56 101 14 217 132 108 10 156 47 29 77 156 220 141      202 248 196 75 240 252 232 27 19 140 52 187 0 0 3 233      0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 2      255 255 255 255 0 0 0 1 0 0 0 208 1 30 136 37      0 0 0 29 0 0 1 0 236 205 214 47 0 22 44 215      0 0 0 29 0 0 0 40 0 0 0 2 0 0 0 1      0 0 0 144 0 0 0 1 0 0 5 238 0 0 0 4      0 0 0 128 240 146 28 72 194 0 0 14 12 48 199 199      8 0 69 0 5 220 65 243 64 0 47 6 23 166 193 104      215 69 147 188 192 24 0 80 142 152 237 60 147 229 114 104      162 142 128 16 0 54 13 151 0 0 1 1 8 10 139 71      198 66 37 2 188 213 16 243 209 241 120 208 124 252 85 108      101 62 10 255 21 98 62 58 136 127 106 62 238 76 85 231      227 224 70 62 31 217 151 211 47 106 246 111 160 87 164 114      43 83 45 230 197 131 18 49 110 159 251 162 207 148 178 31      212 40 81 190 0 0 3 233 0 0 0 16 0 0 0 3      0 0 0 2 0 0 0 2 255 255 255 255 0 0 0 1      0 0 0 148 1 30 136 38 0 0 0 29 0 0 1 0      236 205 214 158 0 22 44 215 0 0 0 0 0 0 0 29      0 0 0 2 0 0 0 1 0 0 0 84 0 0 0 1      0 0 0 70 0 0 0 4 0 0 0 68 0 14 12 48      199 199 240 146 28 72 194 0 8 0 69 0 0 52 28 175      64 0 63 6 50 146 147 188 192 24 193 104 215 69 142 152      0 80 114 104 162 142 237 62 109 231 128 16 36 63 51 129      0 0 1 1 8 10 37 2 188 231 139 71 198 66 0 0      0 0 3 233 0 0 0 16 255 255 255 255 0 0 0 0      0 0 0 3 255 255 255 255 0 0 0 1 0 0 0 208      1 30 136 39 0 0 0 29 0 0 1 0 236 205 215 173      0 22 44 215 0 0 0 29 0 0 0 40 0 0 0 2      0 0 0 1 0 0 0 144 0 0 0 1 0 0 5 238      0 0 0 4 0 0 0 128 240 146 28 72 194 0 0 14      12 48 199 199 8 0 69 0 5 220 67 10 64 0 47 6      22 143 193 104 215 69 147 188 192 24 0 80 142 152 237 66      188 223 114 104 162 142 128 16 0 54 185 33 0 0 1 1      8 10 139 71 198 102 37 2 188 248 226 4 177 86 140 52      15 181 49 144 230 162 19 81 72 179 190 46 196 123 24 85      38 153 175 213 96 59 3 73 194 138 211 35 187 143 148 46      200 190 255 249 6 223 220 57 180 2 123 223 184 204 149 28      127 218 240 134 94 247 236 103 0 0 3 233 0 0 0 16      0 0 0 3 0 0 0 2 0 0 0 2 255 255 255 255      0 0 0 1 0 0 0 208 1 30 136 40 0 0 0 29      0 0 1 0 236 205 216 48 0 22 44 215 0 0 0 29      0 0 0 40 0 0 0 2 0 0 0 1 0 0 0 144      0 0 0 1 0 0 5 238 0 0 0 4 0 0 0 128      240 146 28 72 194 0 0 14 12 48 199 199 8 0 69 0      5 220 67 144 64 0 47 6 22 9 193 104 215 69 147 188      192 24 0 80 142 152 237 69 173 223 114 104 162 142 128 16      0 54 47 172 0 0 1 1 8 10 139 71 198 102 37 2      188 249 253 49 241 16 12 100 96 130 25 195 170 251 218 202      149 6 45 216 81 206 145 254 7 147 240 20 103 185 112 138      115 50 158 226 156 204 78 113 98 240 114 65 240 51 253 252      102 174 242 80 12 50 241 179 148 204 90 200 196 66 118 137      0 0 3 233 0 0 0 16 0 0 0 3 0 0 0 2      0 0 0 2 255 255 255 255 0 0 0 1 0 0 0 148      1 30 136 41 0 0 0 29 0 0 1 0 236 205 217 14      0 22 44 215 0 0 0 29 0 0 0 25 0 0 0 2      0 0 0 1 0 0 0 84 0 0 0 1 0 0 0 70      0 0 0 4 0 0 0 68 240 146 28 72 194 0 0 14      12 48 199 199 8 0 69 0 0 52 174 239 0 0 48 6      219 72 216 58 210 78 147 188 194 70 1 187 179 154 222 83      63 174 28 240 175 235 128 16 5 91 120 31 0 0 1 1      8 10 94 165 224 71 49 84 232 65 0 0 0 0 3 233      0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 14      255 255 255 255 

This is a sflow data collected from a core switch.So I have to find the Ethernet, IPv4, IPv6,extended switch data from this payload and print them. Before that I need to find the octet position of each of these in the payload. can you advise me how should I find the octet position of each of them ?

Errors while using the structs in above code:

     udps.c:25: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘ip_v4’
udps.c:26: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘ip_v6’
udps.c:33: error: two or more data types in declaration specifiers
udps.c:33: error: expected ‘)’ before ‘type’
udps.c:45: error: expected specifier-qualifier-list before ‘header_protocol’
udps.c:58: error: expected specifier-qualifier-list before ‘ip_v4’
udps.c:69: error: two or more data types in declaration specifiers
udps.c:74: error: expected specifier-qualifier-list before ‘ip_v6’
udps.c:87: error: two or more data types in declaration specifiers
udps.c:93: error: two or more data types in declaration specifiers
udps.c:93: error: two or more data types in declaration specifiers
udps.c:93: error: expected ‘)’ before ‘type’
udps.c:115: error: two or more data types in declaration specifiers
udps.c: In function ‘main’:
udps.c:131: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected
udps.c:147: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected
udps.c:163: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected
udps.c:173: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected
user known
  • 31
  • 2
  • 6
  • 1
    same way as usual.. define struct for ipv4 header, ipv6 header, udp header. now use this structs to "parse" your data and get the information you want... at which point are you struggling? – Joshua K Aug 12 '15 at 14:28
  • [packet sniffer in C](http://www.binarytides.com/packet-sniffer-code-c-linux/) see how he uses struct and pointer – axellink Aug 12 '15 at 14:32
  • Since this is a Sflow data, I have to capture specific informations. in sflow documentation which I referred, the url is this : sflow.org/sflow_version_5.txt . It defines struct for each of them I mentioned in my question. what I thought was I can define these structs in my code and use memcpy to fetch the information from buffer. But to specify the location of these, I need to find the octet value for these. that's the place where I am confused. – user known Aug 12 '15 at 14:42
  • 1
    How exactly did you capture this packet? More specifically, can you show the code you used to open the socket and read the data? – dbush Aug 12 '15 at 17:16
  • @dbush I have attached my code in the question. – user known Aug 12 '15 at 17:40

1 Answers1

0

When use create a socket of type AF_INET / SOCK_DGRAM, the operating system processes the Ethernet, 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.

The fifth parameter to recvfrom gives you the source IP and source port of the incoming packet. If you want to see more than just that you need to use a packet capture library like libpcap.

Edit:

It seems that this data packet contains IP addresses as part of sflow data. You were trying to parse it as if it was a raw Ethernet frame. What you instead need to do is look at the sflow datagram definition and use that to figure out how the packet is laid out and parse accordingly. You don't need to use memcpy to do that, just use pointers to the relevant structs to point to the proper place in the buffer. This is the same basic technique you were using before, just with a different set of structs.

Edit 2:

It looks like we're way off on what the data looks like. I took the bytes from the packet listed above, read them into a buffer and sent it out in a UDP packet. I fired up Wireshark, which gave us this:

Wireshark capture

So the packet contains:

  • The sflow version, 32-bit (5)
  • an 32 bit int (value=1)
  • a struct sample_datagram_v5
  • the number of samples (32-bit int, value=6)
  • six samples

The first sample contains:

  • The sample type as a data_format (in this case a flow sample)
  • a struct flow_sample
  • the number of flow samples (32-bit int, value=2)

The first flow in the first sample:

  • The flow type as a data_format (int this case a raw packet sample, so...)
  • the flow data length (32-bit int, value=144)
  • a struct sampled_header
  • 4 bytes that are skipped as per the value of sampled_header.stripped
  • ethernet header
  • IP header (payload=TCP)
  • TCP header (port=80)
  • data bytes (62)

The second flow in the first sample:

  • The flow type as a data_format (int this case extended switch data)
  • the flow data length (32-bit int, value=16)
  • a struct extended_switch

Then five more samples. In this case, all the samples contain a raw packet header and extended switch data.

So this should give you a better idea of what you need to do. Since each data packet will be different, you'll need to figure our how many samples you have. Then for each sample, you'll need to figure out the type, and based on that figure out how to parse the individual flows.

If you need more examples I'd strongly suggest using Wireshark to capture these sflow packets so you can see exactly what's in them to validate that your parser works for all expected input.

Related question for reference: use of memcpy to store data from buffer into struct

Community
  • 1
  • 1
dbush
  • 205,898
  • 23
  • 218
  • 273
  • I was told not to make use of packet capture library like libpcap by my supervisor. Also the packet what I am receiving is a UDP packet. In that case SOCK_DGRAM is the right sock type isn't ?? is there any other way of mentioning the sock type ? – user known Aug 12 '15 at 18:16
  • As you said, if the Ethernet, IP and UDP headers are removed and only data payload is stored in the buffer, then will the buffer does not contain any information on IP address, port etc which are seen in headers.? – user known Aug 12 '15 at 18:18
  • @userknown Yes `SOCK_DGRAM` is the correct socket type. Since you can't use a packet capture library, the buffer you get back from `recvfrom` contains only the sflow data, and nothing from the upper layer headers. All you get from this is the socket info returned in the fifth parameter to `recvfrom`. – dbush Aug 12 '15 at 18:20
  • The payload which I mentioned above contains IP addresses and other informations..How can I print them from the payload mentioned above. is use of memcpy a wise idea to use ? – user known Aug 12 '15 at 19:02
  • @userknown See my edit. Let me know if you have any other questions. – dbush Aug 13 '15 at 00:44
  • I am trying to use structs relevant for the parameters I need to pick from the payload, but they are showing many errors. – user known Aug 13 '15 at 11:14
  • udps.c:131: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected udps.c:147: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected udps.c:163: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected udps.c:173: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected – user known Aug 13 '15 at 11:20
  • udps.c:45: error: expected specifier-qualifier-list before ‘header_protocol’ udps.c:58: error: expected specifier-qualifier-list before ‘ip_v4’ udps.c:69: error: two or more data types in declaration specifiers udps.c:74: error: expected specifier-qualifier-list before ‘ip_v6’ udps.c:87: error: two or more data types in declaration specifiers udps.c:93: error: two or more data types in declaration specifiers udps.c:93: error: two or more data types in declaration specifiers udps.c:93: error: expected ‘)’ before ‘type’ udps.c:115: error: two or more data types in declaration specifiers – user known Aug 13 '15 at 11:26
  • The errors you listed do not appear when your code is compiled. Please update your question with the code you are actually trying to use, along with the errors you get when building it. – dbush Aug 13 '15 at 12:07
  • I have updated the code with the structs I am using and also pasted my error log in the question. – user known Aug 13 '15 at 12:53