summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-doip.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-doip.c')
-rw-r--r--epan/dissectors/packet-doip.c1350
1 files changed, 1350 insertions, 0 deletions
diff --git a/epan/dissectors/packet-doip.c b/epan/dissectors/packet-doip.c
new file mode 100644
index 00000000..76674c1f
--- /dev/null
+++ b/epan/dissectors/packet-doip.c
@@ -0,0 +1,1350 @@
+/* packet-doip.c
+ * Routines for DoIP (ISO13400) protocol packet disassembly
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include <epan/packet.h>
+#include <epan/uat.h>
+#include <epan/expert.h>
+
+#include "packet-tcp.h"
+#include "packet-tls.h"
+#include "packet-doip.h"
+
+void proto_register_doip(void);
+void proto_reg_handoff_doip(void);
+
+
+#define DOIP_PORT 13400
+#define DOIP_TLS_PORT 3496
+
+#define DOIP_GENERIC_NACK 0x0000
+#define DOIP_VEHICLE_IDENTIFICATION_REQ 0x0001
+#define DOIP_VEHICLE_IDENTIFICATION_REQ_EID 0x0002
+#define DOIP_VEHICLE_IDENTIFICATION_REQ_VIN 0x0003
+#define DOIP_VEHICLE_ANNOUNCEMENT_MESSAGE 0x0004
+#define DOIP_ROUTING_ACTIVATION_REQUEST 0x0005
+#define DOIP_ROUTING_ACTIVATION_RESPONSE 0x0006
+#define DOIP_ALIVE_CHECK_REQUEST 0x0007
+#define DOIP_ALIVE_CHECK_RESPONSE 0x0008
+#define DOIP_ENTITY_STATUS_REQUEST 0x4001
+#define DOIP_ENTITY_STATUS_RESPONSE 0x4002
+#define DOIP_POWER_INFORMATION_REQUEST 0x4003
+#define DOIP_POWER_INFORMATION_RESPONSE 0x4004
+#define DOIP_DIAGNOSTIC_MESSAGE 0x8001
+#define DOIP_DIAGNOSTIC_MESSAGE_ACK 0x8002
+#define DOIP_DIAGNOSTIC_MESSAGE_NACK 0x8003
+
+
+/* Header */
+#define DOIP_VERSION_OFFSET 0
+#define DOIP_VERSION_LEN 1
+#define DOIP_INV_VERSION_OFFSET (DOIP_VERSION_OFFSET + DOIP_VERSION_LEN)
+#define DOIP_INV_VERSION_LEN 1
+#define DOIP_TYPE_OFFSET (DOIP_INV_VERSION_OFFSET + DOIP_INV_VERSION_LEN)
+#define DOIP_TYPE_LEN 2
+#define DOIP_LENGTH_OFFSET (DOIP_TYPE_OFFSET + DOIP_TYPE_LEN)
+#define DOIP_LENGTH_LEN 4
+#define DOIP_HEADER_LEN (DOIP_LENGTH_OFFSET + DOIP_LENGTH_LEN)
+
+#define RESERVED_VER 0x00
+#define ISO13400_2010 0x01
+#define ISO13400_2012 0x02
+#define ISO13400_2019 0x03
+#define ISO13400_2019_AMD1 0x04
+#define DEFAULT_VALUE 0xFF
+
+
+/* Generic NACK */
+#define DOIP_GENERIC_NACK_OFFSET DOIP_HEADER_LEN
+#define DOIP_GENERIC_NACK_LEN 1
+
+
+/* Common */
+#define DOIP_COMMON_VIN_LEN 17
+#define DOIP_COMMON_EID_LEN 6
+
+
+/* Vehicle identifcation request */
+#define DOIP_VEHICLE_IDENTIFICATION_EID_OFFSET DOIP_HEADER_LEN
+#define DOIP_VEHICLE_IDENTIFICATION_VIN_OFFSET DOIP_HEADER_LEN
+
+
+/* Routing activation request */
+#define DOIP_ROUTING_ACTIVATION_REQ_SRC_OFFSET DOIP_HEADER_LEN
+#define DOIP_ROUTING_ACTIVATION_REQ_SRC_LEN 2
+#define DOIP_ROUTING_ACTIVATION_REQ_TYPE_OFFSET (DOIP_ROUTING_ACTIVATION_REQ_SRC_OFFSET + DOIP_ROUTING_ACTIVATION_REQ_SRC_LEN)
+#define DOIP_ROUTING_ACTIVATION_REQ_TYPE_LEN_V1 2
+#define DOIP_ROUTING_ACTIVATION_REQ_TYPE_LEN_V2 1
+#define DOIP_ROUTING_ACTIVATION_REQ_ISO_OFFSET_V1 (DOIP_ROUTING_ACTIVATION_REQ_TYPE_OFFSET + DOIP_ROUTING_ACTIVATION_REQ_TYPE_LEN_V1)
+#define DOIP_ROUTING_ACTIVATION_REQ_ISO_OFFSET_V2 (DOIP_ROUTING_ACTIVATION_REQ_TYPE_OFFSET + DOIP_ROUTING_ACTIVATION_REQ_TYPE_LEN_V2)
+#define DOIP_ROUTING_ACTIVATION_REQ_ISO_LEN 4
+#define DOIP_ROUTING_ACTIVATION_REQ_OEM_OFFSET_V1 (DOIP_ROUTING_ACTIVATION_REQ_ISO_OFFSET_V1 + DOIP_ROUTING_ACTIVATION_REQ_ISO_LEN)
+#define DOIP_ROUTING_ACTIVATION_REQ_OEM_OFFSET_V2 (DOIP_ROUTING_ACTIVATION_REQ_ISO_OFFSET_V2 + DOIP_ROUTING_ACTIVATION_REQ_ISO_LEN)
+#define DOIP_ROUTING_ACTIVATION_REQ_OEM_LEN 4
+
+
+/* Routing activation response */
+#define DOIP_ROUTING_ACTIVATION_RES_TESTER_OFFSET DOIP_HEADER_LEN
+#define DOIP_ROUTING_ACTIVATION_RES_TESTER_LEN 2
+#define DOIP_ROUTING_ACTIVATION_RES_ENTITY_OFFSET (DOIP_ROUTING_ACTIVATION_RES_TESTER_OFFSET + DOIP_ROUTING_ACTIVATION_RES_TESTER_LEN)
+#define DOIP_ROUTING_ACTIVATION_RES_ENTITY_LEN 2
+#define DOIP_ROUTING_ACTIVATION_RES_CODE_OFFSET (DOIP_ROUTING_ACTIVATION_RES_ENTITY_OFFSET + DOIP_ROUTING_ACTIVATION_RES_ENTITY_LEN)
+#define DOIP_ROUTING_ACTIVATION_RES_CODE_LEN 1
+#define DOIP_ROUTING_ACTIVATION_RES_ISO_OFFSET (DOIP_ROUTING_ACTIVATION_RES_CODE_OFFSET + DOIP_ROUTING_ACTIVATION_RES_CODE_LEN)
+#define DOIP_ROUTING_ACTIVATION_RES_ISO_LEN 4
+#define DOIP_ROUTING_ACTIVATION_RES_OEM_OFFSET (DOIP_ROUTING_ACTIVATION_RES_ISO_OFFSET + DOIP_ROUTING_ACTIVATION_RES_ISO_LEN)
+#define DOIP_ROUTING_ACTIVATION_RES_OEM_LEN 4
+
+
+/* Vehicle announcement message */
+#define DOIP_VEHICLE_ANNOUNCEMENT_VIN_OFFSET DOIP_HEADER_LEN
+#define DOIP_VEHICLE_ANNOUNCEMENT_ADDRESS_OFFSET (DOIP_VEHICLE_ANNOUNCEMENT_VIN_OFFSET + DOIP_COMMON_VIN_LEN)
+#define DOIP_VEHICLE_ANNOUNCEMENT_ADDRESS_LEN 2
+#define DOIP_VEHICLE_ANNOUNCEMENT_EID_OFFSET (DOIP_VEHICLE_ANNOUNCEMENT_ADDRESS_OFFSET + DOIP_VEHICLE_ANNOUNCEMENT_ADDRESS_LEN)
+#define DOIP_VEHICLE_ANNOUNCEMENT_GID_OFFSET (DOIP_VEHICLE_ANNOUNCEMENT_EID_OFFSET + DOIP_COMMON_EID_LEN)
+#define DOIP_VEHICLE_ANNOUNCEMENT_GID_LEN 6
+#define DOIP_VEHICLE_ANNOUNCEMENT_ACTION_OFFSET (DOIP_VEHICLE_ANNOUNCEMENT_GID_OFFSET + DOIP_VEHICLE_ANNOUNCEMENT_GID_LEN)
+#define DOIP_VEHICLE_ANNOUNCEMENT_ACTION_LEN 1
+#define DOIP_VEHICLE_ANNOUNCEMENT_SYNC_OFFSET (DOIP_VEHICLE_ANNOUNCEMENT_ACTION_OFFSET + DOIP_VEHICLE_ANNOUNCEMENT_ACTION_LEN)
+#define DOIP_VEHICLE_ANNOUNCEMENT_SYNC_LEN 1
+
+
+/* Alive check response */
+#define DOIP_ALIVE_CHECK_RESPONSE_SOURCE_OFFSET DOIP_HEADER_LEN
+#define DOIP_ALIVE_CHECK_RESPONSE_SOURCE_LEN 2
+
+
+/* Entity status response */
+#define DOIP_ENTITY_STATUS_RESPONSE_NODE_OFFSET DOIP_HEADER_LEN
+#define DOIP_ENTITY_STATUS_RESPONSE_NODE_LEN 1
+#define DOIP_ENTITY_STATUS_RESPONSE_MCTS_OFFSET (DOIP_ENTITY_STATUS_RESPONSE_NODE_OFFSET + DOIP_ENTITY_STATUS_RESPONSE_NODE_LEN)
+#define DOIP_ENTITY_STATUS_RESPONSE_MCTS_LEN 1
+#define DOIP_ENTITY_STATUS_RESPONSE_NCTS_OFFSET (DOIP_ENTITY_STATUS_RESPONSE_MCTS_OFFSET + DOIP_ENTITY_STATUS_RESPONSE_MCTS_LEN)
+#define DOIP_ENTITY_STATUS_RESPONSE_NCTS_LEN 1
+#define DOIP_ENTITY_STATUS_RESPONSE_MDS_OFFSET (DOIP_ENTITY_STATUS_RESPONSE_NCTS_OFFSET + DOIP_ENTITY_STATUS_RESPONSE_NCTS_LEN)
+#define DOIP_ENTITY_STATUS_RESPONSE_MDS_LEN 4
+
+
+/* Diagnostic power mode information response */
+#define DOIP_POWER_MODE_OFFSET DOIP_HEADER_LEN
+#define DOIP_POWER_MODE_LEN 1
+
+
+/* Common */
+#define DOIP_DIAG_COMMON_SOURCE_OFFSET DOIP_HEADER_LEN
+#define DOIP_DIAG_COMMON_SOURCE_LEN 2
+#define DOIP_DIAG_COMMON_TARGET_OFFSET (DOIP_DIAG_COMMON_SOURCE_OFFSET + DOIP_DIAG_COMMON_SOURCE_LEN)
+#define DOIP_DIAG_COMMON_TARGET_LEN 2
+
+
+/* Diagnostic message */
+#define DOIP_DIAG_MESSAGE_DATA_OFFSET (DOIP_DIAG_COMMON_TARGET_OFFSET + DOIP_DIAG_COMMON_TARGET_LEN)
+
+
+/* Diagnostic message ACK */
+#define DOIP_DIAG_MESSAGE_ACK_CODE_OFFSET (DOIP_DIAG_COMMON_TARGET_OFFSET + DOIP_DIAG_COMMON_TARGET_LEN)
+#define DOIP_DIAG_MESSAGE_ACK_CODE_LEN 1
+#define DOIP_DIAG_MESSAGE_ACK_PREVIOUS_OFFSET (DOIP_DIAG_MESSAGE_ACK_CODE_OFFSET + DOIP_DIAG_MESSAGE_ACK_CODE_LEN)
+
+
+/* Diagnostic message NACK */
+#define DOIP_DIAG_MESSAGE_NACK_CODE_OFFSET (DOIP_DIAG_COMMON_TARGET_OFFSET + DOIP_DIAG_COMMON_TARGET_LEN)
+#define DOIP_DIAG_MESSAGE_NACK_CODE_LEN 1
+#define DOIP_DIAG_MESSAGE_NACK_PREVIOUS_OFFSET (DOIP_DIAG_MESSAGE_NACK_CODE_OFFSET + DOIP_DIAG_MESSAGE_NACK_CODE_LEN)
+
+
+
+/*
+ * Enums
+ */
+
+/* Header */
+/* Protocol version */
+static const value_string doip_versions[] = {
+ { RESERVED_VER, "Reserved" },
+ { ISO13400_2010, "DoIP ISO/DIS 13400-2:2010" },
+ { ISO13400_2012, "DoIP ISO 13400-2:2012" },
+ { ISO13400_2019, "DoIP ISO 13400-2:2019" },
+ { ISO13400_2019_AMD1, "DoIP ISO 13400-2:2019 Amd1 (experimental)" },
+ { DEFAULT_VALUE, "Default value for vehicle identification request messages" },
+ { 0, NULL }
+};
+
+/* Payload type */
+static const value_string doip_payloads[] = {
+ { DOIP_GENERIC_NACK, "Generic DoIP header NACK" },
+ { DOIP_VEHICLE_IDENTIFICATION_REQ, "Vehicle identification request" },
+ { DOIP_VEHICLE_IDENTIFICATION_REQ_EID, "Vehicle identification request with EID" },
+ { DOIP_VEHICLE_IDENTIFICATION_REQ_VIN, "Vehicle identification request with VIN" },
+ { DOIP_VEHICLE_ANNOUNCEMENT_MESSAGE, "Vehicle announcement message/vehicle identification response message" },
+ { DOIP_ROUTING_ACTIVATION_REQUEST, "Routing activation request" },
+ { DOIP_ROUTING_ACTIVATION_RESPONSE, "Routing activation response" },
+ { DOIP_ALIVE_CHECK_REQUEST, "Alive check request" },
+ { DOIP_ALIVE_CHECK_RESPONSE, "Alive check response" },
+ { DOIP_ENTITY_STATUS_REQUEST, "DoIP entity status request" },
+ { DOIP_ENTITY_STATUS_RESPONSE, "DoIP entity status response" },
+ { DOIP_POWER_INFORMATION_REQUEST, "Diagnostic power mode information request" },
+ { DOIP_POWER_INFORMATION_RESPONSE, "Diagnostic power mode information response" },
+ { DOIP_DIAGNOSTIC_MESSAGE, "Diagnostic message" },
+ { DOIP_DIAGNOSTIC_MESSAGE_ACK, "Diagnostic message ACK" },
+ { DOIP_DIAGNOSTIC_MESSAGE_NACK, "Diagnostic message NACK" },
+ { 0, NULL }
+};
+
+
+/* Generic NACK */
+static const value_string nack_codes[] = {
+ { 0x00, "Incorrect pattern format" },
+ { 0x01, "Unknown payload type" },
+ { 0x02, "Message too large" },
+ { 0x03, "Out of memory" },
+ { 0x04, "Invalid payload length" },
+ { 0, NULL }
+};
+
+
+/* Routing activation request */
+static const value_string activation_types[] = {
+ { 0x00, "Default" },
+ { 0x01, "WWH-OBD" },
+ { 0xE0, "Central security" },
+ { 0, NULL }
+};
+
+
+/* Routing activation response */
+static const value_string activation_codes[] = {
+ { 0x00, "Routing activation denied due to unknown source address." },
+ { 0x01, "Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active." },
+ { 0x02, "Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket." },
+ { 0x03, "Routing activation denied because the SA is already registered and active on a different TCP_DATA socket." },
+ { 0x04, "Routing activation denied due to missing authentication." },
+ { 0x05, "Routing activation denied due to rejected confirmation." },
+ { 0x06, "Routing activation denied due to unsupported routing activation type." },
+ { 0x07, "Routing activation denied due to request for encrypted connection via TLS." },
+ { 0x08, "Reserved by ISO 13400." },
+ { 0x09, "Reserved by ISO 13400." },
+ { 0x0A, "Reserved by ISO 13400." },
+ { 0x0B, "Reserved by ISO 13400." },
+ { 0x0C, "Reserved by ISO 13400." },
+ { 0x0D, "Reserved by ISO 13400." },
+ { 0x0E, "Reserved by ISO 13400." },
+ { 0x0F, "Reserved by ISO 13400." },
+ { 0x10, "Routing successfully activated." },
+ { 0x11, "Routing will be activated; confirmation required." },
+ { 0, NULL }
+};
+
+
+/* Vehicle announcement message */
+/* Action code */
+static const value_string action_codes[] = {
+ { 0x00, "No further action required" },
+ { 0x01, "Reserved by ISO 13400" },
+ { 0x02, "Reserved by ISO 13400" },
+ { 0x03, "Reserved by ISO 13400" },
+ { 0x04, "Reserved by ISO 13400" },
+ { 0x05, "Reserved by ISO 13400" },
+ { 0x06, "Reserved by ISO 13400" },
+ { 0x07, "Reserved by ISO 13400" },
+ { 0x08, "Reserved by ISO 13400" },
+ { 0x09, "Reserved by ISO 13400" },
+ { 0x0A, "Reserved by ISO 13400" },
+ { 0x0B, "Reserved by ISO 13400" },
+ { 0x0C, "Reserved by ISO 13400" },
+ { 0x0D, "Reserved by ISO 13400" },
+ { 0x0E, "Reserved by ISO 13400" },
+ { 0x0F, "Reserved by ISO 13400" },
+ { 0x10, "Routing activation required to initiate central security" },
+ { 0, NULL }
+};
+
+/* Sync status */
+static const value_string sync_status[] = {
+ { 0x00, "VIN and/or GID are synchronized" },
+ { 0x01, "Reserved by ISO 13400" },
+ { 0x02, "Reserved by ISO 13400" },
+ { 0x03, "Reserved by ISO 13400" },
+ { 0x04, "Reserved by ISO 13400" },
+ { 0x05, "Reserved by ISO 13400" },
+ { 0x06, "Reserved by ISO 13400" },
+ { 0x07, "Reserved by ISO 13400" },
+ { 0x08, "Reserved by ISO 13400" },
+ { 0x09, "Reserved by ISO 13400" },
+ { 0x0A, "Reserved by ISO 13400" },
+ { 0x0B, "Reserved by ISO 13400" },
+ { 0x0C, "Reserved by ISO 13400" },
+ { 0x0D, "Reserved by ISO 13400" },
+ { 0x0E, "Reserved by ISO 13400" },
+ { 0x0F, "Reserved by ISO 13400" },
+ { 0x10, "Incomplete: VIN and GID are NOT synchronized" },
+ { 0, NULL }
+};
+
+/* Entity status response */
+/* Node type */
+static const value_string node_types[] = {
+ { 0x00, "DoIP gateway" },
+ { 0x01, "DoIp node" },
+ { 0, NULL }
+};
+
+
+/* Diagnostic power mode information response */
+/* Power mode */
+static const value_string power_modes[] = {
+ { 0x00, "not ready" },
+ { 0x01, "ready" },
+ { 0x02, "not supported" },
+ { 0, NULL }
+};
+
+
+/* Diagnostic message ACK */
+static const value_string diag_ack_codes[] = {
+ { 0x00, "ACK" },
+ { 0, NULL }
+};
+
+
+/* Diagnostic message NACK */
+static const value_string diag_nack_codes[] = {
+ { 0x00, "Reserved by ISO 13400" },
+ { 0x01, "Reserved by ISO 13400" },
+ { 0x02, "Invalid source address" },
+ { 0x03, "Unknown target address" },
+ { 0x04, "Diagnostic message too large" },
+ { 0x05, "Out of memory" },
+ { 0x06, "Target unreachable" },
+ { 0x07, "Unknown network" },
+ { 0x08, "Transport protocol error" },
+ { 0, NULL }
+};
+
+
+
+/*
+ * Config
+ */
+
+static gboolean doip_hide_address_names = TRUE;
+
+ /*
+ * Fields
+ */
+
+/* DoIP header */
+static int hf_doip_version = -1;
+static int hf_doip_inv_version = -1;
+static int hf_doip_type = -1;
+static int hf_doip_length = -1;
+
+
+/* Generic NACK */
+static int hf_generic_nack_code = -1;
+
+
+/* Common */
+static int hf_reserved_iso = -1;
+static int hf_reserved_oem = -1;
+
+
+/* Routing activation request */
+static int hf_activation_type_v1 = -1;
+static int hf_activation_type_v2 = -1;
+
+
+/* Routing activation response */
+static int hf_tester_logical_address = -1;
+static int hf_tester_logical_address_name = -1;
+static int hf_response_code = -1;
+
+
+/* Vehicle announcement message */
+static int hf_logical_address = -1;
+static int hf_logical_address_name = -1;
+static int hf_gid = -1;
+static int hf_futher_action = -1;
+static int hf_sync_status = -1;
+
+
+/* Diagnostic power mode information response */
+static int hf_power_mode = -1;
+
+
+/* Entity status response */
+static int hf_node_type = -1;
+static int hf_max_sockets = -1;
+static int hf_current_sockets = -1;
+static int hf_max_data_size = -1;
+
+
+/* Common */
+static int hf_vin = -1;
+static int hf_eid = -1;
+static int hf_source_address = -1;
+static int hf_source_address_name = -1;
+static int hf_target_address = -1;
+static int hf_target_address_name = -1;
+static int hf_previous = -1;
+
+
+/* Diagnostic message */
+static int hf_data = -1;
+
+
+/* Diagnostic message ACK */
+static int hf_ack_code = -1;
+
+
+/* Diagnostic message NACK */
+static int hf_nack_code = -1;
+
+
+
+/*
+ * Trees
+ */
+static gint ett_doip = -1;
+static gint ett_header = -1;
+static gint ett_address = -1;
+
+
+/* Misc */
+static dissector_handle_t doip_handle;
+static dissector_handle_t uds_handle;
+static gint proto_doip = -1;
+
+
+/* expert info items */
+static expert_field ef_doip_illegal_length_field = EI_INIT;
+
+
+/*
+ * UATs
+ */
+
+typedef struct _generic_one_id_string {
+ guint id;
+ gchar *name;
+} generic_one_id_string_t;
+
+static void
+doip_uat_free_key(gpointer key) {
+ wmem_free(wmem_epan_scope(), key);
+}
+
+static void
+simple_free(gpointer data) {
+ /* we need to free because of the g_strdup in post_update*/
+ g_free(data);
+}
+
+/* ID -> Name */
+static void *
+copy_generic_one_id_string_cb(void* n, const void* o, size_t size _U_) {
+ generic_one_id_string_t* new_rec = (generic_one_id_string_t*)n;
+ const generic_one_id_string_t* old_rec = (const generic_one_id_string_t*)o;
+
+ new_rec->name = g_strdup(old_rec->name);
+ new_rec->id = old_rec->id;
+ return new_rec;
+}
+
+static bool
+update_generic_one_identifier_16bit(void *r, char **err) {
+ generic_one_id_string_t *rec = (generic_one_id_string_t *)r;
+
+ if (rec->id > 0xffff) {
+ *err = ws_strdup_printf("We currently only support 16 bit identifiers (ID: %i Name: %s)", rec->id, rec->name);
+ return FALSE;
+ }
+
+ if (rec->name == NULL || rec->name[0] == 0) {
+ *err = g_strdup("Name cannot be empty");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+free_generic_one_id_string_cb(void*r) {
+ generic_one_id_string_t* rec = (generic_one_id_string_t*)r;
+ /* freeing result of g_strdup */
+ g_free(rec->name);
+ rec->name = NULL;
+}
+
+static void
+post_update_one_id_string_template_cb(generic_one_id_string_t *data, guint data_num, GHashTable *ht) {
+ guint i;
+ int *key = NULL;
+
+ for (i = 0; i < data_num; i++) {
+ key = wmem_new(wmem_epan_scope(), int);
+ *key = data[i].id;
+
+ g_hash_table_insert(ht, key, g_strdup(data[i].name));
+ }
+}
+
+static char*
+ht_lookup_name(GHashTable* ht, unsigned int identifier) {
+ char *tmp = NULL;
+ unsigned int *id = NULL;
+
+ if (ht == NULL) {
+ return NULL;
+ }
+
+ id = wmem_new(wmem_epan_scope(), unsigned int);
+ *id = (unsigned int)identifier;
+ tmp = (char *)g_hash_table_lookup(ht, id);
+ wmem_free(wmem_epan_scope(), id);
+
+ return tmp;
+}
+
+/*
+ * UAT DoIP Diagnostic Addresses
+ */
+#define DATAFILE_DOIP_DIAG_ADDRESSES "DoIP_diagnostic_addresses"
+
+static GHashTable *data_doip_diag_addresses = NULL;
+static generic_one_id_string_t* doip_diag_addresses = NULL;
+static guint doip_diag_address_count = 0;
+
+UAT_HEX_CB_DEF(doip_diag_addresses, id, generic_one_id_string_t)
+UAT_CSTRING_CB_DEF(doip_diag_addresses, name, generic_one_id_string_t)
+
+static void
+post_update_doip_diag_addresses(void) {
+ /* destroy old hash table, if it exists */
+ if (data_doip_diag_addresses) {
+ g_hash_table_destroy(data_doip_diag_addresses);
+ data_doip_diag_addresses = NULL;
+ }
+
+ /* create new hash table */
+ data_doip_diag_addresses = g_hash_table_new_full(g_int_hash, g_int_equal, &doip_uat_free_key, &simple_free);
+ post_update_one_id_string_template_cb(doip_diag_addresses, doip_diag_address_count, data_doip_diag_addresses);
+}
+
+static proto_item *
+doip_prototree_add_with_resolv(proto_tree* doip_tree, int hfindex, int hfindex_name, tvbuff_t* tvb, const gint start, gint length, const guint encoding, guint *diag_addr) {
+ guint diag_addr_tmp;
+ proto_item *ti;
+ proto_tree *tree;
+
+ ti = proto_tree_add_item_ret_uint(doip_tree, hfindex, tvb, start, length, encoding, &diag_addr_tmp);
+ const gchar *name = ht_lookup_name(data_doip_diag_addresses, diag_addr_tmp);
+ if (name != NULL) {
+ proto_item_append_text(ti, " (%s)", name);
+ tree = proto_item_add_subtree(ti, ett_address);
+ ti = proto_tree_add_string(tree, hfindex_name, tvb, start, length, name);
+
+ if (doip_hide_address_names) {
+ proto_item_set_hidden(ti);
+ }
+ }
+
+ if (diag_addr != NULL) {
+ *diag_addr = diag_addr_tmp;
+ }
+
+ return ti;
+}
+
+/*
+ * UAT DoIP Payload Types
+ */
+#define DATAFILE_DOIP_PAYLOAD_TYPES "DoIP_payload_types"
+
+static GHashTable *data_doip_payload_types = NULL;
+static generic_one_id_string_t* doip_payload_types = NULL;
+static guint doip_payload_type_count = 0;
+
+UAT_HEX_CB_DEF(doip_payload_types, id, generic_one_id_string_t)
+UAT_CSTRING_CB_DEF(doip_payload_types, name, generic_one_id_string_t)
+
+static void
+post_update_doip_payload_types(void) {
+ /* destroy old hash table, if it exists */
+ if (data_doip_payload_types) {
+ g_hash_table_destroy(data_doip_payload_types);
+ data_doip_payload_types = NULL;
+ }
+
+ /* create new hash table */
+ data_doip_payload_types = g_hash_table_new_full(g_int_hash, g_int_equal, &doip_uat_free_key, &simple_free);
+ post_update_one_id_string_template_cb(doip_payload_types, doip_payload_type_count, data_doip_payload_types);
+}
+
+static const gchar*
+resolve_doip_payload_type(guint16 payload_type, gboolean is_col)
+{
+ const gchar *tmp = ht_lookup_name(data_doip_payload_types, payload_type);
+
+ /* lets look at the static values, if nothing is configured */
+ if (tmp == NULL) {
+ tmp = try_val_to_str(payload_type, doip_payloads);
+ }
+
+ /* no configured or standardized name known */
+ if (tmp != NULL) {
+ if (is_col) {
+ return tmp;
+ } else {
+ return wmem_strdup_printf(wmem_packet_scope(), "%s (0x%04x)", tmp, payload_type);
+ }
+ }
+
+ /* just give back unknown */
+ if (is_col) {
+ return wmem_strdup_printf(wmem_packet_scope(), "0x%04x Unknown Payload", payload_type);
+ } else {
+ return wmem_strdup_printf(wmem_packet_scope(), "Unknown (0x%04x)", payload_type);
+ }
+}
+
+static void
+add_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *doip_tree)
+{
+ guint32 len;
+ guint32 payload_type;
+
+ proto_tree *subtree = proto_tree_add_subtree(doip_tree, tvb, DOIP_VERSION_OFFSET, DOIP_HEADER_LEN, ett_header, NULL, "Header");
+ proto_tree_add_item(subtree, hf_doip_version, tvb, DOIP_VERSION_OFFSET, DOIP_VERSION_LEN, ENC_BIG_ENDIAN);
+ proto_tree_add_item(subtree, hf_doip_inv_version, tvb, DOIP_INV_VERSION_OFFSET, DOIP_INV_VERSION_LEN, ENC_BIG_ENDIAN);
+ payload_type = tvb_get_guint16(tvb, DOIP_TYPE_OFFSET, ENC_BIG_ENDIAN);
+ proto_tree_add_uint_format(subtree, hf_doip_type, tvb, DOIP_TYPE_OFFSET, DOIP_TYPE_LEN, payload_type, "Type: %s", resolve_doip_payload_type(payload_type, false));
+ proto_tree_add_item_ret_uint(subtree, hf_doip_length, tvb, DOIP_LENGTH_OFFSET, DOIP_LENGTH_LEN, ENC_BIG_ENDIAN, &len);
+
+ if (tvb_captured_length(tvb) < len) {
+ proto_tree_add_expert(doip_tree, pinfo, &ef_doip_illegal_length_field, tvb, DOIP_LENGTH_OFFSET, DOIP_LENGTH_LEN);
+ col_append_str(pinfo->cinfo, COL_INFO, " [DoIP Length Field: Illegal Value]");
+ }
+}
+
+
+static void
+add_generic_header_nack_fields(proto_tree *doip_tree, tvbuff_t *tvb)
+{
+ proto_tree_add_item(doip_tree, hf_generic_nack_code, tvb, DOIP_GENERIC_NACK_OFFSET, DOIP_GENERIC_NACK_LEN, ENC_NA);
+}
+
+
+static void
+add_vehicle_identification_eid_fields(proto_tree *doip_tree, tvbuff_t *tvb)
+{
+ proto_tree_add_item(doip_tree, hf_eid, tvb, DOIP_VEHICLE_IDENTIFICATION_EID_OFFSET, DOIP_COMMON_EID_LEN, ENC_NA);
+}
+
+
+static void
+add_vehicle_identification_vin_fields(proto_tree *doip_tree, tvbuff_t *tvb)
+{
+ proto_tree_add_item(doip_tree, hf_vin, tvb, DOIP_VEHICLE_IDENTIFICATION_VIN_OFFSET, DOIP_COMMON_VIN_LEN, ENC_ASCII | ENC_NA);
+}
+
+
+static void
+add_routing_activation_request_fields(proto_tree *doip_tree, tvbuff_t *tvb, guint8 version)
+{
+ doip_prototree_add_with_resolv(doip_tree, hf_source_address, hf_source_address_name, tvb, DOIP_ROUTING_ACTIVATION_REQ_SRC_OFFSET, DOIP_ROUTING_ACTIVATION_REQ_SRC_LEN, ENC_BIG_ENDIAN, NULL);
+
+ if (version == ISO13400_2010) {
+ proto_tree_add_item(doip_tree, hf_activation_type_v1, tvb, DOIP_ROUTING_ACTIVATION_REQ_TYPE_OFFSET, DOIP_ROUTING_ACTIVATION_REQ_TYPE_LEN_V1, ENC_NA);
+ proto_tree_add_item(doip_tree, hf_reserved_iso, tvb, DOIP_ROUTING_ACTIVATION_REQ_ISO_OFFSET_V1, DOIP_ROUTING_ACTIVATION_REQ_ISO_LEN, ENC_BIG_ENDIAN);
+
+ if ( tvb_bytes_exist(tvb, DOIP_ROUTING_ACTIVATION_REQ_OEM_OFFSET_V1, DOIP_ROUTING_ACTIVATION_REQ_OEM_LEN) ) {
+ proto_tree_add_item(doip_tree, hf_reserved_oem, tvb, DOIP_ROUTING_ACTIVATION_REQ_OEM_OFFSET_V1, DOIP_ROUTING_ACTIVATION_REQ_OEM_LEN, ENC_BIG_ENDIAN);
+ }
+ } else if ((version == ISO13400_2012) || (version == ISO13400_2019)) {
+ proto_tree_add_item(doip_tree, hf_activation_type_v2, tvb, DOIP_ROUTING_ACTIVATION_REQ_TYPE_OFFSET, DOIP_ROUTING_ACTIVATION_REQ_TYPE_LEN_V2, ENC_NA);
+ proto_tree_add_item(doip_tree, hf_reserved_iso, tvb, DOIP_ROUTING_ACTIVATION_REQ_ISO_OFFSET_V2, DOIP_ROUTING_ACTIVATION_REQ_ISO_LEN, ENC_BIG_ENDIAN);
+
+ if ( tvb_bytes_exist(tvb, DOIP_ROUTING_ACTIVATION_REQ_OEM_OFFSET_V2, DOIP_ROUTING_ACTIVATION_REQ_OEM_LEN) ) {
+ proto_tree_add_item(doip_tree, hf_reserved_oem, tvb, DOIP_ROUTING_ACTIVATION_REQ_OEM_OFFSET_V2, DOIP_ROUTING_ACTIVATION_REQ_OEM_LEN, ENC_BIG_ENDIAN);
+ }
+ }
+}
+
+
+static void
+add_routing_activation_response_fields(proto_tree *doip_tree, tvbuff_t *tvb)
+{
+ doip_prototree_add_with_resolv(doip_tree, hf_tester_logical_address, hf_tester_logical_address_name, tvb, DOIP_ROUTING_ACTIVATION_RES_TESTER_OFFSET, DOIP_ROUTING_ACTIVATION_RES_TESTER_LEN, ENC_BIG_ENDIAN, NULL);
+ doip_prototree_add_with_resolv(doip_tree, hf_source_address, hf_source_address_name, tvb, DOIP_ROUTING_ACTIVATION_RES_ENTITY_OFFSET, DOIP_ROUTING_ACTIVATION_RES_ENTITY_LEN, ENC_BIG_ENDIAN, NULL);
+ proto_tree_add_item(doip_tree, hf_response_code, tvb, DOIP_ROUTING_ACTIVATION_RES_CODE_OFFSET, DOIP_ROUTING_ACTIVATION_RES_CODE_LEN, ENC_NA);
+ proto_tree_add_item(doip_tree, hf_reserved_iso, tvb, DOIP_ROUTING_ACTIVATION_RES_ISO_OFFSET, DOIP_ROUTING_ACTIVATION_RES_ISO_LEN, ENC_BIG_ENDIAN);
+
+ if ( tvb_bytes_exist(tvb, DOIP_ROUTING_ACTIVATION_RES_OEM_OFFSET, DOIP_ROUTING_ACTIVATION_RES_OEM_LEN) ) {
+ proto_tree_add_item(doip_tree, hf_reserved_oem, tvb, DOIP_ROUTING_ACTIVATION_RES_OEM_OFFSET, DOIP_ROUTING_ACTIVATION_RES_OEM_LEN, ENC_BIG_ENDIAN);
+ }
+}
+
+
+static void
+add_vehicle_announcement_message_fields(proto_tree *doip_tree, tvbuff_t *tvb)
+{
+ proto_tree_add_item(doip_tree, hf_vin, tvb, DOIP_VEHICLE_ANNOUNCEMENT_VIN_OFFSET, DOIP_COMMON_VIN_LEN, ENC_ASCII | ENC_NA);
+ doip_prototree_add_with_resolv(doip_tree, hf_logical_address, hf_logical_address_name, tvb, DOIP_VEHICLE_ANNOUNCEMENT_ADDRESS_OFFSET, DOIP_VEHICLE_ANNOUNCEMENT_ADDRESS_LEN, ENC_BIG_ENDIAN, NULL);
+ proto_tree_add_item(doip_tree, hf_eid, tvb, DOIP_VEHICLE_ANNOUNCEMENT_EID_OFFSET, DOIP_COMMON_EID_LEN, ENC_NA);
+ proto_tree_add_item(doip_tree, hf_gid, tvb, DOIP_VEHICLE_ANNOUNCEMENT_GID_OFFSET, DOIP_VEHICLE_ANNOUNCEMENT_GID_LEN, ENC_NA);
+ proto_tree_add_item(doip_tree, hf_futher_action, tvb, DOIP_VEHICLE_ANNOUNCEMENT_ACTION_OFFSET, DOIP_VEHICLE_ANNOUNCEMENT_ACTION_LEN, ENC_BIG_ENDIAN);
+
+ if ( tvb_bytes_exist(tvb, DOIP_VEHICLE_ANNOUNCEMENT_SYNC_OFFSET, DOIP_VEHICLE_ANNOUNCEMENT_SYNC_LEN) ) {
+ /* Not part of version 1 and optional in version 2. */
+ proto_tree_add_item(doip_tree, hf_sync_status, tvb, DOIP_VEHICLE_ANNOUNCEMENT_SYNC_OFFSET, DOIP_VEHICLE_ANNOUNCEMENT_SYNC_LEN, ENC_BIG_ENDIAN);
+ }
+}
+
+
+static void
+add_alive_check_response_fields(proto_tree *doip_tree, tvbuff_t *tvb)
+{
+ doip_prototree_add_with_resolv(doip_tree, hf_source_address, hf_source_address_name, tvb, DOIP_ALIVE_CHECK_RESPONSE_SOURCE_OFFSET, DOIP_ALIVE_CHECK_RESPONSE_SOURCE_LEN, ENC_BIG_ENDIAN, NULL);
+}
+
+
+static void
+add_entity_status_response_fields(proto_tree *doip_tree, tvbuff_t *tvb)
+{
+ proto_tree_add_item(doip_tree, hf_node_type, tvb, DOIP_ENTITY_STATUS_RESPONSE_NODE_OFFSET, DOIP_ENTITY_STATUS_RESPONSE_NODE_LEN, ENC_NA);
+ proto_tree_add_item(doip_tree, hf_max_sockets, tvb, DOIP_ENTITY_STATUS_RESPONSE_MCTS_OFFSET, DOIP_ENTITY_STATUS_RESPONSE_MCTS_LEN, ENC_NA);
+ proto_tree_add_item(doip_tree, hf_current_sockets, tvb, DOIP_ENTITY_STATUS_RESPONSE_NCTS_OFFSET, DOIP_ENTITY_STATUS_RESPONSE_NCTS_LEN, ENC_NA);
+ if ( tvb_bytes_exist(tvb, DOIP_ENTITY_STATUS_RESPONSE_MDS_OFFSET, DOIP_ENTITY_STATUS_RESPONSE_MDS_LEN) ) {
+ proto_tree_add_item(doip_tree, hf_max_data_size, tvb, DOIP_ENTITY_STATUS_RESPONSE_MDS_OFFSET, DOIP_ENTITY_STATUS_RESPONSE_MDS_LEN, ENC_BIG_ENDIAN);
+ }
+}
+
+
+static void
+add_power_mode_information_response_fields(proto_tree *doip_tree, tvbuff_t *tvb)
+{
+ proto_tree_add_item(doip_tree, hf_power_mode, tvb, DOIP_POWER_MODE_OFFSET, DOIP_POWER_MODE_LEN, ENC_NA);
+}
+
+
+static void
+add_diagnostic_message_fields(proto_tree *doip_tree, tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ doip_info_t doip_info;
+ guint32 tmp;
+
+ doip_prototree_add_with_resolv(doip_tree, hf_source_address, hf_source_address_name, tvb, DOIP_DIAG_COMMON_SOURCE_OFFSET, DOIP_DIAG_COMMON_SOURCE_LEN, ENC_BIG_ENDIAN, &tmp);
+ doip_info.source_address = tmp;
+ doip_prototree_add_with_resolv(doip_tree, hf_target_address, hf_target_address_name, tvb, DOIP_DIAG_COMMON_TARGET_OFFSET, DOIP_DIAG_COMMON_TARGET_LEN, ENC_BIG_ENDIAN, &tmp);
+ doip_info.target_address = tmp;
+
+ if (uds_handle != 0) {
+ call_dissector_with_data(uds_handle, tvb_new_subset_length(tvb, DOIP_DIAG_MESSAGE_DATA_OFFSET, -1), pinfo, parent_tree, &doip_info);
+ } else if (tvb_reported_length_remaining(tvb, DOIP_DIAG_MESSAGE_DATA_OFFSET) > 0) {
+ proto_tree_add_item(doip_tree, hf_data, tvb, DOIP_DIAG_MESSAGE_DATA_OFFSET, tvb_reported_length_remaining(tvb, DOIP_DIAG_MESSAGE_DATA_OFFSET), ENC_NA);
+ }
+}
+
+
+static void
+add_diagnostic_message_ack_fields(proto_tree *doip_tree, tvbuff_t *tvb)
+{
+ doip_prototree_add_with_resolv(doip_tree, hf_source_address, hf_source_address_name, tvb, DOIP_DIAG_COMMON_SOURCE_OFFSET, DOIP_DIAG_COMMON_SOURCE_LEN, ENC_BIG_ENDIAN, NULL);
+ doip_prototree_add_with_resolv(doip_tree, hf_target_address, hf_target_address_name, tvb, DOIP_DIAG_COMMON_TARGET_OFFSET, DOIP_DIAG_COMMON_TARGET_LEN, ENC_BIG_ENDIAN, NULL);
+ proto_tree_add_item(doip_tree, hf_ack_code, tvb, DOIP_DIAG_MESSAGE_ACK_CODE_OFFSET, DOIP_DIAG_MESSAGE_ACK_CODE_LEN, ENC_NA);
+
+ if (tvb_captured_length_remaining(tvb, DOIP_DIAG_MESSAGE_ACK_PREVIOUS_OFFSET) > 0) {
+ proto_tree_add_item(doip_tree, hf_previous, tvb, DOIP_DIAG_MESSAGE_ACK_PREVIOUS_OFFSET, tvb_captured_length_remaining(tvb, DOIP_DIAG_MESSAGE_ACK_PREVIOUS_OFFSET), ENC_NA);
+ }
+}
+
+
+static void
+add_diagnostic_message_nack_fields(proto_tree *doip_tree, tvbuff_t *tvb)
+{
+ doip_prototree_add_with_resolv(doip_tree, hf_source_address, hf_source_address_name, tvb, DOIP_DIAG_COMMON_SOURCE_OFFSET, DOIP_DIAG_COMMON_SOURCE_LEN, ENC_BIG_ENDIAN, NULL);
+ doip_prototree_add_with_resolv(doip_tree, hf_target_address, hf_target_address_name, tvb, DOIP_DIAG_COMMON_TARGET_OFFSET, DOIP_DIAG_COMMON_TARGET_LEN, ENC_BIG_ENDIAN, NULL);
+ proto_tree_add_item(doip_tree, hf_nack_code, tvb, DOIP_DIAG_MESSAGE_NACK_CODE_OFFSET, DOIP_DIAG_MESSAGE_NACK_CODE_LEN, ENC_NA);
+
+ if (tvb_captured_length_remaining(tvb, DOIP_DIAG_MESSAGE_NACK_PREVIOUS_OFFSET) > 0) {
+ proto_tree_add_item(doip_tree, hf_previous, tvb, DOIP_DIAG_MESSAGE_NACK_PREVIOUS_OFFSET, tvb_captured_length_remaining(tvb, DOIP_DIAG_MESSAGE_NACK_PREVIOUS_OFFSET), ENC_NA);
+ }
+}
+
+
+/* DoIP protocol dissector */
+static void
+dissect_doip_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 version = tvb_get_guint8(tvb, DOIP_VERSION_OFFSET);
+ guint16 payload_type = tvb_get_ntohs(tvb, DOIP_TYPE_OFFSET);
+
+ /* Set protocol and clear information columns */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DoIP");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (
+ version == ISO13400_2010 ||
+ version == ISO13400_2012 ||
+ version == ISO13400_2019 ||
+ version == ISO13400_2019_AMD1 ||
+ (version == DEFAULT_VALUE && (payload_type >= DOIP_VEHICLE_IDENTIFICATION_REQ && payload_type <= DOIP_VEHICLE_IDENTIFICATION_REQ_VIN))
+ ) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", resolve_doip_payload_type(payload_type, true));
+ } else {
+ col_set_str(pinfo->cinfo, COL_INFO, "Invalid/unsupported DoIP version");
+ }
+
+
+ if (tree) {
+ proto_item *ti = NULL;
+ proto_tree *doip_tree = NULL;
+
+ ti = proto_tree_add_item(tree, proto_doip, tvb, 0, -1, ENC_NA);
+ doip_tree = proto_item_add_subtree(ti, ett_doip);
+
+ add_header(tvb, pinfo, doip_tree);
+
+ switch (payload_type) {
+ case DOIP_GENERIC_NACK:
+ add_generic_header_nack_fields(doip_tree, tvb);
+ break;
+
+ case DOIP_VEHICLE_IDENTIFICATION_REQ:
+ break;
+
+ case DOIP_VEHICLE_IDENTIFICATION_REQ_EID:
+ add_vehicle_identification_eid_fields(doip_tree, tvb);
+ break;
+
+ case DOIP_VEHICLE_IDENTIFICATION_REQ_VIN:
+ add_vehicle_identification_vin_fields(doip_tree, tvb);
+ break;
+
+ case DOIP_ROUTING_ACTIVATION_REQUEST:
+ add_routing_activation_request_fields(doip_tree, tvb, version);
+ break;
+
+ case DOIP_ROUTING_ACTIVATION_RESPONSE:
+ add_routing_activation_response_fields(doip_tree, tvb);
+ break;
+
+ case DOIP_VEHICLE_ANNOUNCEMENT_MESSAGE:
+ add_vehicle_announcement_message_fields(doip_tree, tvb);
+ break;
+
+ case DOIP_ALIVE_CHECK_REQUEST:
+ break;
+
+ case DOIP_ALIVE_CHECK_RESPONSE:
+ add_alive_check_response_fields(doip_tree, tvb);
+ break;
+
+ case DOIP_ENTITY_STATUS_REQUEST:
+ break;
+
+ case DOIP_ENTITY_STATUS_RESPONSE:
+ add_entity_status_response_fields(doip_tree, tvb);
+ break;
+
+ case DOIP_POWER_INFORMATION_REQUEST:
+ break;
+
+ case DOIP_POWER_INFORMATION_RESPONSE:
+ add_power_mode_information_response_fields(doip_tree, tvb);
+ break;
+
+ case DOIP_DIAGNOSTIC_MESSAGE:
+ add_diagnostic_message_fields(doip_tree, tvb, pinfo, tree);
+ break;
+
+ case DOIP_DIAGNOSTIC_MESSAGE_ACK:
+ add_diagnostic_message_ack_fields(doip_tree, tvb);
+ break;
+
+ case DOIP_DIAGNOSTIC_MESSAGE_NACK:
+ add_diagnostic_message_nack_fields(doip_tree, tvb);
+ break;
+ }
+ } else if (payload_type == DOIP_DIAGNOSTIC_MESSAGE) {
+ /* Show UDS details in info column */
+ if (uds_handle != 0) {
+ doip_info_t doip_info;
+ doip_info.source_address = tvb_get_guint16(tvb, DOIP_DIAG_COMMON_SOURCE_OFFSET, ENC_BIG_ENDIAN);
+ doip_info.target_address = tvb_get_guint16(tvb, DOIP_DIAG_COMMON_TARGET_OFFSET, ENC_BIG_ENDIAN);
+ call_dissector_with_data(uds_handle, tvb_new_subset_length(tvb, DOIP_DIAG_MESSAGE_DATA_OFFSET, -1), pinfo, NULL, &doip_info);
+ }
+ }
+}
+
+
+/* determine PDU length of protocol DoIP */
+static guint
+get_doip_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *p _U_)
+{
+ guint8 ver1 = tvb_get_guint8(tvb, DOIP_VERSION_OFFSET);
+ guint8 ver2 = tvb_get_guint8(tvb, DOIP_INV_VERSION_OFFSET);
+
+ if (ver1 != ((~ver2) & 0xff)) {
+ /* if ver2 is not the inverse of ver1, we are not at the start of a DoIP message! */
+ /* bounds_error: (0 < return < DOIP_HEADER_LEN) */
+ return 1;
+ }
+
+ /* PDU Length = length field value + header length */
+ guint32 ret = tvb_get_ntohl(tvb, offset + DOIP_LENGTH_OFFSET) + DOIP_HEADER_LEN;
+
+ if (ret < DOIP_HEADER_LEN || ret > 0x7fffffff) {
+ /* catch illegal length fields (overflow or too big) */
+ return DOIP_HEADER_LEN;
+ }
+
+ return ret;
+}
+
+
+static int
+dissect_doip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_doip_message(tvb, pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+
+static int
+dissect_doip(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_, void* data)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, TRUE, DOIP_HEADER_LEN, get_doip_message_len, dissect_doip_pdu, data);
+ return tvb_captured_length(tvb);
+}
+
+
+/* Register DoIP Protocol */
+void
+proto_register_doip(void)
+{
+ module_t *doip_module = NULL;
+ expert_module_t *expert_module_doip = NULL;
+ uat_t *doip_diag_addr_uat = NULL;
+ uat_t *doip_payload_type_uat = NULL;
+
+ static hf_register_info hf[] = {
+ /* Header */
+ { &hf_doip_version,
+ { "Version", "doip.version",
+ FT_UINT8, BASE_HEX,
+ VALS(doip_versions), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_doip_inv_version,
+ { "Inverse version", "doip.inverse",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_doip_type,
+ { "Type", "doip.type",
+ FT_UINT16, BASE_HEX,
+ VALS(doip_payloads), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_doip_length,
+ { "Length", "doip.length",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL }
+ },
+ /* Generic NACK */
+ {
+ &hf_generic_nack_code,
+ {
+ "DoIP Header NACK code", "doip.nack_code",
+ FT_UINT8, BASE_HEX,
+ VALS(nack_codes), 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Vehicle announcement message */
+ {
+ &hf_vin,
+ {
+ "VIN", "doip.vin",
+ FT_STRING, BASE_NONE,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_logical_address,
+ {
+ "Logical Address", "doip.logical_address",
+ FT_UINT16, BASE_HEX,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_logical_address_name,
+ {
+ "Logical Address Name", "doip.logical_address_name",
+ FT_STRING, BASE_NONE,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_eid,
+ {
+ "EID", "doip.eid",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_gid,
+ {
+ "GID", "doip.gid",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_futher_action,
+ {
+ "Further action required", "doip.futher_action",
+ FT_UINT8, BASE_HEX,
+ VALS(action_codes), 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_sync_status,
+ {
+ "VIN/GID sync. status", "doip.sync_status",
+ FT_UINT8, BASE_HEX,
+ VALS(sync_status), 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Diagnostic power mode information response */
+ {
+ &hf_power_mode,
+ {
+ "Diagnostic power mode", "doip.power_mode",
+ FT_UINT8, BASE_HEX,
+ VALS(power_modes), 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Entity status response */
+ {
+ &hf_node_type,
+ {
+ "Node type", "doip.node_type",
+ FT_UINT8, BASE_HEX,
+ VALS(node_types), 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_max_sockets,
+ {
+ "Max concurrent sockets", "doip.max_sockets",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_current_sockets,
+ {
+ "Currently open sockets", "doip.sockets",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_max_data_size,
+ {
+ "Max data size", "doip.max_data_size",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Common */
+ {
+ &hf_source_address,
+ {
+ "Source Address", "doip.source_address",
+ FT_UINT16, BASE_HEX,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_source_address_name,
+ {
+ "Source Address Name", "doip.source_address_name",
+ FT_STRING, BASE_NONE,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_target_address,
+ {
+ "Target Address", "doip.target_address",
+ FT_UINT16, BASE_HEX,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_target_address_name,
+ {
+ "Target Address Name", "doip.target_address_name",
+ FT_STRING, BASE_NONE,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Routing activation request */
+ {
+ &hf_activation_type_v1,
+ {
+ "Activation type", "doip.activation_type_v1",
+ FT_UINT16, BASE_HEX,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_activation_type_v2,
+ {
+ "Activation type", "doip.activation_type",
+ FT_UINT8, BASE_HEX,
+ VALS(activation_types), 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Routing activation response */
+ {
+ &hf_tester_logical_address,
+ {
+ "Logical address of external tester", "doip.tester_logical_address",
+ FT_UINT16, BASE_HEX,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_tester_logical_address_name,
+ {
+ "Name of external tester", "doip.tester_logical_address_name",
+ FT_STRING, BASE_NONE,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_response_code,
+ {
+ "Routing activation response code", "doip.response_code",
+ FT_UINT8, BASE_HEX,
+ VALS(activation_codes), 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Common */
+ {
+ &hf_reserved_iso,
+ {
+ "Reserved by ISO", "doip.reserved_iso",
+ FT_UINT32, BASE_HEX,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_reserved_oem,
+ {
+ "Reserved by OEM", "doip.reserved_oem",
+ FT_UINT32, BASE_HEX,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Diagnostic message */
+ {
+ &hf_data,
+ {
+ "User data", "doip.data",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Diagnostic message ACK */
+ {
+ &hf_ack_code,
+ {
+ "ACK code", "doip.diag_ack_code",
+ FT_UINT8, BASE_HEX,
+ VALS(diag_ack_codes), 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Diagnostic message NACK */
+ {
+ &hf_nack_code,
+ {
+ "NACK code", "doip.diag_nack_code",
+ FT_UINT8, BASE_HEX,
+ VALS(diag_nack_codes), 0x00,
+ NULL, HFILL
+ }
+ },
+ /* Common */
+ {
+ &hf_previous,
+ {
+ "Previous message", "doip.previous",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x00,
+ NULL, HFILL
+ }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_doip,
+ &ett_header,
+ &ett_address
+ };
+
+ /* UAT definitions */
+ static uat_field_t doip_diag_addr_uat_fields[] = {
+ UAT_FLD_HEX(doip_diag_addresses, id, "Diagnostic Address", "Diagnostic Address (hex uint16 without leading 0x)"),
+ UAT_FLD_CSTRING(doip_diag_addresses, name, "Name", "Name of the ECU (string)"),
+ UAT_END_FIELDS
+ };
+
+ static uat_field_t doip_payload_type_uat_fields[] = {
+ UAT_FLD_HEX(doip_payload_types, id, "Payload Type", "Payload Type (hex uint16 without leading 0x)"),
+ UAT_FLD_CSTRING(doip_payload_types, name, "Name", "Name of the Payload Type (string)"),
+ UAT_END_FIELDS
+ };
+
+ proto_doip = proto_register_protocol (
+ "DoIP (ISO13400) Protocol", /* name */
+ "DoIP", /* short name */
+ "doip" /* abbrev */
+ );
+
+ proto_register_field_array(proto_doip, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ doip_handle = register_dissector("doip", dissect_doip, proto_doip);
+ doip_module = prefs_register_protocol(proto_doip, NULL);
+
+ /* UATs */
+ doip_diag_addr_uat = uat_new("Diagnostic Addresses",
+ sizeof(generic_one_id_string_t), /* record size */
+ DATAFILE_DOIP_DIAG_ADDRESSES, /* filename */
+ TRUE, /* from profile */
+ (void**)&doip_diag_addresses, /* data_ptr */
+ &doip_diag_address_count, /* numitems_ptr */
+ UAT_AFFECTS_DISSECTION, /* but not fields */
+ NULL, /* help */
+ copy_generic_one_id_string_cb, /* copy callback */
+ update_generic_one_identifier_16bit, /* update callback */
+ free_generic_one_id_string_cb, /* free callback */
+ post_update_doip_diag_addresses, /* post update callback */
+ NULL, /* reset callback */
+ doip_diag_addr_uat_fields /* UAT field definitions */
+ );
+
+ prefs_register_uat_preference(doip_module, "_udf_doip_diag_addresses", "Diagnostics Addresses",
+ "A table to define names of Diagnostics Addresses.", doip_diag_addr_uat);
+
+ doip_payload_type_uat = uat_new("Payload Types",
+ sizeof(generic_one_id_string_t), /* record size */
+ DATAFILE_DOIP_PAYLOAD_TYPES, /* filename */
+ TRUE, /* from profile */
+ (void**)&doip_payload_types, /* data_ptr */
+ &doip_payload_type_count, /* numitems_ptr */
+ UAT_AFFECTS_DISSECTION, /* but not fields */
+ NULL, /* help */
+ copy_generic_one_id_string_cb, /* copy callback */
+ update_generic_one_identifier_16bit, /* update callback */
+ free_generic_one_id_string_cb, /* free callback */
+ post_update_doip_payload_types, /* post update callback */
+ NULL, /* reset callback */
+ doip_payload_type_uat_fields /* UAT field definitions */
+ );
+
+ prefs_register_uat_preference(doip_module, "_udf_doip_payload_types", "Payload Types",
+ "A table to define names of Payload Types.", doip_payload_type_uat);
+
+ prefs_register_bool_preference(doip_module, "hide_address_name_entries",
+ "Hide Address Name Entries",
+ "Should the dissector hide the names for addresses?",
+ &doip_hide_address_names);
+
+ static ei_register_info ei[] = {
+ { &ef_doip_illegal_length_field, { "doip.illegal_length_field",
+ PI_MALFORMED, PI_ERROR, "DoIP illegal length field", EXPFILL } },
+ };
+
+ expert_module_doip = expert_register_protocol(proto_doip);
+ expert_register_field_array(expert_module_doip, ei, array_length(ei));
+}
+
+void
+proto_reg_handoff_doip(void)
+{
+ dissector_add_uint("udp.port", DOIP_PORT, doip_handle);
+ dissector_add_uint("tcp.port", DOIP_PORT, doip_handle);
+
+ ssl_dissector_add( DOIP_TLS_PORT, doip_handle);
+
+ uds_handle = find_dissector("uds_over_doip");
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */