2 * Routines for LBT-RM 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
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
20 #include <epan/conversation.h>
21 #include <epan/to_str.h>
22 #include <wsutil/pint.h>
23 #include "packet-lbm.h"
24 #include "packet-lbtrm.h"
26 void proto_register_lbtrm(void);
27 void proto_reg_handoff_lbtrm(void);
30 static int proto_lbtrm
;
32 /* Dissector handle */
33 static dissector_handle_t lbtrm_dissector_handle
;
36 static int lbtrm_tap_handle
= -1;
38 /*----------------------------------------------------------------------------*/
39 /* LBT-RM transport management. */
40 /*----------------------------------------------------------------------------*/
42 static const address lbtrm_null_address
= ADDRESS_INIT_NONE
;
44 static lbtrm_transport_t
* lbtrm_transport_unicast_find(const address
* source_address
, uint16_t source_port
, uint32_t session_id
, uint32_t frame
)
46 lbtrm_transport_t
* transport
= NULL
;
47 conversation_t
* conv
= NULL
;
48 wmem_tree_t
* session_tree
= NULL
;
50 conv
= find_conversation(frame
, source_address
, &lbtrm_null_address
, CONVERSATION_UDP
, source_port
, 0, 0);
53 if (frame
> conv
->last_frame
)
55 conv
->last_frame
= frame
;
57 session_tree
= (wmem_tree_t
*) conversation_get_proto_data(conv
, proto_lbtrm
);
58 if (session_tree
!= NULL
)
60 transport
= (lbtrm_transport_t
*) wmem_tree_lookup32(session_tree
, session_id
);
66 static void lbtrm_transport_unicast_add(const address
* source_address
, uint16_t source_port
, uint32_t session_id
, uint32_t frame
, lbtrm_transport_t
* transport
)
68 conversation_t
* conv
= NULL
;
69 wmem_tree_t
* session_tree
= NULL
;
70 lbtrm_transport_t
* transport_entry
= NULL
;
72 conv
= find_conversation(frame
, source_address
, &lbtrm_null_address
, CONVERSATION_UDP
, source_port
, 0, 0);
75 conv
= conversation_new(frame
, source_address
, &lbtrm_null_address
, CONVERSATION_UDP
, source_port
, 0, 0);
77 session_tree
= (wmem_tree_t
*) conversation_get_proto_data(conv
, proto_lbtrm
);
78 if (session_tree
== NULL
)
80 session_tree
= wmem_tree_new(wmem_file_scope());
81 conversation_add_proto_data(conv
, proto_lbtrm
, (void *) session_tree
);
83 transport_entry
= (lbtrm_transport_t
*) wmem_tree_lookup32(session_tree
, session_id
);
84 if (transport_entry
== NULL
)
86 wmem_tree_insert32(session_tree
, session_id
, (void *) transport
);
90 static lbtrm_transport_t
* lbtrm_transport_find(const address
* source_address
, uint16_t source_port
, uint32_t session_id
, const address
* multicast_group
, uint16_t dest_port
, uint32_t frame
)
92 lbtrm_transport_t
* entry
= NULL
;
93 wmem_tree_t
* session_tree
= NULL
;
94 conversation_t
* conv
= NULL
;
96 conv
= find_conversation(frame
, source_address
, multicast_group
, CONVERSATION_UDP
, source_port
, dest_port
, 0);
99 if (frame
> conv
->last_frame
)
101 conv
->last_frame
= frame
;
103 session_tree
= (wmem_tree_t
*) conversation_get_proto_data(conv
, proto_lbtrm
);
104 if (session_tree
!= NULL
)
106 entry
= (lbtrm_transport_t
*) wmem_tree_lookup32(session_tree
, session_id
);
112 lbtrm_transport_t
* lbtrm_transport_add(const address
* source_address
, uint16_t source_port
, uint32_t session_id
, const address
* multicast_group
, uint16_t dest_port
, uint32_t frame
)
114 lbtrm_transport_t
* entry
;
115 conversation_t
* conv
= NULL
;
116 wmem_tree_t
* session_tree
= NULL
;
118 conv
= find_conversation(frame
, source_address
, multicast_group
, CONVERSATION_UDP
, source_port
, dest_port
, 0);
121 conv
= conversation_new(frame
, source_address
, multicast_group
, CONVERSATION_UDP
, source_port
, dest_port
, 0);
123 if (frame
> conv
->last_frame
)
125 conv
->last_frame
= frame
;
127 session_tree
= (wmem_tree_t
*) conversation_get_proto_data(conv
, proto_lbtrm
);
128 if (session_tree
== NULL
)
130 session_tree
= wmem_tree_new(wmem_file_scope());
131 conversation_add_proto_data(conv
, proto_lbtrm
, (void *) session_tree
);
133 entry
= (lbtrm_transport_t
*) wmem_tree_lookup32(session_tree
, session_id
);
138 entry
= wmem_new(wmem_file_scope(), lbtrm_transport_t
);
139 copy_address_wmem(wmem_file_scope(), &(entry
->source_address
), source_address
);
140 entry
->source_port
= source_port
;
141 entry
->session_id
= session_id
;
142 copy_address_wmem(wmem_file_scope(), &(entry
->multicast_group
), multicast_group
);
143 entry
->dest_port
= dest_port
;
144 entry
->channel
= lbm_channel_assign(LBM_CHANNEL_TRANSPORT_LBTRM
);
145 entry
->frame
= wmem_tree_new(wmem_file_scope());
146 entry
->last_frame
= NULL
;
147 entry
->last_data_frame
= NULL
;
148 entry
->last_sm_frame
= NULL
;
149 entry
->last_nak_frame
= NULL
;
150 entry
->last_ncf_frame
= NULL
;
151 entry
->data_sqn
= wmem_tree_new(wmem_file_scope());
152 entry
->sm_sqn
= wmem_tree_new(wmem_file_scope());
153 entry
->data_high_sqn
= 0;
154 entry
->sm_high_sqn
= 0;
155 wmem_tree_insert32(session_tree
, session_id
, (void *) entry
);
156 lbtrm_transport_unicast_add(source_address
, source_port
, session_id
, frame
, entry
);
160 static lbm_transport_sqn_t
* lbtrm_transport_sqn_find(lbtrm_transport_t
* transport
, uint8_t type
, uint32_t sqn
)
162 lbm_transport_sqn_t
* sqn_entry
= NULL
;
166 case LBTRM_PACKET_TYPE_DATA
:
167 sqn_entry
= (lbm_transport_sqn_t
*) wmem_tree_lookup32(transport
->data_sqn
, sqn
);
169 case LBTRM_PACKET_TYPE_SM
:
170 sqn_entry
= (lbm_transport_sqn_t
*) wmem_tree_lookup32(transport
->sm_sqn
, sqn
);
172 case LBTRM_PACKET_TYPE_NAK
:
173 case LBTRM_PACKET_TYPE_NCF
:
181 static lbm_transport_sqn_t
* lbtrm_transport_sqn_add(lbtrm_transport_t
* transport
, lbm_transport_frame_t
* frame
)
183 wmem_tree_t
* sqn_list
= NULL
;
184 lbm_transport_sqn_t
* sqn_entry
= NULL
;
188 case LBTRM_PACKET_TYPE_DATA
:
189 sqn_list
= transport
->data_sqn
;
191 case LBTRM_PACKET_TYPE_SM
:
192 sqn_list
= transport
->sm_sqn
;
194 case LBTRM_PACKET_TYPE_NAK
:
195 case LBTRM_PACKET_TYPE_NCF
:
201 sqn_entry
= lbm_transport_sqn_add(sqn_list
, frame
);
205 static lbm_transport_frame_t
* lbtrm_transport_frame_find(lbtrm_transport_t
* transport
, uint32_t frame
)
207 return ((lbm_transport_frame_t
*) wmem_tree_lookup32(transport
->frame
, frame
));
210 static lbm_transport_frame_t
* lbtrm_transport_frame_add(lbtrm_transport_t
* transport
, uint8_t type
, uint32_t frame
, uint32_t sqn
, bool retransmission
)
212 lbm_transport_sqn_t
* dup_sqn_entry
= NULL
;
213 lbm_transport_frame_t
* frame_entry
= NULL
;
215 /* Locate the frame. */
216 frame_entry
= lbtrm_transport_frame_find(transport
, frame
);
217 if (frame_entry
!= NULL
)
219 return (frame_entry
);
221 frame_entry
= lbm_transport_frame_add(transport
->frame
, type
, frame
, sqn
, retransmission
);
222 if (transport
->last_frame
!= NULL
)
224 frame_entry
->previous_frame
= transport
->last_frame
->frame
;
225 transport
->last_frame
->next_frame
= frame
;
227 transport
->last_frame
= frame_entry
;
230 case LBTRM_PACKET_TYPE_DATA
:
231 if (transport
->last_data_frame
!= NULL
)
233 frame_entry
->previous_type_frame
= transport
->last_data_frame
->frame
;
234 transport
->last_data_frame
->next_type_frame
= frame
;
235 /* Ideally, this frame's sqn is 1 more than the highest data sqn seen */
236 if (frame_entry
->sqn
<= transport
->data_high_sqn
)
238 dup_sqn_entry
= lbtrm_transport_sqn_find(transport
, type
, frame_entry
->sqn
);
239 if (!frame_entry
->retransmission
)
242 if (dup_sqn_entry
!= NULL
)
244 frame_entry
->duplicate
= true;
246 if (frame_entry
->sqn
!= transport
->data_high_sqn
)
248 frame_entry
->ooo_gap
= transport
->data_high_sqn
- frame_entry
->sqn
;
254 if (!frame_entry
->retransmission
)
256 if (frame_entry
->sqn
!= (transport
->data_high_sqn
+ 1))
259 frame_entry
->sqn_gap
= frame_entry
->sqn
- (transport
->last_data_frame
->sqn
+ 1);
264 if ((frame_entry
->sqn
> transport
->data_high_sqn
) && !frame_entry
->retransmission
)
266 transport
->data_high_sqn
= frame_entry
->sqn
;
268 transport
->last_data_frame
= frame_entry
;
270 case LBTRM_PACKET_TYPE_SM
:
271 if (transport
->last_sm_frame
!= NULL
)
273 frame_entry
->previous_type_frame
= transport
->last_sm_frame
->frame
;
274 transport
->last_sm_frame
->next_type_frame
= frame
;
275 /* Ideally, this frame's sqn is 1 more than the highest SM sqn seen */
276 if (frame_entry
->sqn
<= transport
->sm_high_sqn
)
279 dup_sqn_entry
= lbtrm_transport_sqn_find(transport
, type
, frame_entry
->sqn
);
280 if (dup_sqn_entry
!= NULL
)
282 frame_entry
->duplicate
= true;
284 if (frame_entry
->sqn
!= transport
->sm_high_sqn
)
286 frame_entry
->ooo_gap
= transport
->sm_high_sqn
- frame_entry
->sqn
;
291 if (frame_entry
->sqn
!= (transport
->sm_high_sqn
+ 1))
294 frame_entry
->sqn_gap
= frame_entry
->sqn
- (transport
->sm_high_sqn
+ 1);
298 if (frame_entry
->sqn
> transport
->sm_high_sqn
)
300 transport
->sm_high_sqn
= frame_entry
->sqn
;
302 transport
->last_sm_frame
= frame_entry
;
304 case LBTRM_PACKET_TYPE_NAK
:
305 if (transport
->last_nak_frame
!= NULL
)
307 frame_entry
->previous_type_frame
= transport
->last_nak_frame
->frame
;
308 transport
->last_nak_frame
->next_type_frame
= frame
;
310 transport
->last_nak_frame
= frame_entry
;
312 case LBTRM_PACKET_TYPE_NCF
:
313 if (transport
->last_ncf_frame
!= NULL
)
315 frame_entry
->previous_type_frame
= transport
->last_ncf_frame
->frame
;
316 transport
->last_ncf_frame
->next_type_frame
= frame
;
318 transport
->last_ncf_frame
= frame_entry
;
323 (void)lbtrm_transport_sqn_add(transport
, frame_entry
);
324 return (frame_entry
);
327 static char * lbtrm_transport_source_string_format(wmem_allocator_t
*pool
, const address
* source_address
, uint16_t source_port
, uint32_t session_id
, const address
* multicast_group
, uint16_t dest_port
)
329 /* Returns a packet-scoped string. */
330 return (wmem_strdup_printf(pool
, "LBTRM:%s:%" PRIu16
":%08x:%s:%" PRIu16
, address_to_str(pool
, source_address
), source_port
, session_id
,
331 address_to_str(pool
, multicast_group
), dest_port
));
334 char * lbtrm_transport_source_string(const address
* source_address
, uint16_t source_port
, uint32_t session_id
, const address
* multicast_group
, uint16_t dest_port
)
336 /* Returns a file-scoped string. */
337 return lbtrm_transport_source_string_format(wmem_file_scope(), source_address
, source_port
, session_id
, multicast_group
, dest_port
);
340 static char * lbtrm_transport_source_string_transport(wmem_allocator_t
*pool
, lbtrm_transport_t
* transport
)
342 /* Returns a pool-scoped string. */
343 return (lbtrm_transport_source_string_format(pool
, &(transport
->source_address
), transport
->source_port
, transport
->session_id
, &(transport
->multicast_group
), transport
->dest_port
));
346 /*----------------------------------------------------------------------------*/
347 /* Packet definitions. */
348 /*----------------------------------------------------------------------------*/
350 /* LBT-RM main header */
353 lbm_uint8_t ver_type
;
354 lbm_uint8_t next_hdr
;
355 lbm_uint16_t ucast_port
;
356 lbm_uint32_t session_id
;
358 #define O_LBTRM_HDR_T_VER_TYPE OFFSETOF(lbtrm_hdr_t, ver_type)
359 #define L_LBTRM_HDR_T_VER_TYPE SIZEOF(lbtrm_hdr_t, ver_type)
360 #define O_LBTRM_HDR_T_NEXT_HDR OFFSETOF(lbtrm_hdr_t, next_hdr)
361 #define L_LBTRM_HDR_T_NEXT_HDR SIZEOF(lbtrm_hdr_t, next_hdr)
362 #define O_LBTRM_HDR_T_UCAST_PORT OFFSETOF(lbtrm_hdr_t, ucast_port)
363 #define L_LBTRM_HDR_T_UCAST_PORT SIZEOF(lbtrm_hdr_t, ucast_port)
364 #define O_LBTRM_HDR_T_SESSION_ID OFFSETOF(lbtrm_hdr_t, session_id)
365 #define L_LBTRM_HDR_T_SESSION_ID SIZEOF(lbtrm_hdr_t, session_id)
366 #define L_LBTRM_HDR_T (int) (sizeof(lbtrm_hdr_t))
368 #define LBTRM_VERSION 0x00
369 #define LBTRM_HDR_VER(x) (x >> 4)
370 #define LBTRM_HDR_TYPE(x) (x & 0x0F)
371 #define LBTRM_HDR_VER_MASK 0xF0
372 #define LBTRM_HDR_TYPE_MASK 0x0F
374 /* LBT-RM data header */
378 lbm_uint32_t trail_sqn
;
379 lbm_uint8_t flags_fec_type
;
380 lbm_uint8_t flags_tgsz
;
381 lbm_uint16_t fec_symbol
;
383 #define O_LBTRM_DATA_HDR_T_SQN OFFSETOF(lbtrm_data_hdr_t, sqn)
384 #define L_LBTRM_DATA_HDR_T_SQN SIZEOF(lbtrm_data_hdr_t, sqn)
385 #define O_LBTRM_DATA_HDR_T_TRAIL_SQN OFFSETOF(lbtrm_data_hdr_t, trail_sqn)
386 #define L_LBTRM_DATA_HDR_T_TRAIL_SQN SIZEOF(lbtrm_data_hdr_t, trail_sqn)
387 #define O_LBTRM_DATA_HDR_T_FLAGS_FEC_TYPE OFFSETOF(lbtrm_data_hdr_t, flags_fec_type)
388 #define L_LBTRM_DATA_HDR_T_FLAGS_FEC_TYPE SIZEOF(lbtrm_data_hdr_t, flags_fec_type)
389 #define O_LBTRM_DATA_HDR_T_FLAGS_TGSZ OFFSETOF(lbtrm_data_hdr_t, flags_tgsz)
390 #define L_LBTRM_DATA_HDR_T_FLAGS_TGSZ SIZEOF(lbtrm_data_hdr_t, flags_tgsz)
391 #define O_LBTRM_DATA_HDR_T_FEC_SYMBOL OFFSETOF(lbtrm_data_hdr_t, fec_symbol)
392 #define L_LBTRM_DATA_HDR_T_FEC_SYMBOL SIZEOF(lbtrm_data_hdr_t, fec_symbol)
393 #define L_LBTRM_DATA_HDR_T (int) (sizeof(lbtrm_data_hdr_t))
395 #define LBTRM_DATA_UNICAST_NAKS_FLAG 0x80
396 #define LBTRM_MULTICAST_NAKS_FLAG 0x40
397 #define LBTRM_DATA_RETRANSMISSION_FLAG 0x20
398 #define LBTRM_LATE_JOIN_FLAG 0x10
399 #define LBTRM_FEC_TYPE_MASK 0xF
400 #define LBTRM_DATA_FLAGS(x) (x >> 4)
401 #define LBTRM_DATA_FLAGS_MASK 0xF0
403 /* LBT-RM Session Message header */
407 lbm_uint32_t lead_sqn
;
408 lbm_uint32_t trail_sqn
;
409 lbm_uint8_t flags_fec_type
;
410 lbm_uint8_t flags_tgsz
;
411 lbm_uint16_t reserved
;
413 #define O_LBTRM_SM_HDR_T_SM_SQN OFFSETOF(lbtrm_sm_hdr_t, sm_sqn)
414 #define L_LBTRM_SM_HDR_T_SM_SQN SIZEOF(lbtrm_sm_hdr_t, sm_sqn)
415 #define O_LBTRM_SM_HDR_T_LEAD_SQN OFFSETOF(lbtrm_sm_hdr_t, lead_sqn)
416 #define L_LBTRM_SM_HDR_T_LEAD_SQN SIZEOF(lbtrm_sm_hdr_t, lead_sqn)
417 #define O_LBTRM_SM_HDR_T_TRAIL_SQN OFFSETOF(lbtrm_sm_hdr_t, trail_sqn)
418 #define L_LBTRM_SM_HDR_T_TRAIL_SQN SIZEOF(lbtrm_sm_hdr_t, trail_sqn)
419 #define O_LBTRM_SM_HDR_T_FLAGS_FEC_TYPE OFFSETOF(lbtrm_sm_hdr_t, flags_fec_type)
420 #define L_LBTRM_SM_HDR_T_FLAGS_FEC_TYPE SIZEOF(lbtrm_sm_hdr_t, flags_fec_type)
421 #define O_LBTRM_SM_HDR_T_FLAGS_TGSZ OFFSETOF(lbtrm_sm_hdr_t, flags_tgsz)
422 #define L_LBTRM_SM_HDR_T_FLAGS_TGSZ SIZEOF(lbtrm_sm_hdr_t, flags_tgsz)
423 #define O_LBTRM_SM_HDR_T_RESERVED OFFSETOF(lbtrm_sm_hdr_t, reserved)
424 #define L_LBTRM_SM_HDR_T_RESERVED SIZEOF(lbtrm_sm_hdr_t, reserved)
425 #define L_LBTRM_SM_HDR_T (int) (sizeof(lbtrm_sm_hdr_t))
427 #define LBTRM_SM_UNICAST_NAKS_FLAG 0x80
428 #define LBTRM_SM_FLAGS(x) (x >> 4)
429 #define LBTRM_SM_FLAGS_MASK 0xF0
431 /* LBT-RM NAK header */
434 lbm_uint16_t num_naks
;
437 #define O_LBTRM_NAK_HDR_T_NUM_NAKS OFFSETOF(lbtrm_nak_hdr_t, num_naks)
438 #define L_LBTRM_NAK_HDR_T_NUM_NAKS SIZEOF(lbtrm_nak_hdr_t, num_naks)
439 #define O_LBTRM_NAK_HDR_T_FORMAT OFFSETOF(lbtrm_nak_hdr_t, format)
440 #define L_LBTRM_NAK_HDR_T_FORMAT SIZEOF(lbtrm_nak_hdr_t, format)
441 #define L_LBTRM_NAK_HDR_T (int) (sizeof(lbtrm_nak_hdr_t))
443 #define LBTRM_NAK_SELECTIVE_FORMAT 0x0
444 #define LBTRM_NAK_PARITY_FORMAT 0x1
445 #define LBTRM_NAK_HDR_FORMAT(x) (x & 0xF)
446 #define LBTRM_NAK_HDR_FORMAT_MASK 0x0F
448 /* LBT-RM NAK Confirmation */
451 lbm_uint32_t trail_sqn
;
452 lbm_uint16_t num_ncfs
;
453 lbm_uint8_t reserved
;
454 lbm_uint8_t reason_format
;
456 #define O_LBTRM_NCF_HDR_T_TRAIL_SQN OFFSETOF(lbtrm_ncf_hdr_t, trail_sqn)
457 #define L_LBTRM_NCF_HDR_T_TRAIL_SQN SIZEOF(lbtrm_ncf_hdr_t, trail_sqn)
458 #define O_LBTRM_NCF_HDR_T_NUM_NCFS OFFSETOF(lbtrm_ncf_hdr_t, num_ncfs)
459 #define L_LBTRM_NCF_HDR_T_NUM_NCFS SIZEOF(lbtrm_ncf_hdr_t, num_ncfs)
460 #define O_LBTRM_NCF_HDR_T_RESERVED OFFSETOF(lbtrm_ncf_hdr_t, reserved)
461 #define L_LBTRM_NCF_HDR_T_RESERVED SIZEOF(lbtrm_ncf_hdr_t, reserved)
462 #define O_LBTRM_NCF_HDR_T_REASON_FORMAT OFFSETOF(lbtrm_ncf_hdr_t, reason_format)
463 #define L_LBTRM_NCF_HDR_T_REASON_FORMAT SIZEOF(lbtrm_ncf_hdr_t, reason_format)
464 #define L_LBTRM_NCF_HDR_T (int) (sizeof(lbtrm_ncf_hdr_t))
466 #define LBTRM_NCF_SELECTIVE_FORMAT 0x0
467 #define LBTRM_NCF_PARITY_FORMAT 0x1
468 #define LBTRM_NCF_HDR_REASON(x) ((x & 0xF0) >> 4)
469 #define LBTRM_NCF_HDR_FORMAT(x) (x & 0xF)
470 #define LBTRM_NCF_HDR_REASON_MASK 0xF0
471 #define LBTRM_NCF_HDR_FORMAT_MASK 0x0F
473 /* LBT-RM option header */
476 lbm_uint8_t next_hdr
;
480 #define O_LBTRM_BASIC_OPT_T_NEXT_HDR OFFSETOF(lbtrm_basic_opt_t, next_hdr)
481 #define L_LBTRM_BASIC_OPT_T_NEXT_HDR SIZEOF(lbtrm_basic_opt_t, next_hdr)
482 #define O_LBTRM_BASIC_OPT_T_HDR_LEN OFFSETOF(lbtrm_basic_opt_t, hdr_len)
483 #define L_LBTRM_BASIC_OPT_T_HDR_LEN SIZEOF(lbtrm_basic_opt_t, hdr_len)
484 #define O_LBTRM_BASIC_OPT_T_RES OFFSETOF(lbtrm_basic_opt_t, res)
485 #define L_LBTRM_BASIC_OPT_T_RES SIZEOF(lbtrm_basic_opt_t, res)
486 #define L_LBTRM_BASIC_OPT_T (int) (sizeof(lbtrm_basic_opt_t))
488 #define LBTRM_NHDR_DATA 0x0
490 /*----------------------------------------------------------------------------*/
491 /* Value translation tables. */
492 /*----------------------------------------------------------------------------*/
494 static const value_string lbtrm_packet_type
[] =
496 { LBTRM_PACKET_TYPE_DATA
, "DATA" },
497 { LBTRM_PACKET_TYPE_SM
, "SM" },
498 { LBTRM_PACKET_TYPE_NAK
, "NAK" },
499 { LBTRM_PACKET_TYPE_NCF
, "NCF" },
503 static const value_string lbtrm_nak_format
[] =
505 { LBTRM_NAK_SELECTIVE_FORMAT
, "Selective" },
506 { LBTRM_NAK_PARITY_FORMAT
, "Parity" },
510 static const value_string lbtrm_ncf_format
[] =
512 { LBTRM_NCF_SELECTIVE_FORMAT
, "Selective" },
513 { LBTRM_NCF_PARITY_FORMAT
, "Parity" },
517 static const value_string lbtrm_ncf_reason
[] =
519 { LBTRM_NCF_REASON_NO_RETRY
, "Do not retry" },
520 { LBTRM_NCF_REASON_IGNORED
, "NAK Ignored" },
521 { LBTRM_NCF_REASON_RX_DELAY
, "Retransmit Delay" },
522 { LBTRM_NCF_REASON_SHED
, "NAK Shed" },
526 static const value_string lbtrm_next_header
[] =
528 { LBTRM_NHDR_DATA
, "Data" },
532 /*----------------------------------------------------------------------------*/
534 /*----------------------------------------------------------------------------*/
536 /* Preferences default values. */
537 #define LBTRM_DEFAULT_DPORT_LOW 14400
538 #define LBTRM_DEFAULT_DPORT_HIGH 14400
539 #define LBTRM_DEFAULT_SPORT_HIGH 14399
540 #define LBTRM_DEFAULT_SPORT_LOW 14390
541 #define LBTRM_DEFAULT_MC_ADDRESS_LOW "224.10.10.10"
542 #define LBTRM_DEFAULT_MC_ADDRESS_HIGH "224.10.10.14"
543 #define MIM_DEFAULT_INCOMING_DPORT 14401
544 #define MIM_DEFAULT_OUTGOING_DPORT 14401
545 #define MIM_DEFAULT_MC_INCOMING_ADDRESS "224.10.10.21"
546 #define MIM_DEFAULT_MC_OUTGOING_ADDRESS "224.10.10.21"
548 /* Global preferences variables (altered by the preferences dialog). */
549 static const char * global_lbtrm_mc_address_low
= LBTRM_DEFAULT_MC_ADDRESS_LOW
;
550 static const char * global_lbtrm_mc_address_high
= LBTRM_DEFAULT_MC_ADDRESS_HIGH
;
551 static uint32_t global_lbtrm_dest_port_low
= LBTRM_DEFAULT_DPORT_LOW
;
552 static uint32_t global_lbtrm_dest_port_high
= LBTRM_DEFAULT_DPORT_HIGH
;
553 static uint32_t global_lbtrm_src_port_low
= LBTRM_DEFAULT_SPORT_LOW
;
554 static uint32_t global_lbtrm_src_port_high
= LBTRM_DEFAULT_SPORT_HIGH
;
555 static uint32_t global_mim_incoming_dest_port
= MIM_DEFAULT_INCOMING_DPORT
;
556 static uint32_t global_mim_outgoing_dest_port
= MIM_DEFAULT_OUTGOING_DPORT
;
557 static const char * global_mim_incoming_mc_address
= MIM_DEFAULT_MC_INCOMING_ADDRESS
;
558 static const char * global_mim_outgoing_mc_address
= MIM_DEFAULT_MC_OUTGOING_ADDRESS
;
559 static bool global_lbtrm_expert_separate_naks
;
560 static bool global_lbtrm_expert_separate_ncfs
;
561 static bool global_lbtrm_use_tag
;
562 static bool global_lbtrm_sequence_analysis
;
564 /* Local preferences variables (used by the dissector). */
565 static uint32_t lbtrm_mc_address_low_host
;
566 static uint32_t lbtrm_mc_address_high_host
;
567 static uint32_t lbtrm_dest_port_low
= LBTRM_DEFAULT_DPORT_LOW
;
568 static uint32_t lbtrm_dest_port_high
= LBTRM_DEFAULT_DPORT_HIGH
;
569 static uint32_t lbtrm_src_port_low
= LBTRM_DEFAULT_SPORT_LOW
;
570 static uint32_t lbtrm_src_port_high
= LBTRM_DEFAULT_SPORT_HIGH
;
571 static uint32_t mim_incoming_dest_port
= MIM_DEFAULT_INCOMING_DPORT
;
572 static uint32_t mim_outgoing_dest_port
= MIM_DEFAULT_OUTGOING_DPORT
;
573 static uint32_t mim_incoming_mc_address_host
;
574 static uint32_t mim_outgoing_mc_address_host
;
575 static bool lbtrm_expert_separate_naks
;
576 static bool lbtrm_expert_separate_ncfs
;
577 static bool lbtrm_use_tag
;
578 static bool lbtrm_sequence_analysis
;
580 /*----------------------------------------------------------------------------*/
581 /* Tag management. */
582 /*----------------------------------------------------------------------------*/
586 char * mc_address_low
;
587 uint32_t mc_address_low_val_h
;
588 char * mc_address_high
;
589 uint32_t mc_address_high_val_h
;
594 uint32_t mim_incoming_dport
;
595 uint32_t mim_outgoing_dport
;
596 char * mim_mc_incoming_address
;
597 uint32_t mim_mc_incoming_address_val_h
;
598 char * mim_mc_outgoing_address
;
599 uint32_t mim_mc_outgoing_address_val_h
;
602 static lbtrm_tag_entry_t
* lbtrm_tag_entry
;
603 static unsigned lbtrm_tag_count
;
605 UAT_CSTRING_CB_DEF(lbtrm_tag
, name
, lbtrm_tag_entry_t
)
606 UAT_IPV4_MC_CB_DEF(lbtrm_tag
, mc_address_low
, lbtrm_tag_entry_t
)
607 UAT_IPV4_MC_CB_DEF(lbtrm_tag
, mc_address_high
, lbtrm_tag_entry_t
)
608 UAT_DEC_CB_DEF(lbtrm_tag
, dport_low
, lbtrm_tag_entry_t
)
609 UAT_DEC_CB_DEF(lbtrm_tag
, dport_high
, lbtrm_tag_entry_t
)
610 UAT_DEC_CB_DEF(lbtrm_tag
, sport_low
, lbtrm_tag_entry_t
)
611 UAT_DEC_CB_DEF(lbtrm_tag
, sport_high
, lbtrm_tag_entry_t
)
612 UAT_DEC_CB_DEF(lbtrm_tag
, mim_incoming_dport
, lbtrm_tag_entry_t
)
613 UAT_DEC_CB_DEF(lbtrm_tag
, mim_outgoing_dport
, lbtrm_tag_entry_t
)
614 UAT_IPV4_MC_CB_DEF(lbtrm_tag
, mim_mc_incoming_address
, lbtrm_tag_entry_t
)
615 UAT_IPV4_MC_CB_DEF(lbtrm_tag
, mim_mc_outgoing_address
, lbtrm_tag_entry_t
)
616 static uat_field_t lbtrm_tag_array
[] =
618 UAT_FLD_CSTRING(lbtrm_tag
, name
, "Tag name", "Tag name"),
619 UAT_FLD_IPV4_MC(lbtrm_tag
, mc_address_low
, "Multicast address low", "Multicast address low"),
620 UAT_FLD_IPV4_MC(lbtrm_tag
, mc_address_high
, "Multicast address high", "Multicast address high"),
621 UAT_FLD_DEC(lbtrm_tag
, dport_low
, "Destination port low", "Destination port low"),
622 UAT_FLD_DEC(lbtrm_tag
, dport_high
, "Destination port high", "Destination port high"),
623 UAT_FLD_DEC(lbtrm_tag
, sport_low
, "Source port low", "Source port low"),
624 UAT_FLD_DEC(lbtrm_tag
, sport_high
, "Source port high", "Source port high"),
625 UAT_FLD_DEC(lbtrm_tag
, mim_incoming_dport
, "MIM incoming destination port", "MIM incoming destination port"),
626 UAT_FLD_DEC(lbtrm_tag
, mim_outgoing_dport
, "MIM outgoing destination port", "MIM outgoing destination port"),
627 UAT_FLD_IPV4_MC(lbtrm_tag
, mim_mc_incoming_address
, "MIM incoming multicast address", "MIM incoming multicast address"),
628 UAT_FLD_IPV4_MC(lbtrm_tag
, mim_mc_outgoing_address
, "MIM outgoing multicast address", "MIM outgoing multicast address"),
632 /*----------------------------------------------------------------------------*/
633 /* UAT callback functions. */
634 /*----------------------------------------------------------------------------*/
635 static bool lbtrm_tag_update_cb(void * record
, char * * error_string
)
637 lbtrm_tag_entry_t
* tag
= (lbtrm_tag_entry_t
*)record
;
639 if (tag
->name
== NULL
)
641 *error_string
= g_strdup("Tag name can't be empty");
646 g_strstrip(tag
->name
);
647 if (tag
->name
[0] == 0)
649 *error_string
= g_strdup("Tag name can't be empty");
656 static void * lbtrm_tag_copy_cb(void * destination
, const void * source
, size_t length _U_
)
658 const lbtrm_tag_entry_t
* src
= (const lbtrm_tag_entry_t
*)source
;
659 lbtrm_tag_entry_t
* dest
= (lbtrm_tag_entry_t
*)destination
;
661 dest
->name
= g_strdup(src
->name
);
662 dest
->mc_address_low
= g_strdup(src
->mc_address_low
);
663 dest
->mc_address_low_val_h
= src
->mc_address_low_val_h
;
664 dest
->mc_address_high
= g_strdup(src
->mc_address_high
);
665 dest
->mc_address_high_val_h
= src
->mc_address_high_val_h
;
666 dest
->dport_low
= src
->dport_low
;
667 dest
->dport_high
= src
->dport_high
;
668 dest
->sport_low
= src
->sport_low
;
669 dest
->sport_high
= src
->sport_high
;
670 dest
->mim_incoming_dport
= src
->mim_incoming_dport
;
671 dest
->mim_outgoing_dport
= src
->mim_outgoing_dport
;
672 dest
->mim_mc_incoming_address
= g_strdup(src
->mim_mc_incoming_address
);
673 dest
->mim_mc_incoming_address_val_h
= src
->mim_mc_incoming_address_val_h
;
674 dest
->mim_mc_outgoing_address
= g_strdup(src
->mim_mc_outgoing_address
);
675 dest
->mim_mc_outgoing_address_val_h
= src
->mim_mc_outgoing_address_val_h
;
679 static void lbtrm_tag_free_cb(void * record
)
681 lbtrm_tag_entry_t
* tag
= (lbtrm_tag_entry_t
*)record
;
683 if (tag
->name
!= NULL
)
688 if (tag
->mc_address_low
!= NULL
)
690 g_free(tag
->mc_address_low
);
691 tag
->mc_address_low
= NULL
;
693 if (tag
->mc_address_high
!= NULL
)
695 g_free(tag
->mc_address_high
);
696 tag
->mc_address_high
= NULL
;
698 if (tag
->mim_mc_incoming_address
!= NULL
)
700 g_free(tag
->mim_mc_incoming_address
);
701 tag
->mim_mc_incoming_address
= NULL
;
703 if (tag
->mim_mc_outgoing_address
!= NULL
)
705 g_free(tag
->mim_mc_outgoing_address
);
706 tag
->mim_mc_outgoing_address
= NULL
;
710 static char * lbtrm_tag_find(packet_info
* pinfo
)
713 lbtrm_tag_entry_t
* tag
= NULL
;
714 uint32_t dest_addr_h
;
721 dest_addr_h
= pntoh32(pinfo
->dst
.data
);
722 for (idx
= 0; idx
< lbtrm_tag_count
; ++idx
)
724 tag
= &(lbtrm_tag_entry
[idx
]);
725 /* Is the destination a multicast address? */
726 if (IN_MULTICAST(dest_addr_h
))
728 /* Check the MC address. */
729 if ((dest_addr_h
>= tag
->mc_address_low_val_h
) && (dest_addr_h
<= tag
->mc_address_high_val_h
))
731 /* It's in the LBT-RM multicast range. Check the ports. */
732 if ((pinfo
->destport
>= tag
->dport_low
) && (pinfo
->destport
<= tag
->dport_high
))
734 /* Must be one of ours. */
738 else if ((dest_addr_h
== tag
->mim_mc_incoming_address_val_h
) || (dest_addr_h
== tag
->mim_mc_outgoing_address_val_h
))
740 /* Might be MIM. Check the port. */
741 if (((dest_addr_h
== tag
->mim_mc_incoming_address_val_h
) && (pinfo
->destport
== tag
->mim_incoming_dport
))
742 || ((dest_addr_h
== tag
->mim_mc_outgoing_address_val_h
) && (pinfo
->destport
== tag
->mim_outgoing_dport
)))
744 /* Must be one of ours. */
753 /* Not multicast, might be a unicast UDP NAK. Check the destination port. */
754 if ((pinfo
->destport
< tag
->sport_low
) || (pinfo
->destport
> tag
->sport_high
))
759 /* One of ours, so handle it. */
763 /* Not one of ours. */
767 /*----------------------------------------------------------------------------*/
768 /* Handles of all types. */
769 /*----------------------------------------------------------------------------*/
771 /* Dissector tree handles */
772 static int ett_lbtrm
;
773 static int ett_lbtrm_hdr
;
774 static int ett_lbtrm_data
;
775 static int ett_lbtrm_data_flags_fec_type
;
776 static int ett_lbtrm_sm
;
777 static int ett_lbtrm_sm_flags_fec_type
;
778 static int ett_lbtrm_nak
;
779 static int ett_lbtrm_nak_list
;
780 static int ett_lbtrm_ncf
;
781 static int ett_lbtrm_ncf_list
;
782 static int ett_lbtrm_transport
;
783 static int ett_lbtrm_transport_sqn
;
785 /* Dissector field handles */
786 static int hf_lbtrm_channel
;
787 static int hf_lbtrm_tag
;
788 static int hf_lbtrm_hdr
;
789 static int hf_lbtrm_hdr_ver
;
790 static int hf_lbtrm_hdr_type
;
791 static int hf_lbtrm_hdr_next_hdr
;
792 static int hf_lbtrm_hdr_ucast_port
;
793 static int hf_lbtrm_hdr_session_id
;
794 static int hf_lbtrm_data
;
795 static int hf_lbtrm_data_sqn
;
796 static int hf_lbtrm_data_trail_sqn
;
797 static int hf_lbtrm_data_flags_fec_type
;
798 static int hf_lbtrm_data_flags_fec_type_ucast_naks
;
799 static int hf_lbtrm_data_flags_fec_type_rx
;
800 static int hf_lbtrm_data_flags_tgsz
;
801 static int hf_lbtrm_data_fec_symbol
;
802 static int hf_lbtrm_sm
;
803 static int hf_lbtrm_sm_sm_sqn
;
804 static int hf_lbtrm_sm_lead_sqn
;
805 static int hf_lbtrm_sm_trail_sqn
;
806 static int hf_lbtrm_sm_flags_fec_type
;
807 static int hf_lbtrm_sm_flags_fec_type_ucast_naks
;
808 static int hf_lbtrm_sm_flags_tgsz
;
809 static int hf_lbtrm_sm_reserved
;
810 static int hf_lbtrm_nak
;
811 static int hf_lbtrm_nak_num_naks
;
812 static int hf_lbtrm_nak_format
;
813 static int hf_lbtrm_nak_list
;
814 static int hf_lbtrm_nak_list_nak
;
815 static int hf_lbtrm_ncf
;
816 static int hf_lbtrm_ncf_trail_sqn
;
817 static int hf_lbtrm_ncf_num_ncfs
;
818 static int hf_lbtrm_ncf_reserved
;
819 static int hf_lbtrm_ncf_reason
;
820 static int hf_lbtrm_ncf_format
;
821 static int hf_lbtrm_ncf_list
;
822 static int hf_lbtrm_ncf_list_ncf
;
823 static int hf_lbtrm_analysis
;
824 static int hf_lbtrm_analysis_prev_frame
;
825 static int hf_lbtrm_analysis_prev_data_frame
;
826 static int hf_lbtrm_analysis_prev_sm_frame
;
827 static int hf_lbtrm_analysis_prev_nak_frame
;
828 static int hf_lbtrm_analysis_prev_ncf_frame
;
829 static int hf_lbtrm_analysis_next_frame
;
830 static int hf_lbtrm_analysis_next_data_frame
;
831 static int hf_lbtrm_analysis_next_sm_frame
;
832 static int hf_lbtrm_analysis_next_nak_frame
;
833 static int hf_lbtrm_analysis_next_ncf_frame
;
834 static int hf_lbtrm_analysis_sqn
;
835 static int hf_lbtrm_analysis_sqn_frame
;
836 static int hf_lbtrm_analysis_data_retransmission
;
837 static int hf_lbtrm_analysis_data_sqn_gap
;
838 static int hf_lbtrm_analysis_data_ooo_gap
;
839 static int hf_lbtrm_analysis_data_duplicate
;
840 static int hf_lbtrm_analysis_sm_sqn_gap
;
841 static int hf_lbtrm_analysis_sm_ooo_gap
;
842 static int hf_lbtrm_analysis_sm_duplicate
;
844 /* Expert info handles */
845 static expert_field ei_lbtrm_analysis_ncf
;
846 static expert_field ei_lbtrm_analysis_ncf_ncf
;
847 static expert_field ei_lbtrm_analysis_nak
;
848 static expert_field ei_lbtrm_analysis_nak_nak
;
849 static expert_field ei_lbtrm_analysis_sm
;
850 static expert_field ei_lbtrm_analysis_rx
;
851 static expert_field ei_lbtrm_analysis_invalid_value
;
852 static expert_field ei_lbtrm_analysis_data_rx
;
853 static expert_field ei_lbtrm_analysis_data_gap
;
854 static expert_field ei_lbtrm_analysis_data_ooo
;
855 static expert_field ei_lbtrm_analysis_data_dup
;
856 static expert_field ei_lbtrm_analysis_sm_gap
;
857 static expert_field ei_lbtrm_analysis_sm_ooo
;
858 static expert_field ei_lbtrm_analysis_sm_dup
;
860 /*----------------------------------------------------------------------------*/
861 /* LBT-RM data payload dissection functions. */
862 /*----------------------------------------------------------------------------*/
863 static int dissect_lbtrm_data_contents(tvbuff_t
* tvb
, int offset
, packet_info
* pinfo
, proto_tree
* tree
, const char * tag_name
, uint64_t channel
)
867 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
868 return (lbmc_dissect_lbmc_packet(next_tvb
, 0, pinfo
, tree
, tag_name
, channel
));
871 /*----------------------------------------------------------------------------*/
872 /* LBT-RM NAK confirmation packet dissection functions. */
873 /*----------------------------------------------------------------------------*/
874 static int dissect_lbtrm_ncf_list(tvbuff_t
* tvb
, int offset
, packet_info
* pinfo
, proto_tree
* tree
, int ncf_count
, int reason
, lbm_lbtrm_tap_info_t
* tap_info
)
876 proto_tree
* ncf_tree
= NULL
;
877 proto_item
* ncf_item
= NULL
;
882 ncf_item
= proto_tree_add_item(tree
, hf_lbtrm_ncf_list
, tvb
, offset
+ len
, (int)(sizeof(lbm_uint32_t
) * ncf_count
), ENC_NA
);
883 ncf_tree
= proto_item_add_subtree(ncf_item
, ett_lbtrm_ncf_list
);
885 for (idx
= 0; idx
< ncf_count
; idx
++)
887 proto_item
* sep_ncf_item
= NULL
;
889 ncf
= tvb_get_ntohl(tvb
, offset
+ len
);
890 sep_ncf_item
= proto_tree_add_item(ncf_tree
, hf_lbtrm_ncf_list_ncf
, tvb
, offset
+ len
, sizeof(lbm_uint32_t
), ENC_BIG_ENDIAN
);
891 if (lbtrm_expert_separate_ncfs
)
893 expert_add_info_format(pinfo
, sep_ncf_item
, &ei_lbtrm_analysis_ncf_ncf
, "NCF 0x%08x %s", ncf
, val_to_str(reason
, lbtrm_ncf_reason
, "Unknown (0x%02x)"));
895 tap_info
->sqns
[idx
] = ncf
;
901 static int dissect_lbtrm_ncf(tvbuff_t
* tvb
, int offset
, packet_info
* pinfo
, proto_tree
* tree
, lbm_lbtrm_tap_info_t
* tap_info
)
906 proto_tree
* ncf_tree
= NULL
;
907 proto_item
* ncf_item
= NULL
;
908 proto_item
* reason_item
= NULL
;
910 ncf_item
= proto_tree_add_item(tree
, hf_lbtrm_ncf
, tvb
, offset
, -1, ENC_NA
);
911 ncf_tree
= proto_item_add_subtree(ncf_item
, ett_lbtrm_ncf
);
912 num_ncfs
= tvb_get_ntohs(tvb
, offset
+ O_LBTRM_NCF_HDR_T_NUM_NCFS
);
913 reason
= tvb_get_uint8(tvb
, offset
+ O_LBTRM_NCF_HDR_T_REASON_FORMAT
);
914 proto_tree_add_item(ncf_tree
, hf_lbtrm_ncf_trail_sqn
, tvb
, offset
+ O_LBTRM_NCF_HDR_T_TRAIL_SQN
, L_LBTRM_NCF_HDR_T_TRAIL_SQN
, ENC_BIG_ENDIAN
);
915 proto_tree_add_item(ncf_tree
, hf_lbtrm_ncf_num_ncfs
, tvb
, offset
+ O_LBTRM_NCF_HDR_T_NUM_NCFS
, L_LBTRM_NCF_HDR_T_NUM_NCFS
, ENC_BIG_ENDIAN
);
916 proto_tree_add_item(ncf_tree
, hf_lbtrm_ncf_reserved
, tvb
, offset
+ O_LBTRM_NCF_HDR_T_RESERVED
, L_LBTRM_NCF_HDR_T_RESERVED
, ENC_BIG_ENDIAN
);
917 proto_tree_add_item(ncf_tree
, hf_lbtrm_ncf_reason
, tvb
, offset
+ O_LBTRM_NCF_HDR_T_REASON_FORMAT
, L_LBTRM_NCF_HDR_T_REASON_FORMAT
, ENC_BIG_ENDIAN
);
918 proto_tree_add_item(ncf_tree
, hf_lbtrm_ncf_format
, tvb
, offset
+ O_LBTRM_NCF_HDR_T_REASON_FORMAT
, L_LBTRM_NCF_HDR_T_REASON_FORMAT
, ENC_BIG_ENDIAN
);
919 len
= L_LBTRM_NCF_HDR_T
;
920 if (!lbtrm_expert_separate_ncfs
)
922 expert_add_info_format(pinfo
, reason_item
, &ei_lbtrm_analysis_ncf
, "NCF %s", val_to_str(LBTRM_NCF_HDR_REASON(reason
), lbtrm_ncf_reason
, "Unknown (0x%02x)"));
924 tap_info
->ncf_reason
= LBTRM_NCF_HDR_REASON(reason
);
925 tap_info
->num_sqns
= num_ncfs
;
926 tap_info
->sqns
= wmem_alloc_array(pinfo
->pool
, uint32_t, num_ncfs
);
927 len
+= dissect_lbtrm_ncf_list(tvb
, offset
+ len
, pinfo
, ncf_tree
, num_ncfs
, LBTRM_NCF_HDR_REASON(reason
), tap_info
);
928 proto_item_set_len(ncf_item
, len
);
932 /*----------------------------------------------------------------------------*/
933 /* LBT-RM NAK packet dissection functions. */
934 /*----------------------------------------------------------------------------*/
935 static int dissect_lbtrm_nak_list(tvbuff_t
* tvb
, int offset
, packet_info
* pinfo
, proto_tree
* tree
, int nak_count
, lbm_lbtrm_tap_info_t
* tap_info
)
937 proto_tree
* nak_tree
= NULL
;
938 proto_item
* nak_item
= NULL
;
943 nak_item
= proto_tree_add_item(tree
, hf_lbtrm_nak_list
, tvb
, offset
+ len
, (int)(sizeof(lbm_uint32_t
) * nak_count
), ENC_NA
);
944 nak_tree
= proto_item_add_subtree(nak_item
, ett_lbtrm_nak_list
);
946 for (idx
= 0; idx
< nak_count
; idx
++)
948 proto_item
* sep_nak_item
= NULL
;
950 nak
= tvb_get_ntohl(tvb
, offset
+ len
);
951 sep_nak_item
= proto_tree_add_item(nak_tree
, hf_lbtrm_nak_list_nak
, tvb
, offset
+ len
, sizeof(lbm_uint32_t
), ENC_BIG_ENDIAN
);
952 if (lbtrm_expert_separate_naks
)
954 expert_add_info_format(pinfo
, sep_nak_item
, &ei_lbtrm_analysis_nak_nak
, "NAK 0x%08x", nak
);
956 tap_info
->sqns
[idx
] = nak
;
962 static int dissect_lbtrm_nak(tvbuff_t
* tvb
, int offset
, packet_info
* pinfo
, proto_tree
* tree
, lbm_lbtrm_tap_info_t
* tap_info
)
966 proto_tree
* nak_tree
= NULL
;
967 proto_item
* nak_item
= NULL
;
969 nak_item
= proto_tree_add_item(tree
, hf_lbtrm_nak
, tvb
, offset
, -1, ENC_NA
);
970 nak_tree
= proto_item_add_subtree(nak_item
, ett_lbtrm_nak
);
971 num_naks
= tvb_get_ntohs(tvb
, offset
+ O_LBTRM_NAK_HDR_T_NUM_NAKS
);
972 proto_tree_add_item(nak_tree
, hf_lbtrm_nak_num_naks
, tvb
, offset
+ O_LBTRM_NAK_HDR_T_NUM_NAKS
, L_LBTRM_NAK_HDR_T_NUM_NAKS
, ENC_BIG_ENDIAN
);
973 proto_tree_add_item(nak_tree
, hf_lbtrm_nak_format
, tvb
, offset
+ O_LBTRM_NAK_HDR_T_FORMAT
, L_LBTRM_NAK_HDR_T_FORMAT
, ENC_BIG_ENDIAN
);
974 len
= L_LBTRM_NAK_HDR_T
;
975 if (!lbtrm_expert_separate_naks
)
977 expert_add_info(pinfo
, nak_item
, &ei_lbtrm_analysis_nak
);
979 tap_info
->num_sqns
= num_naks
;
980 tap_info
->sqns
= wmem_alloc_array(pinfo
->pool
, uint32_t, num_naks
);
981 len
+= dissect_lbtrm_nak_list(tvb
, offset
+ len
, pinfo
, nak_tree
, num_naks
, tap_info
);
982 proto_item_set_len(nak_item
, len
);
986 /*----------------------------------------------------------------------------*/
987 /* LBT-RM session message packet dissection functions. */
988 /*----------------------------------------------------------------------------*/
989 static int dissect_lbtrm_sm(tvbuff_t
* tvb
, int offset
, packet_info
* pinfo
, proto_tree
* tree
, uint32_t * sequence
, lbm_lbtrm_tap_info_t
* tap_info
)
991 proto_tree
* sm_tree
= NULL
;
992 proto_item
* sm_item
= NULL
;
993 static int * const flags
[] =
995 &hf_lbtrm_sm_flags_fec_type_ucast_naks
,
998 proto_item
* sm_sqn_item
= NULL
;
1001 sm_item
= proto_tree_add_item(tree
, hf_lbtrm_sm
, tvb
, offset
, L_LBTRM_SM_HDR_T
, ENC_NA
);
1002 sm_tree
= proto_item_add_subtree(sm_item
, ett_lbtrm_sm
);
1003 sm_sqn_item
= proto_tree_add_item(sm_tree
, hf_lbtrm_sm_sm_sqn
, tvb
, offset
+ O_LBTRM_SM_HDR_T_SM_SQN
, L_LBTRM_SM_HDR_T_SM_SQN
, ENC_BIG_ENDIAN
);
1004 proto_tree_add_item(sm_tree
, hf_lbtrm_sm_lead_sqn
, tvb
, offset
+ O_LBTRM_SM_HDR_T_LEAD_SQN
, L_LBTRM_SM_HDR_T_LEAD_SQN
, ENC_BIG_ENDIAN
);
1005 proto_tree_add_item(sm_tree
, hf_lbtrm_sm_trail_sqn
, tvb
, offset
+ O_LBTRM_SM_HDR_T_TRAIL_SQN
, L_LBTRM_SM_HDR_T_TRAIL_SQN
, ENC_BIG_ENDIAN
);
1006 proto_tree_add_bitmask(sm_tree
, tvb
, offset
+ O_LBTRM_SM_HDR_T_FLAGS_FEC_TYPE
, hf_lbtrm_sm_flags_fec_type
, ett_lbtrm_sm_flags_fec_type
, flags
, ENC_BIG_ENDIAN
);
1007 proto_tree_add_item(sm_tree
, hf_lbtrm_sm_flags_tgsz
, tvb
, offset
+ O_LBTRM_SM_HDR_T_FLAGS_TGSZ
, L_LBTRM_SM_HDR_T_FLAGS_TGSZ
, ENC_BIG_ENDIAN
);
1008 proto_tree_add_item(sm_tree
, hf_lbtrm_sm_reserved
, tvb
, offset
+ O_LBTRM_SM_HDR_T_RESERVED
, L_LBTRM_SM_HDR_T_RESERVED
, ENC_BIG_ENDIAN
);
1009 sqn
= tvb_get_ntohl(tvb
, offset
+ O_LBTRM_SM_HDR_T_SM_SQN
);
1010 expert_add_info(pinfo
, sm_sqn_item
, &ei_lbtrm_analysis_sm
);
1011 if (sequence
!= NULL
)
1015 tap_info
->sqn
= sqn
;
1016 return (L_LBTRM_SM_HDR_T
);
1019 /*----------------------------------------------------------------------------*/
1020 /* LBT-RM data packet dissection functions. */
1021 /*----------------------------------------------------------------------------*/
1022 static int dissect_lbtrm_data(tvbuff_t
* tvb
, int offset
, packet_info
* pinfo
, proto_tree
* tree
, uint32_t * sequence
, bool * retransmission
, lbm_lbtrm_tap_info_t
* tap_info
)
1024 proto_tree
* data_tree
= NULL
;
1025 proto_item
* data_item
= NULL
;
1026 static int * const flags
[] =
1028 &hf_lbtrm_data_flags_fec_type_ucast_naks
,
1029 &hf_lbtrm_data_flags_fec_type_rx
,
1032 proto_item
* sqn_item
= NULL
;
1035 bool is_retransmission
= false;
1037 data_item
= proto_tree_add_item(tree
, hf_lbtrm_data
, tvb
, offset
, L_LBTRM_DATA_HDR_T
, ENC_NA
);
1038 data_tree
= proto_item_add_subtree(data_item
, ett_lbtrm_data
);
1039 sqn_item
= proto_tree_add_item(data_tree
, hf_lbtrm_data_sqn
, tvb
, offset
+ O_LBTRM_DATA_HDR_T_SQN
, L_LBTRM_DATA_HDR_T_SQN
, ENC_BIG_ENDIAN
);
1040 proto_tree_add_item(data_tree
, hf_lbtrm_data_trail_sqn
, tvb
, offset
+ O_LBTRM_DATA_HDR_T_TRAIL_SQN
, L_LBTRM_DATA_HDR_T_TRAIL_SQN
, ENC_BIG_ENDIAN
);
1041 flags_val
= tvb_get_uint8(tvb
, offset
+ O_LBTRM_DATA_HDR_T_FLAGS_FEC_TYPE
);
1042 proto_tree_add_bitmask(data_tree
, tvb
, offset
+ O_LBTRM_DATA_HDR_T_FLAGS_FEC_TYPE
, hf_lbtrm_data_flags_fec_type
, ett_lbtrm_data_flags_fec_type
, flags
, ENC_BIG_ENDIAN
);
1043 proto_tree_add_item(data_tree
, hf_lbtrm_data_flags_tgsz
, tvb
, offset
+ O_LBTRM_DATA_HDR_T_FLAGS_TGSZ
, L_LBTRM_DATA_HDR_T_FLAGS_TGSZ
, ENC_BIG_ENDIAN
);
1044 proto_tree_add_item(data_tree
, hf_lbtrm_data_fec_symbol
, tvb
, offset
+ O_LBTRM_DATA_HDR_T_FEC_SYMBOL
, L_LBTRM_DATA_HDR_T_FEC_SYMBOL
, ENC_BIG_ENDIAN
);
1045 sqn
= tvb_get_ntohl(tvb
, offset
+ O_LBTRM_DATA_HDR_T_SQN
);
1046 if (sequence
!= NULL
)
1050 if ((flags_val
& LBTRM_DATA_RETRANSMISSION_FLAG
) != 0)
1052 is_retransmission
= true;
1053 expert_add_info_format(pinfo
, sqn_item
, &ei_lbtrm_analysis_rx
, "RX 0x%08x", sqn
);
1055 if (retransmission
!= NULL
)
1057 *retransmission
= is_retransmission
;
1059 tap_info
->retransmission
= is_retransmission
;
1060 tap_info
->sqn
= sqn
;
1061 return (L_LBTRM_DATA_HDR_T
);
1064 /*----------------------------------------------------------------------------*/
1065 /* LBT-RM packet dissector. */
1066 /*----------------------------------------------------------------------------*/
1071 uint32_t current_frame
;
1072 } lbtrm_sqn_frame_list_callback_data_t
;
1074 static bool dissect_lbtrm_sqn_frame_list_callback(const void *key _U_
, void * frame
, void * user_data
)
1076 lbtrm_sqn_frame_list_callback_data_t
* cb_data
= (lbtrm_sqn_frame_list_callback_data_t
*) user_data
;
1077 proto_item
* transport_item
= NULL
;
1078 lbm_transport_sqn_frame_t
* sqn_frame
= (lbm_transport_sqn_frame_t
*) frame
;
1080 if (sqn_frame
->frame
!= cb_data
->current_frame
)
1082 if (sqn_frame
->retransmission
)
1084 transport_item
= proto_tree_add_uint_format_value(cb_data
->tree
, hf_lbtrm_analysis_sqn_frame
, cb_data
->tvb
, 0, 0, sqn_frame
->frame
, "%" PRIu32
" (RX)", sqn_frame
->frame
);
1088 transport_item
= proto_tree_add_uint(cb_data
->tree
, hf_lbtrm_analysis_sqn_frame
, cb_data
->tvb
, 0, 0, sqn_frame
->frame
);
1090 proto_item_set_generated(transport_item
);
1095 static int dissect_lbtrm(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * user_data _U_
)
1097 proto_tree
* lbtrm_tree
= NULL
;
1098 proto_item
* lbtrm_item
;
1100 uint8_t next_hdr
= 0;
1101 char * tag_name
= NULL
;
1102 int dissected_len
= 0;
1103 int total_dissected_len
= 0;
1104 proto_tree
* hdr_tree
= NULL
;
1105 proto_item
* hdr_item
= NULL
;
1106 uint16_t src_port
= 0;
1107 uint32_t session_id
= 0;
1108 uint16_t dest_port
= 0;
1109 lbtrm_transport_t
* transport
= NULL
;
1110 proto_tree
* transport_tree
= NULL
;
1111 proto_item
* transport_item
= NULL
;
1112 uint32_t sequence
= 0;
1113 bool retransmission
= false;
1114 uint8_t packet_type
= 0;
1115 uint64_t channel
= LBM_CHANNEL_NO_CHANNEL
;
1116 uint8_t ver_type
= 0;
1117 uint8_t flags_fec_type
= 0;
1118 uint16_t num_naks
= 0;
1119 uint16_t num_ncfs
= 0;
1120 lbm_lbtrm_tap_info_t
* tapinfo
= NULL
;
1121 proto_item
* header_type_item
= NULL
;
1123 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "LBT-RM");
1124 col_clear(pinfo
->cinfo
, COL_INFO
);
1127 tag_name
= lbtrm_tag_find(pinfo
);
1129 if (tag_name
!= NULL
)
1131 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "[Tag: %s]", tag_name
);
1133 col_set_fence(pinfo
->cinfo
, COL_INFO
);
1135 ver_type
= tvb_get_uint8(tvb
, O_LBTRM_HDR_T_VER_TYPE
);
1136 packet_type
= LBTRM_HDR_TYPE(ver_type
);
1137 next_hdr
= tvb_get_uint8(tvb
, O_LBTRM_HDR_T_NEXT_HDR
);
1138 src_port
= tvb_get_ntohs(tvb
, O_LBTRM_HDR_T_UCAST_PORT
);
1139 session_id
= tvb_get_ntohl(tvb
, O_LBTRM_HDR_T_SESSION_ID
);
1140 if (tag_name
!= NULL
)
1142 lbtrm_item
= proto_tree_add_protocol_format(tree
, proto_lbtrm
, tvb
, offset
, -1, "LBT-RM Protocol (Tag: %s): Version %u, Type %s: Source Unicast Port %" PRIu16
", Session ID 0x%08x",
1143 tag_name
, LBTRM_HDR_VER(ver_type
), val_to_str(packet_type
, lbtrm_packet_type
, "Unknown (0x%02x)"),
1144 src_port
, session_id
);
1148 lbtrm_item
= proto_tree_add_protocol_format(tree
, proto_lbtrm
, tvb
, offset
, -1, "LBT-RM Protocol: Version %u, Type %s: Source Unicast Port %" PRIu16
", Session ID 0x%08x",
1149 LBTRM_HDR_VER(ver_type
), val_to_str(packet_type
, lbtrm_packet_type
, "Unknown (0x%02x)"),
1150 src_port
, session_id
);
1152 lbtrm_tree
= proto_item_add_subtree(lbtrm_item
, ett_lbtrm
);
1154 /* Addresses are in network order, ports in host order. */
1155 dest_port
= pinfo
->destport
;
1157 if (PINFO_FD_VISITED(pinfo
) == 0)
1159 /* First time through - add the info. */
1160 /* Note that this won't handle the case when a NAK occurs in the capture before any other packets for that transport. Oh well. */
1161 if (packet_type
== LBTRM_PACKET_TYPE_NAK
)
1163 transport
= lbtrm_transport_unicast_find(&(pinfo
->dst
), src_port
, session_id
, pinfo
->num
);
1167 transport
= lbtrm_transport_add(&(pinfo
->src
), src_port
, session_id
, &(pinfo
->dst
), dest_port
, pinfo
->num
);
1172 if (packet_type
== LBTRM_PACKET_TYPE_NAK
)
1174 transport
= lbtrm_transport_unicast_find(&(pinfo
->dst
), src_port
, session_id
, pinfo
->num
);
1178 transport
= lbtrm_transport_find(&(pinfo
->src
), src_port
, session_id
, &(pinfo
->dst
), dest_port
, pinfo
->num
);
1181 if (transport
!= NULL
)
1183 proto_item
* item
= NULL
;
1185 channel
= transport
->channel
;
1186 item
= proto_tree_add_uint64(lbtrm_tree
, hf_lbtrm_channel
, tvb
, 0, 0, channel
);
1187 proto_item_set_generated(item
);
1189 if (tag_name
!= NULL
)
1191 proto_item
* item
= NULL
;
1193 item
= proto_tree_add_string(lbtrm_tree
, hf_lbtrm_tag
, tvb
, 0, 0, tag_name
);
1194 proto_item_set_generated(item
);
1196 tapinfo
= wmem_new0(pinfo
->pool
, lbm_lbtrm_tap_info_t
);
1197 if (transport
!= NULL
)
1199 tapinfo
->transport
= lbtrm_transport_source_string_transport(pinfo
->pool
, transport
);
1201 tapinfo
->type
= packet_type
;
1203 hdr_item
= proto_tree_add_item(lbtrm_tree
, hf_lbtrm_hdr
, tvb
, O_LBTRM_HDR_T_VER_TYPE
, L_LBTRM_HDR_T
, ENC_NA
);
1204 hdr_tree
= proto_item_add_subtree(hdr_item
, ett_lbtrm_hdr
);
1205 proto_tree_add_item(hdr_tree
, hf_lbtrm_hdr_ver
, tvb
, O_LBTRM_HDR_T_VER_TYPE
, L_LBTRM_HDR_T_VER_TYPE
, ENC_BIG_ENDIAN
);
1206 header_type_item
= proto_tree_add_item(hdr_tree
, hf_lbtrm_hdr_type
, tvb
, O_LBTRM_HDR_T_VER_TYPE
, L_LBTRM_HDR_T_VER_TYPE
, ENC_BIG_ENDIAN
);
1207 /* Setup the INFO column for this packet. */
1208 switch (packet_type
)
1210 case LBTRM_PACKET_TYPE_DATA
:
1211 sequence
= tvb_get_ntohl(tvb
, L_LBTRM_HDR_T
+ O_LBTRM_DATA_HDR_T_SQN
);
1212 flags_fec_type
= tvb_get_uint8(tvb
, L_LBTRM_HDR_T
+ O_LBTRM_DATA_HDR_T_FLAGS_FEC_TYPE
);
1213 if ((flags_fec_type
& LBTRM_DATA_RETRANSMISSION_FLAG
) != 0)
1215 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "DATA(RX) sqn 0x%x Port %" PRIu16
" ID 0x%08x", sequence
, src_port
, session_id
);
1219 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "DATA sqn 0x%x Port %" PRIu16
" ID 0x%08x", sequence
, src_port
, session_id
);
1222 case LBTRM_PACKET_TYPE_SM
:
1223 sequence
= tvb_get_ntohl(tvb
, L_LBTRM_HDR_T
+ O_LBTRM_SM_HDR_T_SM_SQN
);
1224 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "SM sqn 0x%x Port %" PRIu16
" ID 0x%08x", sequence
, src_port
, session_id
);
1226 case LBTRM_PACKET_TYPE_NAK
:
1227 num_naks
= tvb_get_ntohs(tvb
, L_LBTRM_HDR_T
+ O_LBTRM_NAK_HDR_T_NUM_NAKS
);
1228 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "NAK %u naks Port %" PRIu16
" ID 0x%08x", num_naks
, src_port
, session_id
);
1230 case LBTRM_PACKET_TYPE_NCF
:
1231 num_ncfs
= tvb_get_ntohs(tvb
, L_LBTRM_HDR_T
+ O_LBTRM_NCF_HDR_T_NUM_NCFS
);
1232 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "NCF %u ncfs Port %" PRIu16
" ID 0x%08x", num_ncfs
, src_port
, session_id
);
1235 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "Unknown (0x%02x)", packet_type
);
1236 expert_add_info_format(pinfo
, header_type_item
, &ei_lbtrm_analysis_invalid_value
, "Unrecognized type 0x%02x", packet_type
);
1240 proto_tree_add_item(hdr_tree
, hf_lbtrm_hdr_next_hdr
, tvb
, O_LBTRM_HDR_T_NEXT_HDR
, L_LBTRM_HDR_T_NEXT_HDR
, ENC_BIG_ENDIAN
);
1241 proto_tree_add_item(hdr_tree
, hf_lbtrm_hdr_ucast_port
, tvb
, O_LBTRM_HDR_T_UCAST_PORT
, L_LBTRM_HDR_T_UCAST_PORT
, ENC_BIG_ENDIAN
);
1242 proto_tree_add_item(hdr_tree
, hf_lbtrm_hdr_session_id
, tvb
, O_LBTRM_HDR_T_SESSION_ID
, L_LBTRM_HDR_T_SESSION_ID
, ENC_BIG_ENDIAN
);
1243 total_dissected_len
= L_LBTRM_HDR_T
;
1244 offset
= L_LBTRM_HDR_T
;
1245 switch (packet_type
)
1247 case LBTRM_PACKET_TYPE_DATA
:
1248 dissected_len
= dissect_lbtrm_data(tvb
, offset
, pinfo
, lbtrm_tree
, &sequence
, &retransmission
, tapinfo
);
1250 case LBTRM_PACKET_TYPE_SM
:
1251 dissected_len
= dissect_lbtrm_sm(tvb
, offset
, pinfo
, lbtrm_tree
, &sequence
, tapinfo
);
1253 case LBTRM_PACKET_TYPE_NAK
:
1254 dissected_len
= dissect_lbtrm_nak(tvb
, offset
, pinfo
, lbtrm_tree
, tapinfo
);
1256 case LBTRM_PACKET_TYPE_NCF
:
1257 dissected_len
= dissect_lbtrm_ncf(tvb
, offset
, pinfo
, lbtrm_tree
, tapinfo
);
1260 return (total_dissected_len
);
1262 total_dissected_len
+= dissected_len
;
1263 offset
+= dissected_len
;
1264 while (next_hdr
!= LBTRM_NHDR_DATA
)
1268 next_hdr
= tvb_get_uint8(tvb
, offset
+ O_LBTRM_BASIC_OPT_T_NEXT_HDR
);
1269 hdrlen
= tvb_get_uint8(tvb
, offset
+ O_LBTRM_BASIC_OPT_T_HDR_LEN
);
1275 total_dissected_len
+= hdrlen
;
1278 if (lbtrm_sequence_analysis
)
1280 if (pinfo
->fd
->visited
== 0)
1282 if (transport
!= NULL
)
1284 lbtrm_transport_frame_add(transport
, packet_type
, pinfo
->num
, sequence
, retransmission
);
1289 if (transport
!= NULL
)
1291 lbm_transport_frame_t
* frame
= NULL
;
1293 /* Setup the tree */
1294 transport_item
= proto_tree_add_item(lbtrm_tree
, hf_lbtrm_analysis
, tvb
, 0, 0, ENC_NA
);
1295 proto_item_set_generated(transport_item
);
1296 transport_tree
= proto_item_add_subtree(transport_item
, ett_lbtrm_transport
);
1297 frame
= lbtrm_transport_frame_find(transport
, pinfo
->num
);
1300 lbm_transport_sqn_t
* sqn
= NULL
;
1302 if (frame
->previous_frame
!= 0)
1304 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_prev_frame
, tvb
, 0, 0, frame
->previous_frame
);
1305 proto_item_set_generated(transport_item
);
1307 if (frame
->next_frame
!= 0)
1309 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_next_frame
, tvb
, 0, 0, frame
->next_frame
);
1310 proto_item_set_generated(transport_item
);
1312 switch (packet_type
)
1314 case LBTRM_PACKET_TYPE_DATA
:
1315 if (frame
->previous_type_frame
!= 0)
1317 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_prev_data_frame
, tvb
, 0, 0, frame
->previous_type_frame
);
1318 proto_item_set_generated(transport_item
);
1320 if (frame
->next_type_frame
!= 0)
1322 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_next_data_frame
, tvb
, 0, 0, frame
->next_type_frame
);
1323 proto_item_set_generated(transport_item
);
1325 sqn
= lbtrm_transport_sqn_find(transport
, packet_type
, sequence
);
1328 if (sqn
->frame_count
> 1)
1330 proto_tree
* frame_tree
= NULL
;
1331 proto_item
* frame_tree_item
= NULL
;
1332 lbtrm_sqn_frame_list_callback_data_t cb_data
;
1334 frame_tree_item
= proto_tree_add_item(transport_tree
, hf_lbtrm_analysis_sqn
, tvb
, 0, 0, ENC_NA
);
1335 proto_item_set_generated(frame_tree_item
);
1336 frame_tree
= proto_item_add_subtree(frame_tree_item
, ett_lbtrm_transport_sqn
);
1337 cb_data
.tree
= frame_tree
;
1339 cb_data
.current_frame
= pinfo
->num
;
1340 wmem_tree_foreach(sqn
->frame
, dissect_lbtrm_sqn_frame_list_callback
, (void *) &cb_data
);
1343 if (frame
->retransmission
)
1345 transport_item
= proto_tree_add_boolean(transport_tree
, hf_lbtrm_analysis_data_retransmission
, tvb
, 0, 0, true);
1346 proto_item_set_generated(transport_item
);
1347 expert_add_info(pinfo
, transport_item
, &ei_lbtrm_analysis_data_rx
);
1349 if (frame
->sqn_gap
!= 0)
1351 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_data_sqn_gap
, tvb
, 0, 0, frame
->sqn_gap
);
1352 proto_item_set_generated(transport_item
);
1353 expert_add_info_format(pinfo
, transport_item
, &ei_lbtrm_analysis_data_gap
, "Data sequence gap (%" PRIu32
")", frame
->sqn_gap
);
1355 if (frame
->ooo_gap
!= 0)
1357 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_data_ooo_gap
, tvb
, 0, 0, frame
->ooo_gap
);
1358 proto_item_set_generated(transport_item
);
1359 expert_add_info_format(pinfo
, transport_item
, &ei_lbtrm_analysis_data_ooo
, "Data sequence out of order gap (%" PRIu32
")", frame
->ooo_gap
);
1361 if (frame
->duplicate
)
1363 transport_item
= proto_tree_add_boolean(transport_tree
, hf_lbtrm_analysis_data_duplicate
, tvb
, 0, 0, true);
1364 proto_item_set_generated(transport_item
);
1365 expert_add_info(pinfo
, transport_item
, &ei_lbtrm_analysis_data_dup
);
1368 case LBTRM_PACKET_TYPE_SM
:
1369 if (frame
->previous_type_frame
!= 0)
1371 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_prev_sm_frame
, tvb
, 0, 0, frame
->previous_type_frame
);
1372 proto_item_set_generated(transport_item
);
1374 if (frame
->next_type_frame
!= 0)
1376 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_next_sm_frame
, tvb
, 0, 0, frame
->next_type_frame
);
1377 proto_item_set_generated(transport_item
);
1379 sqn
= lbtrm_transport_sqn_find(transport
, packet_type
, sequence
);
1382 if (sqn
->frame_count
> 1)
1384 proto_tree
* frame_tree
= NULL
;
1385 proto_item
* frame_tree_item
= NULL
;
1386 lbtrm_sqn_frame_list_callback_data_t cb_data
;
1388 frame_tree_item
= proto_tree_add_item(transport_tree
, hf_lbtrm_analysis_sqn
, tvb
, 0, 0, ENC_NA
);
1389 proto_item_set_generated(frame_tree_item
);
1390 frame_tree
= proto_item_add_subtree(frame_tree_item
, ett_lbtrm_transport_sqn
);
1391 cb_data
.tree
= frame_tree
;
1393 cb_data
.current_frame
= pinfo
->num
;
1394 wmem_tree_foreach(sqn
->frame
, dissect_lbtrm_sqn_frame_list_callback
, (void *) &cb_data
);
1397 if (frame
->sqn_gap
!= 0)
1399 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_sm_sqn_gap
, tvb
, 0, 0, frame
->sqn_gap
);
1400 proto_item_set_generated(transport_item
);
1401 expert_add_info_format(pinfo
, transport_item
, &ei_lbtrm_analysis_sm_gap
, "SM sequence gap (%" PRIu32
")", frame
->sqn_gap
);
1403 if (frame
->ooo_gap
!= 0)
1405 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_sm_ooo_gap
, tvb
, 0, 0, frame
->ooo_gap
);
1406 proto_item_set_generated(transport_item
);
1407 expert_add_info_format(pinfo
, transport_item
, &ei_lbtrm_analysis_sm_ooo
, "SM sequence out of order gap (%" PRIu32
")", frame
->ooo_gap
);
1409 if (frame
->duplicate
)
1411 transport_item
= proto_tree_add_boolean(transport_tree
, hf_lbtrm_analysis_sm_duplicate
, tvb
, 0, 0, true);
1412 proto_item_set_generated(transport_item
);
1413 expert_add_info(pinfo
, transport_item
, &ei_lbtrm_analysis_sm_dup
);
1416 case LBTRM_PACKET_TYPE_NAK
:
1417 if (frame
->previous_type_frame
!= 0)
1419 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_prev_nak_frame
, tvb
, 0, 0, frame
->previous_type_frame
);
1420 proto_item_set_generated(transport_item
);
1422 if (frame
->next_type_frame
!= 0)
1424 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_next_nak_frame
, tvb
, 0, 0, frame
->next_type_frame
);
1425 proto_item_set_generated(transport_item
);
1428 case LBTRM_PACKET_TYPE_NCF
:
1429 if (frame
->previous_type_frame
!= 0)
1431 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_prev_ncf_frame
, tvb
, 0, 0, frame
->previous_type_frame
);
1432 proto_item_set_generated(transport_item
);
1434 if (frame
->next_type_frame
!= 0)
1436 transport_item
= proto_tree_add_uint(transport_tree
, hf_lbtrm_analysis_next_ncf_frame
, tvb
, 0, 0, frame
->next_type_frame
);
1437 proto_item_set_generated(transport_item
);
1447 proto_item_set_len(lbtrm_item
, total_dissected_len
);
1448 if ((packet_type
== LBTRM_PACKET_TYPE_DATA
) && (next_hdr
== LBTRM_NHDR_DATA
))
1450 total_dissected_len
+= dissect_lbtrm_data_contents(tvb
, offset
, pinfo
, tree
, tag_name
, channel
);
1452 if (tapinfo
->transport
!= NULL
)
1454 tap_queue_packet(lbtrm_tap_handle
, pinfo
, (void *) tapinfo
);
1456 return (total_dissected_len
);
1459 static bool test_lbtrm_packet(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * user_data
)
1461 uint32_t dest_addr_h
;
1462 bool valid_packet
= false;
1463 uint8_t ver_type
= 0;
1464 uint8_t packet_type
= 0;
1465 uint8_t packet_ver
= 0;
1466 uint8_t next_hdr
= 0;
1468 /* Must be a UDP packet. */
1469 if (pinfo
->ptype
!= PT_UDP
)
1473 /* Destination address must be IPV4 and 4 bytes in length. */
1474 if ((pinfo
->dst
.type
!= AT_IPv4
) || (pinfo
->dst
.len
!= 4))
1478 if (tvb_reported_length_remaining(tvb
, 0) < L_LBTRM_HDR_T
)
1482 ver_type
= tvb_get_uint8(tvb
, O_LBTRM_HDR_T_VER_TYPE
);
1483 packet_type
= LBTRM_HDR_TYPE(ver_type
);
1484 switch (packet_type
)
1486 case LBTRM_PACKET_TYPE_DATA
:
1487 case LBTRM_PACKET_TYPE_SM
:
1488 case LBTRM_PACKET_TYPE_NAK
:
1489 case LBTRM_PACKET_TYPE_NCF
:
1494 packet_ver
= LBTRM_HDR_VER(ver_type
);
1495 if (packet_ver
!= LBTRM_VERSION
)
1499 next_hdr
= tvb_get_uint8(tvb
, O_LBTRM_HDR_T_NEXT_HDR
);
1500 if (next_hdr
!= LBTRM_NHDR_DATA
)
1506 if (lbtrm_tag_find(pinfo
) != NULL
)
1508 valid_packet
= true;
1513 dest_addr_h
= pntoh32(pinfo
->dst
.data
);
1515 /* Is the destination a multicast address? */
1516 if (IN_MULTICAST(dest_addr_h
))
1518 /* Check the MC address. */
1519 if ((dest_addr_h
>= lbtrm_mc_address_low_host
) && (dest_addr_h
<= lbtrm_mc_address_high_host
))
1521 /* It's in the LBT-RM multicast range. Check the ports. */
1522 if ((pinfo
->destport
>= lbtrm_dest_port_low
) && (pinfo
->destport
<= lbtrm_dest_port_high
))
1524 /* Must be one of ours. */
1525 valid_packet
= true;
1528 else if ((dest_addr_h
== mim_incoming_mc_address_host
) || (dest_addr_h
== mim_outgoing_mc_address_host
))
1530 /* Might be MIM. Check the port. */
1531 if (((dest_addr_h
== mim_incoming_mc_address_host
) && (pinfo
->destport
== mim_incoming_dest_port
))
1532 || ((dest_addr_h
== mim_outgoing_mc_address_host
) && (pinfo
->destport
== mim_outgoing_dest_port
)))
1534 /* Must be one of ours. */
1535 valid_packet
= true;
1541 /* Not multicast, might be a unicast UDP NAK. Check the destination port. */
1542 if ((pinfo
->destport
>= lbtrm_src_port_low
) && (pinfo
->destport
<= lbtrm_src_port_high
))
1544 valid_packet
= true;
1550 dissect_lbtrm(tvb
, pinfo
, tree
, user_data
);
1556 /* Register all the bits needed with the filtering engine */
1557 void proto_register_lbtrm(void)
1559 static hf_register_info hf
[] =
1561 { &hf_lbtrm_channel
,
1562 { "Channel ID", "lbtrm.channel", FT_UINT64
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1564 { "Tag", "lbtrm.tag", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1566 { "Header", "lbtrm.hdr", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1567 { &hf_lbtrm_hdr_ver
,
1568 { "Version", "lbtrm.hdr.ver", FT_UINT8
, BASE_HEX
, NULL
, LBTRM_HDR_VER_MASK
, NULL
, HFILL
} },
1569 { &hf_lbtrm_hdr_type
,
1570 { "Type", "lbtrm.hdr.type", FT_UINT8
, BASE_HEX
, VALS(lbtrm_packet_type
), LBTRM_HDR_TYPE_MASK
, NULL
, HFILL
} },
1571 { &hf_lbtrm_hdr_next_hdr
,
1572 { "Next Header", "lbtrm.hdr.next_hdr", FT_UINT8
, BASE_HEX
, VALS(lbtrm_next_header
), 0x0, NULL
, HFILL
} },
1573 { &hf_lbtrm_hdr_ucast_port
,
1574 { "Source Unicast Port", "lbtrm.hdr.ucast_port", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1575 { &hf_lbtrm_hdr_session_id
,
1576 { "Session ID", "lbtrm.hdr.session_id", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1578 { "Data Header", "lbtrm.data", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1579 { &hf_lbtrm_data_sqn
,
1580 { "Sequence Number", "lbtrm.data.sqn", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1581 { &hf_lbtrm_data_trail_sqn
,
1582 { "Trailing Edge Sequence Number", "lbtrm.data.trail_sqn", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1583 { &hf_lbtrm_data_flags_fec_type
,
1584 { "FEC Flags", "lbtrm.data.flags_fec_type", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1585 { &hf_lbtrm_data_flags_fec_type_ucast_naks
,
1586 { "Unicast NAKs", "lbtrm.data.flags_fec_type.ucast_naks", FT_BOOLEAN
, L_LBTRM_DATA_HDR_T_FLAGS_FEC_TYPE
* 8, TFS(&tfs_set_notset
), LBTRM_DATA_UNICAST_NAKS_FLAG
, "Set if NAKs are sent via unicast", HFILL
} },
1587 { &hf_lbtrm_data_flags_fec_type_rx
,
1588 { "Retransmission", "lbtrm.data.flags_fec_type.rx", FT_BOOLEAN
, L_LBTRM_DATA_HDR_T_FLAGS_FEC_TYPE
* 8, TFS(&tfs_set_notset
), LBTRM_DATA_RETRANSMISSION_FLAG
, "Set if this is a retransmission", HFILL
} },
1589 { &hf_lbtrm_data_flags_tgsz
,
1590 { "TGSZ Flags", "lbtrm.data.flags_tgsz", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1591 { &hf_lbtrm_data_fec_symbol
,
1592 { "FEC Symbol", "lbtrm.data.fec_symbol", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1594 { "Session Message Header", "lbtrm.sm", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1595 { &hf_lbtrm_sm_sm_sqn
,
1596 { "Sequence Number", "lbtrm.sm.sm_sqn", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1597 { &hf_lbtrm_sm_lead_sqn
,
1598 { "Lead Sequence Number", "lbtrm.sm.lead_sqn", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1599 { &hf_lbtrm_sm_trail_sqn
,
1600 { "Trail Sequence Number", "lbtrm.sm.trail_sqn", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1601 { &hf_lbtrm_sm_flags_fec_type
,
1602 { "FEC Flags", "lbtrm.sm.flags_fec_type", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1603 { &hf_lbtrm_sm_flags_fec_type_ucast_naks
,
1604 { "Unicast NAKs", "lbtrm.sm.flags_fec_type.ucast_naks", FT_BOOLEAN
, 8, TFS(&tfs_present_not_present
), LBTRM_SM_UNICAST_NAKS_FLAG
, "Set if NAKs are sent via unicast", HFILL
} },
1605 { &hf_lbtrm_sm_flags_tgsz
,
1606 { "TGSZ Flags", "lbtrm.sm.flags_tgsz", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1607 { &hf_lbtrm_sm_reserved
,
1608 { "Reserved", "lbtrm.sm.reserved", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1610 { "NAK Header", "lbtrm.nak", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1611 { &hf_lbtrm_nak_num_naks
,
1612 { "Number of NAKs", "lbtrm.nak.num_naks", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1613 { &hf_lbtrm_nak_format
,
1614 { "Format", "lbtrm.nak.format", FT_UINT8
, BASE_HEX
, VALS(lbtrm_nak_format
), LBTRM_NAK_HDR_FORMAT_MASK
, NULL
, HFILL
} },
1615 { &hf_lbtrm_nak_list
,
1616 { "NAK List", "lbtrm.nak.list", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1617 { &hf_lbtrm_nak_list_nak
,
1618 { "NAK", "lbtrm.nak.list.nak", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1620 { "NAK Confirmation Header", "lbtrm.ncf", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1621 { &hf_lbtrm_ncf_trail_sqn
,
1622 { "Trailing Sequence Number", "lbtrm.ncf.trail_sqn", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1623 { &hf_lbtrm_ncf_num_ncfs
,
1624 { "Number of Individual NCFs", "lbtrm.ncf.num_ncfs", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1625 { &hf_lbtrm_ncf_reserved
,
1626 { "Reserved", "lbtrm.ncf.reserved", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1627 { &hf_lbtrm_ncf_reason
,
1628 { "Reason", "lbtrm.ncf.reason", FT_UINT8
, BASE_HEX
, VALS(lbtrm_ncf_reason
), LBTRM_NCF_HDR_REASON_MASK
, NULL
, HFILL
} },
1629 { &hf_lbtrm_ncf_format
,
1630 { "Format", "lbtrm.ncf.format", FT_UINT8
, BASE_HEX
, VALS(lbtrm_ncf_format
), LBTRM_NCF_HDR_FORMAT_MASK
, NULL
, HFILL
} },
1631 { &hf_lbtrm_ncf_list
,
1632 { "NCF List", "lbtrm.ncf.list", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1633 { &hf_lbtrm_ncf_list_ncf
,
1634 { "NCF", "lbtrm.ncf.list.ncf", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1635 { &hf_lbtrm_analysis
,
1636 { "Transport Analysis", "lbtrm.transport", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1637 { &hf_lbtrm_analysis_prev_frame
,
1638 { "Previous Transport frame", "lbtrm.transport.prev_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1639 { &hf_lbtrm_analysis_prev_data_frame
,
1640 { "Previous Transport DATA frame", "lbtrm.transport.prev_data_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1641 { &hf_lbtrm_analysis_prev_sm_frame
,
1642 { "Previous Transport SM frame", "lbtrm.transport.prev_sm_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1643 { &hf_lbtrm_analysis_prev_nak_frame
,
1644 { "Previous Transport NAK frame", "lbtrm.transport.prev_nak_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1645 { &hf_lbtrm_analysis_prev_ncf_frame
,
1646 { "Previous Transport NCF frame", "lbtrm.transport.prev_ncf_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1647 { &hf_lbtrm_analysis_next_frame
,
1648 { "Next Transport frame", "lbtrm.transport.next_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1649 { &hf_lbtrm_analysis_next_data_frame
,
1650 { "Next Transport DATA frame", "lbtrm.transport.next_data_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1651 { &hf_lbtrm_analysis_next_sm_frame
,
1652 { "Next Transport SM frame", "lbtrm.transport.next_sm_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1653 { &hf_lbtrm_analysis_next_nak_frame
,
1654 { "Next Transport NAK frame", "lbtrm.transport.next_nak_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1655 { &hf_lbtrm_analysis_next_ncf_frame
,
1656 { "Next Transport NCF frame", "lbtrm.transport.next_ncf_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1657 { &hf_lbtrm_analysis_sqn
,
1658 { "SQN Also in", "lbtrm.transport.sqn", FT_NONE
, BASE_NONE
, NULL
, 0x0, "Sequence number also appears in these frames", HFILL
} },
1659 { &hf_lbtrm_analysis_sqn_frame
,
1660 { "Frame", "lbtrm.transport.sqn.frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1661 { &hf_lbtrm_analysis_data_retransmission
,
1662 { "Frame is a Data Retransmission", "lbtrm.transport.data_retransmission", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1663 { &hf_lbtrm_analysis_data_sqn_gap
,
1664 { "Gap in Data Sequence", "lbtrm.transport.data_sqn_gap", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1665 { &hf_lbtrm_analysis_data_ooo_gap
,
1666 { "Data Sequence Out of Order Gap", "lbtrm.transport.data_ooo_gap", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1667 { &hf_lbtrm_analysis_data_duplicate
,
1668 { "Duplicate Data frame", "lbtrm.transport.data_duplicate", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1669 { &hf_lbtrm_analysis_sm_sqn_gap
,
1670 { "Gap in SM Sequence", "lbtrm.transport.sm_sqn_gap", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1671 { &hf_lbtrm_analysis_sm_ooo_gap
,
1672 { "SM Sequence Out of Order Gap", "lbtrm.transport.sm_ooo_gap", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1673 { &hf_lbtrm_analysis_sm_duplicate
,
1674 { "Duplicate SM frame", "lbtrm.transport.sm_duplicate", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1676 static int * ett
[] =
1681 &ett_lbtrm_data_flags_fec_type
,
1683 &ett_lbtrm_sm_flags_fec_type
,
1685 &ett_lbtrm_nak_list
,
1687 &ett_lbtrm_ncf_list
,
1688 &ett_lbtrm_transport
,
1689 &ett_lbtrm_transport_sqn
1691 static ei_register_info ei
[] =
1693 { &ei_lbtrm_analysis_ncf
, { "lbtrm.analysis.ncf", PI_SEQUENCE
, PI_NOTE
, "NCF", EXPFILL
} },
1694 { &ei_lbtrm_analysis_ncf_ncf
, { "lbtrm.analysis.ncf.ncf", PI_SEQUENCE
, PI_NOTE
, "NCF", EXPFILL
} },
1695 { &ei_lbtrm_analysis_nak
, { "lbtrm.analysis.nak", PI_SEQUENCE
, PI_WARN
, "NAK", EXPFILL
} },
1696 { &ei_lbtrm_analysis_nak_nak
, { "lbtrm.analysis.nak.nak", PI_SEQUENCE
, PI_WARN
, "NAK", EXPFILL
} },
1697 { &ei_lbtrm_analysis_sm
, { "lbtrm.analysis.sm", PI_SEQUENCE
, PI_CHAT
, "SM", EXPFILL
} },
1698 { &ei_lbtrm_analysis_rx
, { "lbtrm.analysis.rx", PI_SEQUENCE
, PI_NOTE
, "RX", EXPFILL
} },
1699 { &ei_lbtrm_analysis_invalid_value
, { "lbtrm.analysis.invalid_value", PI_MALFORMED
, PI_ERROR
, "Invalid value", EXPFILL
} },
1700 { &ei_lbtrm_analysis_data_rx
, { "lbtrm.analysis.data.rx", PI_SEQUENCE
, PI_NOTE
, "Data RX", EXPFILL
} },
1701 { &ei_lbtrm_analysis_data_gap
, { "lbtrm.analysis.data.gap", PI_SEQUENCE
, PI_NOTE
, "Data sequence gap", EXPFILL
} },
1702 { &ei_lbtrm_analysis_data_ooo
, { "lbtrm.analysis.data.ooo", PI_SEQUENCE
, PI_NOTE
, "Data out of order", EXPFILL
} },
1703 { &ei_lbtrm_analysis_data_dup
, { "lbtrm.analysis.data.dup", PI_SEQUENCE
, PI_NOTE
, "Duplicate data", EXPFILL
} },
1704 { &ei_lbtrm_analysis_sm_gap
, { "lbtrm.analysis.sm.gap", PI_SEQUENCE
, PI_NOTE
, "SM sequence gap", EXPFILL
} },
1705 { &ei_lbtrm_analysis_sm_ooo
, { "lbtrm.analysis.sm.ooo", PI_SEQUENCE
, PI_NOTE
, "SM out of order", EXPFILL
} },
1706 { &ei_lbtrm_analysis_sm_dup
, { "lbtrm.analysis.sm.dup", PI_SEQUENCE
, PI_NOTE
, "Duplicate SM", EXPFILL
} },
1708 module_t
* lbtrm_module
;
1711 expert_module_t
* expert_lbtrm
;
1713 proto_lbtrm
= proto_register_protocol("LBT Reliable Multicast Protocol",
1716 proto_register_field_array(proto_lbtrm
, hf
, array_length(hf
));
1717 proto_register_subtree_array(ett
, array_length(ett
));
1718 expert_lbtrm
= expert_register_protocol(proto_lbtrm
);
1719 expert_register_field_array(expert_lbtrm
, ei
, array_length(ei
));
1721 lbtrm_dissector_handle
= register_dissector("lbtrm", dissect_lbtrm
, proto_lbtrm
);
1723 lbtrm_module
= prefs_register_protocol_subtree("29West", proto_lbtrm
, proto_reg_handoff_lbtrm
);
1724 ws_inet_pton4(LBTRM_DEFAULT_MC_ADDRESS_LOW
, &addr
);
1725 lbtrm_mc_address_low_host
= g_ntohl(addr
);
1726 prefs_register_string_preference(lbtrm_module
,
1728 "Multicast address range low (default " LBTRM_DEFAULT_MC_ADDRESS_LOW
")",
1729 "Set the low end of the LBT-RM multicast address range (context transport_lbtrm_multicast_address_low)",
1730 &global_lbtrm_mc_address_low
);
1732 ws_inet_pton4(LBTRM_DEFAULT_MC_ADDRESS_HIGH
, &addr
);
1733 lbtrm_mc_address_high_host
= g_ntohl(addr
);
1734 prefs_register_string_preference(lbtrm_module
,
1736 "Multicast address range high (default " LBTRM_DEFAULT_MC_ADDRESS_HIGH
")",
1737 "Set the high end of the LBT-RM multicast address range (context transport_lbtrm_multicast_address_high)",
1738 &global_lbtrm_mc_address_high
);
1740 prefs_register_uint_preference(lbtrm_module
,
1742 "Destination port range low (default " MAKESTRING(LBTRM_DEFAULT_DPORT_LOW
)")",
1743 "Set the low end of the LBT-RM UDP destination port range (source transport_lbtrm_destination_port)",
1745 &global_lbtrm_dest_port_low
);
1747 prefs_register_uint_preference(lbtrm_module
,
1749 "Destination port range high (default " MAKESTRING(LBTRM_DEFAULT_DPORT_HIGH
)")",
1750 "Set the high end of the LBT-RM UDP destination port range (source transport_lbtrm_destination_port)",
1752 &global_lbtrm_dest_port_high
);
1754 prefs_register_uint_preference(lbtrm_module
,
1756 "Source port range low (default " MAKESTRING(LBTRM_DEFAULT_SPORT_LOW
)")",
1757 "Set the low end of the LBT-RM UDP source port range (context transport_lbtrm_source_port_low)",
1759 &global_lbtrm_src_port_low
);
1761 prefs_register_uint_preference(lbtrm_module
,
1763 "Source port range high (default " MAKESTRING(LBTRM_DEFAULT_SPORT_HIGH
)")",
1764 "Set the high end of the LBT-RM UDP source port range (context transport_lbtrm_source_port_high)",
1766 &global_lbtrm_src_port_high
);
1768 ws_inet_pton4(MIM_DEFAULT_MC_INCOMING_ADDRESS
, &addr
);
1769 mim_incoming_mc_address_host
= g_ntohl(addr
);
1770 prefs_register_string_preference(lbtrm_module
,
1771 "mim_incoming_address",
1772 "MIM incoming multicast address (default " MIM_DEFAULT_MC_INCOMING_ADDRESS
")",
1773 "Set the incoming MIM multicast address (context mim_incoming_address)",
1774 &global_mim_incoming_mc_address
);
1776 ws_inet_pton4(MIM_DEFAULT_MC_OUTGOING_ADDRESS
, &addr
);
1777 mim_outgoing_mc_address_host
= g_ntohl(addr
);
1778 prefs_register_string_preference(lbtrm_module
,
1779 "mim_outgoing_address",
1780 "MIM outgoing multicast address (default " MIM_DEFAULT_MC_OUTGOING_ADDRESS
")",
1781 "Set the outgoing MIM multicast address (context mim_outgoing_address)",
1782 &global_mim_outgoing_mc_address
);
1784 prefs_register_uint_preference(lbtrm_module
,
1785 "mim_incoming_dport",
1786 "MIM incoming port (default " MAKESTRING(MIM_DEFAULT_INCOMING_DPORT
)")",
1787 "Set the incoming MIM UDP port (context mim_incoming_destination_port)",
1789 &global_mim_incoming_dest_port
);
1791 prefs_register_uint_preference(lbtrm_module
,
1792 "mim_outgoing_dport",
1793 "MIM outgoing port (default " MAKESTRING(MIM_DEFAULT_OUTGOING_DPORT
)")",
1794 "Set the outgoing MIM UDP port (context mim_outgoing_destination_port)",
1796 &global_mim_outgoing_dest_port
);
1798 lbtrm_expert_separate_naks
= global_lbtrm_expert_separate_naks
;
1799 prefs_register_bool_preference(lbtrm_module
,
1800 "expert_separate_naks",
1801 "Separate NAKs in Expert Info",
1802 "Separate multiple NAKs from a single packet into distinct Expert Info entries",
1803 &global_lbtrm_expert_separate_naks
);
1805 lbtrm_expert_separate_ncfs
= global_lbtrm_expert_separate_ncfs
;
1806 prefs_register_bool_preference(lbtrm_module
,
1807 "expert_separate_ncfs",
1808 "Separate NCFs in Expert Info",
1809 "Separate multiple NCFs from a single packet into distinct Expert Info entries",
1810 &global_lbtrm_expert_separate_ncfs
);
1812 lbtrm_sequence_analysis
= global_lbtrm_sequence_analysis
;
1813 prefs_register_bool_preference(lbtrm_module
,
1814 "sequence_analysis",
1815 "Perform sequence Number Analysis",
1816 "Perform analysis on LBT-RM sequence numbers to determine out-of-order, gaps, loss, etc",
1817 &global_lbtrm_sequence_analysis
);
1819 lbtrm_use_tag
= global_lbtrm_use_tag
;
1820 prefs_register_bool_preference(lbtrm_module
,
1822 "Use LBT-RM tag table",
1823 "Use table of LBT-RM tags to decode the packet instead of above values",
1824 &global_lbtrm_use_tag
);
1825 tag_uat
= uat_new("LBT-RM tag definitions",
1826 sizeof(lbtrm_tag_entry_t
),
1829 (void * *)&lbtrm_tag_entry
,
1831 UAT_AFFECTS_DISSECTION
,
1834 lbtrm_tag_update_cb
,
1839 prefs_register_uat_preference(lbtrm_module
,
1842 "A table to define LBT-RM tags",
1845 lbtrm_tap_handle
= register_tap("lbm_lbtrm");
1848 /* The registration hand-off routine */
1849 void proto_reg_handoff_lbtrm(void)
1851 static bool already_registered
= false;
1853 uint32_t dest_addr_h_low
;
1854 uint32_t dest_addr_h_high
;
1856 if (!already_registered
)
1858 dissector_add_for_decode_as_with_preference("udp.port", lbtrm_dissector_handle
);
1859 heur_dissector_add("udp", test_lbtrm_packet
, "LBT Reliable Multicast over UDP", "lbtrm_udp", proto_lbtrm
, HEURISTIC_ENABLE
);
1862 /* Make sure the low MC address is <= the high MC address. If not, don't change them. */
1863 ws_inet_pton4(global_lbtrm_mc_address_low
, &addr
);
1864 dest_addr_h_low
= g_ntohl(addr
);
1865 ws_inet_pton4(global_lbtrm_mc_address_high
, &addr
);
1866 dest_addr_h_high
= g_ntohl(addr
);
1867 if (dest_addr_h_low
<= dest_addr_h_high
)
1869 lbtrm_mc_address_low_host
= dest_addr_h_low
;
1870 lbtrm_mc_address_high_host
= dest_addr_h_high
;
1873 /* Make sure the low destination port is <= the high destination port. If not, don't change them. */
1874 if (global_lbtrm_dest_port_low
<= global_lbtrm_dest_port_high
)
1876 lbtrm_dest_port_low
= global_lbtrm_dest_port_low
;
1877 lbtrm_dest_port_high
= global_lbtrm_dest_port_high
;
1880 /* Make sure the low source port is <= the high source port. If not, don't change them. */
1881 if (global_lbtrm_src_port_low
<= global_lbtrm_src_port_high
)
1883 lbtrm_src_port_low
= global_lbtrm_src_port_low
;
1884 lbtrm_src_port_high
= global_lbtrm_src_port_high
;
1887 /* Add the dissector hooks for the MIM MC groups. */
1888 ws_inet_pton4(global_mim_incoming_mc_address
, &addr
);
1889 mim_incoming_mc_address_host
= g_htonl(addr
);
1890 ws_inet_pton4(global_mim_outgoing_mc_address
, &addr
);
1891 mim_outgoing_mc_address_host
= g_htonl(addr
);
1893 /* Add the dissector hooks for the MIM ports. */
1894 mim_incoming_dest_port
= global_mim_incoming_dest_port
;
1895 mim_outgoing_dest_port
= global_mim_outgoing_dest_port
;
1897 lbtrm_expert_separate_naks
= global_lbtrm_expert_separate_naks
;
1898 lbtrm_expert_separate_ncfs
= global_lbtrm_expert_separate_ncfs
;
1900 lbtrm_sequence_analysis
= global_lbtrm_sequence_analysis
;
1902 lbtrm_use_tag
= global_lbtrm_use_tag
;
1904 already_registered
= true;
1908 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1913 * indent-tabs-mode: nil
1916 * vi: set shiftwidth=4 tabstop=8 expandtab:
1917 * :indentSize=4:tabSize=8:noTabs=true: