1

I am trying to print sflow data summary from payload. I have defined the struct for the summary details and use memcpy to copy the data from buffer into the struct. I find the values I am printing is not the correct values since it looks like some random values are printed. I was trying to look at the concept of offset which specifies the location of each struct details in buffer. But still I am not able to solve this problem. I have attached the code and output below.

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


void Dataint (unsigned char* , int);
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 */
}swh;


int main(int argc, char *argv[])
    {


    int myaddr_size,data_size, datasize; 
    struct sockaddr_in myaddr;
    struct sockaddr_in daddr;
    struct in_addr addr;

    unsigned char* buffer = (unsigned char *)malloc(65536); // 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 *)&myaddr,0,sizeof(myaddr));
    memset((char *)&daddr,0,sizeof(daddr));
    //prepare the sockaddr_in structure

    daddr.sin_family = AF_INET;
    daddr.sin_addr.s_addr = htons(INADDR_ANY);
    daddr.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)
    {
    myaddr_size = sizeof myaddr;
    printf(" waiting for data...\n");

    //Receive a packet

    datasize = recvfrom(sockt , buffer ,65536 , 0 , (struct sockaddr*) &myaddr , (socklen_t*)&myaddr_size);
    data_size = recvfrom(sockt , buffer ,65536 , 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);
    printf("Agent IP address : %s\n", inet_ntoa(myaddr.sin_addr));
    printf("Source Port : %d\n",ntohs(myaddr.sin_port));
    printf("Destination Port : %d\n",ntohs(daddr.sin_port));

    // copy the buffer data into struct and print the sflow details

    memcpy(&head.protocol,&buffer[4],4);
    memcpy(&head.frame_length,&buffer[4],4);
    //printf("offsets: protocol=%zd, frame_length=%zd\n", offsetof(struct sampled_header, protocol),offsetof(struct sampled_header,frame_length));
    printf("---------------------------------------------\n");
    printf(" Sampled Header \n");
    printf("---------------------------------------------\n");

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


    memcpy(&ether,&buffer[sizeof(head)],sizeof (ether));
    printf("offsets: length=%zd, src_mac=%zd, dst_mac=%zd, type=%zd\n", offsetof(struct sampled_ethernet, length), offsetof(struct sampled_ethernet, src_mac), offsetof(struct sampled_ethernet, dst_mac), offsetof(struct sampled_ethernet, type));
    printf("---------------------------------------------\n");
    printf(" Sampled Ethernet \n");
    printf("---------------------------------------------\n");

    printf("Ethernet Length : %u bytes\n",ntohl(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]);
    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]);
    printf(" Ethernet Type : %d\n",htons(ether.type));                       memcpy(&ip4,&buffer[sizeof(head)+sizeof(ether)],sizeof(ip4));printf("offsets: length=%zd, protocol=%zd, src_ip=%zd, dst_ip=%zd, src_port=%zd, dst_port=%zd, tcp_flags=%zd, tos=%zd\n", offsetof(struct sampled_ipv4, length), offsetof(struct sampled_ipv4, protocol), offsetof(struct sampled_ipv4, src_ip), offsetof(struct sampled_ipv4, dst_ip), offsetof(struct sampled_ipv4, src_port), offsetof(struct sampled_ipv4, dst_port), offsetof(struct sampled_ipv4, tcp_flags), offsetof(struct sampled_ipv4, tos));

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

    printf("IPv4 Length : %u\n", 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",ip4.src_port);
    printf("Destination Port : %d\n",ip4.dst_port);
    printf("TCP flags : %d\n",(unsigned int)ip4.tcp_flags);
    printf("Type of Service : %d\n",htons(ip4.tos));


    /*memcpy(&ip6,&buffer[sizeof(head)+ sizeof(ether)+ sizeof(ip4)],sizeof ip6);
    printf("offsets: length=%zd, protocol=%zd, src_ip=%zd, dst_ip=%zd, src_port=%zd, dst_port=%zd, tcp_flags=%zd, priority=%zd\n", offsetof(struct sampled_ipv6, length), offsetof(struct sampled_ipv6, protocol), offsetof(struct sampled_ipv6, src_ip), offsetof(struct sampled_ipv6, dst_ip), offsetof(struct sampled_ipv6, src_port), offsetof(struct sampled_ipv6, dst_port), offsetof(struct sampled_ipv6, tcp_flags), offsetof(struct sampled_ipv6, priority));
    printf("---------------------------------------------\n");
    printf(" Sampled IPv6 \n");
    printf("---------------------------------------------\n");

    printf("IPv4 Length : %d\n", sizeof(ip6.length));
    printf("IP Protocol : %d\n", ntohl(ip6.protocol));
    printf("Source IP Address : %d.%d.%d.%d\n",ip6.src_ip[0],ip6.src_ip[1],ip6.src_ip[2],ip6.src_ip[3]);
    printf("Destination IP Address : %d.%d.%d.%d\n",ip6.dst_ip[0],ip6.dst_ip[1],ip6.dst_ip[2],ip6.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)ip6.tcp_flags);
    printf("Priority : %d\n",ip6.priority);*/


    memcpy(&swh,&buffer[sizeof(head)+ sizeof(ether)+ sizeof(ip4)],sizeof swh);
    printf("offsets: src_vlan=%zd, src_priority=%zd, dst_vlan=%zd, dst_priority=%zd\n", offsetof(struct extended_switch, src_vlan), offsetof(struct extended_switch, src_priority), offsetof(struct extended_switch, dst_vlan), offsetof(struct extended_switch, dst_priority));

    printf("---------------------------------------------\n");
    printf(" Extended Switch \n");
    printf("---------------------------------------------\n");    

    printf("Source VLAN : %d\n",swh.src_vlan);
    printf("Source Priority : %d\n",swh.src_priority);
    printf("Destination VLAN : %lu\n",swh.dst_vlan);
    printf("Destination Priority : %lu\n",swh.src_priority);


    Dataint(buffer,data_size);

    }
    close(sockt);
    printf("Finished");
    return 0;
    }


    void Dataint (unsigned char* data , int len)
    {

      int i,j;
      i=0;
      for(i=0 ; i <= len ; i++)
      {
        if( i!=0 && i%8==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)data[i]);  

        //print the last spaces         
        if( i==len-1)  
        {
            for(j=0;j<16-i%16;j++) 
            printf("   ");

        }
    }
}  

