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

Assistance with dissector for custom network protocol

0

Hello,

At my job we regularly use switches which got a proprietary ring redundancy protocol. In order to make our job easier, I am trying to make a dissector so wireshark correctly shows information instead of showing 'llc' as it currently does.

I looked up multiple tutorials, but so far almost all of those I found talk about connecting to a specific UDP or TCP port while what I intend to do hooks directly on the MAC/ethernet level.

I know for sure that the lua gets loaded, as writing an error or invalid action causes a crash. I tried multiple ways of getting wireshark to translate as my protocol instead of LLC, but I got no success so far. If anyone can give me a hint or a source where I can find the answer myself I would appreciate it!

wireshark trace of a few packets of the protocol: https://drive.google.com/file/d/0B9vmLCalgzm1NC1KUzNqRENFY1E/view?usp=sharing

image for those who rather don't download files from unknown sources: alt text

My current code attempt:

    original_802_3_dissector = DissectorTable.get( "wtap_encap" ):get_dissector( 1 )

protoRGERP = Proto("RGERP", "Redundant Gigabit Ethernet Ring Protocol")

local f = protoRGERP.fields local vs_state = {[0]="normal",[1]="abnormal"}

f.ringId = ProtoField.uint16("protoRGERP.ringId", "Ring ID") f.ringState = ProtoField.bool("protoRGERP.ringState", "Ring Status") f.ringMaster = ProtoField.ether("protoRGERP.ringMaster","Ring Master") f.ringData = ProtoField.bytes ("protoRGERP.ringData","Data") –f.ringInfo = ProtoField.string("protoRGERP.ringInfo","Ring Info")

local packet_counter function protoRGERP.init() packet_counter = 0 end

function protoRGERP.dissector(buffer, pinfo, tree) –run default ethernet dissector original_802_3_dissector:call(buffer,pinfo,tree) –tree additions local subtree = tree:add(protoRGERP, buffer()) local offset=12 local ringId = buffer(offset,1) subtree:add (f.ringId, ringId) subtree:append_text(", Ring ID: "..ringId:uint()) offset=offset+1

local ringState = buffer(offset,1)
subtree:add(f.ringState, ringState)
subtree:append_text(", Ring normal : "..ringState:bool())
offset=offset+1

local ringMaster = buffer(offset,6)
subtree:add(f.ringMaster, ringMaster)
subtree:append_text(", RM MAC: "..ringMaster:ether())
offset=offset+6

subtree:add( f.ringData, buffer(offset))

-- modify columns; to be extended
pinfo.cols['protocol'] = "RGERP"
pinfo.cols.info = "RGERP ID: "
pinfo.cols.info:append(ringId:uint())

end

–local wtap_encap_table = DissectorTable.get("wtap_encap") –wtap_encap_table:add(0x1a, protoRGERP) –below causes wireshark to crash –local llc_table = DissectorTable.get("llc.dsap") –llc_table:add(0x6b, protoRGERP) local dissector_table2 = DissectorTable.get("ethertype") dissector_table2:add(0x1a,protoRGERP) local dissector_table3 = DissectorTable.get("wtap_encap") dissector_table3:add(wtap.USER0, protoRGERP)

asked 04 Apr ‘17, 08:10

nikdubois's gravatar image

nikdubois
6115
accept rate: 100%

minor update: with replacing ethernet I can get it working, but I can’t get the if structure working to run the original ethernet dissector if mine isn’t needed. A way to do this might be a good workaround if anyone knows how/if this is possible!

this is how I replaced the dissector:

original_802_3_dissector = DissectorTable.get( "wtap_encap" ):get_dissector( 1 )
local dissector_table3 = DissectorTable.get("wtap_encap")
dissector_table3:add(1, protoRGERP)

and then I wrapped my code in the proto.dissector in an if:

function protoRGERP.dissector(buffer, pinfo, tree)
if buffer(0xE,4):string()~='6b726e78' then
~code~
else
original_802_3_dissector:call(buffer,pinfo,tree)
end
end

But this causes ‘wireshark has stopped responding’. I couldn’t find an error in a log yet.

(04 Apr ‘17, 08:48) nikdubois
1

So does this protocol run atop Ethernet?

If so, does it:

  1. have an Ethernet type value assigned to it;
  2. have an 802.2 DSAP assigned to it;
  3. have a SNAP OUI and protocol ID assigned to it;
  4. violate the Ethernet spec?

