使用了memcpy从缓冲存储数据到结构 [英] use of memcpy to store data from buffer into struct

查看:398
本文介绍了使用了memcpy从缓冲存储数据到结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的sFlow数据包捕获code中,我需要打印缓冲区从sFlow的数据信息。我已经定义了结构所需的信息,并试图用的memcpy到缓冲区信息复制到结构。当我打印领域,我得到一些大的值,它是不正确的。该附上以下结构code:

I have sflow packet capture code in which I need to print the sflow data information from buffer. I have defined the structs for the required information and trying to use memcpy to copy the buffer information into the struct. when I print the fields, I get some big value which isn't the correct one. The have attached the struct code below:

     typedef unsigned char mac[6];
     typedef unsigned char ip_v4[4];
     typedef unsigned char ip_v6[16];
     typedef unsigned int header_protocol;


     /* Packet header data */

     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 */
    }head;

    /* Ethernet Frame Data */
    /* opaque = flow_data; enterprise = 0; format = 2 */

    struct sampled_ethernet {
    unsigned int length;   /* The length of the MAC packet received on the
                               network, excluding lower layer encapsulations
                               and framing bits but including FCS octets */
     mac src_mac;           /* Source MAC address */
     mac dst_mac;           /* Destination MAC address */
     unsigned int type;     /* Ethernet packet type */
    }ether;

    /* 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 */
    }ip4;
    /* 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 */
    }ip6;

    /* Extended switch data */

    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 */
}swch;                                                                  

我现在用的缓冲区是无符号字符*缓冲=(无符号字符*)malloc的(65535);

我重视的memcpy部分在这里:

I have attached memcpy part here:

memcpy(&sampled_ethernet,*buffer,sizeof sampled_ethernet);
printf("ethernet protocol : %d\n", head.protocol);
printf("Frame Length : %d\n", head.frame_length); 

我收到的输出是:

The output I am receiving is :

     ethernet protocol : 31961104
     Frame Length : 0

我附上code供大家参考:

I am attaching the code for your consideration:

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

int sockt;
int i,j;
struct sockaddr_in source,dest; 

typedef unsigned char mac[6];
typedef unsigned char ip_v4[4];
typedef unsigned char ip_v6[16];
typedef unsigned int header_protocol;


/* Packet header data */

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 */
}head;

/* Ethernet Frame Data */
/* opaque = flow_data; enterprise = 0; format = 2 */

struct sampled_ethernet {
     unsigned int length;   /* The length of the MAC packet received on the
                               network, excluding lower layer encapsulations
                               and framing bits but including FCS octets */
     mac src_mac;           /* Source MAC address */
     mac dst_mac;           /* Destination MAC address */
     unsigned int type;     /* Ethernet packet type */
}ether;

/* 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 */
}ip4;
/* 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 */
}ip6;

/* Extended switch data */

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 */
}swch;


int main()
    {

    int saddr_size,data_size, datasize; 
    struct sockaddr_in saddr;
    struct sockaddr_in daddr;
    struct in_addr addr;
    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);

    memcpy(&head,&buffer,sizeof head);
    printf("---------------------------------------------\n");
    printf(" Sampled Header \n");
    printf("---------------------------------------------\n");

    printf("ethernet protocol : %d\n",ntohl(head.protocol));
    printf("Frame Length : %d\n", htonl(head.frame_length));

    memcpy(&ether,&buffer,sizeof ether);
    printf("---------------------------------------------\n");
    printf(" Sampled Ethernet \n");
    printf("---------------------------------------------\n");

    printf("Ethernet Length : %u bytes\n",ntohs(ether.length));
    printf("Source MAC : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n", ether.src_mac[0], ether.src_mac[1], ether.src_mac[2], ether.src_mac[3], ether.src_mac[4], ether.src_mac[5], ether.src_mac[6]);
    printf("Destination MAC : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n", ether.dst_mac[0], ether.dst_mac[1], ether.dst_mac[2], ether.dst_mac[3], ether.dst_mac[4], ether.dst_mac[5], ether.dst_mac[6]);
    printf(" Ethernet Type : %u\n",htons(ether.type));

memcpy(&ip4,&buffer[sizeof(head)],sizeof ip4);

