This is a static archive of our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

get NULL if field does not exist in protocol

0

Hello!

I have no idea how to solve one problem:

  1. with the help of dumpcap I capture pcap file
  2. after that I parse pcap file with tshark
  3. some frames are muti-chunk. For example mapping of the frame is the following:

    SCTP -> MTP3 -> SCCP -> TCAP -> GSM_MAP -> GSM_SMS ->

    SCTP -> MTP3 -> SCCP -> TCAP -> GSM_MAP ->

    SCTP -> MTP3 -> SCCP -> TCAP -> GSM_MAP -> GSM_SMS ->

    SCTP -> MTP3 -> SCCP -> TCAP -> GSM_MAP -> GSM_SMS

And with the help of lua script I devide multi-chunk in separate strings

Code of LUA script:


local logfile = "/en_"..os.date("%Y%m%d%H%M%S")..".lua"
io.output(logfile)

local frame_time = Field.new("frame.time") local frame_protocols = Field.new("frame.protocols") local gsm_map_tbcd_digits = Field.new("gsm_map.tbcd_digits")

local gsm_map_cap = Listener.new(nil,"gsm_map")

function gsm_map_cap.packet(pinfo,tvb)

local Mas_frame_time = frame_time()
XMas_frame_time = string.gsub(tostring(Mas_frame_time),"  "," ")
local Mas_frame_protocols = frame_protocols()
local Mas_gsm_map_tbcd_digits = {gsm_map_tbcd_digits()}
p="(%a+) (%d+), (%d+) (%d+):(%d+):(%d+).(%d+) (%a+)"
MON={Jan=1,Feb=2,Mar=3,Apr=4,May=5,Jun=6,Jul=7,Aug=8,Sep=9,Oct=10,Nov=11,Dec=12}

Max_count = 0
count = 0
for k,v in ipairs(Mas_gsm_map_tbcd_digits) do
    count = count + 1
end

for i=1,Max_count do
    xmonth,xday,xyear,xhour,xmin,xsec,xmlsec,xtz=tostring(XMas_frame_time):match(p)
    month=MON[xmonth]
    local convertedTimestamp = os.date("%Y-%m-%d %H:%M:%S",os.time({year = xyear, month = month, day = xday, hour = xhour, min = xmin, sec = xsec}))
    io.write(tostring(convertedTimestamp) .. "\t" ..  tostring(Mas_frame_protocols) .. "\t" .. tostring(Mas_gsm_map_tbcd_digits[i]) .. "\n")
    end
end

end


But the problem is that in one multi-chunk frame one field (gsm_map.tbcd_digits) could exit in one GSM_MAP and in another GSM_MAP in the same frame this field does not exist.

Somebody may be knows how to write listener in LUA to get NULL for the field even if this field does not exist in one of the protocol in multi-chunk frame?

As the result a want to have from lua the following array for field “ gsm_map.tbcd_digits “:

123123123123123123

456456456456456456

NUL

678768678678678678

But now a have only following:

123123123123123123

456456456456456456

678768678678678678

asked 18 Aug ‘15, 04:17

domeno's gravatar image

domeno
216611
accept rate: 0%

edited 18 Aug ‘15, 04:49

Hadriel's gravatar image

Hadriel
2.7k2939


2 Answers:

1

Try something like this - this doesn't do your whole thing, but should give you the idea:

-- creates a Proto object, but doesn't register it yet
local proxy = Proto("tcap_proxy","TCAP-Proxy Fake Protocol")

– these protofields are only used for debugging this thing local total_tbcd_pf = ProtoField.uint16("tcap_proxy.total_tbcd", "Number of TBCD entries created (real and NULL)") local real_tbcd_pf = ProtoField.uint16("tcap_proxy.real_tbcd", "Number of real TBCD entries created") local null_tbcd_pf = ProtoField.uint16("tcap_proxy.null_tbcd", "Number of null TBCD entries created") proxy.fields = { total_tbcd_pf, real_tbcd_pf, null_tbcd_pf }

– this is the field we're going to keep track of local tbcd_digits_field = Field.new("gsm_map.tbcd_digits")

– this will be the tcap dissector, once we get it later local tcap_dissector

– this holds all of counts, in subtables per packet number local packets = {}

function proxy.dissector(tvbuf,pinfo,root)