The output along with offset values I am receiving is as follows:

Packets arrived from 6343 
packet recieved : 1324 bytes
Agent IP address : 147.188.195.6
Source Port : 61842
Destination Port : 6343
---------------------------------------------
 Sampled Header 
---------------------------------------------                            offsets: protocol=0, frame_length=4
ethernet protocol : 16777216
Frame Length : 1
---------------------------------------------
 Sampled Ethernet 
---------------------------------------------                           offsets: length=0, src_mac=4, dst_mac=10, type=16
Ethernet Length : 2478620678 bytes
Source MAC :  0- 0- 0- 0- 0-36
Destination MAC : 1E-9B-32-84-AA-C2
 Ethernet Type : 0
---------------------------------------------
 Sampled IPv4 
---------------------------------------------                          offsets: length=0, protocol=4, src_ip=8, dst_ip=12, src_port=16, dst_port=20, tcp_flags=24, tos=28
IPv4 Length : 83886080
IP Protocol : 1520500736
Source IP Address : 0.0.0.208
Destination IP Address : 0.0.1.0
Source Port : 0
Destination Port : 0
TCP flags : 0
Type of Service : 0
---------------------------------------------
 Extended Switch 
---------------------------------------------                            offsets: src_vlan=0, src_priority=4, dst_vlan=8, dst_priority=12
Source VLAN : 486539264
Source Priority : 33554432
Destination VLAN : 16777216
Destination Priority : 33554432