printf("---------------------------------------------\n");
    printf(" Sampled IPv4 \n");
    printf("---------------------------------------------\n");

    printf("IPv4 Length : %d\n", sizeof(ip4.length));
    printf("IP Protocol : %d\n", ntohl(ip4.protocol));
    printf("Source IP Address : %d.%d.%d.%d\n",ip4.src_ip[0],ip4.src_ip[1],ip4.src_ip[2],ip4.src_ip[3]);
    printf("Destination IP Address : %d.%d.%d.%d\n",ip4.dst_ip[0],ip4.dst_ip[1],ip4.dst_ip[2],ip4.dst_ip[3]);
    printf("Source Port : %d\n",ntohs(myaddr.sin_port));
    printf("Destination Port : %d\n",ntohs(daddr.sin_port));
    printf("TCP flags : %d\n",(unsigned int)ip4.tcp_flags);
    printf("Type of Service : %d\n",htons(ip4.tos));

    memcpy(&swh,&buffer[sizeof(ip4)],sizeof swh);
printf("---------------------------------------------\n");
    printf(" Extended Switch \n");
    printf("---------------------------------------------\n");    

    printf("Source VLAN : %lu\n",offsetof(struct extended_switch,src_vlan));
    printf("Source Priority : %lu\n",(unsigned int)swh.src_priority);
    printf("Destination VLAN : %lu\n",(unsigned int)swh.dst_vlan);
    printf("Destination Priority : %lu\n",(unsigned int)swh.src_priority);
    }
    close(sockt);
    printf("Finished");
    return 0;
    }

我贴我的输出为您考虑

---------------------------------------------
 Sampled Header 
---------------------------------------------
    ethernet protocol : 5
Frame Length : 1

---------------------------------------------
 Sampled Ethernet 
---------------------------------------------


 Ethernet Length : 2478620678 bytes
Source MAC : 00-00-00-00-00-35
Destination MAC : 6D-28-2F-D9-AB-B0
 Ethernet Type : 0
---------------------------------------------
 Sampled IPv4 
---------------------------------------------
IPv4 Length : 4
    IPv4 Length : 4
IP Protocol : 0
Source IP Address : 0.53.109.40
Destination IP Address : 47.217.171.176
Source Port : 61842
Destination Port : 6343
TCP flags : -1811939328
Type of Service : 302

---------------------------------------------
 Extended Switch 
---------------------------------------------
    Source VLAN : 2483027968
Source Priority : 1653157377
Destination VLAN : 486539264
Destination Priority : 1653157377

有仍然是几乎所有字段显示不正确的值,我怎么能解决这个问题呢?

There are still incorrect values shown for almost all the fields, how can I solve this issue?

推荐答案

您是从你的缓冲区错误的偏移量复制。

You're copying from the wrong offsets in your buffer.

假设数据包含结构sampled_header ,随后结构sampled_ethernet ,随后结构sampled_ipv4 ,随后结构extended_switch ,你应该做到以下几点:

Assuming the data contains a struct sampled_header, followed by a struct sampled_ethernet, followed by a struct sampled_ipv4, followed by a struct extended_switch, you should do the following:

memcpy(&head,buffer,sizeof head);
// read contents of head
...
memcpy(&ether,&buffer[sizeof(head)],sizeof ether);
// read contents of ether
...
memcpy(&ip4,&buffer[sizeof(head) + sizeof(ether)],sizeof ip4);
// read contents of ip4
...
memcpy(&swh,&buffer[sizeof(head) + sizeof(ether) + sizeof(ip4)],sizeof swh);
// read contents of swh
...

编辑:

它看起来像我们这样过什么数据的模样。我把你的<上市数据字节href=\"http://stackoverflow.com/questions/31967938/finding-octet-in-a-udp-data-payload-in-c-program\">this问题,他们读入缓冲区,并在一个UDP数据包发送出去。我启动了Wireshark的,这给了我们这样的:

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

Wireshark的捕获

所以数据包包含:


  • sFlow的版本,32位(5)

  • 一个32位的int(值= 1)

  • 结构sample_datagram_v5

  • 样品的数量(32位int,值= 6)

  • 六个样本

第一个示例包括:


  • 样品类型作为 DATA_FORMAT (在此情况下的流样品)

  • 结构flow_sample

  • 流的样本数(32位int,值= 2)

  • 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:


  • 流量类型为 DATA_FORMAT (INT这种情况下,原始数据包样本,所以......)

  • 流量数据长度(32位int,值= 144)

  • 结构sampled_header

  • 被跳过按值
  • 4个字节的 sampled_header.stripped

  • 以太网帧头

  • IP报头(有效载荷= TCP)

  • TCP报头(端口= 80)

  • 数据字节(62)

  • 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)

第一样品中的第二流动


  • 流量类型为 DATA_FORMAT (INT这种情况下,延长开关数据)

  • 流量数据长度(32位int,值= 16)

  • 结构extended_switch

  • 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.

如果你需要更多的例子我强烈建议使用Wireshark来捕获这些sFlow报,所以你可以看到究竟是什么在他们来验证您的解析器适用于所有期望的输入。

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.

这篇关于使用了memcpy从缓冲存储数据到结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