if not pinfo.visited then
    -- first time for this packet, but might not be the first time we've
    -- been invoked in this packet; let's find out
    local counts = packets[pinfo.number]

    if not counts then
        -- ok, it's the first time we've been invoked for this packet, ever.
        -- so create a subtable for this packet's tbcd_digit counts
        counts = { ["number_real_entries"] = 0 }
        packets[pinfo.number] = counts
    end

    local current_count = #counts

    -- for debugging, we're going to add our proxy protocol to the tree
    local tree = root:add(proxy, tvbuf:range(0,pktlen))
    tree:add(total_tbcd_pf, current_count):set_generated()
    tree:add(real_tbcd_pf, counts.number_real_entries):set_generated()
    tree:add(null_tbcd_pf, current_count - counts.number_real_entries):set_generated()

    -- call the TCAP dissector
    tcap_dissector:call(tvbuf,pinfo,root)

    local num_fields = { tbcd_digits_field() }

    if #num_fields > counts.number_real_entries then
        -- we got a new one; it must be the last one in the num_fields table
        counts[current_count + 1] = num_fields[#num_fields].value
        counts.number_real_entries = counts.number_real_entries + 1
    else
        -- no tbcd digits, add a <NONE> entry
        counts[current_count + 1] = "<NONE>"
    end
else
    -- we've processed this whole packet before; just show the debug info
    -- of the counts and invoke the TCAP dissector
    local counts = packets[pinfo.number]

    -- for debugging, we're going to add our proxy protocol to the tree
    local tree = root:add(proxy, tvbuf:range(0,pktlen))
    tree:add(total_tbcd_pf, #counts):set_generated()
    tree:add(real_tbcd_pf, counts.number_real_entries):set_generated()
    tree:add(null_tbcd_pf, #counts - counts.number_real_entries):set_generated()

    -- call the TCAP dissector
    tcap_dissector:call(tvbuf,pinfo,root)
end

end

– we're intercepting SSN range 6-9 for GSM MAP local sccp_tbl = DissectorTable.get("sccp.ssn") – get the TCAP dissector tcap_dissector = sccp_tbl:get_dissector(6) – replace it with our proxy dissector, for the 6-9 range sccp_tbl:set("6-9", proxy)

answered 19 Aug ‘15, 20:19

Hadriel's gravatar image

Hadriel
2.7k2939
accept rate: 18%

Hadriel,

Could you please explain for what is calling “tcap_dissector” inside of “proxy.dissector” (artificial dissector for uor needs)?

Thanks for help!

(20 Aug ‘15, 23:04) domeno

If you look at the bottom of the script, you’ll see I’m getting the “sccp.ssn” dissector table, and then from within that I’m getting the dissector registered for SCCP SSN number 6, and I’m replacing it with this “proxy” protocol’s dissector. (in fact, I’m replacing the whole 6-9 range of SSNs) That dissector I’m replacing is the TCAP dissector - the one written in C-code built into wireshark.

So basically whenever SCCP goes to decode a message of SSN 6-9, instead of invoking TCAP like it would normally do, it invokes our proxy dissector instead. So within the proxy dissector I invoke the original TCAP dissector with the “tcap_dissector:call(tvbuf,pinfo,root)” line.

The reason I’m doing all that is that I can see if the number of GSM MAP TBCD fields has changed. If it’s change, then we’ve got a new TBCD in the message to save; if it has not changed, then I add a “<none>” entry instead.

The reason I’m replacing the range 6-9 is that those are the GSM MAP SSN numbers, I think.

(21 Aug ‘15, 05:58) Hadriel

1

See the answer to question 43543 which is similar.

answered 18 Aug '15, 05:12

Hadriel's gravatar image

Hadriel
2.7k2939
accept rate: 18%

Hadriel, thanks for the reply.

I am a little bit newbie in LUA and WireShark. That’s why I could not understand how to read every protocol in one frame successively.

Here is the code of LUA script for my experiments:


local logfile = "en_"..os.date("%Y%m%d%H%M%S")..".lua" io.output(logfile)

local gsm_map_tbcd_digits = Field.new("gsm_map.tbcd_digits") local m3ua = Listener.new(nil,"m3ua")

function m3ua.packet(pinfo,tvb)

local Mas_gsm_map_tbcd_digits = {gsm_map_tbcd_digits()} io.write("imsi:" .. tostring( Mas_gsm_map_tbcd_digits[0]) .."\n") io.write("imsi:" .. tostring( Mas_gsm_map_tbcd_digits[1]) .."\n") io.write("imsi:" .. tostring( Mas_gsm_map_tbcd_digits[2]) .."\n") io.write("imsi:" .. tostring( Mas_gsm_map_tbcd_digits[3]) .."\n") io.write("imsi:" .. tostring( Mas_gsm_map_tbcd_digits[4]) .."\n") io.write("imsi:" .. tostring( Mas_gsm_map_tbcd_digits[5]) .."\n") io.write("imsi:" .. tostring( Mas_gsm_map_tbcd_digits[6]) .."\n") io.write("imsi:" .. tostring( Mas_gsm_map_tbcd_digits[7]) .."\n")

End


I run it by the command:

Tshark –r /file.pcap –X lua_script:devide_imsi.lua

As far as I can judge I get the whole array of all “gsm_map.tbcd_digits” write in the beginning of the function m3ua.packet. Would you be so kind and explain how to read every protocol in one frame successively? May be you some usefull examples?!

Thanks for any help!

(18 Aug '15, 06:43) domeno

Oh yeah I keep forgetting the taps aren't invoked until after the whole packet's been dissected. Crap.

Hmmm... the only way to do it might be to create a "proxy" Lua protocol, remove the "gsm_map" dissector from TCAP's table, register the proxy Lua dissector in its place for TCAP, and within the proxy one invoke the gsm_map dissector and after it returns see what's changed about the fields you're interested in. Yuck.

Can you share an example capture file for this problem? I might have some time later today to see if I can get the info you want using a Lua script.

(18 Aug '15, 07:30) Hadriel

Hadriel, thanks for the reply.

Could you please give me an advise how can i share the pcap file with example for you? Is it possible to send you this file personally as this file has some private information?

Thanks for any help!

(19 Aug '15, 05:23) domeno

Sure, my email is either [email protected], or [email protected]

(19 Aug '15, 05:31) Hadriel

Wiresharks export-pdu function can do SCTP dechunking if that's of any use, this patch in gerrit implements it for tshark but I think the work on it may have stalled https://code.wireshark.org/review/#/c/5890/

(19 Aug '15, 07:59) Anders ♦