2015-08-13 3 views
0

У меня есть код захвата пакета sflow, в котором мне нужно распечатать информацию данных sflow из буфера. Я определил структуры требуемой информации и попытался использовать memcpy для копирования информации о буфере в структуру. когда я печатаю поля, я получаю некоторое большое значение, которое не является правильным. Присоединили код STRUCT ниже:Использование memcpy для хранения данных из буфера в struct

 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;                 

Буфер Я использую это unsigned char* buffer = (unsigned char *)malloc(65535);

Я прилагаю тетсру Часть здесь:

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

Выход я Прием:

 ethernet protocol : 31961104 
    Frame Length : 0 

Я прилагаю код для вашего рассмотрения:

#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 

Есть еще неправильные значения, указанные для почти всех полей, как я могу решить эту проблему?

+0

Вы не показали нам, что такое '* buffer'. Должно быть, это просто «буфер»? –

+0

вы читаете какую-то структуру с именем 'head', но вы не показываете нам, что это такое. –

+0

Буфер без знака char * buffer = (unsigned char *) malloc (65535); –

ответ

0

Все 3 применения memcpy() показаны проезжают *buffer, &buffer и &buffer, так что ваши копии приходят от неправильного расположения, что приводит к неправильному выходу вы видите. Просто перейдите buffer вместо этого, поскольку он уже нужен указателю.

+0

Комментарии не предназначены для расширенного обсуждения; этот разговор был [перемещен в чат] (http://chat.stackoverflow.com/rooms/87075/discussion-on-answer-by-donjuedo-use-of-memcpy-to-store-data-from-buffer- в-й). –

0

Вы копируете неправильные смещения в своем буфере.

Предполагая, что данные содержат struct sampled_header, после чего struct sampled_ethernet, после чего struct sampled_ipv4, после чего struct extended_switch, вы должны сделать следующее:

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

Edit:

Похоже, что мы» как это выглядит. Я взял байты данных, которые вы указали в this question, прочитал их в буфер и отправил в UDP-пакет.Я разжег Wireshark, который дал нам это:

Wireshark capture

Так что пакет содержит:

  • Sflow версия, 32-разрядный (5)
  • размером 32 бит INT (значение = 1)
  • struct sample_datagram_v5
  • число выборок (32-битный Int, значение = 6)
  • шесть са mples

Первый образец содержит:

  • Тип образца в качестве data_format (в этом случае образец потока)
  • struct flow_sample
  • число выборок потока (32-битный Int , значение = 2)

первый поток в первом образце:

  • Тип потока как data_format (Int этого случая исходного образца пакета, так что ...)
  • длина данных потока (32-битный INT, значение = 144)
  • struct sampled_header
  • 4 байтов, которые пропущены в соответствии с величиной sampled_header.stripped
  • заголовка Ethernet
  • заголовка IP-(полезная нагрузка = TCP)
  • заголовка TCP (порт = 80)
  • байт данных (62)

Второй поток в первом образце:

  • Тип потока как data_format (интермедиат этом случае расширенные данные коммутаторы)
  • длина данных потока (32- бит INT, значение = 16)
  • struct extended_switch

Затем пять больше образцов. В этом случае все образцы содержат исходный заголовок пакета и данные расширенного коммутатора.

Так что это должно дать вам лучшее представление о том, что вам нужно делать. Поскольку каждый пакет данных будет другим, вам нужно будет определить, сколько у вас образцов. Затем для каждого образца вам нужно будет выяснить тип и на основе этого выяснить, как анализировать отдельные потоки.

Если вам нужно больше примеров, я настоятельно рекомендую использовать Wireshark для захвата этих пакетов sflow, чтобы вы могли точно видеть, что в них есть, чтобы проверить, что ваш парсер работает для всех ожидаемых входных данных.

+0

Он не показывает разницы в выходе. Будут ли ошибки в отчетах printf, которые я использую? –

+0

@userknown Это ответ на ваш вопрос? – dbush

+0

Ваш результат wirehark дал представление о том, как детали выглядят в потоке. Но из-за недостатка знаний об этом я изо всех сил пытаюсь превратить эту идею в код. –

 Смежные вопросы

  • Нет связанных вопросов^_^