wirshark lua: 横跨多包解析方法,混搭tap与postdissector解析器(RTP timestamp差值为例)

在分析抓包时,有时需要横跨多个包计算,比如计算所有RTP包的timestamp与之前RTP包的timestamp的差值,这样可以一目了然看出timestamp是否有异常波动。

理想方式是把这个计算出来的差值直接放到RTP信息后面,但wireshark lua目前没有提供可以在某协议dissector解析完后调用自己lua写的dissector的方法,除了http body可借助一些特殊的table实现,可参考《如何在wireshark里用lua脚本编写dissector解析HTTP BODY (after TCP reassembled) 》(http://blog.csdn.net/jasonhwang/article/details/5526383),其它协议必须借助替换tcp或udp端口,在自己的dissector里先调用标准的dissector,再调用自己的代码的所谓chained dissectors方式。一旦协议端口变化,这种方式就很不方便。

我这边用一个tap加postdissector的方式实现计算RTP timestamp相邻包增量值的目的。程序的基本方案是:

  1. 首先用tap注册到解析所有rtp包,在分析过程中,按rtp不同流的方式,各自保存上一个rtp包的timestamp值,然后与当前rtp包算出差值后再把信息记录到一个table(map以seq为键值)里;
  2. 然后用户可以通过Tools->Lua->RTP Timestamp Delta菜单打开一个文本窗口浏览所有rtp包的timestamp与上一个rtp timestamp的差值统计表;
  3. 用户也可以点击某个rtp包,触发wireshark调用postdissector去显示当前rtp包timestamp与上一个包的差值(从tap统计的结果变量里直接去取)。

 

这个例子使用价值可能不高,但可以学到以下几方面知识:

  1. tap是可以在打开wireshark时就可被调用的,不像wireshark lua例子里的tap一样,只在打开TextWindow时才可对之后的抓包起作用;
  2. postdissector不是在解析完一个包后立即执行,而是在点击某个packet记录后才被调用;
  3. 一个抓包里多个RTP的请求(RTSP Interleaved模式)可以用外加table方式或取某变量参数的所有值。

代码如下:

-- Display RTP timestamp delta between current RTP pack and last RTP pack.
-- Author: Huang Qiangxiong (qiangxiong.huang@gmail.com)
-- change log:
--      2012-03-01
--          Just can play.
------------------------------------------------------------------------------------------------
do
-------------
-- tap for saving each RTP timestamp delta value in rtp variables, you can also
-- check the all delta values by menu: tap->RTP Timestamp Delta
-------------
    -- for saving all rtp streams info
    local rtp_streams = {}
    local f_rtp_ssrc = Field.new("rtp.ssrc")
    local f_rtp_timestamp = Field.new("rtp.timestamp")
    local f_rtp_pt = Field.new("rtp.p_type")
    local f_rtp_seq = Field.new("rtp.seq")
    local f_rtp_marker = Field.new("rtp.marker")
    
	local myrtptap = Listener.new(tap, "rtp");
    
    function getkey(ssrc, pt, pinfo)
        return ssrc .. pt .. tostring(pinfo.src) .. pinfo.src_port .. tostring(pinfo.dst) .. pinfo.dst_port
    end

    -- this function will be called once for each packet
    function myrtptap.packet(pinfo,tvb)
        -- using table because one packet may contains 
        -- more than one RTP packets
        local rtp_ssrc = { f_rtp_ssrc() }
        local rtp_pt = { f_rtp_pt() }
        local rtp_timestamp = { f_rtp_timestamp() }
        local rtp_seq = { f_rtp_seq() }
        local rtp_marker = { f_rtp_marker() }
        
        for i,ssrc_f in ipairs(rtp_ssrc) do
            local ssrc = ssrc_f.value
            local pt = rtp_pt[i].value
            local cur_timestamp = rtp_timestamp[i].value
            local seq = rtp_seq[i].value
            local marker = rtp_marker[i].value
            
            local key = getkey(ssrc, pt, pinfo)
        
            local rtp_stream = rtp_streams[key]
            if not rtp_stream then 
                rtp_stream = {}
                rtp_stream.pk_infos = {}
                rtp_stream.ssrc = ssrc
                rtp_stream.pt = pt
                rtp_stream.last_timestamp = cur_timestamp
                rtp_streams[key] = rtp_stream
            end
            
            -- add current rtp packet info to rtp stream
            local rtp_info = {}
            rtp_info.pkno = pinfo.number
            rtp_info.timestamp = cur_timestamp
            rtp_info.seq = seq
            rtp_info.marker = marker
            rtp_info.delta = cur_timestamp - rtp_stream.last_timestamp
            
            rtp_stream.pk_infos[seq] = rtp_info

            rtp_stream.last_timestamp = cur_timestamp
        end
	end

	-- this function will be called whenever a reset is needed
	-- e.g. when reloading the capture file
	function myrtptap.reset()
        rtp_streams = {}
	end
        
	local function menuable_myrtptap()
		-- Declare the window we will use
		local tw = TextWindow.new("Display RTP Timestamp Delta")        
        
        local text = "All RTP Stream Info:\n"
        for key,rtp_stream in pairs(rtp_streams) do
            text = text .. "\nRTP Stream (ssrc=" .. rtp_stream.ssrc .. " payload_type=" .. rtp_stream.pt .. " rtp_packets=" .. #rtp_stream.pk_infos .. "):\n"
            -- print infos order by seq
            local keys = {}
            for seq in pairs(rtp_stream.pk_infos) do
                table.insert(keys, seq)
            end
            table.sort(keys) 
            for i,seq in ipairs(keys) do
                local rtp_info = rtp_stream.pk_infos[seq]
                local marker = ""
                if rtp_info.marker then marker = "set" end
                text = text .. "\tpack_no: " .. rtp_info.pkno .. " \tseq: " .. seq .. " \ttimestamp: " .. rtp_info.timestamp .. " \tdelta: " .. rtp_info.delta .. "\tmarker: " .. marker .. "\n"
            end
        end

        tw:append(text)
	end

    register_menu("Lua/RTP Timestamp Delta", menuable_myrtptap, MENU_TOOLS_UNSORTED)
    
------------
-- post dissector  for showing timestamp delta value in tree item, which get data from variables generated by tap
------------
    local my_rtp_timestamp_delta_proto = Proto("my_rtp_timestamp_delta", "RTP Timestamp Delta [HQX's plugins]")
    
    ---- my dissector
    function my_rtp_timestamp_delta_proto.dissector(tvb, pinfo, tree)
        local rtp_ssrc = { f_rtp_ssrc() }
        local rtp_pt = { f_rtp_pt() }
        local rtp_seq = { f_rtp_seq() }
        
        local subtree = nil
        for i,ssrc_f in ipairs(rtp_ssrc) do
            local ssrc = ssrc_f.value
            local pt = rtp_pt[i].value
            local seq = rtp_seq[i].value
            
            local key = getkey(ssrc, pt, pinfo)
            local stream = rtp_streams[key]
            local rtp_info = stream.pk_infos[seq]
            
            if rtp_info then
                if not subtree then subtree = tree:add(my_rtp_timestamp_delta_proto) end
                subtree:add("PT=" .. stream.pt .. ", SSRC=" .. stream.ssrc .. ", Seq=" .. seq .. ", Timestamp=" .. rtp_info.timestamp .. ", Delta of timestamp=" .. rtp_info.delta)
            end
        end
    end

    -- register this dissector
    register_postdissector(my_rtp_timestamp_delta_proto)

end



 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值