Data Payload: 0 0 0 5 0 0 0 1 147 188 192 6 0 0 0 0 0 54 44 126 50 224 228 124 0 0 0 6 0 0 0 1 0 0 0 208 1 50 160 35 0 0 0 29 0 0 1 0 1 157 88 85 0 22 166 165 0 0 0 29 0 0 0 0 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 176 240 0 0 51 6 194 93 64 15 119 81 147 188 195 177 0 80 15 105 3 108 27 58 205 169 158 110 80 16 0 239 135 97 0 0 10 186 230 180 163 132 153 187 46 104 70 126 109 217 29 196 92 63 8 24 204 255 131 109 60 137 167 141 247 31 227 55 242 178 122 129 253 93 200 255 46 21 24 48 109 130 213 95 161 9 125 90 129 99 166 247 75 246 52 185 27 152 127 19 138 146 225 108 45 99 246 230 25 251 0 0 3 233 0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 5 255 255 255 255 0 0 0 1 0 0 0 208 1 50 160 36 0 0 0 29 0 0 1 0 1 157 90 94 0 22 166 165 0 0 0 29 0 0 0 0 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 178 82 0 0 51 6 192 251 64 15 119 81 147 188 195 177 0 80 15 105 3 115 225 158 205 169 158 110 80 16 0 239 118 126 0 0 59 254 170 184 227 67 248 86 191 227 85 214 128 13 127 11 27 202 144 207 244 34 228 207 203 12 246 161 229 218 73 184 240 205 101 63 75 175 182 203 229 232 87 30 141 242 132 214 192 254 176 92 123 207 21 174 130 56 203 169 182 157 8 157 114 162 151 123 30 228 250 49 124 95 0 0 3 233 0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 5 255 255 255 255 0 0 0 1 0 0 0 140 1 50 160 37 0 0 0 29 0 0 1 0 1 157 90 115 0 22 166 165 0 0 0 0 0 0 0 29 0 0 0 2 0 0 0 1 0 0 0 76 0 0 0 1 0 0 0 64 0 0 0 4 0 0 0 60 0 14 12 48 199 199 240 146 28 72 194 0 8 0 69 0 0 40 9 88 64 0 127 6 227 169 147 188 195 177 64 15 119 81 15 105 0 80 205 169 158 110 3 116 20 242 80 16 1 0 11 207 0 0 0 0 0 0 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 50 160 38 0 0 0 29 0 0 1 0 1 157 91 47 0 22 166 165 0 0 0 29 0 0 0 0 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 178 216 0 0 51 6 192 117 64 15 119 81 147 188 195 177 0 80 15 105 3 118 210 110 205 169 158 110 80 24 0 239 183 68 0 0 88 129 223 184 230 223 53 102 122 246 1 77 205 249 189 7 88 71 27 157 249 169 195 61 224 97 241 150 205 73 255 63 222 86 124 18 123 51 189 252 143 233 59 210 167 247 97 250 218 244 233 220 35 40 255 167 79 47 192 244 165 233 211 43 48 125 65 250 244 122 76 191 46 125 0 0 3 233 0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 5 255 255 255 255 0 0 0 1 0 0 0 208 1 50 160 39 0 0 0 29 0 0 1 0 1 157 92 80 0 22 166 165 0 0 0 29 0 0 0 0 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 179 162 0 0 51 6 191 171 64 15 119 81 147 188 195 177 0 80 15 105 3 123 65 90 205 169 158 110 80 16 0 239 63 87 0 0 40 242 64 127 26 235 137 150 44 212 109 245 48 2 91 24 89 198 98 17 198 188 250 158 160 123 5 244 171 63 159 196 242 241 222 140 233 42 247 64 64 73 108 130 49 239 241 217 27 243 93 172 191 131 171 43 95 186 205 120 110 18 211 203 236 243 122 191 73 63 232 232 149 112 0 0 3 233 0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 5 255 255 255 255 0 0 0 1 0 0 0 148 1 50 160 40 0 0 0 29 0 0 1 0 1 157 92 92 0 22 166 165 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 122 136 64 0 62 6 81 67 147 188 202 13 94 100 180 202 238 166 1 187 102 178 253 255 82 53 99 117 128 16 255 255 241 78 0 0 1 1 8 10 159 45 37 133 10 227 58 33 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

The issue here is the random values getting printed in all the fields. I am not sure if the printf statements are going wrong in printing the values or my memcpy is not actually pointing to correct location of buffer. I require help in solving this issue and understand where I am going wrong. Also I am curious to know if this issue can be resolved without use of any libraries available? This issue is connected with use of memcpy to store data from buffer into struct.

Community
  • 1
  • 1
user known
  • 31
  • 2
  • 6
  • I briefly looked at this, but there isn't a clear indication of how to run the program and what data to send, and while I got the code to compile (I had to reorder some headers, and add some others) and run, I'm not sure where to go from there. – Jonathan Leffler Aug 15 '15 at 18:36
  • you don't need to send any data. you would be capturing data from a port...I have specified a bind to socket part of code there. – user known Aug 15 '15 at 19:04
  • OK; if you say so. I don't know what the trouble is, then, beyond port 6343 isn't seeing any data on my machine. – Jonathan Leffler Aug 15 '15 at 19:32
  • you mean you are not seeing data in the buffer ?? – user known Aug 15 '15 at 21:57
  • Yes; I'm not sure where it would be coming from...have I missed something in your program that's sending as well as receiving? I'm pretty sure the code you showed (when I last looked at or copied it — nearly 18 hours ago) contained nothing that wrote to port 6343. – Jonathan Leffler Aug 15 '15 at 21:58
  • are you using the code mentioned in the question ?? are you able to see in your machine the output i have posted above ? that's the data I am trying to print from the buffer using structs. If you want I will attach a flow's payload which I am getting for your consideration. – user known Aug 15 '15 at 22:40
  • Yes; I copied the code from the question, hacked it a little (not much — I had to resequence the headers, which means the headers here have a bug in them; and added ``, and removed `` — that info is in ``), and ran it. No, I don't get any output worth mentioning. It says: `bind done waiting for data...` and hangs around indefinitely for the data to arrive, and it doesn't. I left it running overnight, more by accident than design, and nothing arrived. I'm on a Mac. I'm not sure what `sflow` means — it may not apply to Macs. – Jonathan Leffler Aug 15 '15 at 22:43
  • Sflow is a sampled flow which send data by using sampling mechanism. I was running this code on linux machine. I don't see any problem in running in Mac. but I am not really sure. But I will paste the output for your consideration. – user known Aug 15 '15 at 23:01
  • 1
    if you ever want people to read your code, you should learn how to ask a question instead of ask a question asap. – Jason Hu Aug 15 '15 at 23:12
  • I'm sorry, but the additional data means nothing to me. I can't make head or tail of what you're dealing with. It probably means I shouldn't be looking at the question — maybe there's someone else out there to whom it is all transparently obvious. I'm going to VTC "unclear what you are asking". Let me know if you make substantive changes to the information in the question (add a comment, tagged with `@Jonathan`), but otherwise, I'm out of ideas. – Jonathan Leffler Aug 15 '15 at 23:32
  • Did you try parsing out the data as I described in your last question? This code doesn't seem to show any attempt to do that. It seems like you have some idea on how to do this based on this code. You just need to use the proper structs that actually describe the data. – dbush Aug 16 '15 at 03:01

