-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpcoip.lua
285 lines (210 loc) · 8.66 KB
/
pcoip.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
-------------------------------------------------
-- PCoIP postdissector --
-------------------------------------------------
-------------------------------------------------
-- Copyright - Advance Seven Limited, 2016
-- License - GNU GPL v3
-- see http://www.gnu.org/licenses/gpl.html
-------------------------------------------------
-------------------------------------------------
-- This code is an output from the Advance7
-- TribeLab project - see www.tribelabzero.com
-------------------------------------------------
------------------------History--------------------------
-- r1 - pjo - Initial release
-- r2 - pjo - Improved the decoding of the PCoIP and ESP
-- r3 - pjo - Removed returns from prefs labels
-- r4 - pjo - Fix sequence number bug
--
---------------------------------------------------------
-- Execution controls -------------------------------------
debug_set = false
go_bang = {}
-- End of Execution Controls ------------------------------
-- Add entries to the service port table for packets to be treated as services
-- This is populated with preferences "service ports" data
udp_svc_port = {}
-- declare the extractors for some Fields to be read
-- these work like getters
frame_number_f = Field.new("frame.number")
eth_type_f = Field.new("eth.type")
ip_proto_f = Field.new("ip.proto")
ipv6_nxt_f = Field.new("ipv6.nxt")
this_udp_src_f = Field.new("udp.srcport")
this_udp_dst_f = Field.new("udp.dstport")
udp_stream_f = Field.new("udp.stream")
this_udp_len_f = Field.new("udp.length")
this_udp_data_f = Field.new("data.data")
-- declare the PCoIP as a protocol
pcoip = Proto("pcoip","PCoIP Postdissector")
esp_seq_array = {}
info_suffix_array = {}
-- Packet information
this_frame = 0
udp_stream = 0
stream_and_dir = 0
last_frame = 0
pcoip_dir = "" -- Direction label used in the protocol tree - "C->S" or "S->C"
pcoip_dir_numeric = 0; -- 0 = C->S and 1 = S->C
pcoip_th = ByteArray.new()
esp_spi = ByteArray.new()
esp_seq = 0
pcoip_missing_count = 0 -- Number of PCoIP APDUs missing in the current sequence
-- add the field to the protocol
-- create the fields for our "protocol"
pcoip_dir_F = ProtoField.string("pcoip.dir","PCoIP Direction")
pcoip_th_F = ProtoField.string("pcoip.th","PCoIP Transport Header")
esp_spi_F = ProtoField.string("pcoip.spi","ESP SPI")
esp_seq_F = ProtoField.uint32("pcoip.seq","ESP Seq")
pcoip_missing_apdus = ProtoExpert.new("pcoip.missing_apdus.expert", "PCoIP APDUs are missing", expert.group.SEQUENCE, expert.severity.WARN)
-- add the field to the protocol
pcoip.fields = {pcoip_dir_F, pcoip_th_F, esp_spi_F, esp_seq_F}
pcoip.experts = {pcoip_missing_apdus}
-- master switch to determine whether this is a PCoIP packet
is_pcoip = false;
function string:explode( inSplitPattern, outResults )
if not outResults then
outResults = { }
end
local theStart = 1
local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
while theSplitStart do
table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
theStart = theSplitEnd + 1
theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
end
table.insert( outResults, string.sub( self, theStart ) )
return outResults
end
-- This function gets called when a new trace file is loaded
function pcoip.init()
local i
if debug_set then info("pcoip.init()") end
prefs_table = {}
prefs_table = pcoip.prefs.udpports:explode(",")
for i = 1, #prefs_table do
udp_svc_port[tonumber(prefs_table[i])] = true
end
for i=0, 20 do
esp_seq_array[i] = 0
end
return
end
-- This function set globals for common frame values.
function set_proto_values(pinfo)
this_frame = pinfo.number
if debug_set then
info("==========================================================================")
info(" ")
info("Frame: " .. this_frame)
info("Visited: " .. tostring(pinfo.visited))
end
ip_protocol = nil
is_pcoip = false -- default
pcoip_missing_count = 0
local eth_type = eth_type_f()
if not eth_type then return end -- This is an 802.3 frame
x_eth_type = eth_type.value
if x_eth_type == 0x0800 or x_eth_type == 0x86dd then
local ip_proto = ip_proto_f()
local srcport = nil
local dstport = nil
if x_eth_type == 0x0800 then ip_proto = ip_proto_f()
elseif x_eth_type == 0x86dd then ip_proto = ipv6_nxt_f()
end
this_ip_protocol = tonumber(ip_proto.value)
if this_ip_protocol == 17 then
-- It's UDP
srcport = this_udp_src_f()
dstport = this_udp_dst_f()
local udp_len = this_udp_len_f()
i_udp_len = tonumber(udp_len.value)
if i_udp_len > 0 then
this_srcport = tonumber(srcport.value)
this_dstport = tonumber(dstport.value)
if udp_svc_port[this_srcport] or udp_svc_port[this_dstport] then
if udp_svc_port[this_dstport] then
pcoip_dir = "C->S"
pcoip_dir_numeric = 0
else
pcoip_dir = "S->C"
pcoip_dir_numeric = 1
end
udp_stream = udp_stream_f()
stream_and_dir = (udp_stream.value * 2) + pcoip_dir_numeric
is_pcoip = true
end
end
end
end
end
-- This function adds the RTE data to the tree
function write_pcoip(tree)
local subtree = tree:add(pcoip,"PCoIP Header Data")
local tempString = ""
local new_item
new_item = subtree:add(pcoip_dir_F, pcoip_dir)
tempString = pcoip_th:tohex(true, ":")
new_item = subtree:add(pcoip_th_F, tempString)
tempString = esp_spi:tohex(true, ":")
new_item = subtree:add(esp_spi_F, tempString)
new_item = subtree:add(esp_seq_F, esp_seq)
-- if pcoip_missing_count > 0 then
-- new_item = subtree:add_proto_expert_info(pcoip_missing_apdus)
-- end
end
function pcoip.dissector(buffer,pinfo,tree)
local info_text
local udp_data
local ptr
local tvbr
set_proto_values(pinfo)
-- Have to wipe the info suffixes if we reload a file or load a new one
if not pinfo.visited then
info_suffix_array[this_frame] = ""
end
if debug_set then info("SNAP01 esp_seq_array[stream_and_dir]: " .. esp_seq_array[stream_and_dir]) end
if is_pcoip then
udp_data = this_udp_data_f()
ptr = udp_data.offset + 0 -- set a pointer to the offset of the PCoIP Transport Header within the tvb
tvbr = buffer:range(ptr, 4) -- set up a range
pcoip_th = tvbr:bytes() -- extract the bytes
ptr = udp_data.offset + 4 -- set a pointer to the offset of the PCoIP Transport Header within the tvb
tvbr = buffer:range(ptr, 4) -- set up a range
esp_spi = tvbr:bytes() -- extract the bytes
ptr = udp_data.offset + 8 -- set a pointer to the offset of the ESP sequence number within the tvb
tvbr = buffer:range(ptr, 4) -- set up a range
esp_seq = tvbr:uint() -- extract the integer value
if pinfo.visited then
write_pcoip(tree)
-- Set the Info column text
info_text = "PCoIP " .. pcoip_dir .. " - ESP Seq. No: " .. esp_seq
if info_suffix_array[this_frame] then
info_text = info_text .. " " .. info_suffix_array[this_frame]
end
pinfo.cols.info:set(info_text)
pinfo.cols.info:fence()
else
if debug_set then info("SNAP02 esp_seq_array[stream_and_dir]: " .. esp_seq_array[stream_and_dir]) end
-- Check for missing sequence numbers
if esp_seq < esp_seq_array[stream_and_dir] then
info_suffix_array[this_frame] = "Sequence number has wrapped"
else
if (esp_seq - 1) > esp_seq_array[stream_and_dir] then
pcoip_missing_count = esp_seq - 1 - esp_seq_array[stream_and_dir]
info_suffix_array[this_frame] = " - The " .. pcoip_missing_count .. " previous PCoIP APDUs are missing"
end
end
end
esp_seq_array[stream_and_dir] = esp_seq
if debug_set then info("SNAP03 esp_seq_array[stream_and_dir]: " .. esp_seq_array[stream_and_dir]) end
end
last_frame = this_frame
end
-- register our protocol as a postdissector
register_postdissector(pcoip)
pcoip.prefs.header = Pref.statictext("PCoIP Dissector r4")
-- Create a range preference for the service ports that this dissector should process
-- Create a range preference that shows under Foo Protocol's preferences
pcoip.prefs.udpports = Pref.range("PCoIP UDP service ports", "4172", "Add and remove ports numbers separated by commas", 65535)
pcoip.prefs.footer = Pref.statictext("Developed by the TribeLab team at Advance7 - see www.tribelab.com", "")