PCAP-NG GPS

GPS data and Pcap-NG

The pcap-ng format does not currently define a standard block or option for GPS data; in the meantime, Kismet uses a standard pcap-ng custom extension under the Kismet IANA PEN to encode this data.

You can follow the development of the GPS standard at the pcap-ng github issue

Once the standard is adopted, Kismet will transition to using the standard options.

The Kismet GPS implementation is directly modeled on the PPI GPS implementation by Jon Ellch and Harris.

Kismet inclusion of GPS data

As of 2021-03 Kismet can include GPS data in pcap-ng when using the kismetdb_to_pcap tool; ultimately this data will be encoded in streamed and directly logged pcap-ng files however while it is under development it is only available when converting from kismetdb logfiles.

Kismet IANA PEN

The IANA maintains a registry of Private Enterprise Numbers, which are unique identifiers.

The Kismet PEN used for custom options and blocks in the pcap-ng file is:

55922

Kismet GPS block

The Kismet GPS block consists of the following:

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     | GPS Magic(0x47)| Version      |            Length             |
     +---------------------------------------------------------------+
     |                  GPS Fields Presence Bitmask                  |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     /                            GPS Data                           /  
     /                         variable length                       /
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The GPS magic field must always be 0x47 (ASCII G). This indicates to parsers that this custom tag contains Kismet GPS data.

The GPS version field indicates the version of this standard; currently this version is 0x1.

The length field should be the length of the GPS data, as dictated by the options set in the GPS fields presence bitmask.

Available fields and sizes are noted below.

The GPS data of the fields must conform to the length of the fields as specified in the field bitmask.

Multi-byte values are encoded as the endian format of the pcap-ng file; parsers should detect this via the pcap-ng endian magic field and process accordingly.

The total content of the GPS record will be padded to 32 bytes to comply with the pcap-ng options format requirements.

GPS fields

FieldIDSize (bytes)UnitsDescription
Longitude0x24DegreesLongitude, encoded as a fixed 3_7 value
Latitude0x44DegreesLatitude, encoded as a fixed 3_7 value
Altitude0x84MetersAltitude in meters encoded as a fixed 6_4 value
Altitude_G0x104MetersAltitude from ground, encoded as a fixed 6_4 value (currently unused by Kismet)
GPS time0x204SecondsSeconds since unix epoch UTC (currently unused by Kismet)
GPS fractional time0x404NanosecondsUnsigned counter, nanosecond resolution. Should not exceed one second (currently unused by Kismet)
EPH0x804MetersEstimated horizontal error as a fixed 6_4 value (currently unused by Kismet)
EPV0x1004MetersEstimated vertical error as a fixed 6_4 value (currently unused by Kismet)
Timestamp (high)0x4004pcap-ng TSTimestamp (high portion) as defined by the pcap-ng standard, section 4.3 (see below)
Timestamp (low)0x8004pcap-ng TSTimestamp (low portion) as defined by the pcap-ng standard, section 4.3 (see below)

Timestamp encoding

The timestamp fields are used to provide a timestamp value for a kismet-gps custom block.

For simplicity, the timestamp values match those of the pcap-ng standard for other timestamp fields, such as in the EPB block. Specifically:

Timestamp (High) and Timestamp (Low): upper 32 bits and lower 32 bits of a 64-bit timestamp. The timestamp is a single 64-bit unsigned integer that represents the number of units of time that have elapsed since 1970-01-01 00:00:00 UTC. The length of a unit of time is specified by the ‘if_tsresol’ option (see Figure 10) of the Interface Description Block referenced by this packet. Note that, unlike timestamps in the libpcap file format, timestamps in Enhanced Packet Blocks are not saved as two 32-bit values that represent the seconds and microseconds that have elapsed since 1970-01-01 00:00:00 UTC. Timestamps in Enhanced Packet Blocks are saved as two 32-bit words that represent the upper and lower 32 bits of a single 64-bit quantity.

A simple example of converting from a second and microsecond timestamp in C or C++:

uint64_t conv_ts = ((uint64_t) ts_sec * 1000000L) + ts_usec;
uint32_t ts_high = (conv_ts >> 32);                                                           
uint32_t ts_low = conv_ts;

Number encoding

To facilitate cross-platform encoding of variable precision floating and double-precision floating numbers, all floating-point data is represented as one of the following:

EncodingRangePrecisionUse
fixed3_6000.000000 to +999.9999993.6Positional error estimates, angular rotations and error estimates, antenna beamwidth, antenna gain
fixed3_7-180.0000001 to +180.00000013.7Latitude and longitude
fixed6_4-180000.0001 to + 180000.00016.4Altitude, positional offsets, velocity, acceleration

Fixed3_6

An example implementation of encoding and decoding fixed3_6 would be:

uint32_t float_to_fixed3_6(float flt) {
    if (flt <= -000.000001)
        throw std::runtime_error("invalid value");
    if (flt > +999.999999)
        throw std::runtime_error("invalid value");

    return (uint32_t) flt * 1000000;
}

float fixed3_6_to_float(uint32_t fixed) {
    if (fixed > 1000000000)
        throw std::runtime_error("invalid value");

    return (double) (fixed / 1000000.0);
}

Fixed3_6 encoding examples

FloatEncodedComments
000.0000000000000000Zero
000.0000010000000001One millionth
001.0000000001000000One
123.1234560123123456
360.0000000360000000
999.9999990999999999Largest legal value
1000.0000001000000000Illegal value

