/* isi-gps.c * Dissector for ISI's Location resource * Copyright 2010-2015, Sebastian Reichel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * GPS Data Packet Reverse Engineered by Luke Dashjr */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include "packet-isi.h" #include "isi-gps.h" /* centimeter per second to kilometer per hour */ #define CMS_TO_KMH 0.036 #define SAT_PKG_LEN 12 static const value_string isi_location_id[] = { {0x00, "LS_LOCATION_REQ"}, {0x01, "LS_LOCATION_RESP"}, {0x02, "LS_LOCATION_NTF"}, {0x03, "LS_LOCATION_STOP_REQ"}, {0x04, "LS_LOCATION_STOP_RESP"}, {0x07, "LS_METHOD_INFORMATION_REQ"}, {0x08, "LS_METHOD_INFORMATION_RESP"}, {0x09, "LS_METHOD_INFORMATION_IND"}, {0x0A, "LS_SERVICE_REQUIRED_REQ"}, {0x0B, "LS_SERVICE_REQUIRED_RESP"}, {0x0C, "LS_SERVICE_REQUIRED_IND"}, {0x0D, "LS_PRIVACY_REGISTRATION_REQ"}, {0x0E, "LS_PRIVACY_REGISTRATION_RESP"}, {0x0F, "LS_PRIVACY_NTF"}, {0x10, "LS_PRIVACY_NOTIFICATION_RESULT_REQ"}, {0x11, "LS_PRIVACY_NOTIFICATION_RESULT_RESP"}, {0x12, "LS_METHOD_REGISTRATION_REQ"}, {0x13, "LS_METHOD_REGISTRATION_RESP"}, {0x14, "LS_METHOD_ASSISTANCE_REQ"}, {0x15, "LS_METHOD_ASSISTANCE_RESP"}, {0x20, "LS_NMEA_LISTENER_REQ"}, {0x21, "LS_NMEA_LISTENER_RESP"}, {0x22, "LS_NMEA_LISTENER_NTF"}, {0x30, "LS_CLEAR_GPS_DATA_REQ"}, {0x31, "LS_CLEAR_GPS_DATA_RESP"}, {0x32, "LS_PING_REQ"}, {0x33, "LS_PING_RESP"}, {0x34, "LS_PING_NTF"}, {0x36, "LS_LTM_TEST_REQ"}, {0x37, "LS_LTM_TEST_RESP"}, {0x38, "LS_LTM_TEST_NTF"}, {0x39, "LS_HW_CONN_TEST_REQ"}, {0x3A, "LS_HW_CONN_TEST_RESP"}, {0x40, "LS_GSM_PRIVACY_REQ"}, {0x41, "LS_GSM_PRIVACY_RESP"}, {0x42, "LS_GSM_PRIVACY_TIMEOUT_REQ"}, {0x43, "LS_GSM_PRIVACY_TIMEOUT_RESP"}, {0x44, "LS_GSM_LOCATE_REQ"}, {0x45, "LS_GSM_LOCATE_RESP"}, {0x50, "LS_SUPL_LISTENER_REGISTRATION_REQ"}, {0x51, "LS_SUPL_LISTENER_REGISTRATION_RESP"}, {0x52, "LS_SUPL_CREATE_SESSION_REQUEST_NTF"}, {0x53, "LS_SUPL_CREATE_SESSION_RESPONSE_NTF"}, {0x54, "LS_SUPL_SESSION_END_NTF"}, {0x55, "LS_SUPL_GET_SUPL_INFO_REQ"}, {0x56, "LS_SUPL_GET_SUPL_INFO_RESP"}, {0x57, "LS_SUPL_CANCEL_SUPL_INFO_REQ"}, {0x58, "LS_SUPL_CANCEL_SUPL_INFO_RESP"}, {0x59, "LS_SUPL_POS_NTF"}, {0x5A, "LS_SUPL_POS_ACK_NTF"}, {0x5B, "LS_SUPL_POS_END_NTF"}, {0x5C, "LS_SUPL_SESSION_STATUS_REQUEST_NTF"}, {0x5D, "LS_SUPL_SESSION_STATUS_RESPONSE_NTF"}, {0x5E, "LS_SUPL_POSITION_FIX_NTF"}, {0x60, "LS_WCDMA_LOCATE_REQ"}, {0x61, "LS_WCDMA_LOCATE_RESP"}, {0x62, "LS_WCDMA_LOCATE_NTF"}, {0x63, "LS_SOURCE_LIST_REQ"}, {0x64, "LS_SOURCE_LIST_RESP"}, {0x65, "LS_TRACKING_START_REQ"}, {0x66, "LS_TRACKING_START_RESP"}, {0x67, "LS_TRACKING_DATA_NTF"}, {0x68, "LS_TRACKING_STOP_REQ"}, {0x69, "LS_TRACKING_STOP_RESP"}, {0x70, "LS_POSITIONING_SUPPORT_REQ"}, {0x71, "LS_POSITIONING_SUPPORT_RESP"}, {0x72, "LS_POSITIONING_SUPPORT_NTF"}, {0x73, "LS_GPS_STATUS_REQ"}, {0x74, "LS_GPS_STATUS_RESP"}, {0x76, "LS_SUPL_ALLOWED_REQ"}, {0x77, "LS_SUPL_ALLOWED_RESP"}, {0x78, "LS_SENSOR_REGISTRATION_REQ"}, {0x79, "LS_SENSOR_REGISTRATION_RESP"}, {0x7A, "LS_SENSOR_EVENT_REQ"}, {0x7B, "LS_SENSOR_EVENT_RESP"}, {0x7C, "LS_SENSOR_NTF"}, {0x7D, "LS_GPS_STATUS_IND"}, {0x7E, "LS_SUPL_SERVER_CONF_REQ"}, {0x7F, "LS_SUPL_SERVER_CONF_RESP"}, {0x80, "LS_SUPL_NW_INIT_REQ"}, {0x81, "LS_SUPL_NW_INIT_RESP"}, {0x82, "LS_SOCKET_REGISTRATION_REQ"}, {0x83, "LS_SOCKET_REGISTRATION_RESP"}, {0x84, "LS_SOCKET_OPEN_REQUEST_NTF"}, {0x85, "LS_SOCKET_OPEN_RESPONSE_NTF"}, {0x86, "LS_SOCKET_SEND_REQUEST_NTF"}, {0x87, "LS_SOCKET_SEND_RESPONSE_NTF"}, {0x88, "LS_SOCKET_RECV_REQ"}, {0x89, "LS_SOCKET_RECV_RESP"}, {0x8A, "LS_SOCKET_CLOSE_REQUEST_NTF"}, {0x8B, "LS_SOCKET_CLOSE_RESPONSE_NTF"}, {0x8C, "LS_SOCKET_CLOSED_REQ"}, {0x8D, "LS_SOCKET_CLOSED_RESP"}, {0x90, "LS_HYBRID_TRACKING_REQ"}, {0x91, "LS_HYBRID_TRACKING_RESP"}, {0x92, "LS_HYBRID_TRACKING_NTF"}, {0xA0, "LS_GPS_ANTENNA_CTRL_REQ"}, {0xA1, "LS_GPS_ANTENNA_CTRL_RESP"}, {0xE0, "LS_DEBUG_REQ"}, {0xE1, "LS_DEBUG_RESP"}, {0x00, NULL } }; static const value_string isi_location_sub_id[] = { {0x0103, "LS_SB_PRIVACY"}, {0x0105, "LS_SB_JAVA_INFO"}, {0x0108, "LS_SB_CDMA_WAP_INFO"}, {0x0109, "LS_SB_SS_REQUESTOR_ID"}, {0x010A, "LS_SB_SS_CODEWORD"}, {0x010B, "LS_SB_SS_SERVICE_TYPE_ID"}, {0x0130, "LS_SB_LATITUDE_LONGITUDE"}, {0x0131, "LS_SB_ALTITUDE"}, {0x0132, "LS_SB_VELOCITY"}, {0x0133, "LS_SB_NMEA_0183"}, {0x0134, "LS_SB_TIMESTAMP"}, {0x0135, "LS_SB_NMEA_OPTIONS"}, {0x0160, "LS_SB_GPS_EXACT_TIME"}, {0x0161, "LS_SB_GPS_USER_DOPS"}, {0x0162, "LS_SB_GPS_SAT_LIST"}, {0x0163, "LS_SB_GPS_CHANNEL_STATUS"}, {0x0524, "LS_SB_GSM_MULTIPLE_SETS"}, {0x0529, "LS_SB_GSM_MEAS_ERROR_INFO"}, {0x052A, "LS_SB_GSM_POSITIONING_INSTR"}, {0x052B, "LS_SB_GSM_LOCATION_INFO"}, {0x052C, "LS_SB_GSM_GPS_MEAS_INFO"}, {0x052D, "LS_SB_GSM_EXT_REF_ID"}, {0x0530, "LS_SB_GSM_GPS_TIME_ASSIST_MEAS"}, {0x0531, "LS_SB_GSM_REQUIRED_RESPONSE_TIME"}, {0x0551, "LS_SB_SS_CLIENT_EXT_ID"}, {0x0554, "LS_SB_SS_CLIENT_NAME"}, {0x0556, "LS_SB_SS_NOTIFICATION_INFO"}, {0x0689, "LS_SB_LTM_TEST_ABORT"}, {0x070B, "LS_SB_LTM_AI2_CMD_PACKET"}, {0x070C, "LS_SB_LTM_AI2_RSP_PACKET"}, {0x070D, "LS_SB_LTM_DELETE_ASSISTANCE_DATA"}, {0x0800, "LS_SB_SUPL_TIMESTAMP"}, {0x0801, "LS_SB_SUPL_POSITION"}, {0x0802, "LS_SB_SUPL_VELOCITY"}, {0x0803, "LS_SB_SUPL_ALLOWED_CAPABILITIES"}, {0x0804, "LS_SB_SUPL_INFO_SET_CAPABILITIES"}, {0x0805, "LS_SB_SUPL_INFO_AD_REQUEST"}, {0x0806, "LS_SB_SUPL_POS"}, {0x0807, "LS_SB_SUPL_RRLP_LOOPBACK"}, {0x0808, "LS_SB_SUPL_QOP"}, {0x0809, "LS_SB_SUPL_SESSION_POSITION"}, {0x080A, "LS_SB_SUPL_SERVER_METHOD"}, {0x0900, "LS_SB_CLIENT_IDENT"}, {0x0901, "LS_SB_HYBRID_TRACKING_INSTR"}, {0x0902, "LS_SB_NPE_POSITION"}, {0x0903, "LS_SB_NPE_TIME"}, {0x0904, "LS_SB_NPE_VELOCITY"}, {0x0905, "LS_SB_NPE_CHANNELS"}, {0x0906, "LS_SB_NPE_NMEA"}, {0x0907, "LS_SB_CELL_INFO_GSM"}, {0x0908, "LS_SB_CELL_INFO_WCDMA"}, {0x0999, "CLMI_SB_ASTNC_GPS_CURR_NAV_MODEL"}, {0x0A00, "LS_SB_WCDMA_POSITIONING_INSTR"}, {0x0A01, "LS_SB_WCDMA_LOCATION_INFO"}, {0x0A02, "LS_SB_WCDMA_MEAS_ERROR_INFO"}, {0x0A03, "LS_SB_WCDMA_GPS_MEAS_INFO"}, {0x1012, "CLMI_SB_ASTNC_GPS_DGPS_CORRECTIONS"}, {0x1013, "CLMI_SB_ASTNC_GPS_EPHEMERIS"}, {0x1014, "CLMI_SB_ASTNC_GPS_IONOSPHERIC"}, {0x1015, "CLMI_SB_ASTNC_GPS_UTC"}, {0x1016, "CLMI_SB_ASTNC_GPS_ALMANAC"}, {0x1017, "CLMI_SB_ASTNC_GPS_BAD_SATELLITES"}, {0x101B, "CLMI_SB_ASTNC_GPS_ACQUISITION"}, {0x1030, "CLMI_SB_ASTNC_GPS_REF_TIME"}, {0x1031, "CLMI_SB_ASTNC_GPS_REF_TIME_UMTS"}, {0x1032, "CLMI_SB_ASTNC_GPS_REF_TIME_GSM"}, {0x1048, "CLMI_SB_ASTNC_FRAME_TRIGGER_UMTS"}, {0x1049, "CLMI_SB_ASTNC_FRAME_TRIGGER_GSM"}, {0x104A, "CLMI_SB_GPS_TOW_RELATION_UMTS"}, {0x104B, "CLMI_SB_GPS_TOW_RELATION_GSM"}, {0x1100, "LS_SB_SENSOR_REGISTRATION_STATUS"}, {0x1101, "LS_SB_SENSOR_TYPE"}, {0x1102, "LS_SB_SENSOR_ACCELEROMETER_ACTION"}, {0x1200, "LS_SB_SOCKET_ADDR"}, {0x1201, "LS_SB_SOCKET_ADDR_EXT"}, {0x1202, "LS_SB_SOCKET_BEARER_TYPE"}, {0x1203, "LS_SB_SOCKET_IPADDR"}, {0xEFEE, "LS_SB_METHOD_INFORMATION"}, {0xEEEF, "CLMI_SB_GPS_PSEUDORANGE_MEAS"}, {0x0000, NULL} }; static const value_string isi_location_socket_addr_type[] = { {0x00, "IPV4"}, {0x01, "IPv6"}, {0x02, "FQDN"}, {0x00, NULL } }; static const value_string isi_location_gps_power[] = { {0x00, "GPS_OFF"}, {0x01, "GPS_ON"}, {0x00, NULL } }; static const value_string isi_location_gps_status[] = { {0x00, "GPS_STATE_NONE"}, {0x01, "GPS_STATE_SEARCH"}, {0x02, "GPS_STATE_FIX"}, {0x03, "GPS_STATE_SLEEP"}, {0x00, NULL } }; static const value_string isi_location_bearer_type[] = { {0x02, "BEARER_GPRS"}, {0x04, "BEARER_WLAN"}, {0x00, NULL } }; static const value_string isi_location_hybrid_cmd[] = { {0x00, "MEASUREMENT_START"}, {0x01, "MEASUREMENT_MODIFY"}, {0x02, "MEASUREMENT_STOP"}, {0x00, NULL } }; static const value_string isi_location_hybrid_report_criteria[] = { {0x00, "LS_HYBRID_REPORT_AT_ALL_INTERVALS"}, {0x01, "LS_HYBRID_REPORT_ONLY_POSITION_CHANGES"}, {0x00, NULL } }; static const value_string isi_location_hybrid_cause[] = { {0x00, "LS_HYBRID_CAUSE_SUCCESS"}, {0x01, "LS_HYBRID_CAUSE_NO_POSITION_YET"}, {0x02, "LS_HYBRID_CAUSE_ERROR_UNSPECIFIED"}, {0x03, "LS_HYBRID_CAUSE_ERROR_NO_METHODS"}, {0x00, NULL } }; static const value_string isi_location_socket_status[] = { {0x00, "OK"}, {0x01, "ERROR"}, {0x02, "SERVER_NOT_AUTHENTICATED"}, {0x00, NULL } }; static dissector_handle_t isi_location_handle; static void dissect_isi_location(tvbuff_t *tvb, packet_info *pinfo, proto_item *tree); static gint32 hf_isi_location_cmd = -1; static gint32 hf_isi_location_sub_pkgs = -1; static gint32 hf_isi_location_sub_type = -1; static gint32 hf_isi_location_sub_len = -1; static gint32 hf_isi_location_gps_power = -1; static gint32 hf_isi_location_gps_status = -1; static gint32 hf_isi_location_year = -1; static gint32 hf_isi_location_month = -1; static gint32 hf_isi_location_day = -1; static gint32 hf_isi_location_hour = -1; static gint32 hf_isi_location_minute = -1; static gint32 hf_isi_location_second = -1; static gint32 hf_isi_location_latitude = -1; static gint32 hf_isi_location_longitude = -1; static gint32 hf_isi_location_eph = -1; static gint32 hf_isi_location_altitude = -1; static gint32 hf_isi_location_epv = -1; static gint32 hf_isi_location_course = -1; static gint32 hf_isi_location_epd = -1; static gint32 hf_isi_location_speed = -1; static gint32 hf_isi_location_eps = -1; static gint32 hf_isi_location_climb = -1; static gint32 hf_isi_location_epc = -1; static gint32 hf_isi_location_mcc = -1; static gint32 hf_isi_location_mnc = -1; static gint32 hf_isi_location_lac = -1; static gint32 hf_isi_location_cid = -1; static gint32 hf_isi_location_ucid = -1; static gint32 hf_isi_location_satellites = -1; static gint32 hf_isi_location_prn = -1; static gint32 hf_isi_location_sat_used = -1; static gint32 hf_isi_location_sat_strength = -1; static gint32 hf_isi_location_sat_elevation = -1; static gint32 hf_isi_location_sat_azimuth = -1; static gint32 hf_isi_location_socket_addr_port = -1; static gint32 hf_isi_location_socket_addr_type = -1; static gint32 hf_isi_location_socket_addr_ip_len = -1; static gint32 hf_isi_location_socket_addr_fqdn_len = -1; static gint32 hf_isi_location_socket_addr_ipv4 = -1; static gint32 hf_isi_location_socket_addr_ipv6 = -1; static gint32 hf_isi_location_socket_addr_fqdn = -1; static gint32 hf_isi_location_socket_bearer = -1; static gint32 hf_isi_location_hybrid_cmd = -1; static gint32 hf_isi_location_hybrid_allowed_methods = -1; static gint32 hf_isi_location_hybrid_options = -1; static gint32 hf_isi_location_hybrid_interval = -1; static gint32 hf_isi_location_hybrid_report_criteria = -1; static gint32 hf_isi_location_hybrid_acwp_timer = -1; static gint32 hf_isi_location_hybrid_method_cwp = -1; static gint32 hf_isi_location_hybrid_method_acwp = -1; static gint32 hf_isi_location_hybrid_method_gnss = -1; static gint32 hf_isi_location_hybrid_method_agnss = -1; static gint32 hf_isi_location_hybrid_option_channel_status = -1; static gint32 hf_isi_location_hybrid_option_cell_info = -1; static gint32 hf_isi_location_hybrid_option_nmea_0183 = -1; static gint32 hf_isi_location_hybrid_client_id = -1; static gint32 hf_isi_location_hybrid_npe_id = -1; static gint32 hf_isi_location_cause = -1; static gint32 hf_isi_location_status = -1; static gint32 hf_isi_location_status_ok = -1; static gint32 hf_isi_location_status_complete = -1; static gint32 hf_isi_location_status_fix = -1; static gint32 hf_isi_location_status_meas_fix = -1; static gint32 hf_isi_location_socket_descriptor = -1; static gint32 hf_isi_location_socket_status = -1; static gint32 hf_isi_location_socket_error = -1; static gint32 hf_isi_location_data_len = -1; static gint32 hf_isi_location_data = -1; static gint ett_flags_methods = -1; static gint ett_flags_options = -1; static gint ett_flags_status = -1; static dissector_handle_t supl_handle; static const int *isi_location_hybrid_method_flags[] = { &hf_isi_location_hybrid_method_cwp, &hf_isi_location_hybrid_method_acwp, &hf_isi_location_hybrid_method_gnss, &hf_isi_location_hybrid_method_agnss, NULL }; static const int *isi_location_hybrid_option_flags[] = { &hf_isi_location_hybrid_option_channel_status, &hf_isi_location_hybrid_option_cell_info, &hf_isi_location_hybrid_option_nmea_0183, NULL }; static const int *isi_location_hybrid_status_flags[] = { &hf_isi_location_status_ok, &hf_isi_location_status_complete, &hf_isi_location_status_fix, &hf_isi_location_status_meas_fix, NULL }; void proto_reg_handoff_isi_location(void) { static gboolean initialized=FALSE; if (!initialized) { isi_location_handle = create_dissector_handle(dissect_isi_location, proto_isi); dissector_add_uint("isi.resource", 0x54, isi_location_handle); supl_handle = find_dissector("ulp"); } } void proto_register_isi_location(void) { static hf_register_info hf[] = { { &hf_isi_location_cmd, { "Command", "isi.location.cmd", FT_UINT8, BASE_HEX, isi_location_id, 0x0, "Command", HFILL }}, { &hf_isi_location_sub_pkgs, { "Number of Subpackets", "isi.location.pkgs", FT_UINT8, BASE_DEC, NULL, 0x0, "Number of Subpackets", HFILL }}, { &hf_isi_location_sub_type, { "Subpacket Type", "isi.location.sub.type", FT_UINT16, BASE_HEX, isi_location_sub_id, 0x0, "Subpacket Type", HFILL }}, { &hf_isi_location_sub_len, { "Subpacket Length", "isi.location.sub.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Subpacket Length", HFILL }}, { &hf_isi_location_gps_power, { "Power", "isi.location.power", FT_UINT8, BASE_HEX, isi_location_gps_power, 0x0, "Power", HFILL }}, { &hf_isi_location_gps_status, { "Status", "isi.location.status", FT_UINT8, BASE_HEX, isi_location_gps_status, 0x0, "Status", HFILL }}, { &hf_isi_location_year, { "Year", "isi.location.date.year", FT_UINT16, BASE_DEC, NULL, 0x0, "Year", HFILL }}, { &hf_isi_location_month, { "Month", "isi.location.date.month", FT_UINT8, BASE_DEC, NULL, 0x0, "Month", HFILL }}, { &hf_isi_location_day, { "Day", "isi.location.date.day", FT_UINT8, BASE_DEC, NULL, 0x0, "Day", HFILL }}, { &hf_isi_location_hour, { "Hour", "isi.location.time.hour", FT_UINT8, BASE_DEC, NULL, 0x0, "Hour", HFILL }}, { &hf_isi_location_minute, { "Minute", "isi.location.time.minute", FT_UINT8, BASE_DEC, NULL, 0x0, "Minute", HFILL }}, { &hf_isi_location_second, { "Second", "isi.location.time.second", FT_FLOAT, BASE_NONE, NULL, 0x0, "Second", HFILL }}, { &hf_isi_location_latitude, { "Latitude", "isi.location.lat", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Latitude", HFILL }}, { &hf_isi_location_longitude, { "Longitude", "isi.location.lon", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Longitude", HFILL }}, { &hf_isi_location_eph, { "Position Accuracy", "isi.location.eph", FT_FLOAT, BASE_NONE, NULL, 0x0, "EPH (position accuracy) in meter", HFILL }}, { &hf_isi_location_altitude, { "Altitude", "isi.location.alt", FT_INT16, BASE_DEC, NULL, 0x0, "Altitude in meter", HFILL }}, { &hf_isi_location_epv, { "Altitude Accuracy", "isi.location.epv", FT_FLOAT, BASE_NONE, NULL, 0x0, "EPV (altitude accuracy) in meter", HFILL }}, { &hf_isi_location_course, { "Course", "isi.location.course", FT_FLOAT, BASE_NONE, NULL, 0x0, "Course in degree", HFILL }}, { &hf_isi_location_epd, { "Course Accuracy", "isi.location.epd", FT_FLOAT, BASE_NONE, NULL, 0x0, "EPD (course accuracy) in degree", HFILL }}, { &hf_isi_location_speed, { "Speed", "isi.location.speed", FT_FLOAT, BASE_NONE, NULL, 0x0, "Speed in km/h", HFILL }}, { &hf_isi_location_eps, { "Speed Accuracy", "isi.location.eps", FT_FLOAT, BASE_NONE, NULL, 0x0, "EPS (speed accuracy) in km/h", HFILL }}, { &hf_isi_location_climb, { "Climb", "isi.location.climb", FT_FLOAT, BASE_NONE, NULL, 0x0, "Climb in km/h", HFILL }}, { &hf_isi_location_satellites, { "Visible Satellites", "isi.location.satellites", FT_UINT8, BASE_DEC, NULL, 0x0, "Visible Satellites", HFILL }}, { &hf_isi_location_prn, { "Pseudeorandom Noise (PRN)", "isi.location.sat.prn", FT_UINT8, BASE_HEX_DEC, NULL, 0x0, "Pseudeorandom Noise (PRN)", HFILL }}, { &hf_isi_location_sat_used, { "in use", "isi.location.sat.used", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "in use", HFILL }}, { &hf_isi_location_sat_strength, { "Signal Strength", "isi.location.sat.strength", FT_FLOAT, BASE_NONE, NULL, 0x0, "Signal Strength", HFILL }}, { &hf_isi_location_sat_elevation, { "Elevation", "isi.location.sat.elevation", FT_FLOAT, BASE_NONE, NULL, 0x0, "Elevation", HFILL }}, { &hf_isi_location_sat_azimuth, { "Azimuth", "isi.location.sat.azimuth", FT_FLOAT, BASE_NONE, NULL, 0x0, "Azimuth", HFILL }}, { &hf_isi_location_epc, { "Climb Accuracy", "isi.location.epc", FT_FLOAT, BASE_NONE, NULL, 0x0, "EPC (climb accuracy) in km/h", HFILL }}, { &hf_isi_location_mcc, { "Mobile Country Code (MCC)", "isi.location.gsm.mcc", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, "Mobile Country Code (MCC)", HFILL }}, { &hf_isi_location_mnc, { "Mobile Network Code (MNC)", "isi.location.gsm.mnc", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, "Mobile Network Code (MNC)", HFILL }}, { &hf_isi_location_lac, { "Location Area Code (LAC)", "isi.location.gsm.lac", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, "Location Area Code (LAC)", HFILL }}, { &hf_isi_location_cid, { "Cell ID (CID)", "isi.location.gsm.cid", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, "Cell ID (CID)", HFILL }}, { &hf_isi_location_ucid, { "Cell ID (UCID)", "isi.location.gsm.ucid", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, "Cell ID (UCID)", HFILL }}, { &hf_isi_location_socket_addr_port, { "Port", "isi.location.socket.addr.port", FT_UINT16, BASE_DEC, NULL, 0x0, "Port", HFILL }}, { &hf_isi_location_socket_addr_type, { "Type", "isi.location.socket.addr.type", FT_UINT8, BASE_HEX, isi_location_socket_addr_type, 0x0, "Type", HFILL }}, { &hf_isi_location_socket_addr_ip_len, { "IP Length", "isi.location.socket.addr.ip.len", FT_UINT8, BASE_DEC, NULL, 0x0, "IP Length", HFILL }}, { &hf_isi_location_socket_addr_fqdn_len, { "Domain Length", "isi.location.socket.addr.fqdn.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Domain Length", HFILL }}, { &hf_isi_location_socket_addr_ipv4, { "IPv4", "isi.location.socket.addr.ip", FT_IPv4, BASE_NONE, NULL, 0x0, "IPv6", HFILL }}, { &hf_isi_location_socket_addr_ipv6, { "IPv6", "isi.location.socket.addr.ip", FT_IPv6, BASE_NONE, NULL, 0x0, "IPv6", HFILL }}, { &hf_isi_location_socket_addr_fqdn, { "Domain", "isi.location.socket.addr.fqdn", FT_STRING, BASE_NONE, NULL, 0x0, "Domain", HFILL }}, { &hf_isi_location_socket_bearer, { "Bearer Type", "isi.location.bearer", FT_UINT8, BASE_HEX, isi_location_bearer_type, 0x0, "Bearer Type", HFILL }}, { &hf_isi_location_hybrid_cmd, { "Hybrid Command", "isi.location.hybrid.cmd", FT_UINT8, BASE_HEX, isi_location_hybrid_cmd, 0x0, "Hybrid Command", HFILL }}, { &hf_isi_location_hybrid_allowed_methods, { "Allowed Methods", "isi.location.hybrid.allowed_methods", FT_UINT32, BASE_HEX, NULL, 0x0, "Allowed Methods", HFILL }}, { &hf_isi_location_hybrid_options, { "Options", "isi.location.hybrid.options", FT_UINT32, BASE_HEX, NULL, 0x0, "Options", HFILL }}, { &hf_isi_location_hybrid_interval, { "Interval", "isi.location.hybrid.interval", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, "Interval", HFILL }}, { &hf_isi_location_hybrid_report_criteria, { "Report Criteria", "isi.location.hybrid.report_criteria", FT_UINT8, BASE_HEX, isi_location_hybrid_report_criteria, 0x0, "Report Criteria", HFILL }}, { &hf_isi_location_hybrid_acwp_timer, { "ACWP Timer", "isi.location.hybrid.acwp_timer", FT_UINT8, BASE_DEC, NULL, 0x0, "ACWP Timer", HFILL }}, { &hf_isi_location_hybrid_option_channel_status, { "Channel Status", "isi.location.hybrid.options.channel_status", FT_BOOLEAN, BASE_NONE, NULL, 0x000000001, "Channel Status", HFILL }}, { &hf_isi_location_hybrid_option_cell_info, { "Cell Info", "isi.location.hybrid.options.cell_info", FT_BOOLEAN, BASE_NONE, NULL, 0x000000002, "Cell Info", HFILL }}, { &hf_isi_location_hybrid_option_nmea_0183, { "NMEA 0183", "isi.location.hybrid.options.nmea_0183", FT_BOOLEAN, BASE_NONE, NULL, 0x000000004, "NMEA 0183", HFILL }}, { &hf_isi_location_hybrid_method_cwp, { "CWP", "isi.location.hybrid.methods.cwp", FT_BOOLEAN, BASE_NONE, NULL, 0x000000001, "CWP", HFILL }}, { &hf_isi_location_hybrid_method_acwp, { "ACWP", "isi.location.hybrid.methods.acwp", FT_BOOLEAN, BASE_NONE, NULL, 0x000000002, "ACWP", HFILL }}, { &hf_isi_location_hybrid_method_gnss, { "GNSS", "isi.location.hybrid.methods.gnss", FT_BOOLEAN, BASE_NONE, NULL, 0x000000004, "GNSS", HFILL }}, { &hf_isi_location_hybrid_method_agnss, { "AGNSS", "isi.location.hybrid.methods.agnss", FT_BOOLEAN, BASE_NONE, NULL, 0x000000008, "AGNSS", HFILL }}, { &hf_isi_location_hybrid_client_id, { "Client ID", "isi.location.hybrid.client_id", FT_UINT32, BASE_HEX, NULL, 0x0, "Client ID", HFILL }}, { &hf_isi_location_hybrid_npe_id, { "NPE ID", "isi.location.hybrid.npe_id", FT_UINT32, BASE_HEX, NULL, 0x0, "NPE ID", HFILL }}, { &hf_isi_location_cause, { "Cause", "isi.location.hybrid.cause", FT_UINT8, BASE_HEX, isi_location_hybrid_cause, 0x0, "Cause", HFILL }}, { &hf_isi_location_status, { "Status", "isi.location.status", FT_UINT8, BASE_HEX, NULL, 0x0, "Status", HFILL }}, { &hf_isi_location_status_ok, { "OK", "isi.location.status.ok", FT_BOOLEAN, BASE_NONE, NULL, 0x01, "OK", HFILL }}, { &hf_isi_location_status_complete, { "Complete", "isi.location.status.complete", FT_BOOLEAN, BASE_NONE, NULL, 0x20, "Complete", HFILL }}, { &hf_isi_location_status_fix, { "Fix", "isi.location.status.fix", FT_BOOLEAN, BASE_NONE, NULL, 0x40, "Fix", HFILL }}, { &hf_isi_location_status_meas_fix, { "Measure Fix", "isi.location.status.meas_fix", FT_BOOLEAN, BASE_NONE, NULL, 0x80, "Measure Fix", HFILL }}, { &hf_isi_location_socket_descriptor, { "Descriptor", "isi.location.socket.status", FT_UINT8, BASE_HEX, NULL, 0x0, "Descriptor", HFILL }}, { &hf_isi_location_socket_status, { "Status", "isi.location.socket.status", FT_UINT8, BASE_HEX, isi_location_socket_status, 0x0, "Status", HFILL }}, { &hf_isi_location_socket_error, { "Error Number", "isi.location.socket.error", FT_UINT16, BASE_HEX, NULL, 0x0, "Error Number", HFILL }}, { &hf_isi_location_data_len, { "Data Length", "isi.location.data.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Data Length", HFILL }}, { &hf_isi_location_data, { "Data", "isi.location.data", FT_BYTES, BASE_NONE, NULL, 0x0, "Data Length", HFILL }} }; static gint *ett[] = { &ett_flags_status, &ett_flags_methods, &ett_flags_options }; proto_register_field_array(proto_isi, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); register_dissector("isi.location", dissect_isi_location, proto_isi); } static size_t dissect_isi_location_subpkg(tvbuff_t *tvb, packet_info *pinfo, proto_item *item, proto_tree *tree, size_t offset) { guint16 sptype = tvb_get_ntohs(tvb, offset+0); guint16 splen = tvb_get_ntohs(tvb, offset+2); proto_item *subitem; proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, offset, splen, ett_isi_msg, &subitem, "Subpacket (%s)", val_to_str(sptype, isi_location_sub_id, "unknown: 0x%x")); proto_tree_add_item(subtree, hf_isi_location_sub_type, tvb, offset+0, 2, FALSE); proto_tree_add_item(subtree, hf_isi_location_sub_len, tvb, offset+2, 2, FALSE); offset += 4; switch(sptype) { case 0x1200: ; /* LS_SB_SOCKET_ADDR */ proto_tree_add_item(subtree, hf_isi_location_socket_addr_port, tvb, offset+0, 2, FALSE); proto_tree_add_item(subtree, hf_isi_location_socket_addr_type, tvb, offset+2, 1, FALSE); proto_tree_add_item(subtree, hf_isi_location_socket_addr_ip_len, tvb, offset+3, 1, FALSE); proto_tree_add_item(subtree, hf_isi_location_socket_addr_fqdn_len, tvb, offset+4, 1, FALSE); guint8 type = tvb_get_guint8(tvb, offset+2); guint8 ip_len = tvb_get_guint8(tvb, offset+3); guint8 fqdn_len = tvb_get_guint8(tvb, offset+4); if(type == 0x00 && ip_len >= FT_IPv4_LEN) proto_tree_add_item(subtree, hf_isi_location_socket_addr_ipv4, tvb, offset+8, ip_len, FALSE); if(type == 0x01 && ip_len >= FT_IPv6_LEN) proto_tree_add_item(subtree, hf_isi_location_socket_addr_ipv6, tvb, offset+8, ip_len, FALSE); if(type == 0x02) proto_tree_add_item(subtree, hf_isi_location_socket_addr_fqdn, tvb, offset+8+ip_len, fqdn_len, FALSE); break; case 0x1202: ; /* LS_SB_SOCKET_BEARER_TYPE */ proto_tree_add_item(subtree, hf_isi_location_socket_bearer, tvb, offset+0, 1, FALSE); break; case 0x0901: ; /* LS_SB_HYBRID_TRACKING_INSTR */ proto_tree_add_bitmask(subtree, tvb, offset+0, hf_isi_location_hybrid_allowed_methods, ett_flags_methods, isi_location_hybrid_method_flags, ENC_BIG_ENDIAN); proto_tree_add_bitmask(subtree, tvb, offset+4, hf_isi_location_hybrid_options, ett_flags_options, isi_location_hybrid_option_flags, ENC_BIG_ENDIAN); guint16 time_raw = tvb_get_ntohs(tvb, offset+8); nstime_t time_conv; time_conv.nsecs = (time_raw % 10) * 100000; time_conv.secs = time_raw / 10; proto_tree_add_time(subtree, hf_isi_location_hybrid_interval, tvb, offset+8, 2, &time_conv); proto_tree_add_item(subtree, hf_isi_location_hybrid_report_criteria, tvb, offset+10, 1, FALSE); proto_tree_add_item(subtree, hf_isi_location_hybrid_acwp_timer, tvb, offset+11, 1, FALSE); break; case 0x0902: ; /* LS_SB_NPE_POSITION */ double lat = tvb_get_ntohl(tvb, offset+0); lat = (lat*360)/4294967296; if(lat > 180.0) lat -= 360.0; proto_tree_add_double(subtree, hf_isi_location_latitude, tvb, offset+0, 4, lat); double lon = tvb_get_ntohl(tvb, offset+4); lon = (lon*360)/4294967296; if(lon > 180.0) lon -= 360.0; proto_tree_add_double(subtree, hf_isi_location_longitude, tvb, offset+4, 4, lon); float eph = tvb_get_ntohl(tvb, offset+12) / 100.0; proto_tree_add_float(subtree, hf_isi_location_eph, tvb, offset+12, 4, eph); gint32 altitude = (tvb_get_ntohs(tvb, offset+18) - tvb_get_ntohs(tvb, offset+22))/2; proto_tree_add_int(subtree, hf_isi_location_altitude, tvb, offset+18, 6, altitude); float epv = tvb_get_ntohs(tvb, offset+20) / 2; proto_tree_add_float(subtree, hf_isi_location_epv, tvb, offset+20, 2, epv); break; case 0x0903: ; /* LS_SB_NPE_TIME */ proto_tree_add_item(subtree, hf_isi_location_year, tvb, offset+0, 2, FALSE); proto_tree_add_item(subtree, hf_isi_location_month, tvb, offset+2, 1, FALSE); proto_tree_add_item(subtree, hf_isi_location_day, tvb, offset+3, 1, FALSE); proto_tree_add_item(subtree, hf_isi_location_hour, tvb, offset+5, 1, FALSE); proto_tree_add_item(subtree, hf_isi_location_minute, tvb, offset+6, 1, FALSE); float second = tvb_get_ntohs(tvb, offset+8) / 1000.0; proto_tree_add_float(subtree, hf_isi_location_second, tvb, offset+8, 2, second); break; case 0x0904: ; /* LS_SB_NPE_VELOCITY */ float course = tvb_get_ntohs(tvb, offset+0) / 100.0; proto_tree_add_float(subtree, hf_isi_location_course, tvb, offset+0, 2, course); float epd = tvb_get_ntohs(tvb, offset+2) / 100.0; proto_tree_add_float(subtree, hf_isi_location_epd, tvb, offset+2, 2, epd); float speed = tvb_get_ntohs(tvb, offset+6) * CMS_TO_KMH; proto_tree_add_float(subtree, hf_isi_location_speed, tvb, offset+6, 2, speed); float eps = tvb_get_ntohs(tvb, offset+8) * CMS_TO_KMH; proto_tree_add_float(subtree, hf_isi_location_eps, tvb, offset+8, 2, eps); float climb = tvb_get_ntohs(tvb, offset+10) * CMS_TO_KMH; proto_tree_add_float(subtree, hf_isi_location_climb, tvb, offset+10, 2, climb); float epc = tvb_get_ntohs(tvb, offset+12) * CMS_TO_KMH; proto_tree_add_float(subtree, hf_isi_location_epc, tvb, offset+12, 2, epc); break; case 0x0905: ; /* LS_SB_NPE_CHANNELS */ guint8 satellites = tvb_get_guint8(tvb, offset+0); proto_tree_add_item(subtree, hf_isi_location_satellites, tvb, offset+0, 1, FALSE); int sat; for(sat = 0; sat < satellites ; sat++) { int pos = offset+4+(sat*SAT_PKG_LEN); proto_tree *sattree = proto_tree_add_subtree_format(subtree, tvb, offset, splen, ett_isi_msg, NULL, "Satellite %d", sat); float signal_strength = tvb_get_ntohs(tvb, pos+3) / 100.0; float elevation = tvb_get_ntohs(tvb, pos+6) / 100.0; float azimuth = tvb_get_ntohs(tvb, pos+8) / 100.0; proto_tree_add_item(sattree, hf_isi_location_prn, tvb, pos+1, 1, FALSE); proto_tree_add_item(sattree, hf_isi_location_sat_used, tvb, pos+2, 1, FALSE); proto_tree_add_float(sattree, hf_isi_location_sat_strength, tvb, pos+3, 2, signal_strength); proto_tree_add_float(sattree, hf_isi_location_sat_elevation, tvb, pos+6, 2, elevation); proto_tree_add_float(sattree, hf_isi_location_sat_azimuth, tvb, pos+8, 2, azimuth); } break; case 0x0907: /* LS_SB_CELL_INFO_GSM */ proto_tree_add_item(subtree, hf_isi_location_mcc, tvb, offset+0, 2, FALSE); proto_tree_add_item(subtree, hf_isi_location_mnc, tvb, offset+2, 2, FALSE); proto_tree_add_item(subtree, hf_isi_location_lac, tvb, offset+4, 2, FALSE); proto_tree_add_item(subtree, hf_isi_location_cid, tvb, offset+6, 2, FALSE); break; case 0x0908: /* LS_SB_CELL_INFO_WCDMA */ proto_tree_add_item(subtree, hf_isi_location_mcc, tvb, offset+0, 2, FALSE); proto_tree_add_item(subtree, hf_isi_location_mnc, tvb, offset+2, 2, FALSE); proto_tree_add_item(subtree, hf_isi_location_ucid, tvb, offset+4, 4, FALSE); break; default: expert_add_info_format(pinfo, subitem, &ei_isi_unsupported_packet, "unsupported sub-packet"); break; } return splen; } static void dissect_isi_location(tvbuff_t *tvb, packet_info *pinfo, proto_item *isitree) { proto_item *item = NULL; proto_tree *tree = NULL; guint8 cmd, pkgcount; guint16 data_len; size_t offset; int i; if(isitree) { tree = proto_tree_add_subtree_format(isitree, tvb, 0, -1, ett_isi_msg, &item, "Payload"); proto_tree_add_item(tree, hf_isi_location_cmd, tvb, 0, 1, FALSE); cmd = tvb_get_guint8(tvb, 0); switch(cmd) { case 0x7D: /* LS_GPS_STATUS_IND */ proto_tree_add_item(tree, hf_isi_location_gps_power, tvb, 1, 1, FALSE); proto_tree_add_item(tree, hf_isi_location_gps_status, tvb, 2, 1, FALSE); guint8 status = tvb_get_guint8(tvb, 2); col_add_fstr(pinfo->cinfo, COL_INFO, "GPS Status Indication: %s", val_to_str(status, isi_location_gps_status, "unknown (0x%x)")); break; case 0x84: /* LS_SOCKET_OPEN_REQUEST_NTF */ col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Open Request"); pkgcount = tvb_get_guint8(tvb, 1); proto_tree_add_item(tree, hf_isi_location_sub_pkgs, tvb, 1, 1, FALSE); offset = 0x03; for(i=0; icinfo, COL_INFO, "Socket Open Response"); proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE); proto_tree_add_item(tree, hf_isi_location_socket_status, tvb, 2, 1, FALSE); pkgcount = tvb_get_guint8(tvb, 3); proto_tree_add_item(tree, hf_isi_location_sub_pkgs, tvb, 3, 1, FALSE); offset = 0x07; for(i=0; icinfo, COL_INFO, "Socket Send Request"); proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE); proto_tree_add_item(tree, hf_isi_location_data_len, tvb, 3, 2, FALSE); data_len = tvb_get_ntohs(tvb, 3); if(supl_handle == NULL) { proto_tree_add_item(tree, hf_isi_location_data, tvb, 7, data_len, FALSE); } else { tvbuff_t *data_tvb = tvb_new_subset(tvb, 7, data_len, data_len); call_dissector(supl_handle, data_tvb, pinfo, tree); } break; case 0x87: /* LS_SOCKET_SEND_RESPONSE_NTF */ col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Send Response"); proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE); proto_tree_add_item(tree, hf_isi_location_socket_status, tvb, 2, 1, FALSE); proto_tree_add_item(tree, hf_isi_location_socket_error, tvb, 3, 2, FALSE); break; case 0x88: /* LS_SOCKET_RECV_REQ */ col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Receive Request"); proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE); proto_tree_add_item(tree, hf_isi_location_data_len, tvb, 3, 2, FALSE); data_len = tvb_get_ntohs(tvb, 3); if(supl_handle == NULL) { proto_tree_add_item(tree, hf_isi_location_data, tvb, 7, data_len, FALSE); } else { tvbuff_t *data_tvb = tvb_new_subset(tvb, 7, data_len, data_len); call_dissector(supl_handle, data_tvb, pinfo, tree); } break; case 0x89: /* LS_SOCKET_RECV_RESP */ col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Receive Response"); proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE); break; case 0x8a: /* LS_SOCKET_CLOSE_REQUEST_NTF */ col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Close Request"); proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE); break; case 0x8b: /* LS_SOCKET_CLOSE_RESPONSE_NTF */ col_add_fstr(pinfo->cinfo, COL_INFO, "Socket Close Response"); proto_tree_add_item(tree, hf_isi_location_socket_descriptor, tvb, 1, 1, FALSE); proto_tree_add_item(tree, hf_isi_location_socket_status, tvb, 2, 1, FALSE); break; case 0x90: /* LS_HYBRID_TRACKING_REQ */ col_set_str(pinfo->cinfo, COL_INFO, "Hybrid Tracking Request"); proto_tree_add_item(tree, hf_isi_location_hybrid_cmd, tvb, 1, 1, FALSE); proto_tree_add_item(tree, hf_isi_location_sub_pkgs, tvb, 2, 1, FALSE); pkgcount = tvb_get_guint8(tvb, 2); proto_tree_add_item(tree, hf_isi_location_hybrid_client_id, tvb, 3, 4, FALSE); proto_tree_add_item(tree, hf_isi_location_hybrid_npe_id, tvb, 7, 4, FALSE); offset = 0x0b; for(i=0; icinfo, COL_INFO, "Hybrid Tracking Response"); proto_tree_add_bitmask(tree, tvb, 1, hf_isi_location_status, ett_flags_status, isi_location_hybrid_status_flags, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_isi_location_cause, tvb, 2, 1, FALSE); proto_tree_add_item(tree, hf_isi_location_hybrid_client_id, tvb, 3, 4, FALSE); proto_tree_add_item(tree, hf_isi_location_hybrid_npe_id, tvb, 7, 4, FALSE); break; case 0x92: /* LS_HYBRID_TRACKING_NTF */ col_set_str(pinfo->cinfo, COL_INFO, "Hybrid Tracking Notification"); pkgcount = tvb_get_guint8(tvb, 0x07); proto_tree_add_item(tree, hf_isi_location_sub_pkgs, tvb, 0x07, 1, FALSE); offset = 0x0b; for(i=0; i