1 Answers1

1

As I mentioned in this answer and the comments that followed, you're not grabbing the correct message offsets.

The packet contents are as follows:

  • 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)
  • The sample length (32-bit int, value 208)
  • 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

Here's an example of how you would read these fields. Instead of using memcpy, I'll just use pointers to the relevant structs directly into the buffer in question.

// main header
int *sflow_version = (int *)buffer;
int *val1 = (int *)(buffer + sizeof(*sflow_version ));
struct sample_datagram_v5 *sdv5 = (struct sample_datagram_v5 *)((char *)val1 + sizeof(*val1));
int *num_samples = (int *)((char *)sdv5 + sizeof(*sdv5));

// first sample
data_format *sample1_type = (data_format *)((char *)num_samples + sizeof(*num_samples));
int *sample1_len = (int *)((char *)sample1_type + sizeof(*sample1_type));
// read *sample1_type to determine that this sample is a flow sample
struct flow_sample *sample1 = (struct flow_sample *)((char *)sample1_len + sizeof(*sample1_len));
int *sample1_count = (int *)((char *)sample1 + sizeof(*sample1));

// first sample, first flow
data_format *s1flow1_type = (data_format *)((char *)sample1_count + sizeof(*sample1_count));
// read *s1flow1_type to determine that this flow is a raw packet
int *s1flow1_len = (int *)((char *)s1flow1_type + sizeof(*s1flow1_type));
struct sampled_header *s1flow1_sheader = (struct sampled_header *)((char *)s1flow1_len + sizeof(*s1flow1_len));

// raw data from first sample, first flow
struct ether_header *ether1 = (struct ether_header *)((char *)sampled_header + sizeof(*sampled_header) + ntohl(s1flow1_sheader->stripped));  // struct from <net/ethernet.h>
struct iphdr *ip1 = (struct iphdr *)((char *)ether1 + sizeof(*ether1));  // struct from <netinet/ip.h>
struct udphdr *udp1 = (struct udphdr *)((char *)ip1 + sizeof(*ip1));  // struct from <netinet/ip.h>
// plus application data

// first sample, second flow
data_format *s1flow2_type = (data_format *)((char *)s1flow1_len + sizeof(*s1flow1_len) + ntohl(*s1flow1_len));
// read *s1flow2_type to determine that this flow is extended switch data
int *s1flow2_len = (int *)((char *)s1flow2_type + sizeof(*s1flow2_type));
struct extended_switch *s1flow2_sheader = (struct sampled_header *)((char *)s1flow2_len + sizeof(*s1flow2_len));

// second sample
data_format *sample2_type = (data_format *)((char *)sample1_len + sizeof(*sample1_len) + ntohl(*sample1_len));
// and so forth...

What we're doing here is finding the offset of each field based on the offset of the previous one. In most cases the previous field is an individual field, but in others the previous field is a composite field. For example, to find the offset of the second flow in the first sample, we start from the field that specifies the length of the first flow, then add the size of that field plus the length of the prior flow (which happens to be the contents of that field in this case).

Because we found out ahead of time what this particular packet looks like using Wireshark, this code snippet doesn't bother to check the type of each sample, the types of flows within each sample, and the total number of each. When reading real packets, you'll need to check each of these fields to know what you'll be reading next.

Also, don't forget to use ntohl and ntohs to convert 32-bit and 16-bit fields respectively to the correct byte ordering in order to read them correctly.

Community
  • 1
  • 1
dbush
  • 205,898
  • 23
  • 218
  • 273