Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
292 views
in Technique[技术] by (71.8m points)

Finding Octet in a UDP data payload in C program

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

//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 
");
  return 1;
}
printf("Packets arrived from %d 
",ntohs(daddr.sin_port));
printf("packet recieved : %lu bytes
", 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
");
  printf("---------------------------------------
");
  printf("Ethernet Header Length   : %u bytes 
",sizeof(eth));
  printf("Destination MAC : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X 
", 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 
", 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 
",eth->h_proto);
  printf("---------------------------------------
");
  }

  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
");
  printf("---------------------------------------
");
  printf("IP Length        : %d
", ntohs(iph->tot_len));
  printf("Source IP        : %s
",inet_ntoa(source.sin_addr));
  printf("Destination IP   : %s
",inet_ntoa(dest.sin_addr));
  printf("Protocol         : %d
", iph->protocol);
  printf("Type Of Service  : %d
",htons(iph->tos));
  printf("---------------------------------------
");
  }


  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
");
   printf("---------------------------------------
");
   printf("UDP Length       : %d
", ntohs(udph->len));
   //printf("UDP Length       : %d
", ntohs(sizeof (struct udphdr))); 
   printf("Source Port      : %d
 ",ntohs(udph->source));
   printf("Destination Port : %d
 ",ntohs(udph->dest));
   printf("Source Port      : %d
 ",ntohs(saddr.sin_port));
   printf("Destination Port : %d
 ",ntohs(daddr.sin_port)); 
   printf("---------------------------------------
");

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


   }

  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 2

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...