1
votes

I'm trying to acquire and parse an ethernet label (dest address, source address, type/length field) using WinPCap.

I'm mostly copying/pasting from the WinPCap SDK. I am trying to store the WinPCap packet data (in pkt_data) in a struct named ethernet containing destination address [6 bytes], source address [6 bytes], type/length field (short int) and packet length (int).

I think that the pkt_data is lined up with the first 6 bytes as the destination address, the next 6 bytes as the source address, and the two after as the type/length field, but I'm not sure.

Does anyone know the exact byte order of the label that WinPCap stores in this example?

/* If device is open, acquire attributes from packet */
if( ( res = pcap_next_ex( fp, &header, &pkt_data)) >= 0)
{
    if(res != 0)
    {
        /* Acquire the length of the capture */
        ethernet->length = header->caplen;

        /* Acquire destination MAC address */
        for (i = 0; i < 6; i++)
            ethernet->destAddress[i] = pkt_data[i];

        /* Acquire source MAC address */
        for ( i = 6; i < 12; i++ )
            ethernet->srcAddress[i] = pkt_data[i];

        /* Acquire etherType type/length designation field */
        ethernet->type = ( pkt_data[12] | pkt_data[13] );

        /* Acquire the remaining data of the packet */
        for ( i = 14; (i < header->caplen + 1); i++ )
            ethernet->data[i - 14] = pkt_data[i];
    }

    /* Device error: cannot read from packet */
    else if(res == -1)
        printf("Error reading the packets: %s\n", pcap_geterr(fp));
}
1

1 Answers

0
votes

The byte order of data in packets captured by libpcap/WinPcap is the byte order in which the data is transmitted on the network; libpcap/WinPcap supply raw packet data (except for "pseudo-header" information such as Radiotap radio headers, which don't appear on the wire and are in whatever byte order the software that generates them use, e.g. little-endian in the case of Radiotap).

MAC addresses are best thought of as 6-byte sequences, rather than as 48-bit numbers, so there's no byte-order issue for them. The destination address comes first, so it's in pkt_data[0] through pkt_data[5]; the source address comes next, so it's in pkt_data[6] through pkt_data[11].

Note that

    /* Acquire source MAC address */
    for ( i = 6; i < 12; i++ )
        ethernet->srcAddress[i] = pkt_data[i];

is wrong - srcAddress is probably a 6-byte array, so it has srcAddress[0] through srcAddress[5], and does not have srcAddress[6] on. You could do it with

    /* Acquire source MAC address */
    for ( i = 0; i < 6; i++ )
        ethernet->srcAddress[i] = pkt_data[i + 6];

but it's probably easiest to use memcpy() to copy the data rather than writing the loop yourself:

    memcpy(ethernet->dstAddress, &pkt_data[0], 6);
    memcpy(ethernet->srcAddress, &pkt_data[6], 6);

The type/length field comes after that, and is two bytes long, so it's in pkt_data[12] and pkt_data[13]. As per the IEEE 802.3 standard, "The Length/Type field is transmitted and received with the high order octet first." The "first" octet is pkt_data[12], so it's the "high order octet" it should be in the high order 8 bits of the value; the "second" octet is pkt_data[13] and is in the low order 8 bits of the value, so

ethernet->type = (pkt_data[12]<<8) | pkt_data[13];