-- CSPv4 Parser -------------------------------- -- -- Date: July 25, 2012 -- Author: Erik Schweigert -- E-mail: erik@lainoox.com -- -- Purpose: To decode the CSPv4 Packet -- CSPv4 + LSAP + PCCC ------------------------------------------------ p_cspv4 = Proto("cspv4","CSPv4") p_lsap = Proto("lsap","LSAP") p_pccc = Proto("pccc","PCCC") -- ----------------- CSPv4 Header ------------ local f_mode = ProtoField.uint8("cspv4.mode", "Mode", base.HEX) local f_submode = ProtoField.uint8("cspv4.submode", "Submode", base.HEX) local f_data_length = ProtoField.uint16("cspv4.data_length", "Data Length", base.HEX) local f_conn_id = ProtoField.uint32("cspv4.conn_id", "Connection ID [slave/server]", base.HEX) local f_status = ProtoField.uint32("cspv4.status", "Status", base.HEX) local f_context = ProtoField.bytes("cspv4.context", "Context", base.HEX) -- ---------------- End CSPv4 Header ----------- -- ------------------ LSAP --------------------- -- Local local f_dest = ProtoField.uint8("cspv4.dst", "Destination Byte", base.HEX) local f_res5 = ProtoField.uint8("cspv4.res5", "Control Byte", base.HEX) local f_src = ProtoField.uint8("cspv4.src", "Source Byte [Master Address]", base.HEX) local f_lsap = ProtoField.uint8("cspv4.lsap", "LSAP", base.HEX) -- Remote local f_resX = ProtoField.uint8("cspv4.resX", "Mystery Byte", base.HEX) local f_dst_link = ProtoField.uint16("cspv4.dst_link","Destination Link Address", base.HEX) local f_dst_station = ProtoField.uint16("cspv4.dst_station", "Destination Station Address", base.HEX) local f_resY = ProtoField.uint8("cspv4.resY", "Mystery Byte 2", base.HEX) local f_src_link = ProtoField.uint16("cspv4.src_link", "Source Link Address", base.HEX) local f_src_station = ProtoField.uint16("cspv4.src_station", "Source Station Address", base.HEX) local f_resZ = ProtoField.uint8("cspv4.resZ", "Mystery Byte 3", base.HEX) -- ------------------ End LSAP ------------------ -- ------------------ PCCC ---------------------- local f_pccc_command = ProtoField.uint8("cspv4.pccc_command", "Command Code", base.HEX) local f_pccc_sts = ProtoField.uint8("cspv4.pccc_sts", "Status Code", base.HEX) local f_pccc_tns = ProtoField.uint16("cspv4.pccc_tns", "Transaction Number", base.HEX) local f_pccc_fnc = ProtoField.uint8("cspv4.pccc_fnc", "Function Code", base.HEX) local f_pccc_addr = ProtoField.uint16("cspv4.pccc_addr", "Address of Memory Location", base.HEX) local f_pccc_size = ProtoField.uint8("cspv4.pccc_size", "Size", base.HEX) local f_pccc_data = ProtoField.bytes("cspv4.pccc_data", "Data", base.HEX) -- ------------------ End PCCC ------------------- -- CSPv4 Fields p_cspv4.fields = {f_mode} p_cspv4.fields = {f_submode} p_cspv4.fields = {f_data_length} p_cspv4.fields = {f_conn_id} p_cspv4.fields = {f_status} p_cspv4.fields = {f_context} p_cspv4.fields = {f_dest} p_cspv4.fields = {f_res5} p_cspv4.fields = {f_src} p_cspv4.fields = {f_lsap} -- Remote LSAP Fields p_cspv4.fields = {f_resX} p_cspv4.fields = {f_dst_link} p_cspv4.fields = {f_dst_station} p_cspv4.fields = {f_resY} p_cspv4.fields = {f_src_link} p_cspv4.fields = {f_src_station} p_cspv4.fields = {f_resZ} -- PCCC Fields p_cspv4.fields = {f_pccc_command} p_cspv4.fields = {f_pccc_sts} p_cspv4.fields = {f_pccc_tns} p_cspv4.fields = {f_pccc_fnc} p_cspv4.fields = {f_pccc_addr} p_cspv4.fields = {f_pccc_size} p_cspv4.fields = {f_pccc_data} function build_cspv4_header(buf) build_request(buf) build_submode(buf) subtree:add(f_data_length, buf(2,2)) subtree:add(f_conn_id, buf(4,4)) subtree:add(f_status, buf(8,4)) subtree:add(f_context, buf(12,16)) end function build_request(buf) if buf(0,1):uint() == 1 then subtree:add(f_mode, buf(0,1)):append_text(" (Request)") elseif buf(0,1):uint() == 2 then subtree:add(f_mode, buf(0,1)):append_text(" (Response)") else subtree:add(f_mode, buf(0,1)) end end function build_submode(buf) if buf(1,1):uint() == 1 then subtree:add(f_submode, buf(1,1)):append_text(" (Connection)") elseif buf(1,1):uint() == 7 then subtree:add(f_submode, buf(1,1)):append_text(" (PCCC)") else subtree:add(f_submode, buf(1,1)) end end function build_lsap(buf, root) lsap_tree = root:add(p_lsap, buf(28)) lsap_tree:add(f_dest, buf(28,1)) lsap_tree:add(f_res5, buf(29,1)) lsap_tree:add(f_src, buf(30,1)) if buf(31,1):uint() == 0 then lsap_tree:add(f_lsap, buf(31,1)):append_text(" (Local Form)") elseif buf(31,1):uint() == 1 then lsap_tree:add(f_lsap, buf(31,1)):append_text(" (Remote Form)") build_lsap_remote(buf, lsap_tree) else lsap_tree:add(f_lsap, buf(31,1)) end end function build_lsap_remote(buf, lsap_tree) lsap_tree:add(f_resX, buf(32,1)) lsap_tree:add(f_dst_link, buf(33,2)) lsap_tree:add(f_dst_station, buf(35,2)) lsap_tree:add(f_resY, buf(37,1)) lsap_tree:add(f_src_link, buf(38,2)) lsap_tree:add(f_src_station, buf(40,2)) lsap_tree:add(f_resZ, buf(42,1)) end function build_pccc(buf, root) pccc_tree = root:add(p_pccc, buf(32)) -- Ensure its PCCCC if buf(1,1):uint() ~= 7 then end if buf(31,1):uint() == 1 then offset = 11 else offset = 0 end pccc_tree:add(f_pccc_command, buf(32 + offset, 1)) pccc_tree:add(f_pccc_sts, buf(33 + offset, 1)) pccc_tree:add(f_pccc_tns, buf(34 + offset, 2)) pccc_tree:add(f_pccc_fnc, buf(36 + offset, 1)) pccc_tree:add(f_pccc_addr, buf(37 + offset, 2)) pccc_tree:add(f_pccc_size, buf(39 + offset, 1)) pccc_tree:add(f_pccc_data, buf(40 + offset, buf:len() - (40 + offset))) end -- cspv4 dissector function function p_cspv4.dissector (buf, pkt, root) -- validate packet length is adequate, otherwise quit if buf:len() == 0 then return end pkt.cols.protocol = p_cspv4.name -- create subtree for cspv4 subtree = root:add(p_cspv4, buf(0)) -- add protocol fields to subtree build_cspv4_header(buf) build_lsap(buf, root) build_pccc(buf, root) -- description of payload subtree:set_text("CSPv4, CSPv4 Header Information") -- add debug info if debug field is not nil if f_debug then -- write debug values subtree:add(f_debug, buf:len()) end end -- Initialization routine function p_cspv4.init() end -- register a chained dissector for port 2222 local tcp_dissector_table = DissectorTable.get("tcp.port") dissector = tcp_dissector_table:get_dissector(2222) -- you can call dissector from function p_cspv4.dissector above -- so that the previous dissector gets called tcp_dissector_table:add(2222, p_cspv4)