Reputation: 31
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;
The buffer I am using is unsigned char* buffer = (unsigned char *)malloc(65535);
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
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(ðer,&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;
}
I have pasted my output for your consideration
---------------------------------------------
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?
Upvotes: 0
Views: 3489
Reputation: 223872
You're copying from the wrong offsets in your buffer.
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(ðer,&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:
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:
So the packet contains:
struct sample_datagram_v5
The first sample contains:
data_format
(in this case a flow sample)struct flow_sample
The first flow in the first sample:
data_format
(int this case a raw packet sample, so...)struct sampled_header
sampled_header.stripped
The second flow in the first sample:
data_format
(int this case extended switch data)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.
Upvotes: 0
Reputation: 2505
All 3 uses of memcpy()
shown are passing *buffer
, &buffer
, and &buffer
, so your copies are coming from the wrong location, leading to the wrong output you see. Just pass buffer
instead, as it is already the pointer needed.
Upvotes: 1