TODO drsuapi compressed
[wireshark-sm.git] / epan / dissectors / packet-lbtru.c
blob67db891174aae1ba47f58cd31e194ed6d848e2fc
1 /* packet-lbtru.c
2 * Routines for LBT-RU Packet dissection
4 * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved.
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
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"
24 void proto_register_lbtru(void);
25 void proto_reg_handoff_lbtru(void);
27 /* Protocol handle */
28 static int proto_lbtru;
30 /* Dissector handle */
31 static dissector_handle_t lbtru_dissector_handle;
33 /* Tap handle */
34 static int lbtru_tap_handle = -1;
36 /*----------------------------------------------------------------------------*/
37 /* LBT-RU transport management. */
38 /*----------------------------------------------------------------------------*/
40 static const address lbtru_null_address = ADDRESS_INIT_NONE;
42 static lbtru_transport_t * lbtru_transport_find(const address * source_address, uint16_t source_port, uint32_t session_id, uint32_t frame)
44 lbtru_transport_t * entry = NULL;
45 wmem_tree_t * session_tree = NULL;
46 conversation_t * conv = NULL;
48 conv = find_conversation(frame, source_address, &lbtru_null_address, CONVERSATION_UDP, source_port, 0, 0);
49 if (conv != NULL)
51 if (frame != 0)
53 if (conv->setup_frame == 0)
55 conv->setup_frame = frame;
57 if (frame > conv->last_frame)
59 conv->last_frame = frame;
62 session_tree = (wmem_tree_t *) conversation_get_proto_data(conv, proto_lbtru);
63 if (session_tree != NULL)
65 entry = (lbtru_transport_t *) wmem_tree_lookup32(session_tree, session_id);
68 return (entry);
71 lbtru_transport_t * lbtru_transport_add(const address * source_address, uint16_t source_port, uint32_t session_id, uint32_t frame)
73 lbtru_transport_t * entry = NULL;
74 wmem_tree_t * session_tree = NULL;
75 conversation_t * conv = NULL;
77 conv = find_conversation(frame, source_address, &lbtru_null_address, CONVERSATION_UDP, source_port, 0, 0);
78 if (conv == NULL)
80 conv = conversation_new(frame, source_address, &lbtru_null_address, CONVERSATION_UDP, source_port, 0, 0);
82 if (frame != 0)
84 if (conv->setup_frame == 0)
86 conv->setup_frame = frame;
88 if (frame > conv->last_frame)
90 conv->last_frame = frame;
93 session_tree = (wmem_tree_t *) conversation_get_proto_data(conv, proto_lbtru);
94 if (session_tree == NULL)
96 session_tree = wmem_tree_new(wmem_file_scope());
97 conversation_add_proto_data(conv, proto_lbtru, (void *)session_tree);
99 entry = (lbtru_transport_t *) wmem_tree_lookup32(session_tree, session_id);
100 if (entry != NULL)
102 return (entry);
104 entry = wmem_new(wmem_file_scope(), lbtru_transport_t);
105 copy_address_wmem(wmem_file_scope(), &(entry->source_address), source_address);
106 entry->source_port = source_port;
107 entry->session_id = session_id;
108 entry->channel = lbm_channel_assign(LBM_CHANNEL_TRANSPORT_LBTRU);
109 entry->next_client_id = 1;
110 entry->client_list = wmem_list_new(wmem_file_scope());
111 wmem_tree_insert32(session_tree, session_id, (void *) entry);
112 return (entry);
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)
117 lbtru_client_transport_t * entry = NULL;
118 conversation_t * client_conv = NULL;
120 if (transport == NULL)
122 return (NULL);
124 client_conv = find_conversation(frame, &(transport->source_address), receiver_address, CONVERSATION_UDP, transport->source_port, receiver_port, 0);
125 if (client_conv != NULL)
127 wmem_tree_t * session_tree = NULL;
129 session_tree = (wmem_tree_t *) conversation_get_proto_data(client_conv, proto_lbtru);
130 if (session_tree != NULL)
132 entry = (lbtru_client_transport_t *) wmem_tree_lookup32(session_tree, transport->session_id);
135 return (entry);
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)
140 lbtru_client_transport_t * entry = NULL;
141 conversation_t * client_conv = NULL;
142 wmem_tree_t * session_tree = NULL;
144 if (transport == NULL)
146 return (NULL);
148 entry = lbtru_client_transport_find(transport, receiver_address, receiver_port, frame);
149 if (entry != NULL)
151 return (entry);
153 entry = wmem_new0(wmem_file_scope(), lbtru_client_transport_t);
154 copy_address_wmem(wmem_file_scope(), &(entry->receiver_address), receiver_address);
155 entry->receiver_port = receiver_port;
156 entry->transport = transport;
157 entry->id = transport->next_client_id++;
158 entry->frame = wmem_tree_new(wmem_file_scope());
159 entry->last_frame = NULL;
160 entry->last_data_frame = NULL;
161 entry->last_sm_frame = NULL;
162 entry->last_nak_frame = NULL;
163 entry->last_ncf_frame = NULL;
164 entry->last_ack_frame = NULL;
165 entry->last_creq_frame = NULL;
166 entry->last_rst_frame = NULL;
167 entry->data_sqn = wmem_tree_new(wmem_file_scope());
168 entry->sm_sqn = wmem_tree_new(wmem_file_scope());
169 entry->data_high_sqn = 0;
170 entry->sm_high_sqn = 0;
172 /* See if a conversation for this address/port pair exists. */
173 client_conv = find_conversation(frame, &(transport->source_address), receiver_address, CONVERSATION_UDP, transport->source_port, receiver_port, 0);
174 if (client_conv == NULL)
176 client_conv = conversation_new(frame, &(transport->source_address), receiver_address, CONVERSATION_UDP, transport->source_port, receiver_port, 0);
177 session_tree = wmem_tree_new(wmem_file_scope());
178 conversation_add_proto_data(client_conv, proto_lbtru, (void *) session_tree);
180 else
182 session_tree = (wmem_tree_t *) conversation_get_proto_data(client_conv, proto_lbtru);
183 if (session_tree == NULL)
185 session_tree = wmem_tree_new(wmem_file_scope());
186 conversation_add_proto_data(client_conv, proto_lbtru, (void *) session_tree);
189 wmem_tree_insert32(session_tree, transport->session_id, (void *) entry);
191 /* Add this client to the transport. */
192 wmem_list_append(transport->client_list, (void *) entry);
193 return (entry);
196 static lbm_transport_sqn_t * lbtru_client_transport_sqn_find(lbtru_client_transport_t * client, uint8_t type, uint32_t sqn)
198 lbm_transport_sqn_t * sqn_entry = NULL;
200 switch (type)
202 case LBTRU_PACKET_TYPE_DATA:
203 sqn_entry = (lbm_transport_sqn_t *) wmem_tree_lookup32(client->data_sqn, sqn);
204 break;
205 case LBTRU_PACKET_TYPE_SM:
206 sqn_entry = (lbm_transport_sqn_t *) wmem_tree_lookup32(client->sm_sqn, sqn);
207 break;
208 case LBTRU_PACKET_TYPE_NAK:
209 case LBTRU_PACKET_TYPE_NCF:
210 case LBTRU_PACKET_TYPE_ACK:
211 case LBTRU_PACKET_TYPE_CREQ:
212 case LBTRU_PACKET_TYPE_RST:
213 default:
214 sqn_entry = NULL;
215 break;
217 return (sqn_entry);
220 static lbm_transport_sqn_t * lbtru_client_transport_sqn_add(lbtru_client_transport_t * client, lbm_transport_frame_t * frame)
222 wmem_tree_t * sqn_list = NULL;
223 lbm_transport_sqn_t * sqn_entry = NULL;
225 switch (frame->type)
227 case LBTRU_PACKET_TYPE_DATA:
228 sqn_list = client->data_sqn;
229 break;
230 case LBTRU_PACKET_TYPE_SM:
231 sqn_list = client->sm_sqn;
232 break;
233 case LBTRU_PACKET_TYPE_NAK:
234 case LBTRU_PACKET_TYPE_NCF:
235 case LBTRU_PACKET_TYPE_ACK:
236 case LBTRU_PACKET_TYPE_CREQ:
237 case LBTRU_PACKET_TYPE_RST:
238 default:
239 return (NULL);
242 /* Add the sqn. */
243 sqn_entry = lbm_transport_sqn_add(sqn_list, frame);
244 return (sqn_entry);
247 static lbm_transport_frame_t * lbtru_client_transport_frame_find(lbtru_client_transport_t * client, uint32_t frame)
249 return ((lbm_transport_frame_t *) wmem_tree_lookup32(client->frame, frame));
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)
254 lbm_transport_sqn_t * dup_sqn_entry = NULL;
255 lbm_transport_frame_t * frame_entry = NULL;
257 /* Locate the frame. */
258 frame_entry = lbtru_client_transport_frame_find(client, frame);
259 if (frame_entry != NULL)
261 return (frame_entry);
263 frame_entry = lbm_transport_frame_add(client->frame, type, frame, sqn, retransmission);
264 if (client->last_frame != NULL)
266 frame_entry->previous_frame = client->last_frame->frame;
267 client->last_frame->next_frame = frame;
269 client->last_frame = frame_entry;
270 switch (type)
272 case LBTRU_PACKET_TYPE_DATA:
273 if (client->last_data_frame != NULL)
275 frame_entry->previous_type_frame = client->last_data_frame->frame;
276 client->last_data_frame->next_type_frame = frame;
277 /* Ideally, this frame's sqn is 1 more than the highest data sqn seen */
278 if (frame_entry->sqn <= client->data_high_sqn)
280 dup_sqn_entry = lbtru_client_transport_sqn_find(client, type, frame_entry->sqn);
281 if (!frame_entry->retransmission)
283 /* Out of order */
284 if (dup_sqn_entry != NULL)
286 frame_entry->duplicate = true;
288 if (frame_entry->sqn != client->data_high_sqn)
290 frame_entry->ooo_gap = client->data_high_sqn - frame_entry->sqn;
294 else
296 if (!frame_entry->retransmission)
298 if (frame_entry->sqn != (client->data_high_sqn + 1))
300 /* Gap */
301 frame_entry->sqn_gap = frame_entry->sqn - (client->last_data_frame->sqn + 1);
306 if ((frame_entry->sqn > client->data_high_sqn) && !frame_entry->retransmission)
308 client->data_high_sqn = frame_entry->sqn;
310 client->last_data_frame = frame_entry;
311 break;
312 case LBTRU_PACKET_TYPE_SM:
313 if (client->last_sm_frame != NULL)
315 frame_entry->previous_type_frame = client->last_sm_frame->frame;
316 client->last_sm_frame->next_type_frame = frame;
317 /* Ideally, this frame's sqn is 1 more than the highest SM sqn seen */
318 if (frame_entry->sqn <= client->sm_high_sqn)
320 /* Out of order */
321 dup_sqn_entry = lbtru_client_transport_sqn_find(client, type, frame_entry->sqn);
322 if (dup_sqn_entry != NULL)
324 frame_entry->duplicate = true;
326 if (frame_entry->sqn != client->sm_high_sqn)
328 frame_entry->ooo_gap = client->sm_high_sqn - frame_entry->sqn;
331 else
333 if (frame_entry->sqn != (client->sm_high_sqn + 1))
335 /* Gap */
336 frame_entry->sqn_gap = frame_entry->sqn - (client->sm_high_sqn + 1);
340 if (frame_entry->sqn > client->sm_high_sqn)
342 client->sm_high_sqn = frame_entry->sqn;
344 client->last_sm_frame = frame_entry;
345 break;
346 case LBTRU_PACKET_TYPE_NAK:
347 if (client->last_nak_frame != NULL)
349 frame_entry->previous_type_frame = client->last_nak_frame->frame;
350 client->last_nak_frame->next_type_frame = frame;
352 client->last_nak_frame = frame_entry;
353 break;
354 case LBTRU_PACKET_TYPE_NCF:
355 if (client->last_ncf_frame != NULL)
357 frame_entry->previous_type_frame = client->last_ncf_frame->frame;
358 client->last_ncf_frame->next_type_frame = frame;
360 client->last_ncf_frame = frame_entry;
361 break;
362 case LBTRU_PACKET_TYPE_ACK:
363 if (client->last_ack_frame != NULL)
365 frame_entry->previous_type_frame = client->last_ack_frame->frame;
366 client->last_ack_frame->next_type_frame = frame;
368 client->last_ack_frame = frame_entry;
369 break;
370 case LBTRU_PACKET_TYPE_CREQ:
371 if (client->last_creq_frame != NULL)
373 frame_entry->previous_type_frame = client->last_creq_frame->frame;
374 client->last_creq_frame->next_type_frame = frame;
376 client->last_creq_frame = frame_entry;
377 break;
378 case LBTRU_PACKET_TYPE_RST:
379 if (client->last_rst_frame != NULL)
381 frame_entry->previous_type_frame = client->last_rst_frame->frame;
382 client->last_rst_frame->next_type_frame = frame;
384 client->last_rst_frame = frame_entry;
385 break;
388 /* Add the sqn. */
389 (void)lbtru_client_transport_sqn_add(client, frame_entry);
390 return (frame_entry);
393 static char * lbtru_transport_source_string_format(wmem_allocator_t *scope, const address * source_address, uint16_t source_port, uint32_t session_id)
395 char * bufptr = NULL;
397 if (session_id == 0)
399 bufptr = wmem_strdup_printf(scope, "LBT-RU:%s:%" PRIu16, address_to_str(scope, source_address), source_port);
401 else
403 bufptr = wmem_strdup_printf(scope, "LBT-RU:%s:%" PRIu16 ":%08x", address_to_str(scope, source_address), source_port, session_id);
405 return (bufptr);
408 char * lbtru_transport_source_string(const address * source_address, uint16_t source_port, uint32_t session_id)
410 /* Returns a file-scoped string. */
411 return lbtru_transport_source_string_format(wmem_file_scope(), source_address, source_port, session_id);
414 static char * lbtru_transport_source_string_transport(wmem_allocator_t *scope, lbtru_transport_t * transport)
416 return lbtru_transport_source_string_format(scope, &(transport->source_address), transport->source_port, transport->session_id);
419 /*----------------------------------------------------------------------------*/
420 /* Packet layouts. */
421 /*----------------------------------------------------------------------------*/
423 /* LBT-RU main header */
424 typedef struct
426 lbm_uint8_t ver_type;
427 lbm_uint8_t next_hdr;
428 lbm_uint16_t flags_or_res;
429 } lbtru_hdr_t;
430 #define O_LBTRU_HDR_T_VER_TYPE OFFSETOF(lbtru_hdr_t, ver_type)
431 #define L_LBTRU_HDR_T_VER_TYPE SIZEOF(lbtru_hdr_t, ver_type)
432 #define O_LBTRU_HDR_T_NEXT_HDR OFFSETOF(lbtru_hdr_t, next_hdr)
433 #define L_LBTRU_HDR_T_NEXT_HDR SIZEOF(lbtru_hdr_t, next_hdr)
434 #define O_LBTRU_HDR_T_FLAGS_OR_RES OFFSETOF(lbtru_hdr_t, flags_or_res)
435 #define L_LBTRU_HDR_T_FLAGS_OR_RES SIZEOF(lbtru_hdr_t, flags_or_res)
436 #define L_LBTRU_HDR_T (int) sizeof(lbtru_hdr_t)
438 #define LBTRU_VERSION 0x00
439 #define LBTRU_HDR_VER(x) (x >> 4)
440 #define LBTRU_HDR_TYPE(x) (x & 0x0F)
441 #define LBTRU_HDR_VER_VER_MASK 0xF0
442 #define LBTRU_HDR_VER_TYPE_MASK 0x0F
444 #define LBTRU_RETRANSMISSION_FLAG 0x4000
446 /* LBT-RU data header */
447 typedef struct
449 lbm_uint32_t sqn;
450 lbm_uint32_t trail_sqn;
451 } lbtru_data_hdr_t;
452 #define O_LBTRU_DATA_HDR_T_SQN OFFSETOF(lbtru_data_hdr_t, sqn)
453 #define L_LBTRU_DATA_HDR_T_SQN SIZEOF(lbtru_data_hdr_t, sqn)
454 #define O_LBTRU_DATA_HDR_T_TRAIL_SQN OFFSETOF(lbtru_data_hdr_t, trail_sqn)
455 #define L_LBTRU_DATA_HDR_T_TRAIL_SQN SIZEOF(lbtru_data_hdr_t, trail_sqn)
456 #define L_LBTRU_DATA_HDR_T (int) (sizeof(lbtru_data_hdr_t))
458 /* LBT-RU Session Message header */
459 typedef struct
461 lbm_uint32_t sm_sqn;
462 lbm_uint32_t lead_sqn;
463 lbm_uint32_t trail_sqn;
464 } lbtru_sm_hdr_t;
465 #define O_LBTRU_SM_HDR_T_SM_SQN OFFSETOF(lbtru_sm_hdr_t, sm_sqn)
466 #define L_LBTRU_SM_HDR_T_SM_SQN SIZEOF(lbtru_sm_hdr_t, sm_sqn)
467 #define O_LBTRU_SM_HDR_T_LEAD_SQN OFFSETOF(lbtru_sm_hdr_t, lead_sqn)
468 #define L_LBTRU_SM_HDR_T_LEAD_SQN SIZEOF(lbtru_sm_hdr_t, lead_sqn)
469 #define O_LBTRU_SM_HDR_T_TRAIL_SQN OFFSETOF(lbtru_sm_hdr_t, trail_sqn)
470 #define L_LBTRU_SM_HDR_T_TRAIL_SQN SIZEOF(lbtru_sm_hdr_t, trail_sqn)
471 #define L_LBTRU_SM_HDR_T (int) (sizeof(lbtru_sm_hdr_t))
473 #define LBTRU_SM_SYN_FLAG 0x8000
475 /* LBT-RU NAK header */
476 typedef struct
478 lbm_uint16_t num_naks;
479 lbm_uint16_t format;
480 } lbtru_nak_hdr_t;
481 #define O_LBTRU_NAK_HDR_T_NUM_NAKS OFFSETOF(lbtru_nak_hdr_t, num_naks)
482 #define L_LBTRU_NAK_HDR_T_NUM_NAKS SIZEOF(lbtru_nak_hdr_t, num_naks)
483 #define O_LBTRU_NAK_HDR_T_FORMAT OFFSETOF(lbtru_nak_hdr_t, format)
484 #define L_LBTRU_NAK_HDR_T_FORMAT SIZEOF(lbtru_nak_hdr_t, format)
485 #define L_LBTRU_NAK_HDR_T (int) (sizeof(lbtru_nak_hdr_t))
487 #define LBTRU_NAK_SELECTIVE_FORMAT 0x0
488 #define LBTRU_NAK_HDR_FORMAT_MASK 0x000F
489 #define LBTRU_NAK_HDR_FORMAT(x) (x & 0xF)
491 /* LBT-RU NAK Confirmation header */
492 typedef struct
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 #define O_LBTRU_NCF_HDR_T_TRAIL_SQN OFFSETOF(lbtru_ncf_hdr_t, trail_sqn)
500 #define L_LBTRU_NCF_HDR_T_TRAIL_SQN SIZEOF(lbtru_ncf_hdr_t, trail_sqn)
501 #define O_LBTRU_NCF_HDR_T_NUM_NCFS OFFSETOF(lbtru_ncf_hdr_t, num_ncfs)
502 #define L_LBTRU_NCF_HDR_T_NUM_NCFS SIZEOF(lbtru_ncf_hdr_t, num_ncfs)
503 #define O_LBTRU_NCF_HDR_T_RESERVED OFFSETOF(lbtru_ncf_hdr_t, reserved)
504 #define L_LBTRU_NCF_HDR_T_RESERVED SIZEOF(lbtru_ncf_hdr_t, reserved)
505 #define O_LBTRU_NCF_HDR_T_REASON_FORMAT OFFSETOF(lbtru_ncf_hdr_t, reason_format)
506 #define L_LBTRU_NCF_HDR_T_REASON_FORMAT SIZEOF(lbtru_ncf_hdr_t, reason_format)
507 #define L_LBTRU_NCF_HDR_T (int) (sizeof(lbtru_ncf_hdr_t))
509 #define LBTRU_NCF_SELECTIVE_FORMAT 0x0
510 #define LBTRU_NCF_HDR_REASON(x) ((x & 0xF0) >> 4)
511 #define LBTRU_NCF_HDR_FORMAT(x) (x & 0xF)
512 #define LBTRU_NCF_HDR_REASON_MASK 0xF0
513 #define LBTRU_NCF_HDR_FORMAT_MASK 0x0F
515 /* LBT-RU ACK header */
516 typedef struct
518 lbm_uint32_t ack_sqn;
519 } lbtru_ack_hdr_t;
520 #define O_LBTRU_ACK_HDR_T_ACK_SQN OFFSETOF(lbtru_ack_hdr_t, ack_sqn)
521 #define L_LBTRU_ACK_HDR_T_ACK_SQN SIZEOF(lbtru_ack_hdr_t, ack_sqn)
522 #define L_LBTRU_ACK_HDR_T (int) (sizeof(lbtru_ack_hdr_t))
524 /* LBT-RU basic option header */
525 typedef struct
527 lbm_uint8_t next_hdr;
528 lbm_uint8_t hdr_len;
529 lbm_uint16_t res;
530 } lbtru_basic_opt_t;
531 #define O_LBTRU_BASIC_OPT_T_NEXT_HDR OFFSETOF(lbtru_basic_opt_t, next_hdr)
532 #define L_LBTRU_BASIC_OPT_T_NEXT_HDR SIZEOF(lbtru_basic_opt_t, next_hdr)
533 #define O_LBTRU_BASIC_OPT_T_HDR_LEN OFFSETOF(lbtru_basic_opt_t, hdr_len)
534 #define L_LBTRU_BASIC_OPT_T_HDR_LEN SIZEOF(lbtru_basic_opt_t, hdr_len)
535 #define O_LBTRU_BASIC_OPT_T_RES OFFSETOF(lbtru_basic_opt_t, res)
536 #define L_LBTRU_BASIC_OPT_T_RES SIZEOF(lbtru_basic_opt_t, res)
537 #define L_LBTRU_BASIC_OPT_T (int) (sizeof(lbtru_basic_opt_t))
539 /* LBT-RU Session ID option header */
540 typedef struct
542 lbm_uint32_t session_id;
543 } lbtru_sid_opt_t;
544 #define O_LBTRU_SID_OPT_T_SESSION_ID OFFSETOF(lbtru_sid_opt_t, session_id)
545 #define L_LBTRU_SID_OPT_T_SESSION_ID SIZEOF(lbtru_sid_opt_t, session_id)
546 #define L_LBTRU_SID_OPT_T (int) (sizeof(lbtru_sid_opt_t))
548 /* LBT-RU Client ID option header */
549 typedef struct
551 lbm_uint32_t client_sid;
552 } lbtru_cid_opt_t;
553 #define O_LBTRU_CID_OPT_T_CLIENT_SID OFFSETOF(lbtru_cid_opt_t, client_sid)
554 #define L_LBTRU_CID_OPT_T_CLIENT_SID SIZEOF(lbtru_cid_opt_t, client_sid)
555 #define L_LBTRU_CID_OPT_T (int) (sizeof(lbtru_cid_opt_t))
557 #define LBTRU_OPT_IGNORE 0x8000
559 #define LBTRU_NHDR_DATA 0x00
560 #define LBTRU_NHDR_SID 0x01
561 #define LBTRU_NHDR_CID 0x02
563 /*----------------------------------------------------------------------------*/
564 /* Value translation tables. */
565 /*----------------------------------------------------------------------------*/
567 static const value_string lbtru_packet_type[] =
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 }
579 static const value_string lbtru_nak_format[] =
581 { LBTRU_NAK_SELECTIVE_FORMAT, "Selective" },
582 { 0x0, NULL }
585 static const value_string lbtru_ncf_format[] =
587 { LBTRU_NCF_SELECTIVE_FORMAT, "Selective" },
588 { 0x0, NULL }
591 static const value_string lbtru_ncf_reason[] =
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 }
600 static const value_string lbtru_creq_request[] =
602 { LBTRU_CREQ_REQUEST_SYN, "SYN" },
603 { 0x0, NULL }
606 static const value_string lbtru_rst_reason[] =
608 { LBTRU_RST_REASON_DEFAULT, "Default" },
609 { 0x0, NULL }
612 static const value_string lbtru_next_header[] =
614 { LBTRU_NHDR_DATA, "DATA" },
615 { LBTRU_NHDR_SID, "SID" },
616 { LBTRU_NHDR_CID, "CID" },
617 { 0x0, NULL }
620 /*----------------------------------------------------------------------------*/
621 /* Preferences. */
622 /*----------------------------------------------------------------------------*/
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
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;
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;
650 /*----------------------------------------------------------------------------*/
651 /* Tag management. */
652 /*----------------------------------------------------------------------------*/
653 typedef struct
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;
662 static lbtru_tag_entry_t * lbtru_tag_entry;
663 static unsigned lbtru_tag_count;
665 UAT_CSTRING_CB_DEF(lbtru_tag, name, lbtru_tag_entry_t)
666 UAT_DEC_CB_DEF(lbtru_tag, source_port_low, lbtru_tag_entry_t)
667 UAT_DEC_CB_DEF(lbtru_tag, source_port_high, lbtru_tag_entry_t)
668 UAT_DEC_CB_DEF(lbtru_tag, receiver_port_low, lbtru_tag_entry_t)
669 UAT_DEC_CB_DEF(lbtru_tag, receiver_port_high, lbtru_tag_entry_t)
670 static uat_field_t lbtru_tag_array[] =
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
680 /*----------------------------------------------------------------------------*/
681 /* UAT callback functions. */
682 /*----------------------------------------------------------------------------*/
683 static bool lbtru_tag_update_cb(void * record, char * * error_string)
685 lbtru_tag_entry_t * tag = (lbtru_tag_entry_t *)record;
687 if (tag->name == NULL)
689 *error_string = g_strdup("Tag name can't be empty");
690 return false;
692 else
694 g_strstrip(tag->name);
695 if (tag->name[0] == 0)
697 *error_string = g_strdup("Tag name can't be empty");
698 return false;
701 return true;
704 static void * lbtru_tag_copy_cb(void * destination, const void * source, size_t length _U_)
706 const lbtru_tag_entry_t * src = (const lbtru_tag_entry_t *)source;
707 lbtru_tag_entry_t * dest = (lbtru_tag_entry_t *)destination;
709 dest->name = g_strdup(src->name);
710 dest->source_port_low = src->source_port_low;
711 dest->source_port_high = src->source_port_high;
712 dest->receiver_port_low = src->receiver_port_low;
713 dest->receiver_port_high = src->receiver_port_high;
714 return (dest);
717 static void lbtru_tag_free_cb(void * record)
719 lbtru_tag_entry_t * tag = (lbtru_tag_entry_t *)record;
721 if (tag->name != NULL)
723 g_free(tag->name);
724 tag->name = NULL;
728 static char * lbtru_tag_find(packet_info * pinfo)
730 unsigned idx;
731 lbtru_tag_entry_t * tag = NULL;
733 if (!lbtru_use_tag)
735 return (NULL);
738 for (idx = 0; idx < lbtru_tag_count; ++idx)
740 tag = &(lbtru_tag_entry[idx]);
741 if (((pinfo->destport >= tag->source_port_low)
742 && (pinfo->destport <= tag->source_port_high)
743 && (pinfo->srcport >= tag->receiver_port_low)
744 && (pinfo->srcport <= tag->receiver_port_high))
745 || ((pinfo->destport >= tag->receiver_port_low)
746 && (pinfo->destport <= tag->receiver_port_high)
747 && (pinfo->srcport >= tag->source_port_low)
748 && (pinfo->srcport <= tag->source_port_high)))
750 /* One of ours. */
751 return tag->name;
754 return (NULL);
757 /*----------------------------------------------------------------------------*/
758 /* Handles of all types. */
759 /*----------------------------------------------------------------------------*/
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;
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;
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;
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)
884 tvbuff_t * next_tvb;
886 next_tvb = tvb_new_subset_remaining(tvb, offset);
887 return (lbmc_dissect_lbmc_packet(next_tvb, 0, pinfo, tree, tag_name, channel));
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)
895 proto_tree * ack_tree = NULL;
896 proto_item * ack_item = NULL;
897 proto_item * ack = NULL;
899 ack_item = proto_tree_add_item(tree, hf_lbtru_ack, tvb, offset, L_LBTRU_ACK_HDR_T, ENC_NA);
900 ack_tree = proto_item_add_subtree(ack_item, ett_lbtru_ack);
901 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 expert_add_info(pinfo, ack, &ei_lbtru_analysis_ack);
903 tap_info->sqn = tvb_get_ntohl(tvb, offset + O_LBTRU_ACK_HDR_T_ACK_SQN);
904 return (L_LBTRU_ACK_HDR_T);
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)
912 proto_tree * ncf_tree = NULL;
913 proto_item * ncf_item = NULL;
914 lbm_uint32_t ncf;
915 int idx = 0;
916 int len = 0;
918 ncf_item = proto_tree_add_item(tree, hf_lbtru_ncf_list, tvb, offset, -1, ENC_NA);
919 ncf_tree = proto_item_add_subtree(ncf_item, ett_lbtru_ncf_list);
921 for (idx = 0; idx < ncf_count; idx++)
923 proto_item * sep_ncf_item = NULL;
925 ncf = tvb_get_ntohl(tvb, offset + len);
926 sep_ncf_item = proto_tree_add_item(ncf_tree, hf_lbtru_ncf_list_ncf, tvb, offset + len, sizeof(lbm_uint32_t), ENC_BIG_ENDIAN);
927 if (lbtru_expert_separate_ncfs)
929 expert_add_info_format(pinfo, sep_ncf_item, &ei_lbtru_analysis_ncf_ncf, "NCF 0x%08x %s", ncf, val_to_str(reason, lbtru_ncf_reason, "Unknown (0x%02x)"));
931 tap_info->sqns[idx] = ncf;
932 len += (int)sizeof(lbm_uint32_t);
934 proto_item_set_len(ncf_item, len);
935 return (len);
938 static int dissect_lbtru_ncf(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, lbm_lbtru_tap_info_t * tap_info)
940 int len_dissected;
941 uint8_t reason_format;
942 proto_tree * ncf_tree = NULL;
943 proto_item * ncf_item = NULL;
944 uint16_t num_ncfs = 0;
946 ncf_item = proto_tree_add_item(tree, hf_lbtru_ncf, tvb, offset, -1, ENC_NA);
947 ncf_tree = proto_item_add_subtree(ncf_item, ett_lbtru_ncf);
948 reason_format = tvb_get_uint8(tvb, offset + O_LBTRU_NCF_HDR_T_REASON_FORMAT);
949 num_ncfs = tvb_get_ntohs(tvb, offset + O_LBTRU_NCF_HDR_T_NUM_NCFS);
950 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);
951 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);
952 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);
953 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);
954 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);
955 len_dissected = L_LBTRU_NCF_HDR_T;
956 if (!lbtru_expert_separate_ncfs)
958 expert_add_info_format(pinfo, ncf_item, &ei_lbtru_analysis_ncf, "NCF %s", val_to_str(LBTRU_NCF_HDR_REASON(reason_format), lbtru_ncf_reason, "Unknown (0x%02x)"));
960 tap_info->ncf_reason = LBTRU_NCF_HDR_REASON(reason_format);
961 tap_info->num_sqns = num_ncfs;
962 tap_info->sqns = wmem_alloc_array(pinfo->pool, uint32_t, num_ncfs);
963 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);
964 proto_item_set_len(ncf_item, len_dissected);
965 return (len_dissected);
968 /*----------------------------------------------------------------------------*/
969 /* LBT-RU NAK packet dissection functions. */
970 /*----------------------------------------------------------------------------*/
971 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)
973 proto_tree * nak_tree = NULL;
974 proto_item * nak_item = NULL;
975 int idx = 0;
976 int len = 0;
978 nak_item = proto_tree_add_item(tree, hf_lbtru_nak_list, tvb, offset, -1, ENC_NA);
979 nak_tree = proto_item_add_subtree(nak_item, ett_lbtru_nak_list);
981 for (idx = 0; idx < nak_count; idx++)
983 proto_item * sep_nak_item = NULL;
984 lbm_uint32_t nak;
986 nak = tvb_get_ntohl(tvb, offset + len);
987 sep_nak_item = proto_tree_add_item(nak_tree, hf_lbtru_nak_list_nak, tvb, offset + len, sizeof(lbm_uint32_t), ENC_BIG_ENDIAN);
988 if (lbtru_expert_separate_naks)
990 expert_add_info_format(pinfo, sep_nak_item, &ei_lbtru_analysis_nak_nak, "NAK 0x%08x", nak);
992 tap_info->sqns[idx] = nak;
993 len += (int)sizeof(lbm_uint32_t);
995 proto_item_set_len(nak_item, len);
996 return (len);
999 static int dissect_lbtru_nak(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, lbm_lbtru_tap_info_t * tap_info)
1001 int len_dissected;
1002 proto_tree * nak_tree = NULL;
1003 proto_item * nak_item = NULL;
1004 uint16_t num_naks = 0;
1006 nak_item = proto_tree_add_item(tree, hf_lbtru_nak, tvb, offset, -1, ENC_NA);
1007 nak_tree = proto_item_add_subtree(nak_item, ett_lbtru_nak);
1008 num_naks = tvb_get_ntohs(tvb, offset + O_LBTRU_NAK_HDR_T_NUM_NAKS);
1009 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);
1010 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);
1011 len_dissected = L_LBTRU_NAK_HDR_T;
1012 if (!lbtru_expert_separate_naks)
1014 expert_add_info(pinfo, nak_item, &ei_lbtru_analysis_nak);
1016 tap_info->num_sqns = num_naks;
1017 tap_info->sqns = wmem_alloc_array(pinfo->pool, uint32_t, num_naks);
1018 len_dissected += dissect_lbtru_nak_list(tvb, offset + L_LBTRU_NAK_HDR_T, pinfo, nak_tree, num_naks, tap_info);
1019 proto_item_set_len(nak_item, len_dissected);
1020 return (len_dissected);
1023 /*----------------------------------------------------------------------------*/
1024 /* LBT-RU session message packet dissection function. */
1025 /*----------------------------------------------------------------------------*/
1026 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)
1028 proto_tree * sm_tree = NULL;
1029 proto_item * sm_item = NULL;
1030 proto_item * sm_sqn = NULL;
1032 sm_item = proto_tree_add_item(tree, hf_lbtru_sm, tvb, offset, L_LBTRU_SM_HDR_T, ENC_NA);
1033 sm_tree = proto_item_add_subtree(sm_item, ett_lbtru_sm);
1034 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);
1035 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);
1036 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);
1037 if (syn)
1039 expert_add_info(pinfo, sm_sqn, &ei_lbtru_analysis_sm_syn);
1041 else
1043 expert_add_info(pinfo, sm_sqn, &ei_lbtru_analysis_sm);
1045 tap_info->sqn = tvb_get_ntohl(tvb, offset + O_LBTRU_SM_HDR_T_SM_SQN);
1046 return (L_LBTRU_SM_HDR_T);
1049 /*----------------------------------------------------------------------------*/
1050 /* LBT-RU data packet dissection functions. */
1051 /*----------------------------------------------------------------------------*/
1052 static int dissect_lbtru_data(tvbuff_t * tvb, int offset, packet_info * pinfo _U_, proto_tree * tree, lbm_lbtru_tap_info_t * tap_info)
1054 proto_tree * data_tree = NULL;
1055 proto_item * data_item = NULL;
1057 data_item = proto_tree_add_item(tree, hf_lbtru_data, tvb, offset, L_LBTRU_DATA_HDR_T, ENC_NA);
1058 data_tree = proto_item_add_subtree(data_item, ett_lbtru_data);
1059 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);
1060 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);
1061 tap_info->sqn = tvb_get_ntohl(tvb, offset + O_LBTRU_DATA_HDR_T_SQN);
1062 return (L_LBTRU_DATA_HDR_T);
1065 /*----------------------------------------------------------------------------*/
1066 /* LBT-RU packet dissector. */
1067 /*----------------------------------------------------------------------------*/
1068 typedef struct
1070 proto_tree * tree;
1071 tvbuff_t * tvb;
1072 uint32_t current_frame;
1073 } lbtru_sqn_frame_list_callback_data_t;
1075 static bool dissect_lbtru_sqn_frame_list_callback(const void *key _U_, void * frame, void * user_data)
1077 lbtru_sqn_frame_list_callback_data_t * cb_data = (lbtru_sqn_frame_list_callback_data_t *) user_data;
1078 proto_item * transport_item = NULL;
1079 lbm_transport_sqn_frame_t * sqn_frame = (lbm_transport_sqn_frame_t *) frame;
1081 if (sqn_frame->frame != cb_data->current_frame)
1083 if (sqn_frame->retransmission)
1085 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);
1087 else
1089 transport_item = proto_tree_add_uint(cb_data->tree, hf_lbtru_analysis_sqn_frame, cb_data->tvb, 0, 0, sqn_frame->frame);
1091 proto_item_set_generated(transport_item);
1093 return false;
1096 static int dissect_lbtru(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * user_data _U_)
1098 proto_tree * lbtru_tree = NULL;
1099 proto_item * lbtru_item = NULL;
1100 static int * const flags_data[] =
1102 &hf_lbtru_hdr_flags_rx,
1103 NULL
1105 static int * const flags_sm[] =
1107 &hf_lbtru_hdr_flags_syn,
1108 NULL
1110 int ofs = 0;
1111 uint32_t session_id = 0;
1112 char * tag_name = NULL;
1113 int dissected_len;
1114 int total_dissected_len = 0;
1115 proto_tree * header_tree = NULL;
1116 proto_item * header_item = NULL;
1117 proto_tree * transport_tree = NULL;
1118 proto_item * transport_item = NULL;
1119 bool from_source = true;
1120 uint8_t packet_type = 0;
1121 address source_address;
1122 address receiver_address;
1123 uint16_t source_port = 0;
1124 uint16_t receiver_port = 0;
1125 lbtru_transport_t * transport = NULL;
1126 lbtru_client_transport_t * client = NULL;
1127 uint64_t channel = LBM_CHANNEL_NO_CHANNEL;
1128 proto_tree * channel_tree = NULL;
1129 proto_item * channel_item = NULL;
1130 uint8_t ver_type = 0;
1131 uint8_t next_hdr = 0;
1132 uint32_t packet_sqn = 0;
1133 uint16_t flags_or_res = 0;
1134 uint16_t num_naks = 0;
1135 uint16_t num_ncfs = 0;
1136 bool retransmission = false;
1137 proto_item * fld_item = NULL;
1138 proto_item * ei_item = NULL;
1139 proto_item * type_item = NULL;
1140 proto_item * next_hdr_item = NULL;
1141 lbm_lbtru_tap_info_t * tapinfo = NULL;
1143 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LBT-RU");
1144 if (lbtru_use_tag)
1146 tag_name = lbtru_tag_find(pinfo);
1148 col_clear(pinfo->cinfo, COL_INFO);
1149 if (tag_name != NULL)
1151 col_add_fstr(pinfo->cinfo, COL_INFO, "[Tag: %s]", tag_name);
1153 col_set_fence(pinfo->cinfo, COL_INFO);
1155 ver_type = tvb_get_uint8(tvb, O_LBTRU_HDR_T_VER_TYPE);
1156 next_hdr = tvb_get_uint8(tvb, O_LBTRU_HDR_T_NEXT_HDR);
1157 flags_or_res = tvb_get_ntohs(tvb, O_LBTRU_HDR_T_FLAGS_OR_RES);
1158 packet_type = LBTRU_HDR_TYPE(ver_type);
1159 if (tag_name != NULL)
1161 lbtru_item = proto_tree_add_protocol_format(tree, proto_lbtru, tvb, ofs, -1, "LBT-RU Protocol (Tag: %s): Version %u, Type %s", tag_name,
1162 LBTRU_HDR_VER(ver_type), val_to_str(LBTRU_HDR_TYPE(ver_type), lbtru_packet_type, "Unknown (0x%02x)"));
1164 else
1166 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),
1167 val_to_str(LBTRU_HDR_TYPE(ver_type), lbtru_packet_type, "Unknown (0x%02x)"));
1169 lbtru_tree = proto_item_add_subtree(lbtru_item, ett_lbtru);
1170 if (tag_name != NULL)
1172 proto_item * item = NULL;
1173 item = proto_tree_add_string(lbtru_tree, hf_lbtru_tag, tvb, 0, 0, tag_name);
1174 proto_item_set_generated(item);
1176 channel_item = proto_tree_add_item(lbtru_tree, hf_lbtru_channel, tvb, 0, 0, ENC_NA);
1177 proto_item_set_generated(channel_item);
1178 channel_tree = proto_item_add_subtree(channel_item, ett_lbtru_channel);
1180 tapinfo = wmem_new0(pinfo->pool, lbm_lbtru_tap_info_t);
1181 tapinfo->type = packet_type;
1183 header_item = proto_tree_add_item(lbtru_tree, hf_lbtru_hdr, tvb, 0, -1, ENC_NA);
1184 header_tree = proto_item_add_subtree(header_item, ett_lbtru_hdr);
1185 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);
1186 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);
1187 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);
1188 total_dissected_len = L_LBTRU_HDR_T_VER_TYPE + L_LBTRU_HDR_T_NEXT_HDR;
1189 ofs = L_LBTRU_HDR_T_VER_TYPE + L_LBTRU_HDR_T_NEXT_HDR;
1191 switch (packet_type)
1193 case LBTRU_PACKET_TYPE_DATA:
1194 packet_sqn = tvb_get_ntohl(tvb, L_LBTRU_HDR_T + O_LBTRU_DATA_HDR_T_SQN);
1195 if ((flags_or_res & LBTRU_RETRANSMISSION_FLAG) != 0)
1197 retransmission = true;
1198 tapinfo->retransmission = true;
1200 if (retransmission)
1202 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "DATA(RX) sqn 0x%x", packet_sqn);
1204 else
1206 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "DATA sqn 0x%x", packet_sqn);
1208 from_source = true;
1209 break;
1210 case LBTRU_PACKET_TYPE_SM:
1211 packet_sqn = tvb_get_ntohl(tvb, L_LBTRU_HDR_T + O_LBTRU_SM_HDR_T_SM_SQN);
1212 if ((flags_or_res & LBTRU_SM_SYN_FLAG) != 0)
1214 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SM sqn 0x%x SYN", packet_sqn);
1216 else
1218 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SM sqn 0x%x", packet_sqn);
1220 from_source = true;
1221 break;
1222 case LBTRU_PACKET_TYPE_NAK:
1223 num_naks = tvb_get_ntohs(tvb, L_LBTRU_HDR_T + O_LBTRU_NAK_HDR_T_NUM_NAKS);
1224 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "NAK %" PRIu16 " naks", num_naks);
1225 from_source = false;
1226 break;
1227 case LBTRU_PACKET_TYPE_NCF:
1228 num_ncfs = tvb_get_ntohs(tvb, L_LBTRU_HDR_T + O_LBTRU_NCF_HDR_T_NUM_NCFS);
1229 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "NCF %" PRIu16 " ncfs", num_ncfs);
1230 from_source = true;
1231 break;
1232 case LBTRU_PACKET_TYPE_ACK:
1233 packet_sqn = tvb_get_ntohl(tvb, L_LBTRU_HDR_T + O_LBTRU_ACK_HDR_T_ACK_SQN);
1234 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "ACK sqn 0x%x", packet_sqn);
1235 from_source = false;
1236 break;
1237 case LBTRU_PACKET_TYPE_CREQ:
1238 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "CREQ %s", val_to_str(flags_or_res, lbtru_creq_request, "Unknown (0x%02x)"));
1239 from_source = false;
1240 break;
1241 case LBTRU_PACKET_TYPE_RST:
1242 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "RST %s", val_to_str(flags_or_res, lbtru_rst_reason, "Unknown (0x%02x)"));
1243 from_source = true;
1244 break;
1245 default:
1246 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "Unknown (0x%02x)", LBTRU_HDR_TYPE(ver_type));
1247 expert_add_info_format(pinfo, type_item, &ei_lbtru_analysis_unknown_type, "Unrecognized type 0x%02x", LBTRU_HDR_TYPE(ver_type));
1248 return (total_dissected_len);
1251 /* Handle the flags_or_res field. */
1252 switch (packet_type)
1254 case LBTRU_PACKET_TYPE_DATA:
1255 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);
1256 total_dissected_len += L_LBTRU_HDR_T_FLAGS_OR_RES;
1257 ofs += L_LBTRU_HDR_T_FLAGS_OR_RES;
1258 break;
1259 case LBTRU_PACKET_TYPE_NAK:
1260 case LBTRU_PACKET_TYPE_NCF:
1261 case LBTRU_PACKET_TYPE_ACK:
1262 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);
1263 total_dissected_len += L_LBTRU_HDR_T_FLAGS_OR_RES;
1264 ofs += L_LBTRU_HDR_T_FLAGS_OR_RES;
1265 break;
1266 case LBTRU_PACKET_TYPE_SM:
1267 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);
1268 total_dissected_len += L_LBTRU_HDR_T_FLAGS_OR_RES;
1269 ofs += L_LBTRU_HDR_T_FLAGS_OR_RES;
1270 break;
1271 case LBTRU_PACKET_TYPE_CREQ:
1272 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);
1273 expert_add_info_format(pinfo, ei_item, &ei_lbtru_analysis_creq, "CREQ %s", val_to_str(flags_or_res, lbtru_creq_request, "Unknown (0x%04x)"));
1274 total_dissected_len += L_LBTRU_HDR_T_FLAGS_OR_RES;
1275 ofs += L_LBTRU_HDR_T_FLAGS_OR_RES;
1276 break;
1277 case LBTRU_PACKET_TYPE_RST:
1278 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);
1279 expert_add_info_format(pinfo, ei_item, &ei_lbtru_analysis_rst, "RST %s", val_to_str(flags_or_res, lbtru_rst_reason, "Unknown (0x%04x)"));
1280 break;
1281 default:
1282 break;
1285 /* Handle the packet-specific data */
1286 switch (packet_type)
1288 case LBTRU_PACKET_TYPE_DATA:
1289 dissected_len = dissect_lbtru_data(tvb, L_LBTRU_HDR_T, pinfo, lbtru_tree, tapinfo);
1290 break;
1291 case LBTRU_PACKET_TYPE_SM:
1292 dissected_len = dissect_lbtru_sm(tvb, L_LBTRU_HDR_T, pinfo, lbtru_tree, (flags_or_res & LBTRU_SM_SYN_FLAG), tapinfo);
1293 break;
1294 case LBTRU_PACKET_TYPE_NAK:
1295 dissected_len = dissect_lbtru_nak(tvb, ofs, pinfo, lbtru_tree, tapinfo);
1296 break;
1297 case LBTRU_PACKET_TYPE_NCF:
1298 dissected_len = dissect_lbtru_ncf(tvb, ofs, pinfo, lbtru_tree, tapinfo);
1299 break;
1300 case LBTRU_PACKET_TYPE_ACK:
1301 dissected_len = dissect_lbtru_ack(tvb, ofs, pinfo, lbtru_tree, tapinfo);
1302 break;
1303 case LBTRU_PACKET_TYPE_CREQ:
1304 dissected_len = 0;
1305 tapinfo->creq_type = flags_or_res;
1306 break;
1307 case LBTRU_PACKET_TYPE_RST:
1308 dissected_len = 0;
1309 tapinfo->rst_type = flags_or_res;
1310 break;
1311 default:
1312 dissected_len = 0;
1313 break;
1315 total_dissected_len += dissected_len;
1316 ofs += dissected_len;
1317 /* If we're doing sequence analysis, the tree goes here. */
1318 if (lbtru_sequence_analysis)
1320 transport_item = proto_tree_add_item(lbtru_tree, hf_lbtru_analysis, tvb, 0, 0, ENC_NA);
1321 proto_item_set_generated(transport_item);
1322 transport_tree = proto_item_add_subtree(transport_item, ett_lbtru_transport);
1324 while (next_hdr != LBTRU_NHDR_DATA)
1326 proto_item * hdr_length_item;
1327 proto_tree * opt_tree = NULL;
1328 static int * const sid_flags[] =
1330 &hf_lbtru_opt_sid_flags_ignore,
1331 NULL
1333 static int * const cid_flags[] =
1335 &hf_lbtru_opt_cid_flags_ignore,
1336 NULL
1338 int hdrlen;
1339 uint8_t cur_next_hdr;
1341 cur_next_hdr = tvb_get_uint8(tvb, ofs + O_LBTRU_BASIC_OPT_T_NEXT_HDR);
1342 hdrlen = (int)tvb_get_uint8(tvb, ofs + O_LBTRU_BASIC_OPT_T_HDR_LEN);
1343 switch (next_hdr)
1345 case LBTRU_NHDR_SID:
1346 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);
1347 opt_tree = proto_item_add_subtree(fld_item, ett_lbtru_opt);
1348 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);
1349 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);
1350 if (hdrlen == 0)
1352 expert_add_info(pinfo, hdr_length_item, &ei_lbtru_analysis_zero_length_header);
1353 return (total_dissected_len);
1355 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);
1356 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);
1357 session_id = tvb_get_ntohl(tvb, ofs + L_LBTRU_BASIC_OPT_T + O_LBTRU_SID_OPT_T_SESSION_ID);
1358 break;
1359 case LBTRU_NHDR_CID:
1360 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);
1361 opt_tree = proto_item_add_subtree(fld_item, ett_lbtru_opt);
1362 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);
1363 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);
1364 if (hdrlen == 0)
1366 expert_add_info(pinfo, hdr_length_item, &ei_lbtru_analysis_zero_length_header);
1367 return (total_dissected_len);
1369 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);
1370 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);
1371 break;
1372 default:
1373 expert_add_info_format(pinfo, next_hdr_item, &ei_lbtru_analysis_unknown_header, "Unrecognized header 0x%02x", next_hdr);
1374 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);
1375 opt_tree = proto_item_add_subtree(fld_item, ett_lbtru_opt);
1376 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);
1377 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);
1378 if (hdrlen == 0)
1380 expert_add_info(pinfo, hdr_length_item, &ei_lbtru_analysis_zero_length_header);
1381 return (total_dissected_len);
1383 break;
1385 next_hdr = cur_next_hdr;
1386 ofs += hdrlen;
1387 total_dissected_len += hdrlen;
1390 /* Find (or create) the transport and client entries */
1391 if (from_source)
1393 copy_address_shallow(&source_address, &(pinfo->src));
1394 source_port = pinfo->srcport;
1395 copy_address_shallow(&receiver_address, &(pinfo->dst));
1396 receiver_port = pinfo->destport;
1398 else
1400 copy_address_shallow(&source_address, &(pinfo->dst));
1401 source_port = pinfo->destport;
1402 copy_address_shallow(&receiver_address, &(pinfo->src));
1403 receiver_port = pinfo->srcport;
1405 if (pinfo->fd->visited == 0)
1407 transport = lbtru_transport_add(&source_address, source_port, session_id, pinfo->num);
1409 else
1411 transport = lbtru_transport_find(&source_address, source_port, session_id, pinfo->num);
1413 if (transport != NULL)
1415 if (pinfo->fd->visited == 0)
1417 client = lbtru_client_transport_add(transport, &receiver_address, receiver_port, pinfo->num);
1418 if (client != NULL)
1420 if (lbtru_sequence_analysis)
1422 lbtru_client_transport_frame_add(client, packet_type, pinfo->num, packet_sqn, retransmission);
1426 else
1428 client = lbtru_client_transport_find(transport, &receiver_address, receiver_port, pinfo->num);
1430 tapinfo->transport = lbtru_transport_source_string_transport(pinfo->pool, transport);
1431 channel = transport->channel;
1432 fld_item = proto_tree_add_uint64(channel_tree, hf_lbtru_channel_id, tvb, 0, 0, channel);
1433 proto_item_set_generated(fld_item);
1434 if (client != NULL)
1436 fld_item = proto_tree_add_uint(channel_tree, hf_lbtru_channel_client, tvb, 0, 0, client->id);
1437 proto_item_set_generated(fld_item);
1440 proto_item_set_len(lbtru_item, total_dissected_len);
1441 if ((packet_type == LBTRU_PACKET_TYPE_DATA) && (next_hdr == LBTRU_NHDR_DATA))
1443 total_dissected_len += dissect_lbtru_data_contents(tvb, ofs, pinfo, tree, tag_name, channel);
1445 if (lbtru_sequence_analysis)
1447 if ((transport != NULL) && (client != NULL))
1449 lbm_transport_frame_t * frame = NULL;
1451 /* Fill in the tree */
1452 frame = lbtru_client_transport_frame_find(client, pinfo->num);
1453 if (frame != NULL)
1455 lbm_transport_sqn_t * sqn = NULL;
1457 if (frame->previous_frame != 0)
1459 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_frame, tvb, 0, 0, frame->previous_frame);
1460 proto_item_set_generated(transport_item);
1462 if (frame->next_frame != 0)
1464 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_frame, tvb, 0, 0, frame->next_frame);
1465 proto_item_set_generated(transport_item);
1467 switch (packet_type)
1469 case LBTRU_PACKET_TYPE_DATA:
1470 if (frame->previous_type_frame != 0)
1472 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_data_frame, tvb, 0, 0, frame->previous_type_frame);
1473 proto_item_set_generated(transport_item);
1475 if (frame->next_type_frame != 0)
1477 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_data_frame, tvb, 0, 0, frame->next_type_frame);
1478 proto_item_set_generated(transport_item);
1480 sqn = lbtru_client_transport_sqn_find(client, packet_type, packet_sqn);
1481 if (sqn != NULL)
1483 if (sqn->frame_count > 1)
1485 proto_tree * frame_tree = NULL;
1486 proto_item * frame_tree_item = NULL;
1487 lbtru_sqn_frame_list_callback_data_t cb_data;
1489 frame_tree_item = proto_tree_add_item(transport_tree, hf_lbtru_analysis_sqn, tvb, 0, 0, ENC_NA);
1490 proto_item_set_generated(frame_tree_item);
1491 frame_tree = proto_item_add_subtree(frame_tree_item, ett_lbtru_transport_sqn);
1492 cb_data.tree = frame_tree;
1493 cb_data.tvb = tvb;
1494 cb_data.current_frame = pinfo->num;
1495 wmem_tree_foreach(sqn->frame, dissect_lbtru_sqn_frame_list_callback, (void *) &cb_data);
1498 if (frame->retransmission)
1500 transport_item = proto_tree_add_boolean(transport_tree, hf_lbtru_analysis_data_retransmission, tvb, 0, 0, true);
1501 proto_item_set_generated(transport_item);
1502 expert_add_info(pinfo, transport_item, &ei_lbtru_analysis_data_rx);
1504 if (frame->sqn_gap != 0)
1506 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_data_sqn_gap, tvb, 0, 0, frame->sqn_gap);
1507 proto_item_set_generated(transport_item);
1508 expert_add_info_format(pinfo, transport_item, &ei_lbtru_analysis_data_gap, "Data sequence gap (%" PRIu32 ")", frame->sqn_gap);
1511 if (frame->ooo_gap != 0)
1513 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_data_ooo_gap, tvb, 0, 0, frame->ooo_gap);
1514 proto_item_set_generated(transport_item);
1515 expert_add_info_format(pinfo, transport_item, &ei_lbtru_analysis_data_ooo, "Data sequence out of order gap (%" PRIu32 ")", frame->ooo_gap);
1517 if (frame->duplicate)
1519 transport_item = proto_tree_add_boolean(transport_tree, hf_lbtru_analysis_data_duplicate, tvb, 0, 0, true);
1520 proto_item_set_generated(transport_item);
1521 expert_add_info(pinfo, transport_item, &ei_lbtru_analysis_data_dup);
1523 break;
1524 case LBTRU_PACKET_TYPE_SM:
1525 if (frame->previous_type_frame != 0)
1527 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_sm_frame, tvb, 0, 0, frame->previous_type_frame);
1528 proto_item_set_generated(transport_item);
1530 if (frame->next_type_frame != 0)
1532 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_sm_frame, tvb, 0, 0, frame->next_type_frame);
1533 proto_item_set_generated(transport_item);
1535 sqn = lbtru_client_transport_sqn_find(client, packet_type, packet_sqn);
1536 if (sqn != NULL)
1538 if (sqn->frame_count > 1)
1540 proto_tree * frame_tree = NULL;
1541 proto_item * frame_tree_item = NULL;
1542 lbtru_sqn_frame_list_callback_data_t cb_data;
1544 frame_tree_item = proto_tree_add_item(transport_tree, hf_lbtru_analysis_sqn, tvb, 0, 0, ENC_NA);
1545 proto_item_set_generated(frame_tree_item);
1546 frame_tree = proto_item_add_subtree(frame_tree_item, ett_lbtru_transport_sqn);
1547 cb_data.tree = frame_tree;
1548 cb_data.tvb = tvb;
1549 cb_data.current_frame = pinfo->num;
1550 wmem_tree_foreach(sqn->frame, dissect_lbtru_sqn_frame_list_callback, (void *) &cb_data);
1553 if (frame->sqn_gap != 0)
1555 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_sm_sqn_gap, tvb, 0, 0, frame->sqn_gap);
1556 proto_item_set_generated(transport_item);
1557 expert_add_info_format(pinfo, transport_item, &ei_lbtru_analysis_sm_gap, "SM sequence gap (%" PRIu32 ")", frame->sqn_gap);
1560 if (frame->ooo_gap != 0)
1562 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_sm_ooo_gap, tvb, 0, 0, frame->ooo_gap);
1563 proto_item_set_generated(transport_item);
1564 expert_add_info_format(pinfo, transport_item, &ei_lbtru_analysis_sm_ooo, "SM sequence out of order gap (%" PRIu32 ")", frame->ooo_gap);
1566 if (frame->duplicate)
1568 transport_item = proto_tree_add_boolean(transport_tree, hf_lbtru_analysis_sm_duplicate, tvb, 0, 0, true);
1569 proto_item_set_generated(transport_item);
1570 expert_add_info(pinfo, transport_item, &ei_lbtru_analysis_sm_dup);
1572 break;
1573 case LBTRU_PACKET_TYPE_NAK:
1574 if (frame->previous_type_frame != 0)
1576 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_nak_frame, tvb, 0, 0, frame->previous_type_frame);
1577 proto_item_set_generated(transport_item);
1579 if (frame->next_type_frame != 0)
1581 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_nak_frame, tvb, 0, 0, frame->next_type_frame);
1582 proto_item_set_generated(transport_item);
1584 break;
1585 case LBTRU_PACKET_TYPE_NCF:
1586 if (frame->previous_type_frame != 0)
1588 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_ncf_frame, tvb, 0, 0, frame->previous_type_frame);
1589 proto_item_set_generated(transport_item);
1591 if (frame->next_type_frame != 0)
1593 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_ncf_frame, tvb, 0, 0, frame->next_type_frame);
1594 proto_item_set_generated(transport_item);
1596 break;
1597 case LBTRU_PACKET_TYPE_ACK:
1598 if (frame->previous_type_frame != 0)
1600 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_ack_frame, tvb, 0, 0, frame->previous_type_frame);
1601 proto_item_set_generated(transport_item);
1603 if (frame->next_type_frame != 0)
1605 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_ack_frame, tvb, 0, 0, frame->next_type_frame);
1606 proto_item_set_generated(transport_item);
1608 break;
1609 case LBTRU_PACKET_TYPE_CREQ:
1610 if (frame->previous_type_frame != 0)
1612 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_creq_frame, tvb, 0, 0, frame->previous_type_frame);
1613 proto_item_set_generated(transport_item);
1615 if (frame->next_type_frame != 0)
1617 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_creq_frame, tvb, 0, 0, frame->next_type_frame);
1618 proto_item_set_generated(transport_item);
1620 break;
1621 case LBTRU_PACKET_TYPE_RST:
1622 if (frame->previous_type_frame != 0)
1624 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_prev_rst_frame, tvb, 0, 0, frame->previous_type_frame);
1625 proto_item_set_generated(transport_item);
1627 if (frame->next_type_frame != 0)
1629 transport_item = proto_tree_add_uint(transport_tree, hf_lbtru_analysis_next_rst_frame, tvb, 0, 0, frame->next_type_frame);
1630 proto_item_set_generated(transport_item);
1632 break;
1633 default:
1634 break;
1639 if (tapinfo->transport != NULL)
1641 tap_queue_packet(lbtru_tap_handle, pinfo, (void *) tapinfo);
1643 return (total_dissected_len);
1646 static bool test_lbtru_packet(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * user_data)
1648 bool valid_packet = false;
1650 /* Must be a UDP packet. */
1651 if (pinfo->ptype != PT_UDP)
1653 return false;
1655 /* Destination address must be IPV4 and 4 bytes in length. */
1656 if ((pinfo->dst.type != AT_IPv4) || (pinfo->dst.len != 4))
1658 return false;
1661 if (lbtru_use_tag)
1663 if (lbtru_tag_find(pinfo) != NULL)
1665 valid_packet = true;
1668 else
1671 Source port must be in the source port range and destination port must be in the receiver port range,
1672 or vice-versa.
1674 if (((pinfo->destport >= lbtru_source_port_low)
1675 && (pinfo->destport <= lbtru_source_port_high)
1676 && (pinfo->srcport >= lbtru_receiver_port_low)
1677 && (pinfo->srcport <= lbtru_receiver_port_high))
1678 || ((pinfo->destport >= lbtru_receiver_port_low)
1679 && (pinfo->destport <= lbtru_receiver_port_high)
1680 && (pinfo->srcport >= lbtru_source_port_low)
1681 && (pinfo->srcport <= lbtru_source_port_high)))
1683 /* One of ours. */
1684 valid_packet = true;
1687 if (valid_packet)
1689 dissect_lbtru(tvb, pinfo, tree, user_data);
1690 return true;
1692 /* Not one of ours. */
1693 return false;
1696 /* Register all the bits needed with the filtering engine */
1697 void proto_register_lbtru(void)
1699 static hf_register_info hf[] =
1701 { &hf_lbtru_channel,
1702 { "Channel", "lbtru.channel", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1703 { &hf_lbtru_channel_id,
1704 { "Channel ID", "lbtru.channel.channel", FT_UINT64, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } },
1705 { &hf_lbtru_channel_client,
1706 { "Channel Client", "lbtru.channel.client", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1707 { &hf_lbtru_tag,
1708 { "Tag", "lbtru.tag", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1709 { &hf_lbtru_hdr,
1710 { "Header", "lbtru.hdr", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1711 { &hf_lbtru_hdr_ver,
1712 { "Version", "lbtru.hdr.ver", FT_UINT8, BASE_DEC, NULL, LBTRU_HDR_VER_VER_MASK, NULL, HFILL } },
1713 { &hf_lbtru_hdr_type,
1714 { "Type", "lbtru.hdr.type", FT_UINT8, BASE_HEX, VALS(lbtru_packet_type), LBTRU_HDR_VER_TYPE_MASK, NULL, HFILL } },
1715 { &hf_lbtru_hdr_next_hdr,
1716 { "Next Header", "lbtru.hdr.next_hdr", FT_UINT8, BASE_HEX, VALS(lbtru_next_header), 0x0, NULL, HFILL } },
1717 { &hf_lbtru_hdr_res,
1718 { "Reserved", "lbtru.hdr.res", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1719 { &hf_lbtru_hdr_flags,
1720 { "Flags", "lbtru.hdr.flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1721 { &hf_lbtru_hdr_flags_rx,
1722 { "Retransmission", "lbtru.hdr.flags.rx", FT_BOOLEAN, L_LBTRU_HDR_T_FLAGS_OR_RES * 8, TFS(&tfs_set_notset), LBTRU_RETRANSMISSION_FLAG, NULL, HFILL } },
1723 { &hf_lbtru_hdr_flags_syn,
1724 { "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 } },
1725 { &hf_lbtru_hdr_request,
1726 { "Request", "lbtru.hdr.request", FT_UINT16, BASE_HEX, VALS(lbtru_creq_request), 0x0, NULL, HFILL } },
1727 { &hf_lbtru_hdr_reason,
1728 { "Reason", "lbtru.hdr.reason", FT_UINT16, BASE_HEX, VALS(lbtru_rst_reason), 0x0, NULL, HFILL } },
1729 { &hf_lbtru_data,
1730 { "Data Header", "lbtru.data", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1731 { &hf_lbtru_data_sqn,
1732 { "Sequence Number", "lbtru.data.sqn", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } },
1733 { &hf_lbtru_data_trail_sqn,
1734 { "Trailing Edge Sequence Number", "lbtru.data.trail", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } },
1735 { &hf_lbtru_sm,
1736 { "Session Message Header", "lbtru.sm", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1737 { &hf_lbtru_sm_sqn,
1738 { "Sequence Number", "lbtru.sm.sqn", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } },
1739 { &hf_lbtru_sm_lead_sqn,
1740 { "Leading Edge Sequence Number", "lbtru.sm.lead", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } },
1741 { &hf_lbtru_sm_trail_sqn,
1742 { "Trailing Edge Sequence Number", "lbtru.sm.trail", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } },
1743 { &hf_lbtru_nak,
1744 { "NAK Header", "lbtru.nak", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1745 { &hf_lbtru_nak_num,
1746 { "Number of NAKs", "lbtru.nak.num", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1747 { &hf_lbtru_nak_format,
1748 { "Format", "lbtru.nak.format", FT_UINT16, BASE_DEC, VALS(lbtru_nak_format), LBTRU_NAK_HDR_FORMAT_MASK, NULL, HFILL } },
1749 { &hf_lbtru_nak_list,
1750 { "NAK List", "lbtru.nak.list", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1751 { &hf_lbtru_nak_list_nak,
1752 { "NAK", "lbtru.nak.list.nak", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1753 { &hf_lbtru_ncf,
1754 { "NAK Confirmation Header", "lbtru.ncf", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1755 { &hf_lbtru_ncf_trail_sqn,
1756 { "Trailing Edge Sequence Number", "lbtru.ncf.trail", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } },
1757 { &hf_lbtru_ncf_num,
1758 { "Number of Individual NCFs", "lbtru.ncf.num", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1759 { &hf_lbtru_ncf_reserved,
1760 { "Reserved", "lbtru.ncf.reserved", FT_UINT8, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } },
1761 { &hf_lbtru_ncf_reason,
1762 { "Reason", "lbtru.ncf.reason", FT_UINT8, BASE_HEX, VALS(lbtru_ncf_reason), LBTRU_NCF_HDR_REASON_MASK, NULL, HFILL } },
1763 { &hf_lbtru_ncf_format,
1764 { "Format", "lbtru.ncf.format", FT_UINT8, BASE_HEX, VALS(lbtru_ncf_format), LBTRU_NCF_HDR_FORMAT_MASK, NULL, HFILL } },
1765 { &hf_lbtru_ncf_list,
1766 { "NCF List", "lbtru.ncf.list", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1767 { &hf_lbtru_ncf_list_ncf,
1768 { "NCF", "lbtru.ncf.list.ncf", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1769 { &hf_lbtru_ack,
1770 { "ACK Header", "lbtru.ack", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1771 { &hf_lbtru_ack_sqn,
1772 { "ACK Sequence Number", "lbtru.ack.sqn", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } },
1773 { &hf_lbtru_opt_sid,
1774 { "SID Option", "lbtru.opt_sid", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1775 { &hf_lbtru_opt_sid_next_hdr,
1776 { "Next Header", "lbtru.opt_sid.next_hdr", FT_UINT8, BASE_DEC_HEX, VALS(lbtru_next_header), 0x0, NULL, HFILL } },
1777 { &hf_lbtru_opt_sid_hdr_len,
1778 { "Header Length", "lbtru.opt_sid.hdr_len", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1779 { &hf_lbtru_opt_sid_flags,
1780 { "Flags", "lbtru.opt_sid.flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1781 { &hf_lbtru_opt_sid_flags_ignore,
1782 { "Ignore", "lbtru.opt_sid.flags.ignore", FT_BOOLEAN, L_LBTRU_BASIC_OPT_T_RES * 8, &(tfs_set_notset), LBTRU_OPT_IGNORE, NULL, HFILL } },
1783 { &hf_lbtru_opt_sid_session_id,
1784 { "Session ID", "lbtru.opt_sid.session_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1785 { &hf_lbtru_opt_cid,
1786 { "CID Option", "lbtru.opt_cid", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1787 { &hf_lbtru_opt_cid_next_hdr,
1788 { "Next Header", "lbtru.opt_cid.next_hdr", FT_UINT8, BASE_DEC_HEX, VALS(lbtru_next_header), 0x0, NULL, HFILL } },
1789 { &hf_lbtru_opt_cid_hdr_len,
1790 { "Header Length", "lbtru.opt_cid.hdr_len", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1791 { &hf_lbtru_opt_cid_flags,
1792 { "Flags", "lbtru.opt_cid.flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1793 { &hf_lbtru_opt_cid_flags_ignore,
1794 { "Ignore", "lbtru.opt_cid.flags.ignore", FT_BOOLEAN, L_LBTRU_BASIC_OPT_T_RES * 8, &(tfs_set_notset), LBTRU_OPT_IGNORE, NULL, HFILL } },
1795 { &hf_lbtru_opt_cid_client_id,
1796 { "Client ID", "lbtru.opt_cid.client_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1797 { &hf_lbtru_opt_unknown,
1798 { "Unknown Option", "lbtru.opt_unknown", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1799 { &hf_lbtru_opt_unknown_next_hdr,
1800 { "Next Header", "lbtru.opt_unknown.next_hdr", FT_UINT8, BASE_DEC_HEX, VALS(lbtru_next_header), 0x0, NULL, HFILL } },
1801 { &hf_lbtru_opt_unknown_hdr_len,
1802 { "Header Length", "lbtru.opt_unknown.hdr_len", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1803 { &hf_lbtru_analysis,
1804 { "Transport Analysis", "lbtru.analysis", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1805 { &hf_lbtru_analysis_prev_frame,
1806 { "Previous Transport Frame", "lbtru.analysis.prev_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1807 { &hf_lbtru_analysis_prev_data_frame,
1808 { "Previous Transport DATA Frame", "lbtru.analysis.prev_data_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1809 { &hf_lbtru_analysis_prev_sm_frame,
1810 { "Previous Transport SM Frame", "lbtru.analysis.prev_sm_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1811 { &hf_lbtru_analysis_prev_nak_frame,
1812 { "Previous Transport NAK Frame", "lbtru.analysis.prev_nak_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1813 { &hf_lbtru_analysis_prev_ncf_frame,
1814 { "Previous Transport NCF Frame", "lbtru.analysis.prev_ncf_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1815 { &hf_lbtru_analysis_prev_ack_frame,
1816 { "Previous Transport ACK Frame", "lbtru.analysis.prev_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1817 { &hf_lbtru_analysis_prev_creq_frame,
1818 { "Previous Transport CREQ Frame", "lbtru.analysis.prev_creq_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1819 { &hf_lbtru_analysis_prev_rst_frame,
1820 { "Previous Transport RST Frame", "lbtru.analysis.prev_rst_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1821 { &hf_lbtru_analysis_next_frame,
1822 { "Next Transport Frame", "lbtru.analysis.next_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1823 { &hf_lbtru_analysis_next_data_frame,
1824 { "Next Transport DATA Frame", "lbtru.analysis.next_data_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1825 { &hf_lbtru_analysis_next_sm_frame,
1826 { "Next Transport SM Frame", "lbtru.analysis.next_sm_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1827 { &hf_lbtru_analysis_next_nak_frame,
1828 { "Next Transport NAK Frame", "lbtru.analysis.next_nak_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1829 { &hf_lbtru_analysis_next_ncf_frame,
1830 { "Next Transport NCF Frame", "lbtru.analysis.next_ncf_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1831 { &hf_lbtru_analysis_next_ack_frame,
1832 { "Next Transport ACK Frame", "lbtru.analysis.next_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1833 { &hf_lbtru_analysis_next_creq_frame,
1834 { "Next Transport CREQ Frame", "lbtru.analysis.next_creq_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1835 { &hf_lbtru_analysis_next_rst_frame,
1836 { "Next Transport RST Frame", "lbtru.analysis.next_rst_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1837 { &hf_lbtru_analysis_sqn,
1838 { "SQN Also in", "lbtru.analysis.sqn", FT_NONE, BASE_NONE, NULL, 0x0, "Sequence number also appears in these frames", HFILL } },
1839 { &hf_lbtru_analysis_sqn_frame,
1840 { "Frame", "lbtru.analysis.sqn.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1841 { &hf_lbtru_analysis_data_retransmission,
1842 { "Frame is a Data Retransmission", "lbtru.analysis.data_retransmission", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1843 { &hf_lbtru_analysis_data_sqn_gap,
1844 { "Gap in Data Sequence", "lbtru.analysis.data_sqn_gap", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1845 { &hf_lbtru_analysis_data_ooo_gap,
1846 { "Data Sequence Out of Order Gap", "lbtru.analysis.data_ooo_gap", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1847 { &hf_lbtru_analysis_data_duplicate,
1848 { "Duplicate Data Frame", "lbtru.analysis.data_duplicate", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1849 { &hf_lbtru_analysis_sm_sqn_gap,
1850 { "Gap in SM Sequence", "lbtru.analysis.sm_sqn_gap", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1851 { &hf_lbtru_analysis_sm_ooo_gap,
1852 { "SM Sequence Out of Order Gap", "lbtru.analysis.sm_ooo_gap", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1853 { &hf_lbtru_analysis_sm_duplicate,
1854 { "Duplicate SM Frame", "lbtru.analysis.sm_duplicate", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1856 static int * ett[] =
1858 &ett_lbtru,
1859 &ett_lbtru_channel,
1860 &ett_lbtru_hdr,
1861 &ett_lbtru_hdr_flags,
1862 &ett_lbtru_data,
1863 &ett_lbtru_sm,
1864 &ett_lbtru_nak,
1865 &ett_lbtru_nak_list,
1866 &ett_lbtru_ncf,
1867 &ett_lbtru_ncf_list,
1868 &ett_lbtru_ack,
1869 &ett_lbtru_opt,
1870 &ett_lbtru_opt_sid_flags,
1871 &ett_lbtru_opt_cid_flags,
1872 &ett_lbtru_transport,
1873 &ett_lbtru_transport_sqn,
1875 static ei_register_info ei[] =
1877 { &ei_lbtru_analysis_unknown_type, { "lbtru.analysis.unknown_type", PI_MALFORMED, PI_ERROR, "Unrecognized type", EXPFILL } },
1878 { &ei_lbtru_analysis_unknown_header, { "lbtru.analysis.unknown_header", PI_MALFORMED, PI_ERROR, "Unrecognized header", EXPFILL } },
1879 { &ei_lbtru_analysis_zero_length_header, { "lbtru.analysis.zero_length_header", PI_MALFORMED, PI_ERROR, "Zero-length header", EXPFILL } },
1880 { &ei_lbtru_analysis_ack, { "lbtru.analysis.ack", PI_SEQUENCE, PI_CHAT, "ACK", EXPFILL } },
1881 { &ei_lbtru_analysis_ncf, { "lbtru.analysis.ncf", PI_SEQUENCE, PI_NOTE, "NCF", EXPFILL } },
1882 { &ei_lbtru_analysis_ncf_ncf, { "lbtru.analysis.ncf.ncf", PI_SEQUENCE, PI_NOTE, "NCF", EXPFILL } },
1883 { &ei_lbtru_analysis_nak, { "lbtru.analysis.nak", PI_SEQUENCE, PI_WARN, "NAK", EXPFILL } },
1884 { &ei_lbtru_analysis_nak_nak, { "lbtru.analysis.nak.nak", PI_SEQUENCE, PI_WARN, "NAK", EXPFILL } },
1885 { &ei_lbtru_analysis_sm, { "lbtru.analysis.sm", PI_SEQUENCE, PI_CHAT, "SM", EXPFILL } },
1886 { &ei_lbtru_analysis_sm_syn, { "lbtru.analysis.sm.syn", PI_SEQUENCE, PI_CHAT, "SM SYN", EXPFILL } },
1887 { &ei_lbtru_analysis_creq, { "lbtru.analysis.creq", PI_SEQUENCE, PI_CHAT, "Connection REQuest", EXPFILL } },
1888 { &ei_lbtru_analysis_rst, { "lbtru.analysis.rst", PI_SEQUENCE, PI_CHAT, "ReSeT", EXPFILL } },
1889 { &ei_lbtru_analysis_data_rx, { "lbtru.analysis.data.rx", PI_SEQUENCE, PI_NOTE, "Data retransmission", EXPFILL } },
1890 { &ei_lbtru_analysis_data_gap, { "lbtru.analysis.data.gap", PI_SEQUENCE, PI_NOTE, "Data sequence gap", EXPFILL } },
1891 { &ei_lbtru_analysis_data_ooo, { "lbtru.analysis.data.ooo", PI_SEQUENCE, PI_NOTE, "Data sequence out of order", EXPFILL } },
1892 { &ei_lbtru_analysis_data_dup, { "lbtru.analysis.data.dup", PI_SEQUENCE, PI_NOTE, "Duplicate data", EXPFILL } },
1893 { &ei_lbtru_analysis_sm_gap, { "lbtru.analysis.sm.gap", PI_SEQUENCE, PI_NOTE, "SM sequence gap", EXPFILL } },
1894 { &ei_lbtru_analysis_sm_ooo, { "lbtru.analysis.sm.ooo", PI_SEQUENCE, PI_NOTE, "SM sequence out of order", EXPFILL } },
1895 { &ei_lbtru_analysis_sm_dup, { "lbtru.analysis.sm.dup", PI_SEQUENCE, PI_NOTE, "Duplicate SM", EXPFILL } },
1897 module_t * lbtru_module;
1898 uat_t * tag_uat;
1899 expert_module_t * expert_lbtru;
1901 proto_lbtru = proto_register_protocol("LBT Reliable Unicast Protocol",
1902 "LBT-RU", "lbtru");
1904 proto_register_field_array(proto_lbtru, hf, array_length(hf));
1905 proto_register_subtree_array(ett, array_length(ett));
1906 expert_lbtru = expert_register_protocol(proto_lbtru);
1907 expert_register_field_array(expert_lbtru, ei, array_length(ei));
1909 lbtru_dissector_handle = register_dissector("lbtru", dissect_lbtru, proto_lbtru);
1911 lbtru_tap_handle = register_tap("lbm_lbtru");
1913 lbtru_module = prefs_register_protocol_subtree("29West", proto_lbtru, proto_reg_handoff_lbtru);
1914 prefs_register_uint_preference(lbtru_module,
1915 "source_port_low",
1916 "Source port range low (default " MAKESTRING(LBTRU_DEFAULT_SOURCE_PORT_LOW)")",
1917 "Set the low end of the LBT-RU source UDP port range (context transport_lbtru_port_low)",
1919 &global_lbtru_source_port_low);
1921 prefs_register_uint_preference(lbtru_module,
1922 "source_port_high",
1923 "Source port range high (default " MAKESTRING(LBTRU_DEFAULT_SOURCE_PORT_HIGH)")",
1924 "Set the high end of the LBT-RU source UDP port range (context transport_lbtru_port_high)",
1926 &global_lbtru_source_port_high);
1928 prefs_register_uint_preference(lbtru_module,
1929 "receiver_port_low",
1930 "Receiver port range low (default " MAKESTRING(LBTRU_DEFAULT_RECEIVER_PORT_LOW)")",
1931 "Set the low end of the LBT-RU receiver UDP port range (receiver transport_lbtru_port_low)",
1933 &global_lbtru_receiver_port_low);
1935 prefs_register_uint_preference(lbtru_module,
1936 "receiver_port_high",
1937 "Receiver port range high (default " MAKESTRING(LBTRU_DEFAULT_RECEIVER_PORT_HIGH)")",
1938 "Set the high end of the LBT-RU receiver UDP port range (receiver transport_lbtru_port_high)",
1940 &global_lbtru_receiver_port_high);
1942 lbtru_expert_separate_naks = global_lbtru_expert_separate_naks;
1943 prefs_register_bool_preference(lbtru_module,
1944 "expert_separate_naks",
1945 "Separate NAKs in Expert Info",
1946 "Separate multiple NAKs from a single packet into distinct Expert Info entries",
1947 &global_lbtru_expert_separate_naks);
1948 lbtru_expert_separate_ncfs = global_lbtru_expert_separate_ncfs;
1949 prefs_register_bool_preference(lbtru_module,
1950 "expert_separate_ncfs",
1951 "Separate NCFs in Expert Info",
1952 "Separate multiple NCFs from a single packet into distinct Expert Info entries",
1953 &global_lbtru_expert_separate_ncfs);
1955 lbtru_sequence_analysis = global_lbtru_sequence_analysis;
1956 prefs_register_bool_preference(lbtru_module,
1957 "sequence_analysis",
1958 "Perform Sequence Number Analysis",
1959 "Perform analysis on LBT-RU sequence numbers to determine out-of-order, gaps, loss, etc",
1960 &global_lbtru_sequence_analysis);
1962 prefs_register_bool_preference(lbtru_module,
1963 "use_lbtru_domain",
1964 "Use LBT-RU tag table",
1965 "Use table of LBT-RU tags to decode the packet instead of above values",
1966 &global_lbtru_use_tag);
1967 tag_uat = uat_new("LBT-RU tag definitions",
1968 sizeof(lbtru_tag_entry_t),
1969 "lbtru_domains",
1970 true,
1971 (void * *)&lbtru_tag_entry,
1972 &lbtru_tag_count,
1973 UAT_AFFECTS_DISSECTION,
1974 NULL,
1975 lbtru_tag_copy_cb,
1976 lbtru_tag_update_cb,
1977 lbtru_tag_free_cb,
1978 NULL,
1979 NULL,
1980 lbtru_tag_array);
1981 prefs_register_uat_preference(lbtru_module,
1982 "tnw_lbtru_tags",
1983 "LBT-RU Tags",
1984 "A table to define LBT-RU tags",
1985 tag_uat);
1988 /* The registration hand-off routine */
1989 void proto_reg_handoff_lbtru(void)
1991 static bool already_registered = false;
1993 if (!already_registered)
1995 dissector_add_for_decode_as_with_preference("udp.port", lbtru_dissector_handle);
1996 heur_dissector_add("udp", test_lbtru_packet, "LBT Reliable Unicast over UDP", "lbtru_udp", proto_lbtru, HEURISTIC_ENABLE);
1999 /* Make sure the low source port is <= the high source port. If not, don't change them. */
2000 if (global_lbtru_source_port_low <= global_lbtru_source_port_high)
2002 lbtru_source_port_low = global_lbtru_source_port_low;
2003 lbtru_source_port_high = global_lbtru_source_port_high;
2006 /* Make sure the low receiver port is <= the high receiver port. If not, don't change them. */
2007 if (global_lbtru_receiver_port_low <= global_lbtru_receiver_port_high)
2009 lbtru_receiver_port_low = global_lbtru_receiver_port_low;
2010 lbtru_receiver_port_high = global_lbtru_receiver_port_high;
2013 lbtru_expert_separate_naks = global_lbtru_expert_separate_naks;
2014 lbtru_expert_separate_ncfs = global_lbtru_expert_separate_ncfs;
2016 lbtru_sequence_analysis = global_lbtru_sequence_analysis;
2018 lbtru_use_tag = global_lbtru_use_tag;
2020 already_registered = true;
2024 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2026 * Local variables:
2027 * c-basic-offset: 4
2028 * tab-width: 8
2029 * indent-tabs-mode: nil
2030 * End:
2032 * vi: set shiftwidth=4 tabstop=8 expandtab:
2033 * :indentSize=4:tabSize=8:noTabs=true: