From c4827aa13af8bd74806ea1e72d91f5862c8c70d6 Mon Sep 17 00:00:00 2001 From: Scott Miller N1VG Date: Wed, 4 Feb 2004 22:34:08 +0000 Subject: Minor bug fixes and some restructuring --- listen/opentracdump.c | 317 +++++++++++++++++++------------------------------- 1 file changed, 118 insertions(+), 199 deletions(-) diff --git a/listen/opentracdump.c b/listen/opentracdump.c index 953618b..7a76df2 100644 --- a/listen/opentracdump.c +++ b/listen/opentracdump.c @@ -1,6 +1,7 @@ /* OpenTRAC packet decoding by Scott Miller, N1VG Copyright (c) 2003 Scott Miller Protocol v1.0 draft, Modified 19 Jun 2003 + Released under the Modified BSD license */ #include @@ -11,42 +12,12 @@ #define MAX_UNIT_INDEX 28 const char *units[]={"Volts","Amperes","Watts","Kelvins","Meters","Seconds", - "Meters/Second","Liters","Kilograms","Bits/Second", - "Bytes","Radians","Radians/Second","Square Meters", - "Joules","Newtons","Pascals","Hertz","Meters/Sec^2", - "Grays","Lumens","Cubic Meters/Second","Pascal Seconds", - "Kilograms/Meter^3","Radians/Second^2","Coulombs", + "Meters/Second","Liters","Kilograms","Bits/Second","Bytes","Radians", + "Radians/Second","Square Meters","Joules","Newtons","Pascals","Hertz", + "Meters/Sec^2","Grays","Lumens","Cubic Meters/Second", + "Pascal Seconds","Kilograms/Meter^3","Radians/Second^2","Coulombs", "Farads","Siemens","Count"}; -// Return values: 0 = OK, -1 = Couldn't Decode, -2 = Invalid Data - -int decode_sequence(unsigned char *element, int element_len); -int decode_origination(unsigned char *element, int element_len); -int decode_entityid(unsigned char *element, int element_len); -int decode_position(unsigned char *element, int element_len); -int decode_timestamp(unsigned char *element, int element_len); -int decode_comment(unsigned char *element, int element_len); -int decode_courseandspeed(unsigned char *element, int element_len); -int decode_ambiguity(unsigned char *element, int element_len); -int decode_country(unsigned char *element, int element_len); -int decode_displayname(unsigned char *element, int element_len); -int decode_waypoint(unsigned char *element, int element_len); -int decode_symbol(unsigned char *element, int element_len); -int decode_pathtrace(unsigned char *element, int element_len); -int decode_heardby(unsigned char *element, int element_len); -int decode_availablenets(unsigned char *element, int element_len); -int decode_maidenhead(unsigned char *element, int element_len); -int decode_gpsquality(unsigned char *element, int element_len); -int decode_acreg(unsigned char *element, int element_len); -int decode_rivergauge(unsigned char *element, int element_len); -int decode_hazmat(unsigned char *element, int element_len); -int flag_emergency(void); -int flag_attention(void); - -int extract_ssid(unsigned char *call); - -int decode_units(unsigned int unitnum, unsigned char *element, int element_len); - unsigned char origin_call[7]; // Who's talking unsigned char origin_ssid; unsigned char entity_call[7]; // What they're talking about @@ -54,110 +25,25 @@ unsigned char entity_ssid; unsigned int entity_serial; unsigned int entity_sequence; -/* Dump an OpenTRAC packet */ -void opentrac_dump(unsigned char *data, int length, int hexdump) -{ - int elen; - int etype; - int decoded = 0; - - lprintf(T_PROTOCOL, "OpenTRAC decode (%d bytes):\r\n", length); - strcpy(origin_call, "SENDER"); // Listen doesn't tell us the sender - origin_ssid = 0; - entity_serial = 0; - entity_sequence = 0; - while (decoded < length) { - elen = (int)*data; - decoded += (elen & 0x7f)+1; - if (elen & 0x80) { // See if it's got a 16-bit ID - elen = (elen & 0x7f) - 2; // Strip the extid flag - etype = get16(++data); - } - else { - elen--; // Don't count the type byte - etype = (int)*(data+1); - } - data+=2; // Skip to the body - lprintf(T_OPENTRAC, "EID 0x%0x len %d: ", etype, elen); - switch (etype) { - case (0x00): // Sequence - decode_sequence(data, elen); - break; - case (0x01): // Originating Station - decode_origination(data, elen); - break; - case (0x02): // Entity ID - decode_entityid(data, elen); - break; - case (0x10): // Position report - decode_position(data, elen); - break; - case (0x11): // Timestamp - decode_timestamp(data, elen); - break; - case (0x12): // Comment - decode_comment(data, elen); - break; - case (0x13): // Course and Speed - decode_courseandspeed(data, elen); - break; - case (0x14): // Positional Ambiguity - decode_ambiguity(data, elen); - break; - case (0x15): // Country Code - decode_country(data, elen); - break; - case (0x16): // Display Name - decode_displayname(data, elen); - break; - case (0x17): // Waypoint Name - decode_waypoint(data, elen); - break; - case (0x18): // Map Symbol - decode_symbol(data, elen); - break; - case (0x20): // Path Trace - decode_pathtrace(data, elen); - break; - case (0x21): // Heard-By List - decode_heardby(data, elen); - break; - case (0x22): // Available Networks - decode_availablenets(data, elen); - break; - case (0x32): // Maidenhead Locator - decode_maidenhead(data, elen); - break; - case (0x34): // GPS Data Quality - decode_gpsquality(data, elen); - break; - case (0x35): // Aircraft Registration - decode_acreg(data, elen); - break; - case (0x42): // River Flow Gauge - decode_rivergauge(data, elen); - break; - case (0x100): // Emergency/distress flag - flag_emergency(); - break; - case (0x101): // Attention/ident flag - flag_attention(); - break; - case (0x300): // Hazmat - decode_hazmat(data, elen); - break; - default: // Everything else - if ((etype & 0xff00) == 0x500) { - decode_units(etype & 0x00ff, data, elen); - } - else { - lprintf(T_OPENTRAC, "Unknown Element Type\r\n"); - } - } - data+=elen; - } + + +int extract_ssid(unsigned char *call) { + // Strip the SSID from the callsign and return it + int c, ssid; + + for (c=ssid=0;c<6;c++) { + ssid |= (call[c] & 0x80) >> (c+2); + call[c] &= 0x7f; + } + + return ssid; } +int decode_units(unsigned int unitnum, unsigned char *element, int element_len); + + +// Return values: 0 = OK, -1 = Couldn't Decode, -2 = Invalid Data + int decode_sequence(unsigned char *element, int element_len) { // 0x00 Sequence number - 16 bit integer if (element_len != 2 && element_len != 0) return -1; @@ -175,33 +61,22 @@ int decode_sequence(unsigned char *element, int element_len) { } int decode_origination(unsigned char *element, int element_len) { - // 0x01 Originating Station - Callsign, SSID, Sequence, and Network - unsigned char network; - - if (element_len < 8) return -1; - if (element_len > 9) return -1; - + // 0x01 Originating Station - Callsign, SSID, and Sequence memcpy(origin_call, element, 6); origin_call[6]=0; origin_ssid = extract_ssid(origin_call); - entity_sequence = get16(element+6); + if (element_len == 8) entity_sequence = get16(element+6); + else entity_sequence = 0; strcpy(entity_call, origin_call); entity_ssid = origin_ssid; entity_serial = 0; - if (element_len == 9) { - network = *(element+9); - lprintf(T_OPENTRAC, "Origin: %s-%d seq %d net %d\r\n",origin_call,origin_ssid,entity_sequence,network); - } - else lprintf(T_OPENTRAC, "Origin: %s-%d seq %d direct\r\n",origin_call,origin_ssid,entity_sequence); + lprintf(T_OPENTRAC, "Origin: %s-%d seq %d\r\n",origin_call,origin_ssid,entity_sequence); return 0; } int decode_entityid(unsigned char *element, int element_len) { // 0x02 Entity ID - - if (element_len > 10) return -1; - if (element_len > 5) { memcpy(entity_call, element, 6); entity_call[6]=0; @@ -251,17 +126,18 @@ int decode_position(unsigned char *element, int element_len) { double lat, lon; float alt = 0; - if (element_len < 8) return -1; // Too short! - if (element_len > 11) return -1; // Too long! - lat = get32(element) / semicircles; lon = get32(element+4) / semicircles; + if (lat >= 90 || lat <= -90 || lon >= 180 || lon <= -180) return -2; if (element_len == 11) { - alt = ((((*(element+8))<<16)+get16(element+9))/100)-10000; + alt = ((*(element+8))<<16)+get16(element+9); + alt = (alt/100)-10000; + lprintf(T_OPENTRAC, "Position: Lat %f Lon %f Alt %f meters\r\n", + lat,lon,alt); + } + else { + lprintf(T_OPENTRAC, "Position: Lat %f Lon %f\r\n",lat,lon); } - if (lat >= 90 || lat <= -90 || lon >= 180 || lon <= -180) return -2; - lprintf(T_OPENTRAC, "Position: Lat %f Lon %f Alt %f\r\n",lat,lon,alt); - return 0; } @@ -269,11 +145,8 @@ int decode_timestamp(unsigned char *element, int element_len) { // 0x11 Timestamp - Unix format time (unsigned) long rawtime = 0; - if (element_len != 4) return -1; - rawtime = get32(element); lprintf(T_OPENTRAC, "Time: %s", ctime(&rawtime)); - return 0; } @@ -281,8 +154,6 @@ int decode_comment(unsigned char *element, int element_len) { // 0x12 Freeform Comment - ASCII text char comment[127]; - if (element_len > 126) return -1; // shouldn't be possible - strncpy(comment, element, element_len); comment[element_len] = 0; lprintf(T_OPENTRAC, "Text: %s\r\n", comment); @@ -296,10 +167,8 @@ int decode_courseandspeed(unsigned char *element, int element_len) { unsigned int rawspeed; float speed; - if (element_len != 3) return -1; - - course = (*element<<1) + ((*(element+1)&0x8000) >> 15); - rawspeed = (get16(element+1) & 0x7ffff); + course = (*element<<1) | ((*(element+1)&0x80) >> 7); + rawspeed = get16(element+1) & 0x7fff; speed = (float)rawspeed*0.072; // kph if (course >= 360) return -2; lprintf(T_OPENTRAC, "Course: %d Speed: %f kph\r\n", course, speed); @@ -311,8 +180,6 @@ int decode_ambiguity(unsigned char *element, int element_len) { // 0x14 Positional Ambiguity - 16 bits, in meters int ambiguity; - if (element_len != 2) return -1; - ambiguity = get16(element); lprintf(T_OPENTRAC, "Position +/- %d meters\r\n", ambiguity); return 0; @@ -323,9 +190,6 @@ int decode_country(unsigned char *element, int element_len) { char country[3]; char subdivision[4]; - if (element_len < 2) return -1; - if (element_len > 5) return -1; - strncpy(country, element, 2); country[2] = 0; if (element_len > 2) { @@ -343,8 +207,6 @@ int decode_displayname(unsigned char *element, int element_len) { // 0x16 - Display Name (UTF-8 text) char displayname[31]; - if (element_len > 30 || !element_len) return -1; - strncpy(displayname, element, element_len); displayname[element_len] = 0; @@ -356,8 +218,6 @@ int decode_waypoint(unsigned char *element, int element_len) { // 0x17 - Waypoint Name (up to 6 chars, uppercase) char waypoint[7]; - if (element_len > 6 || !element_len) return -1; - strncpy(waypoint, element, element_len); waypoint[element_len] = 0; @@ -369,8 +229,6 @@ int decode_symbol(unsigned char *element, int element_len) { // 0x18 Map Symbol - Packed 4-bit integers int c; - if (!element_len) return -1; - lprintf(T_OPENTRAC, "Symbol: "); for (c=0;c0) lprintf(T_OPENTRAC, "."); @@ -438,17 +296,15 @@ int decode_gpsquality(unsigned char *element, int element_len) { const char *validstr[] = {"Invalid", "Valid SPS", "Valid DGPS", "Valid PPS"}; - if (element_len > 4 || !element_len) return -1; - fixtype = (element[0] & 0xc0) >> 6; validity = (element[0] & 0x30) >> 4; sats = (element[0] & 0x0f); lprintf(T_OPENTRAC, "GPS: %s %s, %d sats", fixstr[fixtype], validstr[validity], sats); if (element_len > 1) - lprintf(T_OPENTRAC, " PDOP=%.1f", (float)element[1]/10); + lprintf(T_OPENTRAC, " HDOP=%.1f", (float)element[1]/10); if (element_len > 2) - lprintf(T_OPENTRAC, " HDOP=%.1f", (float)element[2]/10); + lprintf(T_OPENTRAC, " PDOP=%.1f", (float)element[2]/10); if (element_len > 3) lprintf(T_OPENTRAC, " VDOP=%.1f", (float)element[3]/10); lprintf(T_OPENTRAC, "\r\n"); @@ -461,8 +317,6 @@ int decode_acreg(unsigned char *element, int element_len) { // 0x35 Aircraft Registration - ASCII text char nnumber[9]; - if (element_len > 8) return -1; - strncpy(nnumber, element, element_len); nnumber[element_len]=0; lprintf(T_OPENTRAC, "Aircraft ID: %s\r\n", nnumber); @@ -477,8 +331,6 @@ int decode_rivergauge(unsigned char *element, int element_len) { float flowm; float heightm; - if (element_len != 4) return -1; - flow = get16(element); height = get16(element+2); flowm = (float)flow / 64; @@ -523,13 +375,13 @@ int decode_units(unsigned int unitnum, unsigned char *element, int element_len) return 0; } -int flag_emergency(void) { +int flag_emergency(unsigned char *element, int element_len) { // 0x0100 - Emergency / Distress Call lprintf(T_ERROR, "* * * EMERGENCY * * *\r\n"); return 0; } -int flag_attention(void) { +int flag_attention(unsigned char *element, int element_len) { // 0x0101 - Attention / Ident lprintf(T_PROTOCOL, " - ATTENTION - \r\n"); return 0; @@ -542,8 +394,7 @@ int decode_hazmat(unsigned char *element, int element_len) { if (element_len < 2) { lprintf(T_OPENTRAC, "HAZMAT: Unknown Material\r\n"); } - else - { + else { un_id = get16(element) & 0x3fff; lprintf(T_OPENTRAC, "HAZMAT: UN%04d\r\n", un_id); } @@ -563,15 +414,83 @@ int decode_maidenhead(unsigned char *element, int element_len) { return 0; } -int extract_ssid(unsigned char *call) { - // Strip the SSID from the callsign and return it - int c, ssid; - for (c=ssid=0;c<6;c++) { - ssid |= (call[c] & 0x80) >> (c+2); - call[c] &= 0x7f; - } +struct { + unsigned int element_id; + unsigned char min_size; + unsigned char max_size; + int (*pDecode)(unsigned char *element, int element_len); +} element_decode[] = {{0x00, 0, 2, decode_sequence}, + {0x01, 6, 8, decode_origination}, + {0x02, 0, 10, decode_entityid}, + {0x10, 8, 11, decode_position}, + {0x11, 4, 4, decode_timestamp}, + {0x12, 0, 127, decode_comment}, + {0x13, 3, 3, decode_courseandspeed}, + {0x14, 2, 2, decode_ambiguity}, + {0x15, 2, 5, decode_country}, + {0x16, 1, 30, decode_displayname}, + {0x17, 1, 6, decode_waypoint}, + {0x18, 1, 4, decode_symbol}, + {0x20, 0, 127, decode_pathtrace}, + {0x21, 0, 127, decode_heardby}, + {0x22, 0, 127, decode_availablenets}, + {0x32, 4, 6, decode_maidenhead}, + {0x34, 1, 4, decode_gpsquality}, + {0x35, 1, 8, decode_acreg}, + {0x42, 4, 4, decode_rivergauge}, + {0x100, 0, 127, flag_emergency}, + {0x101, 0, 127, flag_attention}, + {0x300, 0, 2, decode_hazmat}, + {0, 0, 0, NULL}}, *element_decode_ptr; - return ssid; -} +/* Dump an OpenTRAC packet */ +void opentrac_dump(unsigned char *data, int length, int hexdump) +{ + int elen; + int etype; + int decoded = 0; + + lprintf(T_PROTOCOL, "OpenTRAC decode (%d bytes):\r\n", length); + strcpy(origin_call, "SENDER"); // Listen doesn't tell us the sender + origin_ssid = 0; + entity_serial = 0; + entity_sequence = 0; + while (decoded < length) { + elen = (int)*data; + decoded += (elen & 0x7f)+1; + if (elen & 0x80) { // See if it's got a 16-bit ID + elen = (elen & 0x7f) - 2; // Strip the extid flag + etype = get16(++data); + } + else { + elen--; // Don't count the type byte + etype = (int)*(data+1); + } + data+=2; // Skip to the body + lprintf(T_OPENTRAC, "EID 0x%0x len %d: ", etype, elen); + for (element_decode_ptr = element_decode; element_decode_ptr->pDecode != NULL; element_decode_ptr++) { + if (etype == element_decode_ptr->element_id) { + if (elen < element_decode_ptr->min_size || elen > element_decode_ptr->max_size) { + lprintf(T_OPENTRAC, "Invalid element length\r\n"); + } + else { + if (element_decode_ptr->pDecode(data, elen)) { + lprintf(T_OPENTRAC, "Unable to decode\r\n"); + } + } + break; + } + } + if (element_decode_ptr->pDecode == NULL) { + if ((etype & 0xff00) == 0x500) { + decode_units(etype & 0x00ff, data, elen); + } + else { + lprintf(T_OPENTRAC, "Unknown element type - unable to decode.\r\n"); + } + } + data+=elen; + } +} -- cgit v1.2.3