Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-lbtrm.c
blobbe5eb82659fb3491888cc8d801f796c41d022d0b
1 /* packet-lbtrm.c
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
13 #include "config.h"
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
18 #include <epan/uat.h>
19 #include <epan/tap.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);
29 /* Protocol handle */
30 static int proto_lbtrm;
32 /* Dissector handle */
33 static dissector_handle_t lbtrm_dissector_handle;
35 /* Tap 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);
51 if (conv != NULL)
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);
63 return (transport);
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);
73 if (conv == NULL)
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);
97 if (conv != NULL)
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);
109 return (entry);
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);
119 if (conv == NULL)
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);
134 if (entry != NULL)
136 return (entry);
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);
157 return (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;
164 switch (type)
166 case LBTRM_PACKET_TYPE_DATA:
167 sqn_entry = (lbm_transport_sqn_t *) wmem_tree_lookup32(transport->data_sqn, sqn);
168 break;
169 case LBTRM_PACKET_TYPE_SM:
170 sqn_entry = (lbm_transport_sqn_t *) wmem_tree_lookup32(transport->sm_sqn, sqn);
171 break;
172 case LBTRM_PACKET_TYPE_NAK:
173 case LBTRM_PACKET_TYPE_NCF:
174 default:
175 sqn_entry = NULL;
176 break;
178 return (sqn_entry);
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;
186 switch (frame->type)
188 case LBTRM_PACKET_TYPE_DATA:
189 sqn_list = transport->data_sqn;
190 break;
191 case LBTRM_PACKET_TYPE_SM:
192 sqn_list = transport->sm_sqn;
193 break;
194 case LBTRM_PACKET_TYPE_NAK:
195 case LBTRM_PACKET_TYPE_NCF:
196 default:
197 return (NULL);
200 /* Add the sqn. */
201 sqn_entry = lbm_transport_sqn_add(sqn_list, frame);
202 return (sqn_entry);
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;
228 switch (type)
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)
241 /* Out of order */
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;
252 else
254 if (!frame_entry->retransmission)
256 if (frame_entry->sqn != (transport->data_high_sqn + 1))
258 /* Gap */
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;
269 break;
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)
278 /* Out of order */
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;
289 else
291 if (frame_entry->sqn != (transport->sm_high_sqn + 1))
293 /* Gap */
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;
303 break;
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;
311 break;
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;
319 break;
322 /* Add the sqn. */
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 */
351 typedef struct
353 lbm_uint8_t ver_type;
354 lbm_uint8_t next_hdr;
355 lbm_uint16_t ucast_port;
356 lbm_uint32_t session_id;
357 } lbtrm_hdr_t;
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 */
375 typedef struct
377 lbm_uint32_t sqn;
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;
382 } lbtrm_data_hdr_t;
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 */
404 typedef struct
406 lbm_uint32_t sm_sqn;
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;
412 } lbtrm_sm_hdr_t;
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 */
432 typedef struct
434 lbm_uint16_t num_naks;
435 lbm_uint16_t format;
436 } lbtrm_nak_hdr_t;
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 */
449 typedef struct
451 lbm_uint32_t trail_sqn;
452 lbm_uint16_t num_ncfs;
453 lbm_uint8_t reserved;
454 lbm_uint8_t reason_format;
455 } lbtrm_ncf_hdr_t;
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 */
474 typedef struct
476 lbm_uint8_t next_hdr;
477 lbm_uint8_t hdr_len;
478 lbm_uint16_t res;
479 } lbtrm_basic_opt_t;
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" },
500 { 0x0, NULL }
503 static const value_string lbtrm_nak_format[] =
505 { LBTRM_NAK_SELECTIVE_FORMAT, "Selective" },
506 { LBTRM_NAK_PARITY_FORMAT, "Parity" },
507 { 0x0, NULL }
510 static const value_string lbtrm_ncf_format[] =
512 { LBTRM_NCF_SELECTIVE_FORMAT, "Selective" },
513 { LBTRM_NCF_PARITY_FORMAT, "Parity" },
514 { 0x0, NULL }
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" },
523 { 0x0, NULL }
526 static const value_string lbtrm_next_header[] =
528 { LBTRM_NHDR_DATA, "Data" },
529 { 0x0, NULL }
532 /*----------------------------------------------------------------------------*/
533 /* Preferences. */
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 /*----------------------------------------------------------------------------*/
583 typedef struct
585 char * name;
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;
590 uint32_t dport_low;
591 uint32_t dport_high;
592 uint32_t sport_low;
593 uint32_t sport_high;
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;
600 } lbtrm_tag_entry_t;
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"),
629 UAT_END_FIELDS
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");
642 return false;
644 else
646 g_strstrip(tag->name);
647 if (tag->name[0] == 0)
649 *error_string = g_strdup("Tag name can't be empty");
650 return false;
653 return true;
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;
676 return (dest);
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)
685 g_free(tag->name);
686 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)
712 unsigned idx;
713 lbtrm_tag_entry_t * tag = NULL;
714 uint32_t dest_addr_h;
716 if (!lbtrm_use_tag)
718 return (NULL);
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. */
735 return (tag->name);
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. */
745 return (tag->name);
748 /* Not ours. */
749 continue;
751 else
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))
756 /* Wrong port. */
757 continue;
759 /* One of ours, so handle it. */
760 return (tag->name);
763 /* Not one of ours. */
764 return (NULL);
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)
865 tvbuff_t * next_tvb;
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;
878 lbm_uint32_t ncf;
879 int idx = 0;
880 int len = 0;
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;
896 len += 4;
898 return (len);
901 static int dissect_lbtrm_ncf(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, lbm_lbtrm_tap_info_t * tap_info)
903 int len = 0;
904 uint16_t num_ncfs;
905 uint8_t reason;
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);
929 return (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;
939 lbm_uint32_t nak;
940 int idx = 0;
941 int len = 0;
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;
957 len += 4;
959 return (len);
962 static int dissect_lbtrm_nak(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, lbm_lbtrm_tap_info_t * tap_info)
964 int len = 0;
965 uint16_t num_naks;
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);
983 return (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,
996 NULL
998 proto_item * sm_sqn_item = NULL;
999 uint32_t sqn;
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)
1013 *sequence = sqn;
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,
1030 NULL
1032 proto_item * sqn_item = NULL;
1033 uint8_t flags_val;
1034 uint32_t sqn;
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)
1048 *sequence = sqn;
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 /*----------------------------------------------------------------------------*/
1067 typedef struct
1069 proto_tree * tree;
1070 tvbuff_t * tvb;
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);
1086 else
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);
1092 return false;
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;
1099 int offset = 0;
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);
1125 if (lbtrm_use_tag)
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);
1146 else
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);
1165 else
1167 transport = lbtrm_transport_add(&(pinfo->src), src_port, session_id, &(pinfo->dst), dest_port, pinfo->num);
1170 else
1172 if (packet_type == LBTRM_PACKET_TYPE_NAK)
1174 transport = lbtrm_transport_unicast_find(&(pinfo->dst), src_port, session_id, pinfo->num);
1176 else
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);
1217 else
1219 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "DATA sqn 0x%x Port %" PRIu16 " ID 0x%08x", sequence, src_port, session_id);
1221 break;
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);
1225 break;
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);
1229 break;
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);
1233 break;
1234 default:
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);
1237 break;
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);
1249 break;
1250 case LBTRM_PACKET_TYPE_SM:
1251 dissected_len = dissect_lbtrm_sm(tvb, offset, pinfo, lbtrm_tree, &sequence, tapinfo);
1252 break;
1253 case LBTRM_PACKET_TYPE_NAK:
1254 dissected_len = dissect_lbtrm_nak(tvb, offset, pinfo, lbtrm_tree, tapinfo);
1255 break;
1256 case LBTRM_PACKET_TYPE_NCF:
1257 dissected_len = dissect_lbtrm_ncf(tvb, offset, pinfo, lbtrm_tree, tapinfo);
1258 break;
1259 default:
1260 return (total_dissected_len);
1262 total_dissected_len += dissected_len;
1263 offset += dissected_len;
1264 while (next_hdr != LBTRM_NHDR_DATA)
1266 uint8_t hdrlen = 0;
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);
1270 if (hdrlen == 0)
1272 break;
1274 offset += hdrlen;
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);
1287 else
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);
1298 if (frame != NULL)
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);
1326 if (sqn != NULL)
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;
1338 cb_data.tvb = tvb;
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);
1367 break;
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);
1380 if (sqn != NULL)
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;
1392 cb_data.tvb = tvb;
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);
1415 break;
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);
1427 break;
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);
1439 break;
1440 default:
1441 break;
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)
1471 return false;
1473 /* Destination address must be IPV4 and 4 bytes in length. */
1474 if ((pinfo->dst.type != AT_IPv4) || (pinfo->dst.len != 4))
1476 return false;
1478 if (tvb_reported_length_remaining(tvb, 0) < L_LBTRM_HDR_T)
1480 return false;
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:
1490 break;
1491 default:
1492 return false;
1494 packet_ver = LBTRM_HDR_VER(ver_type);
1495 if (packet_ver != LBTRM_VERSION)
1497 return false;
1499 next_hdr = tvb_get_uint8(tvb, O_LBTRM_HDR_T_NEXT_HDR);
1500 if (next_hdr != LBTRM_NHDR_DATA)
1502 return false;
1504 if (lbtrm_use_tag)
1506 if (lbtrm_tag_find(pinfo) != NULL)
1508 valid_packet = true;
1511 else
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;
1539 else
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;
1548 if (valid_packet)
1550 dissect_lbtrm(tvb, pinfo, tree, user_data);
1551 return true;
1553 return false;
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 } },
1563 { &hf_lbtrm_tag,
1564 { "Tag", "lbtrm.tag", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1565 { &hf_lbtrm_hdr,
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 } },
1577 { &hf_lbtrm_data,
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 } },
1593 { &hf_lbtrm_sm,
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 } },
1609 { &hf_lbtrm_nak,
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 } },
1619 { &hf_lbtrm_ncf,
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[] =
1678 &ett_lbtrm,
1679 &ett_lbtrm_hdr,
1680 &ett_lbtrm_data,
1681 &ett_lbtrm_data_flags_fec_type,
1682 &ett_lbtrm_sm,
1683 &ett_lbtrm_sm_flags_fec_type,
1684 &ett_lbtrm_nak,
1685 &ett_lbtrm_nak_list,
1686 &ett_lbtrm_ncf,
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;
1709 uint32_t addr;
1710 uat_t * tag_uat;
1711 expert_module_t * expert_lbtrm;
1713 proto_lbtrm = proto_register_protocol("LBT Reliable Multicast Protocol",
1714 "LBT-RM", "lbtrm");
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,
1727 "mc_address_low",
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,
1735 "mc_address_high",
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,
1741 "dport_low",
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,
1748 "dport_high",
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,
1755 "sport_low",
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,
1762 "sport_high",
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,
1821 "use_lbtrm_domain",
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),
1827 "lbtrm_domains",
1828 true,
1829 (void * *)&lbtrm_tag_entry,
1830 &lbtrm_tag_count,
1831 UAT_AFFECTS_DISSECTION,
1832 NULL,
1833 lbtrm_tag_copy_cb,
1834 lbtrm_tag_update_cb,
1835 lbtrm_tag_free_cb,
1836 NULL,
1837 NULL,
1838 lbtrm_tag_array);
1839 prefs_register_uat_preference(lbtrm_module,
1840 "tnw_lbtrm_tags",
1841 "LBT-RM Tags",
1842 "A table to define LBT-RM tags",
1843 tag_uat);
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;
1852 uint32_t addr;
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
1910 * Local variables:
1911 * c-basic-offset: 4
1912 * tab-width: 8
1913 * indent-tabs-mode: nil
1914 * End:
1916 * vi: set shiftwidth=4 tabstop=8 expandtab:
1917 * :indentSize=4:tabSize=8:noTabs=true: