diff --git a/Images/HPAV_LLC_AC.png b/Images/HPAV_LLC_AC.png new file mode 100644 index 0000000..fd112d2 Binary files /dev/null and b/Images/HPAV_LLC_AC.png differ diff --git a/Installer/InstallerScript.iss b/Installer/InstallerScript.iss index 4b55036..0abe9f2 100644 --- a/Installer/InstallerScript.iss +++ b/Installer/InstallerScript.iss @@ -1,5 +1,5 @@ // DO NOT CHANGE VERSION HERE! Run update_version.bat -#define AppVer "1.3.1" +#define AppVer "1.4.0" #define AppId "dsV2Gshark" [Setup] @@ -43,18 +43,20 @@ Name: "plugin/decoder"; Description: "EXI decoder (powered by chargebyte cbexige Name: "plugin/decoder/din"; Description: "DIN 70121 support"; Types: full custom; Flags: fixed Name: "plugin/decoder/iso2"; Description: "ISO 15118-2 support"; Types: full custom; Flags: fixed Name: "plugin/decoder/iso20"; Description: "ISO 15118-20 support (experimental)"; Types: full custom; Flags: fixed -Name: "plugin/autoschema"; Description: "Automatic schema detection"; Types: full custom; Flags: fixed +Name: "plugin/autoschema"; Description: "Automatic schema detection"; Types: full custom; Flags: fixed Name: "plugin/autodecrypt"; Description: "Live TLS decryption with disclosed master secret from UDP packet"; Types: full custom; +Name: "plugin/llc_diagnostic"; Description: "Additional dissector for CP-State related Homeplug AV packets"; Types: full custom; Name: "buttons"; Description: "Add filter buttons to Wireshark (current user only)"; Types: full Name: "colorfilters"; Description: "Highlight V2G messages in Wireshark (current user only)"; Types: full Name: "iograph"; Description: "Prepare Wireshark I/O Graphs for V2G messages{cm:Linebreak}(current user only, may override I/O Graph preferences)"; Types: full [Files] -Source: "..\Wireshark\plugins\v2gshared.lua"; DestDir: "{app}\plugins"; Flags: ignoreversion recursesubdirs; Components: plugin/dissectors +Source: "..\Wireshark\plugins\v2gcommon.lua"; DestDir: "{app}\plugins"; Flags: ignoreversion recursesubdirs; Components: plugin/dissectors Source: "..\Wireshark\plugins\v2gmsg.lua"; DestDir: "{app}\plugins"; Flags: ignoreversion recursesubdirs; Components: plugin/dissectors Source: "..\Wireshark\plugins\v2gtp.lua"; DestDir: "{app}\plugins"; Flags: ignoreversion recursesubdirs; Components: plugin/dissectors Source: "..\Wireshark\plugins\v2gsdp.lua"; DestDir: "{app}\plugins"; Flags: ignoreversion recursesubdirs; Components: plugin/dissectors Source: "..\Wireshark\plugins\v2gtlssecret.lua"; DestDir: "{app}\plugins"; Flags: ignoreversion recursesubdirs; Components: plugin/autodecrypt +Source: "..\Wireshark\plugins\v2gllc.lua"; DestDir: "{app}\plugins"; Flags: ignoreversion recursesubdirs; Components: plugin/llc_diagnostic Source: "..\Wireshark\*.dll"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: plugin/decoder Source: "..\LICENSE"; DestDir: "{app}"; DestName: "dsV2Gshark_LICENSE.txt"; Flags: ignoreversion; Source: "..\OSSAcknowledgements.txt"; DestDir: "{app}"; DestName: "dsV2Gshark_OSSAcknowledgements.txt"; Flags: ignoreversion recursesubdirs; @@ -64,6 +66,7 @@ Source: "dsV2Gshark_README.txt"; DestDir: "{app}"; DestName: "dsV2Gshark_README. Type: filesandordirs; Name: "{app}\luaV2Gdecoder.dll" Type: filesandordirs; Name: "{app}\X509CertInfos.dll" Type: filesandordirs; Name: "{app}\plugins\v2gmsg_generic.lua" +Type: filesandordirs; Name: "{app}\plugins\v2gshared.lua" [Code] function HasWriteAccessToApp: Boolean; @@ -212,10 +215,10 @@ var i: Integer; begin // check version of lua files - StringVersionPrefix := 'v2gshared.DS_V2GSHARK_VERSION = "'; + StringVersionPrefix := 'v2gcommon.DS_V2GSHARK_VERSION = "'; stringVersionSuffix := '" -- DO NOT CHANGE'; - ExtractTemporaryFile('v2gshared.lua'); - if LoadStringsFromFile(ExpandConstant('{tmp}\v2gshared.lua'), Lines) then + ExtractTemporaryFile('v2gcommon.lua'); + if LoadStringsFromFile(ExpandConstant('{tmp}\v2gcommon.lua'), Lines) then begin for i := 0 to GetArrayLength(Lines) - 1 do begin @@ -271,7 +274,7 @@ procedure CurStepChanged(CurStep: TSetupStep); var FileName: string; Lines: TArrayOfString; - StringsToCheck, StringsToAdd: TArrayOfString; + StringsToCheck, StringsToAdd, StringsToRemove: TArrayOfString; begin // add wireshark filter buttons after installation if (CurStep = ssPostInstall) then @@ -335,9 +338,13 @@ begin '"Disabled","[ISO20] Max Current EV","","#2E3436","Line","AVG(Y Field)","v2gmsg.xml.iograph.EVMaximumChargeCurrent","None","1"', '"Disabled","[ISO20] Max Voltage EVSE","","#2E3436","Line","AVG(Y Field)","v2gmsg.xml.iograph.EVSEMaximumVoltage","None","1"', '"Disabled","[ISO20] Max Current EVSE","","#2E3436","Line","AVG(Y Field)","v2gmsg.xml.iograph.EVSEMaximumChargeCurrent","None","1"', - '"Disabled","CP State","","#2E3436","Dot","AVG(Y Field)","homeplug_av.st_iotecha.cpstate.state","None","20"']; + '"Disabled","CP State","","#2E3436","Dot","AVG(Y Field)","homeplug-av-llc.cpstate","None","20"', + '"Disabled","(disabled_filter_button1)","v2gtp or v2gtlssecret or tls.handshake or tls.alert_message or tls.change_cipher_spec or tcp.flags.syn == 1 or tcp.flags.fin == 1 or homeplug or homeplug-av ","#FFFFFF","Line","Packets","","None","1"', + '"Disabled","(disabled_filter_button2)","v2gtp or v2gtlssecret","#FFFFFF","Line","Packets","","None","1"']; + StringsToRemove := ['"Disabled","CP State","","#2E3436","Dot","AVG(Y Field)","homeplug_av.st_iotecha.cpstate.state","None","20"']; if FileExists(FileName) then begin + RemoveFromFile(FileName, StringsToRemove); if not PrependStringsToFile(FileName, StringsToAdd) then MsgBox('Failed to add I/O Graph presets to Wireshark!', mbError, MB_OK); end diff --git a/README.md b/README.md index 98691d8..4b176f5 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ This Wireshark plugin allows to analyze and decode packets between electric vehi - Validation of V2G messages according to XSD specification - Certificate information details for Plug & Charge (PnC) - Live TLS decryption + - LLC diagnostics via HomePlug AV packets for sniffer and debug packets - Automatic schema detection - Detect schema automatically in case of missing SDP or SAP - Color filter for V2G packets @@ -91,3 +92,5 @@ Click on a packet in the graph to inspect it in the Wireshark main window. Press ![Plugin Preferences](Images/WS_Preferences.png) ### Wireshark I/O Graph ![I/O Graph](Images/IO_Graph.png) +### HomePlug AV LLC Diagnostics +![I/O Graph](Images/HPAV_LLC_AC.png) diff --git a/V2G_Libraries/CertificateInfos/main.rc b/V2G_Libraries/CertificateInfos/main.rc index 96cb39e..a3e03d6 100644 --- a/V2G_Libraries/CertificateInfos/main.rc +++ b/V2G_Libraries/CertificateInfos/main.rc @@ -1,11 +1,11 @@ #include -#define VER_FILEVERSION 1,3,1,0 -#define VER_FILEVERSION_STR "1.3.1.0\0" +#define VER_FILEVERSION 1,4,0,0 +#define VER_FILEVERSION_STR "1.4.0.0\0" #define VER_COMPANYNAME_STR "dSPACE GmbH" #define VER_PRODUCTNAME_STR "V2gCertificateInfos" -#define VER_PRODUCTVERSION 1,3,1,0 -#define VER_PRODUCTVERSION_STR "1.3.1.0\0" +#define VER_PRODUCTVERSION 1,4,0,0 +#define VER_PRODUCTVERSION_STR "1.4.0.0\0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION diff --git a/V2G_Libraries/V2GDecoder/main.rc b/V2G_Libraries/V2GDecoder/main.rc index 898ead2..b241f6d 100644 --- a/V2G_Libraries/V2GDecoder/main.rc +++ b/V2G_Libraries/V2GDecoder/main.rc @@ -1,11 +1,11 @@ #include -#define VER_FILEVERSION 1,3,1,0 -#define VER_FILEVERSION_STR "1.3.1.0\0" +#define VER_FILEVERSION 1,4,0,0 +#define VER_FILEVERSION_STR "1.4.0.0\0" #define VER_COMPANYNAME_STR "dSPACE GmbH" #define VER_PRODUCTNAME_STR "V2gDecoder" -#define VER_PRODUCTVERSION 1,3,1,0 -#define VER_PRODUCTVERSION_STR "1.3.1.0\0" +#define VER_PRODUCTVERSION 1,4,0,0 +#define VER_PRODUCTVERSION_STR "1.4.0.0\0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION diff --git a/Wireshark/plugins/v2gcommon.lua b/Wireshark/plugins/v2gcommon.lua new file mode 100644 index 0000000..5422663 --- /dev/null +++ b/Wireshark/plugins/v2gcommon.lua @@ -0,0 +1,33 @@ +-- +-- Copyright 2024, dSPACE GmbH. All rights reserved. +-- +-- See license file (dsV2Gshark_LICENSE.txt) +-- + +-- do OS specific stuff, required to properly load v2g libs +local plugins_path -- path to the plugins directory of this script +local lib_pattern +if package.config:sub(1, 1) == "\\" then + -- WINDOWS + plugins_path = debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])") or "./" + lib_pattern = "?.dll" +else + -- UNIX + plugins_path = debug.getinfo(1, "S").source:sub(2):match("(.*/)") or "./" + lib_pattern = "?.so" +end +local wireshark_path = plugins_path .. "../" +if not string.find(plugins_path, package.path) then + -- extend path (where to load .lua files) + package.path = package.path .. ";" .. plugins_path .. "?.lua" +end +if not string.find(wireshark_path, package.cpath) then + -- extend cpath (where to load .so files) + package.cpath = package.cpath .. ";" .. wireshark_path .. lib_pattern .. ";" .. plugins_path .. lib_pattern +end + +local v2gcommon = {} + +v2gcommon.DS_V2GSHARK_VERSION = "1.4.0" -- DO NOT CHANGE + +return v2gcommon diff --git a/Wireshark/plugins/v2gllc.lua b/Wireshark/plugins/v2gllc.lua new file mode 100644 index 0000000..0ecbe7f --- /dev/null +++ b/Wireshark/plugins/v2gllc.lua @@ -0,0 +1,183 @@ +-- +-- Copyright 2024, dSPACE GmbH. All rights reserved. +-- +-- This dissector adds functionality to the standard HomePlug AV dissector +-- to allow displaying CP State indication packets +-- +-- See license file (dsV2Gshark_LICENSE.txt) +-- +local v2gcommon = require("v2gcommon") + +p_hpav_llc = Proto("homeplug-av-llc", "HomePlug AV protocol LLC diagnostics") +local p_hpav_llc_info = { + version = v2gcommon.DS_V2GSHARK_VERSION, + author = "dSPACE GmbH", + repository = "https://github.com/dspace-group/dsV2Gshark" +} +set_plugin_info(p_hpav_llc_info) + +local f_freq = ProtoField.int16("homeplug-av-llc.freq", "Frequency", base.DEC) +local f_dutycycle = ProtoField.float("homeplug-av-llc.dutycycle", "Duty cycle", base.DEC) +local f_voltage = ProtoField.float("homeplug-av-llc.voltage", "Voltage", base.DEC) +local f_cpstate = ProtoField.int8("homeplug-av-llc.cpstate", "CP State") +local f_acmax = ProtoField.string("homeplug-av-llc.ac_max", "AC max current") +local f_result = ProtoField.string("homeplug-av-llc.result", "Result") + +p_hpav_llc.fields = {f_freq, f_dutycycle, f_voltage, f_cpstate, f_acmax, f_result} + +local function extract_infos_spidcom(buf) + local freq = buf(9, 2):le_int() + local dutycycle = buf(11, 2):le_int() / 10 + local voltage = buf(13, 2):le_int() / 1000 + local result = buf(8, 1):int() + return freq, dutycycle, voltage, result +end + +local function extract_infos_iotecha(buf) + local freq = buf(15, 2):le_int() + local dutycycle = buf(14, 1):le_int() + local voltage = buf(17, 2):le_int() / 1000 + return freq, dutycycle, voltage, -1 +end + +local function get_ac_max_current(dutycycle) + if dutycycle < 8 then + return -1 + elseif dutycycle < 10 then + return 6 + elseif dutycycle < 85 then + return dutycycle * 0.6 + elseif dutycycle < 96 then + return (dutycycle - 64) * 2.5 + elseif dutycycle < 97 then + return 80 + else + return -1 + end +end + +local function get_cp_state(freq, dutycycle, voltage) + local StateA = 12 + local StateB = 9 + local StateC = 6 + local StateD = 3 + local StateEF = 0 + local Tolerance = 1 + + if (dutycycle == 0 or dutycycle == 100) and freq > 0 then + return "-" + end + + local cp_state_out + if voltage <= (StateA + Tolerance) and voltage >= (StateA - Tolerance) then + cp_state_out = "A" + elseif voltage <= (StateB + Tolerance) and voltage >= (StateB - Tolerance) then + cp_state_out = "B" + elseif voltage <= (StateC + Tolerance) and voltage >= (StateC - Tolerance) then + cp_state_out = "C" + elseif voltage <= (StateD + Tolerance) and voltage >= (StateD - Tolerance) then + cp_state_out = "D" + elseif voltage <= (StateEF + Tolerance) then + return "E/F" + else + return "-" + end + + local pwm_active = dutycycle > 0 and dutycycle < 100 and freq > 950 and freq < 1050 + if pwm_active then + return cp_state_out .. "2" + else + return cp_state_out .. "1" + end +end + +local function cp_state_to_int(cp_state) + --- used for I/O Graph plotting of CP State + if cp_state == "A1" then + return 1 + elseif cp_state == "A2" then + return 2 + elseif cp_state == "B1" then + return 3 + elseif cp_state == "B2" then + return 4 + elseif cp_state == "C1" then + return 5 + elseif cp_state == "C2" then + return 6 + elseif cp_state == "D1" then + return 7 + elseif cp_state == "D2" then + return 8 + elseif cp_state == "E/F" then + return -1 + end + return 0 +end + +function p_hpav_llc.dissector(buf, pinfo, root) + if buf:len() == 0 then + return 0 + end + + -- always call default homeplug-av dissector first + local hpav_dissector = Dissector.get("homeplug-av") + local consumed_bytes_hpav + if hpav_dissector ~= nil then + consumed_bytes_hpav = hpav_dissector:call(buf, pinfo, root) + else + -- some older wireshark versions does not have a homeplug-av dissector + consumed_bytes_hpav = Dissector.get("data"):call(buf, pinfo, root) + pinfo.cols.info = "Homeplug AV" + end + + local mac_mme_type = buf(1, 2):le_uint() + local mme_vendor = buf(5, 3):uint() + local freq, dutycycle, voltage, result + if mme_vendor == 0x0013D7 and mac_mme_type == 0xA10E then -- Vendor OUI: SPIDCOM Technologies SA + freq, dutycycle, voltage, result = extract_infos_spidcom(buf) + elseif mme_vendor == 0x0080E1 and mac_mme_type == 0xA22E then -- Vendor OUI: ST/IoTecha + freq, dutycycle, voltage, result = extract_infos_iotecha(buf) + else + -- default homeplug-av packet + return consumed_bytes_hpav + end + + pinfo.cols.protocol = "HomePlug AV LLC" + local subtree = root:add(p_hpav_llc, buf(0)) + + local elem_frequency = subtree:add(f_freq, freq) + elem_frequency:append_text("Hz") + -- frequency bitmask: 001 + if result == 1 or result == 3 or result == 5 or result == 7 then + elem_frequency:append_text(" (changed)") + end + + local elem_dutycycle = subtree:add(f_dutycycle, dutycycle) + elem_dutycycle:append_text("%") + -- duty cycle bitmask: 010 + if result == 2 or result == 3 or result == 6 or result == 7 then + elem_dutycycle:append_text(" (changed)") + end + + local elem_voltage = subtree:add(f_voltage, voltage) + elem_voltage:append_text("V") + -- voltage bitmask: 100 + if result == 4 or result == 5 or result == 6 or result == 7 then + elem_voltage:append_text(" (changed)") + end + + local cp_state = get_cp_state(freq, dutycycle, voltage) + subtree:add(f_cpstate, cp_state_to_int(cp_state)):set_text("CP State: " .. cp_state) -- store as int to allow plotting + + local ac_max_current = get_ac_max_current(dutycycle) + if ac_max_current ~= -1 then + subtree:add(f_acmax, ac_max_current):append_text("A") + pinfo.cols.info = "CP State: " .. cp_state .. " [AC max current: " .. ac_max_current .. "A]" + else + pinfo.cols.info = "CP State: " .. cp_state + end + return buf:len() +end + +DissectorTable.get("ethertype"):add(0x88e1, p_hpav_llc) diff --git a/Wireshark/plugins/v2gmsg.lua b/Wireshark/plugins/v2gmsg.lua index ac837da..4601e1e 100644 --- a/Wireshark/plugins/v2gmsg.lua +++ b/Wireshark/plugins/v2gmsg.lua @@ -11,35 +11,14 @@ -- See license file (dsV2Gshark_LICENSE.txt) -- --- do OS specific stuff, required to properly load v2g libs -local plugins_path -- path to the plugins directory of this script -local lib_pattern -if package.config:sub(1, 1) == "\\" then - -- WINDOWS - plugins_path = debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])") or "./" - lib_pattern = "?.dll" -else - -- UNIX - plugins_path = debug.getinfo(1, "S").source:sub(2):match("(.*/)") or "./" - lib_pattern = "?.so" -end -local wireshark_path = plugins_path .. "../" -if not string.find(plugins_path, package.path) then - -- extend path (where to load .lua files) - package.path = package.path .. ";" .. plugins_path .. "?.lua" -end -if not string.find(wireshark_path, package.cpath) then - -- extend cpath (where to load .so files) - package.cpath = package.cpath .. ";" .. wireshark_path .. lib_pattern .. ";" .. plugins_path .. lib_pattern -end - -local v2gshared = require("v2gshared") +local v2gcommon = require("v2gcommon") p_v2gmsg = Proto("v2gmsg", "V2G Message") local p_v2gmsg_info = { - version = v2gshared.DS_V2GSHARK_VERSION, + version = v2gcommon.DS_V2GSHARK_VERSION, author = "dSPACE GmbH", - description = "Dissector for V2G Messages (DIN 70121, ISO15118-2, ISO15118-20)" + description = "Dissector for V2G Messages (DIN 70121, ISO15118-2, ISO15118-20)", + repository = "https://github.com/dspace-group/dsV2Gshark" } set_plugin_info(p_v2gmsg_info) @@ -93,7 +72,7 @@ local values_to_plot = { "EVSEMaximumChargeCurrent" } local f_plot_fields = {} -- maps value name to iograph-field -for k, value in pairs(values_to_plot) do +for _, value in pairs(values_to_plot) do f_plot_fields[value] = ProtoField.double("v2gmsg.xml.iograph." .. value, "I/O Graph Value") table.insert(p_v2gmsg.fields, f_plot_fields[value]) end @@ -133,8 +112,7 @@ function p_v2gmsg.init() end local function decode_v2g_message(schema, exi_string, packet_number) - local xml_out - local xml_schema + local xml_out, xml_schema, errn decoded_with_auto_schema_detection[packet_number] = false xml_out, xml_schema, errn = v2g_decoder.decodeV2GExi(schema, exi_string) @@ -424,7 +402,7 @@ function p_v2gmsg.dissector(buf, pinfo, root) pinfo, ef_error_generic ) - return + return buf:len() end local message_name = get_message_name(xml_data) @@ -475,7 +453,7 @@ function p_v2gmsg.dissector(buf, pinfo, root) pinfo, ef_error_generic ) - return + return buf:len() end -- get the message name and write it to the info cols @@ -553,4 +531,5 @@ function p_v2gmsg.dissector(buf, pinfo, root) add_xml_table_to_tree(parse_XML(xml_data), subtree, f_entry, pinfo) end end + return buf:len() end diff --git a/Wireshark/plugins/v2gsdp.lua b/Wireshark/plugins/v2gsdp.lua index 90acffb..3675d1a 100644 --- a/Wireshark/plugins/v2gsdp.lua +++ b/Wireshark/plugins/v2gsdp.lua @@ -4,13 +4,14 @@ -- -- See license file (dsV2Gshark_LICENSE.txt) -- -local v2gshared = require("v2gshared") +local v2gcommon = require("v2gcommon") p_sdpreq = Proto("v2gsdp-req", "V2G SECC Discovery Protocol Request") p_sdpres = Proto("v2gsdp-res", "V2G SECC Discovery Protocol Response") local p_v2gsdp_info = { - version = v2gshared.DS_V2GSHARK_VERSION, - author = "dSPACE GmbH" + version = v2gcommon.DS_V2GSHARK_VERSION, + author = "dSPACE GmbH", + repository = "https://github.com/dspace-group/dsV2Gshark" } set_plugin_info(p_v2gsdp_info) @@ -34,7 +35,7 @@ function p_sdpreq.dissector(buf, pinfo, root) pinfo.cols.protocol = "V2GMSG (SDP)" -- create subtree - subtree = root:add(p_sdpreq, buf(0)) + local subtree = root:add(p_sdpreq, buf(0)) -- add protocol fields to subtree @@ -116,4 +117,5 @@ function p_sdpres.dissector(buf, pinfo, root) if selected_schema_at_packet_nr ~= nil then selected_schema_at_packet_nr[pinfo.number] = "urn:iso:15118:2:2010:AppProtocol" end + return buf:len() end diff --git a/Wireshark/plugins/v2gshared.lua b/Wireshark/plugins/v2gshared.lua deleted file mode 100644 index 487a4f6..0000000 --- a/Wireshark/plugins/v2gshared.lua +++ /dev/null @@ -1,10 +0,0 @@ --- --- Copyright 2024, dSPACE GmbH. All rights reserved. --- --- See license file (dsV2Gshark_LICENSE.txt) --- -local v2gshared = {} - -v2gshared.DS_V2GSHARK_VERSION = "1.3.1" -- DO NOT CHANGE - -return v2gshared diff --git a/Wireshark/plugins/v2gtlssecret.lua b/Wireshark/plugins/v2gtlssecret.lua index bcacb98..773d023 100644 --- a/Wireshark/plugins/v2gtlssecret.lua +++ b/Wireshark/plugins/v2gtlssecret.lua @@ -5,12 +5,13 @@ -- -- See license file (dsV2Gshark_LICENSE.txt) -- -local v2gshared = require("v2gshared") +local v2gcommon = require("v2gcommon") p_v2gtlssecret = Proto("v2gtlssecret", "V2G TLS secret") local p_v2gtlssecret_info = { - version = v2gshared.DS_V2GSHARK_VERSION, - author = "dSPACE GmbH" + version = v2gcommon.DS_V2GSHARK_VERSION, + author = "dSPACE GmbH", + repository = "https://github.com/dspace-group/dsV2Gshark" } set_plugin_info(p_v2gtlssecret_info) @@ -26,7 +27,7 @@ p_v2gtlssecret.prefs["portrange_tlssecret"] = 65535 ) p_v2gtlssecret.prefs["additionalinfo3"] = Pref.statictext("") -p_v2gtlssecret.prefs["versioninfo"] = Pref.statictext("Version " .. v2gshared.DS_V2GSHARK_VERSION) +p_v2gtlssecret.prefs["versioninfo"] = Pref.statictext("Version " .. v2gcommon.DS_V2GSHARK_VERSION) local min_wireshark_version = "3.5.0" @@ -56,8 +57,8 @@ p_v2gtlssecret.experts = {ef_io_error, ef_bad_version} -- verify tshark/wireshark version is compatible local function check_version(required_version) - major_req, minor_req, micro_req = required_version:match("(%d+)%.(%d+)%.(%d+)") - major, minor, micro = get_version():match("(%d+)%.(%d+)%.(%d+)") + local major_req, minor_req, micro_req = required_version:match("(%d+)%.(%d+)%.(%d+)") + local major, minor, micro = get_version():match("(%d+)%.(%d+)%.(%d+)") if (tonumber(major) < tonumber(major_req)) or @@ -90,11 +91,11 @@ end -- PDU dissection function function p_v2gtlssecret.dissector(buf, pinfo, root) local str = buf:raw() - local tls_secret_list = {} + local tls_secret_list = {} -- stores secret string [1] and start position in payload [2] local info_strings = {} -- one UDP packet may contain several lines, check each line - for line in str:gmatch "[^\r\n]+" do + for startpos, line in str:gmatch "()([^\r\n\0]+)" do -- check if this is really a secret local match = line:match "^([%u_]+)%d* %x+ %x+$" if match == nil then @@ -114,7 +115,7 @@ function p_v2gtlssecret.dissector(buf, pinfo, root) end -- one last plausibility check if line:len() > 100 and line:len() < 300 then - table.insert(tls_secret_list, line) + table.insert(tls_secret_list, {line, startpos}) end end @@ -122,11 +123,9 @@ function p_v2gtlssecret.dissector(buf, pinfo, root) return 0 end - local byte_offset = 0 local subtree = root:add(p_v2gtlssecret, buf(byte_offset)) for _, v in ipairs(tls_secret_list) do - subtree:add(f_cr, buf(byte_offset, v:len())) - byte_offset = byte_offset + v:len() + 1 -- (+1) for line break + subtree:add(f_cr, buf(v[2] - 1, v[1]:len())) end -- set info column @@ -135,7 +134,7 @@ function p_v2gtlssecret.dissector(buf, pinfo, root) if check_version(min_wireshark_version) == false then subtree:add_proto_expert_info(ef_bad_version) pinfo.cols.info = "[ERROR]" .. tostring(pinfo.cols.info) - return + return buf:len() end -- check if path to 'keylog_file' is not set, use default path defined in this script @@ -162,7 +161,7 @@ function p_v2gtlssecret.dissector(buf, pinfo, root) for idx = #tls_secret_list, 1, -1 do local to_be_removed = false - local splitted_from_packet = split_string(tls_secret_list[idx]) + local splitted_from_packet = split_string(tls_secret_list[idx][1]) for line in file_content:gmatch "[^\r\n]+" do local splitted_from_file = split_string(tostring(line)) if #splitted_from_packet == 3 and #splitted_from_file == 3 then @@ -200,7 +199,7 @@ function p_v2gtlssecret.dissector(buf, pinfo, root) add_expert_info(err_str, subtree, pinfo, ef_io_error) else for _, tls_secret in ipairs(tls_secret_list) do - file:write(tls_secret .. "\n") + file:write(tls_secret[1] .. "\n") end table.insert(frame_numbers, pinfo.number) -- add frame number to table file:close(file) @@ -214,6 +213,7 @@ function p_v2gtlssecret.dissector(buf, pinfo, root) end end end -- end if 'already_visited' + return buf:len() end -- end function 'p_v2gtlssecret.dissector' -- initialization routine diff --git a/Wireshark/plugins/v2gtp.lua b/Wireshark/plugins/v2gtp.lua index c92210c..ce676bd 100644 --- a/Wireshark/plugins/v2gtp.lua +++ b/Wireshark/plugins/v2gtp.lua @@ -4,12 +4,13 @@ -- -- See license file (dsV2Gshark_LICENSE.txt) -- -local v2gshared = require("v2gshared") +local v2gcommon = require("v2gcommon") p_v2gtp = Proto("v2gtp", "V2G Transfer Protocol") local p_v2gtp_info = { - version = v2gshared.DS_V2GSHARK_VERSION, - author = "dSPACE GmbH" + version = v2gcommon.DS_V2GSHARK_VERSION, + author = "dSPACE GmbH", + repository = "https://github.com/dspace-group/dsV2Gshark" } set_plugin_info(p_v2gtp_info) @@ -25,7 +26,7 @@ p_v2gtp.prefs["portrange_v2g"] = 65535 ) p_v2gtp.prefs["additionalinfo3"] = Pref.statictext("") -p_v2gtp.prefs["versioninfo"] = Pref.statictext("Version " .. v2gshared.DS_V2GSHARK_VERSION) +p_v2gtp.prefs["versioninfo"] = Pref.statictext("Version " .. v2gcommon.DS_V2GSHARK_VERSION) local V2GTP_HDR_LENGTH = 8 @@ -129,39 +130,41 @@ local function v2gtp_pdu_dissect(buf, pinfo, root) -- if buf:len() > V2GTP_HDR_LENGTH then if p_type_num == SDP_REQ then - Dissector.get("v2gsdp-req"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gsdp-req"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == SDP_RES then - Dissector.get("v2gsdp-res"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gsdp-res"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == V2G then -- do not set schema for 8001 payloads, s.t. it is derived from the SAP - Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == I20_MAIN then pinfo.private["Schema"] = "urn:iso:std:iso:15118:-20:CommonMessages" - Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == I20_AC then pinfo.private["Schema"] = "urn:iso:std:iso:15118:-20:AC" - Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == I20_DC then pinfo.private["Schema"] = "urn:iso:std:iso:15118:-20:DC" - Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == I20_ACDP then pinfo.private["Schema"] = "urn:iso:std:iso:15118:-20:ACDP" - Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == I20_WPT then pinfo.private["Schema"] = "urn:iso:std:iso:15118:-20:WPT" - Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == I20_SCHEDULE_RENEG then -- the schema must be derived from the SAP in this case. TODO: test this as soon as sidestreams are used - Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == I20_METER_CONF then pinfo.private["Schema"] = "urn:iso:std:iso:15118:-20:CommonMessages" -- Meter Conf Sidestream uses common messages only - Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == I20_ACDP_SYS_STATUS then pinfo.private["Schema"] = "urn:iso:std:iso:15118:-20:ACDP" - Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) elseif p_type_num == I20_PARKING_STATUS then pinfo.private["Schema"] = "urn:iso:std:iso:15118:-20:CommonMessages" - Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + return Dissector.get("v2gmsg"):call(buf(V2GTP_HDR_LENGTH):tvb(), pinfo, root) + else + return 0 end end end diff --git a/update_version.bat b/update_version.bat index 8c24f01..6fda915 100644 --- a/update_version.bat +++ b/update_version.bat @@ -29,15 +29,15 @@ for /F delims^=^ eol^= %%A in ('%SystemRoot%\System32\findstr.exe /N "^" "%FileN ) >>"%TempFile%" move /y %TempFile% %FileName% -:: update v2gshared.lua -set "FileName=.\Wireshark\plugins\v2gshared.lua" +:: update v2gcommon.lua +set "FileName=.\Wireshark\plugins\v2gcommon.lua" del "%TempFile%" 2>nul for /F delims^=^ eol^= %%A in ('%SystemRoot%\System32\findstr.exe /N "^" "%FileName%"') do ( set "Line=%%A" setlocal EnableDelayedExpansion - if not "!Line:v2gshared.DS_V2GSHARK_VERSION=!" == "!Line!" ( + if not "!Line:v2gcommon.DS_V2GSHARK_VERSION=!" == "!Line!" ( if not "!Line:DO NOT CHANGE=!" == "!Line!" ( - echo v2gshared.DS_V2GSHARK_VERSION = "%newVersion%" -- DO NOT CHANGE + echo v2gcommon.DS_V2GSHARK_VERSION = "%newVersion%" -- DO NOT CHANGE ) else echo(!Line:*:=! ) else echo(!Line:*:=! endlocal