2 * Routines for ETSI Distribution & Communication Protocol
3 * Copyright 2006, British Broadcasting Corporation
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 * Ref: ETSI DCP (ETSI TS 102 821)
18 #include <epan/packet.h>
19 #include <epan/expert.h>
20 #include <epan/reassemble.h>
21 #include <epan/crc16-tvb.h>
22 #include <epan/reedsolomon.h>
23 #include <wsutil/array.h>
25 /* forward reference */
26 void proto_register_dcp_etsi(void);
27 void proto_reg_handoff_dcp_etsi(void);
28 static int dissect_af (tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data
);
29 static int dissect_pft (tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data
);
31 static dissector_handle_t dcp_etsi_handle
;
32 static dissector_handle_t af_handle
;
33 static dissector_handle_t pft_handle
;
34 static dissector_handle_t tpl_handle
;
36 static dissector_table_t dcp_dissector_table
;
37 static dissector_table_t af_dissector_table
;
38 static dissector_table_t tpl_dissector_table
;
40 static int proto_dcp_etsi
;
44 static int hf_edcp_sync
;
45 static int hf_edcp_len
;
46 static int hf_edcp_seq
;
47 static int hf_edcp_crcflag
;
48 static int hf_edcp_maj
;
49 static int hf_edcp_min
;
50 static int hf_edcp_pt
;
51 static int hf_edcp_crc
;
52 static int hf_edcp_crc_ok
;
53 /* static int hf_edcp_pft_pt; */
54 static int hf_edcp_pseq
;
55 static int hf_edcp_findex
;
56 static int hf_edcp_fcount
;
57 static int hf_edcp_fecflag
;
58 static int hf_edcp_addrflag
;
59 static int hf_edcp_plen
;
60 static int hf_edcp_rsk
;
61 static int hf_edcp_rsz
;
62 static int hf_edcp_source
;
63 static int hf_edcp_dest
;
64 static int hf_edcp_hcrc
;
65 static int hf_edcp_hcrc_ok
;
66 /* static int hf_edcp_c_max; */
67 /* static int hf_edcp_rx_min; */
68 /* static int hf_edcp_rs_corrected; */
69 static int hf_edcp_rs_ok
;
70 static int hf_edcp_pft_payload
;
72 static int hf_tpl_tlv
;
73 /* static int hf_tpl_ptr; */
75 static int hf_edcp_fragments
;
76 static int hf_edcp_fragment
;
77 static int hf_edcp_fragment_overlap
;
78 static int hf_edcp_fragment_overlap_conflicts
;
79 static int hf_edcp_fragment_multiple_tails
;
80 static int hf_edcp_fragment_too_long_fragment
;
81 static int hf_edcp_fragment_error
;
82 static int hf_edcp_fragment_count
;
83 static int hf_edcp_reassembled_in
;
84 static int hf_edcp_reassembled_length
;
86 /* Initialize the subtree pointers */
91 static int ett_edcp_fragment
;
92 static int ett_edcp_fragments
;
94 static expert_field ei_edcp_reassembly
;
95 static expert_field ei_edcp_reassembly_info
;
97 static reassembly_table dcp_reassembly_table
;
99 static const fragment_items dcp_frag_items
= {
100 /* Fragment subtrees */
103 /* Fragment fields */
106 &hf_edcp_fragment_overlap
,
107 &hf_edcp_fragment_overlap_conflicts
,
108 &hf_edcp_fragment_multiple_tails
,
109 &hf_edcp_fragment_too_long_fragment
,
110 &hf_edcp_fragment_error
,
111 &hf_edcp_fragment_count
,
112 /* Reassembled in field */
113 &hf_edcp_reassembled_in
,
114 /* Reassembled length field */
115 &hf_edcp_reassembled_length
,
116 /* Reassembled data field */
123 /** Dissect a DCP packet. Details follow
125 * \param[in,out] tvb The buffer containing the packet
126 * \param[in,out] pinfo The packet info structure
127 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
131 dissect_dcp_etsi(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * data _U_
)
134 proto_tree
*dcp_tree
;
137 if(tvb_captured_length(tvb
) < 11)
140 /* Clear out stuff in the info column */
141 col_clear(pinfo
->cinfo
, COL_INFO
);
142 col_set_str (pinfo
->cinfo
, COL_PROTOCOL
, "DCP (ETSI)");
143 /*col_append_fstr (pinfo->cinfo, COL_INFO, " tvb %d", tvb_length(tvb));*/
145 ti
= proto_tree_add_item (tree
, proto_dcp_etsi
, tvb
, 0, -1, ENC_NA
);
146 dcp_tree
= proto_item_add_subtree (ti
, ett_edcp
);
148 sync
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, 2, ENC_ASCII
);
149 dissector_try_string_with_data(dcp_dissector_table
, (char*)sync
, tvb
, pinfo
, dcp_tree
, true, NULL
);
151 return tvb_captured_length(tvb
);
154 /** Heuristic dissector for a DCP packet.
155 * \param[in,out] tvb The buffer containing the packet
156 * \param[in,out] pinfo The packet info structure
157 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
161 dissect_dcp_etsi_heur(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * data
)
163 /* 6.1 AF packet structure
167 * 2 bytes 4 bytes 2 bytes 1 byte 1 byte
169 * SYNC: two-byte ASCII representation of "AF".
170 * LEN: length of the payload, in bytes.
171 * SEQ: sequence number
172 * AR: AF protocol Revision - a field combining the CF, MAJ and MIN fields
173 * CF: CRC Flag, 0 if the CRC field is not used
174 * MAJ: major revision of the AF protocol in use, see clause 6.2.
175 * MIN: minor revision of the AF protocol in use, see clause 6.2.
176 * Protocol Type (PT): single byte encoding the protocol of the data carried in the payload.
177 * For TAG Packets, the value shall be the ASCII representation of "T".
179 * 7.1 PFT fragment structure
181 * 14, 16, 18 or 20 bytes (depending on options) Optional present if FEC=1 Optional present if Addr = 1
182 * Psync Pseq Findex Fcount FEC HCRC Addr Plen | RSk RSz | Source Dest
183 * 16 bits 16 bits 24 bits 24 bits 1 bit 16 bits 1 bit 14 bits | 8 bits 8 bits | 16 bits 16 bits
185 * Psync: the ASCII string "PF" is used as the synchronization word for the PFT Layer
187 * Don't accept this packet unless at least a full AF header present(10 bytes).
188 * It should be possible to strengthen the heuristic further if need be.
192 if(tvb_captured_length(tvb
) < 11)
195 word
= tvb_get_ntohs(tvb
,0);
196 /* Check for 'AF or 'PF' */
197 if (word
== 0x4146) {
198 /* AF - check the version, which is only major 1, minor 0 */
199 if ((tvb_get_uint8(tvb
, 8) & 0x7F) != 0x10) {
202 /* Tag packets are the only payload type */
203 if (tvb_get_uint8(tvb
, 9) != 'T') {
206 } else if (word
== 0x5046) {
207 /* PFT - header length 14, 16, 18, or 20 depending on options.
208 * Always contains CRC. */
209 if (tvb_captured_length(tvb
) < 14) {
212 uint16_t plen
= tvb_get_ntohs(tvb
, 10);
213 unsigned header_len
= 14;
220 if (tvb_captured_length(tvb
) < header_len
) {
223 if (crc16_x25_ccitt_tvb(tvb
, header_len
) != 0x1D0F) {
230 dissect_dcp_etsi(tvb
, pinfo
, tree
, data
);
235 #define PFT_RS_N_MAX 207
237 #define PFT_RS_P (PFT_RS_K - PFT_RS_N_MAX)
241 void rs_deinterleave(const uint8_t *input
, uint8_t *output
, uint16_t plen
, uint32_t fcount
)
244 for(fidx
=0; fidx
<fcount
; fidx
++)
247 for (r
=0; r
<plen
; r
++)
249 output
[fidx
+r
*fcount
] = input
[fidx
*plen
+r
];
255 bool rs_correct_data(uint8_t *deinterleaved
, uint8_t *output
,
256 uint32_t c_max
, uint16_t rsk
, uint16_t rsz _U_
)
258 uint32_t i
, index_coded
= 0, index_out
= 0;
260 for (i
=0; i
<c_max
; i
++)
262 memcpy(output
+index_out
, deinterleaved
+index_coded
, rsk
);
264 memcpy(output
+index_out
+PFT_RS_N_MAX
, deinterleaved
+index_coded
, PFT_RS_P
);
265 index_coded
+= PFT_RS_P
;
266 err_corr
= eras_dec_rs(output
+index_out
, NULL
, 0);
275 /* Don't attempt reassembly if we have a huge number of fragments. */
276 #define MAX_FRAGMENTS ((1 * 1024 * 1024) / sizeof(uint32_t))
277 /* If we missed more than this number of consecutive fragments,
278 we don't attempt reassembly */
279 #define MAX_FRAG_GAP 1000
282 dissect_pft_fec_detailed(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
,
294 uint32_t decoded_size
;
297 tvbuff_t
*new_tvb
=NULL
;
299 if (fcount
> MAX_FRAGMENTS
) {
300 proto_tree_add_expert_format(tree
, pinfo
, &ei_edcp_reassembly
, tvb
, 0, -1, "[Reassembly of %d fragments not attempted]", fcount
);
304 decoded_size
= fcount
*plen
;
305 c_max
= fcount
*plen
/(rsk
+PFT_RS_P
); /* rounded down */
306 rx_min
= fcount
- (c_max
*PFT_RS_P
/plen
);
308 new_tvb
= process_reassembled_data (tvb
, offset
, pinfo
,
309 "Reassembled DCP (ETSI)",
310 fdx
, &dcp_frag_items
,
313 unsigned fragments
=0;
316 fragment_head
*fd_head
;
318 proto_tree_add_expert_format(tree
, pinfo
, &ei_edcp_reassembly_info
, tvb
, 0, -1, "want %d, got %d need %d",
319 fcount
, fragments
, rx_min
);
320 got
= (uint32_t *)wmem_alloc(pinfo
->pool
, fcount
*sizeof(uint32_t));
322 /* make a list of the findex (offset) numbers of the fragments we have */
323 fd_head
= fragment_get(&dcp_reassembly_table
, pinfo
, seq
, NULL
);
325 for (fd
= fd_head
->next
; fd
!= NULL
&& fragments
< fcount
; fd
= fd
->next
) {
327 got
[fragments
++] = fd
->offset
; /* this is the findex of the fragment */
331 /* have we got enough for Reed Solomon to try to correct ? */
332 if(fragments
>=rx_min
) { /* yes, in theory */
333 unsigned i
,current_findex
;
334 fragment_head
*frag
=NULL
;
335 uint8_t *dummy_data
= (uint8_t*) wmem_alloc0 (pinfo
->pool
, plen
);
336 tvbuff_t
*dummytvb
= tvb_new_real_data(dummy_data
, plen
, plen
);
337 /* try and decode with missing fragments */
338 proto_tree_add_expert_format(tree
, pinfo
, &ei_edcp_reassembly_info
, tvb
, 0, -1, "want %d, got %d need %d",
339 fcount
, fragments
, rx_min
);
340 /* fill the fragment table with empty fragments */
342 for(i
=0; i
<fragments
; i
++) {
343 unsigned next_fragment_we_have
= got
[i
];
344 if (next_fragment_we_have
> MAX_FRAGMENTS
) {
345 proto_tree_add_expert_format(tree
, pinfo
, &ei_edcp_reassembly
, tvb
, 0, -1, "[Reassembly of %d fragments not attempted]", next_fragment_we_have
);
348 if (next_fragment_we_have
-current_findex
> MAX_FRAG_GAP
) {
349 proto_tree_add_expert_format(tree
, pinfo
, &ei_edcp_reassembly
, tvb
, 0, -1,
350 "[Missing %d consecutive packets. Don't attempt reassembly]",
351 next_fragment_we_have
-current_findex
);
354 for(; current_findex
<next_fragment_we_have
; current_findex
++) {
355 frag
= fragment_add_seq_check (&dcp_reassembly_table
,
356 dummytvb
, 0, pinfo
, seq
, NULL
,
357 current_findex
, plen
, (current_findex
+1!=fcount
));
359 current_findex
++; /* skip over the fragment we have */
364 new_tvb
= process_reassembled_data (tvb
, offset
, pinfo
,
365 "Reassembled DCP (ETSI)",
366 frag
, &dcp_frag_items
,
370 if(new_tvb
&& tvb_captured_length(new_tvb
) > 0) {
372 tvbuff_t
*dtvb
= NULL
;
373 const uint8_t *input
= tvb_get_ptr(new_tvb
, 0, -1);
374 uint32_t reassembled_size
= tvb_captured_length(new_tvb
);
375 uint8_t *deinterleaved
= (uint8_t*) wmem_alloc(pinfo
->pool
, reassembled_size
);
376 uint8_t *output
= (uint8_t*) wmem_alloc(pinfo
->pool
, decoded_size
);
377 rs_deinterleave(input
, deinterleaved
, plen
, fcount
);
379 dtvb
= tvb_new_child_real_data(tvb
, deinterleaved
, reassembled_size
, reassembled_size
);
380 add_new_data_source(pinfo
, dtvb
, "Deinterleaved");
382 decoded
= rs_correct_data(deinterleaved
, output
, c_max
, rsk
, rsz
);
383 proto_tree_add_boolean (tree
, hf_edcp_rs_ok
, tvb
, offset
, 2, decoded
);
385 new_tvb
= tvb_new_child_real_data(dtvb
, output
, decoded_size
, decoded_size
);
386 add_new_data_source(pinfo
, new_tvb
, "RS Error Corrected Data");
392 /** Handle a PFT packet which has the fragmentation header. This uses the
393 * standard wireshark methods for reassembling fragments. If FEC is used,
394 * the FEC is handled too. For the moment, all the fragments must be
395 * available but this could be improved.
396 * \param[in,out] tvb The buffer containing the current fragment
397 * \param[in,out] pinfo The packet info structure
398 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
399 * \param[in] findex the fragment count
400 * \param[in] fcount the number of fragments
401 * \param[in] seq the sequence number of the reassembled packet
402 * \param[in] offset the offset into the tvb of the fragment
403 * \param[in] plen the length of each fragment
404 * \param[in] fec is fec used
405 * \param[in] rsk the number of useful bytes in each chunk
406 * \param[in] rsz the number of padding bytes in each chunk
409 dissect_pft_fragmented(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
,
421 tvbuff_t
*new_tvb
=NULL
;
422 fragment_head
*frag_edcp
= NULL
;
423 pinfo
->fragmented
= true;
425 last
= fcount
== (findex
+1);
426 frag_edcp
= fragment_add_seq_check (
427 &dcp_reassembly_table
,
434 new_tvb
= dissect_pft_fec_detailed(
435 tvb
, pinfo
, tree
, findex
, fcount
, seq
, offset
, plen
, fec
, rsk
, rsz
, frag_edcp
438 new_tvb
= process_reassembled_data (tvb
, offset
, pinfo
,
439 "Reassembled DCP (ETSI)",
440 frag_edcp
, &dcp_frag_items
,
444 col_append_str (pinfo
->cinfo
, COL_INFO
, " (Message Reassembled)");
447 col_append_str (pinfo
->cinfo
, COL_INFO
, " (Message Reassembly failure)");
449 col_append_fstr (pinfo
->cinfo
, COL_INFO
, " (Message fragment %u)", findex
);
453 col_append_str (pinfo
->cinfo
, COL_INFO
, " (first)");
455 col_append_str (pinfo
->cinfo
, COL_INFO
, " (last)");
459 /** Dissect a PFT packet. Details follow
461 * \param[in,out] tvb The buffer containing the packet
462 * \param[in,out] pinfo The packet info structure
463 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
466 dissect_pft(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data
)
470 uint16_t seq
, payload_len
;
471 uint32_t findex
, fcount
;
472 proto_tree
*pft_tree
;
474 tvbuff_t
*next_tvb
= NULL
;
476 uint16_t rsk
=0, rsz
=0;
478 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DCP-PFT");
480 ti
= proto_tree_add_item (tree
, proto_pft
, tvb
, 0, -1, ENC_NA
);
481 pft_tree
= proto_item_add_subtree (ti
, ett_pft
);
482 proto_tree_add_item (pft_tree
, hf_edcp_sync
, tvb
, offset
, 2, ENC_ASCII
);
485 seq
= tvb_get_ntohs (tvb
, offset
);
486 proto_tree_add_item (pft_tree
, hf_edcp_pseq
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
489 findex
= tvb_get_ntoh24 (tvb
, offset
);
490 proto_tree_add_item (pft_tree
, hf_edcp_findex
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
493 fcount
= tvb_get_ntoh24 (tvb
, offset
);
494 proto_tree_add_item (pft_tree
, hf_edcp_fcount
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
497 plen
= tvb_get_ntohs (tvb
, offset
);
498 payload_len
= plen
& 0x3fff;
499 proto_tree_add_item (pft_tree
, hf_edcp_fecflag
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
500 proto_tree_add_item (pft_tree
, hf_edcp_addrflag
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
501 li
= proto_tree_add_item (pft_tree
, hf_edcp_plen
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
506 rsk
= tvb_get_uint8 (tvb
, offset
);
507 proto_tree_add_item (pft_tree
, hf_edcp_rsk
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
509 rsz
= tvb_get_uint8 (tvb
, offset
);
510 proto_tree_add_item (pft_tree
, hf_edcp_rsz
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
514 proto_tree_add_item (pft_tree
, hf_edcp_source
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
516 proto_tree_add_item (pft_tree
, hf_edcp_dest
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
520 proto_item
*ci
= NULL
;
521 unsigned header_len
= offset
+2;
522 uint16_t c
= crc16_x25_ccitt_tvb(tvb
, header_len
);
523 ci
= proto_tree_add_item (pft_tree
, hf_edcp_hcrc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
524 proto_item_append_text(ci
, " (%s)", (c
==0x1D0F)?"Ok":"bad");
525 proto_tree_add_boolean(pft_tree
, hf_edcp_hcrc_ok
, tvb
, offset
, 2, c
==0x1D0F);
528 if (fcount
> 1) { /* fragmented*/
529 bool save_fragmented
= pinfo
->fragmented
;
530 uint16_t real_len
= tvb_captured_length(tvb
)-offset
;
531 proto_tree_add_item (pft_tree
, hf_edcp_pft_payload
, tvb
, offset
, real_len
, ENC_NA
);
532 if(real_len
!= payload_len
|| real_len
== 0) {
533 proto_item_append_text(li
, " (length error (%d))", real_len
);
536 next_tvb
= dissect_pft_fragmented(tvb
, pinfo
, pft_tree
, findex
, fcount
,
537 seq
, offset
, real_len
, fec
, rsk
, rsz
);
539 pinfo
->fragmented
= save_fragmented
;
541 next_tvb
= tvb_new_subset_remaining (tvb
, offset
);
544 dissect_af(next_tvb
, pinfo
, tree
, data
);
546 return tvb_captured_length(tvb
);
549 /** Dissect an AF Packet. Parse an AF packet, checking the CRC if the CRC valid
550 * flag is set and calling any registered sub dissectors on the payload type.
551 * Currently only a payload type 'T' is defined which is the tag packet layer.
552 * If any others are defined then they can register themselves.
553 * \param[in,out] tvb The buffer containing the packet
554 * \param[in,out] pinfo The packet info structure
555 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
558 dissect_af (tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
)
562 proto_item
*li
= NULL
;
566 uint32_t payload_len
;
567 tvbuff_t
*next_tvb
= NULL
;
569 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DCP-AF");
571 ti
= proto_tree_add_item (tree
, proto_af
, tvb
, 0, -1, ENC_NA
);
572 af_tree
= proto_item_add_subtree (ti
, ett_af
);
573 proto_tree_add_item (af_tree
, hf_edcp_sync
, tvb
, offset
, 2, ENC_ASCII
);
576 payload_len
= tvb_get_ntohl(tvb
, offset
);
578 uint32_t real_payload_len
= tvb_captured_length(tvb
)-12;
579 li
= proto_tree_add_item (af_tree
, hf_edcp_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
580 if(real_payload_len
< payload_len
) {
581 proto_item_append_text (li
, " (wrong len claims %d is %d)",
582 payload_len
, real_payload_len
584 } else if(real_payload_len
> payload_len
) {
585 proto_item_append_text (li
, " (%d bytes in packet after end of AF frame)",
586 real_payload_len
-payload_len
591 proto_tree_add_item (af_tree
, hf_edcp_seq
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
593 ver
= tvb_get_uint8 (tvb
, offset
);
594 proto_tree_add_item (af_tree
, hf_edcp_crcflag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
595 proto_tree_add_item (af_tree
, hf_edcp_maj
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
596 proto_tree_add_item (af_tree
, hf_edcp_min
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
599 pt
= tvb_get_uint8 (tvb
, offset
);
600 proto_tree_add_item (af_tree
, hf_edcp_pt
, tvb
, offset
, 1, ENC_ASCII
);
602 next_tvb
= tvb_new_subset_length(tvb
, offset
, payload_len
);
603 offset
+= payload_len
;
604 ci
= proto_tree_add_item (af_tree
, hf_edcp_crc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
605 if (ver
& 0x80) { /* crc valid */
606 unsigned len
= offset
+2;
607 uint16_t c
= crc16_x25_ccitt_tvb(tvb
, len
);
608 proto_item_append_text(ci
, " (%s)", (c
==0x1D0F)?"Ok":"bad");
609 proto_tree_add_boolean(af_tree
, hf_edcp_crc_ok
, tvb
, offset
, 2, c
==0x1D0F);
613 dissector_try_uint(af_dissector_table
, pt
, next_tvb
, pinfo
, tree
);
614 return tvb_captured_length(tvb
);
617 /** Dissect the Tag Packet Layer.
618 * Split the AF packet into its tag items. Each tag item has a 4 character
619 * tag, a length in bits and a value. The *ptr tag is dissected in the routine.
620 * All other tags are listed and may be handled by other dissectors.
621 * Child dissectors are tied to the parent tree, not to this tree, so that
622 * they appear at the same level as DCP.
623 * \param[in,out] tvb The buffer containing the packet
624 * \param[in,out] pinfo The packet info structure
625 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
628 dissect_tpl(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
)
630 proto_tree
*tpl_tree
;
634 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DCP-TPL");
636 ti
= proto_tree_add_item (tree
, proto_tpl
, tvb
, 0, -1, ENC_NA
);
637 tpl_tree
= proto_item_add_subtree (ti
, ett_tpl
);
639 while(offset
<tvb_reported_length(tvb
)) {
643 char *tag
= (char*)tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, 4, ENC_ASCII
);
644 bits
= tvb_get_ntohl(tvb
, offset
+4);
649 proto_tree_add_bytes_format(tpl_tree
, hf_tpl_tlv
, tvb
,
650 offset
, 8+bytes
, NULL
,
651 "%s (%u bits)", tag
, bits
);
653 next_tvb
= tvb_new_subset_length(tvb
, offset
+8, bytes
);
654 dissector_try_string_with_data(tpl_dissector_table
, tag
, next_tvb
, pinfo
, tree
, true, NULL
);
659 return tvb_captured_length(tvb
);
663 proto_reg_handoff_dcp_etsi (void)
665 heur_dissector_add("udp", dissect_dcp_etsi_heur
, "DCP (ETSI) over UDP", "dcp_etsi_udp", proto_dcp_etsi
, HEURISTIC_ENABLE
);
666 dissector_add_for_decode_as("udp.port", dcp_etsi_handle
);
667 dissector_add_string("dcp-etsi.sync", "AF", af_handle
);
668 dissector_add_string("dcp-etsi.sync", "PF", pft_handle
);
669 /* if there are ever other payload types ...*/
670 dissector_add_uint("dcp-af.pt", 'T', tpl_handle
);
674 proto_register_dcp_etsi (void)
676 static hf_register_info hf_edcp
[] = {
678 {"sync", "dcp-etsi.sync",
679 FT_STRING
, BASE_NONE
, NULL
, 0,
683 static hf_register_info hf_af
[] = {
685 {"length", "dcp-af.len",
686 FT_UINT32
, BASE_DEC
, NULL
, 0,
687 "length in bytes of the payload", HFILL
}
690 {"frame count", "dcp-af.seq",
691 FT_UINT16
, BASE_DEC
, NULL
, 0,
692 "Logical Frame Number", HFILL
}
695 {"crc flag", "dcp-af.crcflag",
696 FT_BOOLEAN
, 8, NULL
, 0x80,
697 "Frame is protected by CRC", HFILL
}
700 {"Major Revision", "dcp-af.maj",
701 FT_UINT8
, BASE_DEC
, NULL
, 0x70,
702 "Major Protocol Revision", HFILL
}
705 {"Minor Revision", "dcp-af.min",
706 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
707 "Minor Protocol Revision", HFILL
}
710 {"Payload Type", "dcp-af.pt",
711 FT_STRING
, BASE_NONE
, NULL
, 0,
712 "T means Tag Packets, all other values reserved", HFILL
}
715 {"CRC", "dcp-af.crc",
716 FT_UINT16
, BASE_HEX
, NULL
, 0,
720 {"CRC OK", "dcp-af.crc_ok",
721 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
726 static hf_register_info hf_pft
[] = {
729 {"Sub-protocol", "dcp-pft.pt",
730 FT_UINT8
, BASE_DEC
, NULL
, 0,
735 {"Sequence No", "dcp-pft.seq",
736 FT_UINT16
, BASE_DEC
, NULL
, 0,
737 "PFT Sequence No", HFILL
}
740 {"Fragment Index", "dcp-pft.findex",
741 FT_UINT24
, BASE_DEC
, NULL
, 0,
742 "Index of the fragment within one AF Packet", HFILL
}
745 {"Fragment Count", "dcp-pft.fcount",
746 FT_UINT24
, BASE_DEC
, NULL
, 0,
747 "Number of fragments produced from this AF Packet", HFILL
}
750 {"FEC", "dcp-pft.fec",
751 FT_BOOLEAN
, 16, NULL
, 0x8000,
752 "When set the optional RS header is present", HFILL
}
755 {"Addr", "dcp-pft.addr",
756 FT_BOOLEAN
, 16, NULL
, 0x4000,
757 "When set the optional transport header is present", HFILL
}
760 {"fragment length", "dcp-pft.len",
761 FT_UINT16
, BASE_DEC
, NULL
, 0x3fff,
762 "length in bytes of the payload of this fragment", HFILL
}
765 {"RSk", "dcp-pft.rsk",
766 FT_UINT8
, BASE_DEC
, NULL
, 0,
767 "The length of the Reed Solomon data word", HFILL
}
770 {"RSz", "dcp-pft.rsz",
771 FT_UINT8
, BASE_DEC
, NULL
, 0,
772 "The number of padding bytes in the last Reed Solomon block", HFILL
}
775 {"source addr", "dcp-pft.source",
776 FT_UINT16
, BASE_DEC
, NULL
, 0,
777 "PFT source identifier", HFILL
}
780 {"dest addr", "dcp-pft.dest",
781 FT_UINT16
, BASE_DEC
, NULL
, 0,
782 "PFT destination identifier", HFILL
}
785 {"header CRC", "dcp-pft.crc",
786 FT_UINT16
, BASE_HEX
, NULL
, 0,
787 "PFT Header CRC", HFILL
}
790 {"PFT CRC OK", "dcp-pft.crc_ok",
791 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
792 "PFT Header CRC OK", HFILL
}
795 {"Message fragments", "dcp-pft.fragments",
796 FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
798 {"Message fragment", "dcp-pft.fragment",
799 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
800 {&hf_edcp_fragment_overlap
,
801 {"Message fragment overlap", "dcp-pft.fragment.overlap",
802 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
803 {&hf_edcp_fragment_overlap_conflicts
,
804 {"Message fragment overlapping with conflicting data",
805 "dcp-pft.fragment.overlap.conflicts",
806 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
807 {&hf_edcp_fragment_multiple_tails
,
808 {"Message has multiple tail fragments",
809 "dcp-pft.fragment.multiple_tails",
810 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
811 {&hf_edcp_fragment_too_long_fragment
,
812 {"Message fragment too long", "dcp-pft.fragment.too_long_fragment",
813 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
814 {&hf_edcp_fragment_error
,
815 {"Message defragmentation error", "dcp-pft.fragment.error",
816 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
817 {&hf_edcp_fragment_count
,
818 {"Message fragment count", "dcp-pft.fragment.count",
819 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
820 {&hf_edcp_reassembled_in
,
821 {"Reassembled in", "dcp-pft.reassembled.in",
822 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
823 {&hf_edcp_reassembled_length
,
824 {"Reassembled DCP (ETSI) length", "dcp-pft.reassembled.length",
825 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
828 {"C max", "dcp-pft.cmax",
829 FT_UINT16
, BASE_DEC
, NULL
, 0,
830 "Maximum number of RS chunks sent", HFILL
}
833 {"Rx min", "dcp-pft.rxmin",
834 FT_UINT16
, BASE_DEC
, NULL
, 0,
835 "Minimum number of fragments needed for RS decode", HFILL
}
837 {&hf_edcp_rs_corrected
,
838 {"RS Symbols Corrected", "dcp-pft.rs_corrected",
839 FT_INT16
, BASE_DEC
, NULL
, 0,
840 "Number of symbols corrected by RS decode or -1 for failure", HFILL
}
844 {"RS decode OK", "dcp-pft.rs_ok",
845 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
846 "successfully decoded RS blocks", HFILL
}
848 {&hf_edcp_pft_payload
,
849 {"payload", "dcp-pft.payload",
850 FT_BYTES
, BASE_NONE
, NULL
, 0,
851 "PFT Payload", HFILL
}
855 static hf_register_info hf_tpl
[] = {
857 {"tag", "dcp-tpl.tlv",
858 FT_BYTES
, BASE_NONE
, NULL
, 0,
863 {"Type", "dcp-tpl.ptr",
864 FT_STRING
, BASE_NONE
, NULL
, 0,
865 "Protocol Type & Revision", HFILL
}
870 /* Setup protocol subtree array */
871 static int *ett
[] = {
880 static ei_register_info ei
[] = {
881 { &ei_edcp_reassembly
, { "dcp-etsi.reassembly_failed", PI_REASSEMBLE
, PI_ERROR
, "Reassembly failed", EXPFILL
}},
882 { &ei_edcp_reassembly_info
, { "dcp-etsi.reassembly_info", PI_REASSEMBLE
, PI_CHAT
, "Reassembly information", EXPFILL
}},
885 expert_module_t
* expert_dcp_etsi
;
887 proto_dcp_etsi
= proto_register_protocol ("ETSI Distribution & Communication Protocol (for DRM)", /* name */
888 "DCP (ETSI)", /* short name */
889 "dcp-etsi" /* abbrev */
891 proto_af
= proto_register_protocol ("DCP Application Framing Layer", "DCP-AF", "dcp-af");
892 proto_pft
= proto_register_protocol ("DCP Protection, Fragmentation & Transport Layer", "DCP-PFT", "dcp-pft");
893 proto_tpl
= proto_register_protocol ("DCP Tag Packet Layer", "DCP-TPL", "dcp-tpl");
895 proto_register_field_array (proto_dcp_etsi
, hf_edcp
, array_length (hf_edcp
));
896 proto_register_field_array (proto_af
, hf_af
, array_length (hf_af
));
897 proto_register_field_array (proto_pft
, hf_pft
, array_length (hf_pft
));
898 proto_register_field_array (proto_tpl
, hf_tpl
, array_length (hf_tpl
));
899 proto_register_subtree_array (ett
, array_length (ett
));
900 expert_dcp_etsi
= expert_register_protocol(proto_dcp_etsi
);
901 expert_register_field_array(expert_dcp_etsi
, ei
, array_length(ei
));
903 /* subdissector code */
904 dcp_dissector_table
= register_dissector_table("dcp-etsi.sync",
905 "DCP Sync", proto_dcp_etsi
, FT_STRING
, STRING_CASE_SENSITIVE
);
906 af_dissector_table
= register_dissector_table("dcp-af.pt",
907 "DCP-AF Payload Type", proto_dcp_etsi
, FT_UINT8
, BASE_DEC
);
909 tpl_dissector_table
= register_dissector_table("dcp-tpl.ptr",
910 "DCP-TPL Protocol Type & Revision", proto_dcp_etsi
, FT_STRING
, STRING_CASE_SENSITIVE
);
912 reassembly_table_register (&dcp_reassembly_table
,
913 &addresses_reassembly_table_functions
);
915 dcp_etsi_handle
= register_dissector("dcp-etsi", dissect_dcp_etsi
, proto_dcp_etsi
);
916 af_handle
= register_dissector("dcp-af", dissect_af
, proto_af
);
917 pft_handle
= register_dissector("dcp-pft", dissect_pft
, proto_pft
);
918 tpl_handle
= register_dissector("dcp-tpl", dissect_tpl
, proto_tpl
);
922 * Editor modelines - https://www.wireshark.org/tools/modelines.html
927 * indent-tabs-mode: nil
930 * vi: set shiftwidth=2 tabstop=8 expandtab:
931 * :indentSize=2:tabSize=8:noTabs=true: