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>
24 /* forward reference */
25 void proto_register_dcp_etsi(void);
26 void proto_reg_handoff_dcp_etsi(void);
27 static int dissect_af (tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data
);
28 static int dissect_pft (tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data
);
30 static dissector_handle_t dcp_etsi_handle
;
31 static dissector_handle_t af_handle
;
32 static dissector_handle_t pft_handle
;
33 static dissector_handle_t tpl_handle
;
35 static dissector_table_t dcp_dissector_table
;
36 static dissector_table_t af_dissector_table
;
37 static dissector_table_t tpl_dissector_table
;
39 static int proto_dcp_etsi
;
43 static int hf_edcp_sync
;
44 static int hf_edcp_len
;
45 static int hf_edcp_seq
;
46 static int hf_edcp_crcflag
;
47 static int hf_edcp_maj
;
48 static int hf_edcp_min
;
49 static int hf_edcp_pt
;
50 static int hf_edcp_crc
;
51 static int hf_edcp_crc_ok
;
52 /* static int hf_edcp_pft_pt; */
53 static int hf_edcp_pseq
;
54 static int hf_edcp_findex
;
55 static int hf_edcp_fcount
;
56 static int hf_edcp_fecflag
;
57 static int hf_edcp_addrflag
;
58 static int hf_edcp_plen
;
59 static int hf_edcp_rsk
;
60 static int hf_edcp_rsz
;
61 static int hf_edcp_source
;
62 static int hf_edcp_dest
;
63 static int hf_edcp_hcrc
;
64 static int hf_edcp_hcrc_ok
;
65 /* static int hf_edcp_c_max; */
66 /* static int hf_edcp_rx_min; */
67 /* static int hf_edcp_rs_corrected; */
68 static int hf_edcp_rs_ok
;
69 static int hf_edcp_pft_payload
;
71 static int hf_tpl_tlv
;
72 /* static int hf_tpl_ptr; */
74 static int hf_edcp_fragments
;
75 static int hf_edcp_fragment
;
76 static int hf_edcp_fragment_overlap
;
77 static int hf_edcp_fragment_overlap_conflicts
;
78 static int hf_edcp_fragment_multiple_tails
;
79 static int hf_edcp_fragment_too_long_fragment
;
80 static int hf_edcp_fragment_error
;
81 static int hf_edcp_fragment_count
;
82 static int hf_edcp_reassembled_in
;
83 static int hf_edcp_reassembled_length
;
85 /* Initialize the subtree pointers */
90 static int ett_edcp_fragment
;
91 static int ett_edcp_fragments
;
93 static expert_field ei_edcp_reassembly
;
94 static expert_field ei_edcp_reassembly_info
;
96 static reassembly_table dcp_reassembly_table
;
98 static const fragment_items dcp_frag_items
= {
99 /* Fragment subtrees */
102 /* Fragment fields */
105 &hf_edcp_fragment_overlap
,
106 &hf_edcp_fragment_overlap_conflicts
,
107 &hf_edcp_fragment_multiple_tails
,
108 &hf_edcp_fragment_too_long_fragment
,
109 &hf_edcp_fragment_error
,
110 &hf_edcp_fragment_count
,
111 /* Reassembled in field */
112 &hf_edcp_reassembled_in
,
113 /* Reassembled length field */
114 &hf_edcp_reassembled_length
,
115 /* Reassembled data field */
122 /** Dissect a DCP packet. Details follow
124 * \param[in,out] tvb The buffer containing the packet
125 * \param[in,out] pinfo The packet info structure
126 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
130 dissect_dcp_etsi(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * data _U_
)
133 proto_tree
*dcp_tree
;
136 if(tvb_captured_length(tvb
) < 11)
139 /* Clear out stuff in the info column */
140 col_clear(pinfo
->cinfo
, COL_INFO
);
141 col_set_str (pinfo
->cinfo
, COL_PROTOCOL
, "DCP (ETSI)");
142 /*col_append_fstr (pinfo->cinfo, COL_INFO, " tvb %d", tvb_length(tvb));*/
144 ti
= proto_tree_add_item (tree
, proto_dcp_etsi
, tvb
, 0, -1, ENC_NA
);
145 dcp_tree
= proto_item_add_subtree (ti
, ett_edcp
);
147 sync
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, 2, ENC_ASCII
);
148 dissector_try_string(dcp_dissector_table
, (char*)sync
, tvb
, pinfo
, dcp_tree
, NULL
);
150 return tvb_captured_length(tvb
);
153 /** Heuristic dissector for a DCP packet.
154 * \param[in,out] tvb The buffer containing the packet
155 * \param[in,out] pinfo The packet info structure
156 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
160 dissect_dcp_etsi_heur(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * data
)
162 /* 6.1 AF packet structure
166 * 2 bytes 4 bytes 2 bytes 1 byte 1 byte
168 * SYNC: two-byte ASCII representation of "AF".
169 * LEN: length of the payload, in bytes.
170 * SEQ: sequence number
171 * AR: AF protocol Revision - a field combining the CF, MAJ and MIN fields
172 * CF: CRC Flag, 0 if the CRC field is not used
173 * MAJ: major revision of the AF protocol in use, see clause 6.2.
174 * MIN: minor revision of the AF protocol in use, see clause 6.2.
175 * Protocol Type (PT): single byte encoding the protocol of the data carried in the payload.
176 * For TAG Packets, the value shall be the ASCII representation of "T".
178 * 7.1 PFT fragment structure
180 * 14, 16, 18 or 20 bytes (depending on options) Optional present if FEC=1 Optional present if Addr = 1
181 * Psync Pseq Findex Fcount FEC HCRC Addr Plen | RSk RSz | Source Dest
182 * 16 bits 16 bits 24 bits 24 bits 1 bit 16 bits 1 bit 14 bits | 8 bits 8 bits | 16 bits 16 bits
184 * Psync: the ASCII string "PF" is used as the synchronization word for the PFT Layer
186 * Don't accept this packet unless at least a full AF header present(10 bytes).
187 * It should be possible to strengthen the heuristic further if need be.
191 if(tvb_captured_length(tvb
) < 11)
194 word
= tvb_get_ntohs(tvb
,0);
195 /* Check for 'AF or 'PF' */
196 if (word
== 0x4146) {
197 /* AF - check the version, which is only major 1, minor 0 */
198 if ((tvb_get_uint8(tvb
, 8) & 0x7F) != 0x10) {
201 /* Tag packets are the only payload type */
202 if (tvb_get_uint8(tvb
, 9) != 'T') {
205 } else if (word
== 0x5046) {
206 /* PFT - header length 14, 16, 18, or 20 depending on options.
207 * Always contains CRC. */
208 if (tvb_captured_length(tvb
) < 14) {
211 uint16_t plen
= tvb_get_ntohs(tvb
, 10);
212 unsigned header_len
= 14;
219 if (tvb_captured_length(tvb
) < header_len
) {
222 if (crc16_x25_ccitt_tvb(tvb
, header_len
) != 0x1D0F) {
229 dissect_dcp_etsi(tvb
, pinfo
, tree
, data
);
234 #define PFT_RS_N_MAX 207
236 #define PFT_RS_P (PFT_RS_K - PFT_RS_N_MAX)
240 void rs_deinterleave(const uint8_t *input
, uint8_t *output
, uint16_t plen
, uint32_t fcount
)
243 for(fidx
=0; fidx
<fcount
; fidx
++)
246 for (r
=0; r
<plen
; r
++)
248 output
[fidx
+r
*fcount
] = input
[fidx
*plen
+r
];
254 bool rs_correct_data(uint8_t *deinterleaved
, uint8_t *output
,
255 uint32_t c_max
, uint16_t rsk
, uint16_t rsz _U_
)
257 uint32_t i
, index_coded
= 0, index_out
= 0;
259 for (i
=0; i
<c_max
; i
++)
261 memcpy(output
+index_out
, deinterleaved
+index_coded
, rsk
);
263 memcpy(output
+index_out
+PFT_RS_N_MAX
, deinterleaved
+index_coded
, PFT_RS_P
);
264 index_coded
+= PFT_RS_P
;
265 err_corr
= eras_dec_rs(output
+index_out
, NULL
, 0);
274 /* Don't attempt reassembly if we have a huge number of fragments. */
275 #define MAX_FRAGMENTS ((1 * 1024 * 1024) / sizeof(uint32_t))
276 /* If we missed more than this number of consecutive fragments,
277 we don't attempt reassembly */
278 #define MAX_FRAG_GAP 1000
281 dissect_pft_fec_detailed(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
,
293 uint32_t decoded_size
;
296 tvbuff_t
*new_tvb
=NULL
;
298 if (fcount
> MAX_FRAGMENTS
) {
299 proto_tree_add_expert_format(tree
, pinfo
, &ei_edcp_reassembly
, tvb
, 0, -1, "[Reassembly of %d fragments not attempted]", fcount
);
303 decoded_size
= fcount
*plen
;
304 c_max
= fcount
*plen
/(rsk
+PFT_RS_P
); /* rounded down */
305 rx_min
= fcount
- (c_max
*PFT_RS_P
/plen
);
307 new_tvb
= process_reassembled_data (tvb
, offset
, pinfo
,
308 "Reassembled DCP (ETSI)",
309 fdx
, &dcp_frag_items
,
312 unsigned fragments
=0;
315 fragment_head
*fd_head
;
317 proto_tree_add_expert_format(tree
, pinfo
, &ei_edcp_reassembly_info
, tvb
, 0, -1, "want %d, got %d need %d",
318 fcount
, fragments
, rx_min
);
319 got
= (uint32_t *)wmem_alloc(pinfo
->pool
, fcount
*sizeof(uint32_t));
321 /* make a list of the findex (offset) numbers of the fragments we have */
322 fd_head
= fragment_get(&dcp_reassembly_table
, pinfo
, seq
, NULL
);
324 for (fd
= fd_head
->next
; fd
!= NULL
&& fragments
< fcount
; fd
= fd
->next
) {
326 got
[fragments
++] = fd
->offset
; /* this is the findex of the fragment */
330 /* have we got enough for Reed Solomon to try to correct ? */
331 if(fragments
>=rx_min
) { /* yes, in theory */
332 unsigned i
,current_findex
;
333 fragment_head
*frag
=NULL
;
334 uint8_t *dummy_data
= (uint8_t*) wmem_alloc0 (pinfo
->pool
, plen
);
335 tvbuff_t
*dummytvb
= tvb_new_real_data(dummy_data
, plen
, plen
);
336 /* try and decode with missing fragments */
337 proto_tree_add_expert_format(tree
, pinfo
, &ei_edcp_reassembly_info
, tvb
, 0, -1, "want %d, got %d need %d",
338 fcount
, fragments
, rx_min
);
339 /* fill the fragment table with empty fragments */
341 for(i
=0; i
<fragments
; i
++) {
342 unsigned next_fragment_we_have
= got
[i
];
343 if (next_fragment_we_have
> MAX_FRAGMENTS
) {
344 proto_tree_add_expert_format(tree
, pinfo
, &ei_edcp_reassembly
, tvb
, 0, -1, "[Reassembly of %d fragments not attempted]", next_fragment_we_have
);
347 if (next_fragment_we_have
-current_findex
> MAX_FRAG_GAP
) {
348 proto_tree_add_expert_format(tree
, pinfo
, &ei_edcp_reassembly
, tvb
, 0, -1,
349 "[Missing %d consecutive packets. Don't attempt reassembly]",
350 next_fragment_we_have
-current_findex
);
353 for(; current_findex
<next_fragment_we_have
; current_findex
++) {
354 frag
= fragment_add_seq_check (&dcp_reassembly_table
,
355 dummytvb
, 0, pinfo
, seq
, NULL
,
356 current_findex
, plen
, (current_findex
+1!=fcount
));
358 current_findex
++; /* skip over the fragment we have */
363 new_tvb
= process_reassembled_data (tvb
, offset
, pinfo
,
364 "Reassembled DCP (ETSI)",
365 frag
, &dcp_frag_items
,
369 if(new_tvb
&& tvb_captured_length(new_tvb
) > 0) {
371 tvbuff_t
*dtvb
= NULL
;
372 const uint8_t *input
= tvb_get_ptr(new_tvb
, 0, -1);
373 uint32_t reassembled_size
= tvb_captured_length(new_tvb
);
374 uint8_t *deinterleaved
= (uint8_t*) wmem_alloc(pinfo
->pool
, reassembled_size
);
375 uint8_t *output
= (uint8_t*) wmem_alloc(pinfo
->pool
, decoded_size
);
376 rs_deinterleave(input
, deinterleaved
, plen
, fcount
);
378 dtvb
= tvb_new_child_real_data(tvb
, deinterleaved
, reassembled_size
, reassembled_size
);
379 add_new_data_source(pinfo
, dtvb
, "Deinterleaved");
381 decoded
= rs_correct_data(deinterleaved
, output
, c_max
, rsk
, rsz
);
382 proto_tree_add_boolean (tree
, hf_edcp_rs_ok
, tvb
, offset
, 2, decoded
);
384 new_tvb
= tvb_new_child_real_data(dtvb
, output
, decoded_size
, decoded_size
);
385 add_new_data_source(pinfo
, new_tvb
, "RS Error Corrected Data");
391 /** Handle a PFT packet which has the fragmentation header. This uses the
392 * standard wireshark methods for reassembling fragments. If FEC is used,
393 * the FEC is handled too. For the moment, all the fragments must be
394 * available but this could be improved.
395 * \param[in,out] tvb The buffer containing the current fragment
396 * \param[in,out] pinfo The packet info structure
397 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
398 * \param[in] findex the fragment count
399 * \param[in] fcount the number of fragments
400 * \param[in] seq the sequence number of the reassembled packet
401 * \param[in] offset the offset into the tvb of the fragment
402 * \param[in] plen the length of each fragment
403 * \param[in] fec is fec used
404 * \param[in] rsk the number of useful bytes in each chunk
405 * \param[in] rsz the number of padding bytes in each chunk
408 dissect_pft_fragmented(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
,
420 tvbuff_t
*new_tvb
=NULL
;
421 fragment_head
*frag_edcp
= NULL
;
422 pinfo
->fragmented
= true;
424 last
= fcount
== (findex
+1);
425 frag_edcp
= fragment_add_seq_check (
426 &dcp_reassembly_table
,
433 new_tvb
= dissect_pft_fec_detailed(
434 tvb
, pinfo
, tree
, findex
, fcount
, seq
, offset
, plen
, fec
, rsk
, rsz
, frag_edcp
437 new_tvb
= process_reassembled_data (tvb
, offset
, pinfo
,
438 "Reassembled DCP (ETSI)",
439 frag_edcp
, &dcp_frag_items
,
443 col_append_str (pinfo
->cinfo
, COL_INFO
, " (Message Reassembled)");
446 col_append_str (pinfo
->cinfo
, COL_INFO
, " (Message Reassembly failure)");
448 col_append_fstr (pinfo
->cinfo
, COL_INFO
, " (Message fragment %u)", findex
);
452 col_append_str (pinfo
->cinfo
, COL_INFO
, " (first)");
454 col_append_str (pinfo
->cinfo
, COL_INFO
, " (last)");
458 /** Dissect a PFT packet. Details follow
460 * \param[in,out] tvb The buffer containing the packet
461 * \param[in,out] pinfo The packet info structure
462 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
465 dissect_pft(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data
)
469 uint16_t seq
, payload_len
;
470 uint32_t findex
, fcount
;
471 proto_tree
*pft_tree
;
473 tvbuff_t
*next_tvb
= NULL
;
475 uint16_t rsk
=0, rsz
=0;
477 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DCP-PFT");
479 ti
= proto_tree_add_item (tree
, proto_pft
, tvb
, 0, -1, ENC_NA
);
480 pft_tree
= proto_item_add_subtree (ti
, ett_pft
);
481 proto_tree_add_item (pft_tree
, hf_edcp_sync
, tvb
, offset
, 2, ENC_ASCII
);
484 seq
= tvb_get_ntohs (tvb
, offset
);
485 proto_tree_add_item (pft_tree
, hf_edcp_pseq
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
488 findex
= tvb_get_ntoh24 (tvb
, offset
);
489 proto_tree_add_item (pft_tree
, hf_edcp_findex
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
492 fcount
= tvb_get_ntoh24 (tvb
, offset
);
493 proto_tree_add_item (pft_tree
, hf_edcp_fcount
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
496 plen
= tvb_get_ntohs (tvb
, offset
);
497 payload_len
= plen
& 0x3fff;
498 proto_tree_add_item (pft_tree
, hf_edcp_fecflag
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
499 proto_tree_add_item (pft_tree
, hf_edcp_addrflag
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
500 li
= proto_tree_add_item (pft_tree
, hf_edcp_plen
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
505 rsk
= tvb_get_uint8 (tvb
, offset
);
506 proto_tree_add_item (pft_tree
, hf_edcp_rsk
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
508 rsz
= tvb_get_uint8 (tvb
, offset
);
509 proto_tree_add_item (pft_tree
, hf_edcp_rsz
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
513 proto_tree_add_item (pft_tree
, hf_edcp_source
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
515 proto_tree_add_item (pft_tree
, hf_edcp_dest
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
519 proto_item
*ci
= NULL
;
520 unsigned header_len
= offset
+2;
521 uint16_t c
= crc16_x25_ccitt_tvb(tvb
, header_len
);
522 ci
= proto_tree_add_item (pft_tree
, hf_edcp_hcrc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
523 proto_item_append_text(ci
, " (%s)", (c
==0x1D0F)?"Ok":"bad");
524 proto_tree_add_boolean(pft_tree
, hf_edcp_hcrc_ok
, tvb
, offset
, 2, c
==0x1D0F);
527 if (fcount
> 1) { /* fragmented*/
528 bool save_fragmented
= pinfo
->fragmented
;
529 uint16_t real_len
= tvb_captured_length(tvb
)-offset
;
530 proto_tree_add_item (pft_tree
, hf_edcp_pft_payload
, tvb
, offset
, real_len
, ENC_NA
);
531 if(real_len
!= payload_len
|| real_len
== 0) {
532 proto_item_append_text(li
, " (length error (%d))", real_len
);
535 next_tvb
= dissect_pft_fragmented(tvb
, pinfo
, pft_tree
, findex
, fcount
,
536 seq
, offset
, real_len
, fec
, rsk
, rsz
);
538 pinfo
->fragmented
= save_fragmented
;
540 next_tvb
= tvb_new_subset_remaining (tvb
, offset
);
543 dissect_af(next_tvb
, pinfo
, tree
, data
);
545 return tvb_captured_length(tvb
);
548 /** Dissect an AF Packet. Parse an AF packet, checking the CRC if the CRC valid
549 * flag is set and calling any registered sub dissectors on the payload type.
550 * Currently only a payload type 'T' is defined which is the tag packet layer.
551 * If any others are defined then they can register themselves.
552 * \param[in,out] tvb The buffer containing the packet
553 * \param[in,out] pinfo The packet info structure
554 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
557 dissect_af (tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
)
561 proto_item
*li
= NULL
;
565 uint32_t payload_len
;
566 tvbuff_t
*next_tvb
= NULL
;
568 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DCP-AF");
570 ti
= proto_tree_add_item (tree
, proto_af
, tvb
, 0, -1, ENC_NA
);
571 af_tree
= proto_item_add_subtree (ti
, ett_af
);
572 proto_tree_add_item (af_tree
, hf_edcp_sync
, tvb
, offset
, 2, ENC_ASCII
);
575 payload_len
= tvb_get_ntohl(tvb
, offset
);
577 uint32_t real_payload_len
= tvb_captured_length(tvb
)-12;
578 li
= proto_tree_add_item (af_tree
, hf_edcp_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
579 if(real_payload_len
< payload_len
) {
580 proto_item_append_text (li
, " (wrong len claims %d is %d)",
581 payload_len
, real_payload_len
583 } else if(real_payload_len
> payload_len
) {
584 proto_item_append_text (li
, " (%d bytes in packet after end of AF frame)",
585 real_payload_len
-payload_len
590 proto_tree_add_item (af_tree
, hf_edcp_seq
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
592 ver
= tvb_get_uint8 (tvb
, offset
);
593 proto_tree_add_item (af_tree
, hf_edcp_crcflag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
594 proto_tree_add_item (af_tree
, hf_edcp_maj
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
595 proto_tree_add_item (af_tree
, hf_edcp_min
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
598 pt
= tvb_get_uint8 (tvb
, offset
);
599 proto_tree_add_item (af_tree
, hf_edcp_pt
, tvb
, offset
, 1, ENC_ASCII
);
601 next_tvb
= tvb_new_subset_length(tvb
, offset
, payload_len
);
602 offset
+= payload_len
;
603 ci
= proto_tree_add_item (af_tree
, hf_edcp_crc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
604 if (ver
& 0x80) { /* crc valid */
605 unsigned len
= offset
+2;
606 uint16_t c
= crc16_x25_ccitt_tvb(tvb
, len
);
607 proto_item_append_text(ci
, " (%s)", (c
==0x1D0F)?"Ok":"bad");
608 proto_tree_add_boolean(af_tree
, hf_edcp_crc_ok
, tvb
, offset
, 2, c
==0x1D0F);
612 dissector_try_uint(af_dissector_table
, pt
, next_tvb
, pinfo
, tree
);
613 return tvb_captured_length(tvb
);
616 /** Dissect the Tag Packet Layer.
617 * Split the AF packet into its tag items. Each tag item has a 4 character
618 * tag, a length in bits and a value. The *ptr tag is dissected in the routine.
619 * All other tags are listed and may be handled by other dissectors.
620 * Child dissectors are tied to the parent tree, not to this tree, so that
621 * they appear at the same level as DCP.
622 * \param[in,out] tvb The buffer containing the packet
623 * \param[in,out] pinfo The packet info structure
624 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
627 dissect_tpl(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
)
629 proto_tree
*tpl_tree
;
633 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DCP-TPL");
635 ti
= proto_tree_add_item (tree
, proto_tpl
, tvb
, 0, -1, ENC_NA
);
636 tpl_tree
= proto_item_add_subtree (ti
, ett_tpl
);
638 while(offset
<tvb_reported_length(tvb
)) {
642 char *tag
= (char*)tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, 4, ENC_ASCII
);
643 bits
= tvb_get_ntohl(tvb
, offset
+4);
648 proto_tree_add_bytes_format(tpl_tree
, hf_tpl_tlv
, tvb
,
649 offset
, 8+bytes
, NULL
,
650 "%s (%u bits)", tag
, bits
);
652 next_tvb
= tvb_new_subset_length(tvb
, offset
+8, bytes
);
653 dissector_try_string(tpl_dissector_table
, tag
, next_tvb
, pinfo
, tree
, NULL
);
658 return tvb_captured_length(tvb
);
662 proto_reg_handoff_dcp_etsi (void)
664 heur_dissector_add("udp", dissect_dcp_etsi_heur
, "DCP (ETSI) over UDP", "dcp_etsi_udp", proto_dcp_etsi
, HEURISTIC_ENABLE
);
665 dissector_add_for_decode_as("udp.port", dcp_etsi_handle
);
666 dissector_add_string("dcp-etsi.sync", "AF", af_handle
);
667 dissector_add_string("dcp-etsi.sync", "PF", pft_handle
);
668 /* if there are ever other payload types ...*/
669 dissector_add_uint("dcp-af.pt", 'T', tpl_handle
);
673 proto_register_dcp_etsi (void)
675 static hf_register_info hf_edcp
[] = {
677 {"sync", "dcp-etsi.sync",
678 FT_STRING
, BASE_NONE
, NULL
, 0,
682 static hf_register_info hf_af
[] = {
684 {"length", "dcp-af.len",
685 FT_UINT32
, BASE_DEC
, NULL
, 0,
686 "length in bytes of the payload", HFILL
}
689 {"frame count", "dcp-af.seq",
690 FT_UINT16
, BASE_DEC
, NULL
, 0,
691 "Logical Frame Number", HFILL
}
694 {"crc flag", "dcp-af.crcflag",
695 FT_BOOLEAN
, 8, NULL
, 0x80,
696 "Frame is protected by CRC", HFILL
}
699 {"Major Revision", "dcp-af.maj",
700 FT_UINT8
, BASE_DEC
, NULL
, 0x70,
701 "Major Protocol Revision", HFILL
}
704 {"Minor Revision", "dcp-af.min",
705 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
706 "Minor Protocol Revision", HFILL
}
709 {"Payload Type", "dcp-af.pt",
710 FT_STRING
, BASE_NONE
, NULL
, 0,
711 "T means Tag Packets, all other values reserved", HFILL
}
714 {"CRC", "dcp-af.crc",
715 FT_UINT16
, BASE_HEX
, NULL
, 0,
719 {"CRC OK", "dcp-af.crc_ok",
720 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
725 static hf_register_info hf_pft
[] = {
728 {"Sub-protocol", "dcp-pft.pt",
729 FT_UINT8
, BASE_DEC
, NULL
, 0,
734 {"Sequence No", "dcp-pft.seq",
735 FT_UINT16
, BASE_DEC
, NULL
, 0,
736 "PFT Sequence No", HFILL
}
739 {"Fragment Index", "dcp-pft.findex",
740 FT_UINT24
, BASE_DEC
, NULL
, 0,
741 "Index of the fragment within one AF Packet", HFILL
}
744 {"Fragment Count", "dcp-pft.fcount",
745 FT_UINT24
, BASE_DEC
, NULL
, 0,
746 "Number of fragments produced from this AF Packet", HFILL
}
749 {"FEC", "dcp-pft.fec",
750 FT_BOOLEAN
, 16, NULL
, 0x8000,
751 "When set the optional RS header is present", HFILL
}
754 {"Addr", "dcp-pft.addr",
755 FT_BOOLEAN
, 16, NULL
, 0x4000,
756 "When set the optional transport header is present", HFILL
}
759 {"fragment length", "dcp-pft.len",
760 FT_UINT16
, BASE_DEC
, NULL
, 0x3fff,
761 "length in bytes of the payload of this fragment", HFILL
}
764 {"RSk", "dcp-pft.rsk",
765 FT_UINT8
, BASE_DEC
, NULL
, 0,
766 "The length of the Reed Solomon data word", HFILL
}
769 {"RSz", "dcp-pft.rsz",
770 FT_UINT8
, BASE_DEC
, NULL
, 0,
771 "The number of padding bytes in the last Reed Solomon block", HFILL
}
774 {"source addr", "dcp-pft.source",
775 FT_UINT16
, BASE_DEC
, NULL
, 0,
776 "PFT source identifier", HFILL
}
779 {"dest addr", "dcp-pft.dest",
780 FT_UINT16
, BASE_DEC
, NULL
, 0,
781 "PFT destination identifier", HFILL
}
784 {"header CRC", "dcp-pft.crc",
785 FT_UINT16
, BASE_HEX
, NULL
, 0,
786 "PFT Header CRC", HFILL
}
789 {"PFT CRC OK", "dcp-pft.crc_ok",
790 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
791 "PFT Header CRC OK", HFILL
}
794 {"Message fragments", "dcp-pft.fragments",
795 FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
797 {"Message fragment", "dcp-pft.fragment",
798 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
799 {&hf_edcp_fragment_overlap
,
800 {"Message fragment overlap", "dcp-pft.fragment.overlap",
801 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
802 {&hf_edcp_fragment_overlap_conflicts
,
803 {"Message fragment overlapping with conflicting data",
804 "dcp-pft.fragment.overlap.conflicts",
805 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
806 {&hf_edcp_fragment_multiple_tails
,
807 {"Message has multiple tail fragments",
808 "dcp-pft.fragment.multiple_tails",
809 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
810 {&hf_edcp_fragment_too_long_fragment
,
811 {"Message fragment too long", "dcp-pft.fragment.too_long_fragment",
812 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
813 {&hf_edcp_fragment_error
,
814 {"Message defragmentation error", "dcp-pft.fragment.error",
815 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
816 {&hf_edcp_fragment_count
,
817 {"Message fragment count", "dcp-pft.fragment.count",
818 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
819 {&hf_edcp_reassembled_in
,
820 {"Reassembled in", "dcp-pft.reassembled.in",
821 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
822 {&hf_edcp_reassembled_length
,
823 {"Reassembled DCP (ETSI) length", "dcp-pft.reassembled.length",
824 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
827 {"C max", "dcp-pft.cmax",
828 FT_UINT16
, BASE_DEC
, NULL
, 0,
829 "Maximum number of RS chunks sent", HFILL
}
832 {"Rx min", "dcp-pft.rxmin",
833 FT_UINT16
, BASE_DEC
, NULL
, 0,
834 "Minimum number of fragments needed for RS decode", HFILL
}
836 {&hf_edcp_rs_corrected
,
837 {"RS Symbols Corrected", "dcp-pft.rs_corrected",
838 FT_INT16
, BASE_DEC
, NULL
, 0,
839 "Number of symbols corrected by RS decode or -1 for failure", HFILL
}
843 {"RS decode OK", "dcp-pft.rs_ok",
844 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
845 "successfully decoded RS blocks", HFILL
}
847 {&hf_edcp_pft_payload
,
848 {"payload", "dcp-pft.payload",
849 FT_BYTES
, BASE_NONE
, NULL
, 0,
850 "PFT Payload", HFILL
}
854 static hf_register_info hf_tpl
[] = {
856 {"tag", "dcp-tpl.tlv",
857 FT_BYTES
, BASE_NONE
, NULL
, 0,
862 {"Type", "dcp-tpl.ptr",
863 FT_STRING
, BASE_NONE
, NULL
, 0,
864 "Protocol Type & Revision", HFILL
}
869 /* Setup protocol subtree array */
870 static int *ett
[] = {
879 static ei_register_info ei
[] = {
880 { &ei_edcp_reassembly
, { "dcp-etsi.reassembly_failed", PI_REASSEMBLE
, PI_ERROR
, "Reassembly failed", EXPFILL
}},
881 { &ei_edcp_reassembly_info
, { "dcp-etsi.reassembly_info", PI_REASSEMBLE
, PI_CHAT
, "Reassembly information", EXPFILL
}},
884 expert_module_t
* expert_dcp_etsi
;
886 proto_dcp_etsi
= proto_register_protocol ("ETSI Distribution & Communication Protocol (for DRM)", /* name */
887 "DCP (ETSI)", /* short name */
888 "dcp-etsi" /* abbrev */
890 proto_af
= proto_register_protocol ("DCP Application Framing Layer", "DCP-AF", "dcp-af");
891 proto_pft
= proto_register_protocol ("DCP Protection, Fragmentation & Transport Layer", "DCP-PFT", "dcp-pft");
892 proto_tpl
= proto_register_protocol ("DCP Tag Packet Layer", "DCP-TPL", "dcp-tpl");
894 proto_register_field_array (proto_dcp_etsi
, hf_edcp
, array_length (hf_edcp
));
895 proto_register_field_array (proto_af
, hf_af
, array_length (hf_af
));
896 proto_register_field_array (proto_pft
, hf_pft
, array_length (hf_pft
));
897 proto_register_field_array (proto_tpl
, hf_tpl
, array_length (hf_tpl
));
898 proto_register_subtree_array (ett
, array_length (ett
));
899 expert_dcp_etsi
= expert_register_protocol(proto_dcp_etsi
);
900 expert_register_field_array(expert_dcp_etsi
, ei
, array_length(ei
));
902 /* subdissector code */
903 dcp_dissector_table
= register_dissector_table("dcp-etsi.sync",
904 "DCP Sync", proto_dcp_etsi
, FT_STRING
, STRING_CASE_SENSITIVE
);
905 af_dissector_table
= register_dissector_table("dcp-af.pt",
906 "DCP-AF Payload Type", proto_dcp_etsi
, FT_UINT8
, BASE_DEC
);
908 tpl_dissector_table
= register_dissector_table("dcp-tpl.ptr",
909 "DCP-TPL Protocol Type & Revision", proto_dcp_etsi
, FT_STRING
, STRING_CASE_SENSITIVE
);
911 reassembly_table_register (&dcp_reassembly_table
,
912 &addresses_reassembly_table_functions
);
914 dcp_etsi_handle
= register_dissector("dcp-etsi", dissect_dcp_etsi
, proto_dcp_etsi
);
915 af_handle
= register_dissector("dcp-af", dissect_af
, proto_af
);
916 pft_handle
= register_dissector("dcp-pft", dissect_pft
, proto_pft
);
917 tpl_handle
= register_dissector("dcp-tpl", dissect_tpl
, proto_tpl
);
921 * Editor modelines - https://www.wireshark.org/tools/modelines.html
926 * indent-tabs-mode: nil
929 * vi: set shiftwidth=2 tabstop=8 expandtab:
930 * :indentSize=2:tabSize=8:noTabs=true: