/src/wireshark/epan/dissectors/packet-lbtru.c
Line | Count | Source |
1 | | /* packet-lbtru.c |
2 | | * Routines for LBT-RU Packet dissection |
3 | | * |
4 | | * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved. |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | #include <epan/packet.h> |
15 | | #include <epan/prefs.h> |
16 | | #include <epan/expert.h> |
17 | | #include <epan/uat.h> |
18 | | #include <epan/conversation.h> |
19 | | #include <epan/to_str.h> |
20 | | #include <epan/tap.h> |
21 | | #include "packet-lbm.h" |
22 | | #include "packet-lbtru.h" |
23 | | |
24 | | void proto_register_lbtru(void); |
25 | | void proto_reg_handoff_lbtru(void); |
26 | | |
27 | | /* Protocol handle */ |
28 | | static int proto_lbtru; |
29 | | |
30 | | /* Dissector handle */ |
31 | | static dissector_handle_t lbtru_dissector_handle; |
32 | | |
33 | | /* Tap handle */ |
34 | | static int lbtru_tap_handle = -1; |
35 | | |
36 | | /*----------------------------------------------------------------------------*/ |
37 | | /* LBT-RU transport management. */ |
38 | | /*----------------------------------------------------------------------------*/ |
39 | | |
40 | | static const address lbtru_null_address = ADDRESS_INIT_NONE; |
41 | | |
42 | | static lbtru_transport_t * lbtru_transport_find(const address * source_address, uint16_t source_port, uint32_t session_id, uint32_t frame) |
43 | 0 | { |
44 | 0 | lbtru_transport_t * entry = NULL; |
45 | 0 | wmem_tree_t * session_tree = NULL; |
46 | 0 | conversation_t * conv = NULL; |
47 | |
|
48 | 0 | conv = find_conversation(frame, source_address, &lbtru_null_address, CONVERSATION_UDP, source_port, 0, 0); |
49 | 0 | if (conv != NULL) |
50 | 0 | { |
51 | 0 | if (frame != 0) |
52 | 0 | { |
53 | 0 | if (conv->setup_frame == 0) |
54 | 0 | { |
55 | 0 | conv->setup_frame = frame; |
56 | 0 | } |
57 | 0 | if (frame > conv->last_frame) |
58 | 0 | { |
59 | 0 | conv->last_frame = frame; |
60 | 0 | } |
61 | 0 | } |
62 | 0 | session_tree = (wmem_tree_t *) conversation_get_proto_data(conv, proto_lbtru); |
63 | 0 | if (session_tree != NULL) |
64 | 0 | { |
65 | 0 | entry = (lbtru_transport_t *) wmem_tree_lookup32(session_tree, session_id); |
66 | 0 | } |
67 | 0 | } |
68 | 0 | return (entry); |
69 | 0 | } |
70 | | |
71 | | lbtru_transport_t * lbtru_transport_add(const address * source_address, uint16_t source_port, uint32_t session_id, uint32_t frame) |
72 | 0 | { |
73 | 0 | lbtru_transport_t * entry = NULL; |
74 | 0 | wmem_tree_t * session_tree = NULL; |
75 | 0 | conversation_t * conv = NULL; |
76 | |
|
77 | 0 | conv = find_conversation(frame, source_address, &lbtru_null_address, CONVERSATION_UDP, source_port, 0, 0); |
78 | 0 | if (conv == NULL) |
79 | 0 | { |
80 | 0 | conv = conversation_new(frame, source_address, &lbtru_null_address, CONVERSATION_UDP, source_port, 0, 0); |
81 | 0 | } |
82 | 0 | if (frame != 0) |
83 | 0 | { |
84 | 0 | if (conv->setup_frame == 0) |
85 | 0 | { |
86 | 0 | conv->setup_frame = frame; |
87 | 0 | } |
88 | 0 | if (frame > conv->last_frame) |
89 | 0 | { |
90 | 0 | conv->last_frame = frame; |
91 | 0 | } |
92 | 0 | } |
93 | 0 | session_tree = (wmem_tree_t *) conversation_get_proto_data(conv, proto_lbtru); |
94 | 0 | if (session_tree == NULL) |
95 | 0 | { |
96 | 0 | session_tree = wmem_tree_new(wmem_file_scope()); |
97 | 0 | conversation_add_proto_data(conv, proto_lbtru, (void *)session_tree); |
98 | 0 | } |
99 | 0 | entry = (lbtru_transport_t *) wmem_tree_lookup32(session_tree, session_id); |
100 | 0 | if (entry != NULL) |
101 | 0 | { |
102 | 0 | return (entry); |
103 | 0 | } |
104 | 0 | entry = wmem_new(wmem_file_scope(), lbtru_transport_t); |
105 | 0 | copy_address_wmem(wmem_file_scope(), &(entry->source_address), source_address); |
106 | 0 | entry->source_port = source_port; |
107 | 0 | entry->session_id = session_id; |
108 | 0 | entry->channel = lbm_channel_assign(LBM_CHANNEL_TRANSPORT_LBTRU); |
109 | 0 | entry->next_client_id = 1; |
110 | 0 | entry->client_list = wmem_list_new(wmem_file_scope()); |
111 | 0 | wmem_tree_insert32(session_tree, session_id, (void *) entry); |
112 | 0 | return (entry); |
113 | 0 | } |
114 | | |
115 | | static lbtru_client_transport_t * lbtru_client_transport_find(lbtru_transport_t * transport, const address * receiver_address, uint16_t receiver_port, uint32_t frame) |
116 | 0 | { |
117 | 0 | lbtru_client_transport_t * entry = NULL; |
118 | 0 | conversation_t * client_conv = NULL; |
119 | |
|
120 | 0 | if (transport == NULL) |
121 | 0 | { |
122 | 0 | return (NULL); |
123 | 0 | } |
124 | 0 | client_conv = find_conversation(frame, &(transport->source_address), receiver_address, CONVERSATION_UDP, transport->source_port, receiver_port, 0); |
125 | 0 | if (client_conv != NULL) |
126 | 0 | { |
127 | 0 | wmem_tree_t * session_tree = NULL; |
128 | |
|
129 | 0 | session_tree = (wmem_tree_t *) conversation_get_proto_data(client_conv, proto_lbtru); |
130 | 0 | if (session_tree != NULL) |
131 | 0 | { |
132 | 0 | entry = (lbtru_client_transport_t *) wmem_tree_lookup32(session_tree, transport->session_id); |
133 | 0 | } |
134 | 0 | } |
135 | 0 | return (entry); |
136 | 0 | } |
137 | | |
138 | | static lbtru_client_transport_t * lbtru_client_transport_add(lbtru_transport_t * transport, const address * receiver_address, uint16_t receiver_port, uint32_t frame) |
139 | 0 | { |
140 | 0 | lbtru_client_transport_t * entry = NULL; |
141 | 0 | conversation_t * client_conv = NULL; |
142 | 0 | wmem_tree_t * session_tree = NULL; |
143 | |
|
144 | 0 | if (transport == NULL) |
145 | 0 | { |
146 | 0 | return (NULL); |
147 | 0 | } |
148 | 0 | entry = lbtru_client_transport_find(transport, receiver_address, receiver_port, frame); |
149 | 0 | if (entry != NULL) |
150 | 0 | { |
151 | 0 | return (entry); |
152 | 0 | } |
153 | 0 | entry = wmem_new0(wmem_file_scope(), lbtru_client_transport_t); |
154 | 0 | copy_address_wmem(wmem_file_scope(), &(entry->receiver_address), receiver_address); |
155 | 0 | entry->receiver_port = receiver_port; |
156 | 0 | entry->transport = transport; |
157 | 0 | entry->id = transport->next_client_id++; |
158 | 0 | entry->frame = wmem_tree_new(wmem_file_scope()); |
159 | 0 | entry->last_frame = NULL; |
160 | 0 | entry->last_data_frame = NULL; |
161 | 0 | entry->last_sm_frame = NULL; |
162 | 0 | entry->last_nak_frame = NULL; |
163 | 0 | entry->last_ncf_frame = NULL; |
164 | 0 | entry->last_ack_frame = NULL; |
165 | 0 | entry->last_creq_frame = NULL; |
166 | 0 | entry->last_rst_frame = NULL; |
167 | 0 | entry->data_sqn = wmem_tree_new(wmem_file_scope()); |
168 | 0 | entry->sm_sqn = wmem_tree_new(wmem_file_scope()); |
169 | 0 | entry->data_high_sqn = 0; |
170 | 0 | entry->sm_high_sqn = 0; |
171 | | |
172 | | /* See if a conversation for this address/port pair exists. */ |
173 | 0 | client_conv = find_conversation(frame, &(transport->source_address), receiver_address, CONVERSATION_UDP, transport->source_port, receiver_port, 0); |
174 | 0 | if (client_conv == NULL) |
175 | 0 | { |
176 | 0 | client_conv = conversation_new(frame, &(transport->source_address), receiver_address, CONVERSATION_UDP, transport->source_port, receiver_port, 0); |
177 | 0 | session_tree = wmem_tree_new(wmem_file_scope()); |
178 | 0 | conversation_add_proto_data(client_conv, proto_lbtru, (void *) session_tree); |
179 | 0 | } |
180 | 0 | else |
181 | 0 | { |
182 | 0 | session_tree = (wmem_tree_t *) conversation_get_proto_data(client_conv, proto_lbtru); |
183 | 0 | if (session_tree == NULL) |
184 | 0 | { |
185 | 0 | session_tree = wmem_tree_new(wmem_file_scope()); |
186 | 0 | conversation_add_proto_data(client_conv, proto_lbtru, (void *) session_tree); |
187 | 0 | } |
188 | 0 | } |
189 | 0 | wmem_tree_insert32(session_tree, transport->session_id, (void *) entry); |
190 | | |
191 | | /* Add this client to the transport. */ |
192 | 0 | wmem_list_append(transport->client_list, (void *) entry); |
193 | 0 | return (entry); |
194 | 0 | } |
195 | | |
196 | | static lbm_transport_sqn_t * lbtru_client_transport_sqn_find(lbtru_client_transport_t * client, uint8_t type, uint32_t sqn) |
197 | 0 | { |
198 | 0 | lbm_transport_sqn_t * sqn_entry = NULL; |
199 | |
|
200 | 0 | switch (type) |
201 | 0 | { |
202 | 0 | case LBTRU_PACKET_TYPE_DATA: |
203 | 0 | sqn_entry = (lbm_transport_sqn_t *) wmem_tree_lookup32(client->data_sqn, sqn); |
204 | 0 | break; |
205 | 0 | case LBTRU_PACKET_TYPE_SM: |
206 | 0 | sqn_entry = (lbm_transport_sqn_t *) wmem_tree_lookup32(client->sm_sqn, sqn); |
207 | 0 | break; |
208 | 0 | case LBTRU_PACKET_TYPE_NAK: |
209 | 0 | case LBTRU_PACKET_TYPE_NCF: |
210 | 0 | case LBTRU_PACKET_TYPE_ACK: |
211 | 0 | case LBTRU_PACKET_TYPE_CREQ: |
212 | 0 | case LBTRU_PACKET_TYPE_RST: |
213 | 0 | default: |
214 | 0 | sqn_entry = NULL; |
215 | 0 | break; |
216 | 0 | } |
217 | 0 | return (sqn_entry); |
218 | 0 | } |
219 | | |
220 | | static lbm_transport_sqn_t * lbtru_client_transport_sqn_add(lbtru_client_transport_t * client, lbm_transport_frame_t * frame) |
221 | 0 | { |
222 | 0 | wmem_tree_t * sqn_list = NULL; |
223 | 0 | lbm_transport_sqn_t * sqn_entry = NULL; |
224 | |
|
225 | 0 | switch (frame->type) |
226 | 0 | { |
227 | 0 | case LBTRU_PACKET_TYPE_DATA: |
228 | 0 | sqn_list = client->data_sqn; |
229 | 0 | break; |
230 | 0 | case LBTRU_PACKET_TYPE_SM: |
231 | 0 | sqn_list = client->sm_sqn; |
232 | 0 | break; |
233 | 0 | case LBTRU_PACKET_TYPE_NAK: |
234 | 0 | case LBTRU_PACKET_TYPE_NCF: |
235 | 0 | case LBTRU_PACKET_TYPE_ACK: |
236 | 0 | case LBTRU_PACKET_TYPE_CREQ: |
237 | 0 | case LBTRU_PACKET_TYPE_RST: |
238 | 0 | default: |
239 | 0 | return (NULL); |
240 | 0 | } |
241 | | |
242 | | /* Add the sqn. */ |
243 | 0 | sqn_entry = lbm_transport_sqn_add(sqn_list, frame); |
244 | 0 | return (sqn_entry); |
245 | 0 | } |
246 | | |
247 | | static lbm_transport_frame_t * lbtru_client_transport_frame_find(lbtru_client_transport_t * client, uint32_t frame) |
248 | 0 | { |
249 | 0 | return ((lbm_transport_frame_t *) wmem_tree_lookup32(client->frame, frame)); |
250 | 0 | } |
251 | | |
252 | | static lbm_transport_frame_t * lbtru_client_transport_frame_add(lbtru_client_transport_t * client, uint8_t type, uint32_t frame, uint32_t sqn, bool retransmission) |
253 | 0 | { |
254 | 0 | lbm_transport_sqn_t * dup_sqn_entry = NULL; |
255 | 0 | lbm_transport_frame_t * frame_entry = NULL; |
256 | | |
257 | | /* Locate the frame. */ |
258 | 0 | frame_entry = lbtru_client_transport_frame_find(client, frame); |
259 | 0 | if (frame_entry != NULL) |
260 | 0 | { |
261 | 0 | return (frame_entry); |
262 | 0 | } |
263 | 0 | frame_entry = lbm_transport_frame_add(client->frame, type, frame, sqn, retransmission); |
264 | 0 | if (client->last_frame != NULL) |
265 | 0 | { |
266 | 0 | frame_entry->previous_frame = client->last_frame->frame; |
267 | 0 | client->last_frame->next_frame = frame; |
268 | 0 | } |
269 | 0 | client->last_frame = frame_entry; |
270 | 0 | switch (type) |
271 | 0 | { |
272 | 0 | case LBTRU_PACKET_TYPE_DATA: |
273 | 0 | if (client->last_data_frame != NULL) |
274 | 0 | { |
275 | 0 | frame_entry->previous_type_frame = client->last_data_frame->frame; |
276 | 0 | client->last_data_frame->next_type_frame = frame; |
277 | | /* Ideally, this frame's sqn is 1 more than the highest data sqn seen */ |
278 | 0 | if (frame_entry->sqn <= client->data_high_sqn) |
279 | 0 | { |
280 | 0 | dup_sqn_entry = lbtru_client_transport_sqn_find(client, type, frame_entry->sqn); |
281 | 0 | if (!frame_entry->retransmission) |
282 | 0 | { |
283 | | /* Out of order */ |
284 | 0 | if (dup_sqn_entry != NULL) |
285 | 0 | { |
286 | 0 | frame_entry->duplicate = true; |
287 | 0 | } |
288 | 0 | if (frame_entry->sqn != client->data_high_sqn) |
289 | 0 | { |
290 | 0 | frame_entry->ooo_gap = client->data_high_sqn - frame_entry->sqn; |
291 | 0 | } |
292 | 0 | } |
293 | 0 | } |
294 | 0 | else |
295 | 0 | { |
296 | 0 | if (!frame_entry->retransmission) |
297 | 0 | { |
298 | 0 | if (frame_entry->sqn != (client->data_high_sqn + 1)) |
299 | 0 | { |
300 | | /* Gap */ |
301 | 0 | frame_entry->sqn_gap = frame_entry->sqn - (client->last_data_frame->sqn + 1); |
302 | 0 | } |
303 | 0 | } |
304 | 0 | } |
305 | 0 | } |
306 | 0 | if ((frame_entry->sqn > client->data_high_sqn) && !frame_entry->retransmission) |
307 | 0 | { |
308 | 0 | client->data_high_sqn = frame_entry->sqn; |
309 | 0 | } |
310 | 0 | client->last_data_frame = frame_entry; |
311 | 0 | break; |
312 | 0 | case LBTRU_PACKET_TYPE_SM: |
313 | 0 | if (client->last_sm_frame != NULL) |
314 | 0 | { |
315 | 0 | frame_entry->previous_type_frame = client->last_sm_frame->frame; |
316 | 0 | client->last_sm_frame->next_type_frame = frame; |
317 | | /* Ideally, this frame's sqn is 1 more than the highest SM sqn seen */ |
318 | 0 | if (frame_entry->sqn <= client->sm_high_sqn) |
319 | 0 | { |
320 | | /* Out of order */ |
321 | 0 | dup_sqn_entry = lbtru_client_transport_sqn_find(client, type, frame_entry->sqn); |
322 | 0 | if (dup_sqn_entry != NULL) |
323 | 0 | { |
324 | 0 | frame_entry->duplicate = true; |
325 | 0 | } |
326 | 0 | if (frame_entry->sqn != client->sm_high_sqn) |
327 | 0 | { |
328 | 0 | frame_entry->ooo_gap = client->sm_high_sqn - frame_entry->sqn; |
329 | 0 | } |
330 | 0 | } |
331 | 0 | else |
332 | 0 | { |
333 | 0 | if (frame_entry->sqn != (client->sm_high_sqn + 1)) |
334 | 0 | { |
335 | | /* Gap */ |
336 | 0 | frame_entry->sqn_gap = frame_entry->sqn - (client->sm_high_sqn + 1); |
337 | 0 | } |
338 | 0 | } |
339 | 0 | } |
340 | 0 | if (frame_entry->sqn > client->sm_high_sqn) |
341 | 0 | { |
342 | 0 | client->sm_high_sqn = frame_entry->sqn; |
343 | 0 | } |
344 | 0 | client->last_sm_frame = frame_entry; |
345 | 0 | break; |
346 | 0 | case LBTRU_PACKET_TYPE_NAK: |
347 | 0 | if (client->last_nak_frame != NULL) |
348 | 0 | { |
349 | 0 | frame_entry->previous_type_frame = client->last_nak_frame->frame; |
350 | 0 | client->last_nak_frame->next_type_frame = frame; |
351 | 0 | } |
352 | 0 | client->last_nak_frame = frame_entry; |
353 | 0 | break; |
354 | 0 | case LBTRU_PACKET_TYPE_NCF: |
355 | 0 | if (client->last_ncf_frame != NULL) |
356 | 0 | { |
357 | 0 | frame_entry->previous_type_frame = client->last_ncf_frame->frame; |
358 | 0 | client->last_ncf_frame->next_type_frame = frame; |
359 | 0 | } |
360 | 0 | client->last_ncf_frame = frame_entry; |
361 | 0 | break; |
362 | 0 | case LBTRU_PACKET_TYPE_ACK: |
363 | 0 | if (client->last_ack_frame != NULL) |
364 | 0 | { |
365 | 0 | frame_entry->previous_type_frame = client->last_ack_frame->frame; |
366 | 0 | client->last_ack_frame->next_type_frame = frame; |
367 | 0 | } |
368 | 0 | client->last_ack_frame = frame_entry; |
369 | 0 | break; |
370 | 0 | case LBTRU_PACKET_TYPE_CREQ: |
371 | 0 | if (client->last_creq_frame != NULL) |
372 | 0 | { |
373 | 0 | frame_entry->previous_type_frame = client->last_creq_frame->frame; |
374 | 0 | client->last_creq_frame->next_type_frame = frame; |
375 | 0 | } |
376 | 0 | client->last_creq_frame = frame_entry; |
377 | 0 | break; |
378 | 0 | case LBTRU_PACKET_TYPE_RST: |
379 | 0 | if (client->last_rst_frame != NULL) |
380 | 0 | { |
381 | 0 | frame_entry->previous_type_frame = client->last_rst_frame->frame; |
382 | 0 | client->last_rst_frame->next_type_frame = frame; |
383 | 0 | } |
384 | 0 | client->last_rst_frame = frame_entry; |
385 | 0 | break; |
386 | 0 | } |
387 | | |
388 | | /* Add the sqn. */ |
389 | 0 | (void)lbtru_client_transport_sqn_add(client, frame_entry); |
390 | 0 | return (frame_entry); |
391 | 0 | } |
392 | | |
393 | | static char * lbtru_transport_source_string_format(wmem_allocator_t *scope, const address * source_address, uint16_t source_port, uint32_t session_id) |
394 | 0 | { |
395 | 0 | char * bufptr = NULL; |
396 | |
|
397 | 0 | if (session_id == 0) |
398 | 0 | { |
399 | 0 | bufptr = wmem_strdup_printf(scope, "LBT-RU:%s:%" PRIu16, address_to_str(scope, source_address), source_port); |
400 | 0 | } |
401 | 0 | else |
402 | 0 | { |
403 | 0 | bufptr = wmem_strdup_printf(scope, "LBT-RU:%s:%" PRIu16 ":%08x", address_to_str(scope, source_address), source_port, session_id); |
404 | 0 | } |
405 | 0 | return (bufptr); |
406 | 0 | } |
407 | | |
408 | | char * lbtru_transport_source_string(const address * source_address, uint16_t source_port, uint32_t session_id) |
409 | 0 | { |
410 | | /* Returns a file-scoped string. */ |
411 | 0 | return lbtru_transport_source_string_format(wmem_file_scope(), source_address, source_port, session_id); |
412 | 0 | } |
413 | | |
414 | | static char * lbtru_transport_source_string_transport(wmem_allocator_t *scope, lbtru_transport_t * transport) |
415 | 0 | { |
416 | 0 | return lbtru_transport_source_string_format(scope, &(transport->source_address), transport->source_port, transport->session_id); |
417 | 0 | } |
418 | | |
419 | | /*----------------------------------------------------------------------------*/ |
420 | | /* Packet layouts. */ |
421 | | /*----------------------------------------------------------------------------*/ |
422 | | |
423 | | /* LBT-RU main header */ |
424 | | typedef struct |
425 | | { |
426 | | lbm_uint8_t ver_type; |
427 | | lbm_uint8_t next_hdr; |
428 | | lbm_uint16_t flags_or_res; |
429 | | } lbtru_hdr_t; |
430 | 0 | #define O_LBTRU_HDR_T_VER_TYPE OFFSETOF(lbtru_hdr_t, ver_type) |
431 | 0 | #define L_LBTRU_HDR_T_VER_TYPE SIZEOF(lbtru_hdr_t, ver_type) |
432 | 0 | #define O_LBTRU_HDR_T_NEXT_HDR OFFSETOF(lbtru_hdr_t, next_hdr) |
433 | 0 | #define L_LBTRU_HDR_T_NEXT_HDR SIZEOF(lbtru_hdr_t, next_hdr) |
434 | 0 | #define O_LBTRU_HDR_T_FLAGS_OR_RES OFFSETOF(lbtru_hdr_t, flags_or_res) |
435 | 30 | #define L_LBTRU_HDR_T_FLAGS_OR_RES SIZEOF(lbtru_hdr_t, flags_or_res) |
436 | 0 | #define L_LBTRU_HDR_T (int) sizeof(lbtru_hdr_t) |
437 | | |
438 | | #define LBTRU_VERSION 0x00 |
439 | 0 | #define LBTRU_HDR_VER(x) (x >> 4) |
440 | 0 | #define LBTRU_HDR_TYPE(x) (x & 0x0F) |
441 | 15 | #define LBTRU_HDR_VER_VER_MASK 0xF0 |
442 | 15 | #define LBTRU_HDR_VER_TYPE_MASK 0x0F |
443 | | |
444 | 15 | #define LBTRU_RETRANSMISSION_FLAG 0x4000 |
445 | | |
446 | | /* LBT-RU data header */ |
447 | | typedef struct |
448 | | { |
449 | | lbm_uint32_t sqn; |
450 | | lbm_uint32_t trail_sqn; |
451 | | } lbtru_data_hdr_t; |
452 | 0 | #define O_LBTRU_DATA_HDR_T_SQN OFFSETOF(lbtru_data_hdr_t, sqn) |
453 | 0 | #define L_LBTRU_DATA_HDR_T_SQN SIZEOF(lbtru_data_hdr_t, sqn) |
454 | 0 | #define O_LBTRU_DATA_HDR_T_TRAIL_SQN OFFSETOF(lbtru_data_hdr_t, trail_sqn) |
455 | 0 | #define L_LBTRU_DATA_HDR_T_TRAIL_SQN SIZEOF(lbtru_data_hdr_t, trail_sqn) |
456 | 0 | #define L_LBTRU_DATA_HDR_T (int) (sizeof(lbtru_data_hdr_t)) |
457 | | |
458 | | /* LBT-RU Session Message header */ |
459 | | typedef struct |
460 | | { |
461 | | lbm_uint32_t sm_sqn; |
462 | | lbm_uint32_t lead_sqn; |
463 | | lbm_uint32_t trail_sqn; |
464 | | } lbtru_sm_hdr_t; |
465 | 0 | #define O_LBTRU_SM_HDR_T_SM_SQN OFFSETOF(lbtru_sm_hdr_t, sm_sqn) |
466 | 0 | #define L_LBTRU_SM_HDR_T_SM_SQN SIZEOF(lbtru_sm_hdr_t, sm_sqn) |
467 | 0 | #define O_LBTRU_SM_HDR_T_LEAD_SQN OFFSETOF(lbtru_sm_hdr_t, lead_sqn) |
468 | 0 | #define L_LBTRU_SM_HDR_T_LEAD_SQN SIZEOF(lbtru_sm_hdr_t, lead_sqn) |
469 | 0 | #define O_LBTRU_SM_HDR_T_TRAIL_SQN OFFSETOF(lbtru_sm_hdr_t, trail_sqn) |
470 | 0 | #define L_LBTRU_SM_HDR_T_TRAIL_SQN SIZEOF(lbtru_sm_hdr_t, trail_sqn) |
471 | 0 | #define L_LBTRU_SM_HDR_T (int) (sizeof(lbtru_sm_hdr_t)) |
472 | | |
473 | 15 | #define LBTRU_SM_SYN_FLAG 0x8000 |
474 | | |
475 | | /* LBT-RU NAK header */ |
476 | | typedef struct |
477 | | { |
478 | | lbm_uint16_t num_naks; |
479 | | lbm_uint16_t format; |
480 | | } lbtru_nak_hdr_t; |
481 | 0 | #define O_LBTRU_NAK_HDR_T_NUM_NAKS OFFSETOF(lbtru_nak_hdr_t, num_naks) |
482 | 0 | #define L_LBTRU_NAK_HDR_T_NUM_NAKS SIZEOF(lbtru_nak_hdr_t, num_naks) |
483 | 0 | #define O_LBTRU_NAK_HDR_T_FORMAT OFFSETOF(lbtru_nak_hdr_t, format) |
484 | 0 | #define L_LBTRU_NAK_HDR_T_FORMAT SIZEOF(lbtru_nak_hdr_t, format) |
485 | 0 | #define L_LBTRU_NAK_HDR_T (int) (sizeof(lbtru_nak_hdr_t)) |
486 | | |
487 | | #define LBTRU_NAK_SELECTIVE_FORMAT 0x0 |
488 | 15 | #define LBTRU_NAK_HDR_FORMAT_MASK 0x000F |
489 | | #define LBTRU_NAK_HDR_FORMAT(x) (x & 0xF) |
490 | | |
491 | | /* LBT-RU NAK Confirmation header */ |
492 | | typedef struct |
493 | | { |
494 | | lbm_uint32_t trail_sqn; |
495 | | lbm_uint16_t num_ncfs; |
496 | | lbm_uint8_t reserved; |
497 | | lbm_uint8_t reason_format; |
498 | | } lbtru_ncf_hdr_t; |
499 | 0 | #define O_LBTRU_NCF_HDR_T_TRAIL_SQN OFFSETOF(lbtru_ncf_hdr_t, trail_sqn) |
500 | 0 | #define L_LBTRU_NCF_HDR_T_TRAIL_SQN SIZEOF(lbtru_ncf_hdr_t, trail_sqn) |
501 | 0 | #define O_LBTRU_NCF_HDR_T_NUM_NCFS OFFSETOF(lbtru_ncf_hdr_t, num_ncfs) |
502 | 0 | #define L_LBTRU_NCF_HDR_T_NUM_NCFS SIZEOF(lbtru_ncf_hdr_t, num_ncfs) |
503 | 0 | #define O_LBTRU_NCF_HDR_T_RESERVED OFFSETOF(lbtru_ncf_hdr_t, reserved) |
504 | 0 | #define L_LBTRU_NCF_HDR_T_RESERVED SIZEOF(lbtru_ncf_hdr_t, reserved) |
505 | 0 | #define O_LBTRU_NCF_HDR_T_REASON_FORMAT OFFSETOF(lbtru_ncf_hdr_t, reason_format) |
506 | 0 | #define L_LBTRU_NCF_HDR_T_REASON_FORMAT SIZEOF(lbtru_ncf_hdr_t, reason_format) |
507 | 0 | #define L_LBTRU_NCF_HDR_T (int) (sizeof(lbtru_ncf_hdr_t)) |
508 | | |
509 | | #define LBTRU_NCF_SELECTIVE_FORMAT 0x0 |
510 | 0 | #define LBTRU_NCF_HDR_REASON(x) ((x & 0xF0) >> 4) |
511 | | #define LBTRU_NCF_HDR_FORMAT(x) (x & 0xF) |
512 | 15 | #define LBTRU_NCF_HDR_REASON_MASK 0xF0 |
513 | 15 | #define LBTRU_NCF_HDR_FORMAT_MASK 0x0F |
514 | | |
515 | | /* LBT-RU ACK header */ |
516 | | typedef struct |
517 | | { |
518 | | lbm_uint32_t ack_sqn; |
519 | | } lbtru_ack_hdr_t; |
520 | 0 | #define O_LBTRU_ACK_HDR_T_ACK_SQN OFFSETOF(lbtru_ack_hdr_t, ack_sqn) |
521 | 0 | #define L_LBTRU_ACK_HDR_T_ACK_SQN SIZEOF(lbtru_ack_hdr_t, ack_sqn) |
522 | 0 | #define L_LBTRU_ACK_HDR_T (int) (sizeof(lbtru_ack_hdr_t)) |
523 | | |
524 | | /* LBT-RU basic option header */ |
525 | | typedef struct |
526 | | { |
527 | | lbm_uint8_t next_hdr; |
528 | | lbm_uint8_t hdr_len; |
529 | | lbm_uint16_t res; |
530 | | } lbtru_basic_opt_t; |
531 | 0 | #define O_LBTRU_BASIC_OPT_T_NEXT_HDR OFFSETOF(lbtru_basic_opt_t, next_hdr) |
532 | 0 | #define L_LBTRU_BASIC_OPT_T_NEXT_HDR SIZEOF(lbtru_basic_opt_t, next_hdr) |
533 | 0 | #define O_LBTRU_BASIC_OPT_T_HDR_LEN OFFSETOF(lbtru_basic_opt_t, hdr_len) |
534 | 0 | #define L_LBTRU_BASIC_OPT_T_HDR_LEN SIZEOF(lbtru_basic_opt_t, hdr_len) |
535 | 0 | #define O_LBTRU_BASIC_OPT_T_RES OFFSETOF(lbtru_basic_opt_t, res) |
536 | 30 | #define L_LBTRU_BASIC_OPT_T_RES SIZEOF(lbtru_basic_opt_t, res) |
537 | 0 | #define L_LBTRU_BASIC_OPT_T (int) (sizeof(lbtru_basic_opt_t)) |
538 | | |
539 | | /* LBT-RU Session ID option header */ |
540 | | typedef struct |
541 | | { |
542 | | lbm_uint32_t session_id; |
543 | | } lbtru_sid_opt_t; |
544 | 0 | #define O_LBTRU_SID_OPT_T_SESSION_ID OFFSETOF(lbtru_sid_opt_t, session_id) |
545 | 0 | #define L_LBTRU_SID_OPT_T_SESSION_ID SIZEOF(lbtru_sid_opt_t, session_id) |
546 | 0 | #define L_LBTRU_SID_OPT_T (int) (sizeof(lbtru_sid_opt_t)) |
547 | | |
548 | | /* LBT-RU Client ID option header */ |
549 | | typedef struct |
550 | | { |
551 | | lbm_uint32_t client_sid; |
552 | | } lbtru_cid_opt_t; |
553 | 0 | #define O_LBTRU_CID_OPT_T_CLIENT_SID OFFSETOF(lbtru_cid_opt_t, client_sid) |
554 | 0 | #define L_LBTRU_CID_OPT_T_CLIENT_SID SIZEOF(lbtru_cid_opt_t, client_sid) |
555 | 0 | #define L_LBTRU_CID_OPT_T (int) (sizeof(lbtru_cid_opt_t)) |
556 | | |
557 | 30 | #define LBTRU_OPT_IGNORE 0x8000 |
558 | | |
559 | 0 | #define LBTRU_NHDR_DATA 0x00 |
560 | 0 | #define LBTRU_NHDR_SID 0x01 |
561 | 0 | #define LBTRU_NHDR_CID 0x02 |
562 | | |
563 | | /*----------------------------------------------------------------------------*/ |
564 | | /* Value translation tables. */ |
565 | | /*----------------------------------------------------------------------------*/ |
566 | | |
567 | | static const value_string lbtru_packet_type[] = |
568 | | { |
569 | | { LBTRU_PACKET_TYPE_DATA, "DATA" }, |
570 | | { LBTRU_PACKET_TYPE_SM, "SM" }, |
571 | | { LBTRU_PACKET_TYPE_NAK, "NAK" }, |
572 | | { LBTRU_PACKET_TYPE_NCF, "NCF" }, |
573 | | { LBTRU_PACKET_TYPE_ACK, "ACK" }, |
574 | | { LBTRU_PACKET_TYPE_CREQ, "CREQ" }, |
575 | | { LBTRU_PACKET_TYPE_RST, "RST" }, |
576 | | { 0x0, NULL } |
577 | | }; |
578 | | |
579 | | static const value_string lbtru_nak_format[] = |
580 | | { |
581 | | { LBTRU_NAK_SELECTIVE_FORMAT, "Selective" }, |
582 | | { 0x0, NULL } |
583 | | }; |
584 | | |
585 | | static const value_string lbtru_ncf_format[] = |
586 | | { |
587 | | { LBTRU_NCF_SELECTIVE_FORMAT, "Selective" }, |
588 | | { 0x0, NULL } |
589 | | }; |
590 | | |
591 | | static const value_string lbtru_ncf_reason[] = |
592 | | { |
593 | | { LBTRU_NCF_REASON_NO_RETRY, "Do not retry" }, |
594 | | { LBTRU_NCF_REASON_IGNORED, "NAK Ignored" }, |
595 | | { LBTRU_NCF_REASON_RX_DELAY, "Retransmit Delay" }, |
596 | | { LBTRU_NCF_REASON_SHED, "NAK Shed" }, |
597 | | { 0x0, NULL } |
598 | | }; |
599 | | |
600 | | static const value_string lbtru_creq_request[] = |
601 | | { |
602 | | { LBTRU_CREQ_REQUEST_SYN, "SYN" }, |
603 | | { 0x0, NULL } |
604 | | }; |
605 | | |
606 | | static const value_string lbtru_rst_reason[] = |
607 | | { |
608 | | { LBTRU_RST_REASON_DEFAULT, "Default" }, |
609 | | { 0x0, NULL } |
610 | | }; |
611 | | |
612 | | static const value_string lbtru_next_header[] = |
613 | | { |
614 | | { LBTRU_NHDR_DATA, "DATA" }, |
615 | | { LBTRU_NHDR_SID, "SID" }, |
616 | | { LBTRU_NHDR_CID, "CID" }, |
617 | | { 0x0, NULL } |
618 | | }; |
619 | | |
620 | | /*----------------------------------------------------------------------------*/ |
621 | | /* Preferences. */ |
622 | | /*----------------------------------------------------------------------------*/ |
623 | | |
624 | | /* Preferences default values. */ |
625 | | #define LBTRU_DEFAULT_SOURCE_PORT_LOW 14380 |
626 | | #define LBTRU_DEFAULT_SOURCE_PORT_HIGH 14389 |
627 | | #define LBTRU_DEFAULT_RECEIVER_PORT_LOW 14360 |
628 | | #define LBTRU_DEFAULT_RECEIVER_PORT_HIGH 14379 |
629 | | |
630 | | /* Global preferences variables (altered by the preferences dialog). */ |
631 | | static uint32_t global_lbtru_source_port_low = LBTRU_DEFAULT_SOURCE_PORT_LOW; |
632 | | static uint32_t global_lbtru_source_port_high = LBTRU_DEFAULT_SOURCE_PORT_HIGH; |
633 | | static uint32_t global_lbtru_receiver_port_low = LBTRU_DEFAULT_RECEIVER_PORT_LOW; |
634 | | static uint32_t global_lbtru_receiver_port_high = LBTRU_DEFAULT_RECEIVER_PORT_HIGH; |
635 | | static bool global_lbtru_expert_separate_naks; |
636 | | static bool global_lbtru_expert_separate_ncfs; |
637 | | static bool global_lbtru_use_tag; |
638 | | static bool global_lbtru_sequence_analysis; |
639 | | |
640 | | /* Local preferences variables (used by the dissector). */ |
641 | | static uint32_t lbtru_source_port_low = LBTRU_DEFAULT_SOURCE_PORT_LOW; |
642 | | static uint32_t lbtru_source_port_high = LBTRU_DEFAULT_SOURCE_PORT_HIGH; |
643 | | static uint32_t lbtru_receiver_port_low = LBTRU_DEFAULT_RECEIVER_PORT_LOW; |
644 | | static uint32_t lbtru_receiver_port_high = LBTRU_DEFAULT_RECEIVER_PORT_HIGH; |
645 | | static bool lbtru_expert_separate_naks; |
646 | | static bool lbtru_expert_separate_ncfs; |
647 | | static bool lbtru_use_tag; |
648 | | static bool lbtru_sequence_analysis; |
649 | | |
650 | | /*----------------------------------------------------------------------------*/ |
651 | | /* Tag management. */ |
652 | | /*----------------------------------------------------------------------------*/ |
653 | | typedef struct |
654 | | { |
655 | | char * name; |
656 | | uint32_t source_port_low; |
657 | | uint32_t source_port_high; |
658 | | uint32_t receiver_port_low; |
659 | | uint32_t receiver_port_high; |
660 | | } lbtru_tag_entry_t; |
661 | | |
662 | | static lbtru_tag_entry_t * lbtru_tag_entry; |
663 | | static unsigned lbtru_tag_count; |
664 | | |
665 | 0 | UAT_CSTRING_CB_DEF(lbtru_tag, name, lbtru_tag_entry_t) |
666 | 0 | UAT_DEC_CB_DEF(lbtru_tag, source_port_low, lbtru_tag_entry_t) Unexecuted instantiation: packet-lbtru.c:lbtru_tag_source_port_low_set_cb Unexecuted instantiation: packet-lbtru.c:lbtru_tag_source_port_low_tostr_cb |
667 | 0 | UAT_DEC_CB_DEF(lbtru_tag, source_port_high, lbtru_tag_entry_t) Unexecuted instantiation: packet-lbtru.c:lbtru_tag_source_port_high_set_cb Unexecuted instantiation: packet-lbtru.c:lbtru_tag_source_port_high_tostr_cb |
668 | 0 | UAT_DEC_CB_DEF(lbtru_tag, receiver_port_low, lbtru_tag_entry_t) Unexecuted instantiation: packet-lbtru.c:lbtru_tag_receiver_port_low_set_cb Unexecuted instantiation: packet-lbtru.c:lbtru_tag_receiver_port_low_tostr_cb |
669 | 0 | UAT_DEC_CB_DEF(lbtru_tag, receiver_port_high, lbtru_tag_entry_t) Unexecuted instantiation: packet-lbtru.c:lbtru_tag_receiver_port_high_set_cb Unexecuted instantiation: packet-lbtru.c:lbtru_tag_receiver_port_high_tostr_cb |
670 | | static uat_field_t lbtru_tag_array[] = |
671 | | { |
672 | | UAT_FLD_CSTRING(lbtru_tag, name, "Tag name", "Tag name"), |
673 | | UAT_FLD_DEC(lbtru_tag, source_port_low, "Source port low", "Source port low"), |
674 | | UAT_FLD_DEC(lbtru_tag, source_port_high, "Source port high", "Source port high"), |
675 | | UAT_FLD_DEC(lbtru_tag, receiver_port_low, "Receiver port low", "Receiver port low"), |
676 | | UAT_FLD_DEC(lbtru_tag, receiver_port_high, "Receiver port high", "Receiver port high"), |
677 | | UAT_END_FIELDS |
678 | | }; |
679 | | |
680 | | /*----------------------------------------------------------------------------*/ |
681 | | /* UAT callback functions. */ |
682 | | /*----------------------------------------------------------------------------*/ |
683 | | static bool lbtru_tag_update_cb(void * record, char * * error_string) |
684 | 0 | { |
685 | 0 | lbtru_tag_entry_t * tag = (lbtru_tag_entry_t *)record; |
686 | |
|
687 | 0 | if (tag->name == NULL) |
688 | 0 | { |
689 | 0 | *error_string = g_strdup("Tag name can't be empty"); |
690 | 0 | return false; |
691 | 0 | } |
692 | 0 | else |
693 | 0 | { |
694 | 0 | g_strstrip(tag->name); |
695 | 0 | if (tag->name[0] == 0) |
696 | 0 | { |
697 | 0 | *error_string = g_strdup("Tag name can't be empty"); |
698 | 0 | return false; |
699 | 0 | } |
700 | 0 | } |
701 | 0 | return true; |
702 | 0 | } |
703 | | |
704 | | static void * lbtru_tag_copy_cb(void * destination, const void * source, size_t length _U_) |
705 | 0 | { |
706 | 0 | const lbtru_tag_entry_t * src = (const lbtru_tag_entry_t *)source; |
707 | 0 | lbtru_tag_entry_t * dest = (lbtru_tag_entry_t *)destination; |
708 | |
|
709 | 0 | dest->name = g_strdup(src->name); |
710 | 0 | dest->source_port_low = src->source_port_low; |
711 | 0 | dest->source_port_high = src->source_port_high; |
712 | 0 | dest->receiver_port_low = src->receiver_port_low; |
713 | 0 | dest->receiver_port_high = src->receiver_port_high; |
714 | 0 | return (dest); |
715 | 0 | } |
716 | | |
717 | | static void lbtru_tag_free_cb(void * record) |
718 | 0 | { |
719 | 0 | lbtru_tag_entry_t * tag = (lbtru_tag_entry_t *)record; |
720 | |
|
721 | 0 | if (tag->name != NULL) |
722 | 0 | { |
723 | 0 | g_free(tag->name); |
724 | 0 | tag->name = NULL; |
725 | 0 | } |
726 | 0 | } |
727 | | |
728 | | static char * lbtru_tag_find(packet_info * pinfo) |
729 | 0 | { |
730 | 0 | unsigned idx; |
731 | 0 | lbtru_tag_entry_t * tag = NULL; |
732 | |
|
733 | 0 | if (!lbtru_use_tag) |
734 | 0 | { |
735 | 0 | return (NULL); |
736 | 0 | } |
737 | | |
738 | 0 | for (idx = 0; idx < lbtru_tag_count; ++idx) |
739 | 0 | { |
740 | 0 | tag = &(lbtru_tag_entry[idx]); |
741 | 0 | if (((pinfo->destport >= tag->source_port_low) |
742 | 0 | && (pinfo->destport <= tag->source_port_high) |
743 | 0 | && (pinfo->srcport >= tag->receiver_port_low) |
744 | 0 | && (pinfo->srcport <= tag->receiver_port_high)) |
745 | 0 | || ((pinfo->destport >= tag->receiver_port_low) |
746 | 0 | && (pinfo->destport <= tag->receiver_port_high) |
747 | 0 | && (pinfo->srcport >= tag->source_port_low) |
748 | 0 | && (pinfo->srcport <= tag->source_port_high))) |
749 | 0 | { |
750 | | /* One of ours. */ |
751 | 0 | return tag->name; |
752 | 0 | } |
753 | 0 | } |
754 | 0 | return (NULL); |
755 | 0 | } |
756 | | |
757 | | /*----------------------------------------------------------------------------*/ |
758 | | /* Handles of all types. */ |
759 | | /*----------------------------------------------------------------------------*/ |
760 | | |
761 | | /* Dissector tree handles */ |
762 | | static int ett_lbtru; |
763 | | static int ett_lbtru_channel; |
764 | | static int ett_lbtru_hdr; |
765 | | static int ett_lbtru_hdr_flags; |
766 | | static int ett_lbtru_data; |
767 | | static int ett_lbtru_sm; |
768 | | static int ett_lbtru_nak; |
769 | | static int ett_lbtru_nak_list; |
770 | | static int ett_lbtru_ncf; |
771 | | static int ett_lbtru_ncf_list; |
772 | | static int ett_lbtru_ack; |
773 | | static int ett_lbtru_opt; |
774 | | static int ett_lbtru_opt_sid_flags; |
775 | | static int ett_lbtru_opt_cid_flags; |
776 | | static int ett_lbtru_transport; |
777 | | static int ett_lbtru_transport_sqn; |
778 | | |
779 | | /* Dissector field handles */ |
780 | | static int hf_lbtru_channel; |
781 | | static int hf_lbtru_channel_id; |
782 | | static int hf_lbtru_channel_client; |
783 | | static int hf_lbtru_tag; |
784 | | static int hf_lbtru_hdr; |
785 | | static int hf_lbtru_hdr_ver; |
786 | | static int hf_lbtru_hdr_type; |
787 | | static int hf_lbtru_hdr_next_hdr; |
788 | | static int hf_lbtru_hdr_res; |
789 | | static int hf_lbtru_hdr_flags; |
790 | | static int hf_lbtru_hdr_flags_syn; |
791 | | static int hf_lbtru_hdr_flags_rx; |
792 | | static int hf_lbtru_hdr_request; |
793 | | static int hf_lbtru_hdr_reason; |
794 | | static int hf_lbtru_data; |
795 | | static int hf_lbtru_data_sqn; |
796 | | static int hf_lbtru_data_trail_sqn; |
797 | | static int hf_lbtru_sm; |
798 | | static int hf_lbtru_sm_sqn; |
799 | | static int hf_lbtru_sm_lead_sqn; |
800 | | static int hf_lbtru_sm_trail_sqn; |
801 | | static int hf_lbtru_nak; |
802 | | static int hf_lbtru_nak_num; |
803 | | static int hf_lbtru_nak_format; |
804 | | static int hf_lbtru_nak_list; |
805 | | static int hf_lbtru_nak_list_nak; |
806 | | static int hf_lbtru_ncf; |
807 | | static int hf_lbtru_ncf_trail_sqn; |
808 | | static int hf_lbtru_ncf_num; |
809 | | static int hf_lbtru_ncf_reserved; |
810 | | static int hf_lbtru_ncf_reason; |
811 | | static int hf_lbtru_ncf_format; |
812 | | static int hf_lbtru_ncf_list; |
813 | | static int hf_lbtru_ncf_list_ncf; |
814 | | static int hf_lbtru_ack; |
815 | | static int hf_lbtru_ack_sqn; |
816 | | static int hf_lbtru_opt_sid; |
817 | | static int hf_lbtru_opt_sid_next_hdr; |
818 | | static int hf_lbtru_opt_sid_hdr_len; |
819 | | static int hf_lbtru_opt_sid_flags; |
820 | | static int hf_lbtru_opt_sid_flags_ignore; |
821 | | static int hf_lbtru_opt_sid_session_id; |
822 | | static int hf_lbtru_opt_cid; |
823 | | static int hf_lbtru_opt_cid_next_hdr; |
824 | | static int hf_lbtru_opt_cid_hdr_len; |
825 | | static int hf_lbtru_opt_cid_flags; |
826 | | static int hf_lbtru_opt_cid_flags_ignore; |
827 | | static int hf_lbtru_opt_cid_client_id; |
828 | | static int hf_lbtru_opt_unknown; |
829 | | static int hf_lbtru_opt_unknown_next_hdr; |
830 | | static int hf_lbtru_opt_unknown_hdr_len; |
831 | | static int hf_lbtru_analysis; |
832 | | static int hf_lbtru_analysis_prev_frame; |
833 | | static int hf_lbtru_analysis_prev_data_frame; |
834 | | static int hf_lbtru_analysis_prev_sm_frame; |
835 | | static int hf_lbtru_analysis_prev_nak_frame; |
836 | | static int hf_lbtru_analysis_prev_ncf_frame; |
837 | | static int hf_lbtru_analysis_prev_ack_frame; |
838 | | static int hf_lbtru_analysis_prev_creq_frame; |
839 | | static int hf_lbtru_analysis_prev_rst_frame; |
840 | | static int hf_lbtru_analysis_next_frame; |
841 | | static int hf_lbtru_analysis_next_data_frame; |
842 | | static int hf_lbtru_analysis_next_sm_frame; |
843 | | static int hf_lbtru_analysis_next_nak_frame; |
844 | | static int hf_lbtru_analysis_next_ncf_frame; |
845 | | static int hf_lbtru_analysis_next_ack_frame; |
846 | | static int hf_lbtru_analysis_next_creq_frame; |
847 | | static int hf_lbtru_analysis_next_rst_frame; |
848 | | static int hf_lbtru_analysis_sqn; |
849 | | static int hf_lbtru_analysis_sqn_frame; |
850 | | static int hf_lbtru_analysis_data_retransmission; |
851 | | static int hf_lbtru_analysis_data_sqn_gap; |
852 | | static int hf_lbtru_analysis_data_ooo_gap; |
853 | | static int hf_lbtru_analysis_data_duplicate; |
854 | | static int hf_lbtru_analysis_sm_sqn_gap; |
855 | | static int hf_lbtru_analysis_sm_ooo_gap; |
856 | | static int hf_lbtru_analysis_sm_duplicate; |
857 | | |
858 | | /* Expert info handles */ |
859 | | static expert_field ei_lbtru_analysis_unknown_type; |
860 | | static expert_field ei_lbtru_analysis_unknown_header; |
861 | | static expert_field ei_lbtru_analysis_zero_length_header; |
862 | | static expert_field ei_lbtru_analysis_ack; |
863 | | static expert_field ei_lbtru_analysis_ncf; |
864 | | static expert_field ei_lbtru_analysis_ncf_ncf; |
865 | | static expert_field ei_lbtru_analysis_nak; |
866 | | static expert_field ei_lbtru_analysis_nak_nak; |
867 | | static expert_field ei_lbtru_analysis_sm; |
868 | | static expert_field ei_lbtru_analysis_sm_syn; |
869 | | static expert_field ei_lbtru_analysis_creq; |
870 | | static expert_field ei_lbtru_analysis_rst; |
871 | | static expert_field ei_lbtru_analysis_data_rx; |
872 | | static expert_field ei_lbtru_analysis_data_gap; |
873 | | static expert_field ei_lbtru_analysis_data_ooo; |
874 | | static expert_field ei_lbtru_analysis_data_dup; |
875 | | static expert_field ei_lbtru_analysis_sm_gap; |
876 | | static expert_field ei_lbtru_analysis_sm_ooo; |
877 | | static expert_field ei_lbtru_analysis_sm_dup; |
878 | | |
879 | | /*----------------------------------------------------------------------------*/ |
880 | | /* LBT-RU data payload dissection functions. */ |
881 | | /*----------------------------------------------------------------------------*/ |
882 | | static int dissect_lbtru_data_contents(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, const char * tag_name, uint64_t channel) |
883 | 0 | { |
884 | 0 | tvbuff_t * next_tvb; |
885 | |
|
886 | 0 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
887 | 0 | return (lbmc_dissect_lbmc_packet(next_tvb, 0, pinfo, tree, tag_name, channel)); |
888 | 0 | } |
889 | | |
890 | | /*----------------------------------------------------------------------------*/ |
891 | | /* LBT-RU ACK packet dissection functions. */ |
892 | | /*----------------------------------------------------------------------------*/ |
893 | | static int dissect_lbtru_ack(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, lbm_lbtru_tap_info_t * tap_info) |
894 | 0 | { |
895 | 0 | proto_tree * ack_tree = NULL; |
896 | 0 | proto_item * ack_item = NULL; |
897 | 0 | proto_item * ack = NULL; |
898 | |
|
899 | 0 | ack_item = proto_tree_add_item(tree, hf_lbtru_ack, tvb, offset, L_LBTRU_ACK_HDR_T, ENC_NA); |
900 | 0 | ack_tree = proto_item_add_subtree(ack_item, ett_lbtru_ack); |
901 | 0 | ack = proto_tree_add_item(ack_tree, hf_lbtru_ack_sqn, tvb, offset + O_LBTRU_ACK_HDR_T_ACK_SQN, L_LBTRU_ACK_HDR_T_ACK_SQN, ENC_BIG_ENDIAN); |
902 | 0 | expert_add_info(pinfo, ack, &ei_lbtru_analysis_ack); |
903 | 0 | tap_info->sqn = tvb_get_ntohl(tvb, offset + O_LBTRU_ACK_HDR_T_ACK_SQN); |
904 | 0 | return (L_LBTRU_ACK_HDR_T); |
905 | 0 | } |
906 | | |
907 | | /*----------------------------------------------------------------------------*/ |
908 | | /* LBT-RU NAK confirmation packet dissection functions. */ |
909 | | /*----------------------------------------------------------------------------*/ |
910 | | static int dissect_lbtru_ncf_list(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, int ncf_count, int reason, lbm_lbtru_tap_info_t * tap_info) |
911 | 0 | { |
912 | 0 | proto_tree * ncf_tree = NULL; |
913 | 0 | proto_item * ncf_item = NULL; |
914 | 0 | lbm_uint32_t ncf; |
915 | 0 | int idx = 0; |
916 | 0 | int len = 0; |
917 | |
|
918 | 0 | ncf_item = proto_tree_add_item(tree, hf_lbtru_ncf_list, tvb, offset, -1, ENC_NA); |
919 | 0 | ncf_tree = proto_item_add_subtree(ncf_item, ett_lbtru_ncf_list); |
920 | |
|
921 | 0 | for (idx = 0; idx < ncf_count; idx++) |
922 | 0 | { |
923 | 0 | proto_item * sep_ncf_item = NULL; |
924 | |
|
925 | 0 | sep_ncf_item = proto_tree_add_item_ret_uint(ncf_tree, hf_lbtru_ncf_list_ncf, tvb, offset + len, sizeof(lbm_uint32_t), ENC_BIG_ENDIAN, &ncf); |
926 | 0 | if (lbtru_expert_separate_ncfs) |
927 | 0 | { |
928 | 0 | expert_add_info_format(pinfo, sep_ncf_item, &ei_lbtru_analysis_ncf_ncf, "NCF 0x%08x %s", ncf, val_to_str(pinfo->pool, reason, lbtru_ncf_reason, "Unknown (0x%02x)")); |
929 | 0 | } |
930 | 0 | tap_info->sqns[idx] = ncf; |
931 | 0 | len += (int)sizeof(lbm_uint32_t); |
932 | 0 | } |
933 | 0 | proto_item_set_len(ncf_item, len); |
934 | 0 | return (len); |
935 | 0 | } |
936 | | |
937 | | static int dissect_lbtru_ncf(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, lbm_lbtru_tap_info_t * tap_info) |
938 | 0 | { |
939 | 0 | int len_dissected; |
940 | 0 | uint8_t reason_format; |
941 | 0 | proto_tree * ncf_tree = NULL; |
942 | 0 | proto_item * ncf_item = NULL; |
943 | 0 | uint16_t num_ncfs = 0; |
944 | |
|
945 | 0 | ncf_item = proto_tree_add_item(tree, hf_lbtru_ncf, tvb, offset, -1, ENC_NA); |
946 | 0 | ncf_tree = proto_item_add_subtree(ncf_item, ett_lbtru_ncf); |
947 | 0 | reason_format = tvb_get_uint8(tvb, offset + O_LBTRU_NCF_HDR_T_REASON_FORMAT); |
948 | 0 | num_ncfs = tvb_get_ntohs(tvb, offset + O_LBTRU_NCF_HDR_T_NUM_NCFS); |
949 | 0 | proto_tree_add_item(ncf_tree, hf_lbtru_ncf_trail_sqn, tvb, offset + O_LBTRU_NCF_HDR_T_TRAIL_SQN, L_LBTRU_NCF_HDR_T_TRAIL_SQN, ENC_BIG_ENDIAN); |
950 | 0 | proto_tree_add_item(ncf_tree, hf_lbtru_ncf_num, tvb, offset + O_LBTRU_NCF_HDR_T_NUM_NCFS, L_LBTRU_NCF_HDR_T_NUM_NCFS, ENC_BIG_ENDIAN); |
951 | 0 | proto_tree_add_item(ncf_tree, hf_lbtru_ncf_reserved, tvb, offset + O_LBTRU_NCF_HDR_T_RESERVED, L_LBTRU_NCF_HDR_T_RESERVED, ENC_BIG_ENDIAN); |
952 | 0 | proto_tree_add_item(ncf_tree, hf_lbtru_ncf_reason, tvb, offset + O_LBTRU_NCF_HDR_T_REASON_FORMAT, L_LBTRU_NCF_HDR_T_REASON_FORMAT, ENC_BIG_ENDIAN); |
953 | 0 | proto_tree_add_item(ncf_tree, hf_lbtru_ncf_format, tvb, offset + O_LBTRU_NCF_HDR_T_REASON_FORMAT, L_LBTRU_NCF_HDR_T_REASON_FORMAT, ENC_BIG_ENDIAN); |
954 | 0 | len_dissected = L_LBTRU_NCF_HDR_T; |
955 | 0 | if (!lbtru_expert_separate_ncfs) |
956 | 0 | { |
957 | 0 | expert_add_info_format(pinfo, ncf_item, &ei_lbtru_analysis_ncf, "NCF %s", val_to_str(pinfo->pool, LBTRU_NCF_HDR_REASON(reason_format), lbtru_ncf_reason, "Unknown (0x%02x)")); |
958 | 0 | } |
959 | 0 | tap_info->ncf_reason = LBTRU_NCF_HDR_REASON(reason_format); |
960 | 0 | tap_info->num_sqns = num_ncfs; |
961 | 0 | tap_info->sqns = wmem_alloc_array(pinfo->pool, uint32_t, num_ncfs); |
962 | 0 | len_dissected += dissect_lbtru_ncf_list(tvb, offset + L_LBTRU_NCF_HDR_T, pinfo, ncf_tree, num_ncfs, LBTRU_NCF_HDR_REASON(reason_format), tap_info); |
963 | 0 | proto_item_set_len(ncf_item, len_dissected); |
964 | 0 | return (len_dissected); |
965 | 0 | } |
966 | | |
967 | | /*----------------------------------------------------------------------------*/ |
968 | | /* LBT-RU NAK packet dissection functions. */ |
969 | | /*----------------------------------------------------------------------------*/ |
970 | | static int dissect_lbtru_nak_list(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, int nak_count, lbm_lbtru_tap_info_t * tap_info) |
971 | 0 | { |
972 | 0 | proto_tree * nak_tree = NULL; |
973 | 0 | proto_item * nak_item = NULL; |
974 | 0 | int idx = 0; |
975 | 0 | int len = 0; |
976 | |
|
977 | 0 | nak_item = proto_tree_add_item(tree, hf_lbtru_nak_list, tvb, offset, -1, ENC_NA); |
978 | 0 | nak_tree = proto_item_add_subtree(nak_item, ett_lbtru_nak_list); |
979 | |
|
980 | 0 | for (idx = 0; idx < nak_count; idx++) |
981 | 0 | { |
982 | 0 | proto_item * sep_nak_item = NULL; |
983 | 0 | lbm_uint32_t nak; |
984 | |
|
985 | 0 | sep_nak_item = proto_tree_add_item_ret_uint(nak_tree, hf_lbtru_nak_list_nak, tvb, offset + len, sizeof(lbm_uint32_t), ENC_BIG_ENDIAN, &nak); |
986 | 0 | if (lbtru_expert_separate_naks) |
987 | 0 | { |
988 | 0 | expert_add_info_format(pinfo, sep_nak_item, &ei_lbtru_analysis_nak_nak, "NAK 0x%08x", nak); |
989 | 0 | } |
990 | 0 | tap_info->sqns[idx] = nak; |
991 | 0 | len += (int)sizeof(lbm_uint32_t); |
992 | 0 | } |
993 | 0 | proto_item_set_len(nak_item, len); |
994 | 0 | return (len); |
995 | 0 | } |
996 | | |
997 | | static int dissect_lbtru_nak(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, lbm_lbtru_tap_info_t * tap_info) |
998 | 0 | { |
999 | 0 | int len_dissected; |
1000 | 0 | proto_tree * nak_tree = NULL; |
1001 | 0 | proto_item * nak_item = NULL; |
1002 | 0 | uint16_t num_naks = 0; |
1003 | |
|
1004 | 0 | nak_item = proto_tree_add_item(tree, hf_lbtru_nak, tvb, offset, -1, ENC_NA); |
1005 | 0 | nak_tree = proto_item_add_subtree(nak_item, ett_lbtru_nak); |
1006 | 0 | num_naks = tvb_get_ntohs(tvb, offset + O_LBTRU_NAK_HDR_T_NUM_NAKS); |
1007 | 0 | proto_tree_add_item(nak_tree, hf_lbtru_nak_num, tvb, offset + O_LBTRU_NAK_HDR_T_NUM_NAKS, L_LBTRU_NAK_HDR_T_NUM_NAKS, ENC_BIG_ENDIAN); |
1008 | 0 | proto_tree_add_item(nak_tree, hf_lbtru_nak_format, tvb, offset + O_LBTRU_NAK_HDR_T_FORMAT, L_LBTRU_NAK_HDR_T_FORMAT, ENC_BIG_ENDIAN); |
1009 | 0 | len_dissected = L_LBTRU_NAK_HDR_T; |
1010 | 0 | if (!lbtru_expert_separate_naks) |
1011 | 0 | { |
1012 | 0 | expert_add_info(pinfo, nak_item, &ei_lbtru_analysis_nak); |
1013 | 0 | } |
1014 | 0 | tap_info->num_sqns = num_naks; |
1015 | 0 | tap_info->sqns = wmem_alloc_array(pinfo->pool, uint32_t, num_naks); |
1016 | 0 | len_dissected += dissect_lbtru_nak_list(tvb, offset + L_LBTRU_NAK_HDR_T, pinfo, nak_tree, num_naks, tap_info); |
1017 | 0 | proto_item_set_len(nak_item, len_dissected); |
1018 | 0 | return (len_dissected); |
1019 | 0 | } |
1020 | | |
1021 | | /*----------------------------------------------------------------------------*/ |
1022 | | /* LBT-RU session message packet dissection function. */ |
1023 | | /*----------------------------------------------------------------------------*/ |
1024 | | static int dissect_lbtru_sm(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, int syn, lbm_lbtru_tap_info_t * tap_info) |
1025 | 0 | { |
1026 | 0 | proto_tree * sm_tree = NULL; |
1027 | 0 | proto_item * sm_item = NULL; |
1028 | 0 | proto_item * sm_sqn = NULL; |
1029 | |
|
1030 | 0 | sm_item = proto_tree_add_item(tree, hf_lbtru_sm, tvb, offset, L_LBTRU_SM_HDR_T, ENC_NA); |
1031 | 0 | sm_tree = proto_item_add_subtree(sm_item, ett_lbtru_sm); |
1032 | 0 | sm_sqn = proto_tree_add_item(sm_tree, hf_lbtru_sm_sqn, tvb, offset + O_LBTRU_SM_HDR_T_SM_SQN, L_LBTRU_SM_HDR_T_SM_SQN, ENC_BIG_ENDIAN); |
1033 | 0 | proto_tree_add_item(sm_tree, hf_lbtru_sm_lead_sqn, tvb, offset + O_LBTRU_SM_HDR_T_LEAD_SQN, L_LBTRU_SM_HDR_T_LEAD_SQN, ENC_BIG_ENDIAN); |
1034 | 0 | proto_tree_add_item(sm_tree, hf_lbtru_sm_trail_sqn, tvb, offset + O_LBTRU_SM_HDR_T_TRAIL_SQN, L_LBTRU_SM_HDR_T_TRAIL_SQN, ENC_BIG_ENDIAN); |
1035 | 0 | if (syn) |
1036 | 0 | { |
1037 | 0 | expert_add_info(pinfo, sm_sqn, &ei_lbtru_analysis_sm_syn); |
1038 | 0 | } |
1039 | 0 | else |
1040 | 0 | { |
1041 | 0 | expert_add_info(pinfo, sm_sqn, &ei_lbtru_analysis_sm); |
1042 | 0 | } |
1043 | 0 | tap_info->sqn = tvb_get_ntohl(tvb, offset + O_LBTRU_SM_HDR_T_SM_SQN); |
1044 | 0 | return (L_LBTRU_SM_HDR_T); |
1045 | 0 | } |
1046 | | |
1047 | | /*----------------------------------------------------------------------------*/ |
1048 | | /* LBT-RU data packet dissection functions. */ |
1049 | | /*----------------------------------------------------------------------------*/ |
1050 | | static int dissect_lbtru_data(tvbuff_t * tvb, int offset, packet_info * pinfo _U_, proto_tree * tree, lbm_lbtru_tap_info_t * tap_info) |
1051 | 0 | { |
1052 | 0 | proto_tree * data_tree = NULL; |
1053 | 0 | proto_item * data_item = NULL; |
1054 | |
|
1055 | 0 | data_item = proto_tree_add_item(tree, hf_lbtru_data, tvb, offset, L_LBTRU_DATA_HDR_T, ENC_NA); |
1056 | 0 | data_tree = proto_item_add_subtree(data_item, ett_lbtru_data); |
1057 | 0 | proto_tree_add_item(data_tree, hf_lbtru_data_sqn, tvb, offset + O_LBTRU_DATA_HDR_T_SQN, L_LBTRU_DATA_HDR_T_SQN, ENC_BIG_ENDIAN); |
1058 | 0 | proto_tree_add_item(data_tree, hf_lbtru_data_trail_sqn, tvb, offset + O_LBTRU_DATA_HDR_T_TRAIL_SQN, L_LBTRU_DATA_HDR_T_TRAIL_SQN, ENC_BIG_ENDIAN); |
1059 | 0 | tap_info->sqn = tvb_get_ntohl(tvb, offset + O_LBTRU_DATA_HDR_T_SQN); |
1060 | 0 | return (L_LBTRU_DATA_HDR_T); |
1061 | 0 | } |
1062 | | |
1063 | | /*----------------------------------------------------------------------------*/ |
1064 | | /* LBT-RU packet dissector. */ |
1065 | | /*----------------------------------------------------------------------------*/ |
1066 | | typedef struct |
1067 | | { |
1068 | | proto_tree * tree; |
1069 | | tvbuff_t * tvb; |
1070 | | uint32_t current_frame; |
1071 | | } lbtru_sqn_frame_list_callback_data_t; |
1072 | | |
1073 | | static bool dissect_lbtru_sqn_frame_list_callback(const void *key _U_, void * frame, void * user_data) |
1074 | 0 | { |
1075 | 0 | lbtru_sqn_frame_list_callback_data_t * cb_data = (lbtru_sqn_frame_list_callback_data_t *) user_data; |
1076 | 0 | proto_item * transport_item = NULL; |
1077 | 0 | lbm_transport_sqn_frame_t * sqn_frame = (lbm_transport_sqn_frame_t *) frame; |
1078 | |
|
1079 | 0 | if (sqn_frame->frame != cb_data->current_frame) |
1080 | 0 | { |
1081 | 0 | if (sqn_frame->retransmission) |
1082 | 0 | { |
1083 | 0 | transport_item = proto_tree_add_uint_format_value(cb_data->tree, hf_lbtru_analysis_sqn_frame, cb_data->tvb, 0, 0, sqn_frame->frame, "%" PRIu32 " (RX)", sqn_frame->frame); |
1084 | 0 | } |
1085 | 0 | else |
1086 | 0 | { |
1087 | 0 | transport_item = proto_tree_add_uint(cb_data->tree, hf_lbtru_analysis_sqn_frame, cb_data->tvb, 0, 0, sqn_frame->frame); |
1088 | 0 | } |
1089 | 0 | proto_item_set_generated(transport_item); |
1090 | 0 | } |
1091 | 0 | return false; |
1092 | 0 | } |
1093 | | |
1094 | | static int dissect_lbtru(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * user_data _U_) |
1095 | 0 | { |
1096 | 0 | proto_tree * lbtru_tree = NULL; |
1097 | 0 | proto_item * lbtru_item = NULL; |
1098 | 0 | static int * const flags_data[] = |
1099 | 0 | { |
1100 | 0 | &hf_lbtru_hdr_flags_rx, |
1101 | 0 | NULL |
1102 | 0 | }; |
1103 | 0 | static int * const flags_sm[] = |
1104 | 0 | { |
1105 | 0 | &hf_lbtru_hdr_flags_syn, |
1106 | 0 | NULL |
1107 | 0 | }; |
1108 | 0 | int ofs = 0; |
1109 | 0 | uint32_t session_id = 0; |
1110 | 0 | char * tag_name = NULL; |
1111 | 0 | int dissected_len; |
1112 | 0 | int total_dissected_len = 0; |
1113 | 0 | proto_tree * header_tree = NULL; |
1114 | 0 | proto_item * header_item = NULL; |
1115 | 0 | proto_tree * transport_tree = NULL; |
1116 | 0 | proto_item * transport_item = NULL; |
1117 | 0 | bool from_source = true; |
1118 | 0 | uint8_t packet_type = 0; |
1119 | 0 | address source_address; |
1120 | 0 | address receiver_address; |
1121 | 0 | uint16_t source_port = 0; |
1122 | 0 | uint16_t receiver_port = 0; |
1123 | 0 | lbtru_transport_t * transport = NULL; |
1124 | 0 | lbtru_client_transport_t * client = NULL; |
1125 | 0 | uint64_t channel = LBM_CHANNEL_NO_CHANNEL; |
1126 | 0 | proto_tree * channel_tree = NULL; |
1127 | 0 | proto_item * channel_item = NULL; |
1128 | 0 | uint8_t ver_type = 0; |
1129 | 0 | uint8_t next_hdr = 0; |
1130 | 0 | uint32_t packet_sqn = 0; |
1131 | 0 | uint16_t flags_or_res = 0; |
1132 | 0 | uint16_t num_naks = 0; |
1133 | 0 | uint16_t num_ncfs = 0; |
1134 | 0 | bool retransmission = false; |
1135 | 0 | proto_item * fld_item = NULL; |
1136 | 0 | proto_item * ei_item = NULL; |
1137 | 0 | proto_item * type_item = NULL; |
1138 | 0 | proto_item * next_hdr_item = NULL; |
1139 | 0 | lbm_lbtru_tap_info_t * tapinfo = NULL; |
1140 | |
|
1141 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "LBT-RU"); |
1142 | 0 | if (lbtru_use_tag) |
1143 | 0 | { |
1144 | 0 | tag_name = lbtru_tag_find(pinfo); |
1145 | 0 | } |
1146 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
1147 | 0 | if (tag_name != NULL) |
1148 | 0 | { |
1149 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "[Tag: %s]", tag_name); |
1150 | 0 | } |
1151 | 0 | col_set_fence(pinfo->cinfo, COL_INFO); |
1152 | |
|
1153 | 0 | ver_type = tvb_get_uint8(tvb, O_LBTRU_HDR_T_VER_TYPE); |
1154 | 0 | next_hdr = tvb_get_uint8(tvb, O_LBTRU_HDR_T_NEXT_HDR); |
1155 | 0 | flags_or_res = tvb_get_ntohs(tvb, O_LBTRU_HDR_T_FLAGS_OR_RES); |
1156 | 0 | packet_type = LBTRU_HDR_TYPE(ver_type); |
1157 | 0 | if (tag_name != NULL) |
1158 | 0 | { |
1159 | 0 | lbtru_item = proto_tree_add_protocol_format(tree, proto_lbtru, tvb, ofs, -1, "LBT-RU Protocol (Tag: %s): Version %u, Type %s", tag_name, |
1160 | 0 | LBTRU_HDR_VER(ver_type), val_to_str(pinfo->pool, LBTRU_HDR_TYPE(ver_type), lbtru_packet_type, "Unknown (0x%02x)")); |
1161 | 0 | } |
1162 | 0 | else |
1163 | 0 | { |
1164 | 0 | lbtru_item = proto_tree_add_protocol_format(tree, proto_lbtru, tvb, ofs, -1, "LBT-RU Protocol: Version %u, Type %s", LBTRU_HDR_VER(ver_type), |
1165 | 0 | val_to_str(pinfo->pool, LBTRU_HDR_TYPE(ver_type), lbtru_packet_type, "Unknown (0x%02x)")); |
1166 | 0 | } |
1167 | 0 | lbtru_tree = proto_item_add_subtree(lbtru_item, ett_lbtru); |
1168 | 0 | if (tag_name != NULL) |
1169 | 0 | { |
1170 | 0 | proto_item * item = NULL; |
1171 | 0 | item = proto_tree_add_string(lbtru_tree, hf_lbtru_tag, tvb, 0, 0, tag_name); |
1172 | 0 | proto_item_set_generated(item); |
1173 | 0 | } |
1174 | 0 | channel_item = proto_tree_add_item(lbtru_tree, hf_lbtru_channel, tvb, 0, 0, ENC_NA); |
1175 | 0 | proto_item_set_generated(channel_item); |
1176 | 0 | channel_tree = proto_item_add_subtree(channel_item, ett_lbtru_channel); |
1177 | |
|
1178 | 0 | tapinfo = wmem_new0(pinfo->pool, lbm_lbtru_tap_info_t); |
1179 | 0 | tapinfo->type = packet_type; |
1180 | |
|
1181 | 0 | header_item = proto_tree_add_item(lbtru_tree, hf_lbtru_hdr, tvb, 0, -1, ENC_NA); |
1182 | 0 | header_tree = proto_item_add_subtree(header_item, ett_lbtru_hdr); |
1183 | 0 | proto_tree_add_item(header_tree, hf_lbtru_hdr_ver, tvb, O_LBTRU_HDR_T_VER_TYPE, L_LBTRU_HDR_T_VER_TYPE, ENC_BIG_ENDIAN); |
1184 | 0 | type_item = proto_tree_add_item(header_tree, hf_lbtru_hdr_type, tvb, O_LBTRU_HDR_T_VER_TYPE, L_LBTRU_HDR_T_VER_TYPE, ENC_BIG_ENDIAN); |
1185 | 0 | next_hdr_item = proto_tree_add_item(header_tree, hf_lbtru_hdr_next_hdr, tvb, O_LBTRU_HDR_T_NEXT_HDR, L_LBTRU_HDR_T_NEXT_HDR, ENC_BIG_ENDIAN); |
1186 | 0 | total_dissected_len = L_LBTRU_HDR_T_VER_TYPE + L_LBTRU_HDR_T_NEXT_HDR; |
1187 | 0 | ofs = L_LBTRU_HDR_T_VER_TYPE + L_LBTRU_HDR_T_NEXT_HDR; |
1188 | |
|
1189 | 0 | switch (packet_type) |
1190 | 0 | { |
1191 | 0 | case LBTRU_PACKET_TYPE_DATA: |
1192 | 0 | packet_sqn = tvb_get_ntohl(tvb, L_LBTRU_HDR_T + O_LBTRU_DATA_HDR_T_SQN); |
1193 | 0 | if ((flags_or_res & LBTRU_RETRANSMISSION_FLAG) != 0) |
1194 | 0 | { |
1195 | 0 | retransmission = true; |
1196 | 0 | tapinfo->retransmission = true; |
1197 | 0 | } |
1198 | 0 | if (retransmission) |
1199 | 0 | { |
1200 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "DATA(RX) sqn 0x%x", packet_sqn); |
1201 | 0 | } |
1202 | 0 | else |
1203 | 0 | { |
1204 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "DATA sqn 0x%x", packet_sqn); |
1205 | 0 | } |
1206 | 0 | from_source = true; |
1207 | 0 | break; |
1208 | 0 | case LBTRU_PACKET_TYPE_SM: |
1209 | 0 | packet_sqn = tvb_get_ntohl(tvb, L_LBTRU_HDR_T + O_LBTRU_SM_HDR_T_SM_SQN); |
1210 | 0 | if ((flags_or_res & LBTRU_SM_SYN_FLAG) != 0) |
1211 | 0 | { |
1212 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SM sqn 0x%x SYN", packet_sqn); |
1213 | 0 | } |
1214 | 0 | else |
1215 | 0 | { |
1216 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SM sqn 0x%x", packet_sqn); |
1217 | 0 | } |
1218 | 0 | from_source = true; |
1219 | 0 | break; |
1220 | 0 | case LBTRU_PACKET_TYPE_NAK: |
1221 | 0 | num_naks = tvb_get_ntohs(tvb, L_LBTRU_HDR_T + O_LBTRU_NAK_HDR_T_NUM_NAKS); |
1222 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "NAK %" PRIu16 " naks", num_naks); |
1223 | 0 | from_source = false; |
1224 | 0 | break; |
1225 | 0 | case LBTRU_PACKET_TYPE_NCF: |
1226 | 0 | num_ncfs = tvb_get_ntohs(tvb, L_LBTRU_HDR_T + O_LBTRU_NCF_HDR_T_NUM_NCFS); |
1227 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "NCF %" PRIu16 " ncfs", num_ncfs); |
1228 | 0 | from_source = true; |
1229 | 0 | break; |
1230 | 0 | case LBTRU_PACKET_TYPE_ACK: |
1231 | 0 | packet_sqn = tvb_get_ntohl(tvb, L_LBTRU_HDR_T + O_LBTRU_ACK_HDR_T_ACK_SQN); |
1232 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "ACK sqn 0x%x", packet_sqn); |
1233 | 0 | from_source = false; |
1234 | 0 | break; |
1235 | 0 | case LBTRU_PACKET_TYPE_CREQ: |
1236 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "CREQ %s", val_to_str(pinfo->pool, flags_or_res, lbtru_creq_request, "Unknown (0x%02x)")); |
1237 | 0 | from_source = false; |
1238 | 0 | break; |
1239 | 0 | case LBTRU_PACKET_TYPE_RST: |
1240 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "RST %s", val_to_str(pinfo->pool, flags_or_res, lbtru_rst_reason, "Unknown (0x%02x)")); |
1241 | 0 | from_source = true; |
1242 | 0 | break; |
1243 | 0 | default: |
1244 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "Unknown (0x%02x)", LBTRU_HDR_TYPE(ver_type)); |
1245 | 0 | expert_add_info_format(pinfo, type_item, &ei_lbtru_analysis_unknown_type, "Unrecognized type 0x%02x", LBTRU_HDR_TYPE(ver_type)); |
1246 | 0 | return (total_dissected_len); |
1247 | 0 | } |
1248 | | |
1249 | | /* Handle the flags_or_res field. */ |
1250 | 0 | switch (packet_type) |
1251 | 0 | { |
1252 | 0 | case LBTRU_PACKET_TYPE_DATA: |
1253 | 0 | proto_tree_add_bitmask(header_tree, tvb, O_LBTRU_HDR_T_FLAGS_OR_RES, hf_lbtru_hdr_flags, ett_lbtru_hdr_flags, flags_data, ENC_BIG_ENDIAN); |
1254 | 0 | total_dissected_len += L_LBTRU_HDR_T_FLAGS_OR_RES; |
1255 | 0 | ofs += L_LBTRU_HDR_T_FLAGS_OR_RES; |
1256 | 0 | break; |
1257 | 0 | case LBTRU_PACKET_TYPE_NAK: |
1258 | 0 | case LBTRU_PACKET_TYPE_NCF: |
1259 | 0 | case LBTRU_PACKET_TYPE_ACK: |
1260 | 0 | proto_tree_add_item(header_tree, hf_lbtru_hdr_res, tvb, O_LBTRU_HDR_T_FLAGS_OR_RES, L_LBTRU_HDR_T_FLAGS_OR_RES, ENC_BIG_ENDIAN); |
1261 | 0 | total_dissected_len += L_LBTRU_HDR_T_FLAGS_OR_RES; |
1262 | 0 | ofs += L_LBTRU_HDR_T_FLAGS_OR_RES; |
1263 | 0 | break; |
1264 | 0 | case LBTRU_PACKET_TYPE_SM: |
1265 | 0 | proto_tree_add_bitmask(header_tree, tvb, O_LBTRU_HDR_T_FLAGS_OR_RES, hf_lbtru_hdr_flags, ett_lbtru_hdr_flags, flags_sm, ENC_BIG_ENDIAN); |
1266 | 0 | total_dissected_len += L_LBTRU_HDR_T_FLAGS_OR_RES; |
1267 | 0 | ofs += L_LBTRU_HDR_T_FLAGS_OR_RES; |
1268 | 0 | break; |
1269 | 0 | case LBTRU_PACKET_TYPE_CREQ: |
1270 | 0 | ei_item = proto_tree_add_item(header_tree, hf_lbtru_hdr_request, tvb, O_LBTRU_HDR_T_FLAGS_OR_RES, L_LBTRU_HDR_T_FLAGS_OR_RES, ENC_BIG_ENDIAN); |
1271 | 0 | expert_add_info_format(pinfo, ei_item, &ei_lbtru_analysis_creq, "CREQ %s", val_to_str(pinfo->pool, flags_or_res, lbtru_creq_request, "Unknown (0x%04x)")); |
1272 | 0 | total_dissected_len += L_LBTRU_HDR_T_FLAGS_OR_RES; |
1273 | 0 | ofs += L_LBTRU_HDR_T_FLAGS_OR_RES; |
1274 | 0 | break; |
1275 | 0 | case LBTRU_PACKET_TYPE_RST: |
1276 | 0 | ei_item = proto_tree_add_item(header_tree, hf_lbtru_hdr_reason, tvb, O_LBTRU_HDR_T_FLAGS_OR_RES, L_LBTRU_HDR_T_FLAGS_OR_RES, ENC_BIG_ENDIAN); |
1277 | 0 | expert_add_info_format(pinfo, ei_item, &ei_lbtru_analysis_rst, "RST %s", val_to_str(pinfo->pool, flags_or_res, lbtru_rst_reason, "Unknown (0x%04x)")); |
1278 | 0 | break; |
1279 | 0 | default: |
1280 | 0 | break; |
1281 | 0 | } |
1282 | | |
1283 | | /* Handle the packet-specific data */ |
1284 | 0 | switch (packet_type) |
1285 | 0 | { |
1286 | 0 | case LBTRU_PACKET_TYPE_DATA: |
1287 | 0 | dissected_len = dissect_lbtru_data(tvb, L_LBTRU_HDR_T, pinfo, lbtru_tree, tapinfo); |
1288 | 0 | break; |
1289 | 0 | case LBTRU_PACKET_TYPE_SM: |
1290 | 0 | dissected_len = dissect_lbtru_sm(tvb, L_LBTRU_HDR_T, pinfo, lbtru_tree, (flags_or_res & LBTRU_SM_SYN_FLAG), tapinfo); |
1291 | 0 | break; |
1292 | 0 | case LBTRU_PACKET_TYPE_NAK: |
1293 | 0 | dissected_len = dissect_lbtru_nak(tvb, ofs, pinfo, lbtru_tree, tapinfo); |
1294 | 0 | break; |
1295 | 0 | case LBTRU_PACKET_TYPE_NCF: |
1296 | 0 | dissected_len = dissect_lbtru_ncf(tvb, ofs, pinfo, lbtru_tree, tapinfo); |
1297 | 0 | break; |
1298 | 0 | case LBTRU_PACKET_TYPE_ACK: |
1299 | 0 | dissected_len = dissect_lbtru_ack(tvb, ofs, pinfo, lbtru_tree, tapinfo); |
1300 | 0 | break; |
1301 | 0 | case LBTRU_PACKET_TYPE_CREQ: |
1302 | 0 | dissected_len = 0; |
1303 | 0 | tapinfo->creq_type = flags_or_res; |
1304 | 0 | break; |
1305 | 0 | case LBTRU_PACKET_TYPE_RST: |
1306 | 0 | dissected_len = 0; |
1307 | 0 | tapinfo->rst_type = flags_or_res; |
1308 | 0 | break; |
1309 | 0 | default: |
1310 | 0 | dissected_len = 0; |
1311 | 0 | break; |
1312 | 0 | } |
1313 | 0 | total_dissected_len += dissected_len; |
1314 | 0 | ofs += dissected_len; |
1315 | | /* If we're doing sequence analysis, the tree goes here. */ |
1316 | 0 | if (lbtru_sequence_analysis) |
1317 | 0 | { |
1318 | 0 | transport_item = proto_tree_add_item(lbtru_tree, hf_lbtru_analysis, tvb, 0, 0, ENC_NA); |
1319 | 0 | proto_item_set_generated(transport_item); |
1320 | 0 | transport_tree = proto_item_add_subtree(transport_item, ett_lbtru_transport); |
1321 | 0 | } |
1322 | 0 | while (next_hdr != LBTRU_NHDR_DATA) |
1323 | 0 | { |
1324 | 0 | proto_item * hdr_length_item; |
1325 | 0 | proto_tree * opt_tree = NULL; |
1326 | 0 | static int * const sid_flags[] = |
1327 | 0 | { |
1328 | 0 | &hf_lbtru_opt_sid_flags_ignore, |
1329 | 0 | NULL |
1330 | 0 | }; |
1331 | 0 | static int * const cid_flags[] = |
1332 | 0 | { |
1333 | 0 | &hf_lbtru_opt_cid_flags_ignore, |
1334 | 0 | NULL |
1335 | 0 | }; |
1336 | 0 | int hdrlen; |
1337 | 0 | uint8_t cur_next_hdr; |
1338 | |
|
1339 | 0 | cur_next_hdr = tvb_get_uint8(tvb, ofs + O_LBTRU_BASIC_OPT_T_NEXT_HDR); |
1340 | 0 | hdrlen = (int)tvb_get_uint8(tvb, ofs + O_LBTRU_BASIC_OPT_T_HDR_LEN); |
1341 | 0 | switch (next_hdr) |
1342 | 0 | { |
1343 | 0 | case LBTRU_NHDR_SID: |
1344 | 0 | fld_item = proto_tree_add_item(lbtru_tree, hf_lbtru_opt_sid, tvb, ofs, L_LBTRU_BASIC_OPT_T + L_LBTRU_SID_OPT_T, ENC_NA); |
1345 | 0 | opt_tree = proto_item_add_subtree(fld_item, ett_lbtru_opt); |
1346 | 0 | next_hdr_item = proto_tree_add_item(opt_tree, hf_lbtru_opt_sid_next_hdr, tvb, ofs + O_LBTRU_BASIC_OPT_T_NEXT_HDR, L_LBTRU_BASIC_OPT_T_NEXT_HDR, ENC_BIG_ENDIAN); |
1347 | 0 | hdr_length_item = proto_tree_add_item(opt_tree, hf_lbtru_opt_sid_hdr_len, tvb, ofs + O_LBTRU_BASIC_OPT_T_HDR_LEN, L_LBTRU_BASIC_OPT_T_HDR_LEN, ENC_BIG_ENDIAN); |
1348 | 0 | if (hdrlen == 0) |
1349 | 0 | { |
1350 | 0 | expert_add_info(pinfo, hdr_length_item, &ei_lbtru_analysis_zero_length_header); |
1351 | 0 | return (total_dissected_len); |
1352 | 0 | } |
1353 | 0 | proto_tree_add_bitmask(opt_tree, tvb, ofs + O_LBTRU_BASIC_OPT_T_RES, hf_lbtru_opt_sid_flags, ett_lbtru_opt_sid_flags, sid_flags, ENC_BIG_ENDIAN); |
1354 | 0 | proto_tree_add_item(opt_tree, hf_lbtru_opt_sid_session_id, tvb, ofs + L_LBTRU_BASIC_OPT_T + O_LBTRU_SID_OPT_T_SESSION_ID, L_LBTRU_SID_OPT_T_SESSION_ID, ENC_BIG_ENDIAN); |
1355 | 0 | session_id = tvb_get_ntohl(tvb, ofs + L_LBTRU_BASIC_OPT_T + O_LBTRU_SID_OPT_T_SESSION_ID); |
1356 | 0 | break; |
1357 | 0 | case LBTRU_NHDR_CID: |
1358 | 0 | fld_item = proto_tree_add_item(lbtru_tree, hf_lbtru_opt_cid, tvb, ofs, L_LBTRU_BASIC_OPT_T + L_LBTRU_CID_OPT_T, ENC_NA); |
1359 | 0 | opt_tree = proto_item_add_subtree(fld_item, ett_lbtru_opt); |
1360 | 0 | next_hdr_item = proto_tree_add_item(opt_tree, hf_lbtru_opt_cid_next_hdr, tvb, ofs + O_LBTRU_BASIC_OPT_T_NEXT_HDR, L_LBTRU_BASIC_OPT_T_NEXT_HDR, ENC_BIG_ENDIAN); |
1361 | 0 | hdr_length_item = proto_tree_add_item(opt_tree, hf_lbtru_opt_cid_hdr_len, tvb, ofs + O_LBTRU_BASIC_OPT_T_HDR_LEN, L_LBTRU_BASIC_OPT_T_HDR_LEN, ENC_BIG_ENDIAN); |
1362 | 0 | if (hdrlen == 0) |
1363 | 0 | { |
1364 | 0 | expert_add_info(pinfo, hdr_length_item, &ei_lbtru_analysis_zero_length_header); |
1365 | 0 | return (total_dissected_len); |
1366 | 0 | } |
1367 | 0 | proto_tree_add_bitmask(opt_tree, tvb, ofs + O_LBTRU_BASIC_OPT_T_RES, hf_lbtru_opt_cid_flags, ett_lbtru_opt_cid_flags, cid_flags, ENC_BIG_ENDIAN); |
1368 | 0 | proto_tree_add_item(opt_tree, hf_lbtru_opt_cid_client_id, tvb, ofs + L_LBTRU_BASIC_OPT_T + O_LBTRU_CID_OPT_T_CLIENT_SID, L_LBTRU_CID_OPT_T_CLIENT_SID, ENC_BIG_ENDIAN); |
1369 | 0 | break; |
1370 | 0 | default: |
1371 | 0 | expert_add_info_format(pinfo, next_hdr_item, &ei_lbtru_analysis_unknown_header, "Unrecognized header 0x%02x", next_hdr); |
1372 | 0 | fld_item = proto_tree_add_item(lbtru_tree, hf_lbtru_opt_unknown, tvb, ofs, L_LBTRU_BASIC_OPT_T + L_LBTRU_CID_OPT_T, ENC_NA); |
1373 | 0 | opt_tree = proto_item_add_subtree(fld_item, ett_lbtru_opt); |
1374 | 0 | next_hdr_item = proto_tree_add_item(opt_tree, hf_lbtru_opt_unknown_next_hdr, tvb, ofs + O_LBTRU_BASIC_OPT_T_NEXT_HDR, L_LBTRU_BASIC_OPT_T_NEXT_HDR, ENC_BIG_ENDIAN); |
1375 | 0 | hdr_length_item = proto_tree_add_item(opt_tree, hf_lbtru_opt_unknown_hdr_len, tvb, ofs + O_LBTRU_BASIC_OPT_T_HDR_LEN, L_LBTRU_BASIC_OPT_T_HDR_LEN, ENC_BIG_ENDIAN); |
1376 | 0 | if (hdrlen == 0) |
1377 | 0 | { |
1378 | 0 | expert_add_info(pinfo, hdr_length_item, &ei_lbtru_analysis_zero_length_header); |
1379 | 0 | return (total_dissected_len); |
1380 | 0 | } |
1381 | 0 | break; |
1382 | 0 | } |
1383 | 0 | next_hdr = cur_next_hdr; |
1384 | 0 | ofs += hdrlen; |
1385 | 0 | total_dissected_len += hdrlen; |
1386 | 0 | } |
1387 | | |
1388 | | /* Find (or create) the transport and client entries */ |
1389 | 0 | if (from_source) |
1390 | 0 | { |
1391 | 0 | copy_address_shallow(&source_address, &(pinfo->src)); |
1392 | 0 | source_port = pinfo->srcport; |
1393 | 0 | copy_address_shallow(&receiver_address, &(pinfo->dst)); |
1394 | 0 | receiver_port = pinfo->destport; |
1395 | 0 | } |
1396 | 0 | else |
1397 | 0 | { |
1398 | 0 | copy_address_shallow(&source_address, &(pinfo->dst)); |
1399 | 0 | source_port = pinfo->destport; |
1400 | 0 | copy_address_shallow(&receiver_address, &(pinfo->src)); |
1401 | 0 | receiver_port = pinfo->srcport; |
1402 | 0 | } |
1403 | 0 | if (pinfo->fd->visited == 0) |
1404 | 0 | { |
1405 | 0 | transport = lbtru_transport_add(&source_address, source_port, session_id, pinfo->num); |
1406 | 0 | } |
1407 | 0 | else |
1408 | 0 | { |
1409 | 0 | transport = lbtru_transport_find(&source_address, source_port, session_id, pinfo->num); |
1410 | 0 | } |
1411 | 0 | if (transport != NULL) |
1412 | 0 | { |
1413 | 0 | if (pinfo->fd->visited == 0) |
1414 | 0 | { |
1415 | 0 | client = lbtru_client_transport_add(transport, &receiver_address, receiver_port, pinfo->num); |
1416 | 0 | if (client != NULL) |
1417 | 0 | { |
1418 | 0 | if (lbtru_sequence_analysis) |
1419 | 0 | { |
1420 | 0 | lbtru_client_transport_frame_add(client, packet_type, pinfo->num, packet_sqn, retransmission); |
1421 | 0 | } |
1422 | 0 | } |
1423 | 0 | } |
1424 | 0 | else |
1425 | 0 | { |
1426 | 0 | client = lbtru_client_transport_find(transport, &receiver_address, receiver_port, pinfo->num); |
1427 | 0 | } |
1428 | 0 | tapinfo->transport = lbtru_transport_source_string_transport(pinfo->pool, transport); |
1429 | 0 | channel = transport->channel; |
1430 | 0 | fld_item = proto_tree_add_uint64(channel_tree, hf_lbtru_channel_id, tvb, 0, 0, channel); |
1431 | 0 | proto_item_set_generated(fld_item); |
1432 | 0 | if (client != NULL) |
1433 | 0 | { |
1434 | 0 | fld_item = proto_tree_add_uint(channel_tree, hf_lbtru_channel_client, tvb, 0, 0, client->id); |
1435 | 0 | proto_item_set_generated(fld_item); |
1436 | 0 | } |
1437 | 0 | } |
1438 | 0 | proto_item_set_len(lbtru_item, total_dissected_len); |
1439 | 0 | if ((packet_type == LBTRU_PACKET_TYPE_DATA) && (next_hdr == LBTRU_NHDR_DATA)) |
1440 | 0 | { |
1441 | 0 | total_dissected_len += dissect_lbtru_data_contents(tvb, ofs, pinfo, tree, tag_name, channel); |
1442 | 0 | } |
1443 | 0 | if (lbtru_sequence_analysis) |
1444 | 0 | { |
1445 | 0 | if ((transport != NULL) && (client != NULL)) |
1446 | 0 | { |
1447 | 0 | lbm_transport_frame_t * frame = NULL; |
1448 | | |
1449 | | /* Fill in the tree */ |
1450 | 0 | frame = lbtru_client_transport_frame_find(client, pinfo->num); |
1451 | 0 | if (frame != NULL) |
1452 | 0 | { |
1453 | 0 | lbm_transport_sqn_t * sqn = NULL; |
1454 | |
|
1455 | 0 | if (frame->previous_frame != 0) |
1456 | 0 | { |
1457 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_frame, tvb, 0, 0, frame->previous_frame); |
1458 | 0 | proto_item_set_generated(transport_item); |
1459 | 0 | } |
1460 | 0 | if (frame->next_frame != 0) |
1461 | 0 | { |
1462 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_frame, tvb, 0, 0, frame->next_frame); |
1463 | 0 | proto_item_set_generated(transport_item); |
1464 | 0 | } |
1465 | 0 | switch (packet_type) |
1466 | 0 | { |
1467 | 0 | case LBTRU_PACKET_TYPE_DATA: |
1468 | 0 | if (frame->previous_type_frame != 0) |
1469 | 0 | { |
1470 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_data_frame, tvb, 0, 0, frame->previous_type_frame); |
1471 | 0 | proto_item_set_generated(transport_item); |
1472 | 0 | } |
1473 | 0 | if (frame->next_type_frame != 0) |
1474 | 0 | { |
1475 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_data_frame, tvb, 0, 0, frame->next_type_frame); |
1476 | 0 | proto_item_set_generated(transport_item); |
1477 | 0 | } |
1478 | 0 | sqn = lbtru_client_transport_sqn_find(client, packet_type, packet_sqn); |
1479 | 0 | if (sqn != NULL) |
1480 | 0 | { |
1481 | 0 | if (sqn->frame_count > 1) |
1482 | 0 | { |
1483 | 0 | proto_tree * frame_tree = NULL; |
1484 | 0 | proto_item * frame_tree_item = NULL; |
1485 | 0 | lbtru_sqn_frame_list_callback_data_t cb_data; |
1486 | |
|
1487 | 0 | frame_tree_item = proto_tree_add_item(transport_tree, hf_lbtru_analysis_sqn, tvb, 0, 0, ENC_NA); |
1488 | 0 | proto_item_set_generated(frame_tree_item); |
1489 | 0 | frame_tree = proto_item_add_subtree(frame_tree_item, ett_lbtru_transport_sqn); |
1490 | 0 | cb_data.tree = frame_tree; |
1491 | 0 | cb_data.tvb = tvb; |
1492 | 0 | cb_data.current_frame = pinfo->num; |
1493 | 0 | wmem_tree_foreach(sqn->frame, dissect_lbtru_sqn_frame_list_callback, (void *) &cb_data); |
1494 | 0 | } |
1495 | 0 | } |
1496 | 0 | if (frame->retransmission) |
1497 | 0 | { |
1498 | 0 | transport_item = proto_tree_add_boolean(transport_tree, hf_lbtru_analysis_data_retransmission, tvb, 0, 0, true); |
1499 | 0 | proto_item_set_generated(transport_item); |
1500 | 0 | expert_add_info(pinfo, transport_item, &ei_lbtru_analysis_data_rx); |
1501 | 0 | } |
1502 | 0 | if (frame->sqn_gap != 0) |
1503 | 0 | { |
1504 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_data_sqn_gap, tvb, 0, 0, frame->sqn_gap); |
1505 | 0 | proto_item_set_generated(transport_item); |
1506 | 0 | expert_add_info_format(pinfo, transport_item, &ei_lbtru_analysis_data_gap, "Data sequence gap (%" PRIu32 ")", frame->sqn_gap); |
1507 | |
|
1508 | 0 | } |
1509 | 0 | if (frame->ooo_gap != 0) |
1510 | 0 | { |
1511 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_data_ooo_gap, tvb, 0, 0, frame->ooo_gap); |
1512 | 0 | proto_item_set_generated(transport_item); |
1513 | 0 | expert_add_info_format(pinfo, transport_item, &ei_lbtru_analysis_data_ooo, "Data sequence out of order gap (%" PRIu32 ")", frame->ooo_gap); |
1514 | 0 | } |
1515 | 0 | if (frame->duplicate) |
1516 | 0 | { |
1517 | 0 | transport_item = proto_tree_add_boolean(transport_tree, hf_lbtru_analysis_data_duplicate, tvb, 0, 0, true); |
1518 | 0 | proto_item_set_generated(transport_item); |
1519 | 0 | expert_add_info(pinfo, transport_item, &ei_lbtru_analysis_data_dup); |
1520 | 0 | } |
1521 | 0 | break; |
1522 | 0 | case LBTRU_PACKET_TYPE_SM: |
1523 | 0 | if (frame->previous_type_frame != 0) |
1524 | 0 | { |
1525 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_sm_frame, tvb, 0, 0, frame->previous_type_frame); |
1526 | 0 | proto_item_set_generated(transport_item); |
1527 | 0 | } |
1528 | 0 | if (frame->next_type_frame != 0) |
1529 | 0 | { |
1530 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_sm_frame, tvb, 0, 0, frame->next_type_frame); |
1531 | 0 | proto_item_set_generated(transport_item); |
1532 | 0 | } |
1533 | 0 | sqn = lbtru_client_transport_sqn_find(client, packet_type, packet_sqn); |
1534 | 0 | if (sqn != NULL) |
1535 | 0 | { |
1536 | 0 | if (sqn->frame_count > 1) |
1537 | 0 | { |
1538 | 0 | proto_tree * frame_tree = NULL; |
1539 | 0 | proto_item * frame_tree_item = NULL; |
1540 | 0 | lbtru_sqn_frame_list_callback_data_t cb_data; |
1541 | |
|
1542 | 0 | frame_tree_item = proto_tree_add_item(transport_tree, hf_lbtru_analysis_sqn, tvb, 0, 0, ENC_NA); |
1543 | 0 | proto_item_set_generated(frame_tree_item); |
1544 | 0 | frame_tree = proto_item_add_subtree(frame_tree_item, ett_lbtru_transport_sqn); |
1545 | 0 | cb_data.tree = frame_tree; |
1546 | 0 | cb_data.tvb = tvb; |
1547 | 0 | cb_data.current_frame = pinfo->num; |
1548 | 0 | wmem_tree_foreach(sqn->frame, dissect_lbtru_sqn_frame_list_callback, (void *) &cb_data); |
1549 | 0 | } |
1550 | 0 | } |
1551 | 0 | if (frame->sqn_gap != 0) |
1552 | 0 | { |
1553 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_sm_sqn_gap, tvb, 0, 0, frame->sqn_gap); |
1554 | 0 | proto_item_set_generated(transport_item); |
1555 | 0 | expert_add_info_format(pinfo, transport_item, &ei_lbtru_analysis_sm_gap, "SM sequence gap (%" PRIu32 ")", frame->sqn_gap); |
1556 | |
|
1557 | 0 | } |
1558 | 0 | if (frame->ooo_gap != 0) |
1559 | 0 | { |
1560 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_sm_ooo_gap, tvb, 0, 0, frame->ooo_gap); |
1561 | 0 | proto_item_set_generated(transport_item); |
1562 | 0 | expert_add_info_format(pinfo, transport_item, &ei_lbtru_analysis_sm_ooo, "SM sequence out of order gap (%" PRIu32 ")", frame->ooo_gap); |
1563 | 0 | } |
1564 | 0 | if (frame->duplicate) |
1565 | 0 | { |
1566 | 0 | transport_item = proto_tree_add_boolean(transport_tree, hf_lbtru_analysis_sm_duplicate, tvb, 0, 0, true); |
1567 | 0 | proto_item_set_generated(transport_item); |
1568 | 0 | expert_add_info(pinfo, transport_item, &ei_lbtru_analysis_sm_dup); |
1569 | 0 | } |
1570 | 0 | break; |
1571 | 0 | case LBTRU_PACKET_TYPE_NAK: |
1572 | 0 | if (frame->previous_type_frame != 0) |
1573 | 0 | { |
1574 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_nak_frame, tvb, 0, 0, frame->previous_type_frame); |
1575 | 0 | proto_item_set_generated(transport_item); |
1576 | 0 | } |
1577 | 0 | if (frame->next_type_frame != 0) |
1578 | 0 | { |
1579 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_nak_frame, tvb, 0, 0, frame->next_type_frame); |
1580 | 0 | proto_item_set_generated(transport_item); |
1581 | 0 | } |
1582 | 0 | break; |
1583 | 0 | case LBTRU_PACKET_TYPE_NCF: |
1584 | 0 | if (frame->previous_type_frame != 0) |
1585 | 0 | { |
1586 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_ncf_frame, tvb, 0, 0, frame->previous_type_frame); |
1587 | 0 | proto_item_set_generated(transport_item); |
1588 | 0 | } |
1589 | 0 | if (frame->next_type_frame != 0) |
1590 | 0 | { |
1591 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_ncf_frame, tvb, 0, 0, frame->next_type_frame); |
1592 | 0 | proto_item_set_generated(transport_item); |
1593 | 0 | } |
1594 | 0 | break; |
1595 | 0 | case LBTRU_PACKET_TYPE_ACK: |
1596 | 0 | if (frame->previous_type_frame != 0) |
1597 | 0 | { |
1598 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_ack_frame, tvb, 0, 0, frame->previous_type_frame); |
1599 | 0 | proto_item_set_generated(transport_item); |
1600 | 0 | } |
1601 | 0 | if (frame->next_type_frame != 0) |
1602 | 0 | { |
1603 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_ack_frame, tvb, 0, 0, frame->next_type_frame); |
1604 | 0 | proto_item_set_generated(transport_item); |
1605 | 0 | } |
1606 | 0 | break; |
1607 | 0 | case LBTRU_PACKET_TYPE_CREQ: |
1608 | 0 | if (frame->previous_type_frame != 0) |
1609 | 0 | { |
1610 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_creq_frame, tvb, 0, 0, frame->previous_type_frame); |
1611 | 0 | proto_item_set_generated(transport_item); |
1612 | 0 | } |
1613 | 0 | if (frame->next_type_frame != 0) |
1614 | 0 | { |
1615 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_creq_frame, tvb, 0, 0, frame->next_type_frame); |
1616 | 0 | proto_item_set_generated(transport_item); |
1617 | 0 | } |
1618 | 0 | break; |
1619 | 0 | case LBTRU_PACKET_TYPE_RST: |
1620 | 0 | if (frame->previous_type_frame != 0) |
1621 | 0 | { |
1622 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_rst_frame, tvb, 0, 0, frame->previous_type_frame); |
1623 | 0 | proto_item_set_generated(transport_item); |
1624 | 0 | } |
1625 | 0 | if (frame->next_type_frame != 0) |
1626 | 0 | { |
1627 | 0 | transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_rst_frame, tvb, 0, 0, frame->next_type_frame); |
1628 | 0 | proto_item_set_generated(transport_item); |
1629 | 0 | } |
1630 | 0 | break; |
1631 | 0 | default: |
1632 | 0 | break; |
1633 | 0 | } |
1634 | 0 | } |
1635 | 0 | } |
1636 | 0 | } |
1637 | 0 | if (tapinfo->transport != NULL) |
1638 | 0 | { |
1639 | 0 | tap_queue_packet(lbtru_tap_handle, pinfo, (void *) tapinfo); |
1640 | 0 | } |
1641 | 0 | return (total_dissected_len); |
1642 | 0 | } |
1643 | | |
1644 | | static bool test_lbtru_packet(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * user_data) |
1645 | 881 | { |
1646 | 881 | bool valid_packet = false; |
1647 | | |
1648 | | /* Must be a UDP packet. */ |
1649 | 881 | if (pinfo->ptype != PT_UDP) |
1650 | 1 | { |
1651 | 1 | return false; |
1652 | 1 | } |
1653 | | /* Destination address must be IPV4 and 4 bytes in length. */ |
1654 | 880 | if ((pinfo->dst.type != AT_IPv4) || (pinfo->dst.len != 4)) |
1655 | 880 | { |
1656 | 880 | return false; |
1657 | 880 | } |
1658 | | |
1659 | 0 | if (lbtru_use_tag) |
1660 | 0 | { |
1661 | 0 | if (lbtru_tag_find(pinfo) != NULL) |
1662 | 0 | { |
1663 | 0 | valid_packet = true; |
1664 | 0 | } |
1665 | 0 | } |
1666 | 0 | else |
1667 | 0 | { |
1668 | | /* |
1669 | | Source port must be in the source port range and destination port must be in the receiver port range, |
1670 | | or vice-versa. |
1671 | | */ |
1672 | 0 | if (((pinfo->destport >= lbtru_source_port_low) |
1673 | 0 | && (pinfo->destport <= lbtru_source_port_high) |
1674 | 0 | && (pinfo->srcport >= lbtru_receiver_port_low) |
1675 | 0 | && (pinfo->srcport <= lbtru_receiver_port_high)) |
1676 | 0 | || ((pinfo->destport >= lbtru_receiver_port_low) |
1677 | 0 | && (pinfo->destport <= lbtru_receiver_port_high) |
1678 | 0 | && (pinfo->srcport >= lbtru_source_port_low) |
1679 | 0 | && (pinfo->srcport <= lbtru_source_port_high))) |
1680 | 0 | { |
1681 | | /* One of ours. */ |
1682 | 0 | valid_packet = true; |
1683 | 0 | } |
1684 | 0 | } |
1685 | 0 | if (valid_packet) |
1686 | 0 | { |
1687 | 0 | dissect_lbtru(tvb, pinfo, tree, user_data); |
1688 | 0 | return true; |
1689 | 0 | } |
1690 | | /* Not one of ours. */ |
1691 | 0 | return false; |
1692 | 0 | } |
1693 | | |
1694 | | /* Register all the bits needed with the filtering engine */ |
1695 | | void proto_register_lbtru(void) |
1696 | 15 | { |
1697 | 15 | static hf_register_info hf[] = |
1698 | 15 | { |
1699 | 15 | { &hf_lbtru_channel, |
1700 | 15 | { "Channel", "lbtru.channel", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1701 | 15 | { &hf_lbtru_channel_id, |
1702 | 15 | { "Channel ID", "lbtru.channel.channel", FT_UINT64, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } }, |
1703 | 15 | { &hf_lbtru_channel_client, |
1704 | 15 | { "Channel Client", "lbtru.channel.client", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1705 | 15 | { &hf_lbtru_tag, |
1706 | 15 | { "Tag", "lbtru.tag", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1707 | 15 | { &hf_lbtru_hdr, |
1708 | 15 | { "Header", "lbtru.hdr", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1709 | 15 | { &hf_lbtru_hdr_ver, |
1710 | 15 | { "Version", "lbtru.hdr.ver", FT_UINT8, BASE_DEC, NULL, LBTRU_HDR_VER_VER_MASK, NULL, HFILL } }, |
1711 | 15 | { &hf_lbtru_hdr_type, |
1712 | 15 | { "Type", "lbtru.hdr.type", FT_UINT8, BASE_HEX, VALS(lbtru_packet_type), LBTRU_HDR_VER_TYPE_MASK, NULL, HFILL } }, |
1713 | 15 | { &hf_lbtru_hdr_next_hdr, |
1714 | 15 | { "Next Header", "lbtru.hdr.next_hdr", FT_UINT8, BASE_HEX, VALS(lbtru_next_header), 0x0, NULL, HFILL } }, |
1715 | 15 | { &hf_lbtru_hdr_res, |
1716 | 15 | { "Reserved", "lbtru.hdr.res", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
1717 | 15 | { &hf_lbtru_hdr_flags, |
1718 | 15 | { "Flags", "lbtru.hdr.flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
1719 | 15 | { &hf_lbtru_hdr_flags_rx, |
1720 | 15 | { "Retransmission", "lbtru.hdr.flags.rx", FT_BOOLEAN, L_LBTRU_HDR_T_FLAGS_OR_RES * 8, TFS(&tfs_set_notset), LBTRU_RETRANSMISSION_FLAG, NULL, HFILL } }, |
1721 | 15 | { &hf_lbtru_hdr_flags_syn, |
1722 | 15 | { "SYN", "lbtru.hdr.flags.syn", FT_BOOLEAN, L_LBTRU_HDR_T_FLAGS_OR_RES * 8, TFS(&tfs_set_notset), LBTRU_SM_SYN_FLAG, NULL, HFILL } }, |
1723 | 15 | { &hf_lbtru_hdr_request, |
1724 | 15 | { "Request", "lbtru.hdr.request", FT_UINT16, BASE_HEX, VALS(lbtru_creq_request), 0x0, NULL, HFILL } }, |
1725 | 15 | { &hf_lbtru_hdr_reason, |
1726 | 15 | { "Reason", "lbtru.hdr.reason", FT_UINT16, BASE_HEX, VALS(lbtru_rst_reason), 0x0, NULL, HFILL } }, |
1727 | 15 | { &hf_lbtru_data, |
1728 | 15 | { "Data Header", "lbtru.data", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1729 | 15 | { &hf_lbtru_data_sqn, |
1730 | 15 | { "Sequence Number", "lbtru.data.sqn", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } }, |
1731 | 15 | { &hf_lbtru_data_trail_sqn, |
1732 | 15 | { "Trailing Edge Sequence Number", "lbtru.data.trail", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } }, |
1733 | 15 | { &hf_lbtru_sm, |
1734 | 15 | { "Session Message Header", "lbtru.sm", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1735 | 15 | { &hf_lbtru_sm_sqn, |
1736 | 15 | { "Sequence Number", "lbtru.sm.sqn", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } }, |
1737 | 15 | { &hf_lbtru_sm_lead_sqn, |
1738 | 15 | { "Leading Edge Sequence Number", "lbtru.sm.lead", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } }, |
1739 | 15 | { &hf_lbtru_sm_trail_sqn, |
1740 | 15 | { "Trailing Edge Sequence Number", "lbtru.sm.trail", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } }, |
1741 | 15 | { &hf_lbtru_nak, |
1742 | 15 | { "NAK Header", "lbtru.nak", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1743 | 15 | { &hf_lbtru_nak_num, |
1744 | 15 | { "Number of NAKs", "lbtru.nak.num", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1745 | 15 | { &hf_lbtru_nak_format, |
1746 | 15 | { "Format", "lbtru.nak.format", FT_UINT16, BASE_DEC, VALS(lbtru_nak_format), LBTRU_NAK_HDR_FORMAT_MASK, NULL, HFILL } }, |
1747 | 15 | { &hf_lbtru_nak_list, |
1748 | 15 | { "NAK List", "lbtru.nak.list", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1749 | 15 | { &hf_lbtru_nak_list_nak, |
1750 | 15 | { "NAK", "lbtru.nak.list.nak", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, |
1751 | 15 | { &hf_lbtru_ncf, |
1752 | 15 | { "NAK Confirmation Header", "lbtru.ncf", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1753 | 15 | { &hf_lbtru_ncf_trail_sqn, |
1754 | 15 | { "Trailing Edge Sequence Number", "lbtru.ncf.trail", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } }, |
1755 | 15 | { &hf_lbtru_ncf_num, |
1756 | 15 | { "Number of Individual NCFs", "lbtru.ncf.num", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1757 | 15 | { &hf_lbtru_ncf_reserved, |
1758 | 15 | { "Reserved", "lbtru.ncf.reserved", FT_UINT8, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } }, |
1759 | 15 | { &hf_lbtru_ncf_reason, |
1760 | 15 | { "Reason", "lbtru.ncf.reason", FT_UINT8, BASE_HEX, VALS(lbtru_ncf_reason), LBTRU_NCF_HDR_REASON_MASK, NULL, HFILL } }, |
1761 | 15 | { &hf_lbtru_ncf_format, |
1762 | 15 | { "Format", "lbtru.ncf.format", FT_UINT8, BASE_HEX, VALS(lbtru_ncf_format), LBTRU_NCF_HDR_FORMAT_MASK, NULL, HFILL } }, |
1763 | 15 | { &hf_lbtru_ncf_list, |
1764 | 15 | { "NCF List", "lbtru.ncf.list", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1765 | 15 | { &hf_lbtru_ncf_list_ncf, |
1766 | 15 | { "NCF", "lbtru.ncf.list.ncf", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, |
1767 | 15 | { &hf_lbtru_ack, |
1768 | 15 | { "ACK Header", "lbtru.ack", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1769 | 15 | { &hf_lbtru_ack_sqn, |
1770 | 15 | { "ACK Sequence Number", "lbtru.ack.sqn", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } }, |
1771 | 15 | { &hf_lbtru_opt_sid, |
1772 | 15 | { "SID Option", "lbtru.opt_sid", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1773 | 15 | { &hf_lbtru_opt_sid_next_hdr, |
1774 | 15 | { "Next Header", "lbtru.opt_sid.next_hdr", FT_UINT8, BASE_DEC_HEX, VALS(lbtru_next_header), 0x0, NULL, HFILL } }, |
1775 | 15 | { &hf_lbtru_opt_sid_hdr_len, |
1776 | 15 | { "Header Length", "lbtru.opt_sid.hdr_len", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, |
1777 | 15 | { &hf_lbtru_opt_sid_flags, |
1778 | 15 | { "Flags", "lbtru.opt_sid.flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
1779 | 15 | { &hf_lbtru_opt_sid_flags_ignore, |
1780 | 15 | { "Ignore", "lbtru.opt_sid.flags.ignore", FT_BOOLEAN, L_LBTRU_BASIC_OPT_T_RES * 8, &(tfs_set_notset), LBTRU_OPT_IGNORE, NULL, HFILL } }, |
1781 | 15 | { &hf_lbtru_opt_sid_session_id, |
1782 | 15 | { "Session ID", "lbtru.opt_sid.session_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
1783 | 15 | { &hf_lbtru_opt_cid, |
1784 | 15 | { "CID Option", "lbtru.opt_cid", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1785 | 15 | { &hf_lbtru_opt_cid_next_hdr, |
1786 | 15 | { "Next Header", "lbtru.opt_cid.next_hdr", FT_UINT8, BASE_DEC_HEX, VALS(lbtru_next_header), 0x0, NULL, HFILL } }, |
1787 | 15 | { &hf_lbtru_opt_cid_hdr_len, |
1788 | 15 | { "Header Length", "lbtru.opt_cid.hdr_len", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, |
1789 | 15 | { &hf_lbtru_opt_cid_flags, |
1790 | 15 | { "Flags", "lbtru.opt_cid.flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
1791 | 15 | { &hf_lbtru_opt_cid_flags_ignore, |
1792 | 15 | { "Ignore", "lbtru.opt_cid.flags.ignore", FT_BOOLEAN, L_LBTRU_BASIC_OPT_T_RES * 8, &(tfs_set_notset), LBTRU_OPT_IGNORE, NULL, HFILL } }, |
1793 | 15 | { &hf_lbtru_opt_cid_client_id, |
1794 | 15 | { "Client ID", "lbtru.opt_cid.client_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
1795 | 15 | { &hf_lbtru_opt_unknown, |
1796 | 15 | { "Unknown Option", "lbtru.opt_unknown", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1797 | 15 | { &hf_lbtru_opt_unknown_next_hdr, |
1798 | 15 | { "Next Header", "lbtru.opt_unknown.next_hdr", FT_UINT8, BASE_DEC_HEX, VALS(lbtru_next_header), 0x0, NULL, HFILL } }, |
1799 | 15 | { &hf_lbtru_opt_unknown_hdr_len, |
1800 | 15 | { "Header Length", "lbtru.opt_unknown.hdr_len", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, |
1801 | 15 | { &hf_lbtru_analysis, |
1802 | 15 | { "Transport Analysis", "lbtru.analysis", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1803 | 15 | { &hf_lbtru_analysis_prev_frame, |
1804 | 15 | { "Previous Transport Frame", "lbtru.analysis.prev_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1805 | 15 | { &hf_lbtru_analysis_prev_data_frame, |
1806 | 15 | { "Previous Transport DATA Frame", "lbtru.analysis.prev_data_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1807 | 15 | { &hf_lbtru_analysis_prev_sm_frame, |
1808 | 15 | { "Previous Transport SM Frame", "lbtru.analysis.prev_sm_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1809 | 15 | { &hf_lbtru_analysis_prev_nak_frame, |
1810 | 15 | { "Previous Transport NAK Frame", "lbtru.analysis.prev_nak_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1811 | 15 | { &hf_lbtru_analysis_prev_ncf_frame, |
1812 | 15 | { "Previous Transport NCF Frame", "lbtru.analysis.prev_ncf_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1813 | 15 | { &hf_lbtru_analysis_prev_ack_frame, |
1814 | 15 | { "Previous Transport ACK Frame", "lbtru.analysis.prev_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1815 | 15 | { &hf_lbtru_analysis_prev_creq_frame, |
1816 | 15 | { "Previous Transport CREQ Frame", "lbtru.analysis.prev_creq_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1817 | 15 | { &hf_lbtru_analysis_prev_rst_frame, |
1818 | 15 | { "Previous Transport RST Frame", "lbtru.analysis.prev_rst_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1819 | 15 | { &hf_lbtru_analysis_next_frame, |
1820 | 15 | { "Next Transport Frame", "lbtru.analysis.next_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1821 | 15 | { &hf_lbtru_analysis_next_data_frame, |
1822 | 15 | { "Next Transport DATA Frame", "lbtru.analysis.next_data_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1823 | 15 | { &hf_lbtru_analysis_next_sm_frame, |
1824 | 15 | { "Next Transport SM Frame", "lbtru.analysis.next_sm_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1825 | 15 | { &hf_lbtru_analysis_next_nak_frame, |
1826 | 15 | { "Next Transport NAK Frame", "lbtru.analysis.next_nak_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1827 | 15 | { &hf_lbtru_analysis_next_ncf_frame, |
1828 | 15 | { "Next Transport NCF Frame", "lbtru.analysis.next_ncf_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1829 | 15 | { &hf_lbtru_analysis_next_ack_frame, |
1830 | 15 | { "Next Transport ACK Frame", "lbtru.analysis.next_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1831 | 15 | { &hf_lbtru_analysis_next_creq_frame, |
1832 | 15 | { "Next Transport CREQ Frame", "lbtru.analysis.next_creq_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1833 | 15 | { &hf_lbtru_analysis_next_rst_frame, |
1834 | 15 | { "Next Transport RST Frame", "lbtru.analysis.next_rst_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1835 | 15 | { &hf_lbtru_analysis_sqn, |
1836 | 15 | { "SQN Also in", "lbtru.analysis.sqn", FT_NONE, BASE_NONE, NULL, 0x0, "Sequence number also appears in these frames", HFILL } }, |
1837 | 15 | { &hf_lbtru_analysis_sqn_frame, |
1838 | 15 | { "Frame", "lbtru.analysis.sqn.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1839 | 15 | { &hf_lbtru_analysis_data_retransmission, |
1840 | 15 | { "Frame is a Data Retransmission", "lbtru.analysis.data_retransmission", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1841 | 15 | { &hf_lbtru_analysis_data_sqn_gap, |
1842 | 15 | { "Gap in Data Sequence", "lbtru.analysis.data_sqn_gap", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1843 | 15 | { &hf_lbtru_analysis_data_ooo_gap, |
1844 | 15 | { "Data Sequence Out of Order Gap", "lbtru.analysis.data_ooo_gap", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1845 | 15 | { &hf_lbtru_analysis_data_duplicate, |
1846 | 15 | { "Duplicate Data Frame", "lbtru.analysis.data_duplicate", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1847 | 15 | { &hf_lbtru_analysis_sm_sqn_gap, |
1848 | 15 | { "Gap in SM Sequence", "lbtru.analysis.sm_sqn_gap", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1849 | 15 | { &hf_lbtru_analysis_sm_ooo_gap, |
1850 | 15 | { "SM Sequence Out of Order Gap", "lbtru.analysis.sm_ooo_gap", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1851 | 15 | { &hf_lbtru_analysis_sm_duplicate, |
1852 | 15 | { "Duplicate SM Frame", "lbtru.analysis.sm_duplicate", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1853 | 15 | }; |
1854 | 15 | static int * ett[] = |
1855 | 15 | { |
1856 | 15 | &ett_lbtru, |
1857 | 15 | &ett_lbtru_channel, |
1858 | 15 | &ett_lbtru_hdr, |
1859 | 15 | &ett_lbtru_hdr_flags, |
1860 | 15 | &ett_lbtru_data, |
1861 | 15 | &ett_lbtru_sm, |
1862 | 15 | &ett_lbtru_nak, |
1863 | 15 | &ett_lbtru_nak_list, |
1864 | 15 | &ett_lbtru_ncf, |
1865 | 15 | &ett_lbtru_ncf_list, |
1866 | 15 | &ett_lbtru_ack, |
1867 | 15 | &ett_lbtru_opt, |
1868 | 15 | &ett_lbtru_opt_sid_flags, |
1869 | 15 | &ett_lbtru_opt_cid_flags, |
1870 | 15 | &ett_lbtru_transport, |
1871 | 15 | &ett_lbtru_transport_sqn, |
1872 | 15 | }; |
1873 | 15 | static ei_register_info ei[] = |
1874 | 15 | { |
1875 | 15 | { &ei_lbtru_analysis_unknown_type, { "lbtru.analysis.unknown_type", PI_MALFORMED, PI_ERROR, "Unrecognized type", EXPFILL } }, |
1876 | 15 | { &ei_lbtru_analysis_unknown_header, { "lbtru.analysis.unknown_header", PI_MALFORMED, PI_ERROR, "Unrecognized header", EXPFILL } }, |
1877 | 15 | { &ei_lbtru_analysis_zero_length_header, { "lbtru.analysis.zero_length_header", PI_MALFORMED, PI_ERROR, "Zero-length header", EXPFILL } }, |
1878 | 15 | { &ei_lbtru_analysis_ack, { "lbtru.analysis.ack", PI_SEQUENCE, PI_CHAT, "ACK", EXPFILL } }, |
1879 | 15 | { &ei_lbtru_analysis_ncf, { "lbtru.analysis.ncf", PI_SEQUENCE, PI_NOTE, "NCF", EXPFILL } }, |
1880 | 15 | { &ei_lbtru_analysis_ncf_ncf, { "lbtru.analysis.ncf.ncf", PI_SEQUENCE, PI_NOTE, "NCF", EXPFILL } }, |
1881 | 15 | { &ei_lbtru_analysis_nak, { "lbtru.analysis.nak", PI_SEQUENCE, PI_WARN, "NAK", EXPFILL } }, |
1882 | 15 | { &ei_lbtru_analysis_nak_nak, { "lbtru.analysis.nak.nak", PI_SEQUENCE, PI_WARN, "NAK", EXPFILL } }, |
1883 | 15 | { &ei_lbtru_analysis_sm, { "lbtru.analysis.sm", PI_SEQUENCE, PI_CHAT, "SM", EXPFILL } }, |
1884 | 15 | { &ei_lbtru_analysis_sm_syn, { "lbtru.analysis.sm.syn", PI_SEQUENCE, PI_CHAT, "SM SYN", EXPFILL } }, |
1885 | 15 | { &ei_lbtru_analysis_creq, { "lbtru.analysis.creq", PI_SEQUENCE, PI_CHAT, "Connection REQuest", EXPFILL } }, |
1886 | 15 | { &ei_lbtru_analysis_rst, { "lbtru.analysis.rst", PI_SEQUENCE, PI_CHAT, "ReSeT", EXPFILL } }, |
1887 | 15 | { &ei_lbtru_analysis_data_rx, { "lbtru.analysis.data.rx", PI_SEQUENCE, PI_NOTE, "Data retransmission", EXPFILL } }, |
1888 | 15 | { &ei_lbtru_analysis_data_gap, { "lbtru.analysis.data.gap", PI_SEQUENCE, PI_NOTE, "Data sequence gap", EXPFILL } }, |
1889 | 15 | { &ei_lbtru_analysis_data_ooo, { "lbtru.analysis.data.ooo", PI_SEQUENCE, PI_NOTE, "Data sequence out of order", EXPFILL } }, |
1890 | 15 | { &ei_lbtru_analysis_data_dup, { "lbtru.analysis.data.dup", PI_SEQUENCE, PI_NOTE, "Duplicate data", EXPFILL } }, |
1891 | 15 | { &ei_lbtru_analysis_sm_gap, { "lbtru.analysis.sm.gap", PI_SEQUENCE, PI_NOTE, "SM sequence gap", EXPFILL } }, |
1892 | 15 | { &ei_lbtru_analysis_sm_ooo, { "lbtru.analysis.sm.ooo", PI_SEQUENCE, PI_NOTE, "SM sequence out of order", EXPFILL } }, |
1893 | 15 | { &ei_lbtru_analysis_sm_dup, { "lbtru.analysis.sm.dup", PI_SEQUENCE, PI_NOTE, "Duplicate SM", EXPFILL } }, |
1894 | 15 | }; |
1895 | 15 | module_t * lbtru_module; |
1896 | 15 | uat_t * tag_uat; |
1897 | 15 | expert_module_t * expert_lbtru; |
1898 | | |
1899 | 15 | proto_lbtru = proto_register_protocol("LBT Reliable Unicast Protocol", |
1900 | 15 | "LBT-RU", "lbtru"); |
1901 | | |
1902 | 15 | proto_register_field_array(proto_lbtru, hf, array_length(hf)); |
1903 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
1904 | 15 | expert_lbtru = expert_register_protocol(proto_lbtru); |
1905 | 15 | expert_register_field_array(expert_lbtru, ei, array_length(ei)); |
1906 | | |
1907 | 15 | lbtru_dissector_handle = register_dissector("lbtru", dissect_lbtru, proto_lbtru); |
1908 | | |
1909 | 15 | lbtru_tap_handle = register_tap("lbm_lbtru"); |
1910 | | |
1911 | 15 | lbtru_module = prefs_register_protocol_subtree("29West", proto_lbtru, proto_reg_handoff_lbtru); |
1912 | 15 | prefs_register_uint_preference(lbtru_module, |
1913 | 15 | "source_port_low", |
1914 | 15 | "Source port range low (default " MAKESTRING(LBTRU_DEFAULT_SOURCE_PORT_LOW)")", |
1915 | 15 | "Set the low end of the LBT-RU source UDP port range (context transport_lbtru_port_low)", |
1916 | 15 | 10, |
1917 | 15 | &global_lbtru_source_port_low); |
1918 | | |
1919 | 15 | prefs_register_uint_preference(lbtru_module, |
1920 | 15 | "source_port_high", |
1921 | 15 | "Source port range high (default " MAKESTRING(LBTRU_DEFAULT_SOURCE_PORT_HIGH)")", |
1922 | 15 | "Set the high end of the LBT-RU source UDP port range (context transport_lbtru_port_high)", |
1923 | 15 | 10, |
1924 | 15 | &global_lbtru_source_port_high); |
1925 | | |
1926 | 15 | prefs_register_uint_preference(lbtru_module, |
1927 | 15 | "receiver_port_low", |
1928 | 15 | "Receiver port range low (default " MAKESTRING(LBTRU_DEFAULT_RECEIVER_PORT_LOW)")", |
1929 | 15 | "Set the low end of the LBT-RU receiver UDP port range (receiver transport_lbtru_port_low)", |
1930 | 15 | 10, |
1931 | 15 | &global_lbtru_receiver_port_low); |
1932 | | |
1933 | 15 | prefs_register_uint_preference(lbtru_module, |
1934 | 15 | "receiver_port_high", |
1935 | 15 | "Receiver port range high (default " MAKESTRING(LBTRU_DEFAULT_RECEIVER_PORT_HIGH)")", |
1936 | 15 | "Set the high end of the LBT-RU receiver UDP port range (receiver transport_lbtru_port_high)", |
1937 | 15 | 10, |
1938 | 15 | &global_lbtru_receiver_port_high); |
1939 | | |
1940 | 15 | lbtru_expert_separate_naks = global_lbtru_expert_separate_naks; |
1941 | 15 | prefs_register_bool_preference(lbtru_module, |
1942 | 15 | "expert_separate_naks", |
1943 | 15 | "Separate NAKs in Expert Info", |
1944 | 15 | "Separate multiple NAKs from a single packet into distinct Expert Info entries", |
1945 | 15 | &global_lbtru_expert_separate_naks); |
1946 | 15 | lbtru_expert_separate_ncfs = global_lbtru_expert_separate_ncfs; |
1947 | 15 | prefs_register_bool_preference(lbtru_module, |
1948 | 15 | "expert_separate_ncfs", |
1949 | 15 | "Separate NCFs in Expert Info", |
1950 | 15 | "Separate multiple NCFs from a single packet into distinct Expert Info entries", |
1951 | 15 | &global_lbtru_expert_separate_ncfs); |
1952 | | |
1953 | 15 | lbtru_sequence_analysis = global_lbtru_sequence_analysis; |
1954 | 15 | prefs_register_bool_preference(lbtru_module, |
1955 | 15 | "sequence_analysis", |
1956 | 15 | "Perform Sequence Number Analysis", |
1957 | 15 | "Perform analysis on LBT-RU sequence numbers to determine out-of-order, gaps, loss, etc", |
1958 | 15 | &global_lbtru_sequence_analysis); |
1959 | | |
1960 | 15 | prefs_register_bool_preference(lbtru_module, |
1961 | 15 | "use_lbtru_domain", |
1962 | 15 | "Use LBT-RU tag table", |
1963 | 15 | "Use table of LBT-RU tags to decode the packet instead of above values", |
1964 | 15 | &global_lbtru_use_tag); |
1965 | 15 | tag_uat = uat_new("LBT-RU tag definitions", |
1966 | 15 | sizeof(lbtru_tag_entry_t), |
1967 | 15 | "lbtru_domains", |
1968 | 15 | true, |
1969 | 15 | (void * *)&lbtru_tag_entry, |
1970 | 15 | &lbtru_tag_count, |
1971 | 15 | UAT_AFFECTS_DISSECTION, |
1972 | 15 | NULL, |
1973 | 15 | lbtru_tag_copy_cb, |
1974 | 15 | lbtru_tag_update_cb, |
1975 | 15 | lbtru_tag_free_cb, |
1976 | 15 | NULL, |
1977 | 15 | NULL, |
1978 | 15 | lbtru_tag_array); |
1979 | 15 | prefs_register_uat_preference(lbtru_module, |
1980 | 15 | "tnw_lbtru_tags", |
1981 | 15 | "LBT-RU Tags", |
1982 | 15 | "A table to define LBT-RU tags", |
1983 | 15 | tag_uat); |
1984 | 15 | } |
1985 | | |
1986 | | /* The registration hand-off routine */ |
1987 | | void proto_reg_handoff_lbtru(void) |
1988 | 15 | { |
1989 | 15 | static bool already_registered = false; |
1990 | | |
1991 | 15 | if (!already_registered) |
1992 | 15 | { |
1993 | 15 | dissector_add_for_decode_as_with_preference("udp.port", lbtru_dissector_handle); |
1994 | 15 | heur_dissector_add("udp", test_lbtru_packet, "LBT Reliable Unicast over UDP", "lbtru_udp", proto_lbtru, HEURISTIC_ENABLE); |
1995 | 15 | } |
1996 | | |
1997 | | /* Make sure the low source port is <= the high source port. If not, don't change them. */ |
1998 | 15 | if (global_lbtru_source_port_low <= global_lbtru_source_port_high) |
1999 | 15 | { |
2000 | 15 | lbtru_source_port_low = global_lbtru_source_port_low; |
2001 | 15 | lbtru_source_port_high = global_lbtru_source_port_high; |
2002 | 15 | } |
2003 | | |
2004 | | /* Make sure the low receiver port is <= the high receiver port. If not, don't change them. */ |
2005 | 15 | if (global_lbtru_receiver_port_low <= global_lbtru_receiver_port_high) |
2006 | 15 | { |
2007 | 15 | lbtru_receiver_port_low = global_lbtru_receiver_port_low; |
2008 | 15 | lbtru_receiver_port_high = global_lbtru_receiver_port_high; |
2009 | 15 | } |
2010 | | |
2011 | 15 | lbtru_expert_separate_naks = global_lbtru_expert_separate_naks; |
2012 | 15 | lbtru_expert_separate_ncfs = global_lbtru_expert_separate_ncfs; |
2013 | | |
2014 | 15 | lbtru_sequence_analysis = global_lbtru_sequence_analysis; |
2015 | | |
2016 | 15 | lbtru_use_tag = global_lbtru_use_tag; |
2017 | | |
2018 | | already_registered = true; |
2019 | 15 | } |
2020 | | |
2021 | | /* |
2022 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
2023 | | * |
2024 | | * Local variables: |
2025 | | * c-basic-offset: 4 |
2026 | | * tab-width: 8 |
2027 | | * indent-tabs-mode: nil |
2028 | | * End: |
2029 | | * |
2030 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
2031 | | * :indentSize=4:tabSize=8:noTabs=true: |
2032 | | */ |