diff --git a/epan/dissectors/packet-someip-sd.c b/epan/dissectors/packet-someip-sd.c index 84134a9bfe..247b54afa1 100644 --- a/epan/dissectors/packet-someip-sd.c +++ b/epan/dissectors/packet-someip-sd.c @@ -1,7 +1,7 @@ /* packet-someip-sd.c * SOME/IP-SD dissector. * By Dr. Lars Voelker / - * Copyright 2012-2021 Dr. Lars Voelker + * Copyright 2012-2022 Dr. Lars Voelker * Copyright 2020 Ayoub Kaanich * Copyright 2019 Ana Pantar * Copyright 2019 Guenter Ebermann @@ -14,12 +14,15 @@ */ #include + #include #include #include #include -#include "packet-udp.h" -#include "packet-someip.h" +#include + +#include +#include /* * Dissector for SOME/IP Service Discovery (SOME/IP-SD). @@ -142,6 +145,28 @@ static gint ett_someip_sd_options = -1; static gint ett_someip_sd_option = -1; static gint ett_someip_sd_config_string = -1; + +/*** Taps ***/ +static int tap_someip_sd_entries = -1; + +typedef struct _someip_sd_entries_tap { + guint8 entry_type; + guint16 service_id; + guint8 major_version; + guint32 minor_version; + guint16 instance_id; + guint16 eventgroup_id; + guint32 ttl; +} someip_sd_entries_tap_t; + + +/*** Stats ***/ +static const gchar *st_str_ip_src = "Source Addresses"; +static const gchar *st_str_ip_dst = "Destination Addresses"; + +static int st_node_ip_src = -1; +static int st_node_ip_dst = -1; + /*** Preferences ***/ static range_t *someip_ignore_ports_udp = NULL; static range_t *someip_ignore_ports_tcp = NULL; @@ -477,7 +502,7 @@ dissect_someip_sd_pdu_options(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre } static void -dissect_someip_sd_pdu_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset_orig, guint32 length _U_, guint32 *entry_flags, guint32 *stop_entry_flags) { +dissect_someip_sd_pdu_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset_orig, guint32 length, guint32 *entry_flags, guint32 *stop_entry_flags) { guint8 type = 255; guint32 serviceid = 0; guint32 instanceid = 0; @@ -638,6 +663,20 @@ dissect_someip_sd_pdu_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, if (ti != NULL) { PROTO_ITEM_SET_HIDDEN(ti); } + + /* TAP */ + if (have_tap_listener(tap_someip_sd_entries)) { + someip_sd_entries_tap_t *data = wmem_alloc(pinfo->pool, sizeof(someip_sd_entries_tap_t)); + data->entry_type = type; + data->service_id = (guint16)serviceid; + data->major_version = (guint8)majorver; + data->minor_version = minorver; + data->instance_id = (guint16)instanceid; + data->eventgroup_id = (guint16)eventgroupid; + data->ttl = ttl; + + tap_queue_packet(tap_someip_sd_entries, pinfo, data); + } } static int @@ -797,6 +836,125 @@ dissect_someip_sd_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void return offset; } +static void +someipsd_entries_stats_tree_init(stats_tree *st) { + st_node_ip_src = stats_tree_create_node(st, st_str_ip_src, 0, STAT_DT_INT, TRUE); + stat_node_set_flags(st, st_str_ip_src, 0, FALSE, ST_FLG_SORT_TOP); + st_node_ip_dst = stats_tree_create_node(st, st_str_ip_dst, 0, STAT_DT_INT, TRUE); +} + +static void +stat_number_to_string_with_any(guint32 value, guint max, gchar *format_string, gchar *ret, size_t size_limit) { + if (value == max) { + snprintf(ret, size_limit, "%s", "MAX"); + } else { + snprintf(ret, size_limit, format_string, value); + } +} + +static void +stat_create_entry_summary_string(const someip_sd_entries_tap_t *data, gchar *ret, size_t size_limit) { + gchar service_str[128]; + gchar instance_str[128]; + gchar majorver_str[128]; + gchar minorver_str[128]; + gchar eventgrp_str[128]; + + stat_number_to_string_with_any(data->service_id, UINT32_MAX, "0x%04x", service_str, sizeof(service_str) - 1); + stat_number_to_string_with_any(data->instance_id, UINT32_MAX, "0x%04x", instance_str, sizeof(instance_str) - 1); + stat_number_to_string_with_any(data->major_version, UINT8_MAX, "%d", majorver_str, sizeof(majorver_str) - 1); + + switch (data->entry_type) { + case SD_ENTRY_FIND_SERVICE: + case SD_ENTRY_OFFER_SERVICE: + stat_number_to_string_with_any(data->minor_version, UINT32_MAX, "%d", minorver_str, sizeof(minorver_str) - 1); + snprintf(ret, size_limit, "Service %s Version %s.%s Instance %s", service_str, majorver_str, minorver_str, instance_str); + break; + + case SD_ENTRY_SUBSCRIBE_EVENTGROUP: + case SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK: + stat_number_to_string_with_any(data->eventgroup_id, UINT32_MAX, "0x%04x", eventgrp_str, sizeof(eventgrp_str) - 1); + snprintf(ret, size_limit, "Service %s Version %s Instance %s Eventgroup %s", service_str, majorver_str, instance_str, eventgrp_str); + break; + } +} + +static tap_packet_status +someipsd_entries_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p) { + DISSECTOR_ASSERT(p); + const someip_sd_entries_tap_t *data = (const someip_sd_entries_tap_t *)p; + + gchar *src_addr = address_to_str(pinfo->pool, &pinfo->net_src); + gchar *dst_addr = address_to_str(pinfo->pool, &pinfo->net_dst); + + tick_stat_node(st, st_str_ip_src, 0, FALSE); + int src_id = tick_stat_node(st, src_addr, st_node_ip_src, TRUE); + tick_stat_node(st, st_str_ip_dst, 0, FALSE); + int dst_id = tick_stat_node(st, dst_addr, st_node_ip_dst, TRUE); + + int tmp_id; + static gchar tmp_str[128]; + + if (data->ttl == 0) { + switch (data->entry_type) { + case SD_ENTRY_STOP_OFFER_SERVICE: + stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1); + tmp_id = tick_stat_node(st, "Stop Offer Service", src_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + tmp_id = tick_stat_node(st, "Stop Offer Service", dst_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + break; + case SD_ENTRY_STOP_SUBSCRIBE_EVENTGROUP: + stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1); + tmp_id = tick_stat_node(st, "Stop Subscribe Eventgroup", src_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + tmp_id = tick_stat_node(st, "Stop Subscribe Eventgroup", dst_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + break; + case SD_ENTRY_SUBSCRIBE_EVENTGROUP_NACK: + stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1); + tmp_id = tick_stat_node(st, "Subscribe Eventgroup Nack", src_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + tmp_id = tick_stat_node(st, "Subscribe Eventgroup Nack", dst_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + break; + } + } else { + switch (data->entry_type) { + case SD_ENTRY_FIND_SERVICE: + stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1); + tmp_id = tick_stat_node(st, "Find Service", src_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + tmp_id = tick_stat_node(st, "Find Service", dst_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + break; + case SD_ENTRY_OFFER_SERVICE: + stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1); + tmp_id = tick_stat_node(st, "Offer Service", src_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + tmp_id = tick_stat_node(st, "Offer Service", dst_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + break; + case SD_ENTRY_SUBSCRIBE_EVENTGROUP: + stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1); + tmp_id = tick_stat_node(st, "Subscribe Eventgroup", src_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + tmp_id = tick_stat_node(st, "Subscribe Eventgroup", dst_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + break; + case SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK: + stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1); + tmp_id = tick_stat_node(st, "Subscribe Eventgroup Ack", src_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + tmp_id = tick_stat_node(st, "Subscribe Eventgroup Ack", dst_id, TRUE); + tick_stat_node(st, tmp_str, tmp_id, FALSE); + break; + } + } + + return TAP_PACKET_REDRAW; +} + void proto_register_someip_sd(void) { module_t *someipsd_module; @@ -974,12 +1132,13 @@ proto_register_someip_sd(void) { { &ef_someipsd_config_string_malformed,{ "someipsd.config_string_malformed", PI_MALFORMED, PI_ERROR, "SOME/IP-SD Configuration String malformed!", EXPFILL } }, }; - /* Register ETTs */ + /* Register Protocol, Fields, ETTs, Expert Info, Taps */ proto_someip_sd = proto_register_protocol(SOMEIP_SD_NAME_LONG, SOMEIP_SD_NAME, SOMEIP_SD_NAME_FILTER); proto_register_field_array(proto_someip_sd, hf_sd, array_length(hf_sd)); proto_register_subtree_array(ett_sd, array_length(ett_sd)); expert_module_someip_sd = expert_register_protocol(proto_someip_sd); expert_register_field_array(expert_module_someip_sd, ei_sd, array_length(ei_sd)); + tap_someip_sd_entries = register_tap("someipsd_entries"); /* Register preferences */ someipsd_module = prefs_register_protocol(proto_someip_sd, &proto_reg_handoff_someip_sd); @@ -1003,6 +1162,9 @@ proto_reg_handoff_someip_sd(void) { if (!initialized) { someip_sd_handle = create_dissector_handle(dissect_someip_sd_pdu, proto_someip_sd); dissector_add_uint("someip.messageid", SOMEIP_SD_MESSAGEID, someip_sd_handle); + + stats_tree_register("someipsd_entries", "someipsd_entries", "SOME/IP-SD Entries", 0, someipsd_entries_stats_tree_packet, someipsd_entries_stats_tree_init, NULL); + initialized = TRUE; } diff --git a/epan/dissectors/packet-someip.c b/epan/dissectors/packet-someip.c index 8b23c01061..5485df94b0 100644 --- a/epan/dissectors/packet-someip.c +++ b/epan/dissectors/packet-someip.c @@ -1,7 +1,7 @@ /* packet-someip.c * SOME/IP dissector. * By Dr. Lars Voelker / - * Copyright 2012-2021 Dr. Lars Voelker + * Copyright 2012-2022 Dr. Lars Voelker * Copyright 2019 Ana Pantar * Copyright 2019 Guenter Ebermann * @@ -13,6 +13,7 @@ */ #include + #include #include #include @@ -20,10 +21,12 @@ #include #include #include -#include "packet-udp.h" -#include "packet-dtls.h" -#include "packet-someip.h" -#include "packet-tls.h" +#include + +#include +#include +#include +#include /* * Dissector for SOME/IP, SOME/IP-TP, and SOME/IP Payloads. @@ -291,6 +294,15 @@ static GHashTable *data_someip_parameter_structs = NULL; static GHashTable *data_someip_parameter_unions = NULL; static GHashTable *data_someip_parameter_enums = NULL; +/*** Taps ***/ +static int tap_someip_messages = -1; + +/*** Stats ***/ +static const gchar *st_str_ip_src = "Source Addresses"; +static const gchar *st_str_ip_dst = "Destination Addresses"; + +static int st_node_ip_src = -1; +static int st_node_ip_dst = -1; /*********************************************** ********* Preferences / Configuration ********* @@ -2326,6 +2338,46 @@ expert_someip_payload_alignment_error(proto_tree *tree, packet_info *pinfo, tvbu col_append_str(pinfo->cinfo, COL_INFO, " [SOME/IP Payload: Alignment problem]"); } +/******************************************* + **************** Statistics *************** + ******************************************/ + +static void +someip_messages_stats_tree_init(stats_tree *st) { + st_node_ip_src = stats_tree_create_node(st, st_str_ip_src, 0, STAT_DT_INT, TRUE); + stat_node_set_flags(st, st_str_ip_src, 0, FALSE, ST_FLG_SORT_TOP); + st_node_ip_dst = stats_tree_create_node(st, st_str_ip_dst, 0, STAT_DT_INT, TRUE); +} + +static tap_packet_status +someip_messages_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p) { + static gchar tmp_srv_str[128]; + static gchar tmp_meth_str[128]; + int tmp; + + DISSECTOR_ASSERT(p); + const someip_messages_tap_t *data = (const someip_messages_tap_t *)p; + + gchar *src_addr = address_to_str(pinfo->pool, &pinfo->net_src); + tick_stat_node(st, st_str_ip_src, 0, FALSE); + int src_id = tick_stat_node(st, src_addr, st_node_ip_src, TRUE); + + gchar *dst_addr = address_to_str(pinfo->pool, &pinfo->net_dst); + tick_stat_node(st, st_str_ip_dst, 0, FALSE); + int dst_id = tick_stat_node(st, dst_addr, st_node_ip_dst, TRUE); + + snprintf(tmp_srv_str, sizeof(tmp_srv_str) - 1, "Service 0x%04x", data->service_id); + snprintf(tmp_meth_str, sizeof(tmp_meth_str) - 1, "Method 0x%04x %s", data->method_id, + val_to_str(data->message_type, someip_msg_type, "Message-Type: 0x%02x")); + + tmp = tick_stat_node(st, tmp_srv_str, src_id, TRUE); + tick_stat_node(st, tmp_meth_str, tmp, FALSE); + tmp = tick_stat_node(st, tmp_srv_str, dst_id, TRUE); + tick_stat_node(st, tmp_meth_str, tmp, FALSE); + + return TAP_PACKET_REDRAW; +} + /******************************************* ******** SOME/IP Payload Dissector ******** *******************************************/ @@ -3315,6 +3367,17 @@ dissect_someip_payload(tvbuff_t* tvb, packet_info* pinfo, proto_item *ti, guint1 proto_tree *tree = NULL; + /* TAP */ + if (have_tap_listener(tap_someip_messages)) { + someip_messages_tap_t *data = wmem_alloc(pinfo->pool, sizeof(someip_messages_tap_t)); + data->service_id = serviceid; + data->method_id = methodid; + data->interface_version = version; + data->message_type = msgtype; + + tap_queue_packet(tap_someip_messages, pinfo, data); + } + length = tvb_captured_length_remaining(tvb, 0); tree = proto_item_add_subtree(ti, ett_someip_payload); paramlist = get_parameter_config(serviceid, methodid, version, msgtype); @@ -3335,7 +3398,7 @@ dissect_someip_payload(tvbuff_t* tvb, packet_info* pinfo, proto_item *ti, guint1 if (offset_bits != 0) { expert_someip_payload_malformed(tree, pinfo, tvb, offset, 0); - /* allign to byte */ + /* align to byte */ offset += 1; } @@ -3949,7 +4012,7 @@ proto_register_someip(void) { PI_MALFORMED, PI_WARN, "SOME/IP Payload: Dynamic array does not stay between Min and Max values!", EXPFILL} }, }; - /* Register ETTs */ + /* Register Protocol, Handles, Fields, ETTs, Expert Info, Dissector Table, Taps */ proto_someip = proto_register_protocol(SOMEIP_NAME_LONG, SOMEIP_NAME, SOMEIP_NAME_FILTER); someip_handle_udp = register_dissector("someip_udp", dissect_someip_udp, proto_someip); someip_handle_tcp = register_dissector("someip_tcp", dissect_someip_tcp, proto_someip); @@ -3961,6 +4024,8 @@ proto_register_someip(void) { someip_dissector_table = register_dissector_table("someip.messageid", "SOME/IP Message ID", proto_someip, FT_UINT32, BASE_HEX); + tap_someip_messages = register_tap("someip_messages"); + /* init for SOME/IP-TP */ reassembly_table_init(&someip_tp_reassembly_table, &addresses_ports_reassembly_table_functions); @@ -4271,6 +4336,8 @@ proto_reg_handoff_someip(void) { heur_dissector_add("udp", dissect_some_ip_heur_udp, "SOME/IP_UDP_Heuristic", "someip_udp_heur", proto_someip, HEURISTIC_DISABLE); heur_dissector_add("tcp", dissect_some_ip_heur_tcp, "SOME/IP_TCP_Heuristic", "someip_tcp_heur", proto_someip, HEURISTIC_DISABLE); + stats_tree_register("someip_messages", "someip_messages", "SOME/IP Messages", 0, someip_messages_stats_tree_packet, someip_messages_stats_tree_init, NULL); + initialized = TRUE; } else { /* delete all my ports even the dynamically registered ones */ diff --git a/epan/dissectors/packet-someip.h b/epan/dissectors/packet-someip.h index 83e2fdc2b0..bf273da49a 100644 --- a/epan/dissectors/packet-someip.h +++ b/epan/dissectors/packet-someip.h @@ -1,7 +1,7 @@ /* packet-someip.h * Definitions for SOME/IP packet disassembly structures and routines * By Dr. Lars Voelker / - * Copyright 2012-2021 Dr. Lars Voelker + * Copyright 2012-2022 Dr. Lars Voelker * * Wireshark - Network traffic analyzer * By Gerald Combs @@ -26,6 +26,13 @@ typedef struct _someip_info guint8 major_version; } someip_info_t; +typedef struct _someip_messages_tap { + guint16 service_id; + guint16 method_id; + guint8 interface_version; + guint8 message_type; +} someip_messages_tap_t; + /* * Editor modelines * diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 8f7ad2660b..e24b228eac 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -689,6 +689,8 @@ private slots: void actionStatisticsPlugin_triggered(); void on_actionStatisticsHpfeeds_triggered(); void on_actionStatisticsHTTP2_triggered(); + void on_actionStatisticsSOMEIPmessages_triggered(); + void on_actionStatisticsSOMEIPSDentries_triggered(); RtpStreamDialog *openTelephonyRtpStreamsDialog(); RtpPlayerDialog *openTelephonyRtpPlayerDialog(); diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index 60075d3f11..150acd8166 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -553,6 +553,14 @@ + + + + SOME/IP + + + + @@ -1927,6 +1935,22 @@ Sametime statistics + + + + SOME/IP Messages + + + SOME/IP Message statistics + + + + + SOME/IP-SD Entries + + + SOME/IP-SD Entries statistics + diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index aedb0b1261..6a767296c8 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -3418,6 +3418,16 @@ void MainWindow::on_actionStatisticsHTTP2_triggered() } +void MainWindow::on_actionStatisticsSOMEIPmessages_triggered() +{ + openStatisticsTreeDialog("someip_messages"); +} + +void MainWindow::on_actionStatisticsSOMEIPSDentries_triggered() +{ + openStatisticsTreeDialog("someipsd_entries"); +} + // Telephony Menu RtpPlayerDialog *MainWindow::openTelephonyRtpPlayerDialog()