在C程序中查找UDP数据有效负载中的Octet

时间:2015-08-12 14:20:57

标签: c udp payload

我试图通过从端口6343捕获数据包来使用C程序收集UDP数据有效负载信息。我使用的代码如下:

#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("   ");

    }
   }
  } 

我将有效负载转换为整数形式,如下所示:

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 

这是从核心交换机收集的sflow数据。所以我必须从此有效负载中找到以太网,IPv4,IPv6,扩展交换机数据并打印它们。在此之前,我需要在有效载荷中找到每个八位位置。你能告诉我怎样才能找到他们每个人的八位位置?

使用上面代码中的结构时出错:

     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

1 个答案:

答案 0 :(得分:0)

当使用创建类型为AF_INET / SOCK_DGRAM的套接字​​时,操作系统会处理以太网,IP和UDP标头,并在将它们传递给您之前将其剥离。您在缓冲区中看到的是紧跟在UDP标头之后的内容。

recvfrom的第五个参数为您提供传入数据包的源IP和源端口。如果你想要看到的不仅仅是你需要使用像libpcap这样的数据包捕获库。

编辑:

该数据包似乎包含IP地址作为sflow数据的一部分。您试图将其解析为原始以太网帧。您需要做的是查看sflow数据报定义并使用它来确定数据包的布局方式并进行相应的解析。您不需要使用memcpy来执行此操作,只需使用指向相关结构的指针指向缓冲区中的正确位置。这与您之前使用的基本技术相同,只是使用了一组不同的结构。

编辑2:

看起来我们的数据看起来很糟糕。我从上面列出的数据包中取出字节,将它们读入缓冲区并通过UDP数据包发送出去。我解雇了Wireshark,它给了我们这个:

Wireshark capture

所以数据包包含:

  • sflow版本,32位(5)
  • 32位int(值= 1)
  • a struct sample_datagram_v5
  • 样本数(32位int,值= 6)
  • 六个样本

第一个样本包含:

  • 样本类型为data_format(在本例中为流量样本)
  • a struct flow_sample
  • 流样本数(32位整数,值= 2)

第一个样本中的第一个流程:

  • 流类型为data_format(在本例中为原始数据包样本,因此......)
  • 流数据长度(32位int,值= 144)
  • a struct sampled_header
  • 根据sampled_header.stripped
  • 的值跳过的4个字节
  • 以太网标题
  • IP标头(有效负载= TCP)
  • TCP标头(端口= 80)
  • 数据字节(62)

第一个样本中的第二个流程:

  • 流类型为data_format(在本例中为扩展交换机数据)
  • 流数据长度(32位int,值= 16)
  • a struct extended_switch

然后又有五个样本。在这种情况下,所有样本都包含原始数据包标头和扩展开关数据。

所以这应该可以让你更好地了解你需要做什么。由于每个数据包都不同,因此您需要确定您拥有的样本数量。然后,对于每个样本,您需要确定类型,并根据该数据解析如何解析各个流。

如果您需要更多示例,我强烈建议您使用Wireshark捕获这些sflow数据包,以便您可以准确了解其中的内容,以验证您的解析器是否适用于所有预期的输入。

相关问题供参考:use of memcpy to store data from buffer into struct