最近项目开发需要,数据转发组同事写了一个lua插件,来解析mac in mac的内部协议上送的报文,在老的wireshark中使用是没有问题的,但是在新的wireshark版本中,解析到内层mac时就挂,看了下lua脚本,定位出是二层mac解析出错,下载了最新wireshark版本的源代码,对比了源代码中的lua插件的接口api,发现外层mac解析时是需要进行Ethernet的fcs检查的,而内层的mac是不需要的,所以内层解析mac二层信息时需要注意没有fcs信息,调用的是eth_withoutfcs,问题解决!
下附wireshark的lua开发手册:https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Proto.html,有需要开发lua插件的可以参考开发手册。
最后附上我们项目的lua脚本,解析data-plane和control-plane通过internal口上送下发的报文:
--[[
Wireshark解析DPTUN报文的脚本
struct dptunhdr{
uint64_t dp_cookie;
uint16_t exec_type;
uint16_t blade_id;
uint32_t ifindex;
uint32_t vxlanid;
uint16_t dptun_proto;
uint16_t payload_len;
} __attribute__ ((__packed__));
]]
--协议名称
local p_dptun = Proto("dptun", "DP exception tunnel");
-- exec_type的类型值对应的名字
local vs_exec_types = {
--CP exception
[0x0000] = "basic exception",
[0x0001] = "ethernet input exception",
[0x0002] = "ethernet output exception",
[0x0003] = "ipv4 input exception",
[0x0004] = "ipv4 output exception",
[0x0005] = "ipv6 input exception",
[0x0006] = "ipv6 output exception",
[0x0007] = "pppoe exception",
[0x0008] = "ipmr user exception",
[0x0009] = "arp requset to dp",
--SP exception
[0x8001] = "ARP exception",
[0x8002] = "ipmr exception",
[0x8002] = "ipmr unres exception",
[0x8004] = "VPLS fdb mac learn exception",
[0x8005] = "Vxlan fdb learn exception"
}
--定义各个字段的类型
local f_exec_type = ProtoField.uint16("exec_type", "exception type", base.DEC, vs_exec_types)
local f_dp_cookie = ProtoField.uint64("dp_cookie", "dp_cookie", base.DEC)
local f_blade_id = ProtoField.uint16("blade_id", "blade id", base.DEC)
local f_ifindex = ProtoField.uint32("ifindex", "interface index", base.DEC)
local f_vxlanid = ProtoField.uint32("vxlanid", "vxlanid", base.DEC)
local f_dptun_proto = ProtoField.uint16("dptun_proto", "dptun proto", base.DEC)
local f_payload_len = ProtoField.uint16("payload_len", "payload length", base.DEC)
--定义协议包含哪些字段
p_dptun.fields = {f_dp_cookie,f_exec_type, f_blade_id, f_ifindex, f_vxlanid,f_dptun_proto, f_payload_len}
--内层报文解析器
local encap_tbl = DissectorTable.get("wtap_encap")
--以太报文解析器
local eth_dis = encap_tbl:get_dissector(wtap_encaps.ETHERNET)
--IPv4报文解析器
local ipv4_dis = encap_tbl:get_dissector(wtap_encaps.RAW_IP4)
--IPv6报文解析器
local ipv6_dis = encap_tbl:get_dissector(wtap_encaps.RAW_IP6)
local data_dis = Dissector.get("data")
local eth_withoutfcs = Dissector.get("eth_withoutfcs")
local raw_ipv4_dis = Dissector.get("raw_ip")
p_dptun.prefs["ethernet_type"] = Pref.uint(
"DPTUN",
0x1212,
"Data Plane Tunnel Head"
)
--协议解析器
function p_dptun.dissector(buffer, pinfo, tree)
--设置wireshark protocol列协议显示为dptun
pinfo.cols.protocol:set("dptun")
--设置wireshark info列显示
pinfo.cols.info:set("DP tunnel")
--在Wireshark中添加DPTUN的树形结构
local buffer_len = buffer:len()
local dptun_proto_tree = tree:add(p_dptun, buffer(0, buffer_len), "DP exception tunnel")
--以下开始解析各个字段的含义
local offset = 0
--解析exec_type
local exec_type = buffer(offset, 2):uint()
--[[if exec_type > 8 then
-- 如果exec_type值大于8,输出错误后退出
pinfo.cols.info:set("Invalid Exec Type")
return
else
--添加exec_type子节点
dptun_proto_tree:add(f_exec_type, buffer(offset, 2))
end]]
--添加dp_cookie子节点
dptun_proto_tree:add(f_dp_cookie, buffer(offset, 8))
--解析下一个字段,偏移量增加
offset = offset + 8
--添加exec_type子节点
dptun_proto_tree:add(f_exec_type, buffer(offset, 2))
--解析下一个字段,偏移量增加
offset = offset + 2
--添加ifindex子节点
dptun_proto_tree:add(f_ifindex, buffer(offset, 4))
--解析下一个字段,偏移量增加
offset = offset + 4
--添加f_vxlanid子节点
dptun_proto_tree:add(f_vxlanid, buffer(offset, 4))
--解析下一个字段,偏移量增加
offset = offset + 4
--添加f_dptun_proto子节点
dptun_proto_tree:add(f_dptun_proto, buffer(offset, 2))
--解析下一个字段,偏移量增加
offset = offset + 2
--添加f_payload_len子节点
dptun_proto_tree:add(f_payload_len, buffer(offset, 2))
--解析内层报文
offset = offset + 2
-- 以太报文解析
if exec_type == 0x0000
or exec_type == 0x0001
or exec_type == 0x0002
or exec_type == 0x0007
or exec_type == 0x0008
then
--eth_dis(buffer(offset, buffer_len - offset):tvb(), pinfo, tree)
eth_withoutfcs(buffer(offset, buffer_len - offset):tvb(), pinfo, tree)
--eth(buffer(offset, buffer_len - offset):tvb(), pinfo, tree)
--IPv4报文解析
elseif exec_type == 0x0003
or exec_type == 0x0004
then
--ipv4_dis(buffer(offset, buffer_len - offset):tvb(), pinfo, tree)
raw_ipv4_dis(buffer(offset, buffer_len - offset):tvb(), pinfo, tree)
--IPv6报文解析
elseif exec_type == 0x0005
or exec_type == 0x0006
then
ipv6_dis(buffer(offset, buffer_len - offset):tvb(), pinfo, tree)
--其它报文解析
else
data_dis(buffer(offset, buffer_len - offset):tvb(), pinfo, tree)
end
end
--将dptun协议添加到ethertype 0x1212解析器中
local ethertype_table = DissectorTable.get("ethertype")
ethertype_table:add(p_dptun.prefs["ethernet_type"], p_dptun)