blob: 9037b5cb7c8241cf952b88a3de1d842b52c4af56 [file] [log] [blame]
Davide Pesaventodb9613e2023-01-20 20:52:21 -05001-- Copyright (c) 2015-2023, Regents of the University of California.
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -07002--
3-- This file is part of ndn-tools (Named Data Networking Essential Tools).
4-- See AUTHORS.md for complete list of ndn-tools authors and contributors.
5--
6-- ndn-tools is free software: you can redistribute it and/or modify it under the terms
7-- of the GNU General Public License as published by the Free Software Foundation,
8-- either version 3 of the License, or (at your option) any later version.
9--
10-- ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12-- PURPOSE. See the GNU General Public License for more details.
13--
14-- You should have received a copy of the GNU General Public License along with
15-- ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
16--
17-- @author Qi Zhao <https://www.linkedin.com/pub/qi-zhao/73/835/9a3>
18-- @author Seunghyun Yoo <http://relue2718.com/>
19-- @author Seungbae Kim <https://sites.google.com/site/sbkimcv/>
Alexander Afanasyev357c2052015-08-10 21:26:52 -070020-- @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Zipeng Wang574eeb02016-10-05 21:46:02 -070021-- @author Zipeng Wang
22-- @author Qianshan Yu
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -070023
24-- inspect.lua (https://github.com/kikito/inspect.lua) can be used for debugging.
25-- See more at http://stackoverflow.com/q/15175859/2150331
26-- local inspect = require('inspect')
27
28-- NDN protocol
Alexander Afanasyev357c2052015-08-10 21:26:52 -070029ndn = Proto("ndn", "Named Data Networking (NDN)")
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -070030
Zipeng Wang574eeb02016-10-05 21:46:02 -070031-- TODO with NDNLPv2 processing:
32-- * mark field "unknown" when the field is recognized but the relevant feature is disabled
33-- * colorize "unknown field"
34-- * for a field that appears out-of-order, display "out-of-order field " in red
35
Alexander Afanasyev357c2052015-08-10 21:26:52 -070036-----------------------------------------------------
37-----------------------------------------------------
38-- Field formatting helpers
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -070039
Junxiao Shi5e384792016-11-24 03:59:06 +000040-- @return TLV-VALUE portion of a TLV block
41function getValue(b)
42 return b.tvb(b.offset + b.typeLen + b.lengthLen, b.length)
43end
44
Junxiao Shi89db73c2018-05-27 15:22:49 +000045function getNonNegativeInteger(b)
46 if b.length == 1 or b.length == 2 or b.length == 4 or b.length == 8 then
47 return getValue(b):uint64()
48 end
49 return UInt64.max()
50end
51
Davide Pesavento89b52d42021-11-27 22:10:42 -050052function getUriFromSha256DigestComponent(b)
53 local s = ""
54 if b.type == 1 then
55 s = "sha256digest="
56 elseif b.type == 2 then
57 s = "params-sha256="
58 else
59 assert(false)
60 end
61
Junxiao Shic687af62018-05-06 21:58:09 +000062 for i = 0, (b.length - 1) do
Davide Pesavento89b52d42021-11-27 22:10:42 -050063 local byte = b.tvb(b.offset + b.typeLen + b.lengthLen + i, 1)
Junxiao Shic687af62018-05-06 21:58:09 +000064 s = s .. string.format("%02x", byte:uint())
65 end
66 return s
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -070067end
68
Junxiao Shic687af62018-05-06 21:58:09 +000069function getUriFromNameComponent(b)
Davide Pesavento89b52d42021-11-27 22:10:42 -050070 if b.type == 1 or b.type == 2 then
71 return getUriFromSha256DigestComponent(b)
Alexander Afanasyev357c2052015-08-10 21:26:52 -070072 end
Davide Pesavento89b52d42021-11-27 22:10:42 -050073
74 local s = ""
Junxiao Shic687af62018-05-06 21:58:09 +000075 if b.type ~= 8 then
76 s = string.format("%d=", b.type)
77 end
78 hasNonPeriod = false
79 for i = 0, (b.length - 1) do
Davide Pesavento89b52d42021-11-27 22:10:42 -050080 local byte = b.tvb(b.offset + b.typeLen + b.lengthLen + i, 1)
81 local ch = byte:uint()
Junxiao Shic687af62018-05-06 21:58:09 +000082 hasNonPeriod = hasNonPeriod or ch ~= 0x2E
83 if (ch >= 0x41 and ch <= 0x5A) or (ch >= 0x61 and ch <= 0x7A) or (ch >= 0x30 and ch <= 0x39) or ch == 0x2D or ch == 0x2E or ch == 0x5F or ch == 0x7E then
84 s = s .. byte:string()
85 else
86 s = s .. string.format("%%%02X", ch)
87 end
88 end
89 if not hasNonPeriod then
90 s = s .. "..."
91 end
92 return s
93end
94
95function getUriFromName(b)
96 if b.elements == nil then
97 return "/"
98 end
Davide Pesavento89b52d42021-11-27 22:10:42 -050099
Junxiao Shic687af62018-05-06 21:58:09 +0000100 components = {}
101 for i, comp in pairs(b.elements) do
102 table.insert(components, getUriFromNameComponent(comp))
103 end
104 return "/" .. table.concat(components, "/")
105end
106
107function getUriFromFinalBlockId(b)
108 if b.elements == nil then
109 return "/"
110 end
111 return getUriFromNameComponent(b.elements[1])
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700112end
113
Zipeng Wang574eeb02016-10-05 21:46:02 -0700114function getNackReasonDetail(b)
Davide Pesavento91865282021-11-27 22:18:08 -0500115 assert(b.type == 801)
Zipeng Wang574eeb02016-10-05 21:46:02 -0700116 local code = getNonNegativeInteger(b)
Davide Pesavento91865282021-11-27 22:18:08 -0500117
118 if code == UInt64(0) then return "None"
119 elseif code == UInt64(50) then return "Congestion"
Junxiao Shi89db73c2018-05-27 15:22:49 +0000120 elseif code == UInt64(100) then return "Duplicate"
121 elseif code == UInt64(150) then return "NoRoute"
122 else return tostring(code)
Zipeng Wang574eeb02016-10-05 21:46:02 -0700123 end
124end
125
126function getCachePolicyDetail(b)
Davide Pesavento91865282021-11-27 22:18:08 -0500127 assert(b.type == 821)
Zipeng Wang574eeb02016-10-05 21:46:02 -0700128 local code = getNonNegativeInteger(b)
Davide Pesavento91865282021-11-27 22:18:08 -0500129
130 if code == UInt64(0) then return "None"
131 elseif code == UInt64(1) then return "NoCache"
132 else return tostring(code) .. " (unknown)"
Zipeng Wang574eeb02016-10-05 21:46:02 -0700133 end
134end
135
Junxiao Shi5e384792016-11-24 03:59:06 +0000136function getNonce(b)
137 assert(b.type == 10)
Davide Pesavento91865282021-11-27 22:18:08 -0500138 if b.length ~= 4 then
Junxiao Shi5e384792016-11-24 03:59:06 +0000139 return "invalid (should have 4 octets)"
140 end
141 return getValue(b):uint()
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700142end
143
Davide Pesavento91865282021-11-27 22:18:08 -0500144function getHopLimit(b)
145 assert(b.type == 34)
146 if b.length ~= 1 then
147 return "invalid (should have 1 octet)"
148 end
149 return getValue(b):uint()
150end
151
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700152function getTrue(block)
153 return "Yes"
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700154end
155
Zipeng Wang574eeb02016-10-05 21:46:02 -0700156local AppPrivateBlock1 = 100
157local AppPrivateBlock2 = 800
158local AppPrivateBlock3 = 1000
159
160function canIgnoreTlvType(t)
Davide Pesavento585e18a2021-11-27 22:58:02 -0500161 if t < AppPrivateBlock2 or t >= AppPrivateBlock3 then
Zipeng Wang574eeb02016-10-05 21:46:02 -0700162 return false
163 else
Davide Pesavento585e18a2021-11-27 22:58:02 -0500164 if math.fmod(t, 2) == 1 then
Zipeng Wang574eeb02016-10-05 21:46:02 -0700165 return true
166 else
167 return false
168 end
169 end
170end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700171
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700172function getGenericBlockInfo(block)
173 local name = ""
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700174
Zipeng Wang574eeb02016-10-05 21:46:02 -0700175 -- TODO: Properly format informational message based type value reservations
Davide Pesaventodb9613e2023-01-20 20:52:21 -0500176 -- (https://docs.named-data.net/NDN-packet-spec/current/types.html#reserved-ranges)
Zipeng Wang574eeb02016-10-05 21:46:02 -0700177 if (block.type <= AppPrivateBlock1) then
178 name = "Unrecognized from the reserved range " .. 0 .. "-" .. AppPrivateBlock1 .. ""
179 elseif (AppPrivateBlock1 < block.type and block.type < AppPrivateBlock2) then
180 name = "Unrecognized from the reserved range " .. (AppPrivateBlock1 + 1) .. "-" .. (AppPrivateBlock2 - 1) .. ""
181 elseif (AppPrivateBlock2 <= block.type and block.type <= AppPrivateBlock3) then
Davide Pesavento585e18a2021-11-27 22:58:02 -0500182 if canIgnoreTlvType(block.type) then
Zipeng Wang574eeb02016-10-05 21:46:02 -0700183 name = "Unknown field (ignored)"
184 else
Davide Pesavento585e18a2021-11-27 22:58:02 -0500185 name = "Unknown field"
Zipeng Wang574eeb02016-10-05 21:46:02 -0700186 end
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700187 else
Zipeng Wang574eeb02016-10-05 21:46:02 -0700188 name = "RESERVED_3"
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700189 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700190
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700191 return name .. ", Type: " .. block.type .. ", Length: " .. block.length
192end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700193
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700194-----------------------------------------------------
195-----------------------------------------------------
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700196
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700197local NDN_DICT = {
Davide Pesavento105cd9e2019-04-06 18:13:44 -0400198 -- Name and name components
Davide Pesavento89b52d42021-11-27 22:10:42 -0500199 [7] = {name = "Name" , field = ProtoField.string("ndn.name", "Name") , value = getUriFromName},
200 [1] = {name = "ImplicitSha256DigestComponent" , field = ProtoField.string("ndn.implicit_sha256", "ImplicitSha256DigestComponent"), value = getUriFromNameComponent},
201 [2] = {name = "ParametersSha256DigestComponent", field = ProtoField.string("ndn.params_sha256", "ParametersSha256DigestComponent"), value = getUriFromNameComponent},
202 [8] = {name = "GenericNameComponent" , field = ProtoField.string("ndn.namecomponent", "GenericNameComponent") , value = getUriFromNameComponent},
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700203
Junxiao Shiac4b5462018-04-17 02:26:17 +0000204 -- Interest and its sub-elements in Packet Format v0.3
205 [5] = {name = "Interest" , summary = true},
206 [33] = {name = "CanBePrefix" , field = ProtoField.string("ndn.canbeprefix", "CanBePrefix") , value = getTrue},
207 [18] = {name = "MustBeFresh" , field = ProtoField.string("ndn.mustbefresh", "MustBeFresh") , value = getTrue},
Davide Pesavento84eb4872021-11-27 23:01:04 -0500208 [30] = {name = "ForwardingHint" , summary = true},
Junxiao Shi5e384792016-11-24 03:59:06 +0000209 [10] = {name = "Nonce" , field = ProtoField.uint32("ndn.nonce", "Nonce", base.HEX) , value = getNonce},
Davide Pesavento91865282021-11-27 22:18:08 -0500210 [12] = {name = "InterestLifetime" , field = ProtoField.uint64("ndn.lifetime", "InterestLifetime", base.DEC) , value = getNonNegativeInteger},
211 [34] = {name = "HopLimit" , field = ProtoField.uint8("ndn.hoplimit", "HopLimit", base.DEC) , value = getHopLimit},
212 [36] = {name = "ApplicationParameters" , field = ProtoField.bytes("ndn.app_params", "ApplicationParameters")},
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700213
Junxiao Shiac4b5462018-04-17 02:26:17 +0000214 -- Data and its sub-elements in Packet Format v0.3
215 [6] = {name = "Data" , summary = true},
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700216 [20] = {name = "MetaInfo" , summary = true},
Davide Pesavento91865282021-11-27 22:18:08 -0500217 [24] = {name = "ContentType" , field = ProtoField.uint64("ndn.contenttype", "ContentType", base.DEC) , value = getNonNegativeInteger},
218 [25] = {name = "FreshnessPeriod" , field = ProtoField.uint64("ndn.freshness", "FreshnessPeriod", base.DEC) , value = getNonNegativeInteger},
219 [26] = {name = "FinalBlockId" , field = ProtoField.string("ndn.finalblock", "FinalBlockId") , value = getUriFromFinalBlockId},
220 [21] = {name = "Content" , field = ProtoField.bytes("ndn.content", "Content")},
Junxiao Shiac4b5462018-04-17 02:26:17 +0000221 [22] = {name = "SignatureInfo" , summary = true},
Davide Pesavento585e18a2021-11-27 22:58:02 -0500222 [27] = {name = "SignatureType" , field = ProtoField.uint64("ndn.sigtype", "SignatureType", base.DEC) , value = getNonNegativeInteger},
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700223 [28] = {name = "KeyLocator" , summary = true},
224 [29] = {name = "KeyDigest" , field = ProtoField.bytes("ndn.keydigest", "KeyDigest")},
Davide Pesavento585e18a2021-11-27 22:58:02 -0500225 [23] = {name = "SignatureValue" , field = ProtoField.bytes("ndn.sigvalue", "SignatureValue")},
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700226
Junxiao Shiac4b5462018-04-17 02:26:17 +0000227 -- NDNLPv2 headers
Zipeng Wang574eeb02016-10-05 21:46:02 -0700228 [80] = {name = "Fragment" },
Junxiao Shi89db73c2018-05-27 15:22:49 +0000229 [81] = {name = "Sequence" , field = ProtoField.uint64("ndn.sequence", "Sequence", base.DEC) , value = getNonNegativeInteger},
230 [82] = {name = "FragIndex" , field = ProtoField.uint64("ndn.fragindex", "FragIndex", base.DEC) , value = getNonNegativeInteger},
231 [83] = {name = "FragCount" , field = ProtoField.uint64("ndn.fragcount", "FragCount", base.DEC) , value = getNonNegativeInteger},
Davide Pesavento91865282021-11-27 22:18:08 -0500232 [98] = {name = "PitToken" , field = ProtoField.bytes("ndn.pit_token", "PitToken")},
Zipeng Wang574eeb02016-10-05 21:46:02 -0700233 [100] = {name = "LpPacket" , summary = true},
234 [800] = {name = "Nack" , summary = true},
Junxiao Shi89db73c2018-05-27 15:22:49 +0000235 [801] = {name = "NackReason" , field = ProtoField.string("ndn.nack_reason", "NackReason") , value = getNackReasonDetail},
Davide Pesavento38dca392021-12-20 20:50:45 -0500236 [812] = {name = "IncomingFaceId" , field = ProtoField.uint64("ndn.incoming_face", "IncomingFaceId", base.DEC) , value = getNonNegativeInteger},
Davide Pesavento585e18a2021-11-27 22:58:02 -0500237 [816] = {name = "NextHopFaceId" , field = ProtoField.uint64("ndn.nexthop_face", "NextHopFaceId", base.DEC) , value = getNonNegativeInteger},
Zipeng Wang574eeb02016-10-05 21:46:02 -0700238 [820] = {name = "CachePolicy" , summary = true},
Davide Pesavento585e18a2021-11-27 22:58:02 -0500239 [821] = {name = "CachePolicyType" , field = ProtoField.string("ndn.cache_policy", "CachePolicyType") , value = getCachePolicyDetail},
Junxiao Shi89db73c2018-05-27 15:22:49 +0000240 [832] = {name = "CongestionMark" , field = ProtoField.uint64("ndn.congestion_mark", "CongestionMark", base.DEC) , value = getNonNegativeInteger},
241 [836] = {name = "Ack" , field = ProtoField.uint64("ndn.ack", "Ack", base.DEC) , value = getNonNegativeInteger},
Davide Pesavento200014a2021-11-27 21:21:47 -0500242 [840] = {name = "TxSequence" , field = ProtoField.uint64("ndn.txseq", "TxSequence", base.DEC) , value = getNonNegativeInteger},
Zipeng Wang574eeb02016-10-05 21:46:02 -0700243}
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700244
245-- -- Add protofields in NDN protocol
Davide Pesavento200014a2021-11-27 21:21:47 -0500246ndn.fields = {}
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700247for key, value in pairs(NDN_DICT) do
248 table.insert(ndn.fields, value.field)
249end
250
Varun Patil0168d282022-09-15 20:38:18 -0700251ndn.fields.bin = ProtoField.bytes("ndn.bin", "Binary")
252ndn.fields.len = ProtoField.uint32("ndn.len", "Packet Length")
253ndn.fields.type = ProtoField.string("ndn.type", "Packet Type")
254
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700255-----------------------------------------------------
256-----------------------------------------------------
257
258-- block
259-- .tvb
260-- .offset
261-- .type
262-- .typeLen
263-- .length
264-- .lengthLen
265-- .size = .typeLen + .lengthLen + .length
266
267function addInfo(block, root) -- may be add additional context later
268 local info = NDN_DICT[block.type]
269
270 if (info == nil) then
271 info = {}
272 info.value = getGenericBlockInfo
Zipeng Wang574eeb02016-10-05 21:46:02 -0700273 -- color
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700274 end
275
276 local treeInfo
277 if (info.value == nil) then
278
279 if (info.field ~= nil) then
280 treeInfo = root:add(info.field, block.tvb(block.offset, block.size))
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700281 else
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700282 treeInfo = root:add(block.tvb(block.offset, block.size), info.name)
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700283 end
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700284
285 treeInfo:append_text(", Type: " .. block.type .. ", Length: " .. block.length)
286 else
287 block.value = info.value(block)
288
289 if (info.field ~= nil) then
290 treeInfo = root:add(info.field, block.tvb(block.offset, block.size), block.value)
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700291 else
Zipeng Wang574eeb02016-10-05 21:46:02 -0700292 treeInfo = root:add(block.tvb(block.offset, block.size), block.value)
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700293 end
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700294 end
295 block.root = treeInfo
296 return block.root
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700297end
298
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700299function addSummary(block)
300 if (block.elements == nil) then
301 return
302 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700303
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700304 local info = NDN_DICT[block.type]
305 if (info == nil or info.summary == nil) then
306 return
307 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700308
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700309 local summary = {}
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700310
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700311 for k, subblock in pairs(block.elements) do
312 if (subblock.value ~= nil) then
313 local info = NDN_DICT[subblock.type]
314 if (info ~= nil) then
315 table.insert(summary, info.name .. ": " .. subblock.value)
316 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700317 end
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700318 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700319
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700320 if (#summary > 0) then
321 block.summary = table.concat(summary, ", ")
322 if (block.value == nil) then
323 block.value = block.summary
324 end
325 block.root:append_text(", " .. block.summary)
326 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700327end
328
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700329-----------------------------------------------------
330-----------------------------------------------------
331
332function readVarNumber(tvb, offset)
Junxiao Shie65c6d72016-07-24 21:53:19 +0000333 if offset >= tvb:len() then
334 return 0, 0
335 end
336
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700337 local firstOctet = tvb(offset, 1):uint()
338 if (firstOctet < 253) then
339 return firstOctet, 1
Junxiao Shie65c6d72016-07-24 21:53:19 +0000340 elseif (firstOctet == 253) and (offset + 3 < tvb:len()) then
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700341 return tvb(offset + 1, 2):uint(), 3
Junxiao Shie65c6d72016-07-24 21:53:19 +0000342 elseif (firstOctet == 254) and (offset + 5 < tvb:len()) then
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700343 return tvb(offset + 1, 4):uint(), 5
Junxiao Shie65c6d72016-07-24 21:53:19 +0000344 elseif (firstOctet == 255) and (offset + 9 < tvb:len()) then
345 return tvb(offset + 1, 8):uint64(), 9
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700346 end
Junxiao Shie65c6d72016-07-24 21:53:19 +0000347
348 return 0, 0
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700349end
350
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700351function getBlock(tvb, offset)
352 local block = {}
353 block.tvb = tvb
354 block.offset = offset
355
356 block.type, block.typeLen = readVarNumber(block.tvb, block.offset)
Junxiao Shie65c6d72016-07-24 21:53:19 +0000357 if block.typeLen == 0 then
358 return nil
359 end
360
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700361 block.length, block.lengthLen = readVarNumber(block.tvb, block.offset + block.typeLen)
Junxiao Shie65c6d72016-07-24 21:53:19 +0000362 if block.lengthLen == 0 then
363 return nil
364 end
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700365
366 block.size = block.typeLen + block.lengthLen + block.length
367
368 return block
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700369end
370
Alexander Afanasyev7f43c532015-08-12 15:28:51 -0700371function canBeValidNdnPacket(block)
Zipeng Wang574eeb02016-10-05 21:46:02 -0700372 if ((block.type == 5 or block.type == 6 or block.type == 100) and block.length <= 8800) then
Alexander Afanasyev7f43c532015-08-12 15:28:51 -0700373 return true
374 else
375 return false
376 end
377end
378
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700379function findNdnPacket(tvb)
380 offset = 0
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700381
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700382 while offset + 2 < tvb:len() do
383 local block = getBlock(tvb, offset)
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700384
Junxiao Shie65c6d72016-07-24 21:53:19 +0000385 if (block ~= nil) and canBeValidNdnPacket(block) then
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700386 return block
387 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700388
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700389 offset = offset + 1
390 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700391
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700392 return nil
393end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700394
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700395function getSubBlocks(block)
396 local valueLeft = block.length
397 local subBlocks = {}
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700398
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700399 while valueLeft > 0 do
Junxiao Shie65c6d72016-07-24 21:53:19 +0000400 local offset = block.offset + block.typeLen + block.lengthLen + (block.length - valueLeft)
401 local child = getBlock(block.tvb, offset)
402 if child == nil then
403 return nil
404 end
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700405
406 valueLeft = valueLeft - child.size
407 table.insert(subBlocks, child)
408 end
409
410 if (valueLeft == 0) then
411 return subBlocks
412 else
413 return nil
414 end
415end
416
417-----------------------------------------------------
418-----------------------------------------------------
419
420-- NDN protocol dissector function
421function ndn.dissector(tvb, pInfo, root) -- Tvb, Pinfo, TreeItem
422
423 if (tvb:len() ~= tvb:reported_len()) then
424 return 0 -- ignore partially captured packets
425 -- this can/may be re-enabled only for unfragmented UDP packets
426 end
427
428 local ok, block = pcall(findNdnPacket, tvb)
429 if (not ok) then
430 return 0
431 end
432
433 if (block == nil or block.offset == nil) then
434 -- no valid NDN packets found
435 return 0
436 end
437
438 local nBytesLeft = tvb:len() - block.offset
439 -- print (pInfo.number .. ":: Found block: " .. block.type .. " of length " .. block.size .. " bytesLeft: " .. nBytesLeft)
440
Junxiao Shi1fda67d2018-01-12 21:35:31 +0000441 local pktType = ""
442 local pktName = ""
443
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700444 while (block.size <= nBytesLeft) do
445 -- Create TreeItems
446 block.tree = root:add(ndn, tvb(block.offset, block.size))
447
448 local queue = {block}
449 while (#queue > 0) do
450 local block = queue[1]
451 table.remove(queue, 1)
452
453 block.elements = getSubBlocks(block)
454 local subtree = addInfo(block, block.tree)
455
456 if (block.elements ~= nil) then
457 for i, subBlock in pairs(block.elements) do
458 subBlock.tree = subtree
459 table.insert(queue, subBlock)
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700460 end
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700461 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700462 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700463
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700464 -- Make summaries
465 local queue = {block}
466 while (#queue > 0) do
467 local block = queue[1]
468 if (block.visited ~= nil or block.elements == nil) then
469 -- try to make summary
470 table.remove(queue, 1)
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700471
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700472 addSummary(block)
473 else
474 for i, subBlock in pairs(block.elements) do
475 table.insert(queue, 1, subBlock)
476 end
477 block.visited = true
478 end
Junxiao Shi1fda67d2018-01-12 21:35:31 +0000479
480 -- prepare information to fill info column
481 if block.type == 5 and pktType ~= "Nack" then
482 pktType = "Interest"
483 elseif block.type == 6 then
484 pktType = "Data"
485 elseif block.type == 800 then
486 pktType = "Nack"
487 end
488
Alexander Afanasyev4fb67ea2018-08-02 08:18:28 -0600489 if block.type == 7 then
Junxiao Shi1fda67d2018-01-12 21:35:31 +0000490 pktName = getUriFromName(block)
491 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700492 end
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700493
494 local info = NDN_DICT[block.type]
495 if (info ~= nil) then
Zipeng Wang574eeb02016-10-05 21:46:02 -0700496 if (block.summary ~= nil) then
497 block.tree:append_text(", " .. NDN_DICT[block.type].name .. ", " .. block.summary)
498 else
499 block.tree:append_text(", " .. NDN_DICT[block.type].name)
500 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700501 end
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700502
503 nBytesLeft = nBytesLeft - block.size
504
505 if (nBytesLeft > 0) then
506 ok, block = pcall(getBlock, tvb, tvb:len() - nBytesLeft)
Zipeng Wang574eeb02016-10-05 21:46:02 -0700507 if (not ok or block == nil or not canBeValidNdnPacket(block)) then
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700508 break
509 end
510 end
Varun Patil0168d282022-09-15 20:38:18 -0700511
512 -- These fields can be used to get NDN-packet level information using tshark,
513 -- for example when using the dissector only for reassembling NDN packets from TCP
514 block.tree:add(ndn.fields.bin, tvb(0, tvb:len())):set_hidden()
515 block.tree:add(ndn.fields.len, tvb:len()):set_hidden()
516 block.tree:add(ndn.fields.type, pktType):set_hidden()
Zipeng Wang574eeb02016-10-05 21:46:02 -0700517 end -- while(block.size <= nBytesLeft)
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700518
519 pInfo.cols.protocol = tostring(pInfo.cols.protocol) .. " (" .. ndn.name .. ")"
Junxiao Shi1fda67d2018-01-12 21:35:31 +0000520 pInfo.cols.info = pktType .. " " .. pktName
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700521
Alexander Afanasyev7f43c532015-08-12 15:28:51 -0700522 if (nBytesLeft > 0 and block ~= nil and block.size ~= nil and block.size > nBytesLeft) then
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700523 pInfo.desegment_offset = tvb:len() - nBytesLeft
524
525 -- Originally, I set desegment_len to the exact lenght, but it mysteriously didn't work for TCP
526 -- pInfo.desegment_len = block.size -- this will not work to desegment TCP streams
527 pInfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT
528 end
Alexander Afanasyev6fbb7b42015-08-10 11:53:49 -0700529end
530
Alexander Afanasyev357c2052015-08-10 21:26:52 -0700531local udpDissectorTable = DissectorTable.get("udp.port")
532udpDissectorTable:add("6363", ndn)
533udpDissectorTable:add("56363", ndn)
534
535local tcpDissectorTable = DissectorTable.get("tcp.port")
536tcpDissectorTable:add("6363", ndn)
537
538local websocketDissectorTable = DissectorTable.get("ws.port")
539-- websocketDissectorTable:add("9696", ndn)
540websocketDissectorTable:add("1-65535", ndn)
541
Alexander Afanasyev7f43c532015-08-12 15:28:51 -0700542local ethernetDissectorTable = DissectorTable.get("ethertype")
543ethernetDissectorTable:add(0x8624, ndn)
544
Alexander Afanasyev4fb67ea2018-08-02 08:18:28 -0600545local pppDissectorTable = DissectorTable.get("ppp.protocol")
546pppDissectorTable:add(0x0077, ndn)
547
Junxiao Shiac4b5462018-04-17 02:26:17 +0000548io.stderr:write("NDN dissector successfully loaded\n")