(All protocols that run atop Ethernet do one of those four things; i.e., if they don’t have one of those values assigned to them, they’re violating the Ethernet spec.)

(04 Apr ‘17, 18:05) Guy Harris ♦♦

I fear it is the last. I will raise the issue with the manufacturer, but I don’t think this can/will be changed by them anytime soon.

My guess is that I will have to do the workaround using a chained dissector (my own into the ethernet if it is not my own protocol). So far this always crashes for me though, so if you have a working example using the ethernet dissector I would appreciate it!

(05 Apr ‘17, 00:15) nikdubois


One Answer:

0

I managed to get it working eventually, but make sure to read the comment of Guy Harris as he is right. What I used below is an ugly way to get around it and there are better solutions. Just posting this so others in a similar situation can get a workaround untill they fix it.

protoRGERP = Proto("RGERP", "RGERP", "Redundant Gigabit Ethernet Ring Protocol")

local f = protoRGERP.fields local vs_ringState = {[0]="normal",[1]="abnormal"} local vs_portState = {[0]="up",[1]="down"}

–f.packetSource = ProtoField.ether("protoRGERP.packetSource","Source") –f.packetDest = ProtoField.ether("protoRGERP.packetSource","Destination") f.packetType = ProtoField.string("protoRGERP.packetType","LLC Type") f.ringId = ProtoField.uint16("protoRGERP.ringId", "Ring ID") f.ringState = ProtoField.uint16("protoRGERP.ringState", "Ring State") f.ringMaster = ProtoField.ether("protoRGERP.ringMaster","Ring Master")

f.portState = ProtoField.uint16("protoRGERP.portState", "Port State") f.portId = ProtoField.uint16("protoRGERP.portId", "Port ID") f.packetSender = ProtoField.ether("protoRGERP.packetSender","Packet Sender")

local packet_counter function protoRGERP.init() packet_counter = 0 end

function protoRGERP.dissector(buffer, pinfo, tree) local subtree = tree:add(protoRGERP, buffer())

--tree additions
local packetType
if string.sub(tostring(pinfo.cols.src),-1)=='2' then
    packetType="LINK_CHANGE_DOWN"
elseif string.sub(tostring(pinfo.cols.dst),-1)=='3' then
    packetType="LINK_CHANGE_UP"
else
    packetType="WATCHDOG"
end
subtree:add(f.packetType, packetType)

local offset=0
if packetType=="WATCHDOG" then
    local ringId = buffer(offset,1)
    subtree:add (f.ringId, ringId)
    offset=offset+1

    local ringState = buffer(offset,1)
    subtree:add(f.ringState, ringState)
    offset=offset+1

    local ringMaster = buffer(offset,6)
    subtree:add(f.ringMaster, ringMaster)
    offset=offset+6

    -- modify columns; replace LLC with custom
    pinfo.cols['protocol'] = "RGERP"
    pinfo.cols.info = "Ring ID: "
    pinfo.cols.info:append(ringId:uint())
    pinfo.cols.info:append(", ring status: ")
    pinfo.cols.info:append(vs_ringState[ringState:uint()])
    pinfo.cols.info:append(", packet type: "..packetType)
else
    --linkchange
    local portState = buffer(offset,1)
    subtree:add (f.portState, portState)
    offset = offset+1

    local portId = buffer(offset,1)
    subtree:add (f.portId, portId)
    offset = offset+1

    local packetSender = buffer(offset,6)
    subtree:add (f.packetSender, packetSender)
    offset = offset+1

    local ringId = buffer(offset,1)
    subtree:add (f.ringId, ringId)
    offset=offset+1

    pinfo.cols['protocol'] = "RGERP"
    pinfo.cols.info = "Ring ID: "
    pinfo.cols.info:append(ringId:uint())
    pinfo.cols.info:append(", port ID: "..portId:uint().." is ")
    pinfo.cols.info:append(vs_portState[portState:uint()])
    pinfo.cols.info:append(", packet type: "..packetType)        
end

end

local llc_table = DissectorTable.get("llc.dsap") llc_table:add(0x6b, protoRGERP)

answered 05 Apr ‘17, 02:13

nikdubois's gravatar image

nikdubois
6115
accept rate: 100%

edited 05 Apr ‘17, 02:15