↓ModBus/RTUの時に書いた
UDPを解析する機会があったのでWiresharkのLuaを作った件
Luaの作成
大半は1個目の参考URL様をベースとして作成しました。
作り方の詳細は各URLを参考にしてください。
作ったまま乗せるのはあれなので適当にアレンジして載せます。
(動作確認しましたが、bufferの位置とか間違ってるかもしれません、、
-- (1)独自プロトコルの定義
-- Org.lua
OrgProto = Proto.new("Org", "Org DATA PACKET")
-- (2)プロトコルフィールドの定義
f_ContData1 = ProtoField.new("Frame Bytes" , "Org.frame" , ftypes.UINT16 , nil)
f_ContData2 = ProtoField.new("Version" , "Org.ver" , ftypes.UINT8 , nil, base.DEC_HEX)
f_ContData3 = ProtoField.new("Reserved1" , "Org.Reserved1" , ftypes.UINT8 , nil, base.DEC_HEX, 0x03)
f_ContData4 = ProtoField.new("Reserved2" , "Org.Reserved2" , ftypes.UINT8 , nil, base.DEC_HEX, 0x60)
f_ContData5 = ProtoField.new("データ数" , "Org.datasize" , ftypes.UINT16 , nil)
f_ContData6 = ProtoField.new("DATA_ID" , "Org.dataid" , ftypes.UINT32 , nil)
f_ContData7 = ProtoField.new("DATA" , "Org.data" , ftypes.FLOAT , nil)
f_ContData8 = ProtoField.new("TIME" , "Org.time" , ftypes.UINT64, nil)
-- (3)定義したプロトコルフィールドをプロトコルフィールド配列に登録
OrgProto.fields = {f_ContData1, f_ContData2, f_ContData3, f_ContData4, f_ContData5,f_ContData6,f_ContData7,f_ContData8}
-- (4)dissector関数の定義
function OrgProto.dissector(buffer, pinfo, tree)
-- (5)dissector関数内で使用するローカル変数の定義及びbufferからの値の取得
local ContData1 = buffer(0, 2):uint()
local ContData2 = buffer(2, 1):uint()
local ContData3 = buffer(3, 1):uint()
local ContData4 = buffer(3, 1):uint()
local ContData5 = buffer(4, 2):uint()
local ContData6 = buffer(6, 4):uint()
local ContData7 = buffer(10, 8):float()
local ContData8 = buffer(18, 8):uint64()
-- (6)プロトコル情報を設定
-- "Protocol"列の表示
pinfo.cols.protocol = "Org protocol"
-- "info"列の表示
pinfo.cols.info = "Frame Bytes:" .. ContData1 .. " データ数:" .. ContData5.. " データ 1:" .. ContData7
-- (7)treeに"Original Protocol"の情報を追加
-- treeにサブツリーとして"Original Protocol"を追加
local subtree = tree:add( OrgProto, buffer() )
-- サブツリー内に上記で定義した各プロトコルフィールドの値を追加
subtree:add( f_ContData1, buffer(0, 2) )
subtree:add( f_ContData2, buffer(2, 1) , buffer(2, 1):uint(), "Version: " .. buffer(2, 1):uint() .. string.format("", buffer(2, 1):uint()) .. "(0 :Version A)")
subtree:add( f_ContData3, buffer(3, 1) )
subtree:add( f_ContData4, buffer(3, 1) )
subtree:add( f_ContData5, buffer(4, 2) )
local datalen = buffer:len() - 6
local subtree2=subtree:add(buffer(6,datalen), "DATA" )
-- データ数分ループする
local i = 1
local offset =6
for i = 1,ContData5 do
offset =20*(i-1)
subtree2:add( f_ContData6, buffer(6+offset,4), buffer(6+offset,4):uint(), "DATA_ID:" .. buffer(6+offset,4):uint() .. string.format("(0x%04x)", buffer(6+offset,4):uint()) .. " ")
subtree2:add( f_ContData7, buffer(6+4+offset,8), buffer(6+4+offset,8):float(), "DATA:" .. buffer(6+4+offset,8):float() )
local timestamp = buffer(6+12+offset,8):uint64()
-- UNIX時間(秒)に変換
local unix_time = timestamp / 1000
local formatted_time = os.date("!%Y-%m-%d %H:%M:%S", tostring(unix_time))
-- local time zone of the system
-- local formatted_time = os.date("%Y-%m-%d %H:%M:%S", tostring(unix_time))
subtree2:add( f_ContData8,buffer(6+12+offset,8), buffer(6+12+offset,8):uint64(), "TIME: " .. formatted_time)
end
end
-- (8)定義したプロトコルをUDPポート番号を指定した紐づけ
udp_table = DissectorTable.get("udp.port")
udp_table:add(9898, OrgProto)
作成時困ったことは時間の所くらいです。
msで入っていたので秒に変換してosdateで表示
システムのtime zoneで表示したいときはコメントアウトしているところを使用
一つのパケットに複数のデータを送れるようになっていたので
データ数を見てループしました。
使い方
wireshark\pluginsに入れて起動する
動作
UDPの送信はUDP/IPテストツールをお借りして模擬的に送信しました。
送ったデータは適当です。
参考URL