Fixed3_7

Latitude and longitude are typically represented as double-precision floating point values between -180.0000000 and +180.0000000. In order to eliminate storing a signed value, these are mapped to the range (0, 3600000000) with a fixed decimal point at the third digit. This allows any longitude and latitude to be represented in 4 bytes with 7 digits of precision to the right of the decimal. Any values between 3600000001 (0x0xD693A401) and 4294967295 (0xFFFFFFFF) are invalid

An example implementation of encoding and decoding fixed3_7 would be:

uint32_t float_to_fixed3_7(double flt) {
    if (flt <= -180.0000001) 
        throw std::runtime_error("invalid value");
    if (flt >= +180.0000001)
        throw std::runtime_error("invalid value");
 
    int32_t scaled = (int32_t) ((flt) * (double) 10000000);
    return = (u_int32_t) (scaled + ((int32_t) 180 * 10000000));
}

double fixed3_7_to_float(uint32_t fixed) {
    if (fixed > 3600000000)
        throw std::runtime_error("invalid value");
 
    int32_t remapped = fixed – (180 * 10000000);
    return (double) ((double) remapped / 10000000);
}

Fixed3_7 encoding examples

DoubleEncodedComments
-180.0000001-Illegal value
-180.00000000000000000Smallest legal value
-179.99999990000000001
000.00000001800000000Zero
+123.12345673031234567
+179.99999993599999999
+180.00000003600000000Largest legal value
+180.00000013600000001Illegal value

Fixed6_4

Most other data such as altitude does not need high precision, but may need larger range; the fixed6_4 encoding can express -180000.0000 to 180000.0000.

An example implementation of encoding and decoding fixed3_7 would be:

uint32_t float_to_fixed3_7(double flt) {
    if (flt <= -180000.0001) 
        throw std::runtime_error("invalid value");
    if (flt >= +180000.0001)
        throw std::runtime_error("invalid value");
        
    int32_t scaled_l = (int32_t) ((flt) * (double) 10000);
    return (u_int32_t) (scaled_l + ((int32_t) 180000 * 10000)); 
}

double fixed3_7_to_float(uint32_t fixed) {
    if (fixed > 3600000000)
        throw std::runtime_error("invalid value");

    int32_t remapped = fixed – (180000 * 10000);
    return (double) ((double) remapped / 10000);
}

Fixed6_4 encoding examples

DoubleEncodedComments
-180000.0001Illegal value
-180000.00000000000000Most negative expressible value
-179999.99990000000001
-010000.00000800000000Marianas trench (approx)
000000.00001800000000Sea level
+000000.00011800000001Sea level plus .0001 meters
+021000.01232010000123Very high altitude flight
+179999.99993599999999
+180000.00003600000000Most positive expressible value
+180000.0001Illegal value

Role in pcap-ng

The Kismet GPS block can be contained in pcap-ng as an option on an enhanced packet EPB block, or as a custom block type. When found as an option in the EPB, it is the GPS information for that specific packet, and when found as a custom block type, it is the track data or location of the system at that time, but not otherwise tied to a specific packet.

GPS custom option

The Kismet GPS data follows the rules of the pcap-ng custom options: It must be identified as a custom binary option, using the Kismet IANA PEN, and padded to 32 bits.

An EPB with the Kismet GPS data would look like:

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +---------------------------------------------------------------+
    0 |                    Block Type = 0x00000006                    |
      +---------------------------------------------------------------+
    4 |                      Block Total Length                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    8 |                         Interface ID                          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   12 |                        Timestamp (High)                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   16 |                        Timestamp (Low)                        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   20 |                    Captured Packet Length                     |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   24 |                    Original Packet Length                     |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   28 /                                                               /
      /                          Packet Data                          /
      /              variable length, padded to 32 bits               /
      /                                                               /
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      /                                                               /
      /                      Options (variable)                       /
      /                                                               /
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |     Custom Option Code (2989) |         Option Length         |
      +---------------------------------------------------------------+
      |                Private Enterprise Number (55922)              |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      | GPS Magic(0x47)| Version      |            Length             |
      +---------------------------------------------------------------+
      |                  GPS Fields Presence Bitmask                  |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      /                            GPS Data                           /  
      /              variable length, padded to 32 bits               /
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                      End-of-options block                     |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                      Block Total Length                       |
      +---------------------------------------------------------------+

GPS custom block

A custom pcap-ng Kismet GPS block would look like:

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +---------------------------------------------------------------+
    0 |                    Block Type = 0x00000BAD                    |
      +---------------------------------------------------------------+
    4 |                      Block Total Length                       |
      +---------------------------------------------------------------+
    8 |                Private Enterprise Number (55922)              |
      +---------------------------------------------------------------+
      | GPS Magic(0x47)| Version      |            Length             |
      +---------------------------------------------------------------+
      |                  GPS Fields Presence Bitmask                  |
      +---------------------------------------------------------------+
      /                            GPS Data                           /  
      /              variable length, padded to 32 bits               /
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      /                      Options (variable)                       /
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                      Block Total Length                       |
      +---------------------------------------------------------------+

Current implementation

Currently, no tools exist to read the custom fields from the pcapng; any extraction of the data must be done with custom tools.

Any tool capable of parsing pcap-ng files should be able to process a GPS tagged file without incident, but will not read the data.