1require "bit32"
2--[[
3SPDX-License-Identifier: GPL-2.0-or-later
4Copyright (c) 2022 Huawei Device Co., Ltd.
5
6Description: wireshark lua configure for NewIP protocol stack
7
8Author: Yang Yanjun <yangyanjun@huawei.com>
9
10Data: 2022-05-27
11--]]
12
13do -- lua begin
14
15--协议名称为NewIP,在Packet Details窗格显示为NewIP
16-- create a new protocol
17local nip_proto_name = "NewIP"
18local nip_proto_desc = "NewIP Protocol"
19local nip_proto_obj = Proto(nip_proto_name, nip_proto_desc)
20
21--[[
22NewIP协议字段定义
23	ProtoField 参数:
24	para1 [必选] - 字段的缩写名称(过滤器中使用的字符串)
25	para2 [可选] - 字段的实际名称(出现在树中的字符串)
26	para3 [可选] - 字段类型
27--]]
28--[[
29ProtoField.{type}(abbr, [name], [base], [valuestring], [mask], [desc])
30·type包括:uint8, uint16, uint24, uint32, uint64, framenum, float, double, string, stringz, bytes, bool, ipv4, ipv6, ether,oid, guid
31
32abbr 字段的缩写名称(过滤器中使用的字符串)。
33name (optional) 字段的实际名称(出现在树中的字符串)。
34base (optional) base.DEC,base.HEX或base.OCT,base.DEC_HEX,base.HEX_DEC,base.UNIT_STRING或base.RANGE_STRING。
35valuestring (optional) 包含与值对应的文本的表,或包含与值 ({min, max, “string”}) 对应的范围字符串值表的表(如果基数为 )base.RANGE_STRING,
36                       或包含单位名称的表如果 base 是base.UNIT_STRING.
37mask (optional) 此字段的整数掩码。
38desc (optional) 字段说明。
39
40--]]
41local _ttl        = ProtoField.uint8 (nip_proto_name .. ".ttl",        "ttl       (  1 Byte)",  base.DEC)
42local _total_len  = ProtoField.uint16(nip_proto_name .. ".total_len",  "total_len (  2 Byte)",  base.DEC)
43local _nexthdr    = ProtoField.uint8 (nip_proto_name .. ".nexthdr",    "nexthdr   (  1 Byte)",  base.DEC)
44local _daddr      = ProtoField.bytes (nip_proto_name .. ".daddr",      "daddr     (1~8 Byte)",  base.SPACE)
45local _saddr      = ProtoField.bytes (nip_proto_name .. ".saddr",      "saddr     (1~8 Byte)",  base.SPACE)
46local _hdr_len    = ProtoField.uint8 (nip_proto_name .. ".hdr_len",    "hdr_len   (  1 Byte)",  base.DEC)
47local _trans_data = ProtoField.bytes (nip_proto_name .. ".trans_data", "trans_data", base.SPACE)
48
49-- 将字段添加都协议中
50nip_proto_obj.fields = {
51	_ttl,
52	_total_len,
53	_nexthdr,
54	_daddr,
55	_saddr,
56	_hdr_len,
57	_trans_data
58}
59--获取 _trans_data 解析器
60local _unknown_data_dis = Dissector.get("data")
61
62--定义 bitmap1 子菜单
63-- create a new protocol
64local bitmap1_name = "bitmap1"
65local bitmap1_desc = "bitmap1"
66local bitmap1_obj = Proto(bitmap1_name, bitmap1_desc)
67
68--[[
69bitmap1 子菜单字段定义
70	ProtoField 参数:
71	para1 [必选] - 字段的缩写名称(过滤器中使用的字符串)
72	para2 [可选] - 字段的实际名称(出现在树中的字符串)
73	para3 [可选] - 字段类型
74--]]
75local _bitmap1           = ProtoField.uint8(bitmap1_name .. ".bitmap1",           "bitmap1",           base.HEX)
76local _pkt_hdr_type      = ProtoField.uint8(bitmap1_name .. ".pkt_hdr_type",      "pkt_hdr_type     ", base.DEC, Payload_type, 0x80) --_bitmap1的8bit
77local _include_ttl       = ProtoField.uint8(bitmap1_name .. ".include_ttl",       "include_ttl      ", base.DEC, Payload_type, 0x40) --_bitmap1的7bit
78local _include_total_len = ProtoField.uint8(bitmap1_name .. ".include_total_len", "include_total_len", base.DEC, Payload_type, 0x20) --_bitmap1的6bit
79local _include_nexthdr   = ProtoField.uint8(bitmap1_name .. ".include_nexthdr",   "include_nexthdr  ", base.DEC, Payload_type, 0x10) --_bitmap1的5bit
80local _include_reserve1  = ProtoField.uint8(bitmap1_name .. ".include_reserve1",  "include_reserve1 ", base.DEC, Payload_type, 0x08) --_bitmap1的4bit
81local _include_daddr     = ProtoField.uint8(bitmap1_name .. ".include_daddr",     "include_daddr    ", base.DEC, Payload_type, 0x04) --_bitmap1的3bit
82local _include_saddr     = ProtoField.uint8(bitmap1_name .. ".include_saddr",     "include_saddr    ", base.DEC, Payload_type, 0x02) --_bitmap1的2bit
83local _include_bitmap2   = ProtoField.uint8(bitmap1_name .. ".include_bitmap2",   "include_bitmap2  ", base.DEC, Payload_type, 0x01) --_bitmap1的1bit
84
85-- 将字段添加都协议中
86bitmap1_obj.fields = {
87	_bitmap1, _pkt_hdr_type, _include_ttl, _include_total_len, _include_nexthdr,
88	_include_reserve1, _include_daddr, _include_saddr, _include_bitmap2
89}
90
91--定义 bitmap2 子菜单
92-- create a new protocol
93local bitmap2_name = "bitmap2"
94local bitmap2_desc = "bitmap2"
95local bitmap2_obj = Proto(bitmap2_name, bitmap2_desc)
96
97--[[
98bitmap2 子菜单字段定义
99	ProtoField 参数:
100	para1 [必选] - 字段的缩写名称(过滤器中使用的字符串)
101	para2 [可选] - 字段的实际名称(出现在树中的字符串)
102	para3 [可选] - 字段类型
103--]]
104local _bitmap2          = ProtoField.uint8(bitmap2_name .. ".bitmap2",          "bitmap2",          base.HEX)
105local _include_hdr_len  = ProtoField.uint8(bitmap2_name .. ".include_hdr_len",  "include_hdr_len ", base.DEC, Payload_type, 0x80) --_bitmap2的8bit
106local _include_reserve2 = ProtoField.uint8(bitmap2_name .. ".include_reserve2", "include_reserve2", base.DEC, Payload_type, 0x40) --_bitmap2的7bit
107local _include_reserve3 = ProtoField.uint8(bitmap2_name .. ".include_reserve3", "include_reserve3", base.DEC, Payload_type, 0x20) --_bitmap2的6bit
108local _include_reserve4 = ProtoField.uint8(bitmap2_name .. ".include_reserve4", "include_reserve4", base.DEC, Payload_type, 0x10) --_bitmap2的5bit
109local _include_reserve5 = ProtoField.uint8(bitmap2_name .. ".include_reserve5", "include_reserve5", base.DEC, Payload_type, 0x08) --_bitmap2的4bit
110local _include_reserve6 = ProtoField.uint8(bitmap2_name .. ".include_reserve6", "include_reserve6", base.DEC, Payload_type, 0x04) --_bitmap2的3bit
111local _include_reserve7 = ProtoField.uint8(bitmap2_name .. ".include_reserve7", "include_reserve7", base.DEC, Payload_type, 0x02) --_bitmap2的2bit
112local _include_bitmap3  = ProtoField.uint8(bitmap2_name .. ".include_bitmap3",  "include_bitmap3 ", base.DEC, Payload_type, 0x01) --_bitmap2的1bit
113
114-- 将字段添加都协议中
115bitmap2_obj.fields = {
116	_bitmap2, _include_hdr_len, _include_reserve2, _include_reserve3, _include_reserve4,
117	_include_reserve5, _include_reserve6, _include_reserve7, _include_bitmap3
118}
119
120--定义 nd icmp 子菜单
121-- create a new protocol
122local nd_icmp_name = "nd_icmp"
123local nd_icmp_desc = "nd_icmp"
124local nd_icmp_obj = Proto(nd_icmp_name, nd_icmp_desc)
125
126--[[
127nd_icmp 子菜单字段定义
128	ProtoField 参数:
129	para1 [必选] - 字段的缩写名称(过滤器中使用的字符串)
130	para2 [可选] - 字段的实际名称(出现在树中的字符串)
131	para3 [可选] - 字段类型
132--]]
133local _type     = ProtoField.uint8 (nd_icmp_name .. ".type",     "type    (  1 Byte)", base.DEC)
134local _code     = ProtoField.uint8 (nd_icmp_name .. ".code",     "code    (  1 Byte)", base.DEC)
135local _checksum = ProtoField.uint16(nd_icmp_name .. ".checksum", "checksum(  2 Byte)", base.HEX)
136local _rs_daddr = ProtoField.bytes (nd_icmp_name .. ".rs_daddr", "rs_daddr(1~8 Byte)", base.SPACE)
137local _mac_len  = ProtoField.uint8 (nd_icmp_name .. ".mac_len",  "mac_len (  1 Byte)", base.DEC)
138local _mac      = ProtoField.bytes (nd_icmp_name .. ".mac",      "mac     (  6 Byte)", base.SPACE)
139
140-- 将字段添加都协议中
141nd_icmp_obj.fields = {
142	_type, _code, _checksum, _rs_daddr, _mac_len, _mac
143}
144
145--[[
146	下面定义 newip 解析器的主函数
147	第一个参数是 tvb      类型,表示的是需要此解析器解析的数据
148	第二个参数是 pinfo    类型,是协议解析树上的信息,包括 UI 上的显示
149	第三个参数是 treeitem 类型,表示上一级解析树
150--]]
151function nip_dissector(tvb, pinfo, treeitem)
152	--设置一些 UI 上面的信息
153	pinfo.cols.protocol:set(nip_proto_name)
154	pinfo.cols.info:set(nip_proto_desc)
155
156	local offset = 0
157	local tvb_len = tvb:len()
158	local nexthdr = 0
159
160	-- 在上一级解析树上创建 nip 的根节点
161	local nip_tree = treeitem:add(nip_proto_obj, tvb:range(tvb_len))
162
163	local bitmap1 = tvb(offset, 1):uint()	--表示从报文缓冲区0开始取1个字节
164	local pkt_hdr_type			= bit.band(bit.rshift(bitmap1, 7), 0x00000001)	--右移 7 位 与 0x01 相与,获取 pkt_hdr_type 位
165	local include_ttl		= bit.band(bit.rshift(bitmap1, 6), 0x00000001)	--右移 6 位 与 0x01 相与,获取 include_ttl 位
166	local include_total_len	= bit.band(bit.rshift(bitmap1, 5), 0x00000001)	--右移 5 位 与 0x01 相与,获取 include_total_len 位
167	local include_nexthdr	= bit.band(bit.rshift(bitmap1, 4), 0x00000001)	--右移 4 位 与 0x01 相与,获取 include_nexthdr 位
168	local include_daddr		= bit.band(bit.rshift(bitmap1, 2), 0x00000001)	--右移 2 位 与 0x01 相与,获取 include_daddr 位
169	local include_saddr		= bit.band(bit.rshift(bitmap1, 1), 0x00000001)	--右移 1 位 与 0x01 相与,获取 include_saddr 位
170	local include_bitmap2	= bit.band(bitmap1, 0x00000001)					--获取 include_bitmap2 位
171
172	--nip报头无效(0表示有效)
173	if pkt_hdr_type ~= 0 then
174		return false
175	else
176		--bitmap1子菜单
177		local bitmap1_tree = nip_tree:add(bitmap1_obj, tvb:range(tvb_len))
178		bitmap1_tree:add(_bitmap1,           bitmap1)
179		bitmap1_tree:add(_pkt_hdr_type,      bitmap1):append_text("  (".."0-New IP; 1-Reserve"..")")
180		bitmap1_tree:add(_include_ttl,       bitmap1)
181		bitmap1_tree:add(_include_total_len, bitmap1)
182		bitmap1_tree:add(_include_nexthdr,   bitmap1)
183		bitmap1_tree:add(_include_reserve1,  bitmap1)
184		bitmap1_tree:add(_include_daddr,     bitmap1)
185		bitmap1_tree:add(_include_saddr,     bitmap1)
186		bitmap1_tree:add(_include_bitmap2,   bitmap1)
187		offset = offset + 1	--_bitmap1 占用1字节
188	end
189
190	local include_hdr_len = 0
191	if include_bitmap2 ~= 0 then
192		--bitmap2子菜单
193		local bitmap2_tree = nip_tree:add(bitmap2_obj, tvb:range(tvb_len))
194		local bitmap2 = tvb(offset, 1):uint()
195		include_hdr_len         = bit.band(bit.rshift(bitmap2, 7), 0x00000001)	--右移 7 位 与 0x01 相与,获取 include_hdr_len 位
196		offset = offset + 1	--_bitmap2 占用1字节
197
198		bitmap2_tree:add(_bitmap2,          bitmap2)
199		bitmap2_tree:add(_include_hdr_len,  bitmap2)
200		bitmap2_tree:add(_include_reserve2, bitmap2)
201		bitmap2_tree:add(_include_reserve3, bitmap2)
202		bitmap2_tree:add(_include_reserve4, bitmap2)
203		bitmap2_tree:add(_include_reserve5, bitmap2)
204		bitmap2_tree:add(_include_reserve6, bitmap2)
205		bitmap2_tree:add(_include_reserve7, bitmap2)
206		bitmap2_tree:add(_include_bitmap3,  bitmap2)
207	end
208
209	if include_ttl ~= 0 then
210		nip_tree:add(_ttl, tvb(offset, 1))
211		offset = offset + 1	--_ttl 占用1字节
212	end
213
214	if include_total_len ~= 0 then
215		nip_tree:add(_total_len, tvb(offset, 2))
216		offset = offset + 2	--_total_len 占用2字节
217	end
218
219	if include_nexthdr ~= 0 then
220		nexthdr = tvb(offset, 1):uint()
221		nip_tree:add(_nexthdr, tvb(offset, 1))
222		offset = offset + 1	--_nexthdr 占用1字节
223	end
224
225	if include_daddr ~= 0 then
226		local first_addr = tvb(offset, 1):uint()
227		local addr_len = get_nip_addr_len (first_addr)
228		if addr_len == 0 then
229			return false
230		end
231		nip_tree:add(_daddr, tvb(offset, addr_len))
232		offset = offset + addr_len	--_daddr 占用 addr_len 字节
233	end
234
235	if include_saddr ~= 0 then
236		local first_addr = tvb(offset, 1):uint()
237		local addr_len = get_nip_addr_len (first_addr)
238		if addr_len == 0 then
239			return false
240		end
241		nip_tree:add(_saddr, tvb(offset, addr_len))
242		offset = offset + addr_len	--_daddr 占用 addr_len 字节
243	end
244
245	if include_hdr_len ~= 0 then
246		nip_tree:add(_hdr_len, tvb(offset, 1))
247		offset = offset + 1	--_hdr_len 占用1字节
248	end
249
250	--根据next header 确定上层协议
251	local trans_data = tvb(offset, tvb_len - offset)
252	if (nexthdr == 177) then
253		local nd_icmp_tree = nip_tree:add(nd_icmp_obj, tvb:range(tvb_len))
254		local type = tvb(offset, 1):uint()
255		nd_icmp_tree:add(_type, tvb(offset, 1))
256		offset = offset + 1
257		nd_icmp_tree:add(_code, tvb(offset, 1))
258		offset = offset + 1
259		nd_icmp_tree:add(_checksum, tvb(offset, 2))
260		offset = offset + 2
261		if type == 1 then
262			local first_addr = tvb(offset, 1):uint()
263			local addr_len = get_nip_addr_len (first_addr)
264			if addr_len == 0 then
265				return false
266			end
267			nd_icmp_tree:add(_rs_daddr, tvb(offset, addr_len))
268			offset = offset + addr_len	--_rs_daddr 占用 addr_len 字节
269			pinfo.cols.protocol = "ND request based NewIP"
270		else
271			nd_icmp_tree:add(_mac_len, tvb(offset, 1))
272			offset = offset + 1
273			nd_icmp_tree:add(_mac, tvb(offset, 6))
274			offset = offset + 6
275			pinfo.cols.protocol = "ND response based NewIP"
276		end
277	elseif (nexthdr == 6) then
278		Dissector.get("tcp"):call(trans_data:tvb(), pinfo, treeitem)
279		pinfo.cols.protocol = "TCP based NewIP"
280	elseif (nexthdr == 17) then
281		Dissector.get("udp"):call(trans_data:tvb(), pinfo, treeitem)
282		pinfo.cols.protocol = "UDP based NewIP"
283	else
284		nip_tree:add(_trans_data, trans_data)
285	end
286end
287
288--[[
289	下面定义 NewIP 解析器的主函数,这个函数由 wireshark调用
290	第一个参数是 Tvb      类型,表示的是需要此解析器解析的数据
291	第二个参数是 Pinfo    类型,是协议解析树上的信息,包括 UI 上的显示
292	第三个参数是 TreeItem 类型,表示上一级解析树
293--]]
294function nip_proto_obj.dissector(tvb, pinfo, treeitem)
295	if nip_dissector(tvb, pinfo, treeitem) then
296		--valid NewIP diagram
297	else
298		--不是NewIP协议(其他未知协议)时,直接输出报文数据
299		_unknown_data_dis:call(tvb, pinfo, treeitem)
300	end
301
302end
303
304
305--向 wireshark 注册协议插件被调用的条件
306local ipn_encap_table = DissectorTable.get("ethertype")
307ipn_encap_table:add(0xEADD, nip_proto_obj)
308
309--NewIP地址长度计算
310function get_nip_addr_len (first_addr)
311	if first_addr <= 0xDC then
312		return 1
313	elseif first_addr >= 0xDD and first_addr <= 0xF0 then
314		return 2
315	elseif first_addr == 0xF1 then
316		return 3
317	elseif first_addr == 0xF2 then
318		return 5
319	elseif first_addr == 0xF3 then
320		return 7
321	elseif first_addr == 0xFE then
322		return 8
323	elseif first_addr == 0xFF then
324		return 2
325	else
326		return 0
327	end
328end
329
330end -- lua end
331