2 * Routines for ETSI Distribution & Communication Protocol
3 * Copyright 2006, British Broadcasting Corporation
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * Ref: ETSI DCP (ETSI TS 102 821)
31 #include <epan/packet.h>
32 #include <epan/reassemble.h>
33 #include <wsutil/crcdrm.h>
34 #include <epan/reedsolomon.h>
35 #include <epan/wmem/wmem.h>
38 /* forward reference */
39 void proto_register_dcp_etsi(void);
40 void proto_reg_handoff_dcp_etsi(void);
41 static void dissect_af (tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
);
42 static void dissect_pft (tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
);
43 static void dissect_tpl(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
);
45 static dissector_table_t dcp_dissector_table
;
46 static dissector_table_t af_dissector_table
;
47 static dissector_table_t tpl_dissector_table
;
49 static int proto_dcp_etsi
= -1;
50 static int proto_af
= -1;
51 static int proto_pft
= -1;
52 static int proto_tpl
= -1;
53 static int hf_edcp_sync
= -1;
54 static int hf_edcp_len
= -1;
55 static int hf_edcp_seq
= -1;
56 static int hf_edcp_crcflag
= -1;
57 static int hf_edcp_maj
= -1;
58 static int hf_edcp_min
= -1;
59 static int hf_edcp_pt
= -1;
60 static int hf_edcp_crc
= -1;
61 static int hf_edcp_crc_ok
= -1;
62 /* static int hf_edcp_pft_pt = -1; */
63 static int hf_edcp_pseq
= -1;
64 static int hf_edcp_findex
= -1;
65 static int hf_edcp_fcount
= -1;
66 static int hf_edcp_fecflag
= -1;
67 static int hf_edcp_addrflag
= -1;
68 static int hf_edcp_plen
= -1;
69 static int hf_edcp_rsk
= -1;
70 static int hf_edcp_rsz
= -1;
71 static int hf_edcp_source
= -1;
72 static int hf_edcp_dest
= -1;
73 static int hf_edcp_hcrc
= -1;
74 static int hf_edcp_hcrc_ok
= -1;
75 /* static int hf_edcp_c_max = -1; */
76 /* static int hf_edcp_rx_min = -1; */
77 /* static int hf_edcp_rs_corrected = -1; */
78 static int hf_edcp_rs_ok
= -1;
79 static int hf_edcp_pft_payload
= -1;
81 static int hf_tpl_tlv
= -1;
82 /* static int hf_tpl_ptr = -1; */
84 static int hf_edcp_fragments
= -1;
85 static int hf_edcp_fragment
= -1;
86 static int hf_edcp_fragment_overlap
= -1;
87 static int hf_edcp_fragment_overlap_conflicts
= -1;
88 static int hf_edcp_fragment_multiple_tails
= -1;
89 static int hf_edcp_fragment_too_long_fragment
= -1;
90 static int hf_edcp_fragment_error
= -1;
91 static int hf_edcp_fragment_count
= -1;
92 static int hf_edcp_reassembled_in
= -1;
93 static int hf_edcp_reassembled_length
= -1;
95 /* Initialize the subtree pointers */
96 static gint ett_edcp
= -1;
97 static gint ett_af
= -1;
98 static gint ett_pft
= -1;
99 static gint ett_tpl
= -1;
100 static gint ett_edcp_fragment
= -1;
101 static gint ett_edcp_fragments
= -1;
103 static reassembly_table dcp_reassembly_table
;
105 static const fragment_items dcp_frag_items
= {
106 /* Fragment subtrees */
109 /* Fragment fields */
112 &hf_edcp_fragment_overlap
,
113 &hf_edcp_fragment_overlap_conflicts
,
114 &hf_edcp_fragment_multiple_tails
,
115 &hf_edcp_fragment_too_long_fragment
,
116 &hf_edcp_fragment_error
,
117 &hf_edcp_fragment_count
,
118 /* Reassembled in field */
119 &hf_edcp_reassembled_in
,
120 /* Reassembled length field */
121 &hf_edcp_reassembled_length
,
122 /* Reassembled data field */
128 /** initialise the DCP protocol. Details follow
132 dcp_init_protocol(void)
134 reassembly_table_init (&dcp_reassembly_table
,
135 &addresses_reassembly_table_functions
);
139 /** Dissect a DCP packet. Details follow
141 * \param[in,out] tvb The buffer containing the packet
142 * \param[in,out] pinfo The packet info structure
143 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
147 dissect_dcp_etsi (tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * data _U_
)
150 proto_tree
*dcp_tree
= NULL
;
153 /* 6.1 AF packet structure
157 * 2 bytes 4 bytes 2 bytes 1 byte 1 byte
159 * SYNC: two-byte ASCII representation of "AF".
160 * LEN: length of the payload, in bytes.
161 * SEQ: sequence number
162 * AR: AF protocol Revision - a field combining the CF, MAJ and MIN fields
163 * CF: CRC Flag, 0 if the CRC field is not used
164 * MAJ: major revision of the AF protocol in use, see clause 6.2.
165 * MIN: minor revision of the AF protocol in use, see clause 6.2.
166 * Protocol Type (PT): single byte encoding the protocol of the data carried in the payload. For TAG Packets, the value
167 * shall be the ASCII representation of "T".
169 * 7.1 PFT fragment structure
171 * 14, 16, 18 or 20 bytes (depending on options) Optional present if FEC=1 Optional present if Addr = 1
172 * Psync Pseq Findex Fcount FEC HCRC Addr Plen | RSk RSz | Source Dest
173 * 16 bits 16 bits 24 bits 24 bits 1 bit 16 bits 1 bit 14 bits | 8 bits 8 bits | 16 bits 16 bits
175 * Psync: the ASCII string "PF" is used as the synchronization word for the PFT Layer
177 * Don't accept this packet unless at least a full AF header present(10 bytes).
178 * It should be possible to strengthen the heuristic further if need be.
180 if(tvb_length(tvb
) < 11)
183 word
= tvb_get_ntohs(tvb
,0);
184 /* Check for 'AF or 'PF' */
185 if(word
!= 0x4146 && word
!= 0x5046)
188 pinfo
->current_proto
= "DCP (ETSI)";
190 /* Clear out stuff in the info column */
191 col_clear(pinfo
->cinfo
, COL_INFO
);
192 col_set_str (pinfo
->cinfo
, COL_PROTOCOL
, "DCP (ETSI)");
193 /*col_append_fstr (pinfo->cinfo, COL_INFO, " tvb %d", tvb_length(tvb));*/
196 proto_item
*ti
= NULL
;
197 ti
= proto_tree_add_item (tree
, proto_dcp_etsi
, tvb
, 0, -1, ENC_NA
);
198 dcp_tree
= proto_item_add_subtree (ti
, ett_edcp
);
201 sync
= tvb_get_string (wmem_packet_scope(), tvb
, 0, 2);
202 dissector_try_string(dcp_dissector_table
, (char*)sync
, tvb
, pinfo
, dcp_tree
, NULL
);
206 #define PFT_RS_N_MAX 207
208 #define PFT_RS_P (PFT_RS_K - PFT_RS_N_MAX)
212 void rs_deinterleave(const guint8
*input
, guint8
*output
, guint16 plen
, guint32 fcount
)
215 for(fidx
=0; fidx
<fcount
; fidx
++)
218 for (r
=0; r
<plen
; r
++)
220 output
[fidx
+r
*fcount
] = input
[fidx
*plen
+r
];
226 gboolean
rs_correct_data(guint8
*deinterleaved
, guint8
*output
,
227 guint32 c_max
, guint16 rsk
, guint16 rsz _U_
)
229 guint32 i
, index_coded
= 0, index_out
= 0;
231 for (i
=0; i
<c_max
; i
++)
233 memcpy(output
+index_out
, deinterleaved
+index_coded
, rsk
);
235 memcpy(output
+index_out
+PFT_RS_N_MAX
, deinterleaved
+index_coded
, PFT_RS_P
);
236 index_coded
+= PFT_RS_P
;
237 err_corr
= eras_dec_rs(output
+index_out
, NULL
, 0);
246 /* Don't attempt reassembly if we have a huge number of fragments. */
247 #define MAX_FRAGMENTS ((1 * 1024 * 1024) / sizeof(guint32))
248 /* If we missed more than this number of consecutive fragments,
249 we don't attempt reassembly */
250 #define MAX_FRAG_GAP 1000
253 dissect_pft_fec_detailed(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
,
265 guint32 decoded_size
;
268 tvbuff_t
*new_tvb
=NULL
;
270 if (fcount
> MAX_FRAGMENTS
) {
271 proto_tree_add_text(tree
, tvb
, 0, -1, "[Reassembly of %d fragments not attempted]", fcount
);
275 decoded_size
= fcount
*plen
;
276 c_max
= fcount
*plen
/(rsk
+PFT_RS_P
); /* rounded down */
277 rx_min
= fcount
- (c_max
*PFT_RS_P
/plen
);
279 new_tvb
= process_reassembled_data (tvb
, offset
, pinfo
,
280 "Reassembled DCP (ETSI)",
281 fdx
, &dcp_frag_items
,
287 fragment_head
*fd_head
;
290 proto_tree_add_text (tree
, tvb
, 0, -1, "want %d, got %d need %d",
291 fcount
, fragments
, rx_min
293 got
= (guint32
*)wmem_alloc(wmem_packet_scope(), fcount
*sizeof(guint32
));
295 /* make a list of the findex (offset) numbers of the fragments we have */
296 fd
= fragment_get(&dcp_reassembly_table
, pinfo
, seq
, NULL
);
297 for (fd_head
= fd
; fd_head
!= NULL
&& fragments
< fcount
; fd_head
= fd_head
->next
) {
298 if(fd_head
->tvb_data
) {
299 got
[fragments
++] = fd_head
->offset
; /* this is the findex of the fragment */
302 /* have we got enough for Reed Solomon to try to correct ? */
303 if(fragments
>=rx_min
) { /* yes, in theory */
304 guint i
,current_findex
;
305 fragment_head
*frag
=NULL
;
306 guint8
*dummy_data
= (guint8
*) wmem_alloc0 (wmem_packet_scope(), plen
);
307 tvbuff_t
*dummytvb
= tvb_new_real_data(dummy_data
, plen
, plen
);
308 /* try and decode with missing fragments */
310 proto_tree_add_text (tree
, tvb
, 0, -1, "want %d, got %d need %d",
311 fcount
, fragments
, rx_min
313 /* fill the fragment table with empty fragments */
315 for(i
=0; i
<fragments
; i
++) {
316 guint next_fragment_we_have
= got
[i
];
317 if (next_fragment_we_have
> MAX_FRAGMENTS
) {
318 proto_tree_add_text(tree
, tvb
, 0, -1, "[Reassembly of %d fragments not attempted]", next_fragment_we_have
);
321 if (next_fragment_we_have
-current_findex
> MAX_FRAG_GAP
) {
322 proto_tree_add_text(tree
, tvb
, 0, -1,
323 "[Missing %d consecutive packets. Don't attempt reassembly]",
324 next_fragment_we_have
-current_findex
);
327 for(; current_findex
<next_fragment_we_have
; current_findex
++) {
328 frag
= fragment_add_seq_check (&dcp_reassembly_table
,
329 dummytvb
, 0, pinfo
, seq
, NULL
,
330 current_findex
, plen
, (current_findex
+1!=fcount
));
332 current_findex
++; /* skip over the fragment we have */
337 new_tvb
= process_reassembled_data (tvb
, offset
, pinfo
,
338 "Reassembled DCP (ETSI)",
339 frag
, &dcp_frag_items
,
343 if(new_tvb
&& tvb_length(new_tvb
) > 0) {
344 gboolean decoded
= TRUE
;
345 tvbuff_t
*dtvb
= NULL
;
346 const guint8
*input
= tvb_get_ptr(new_tvb
, 0, -1);
347 guint32 reassembled_size
= tvb_length(new_tvb
);
348 guint8
*deinterleaved
= (guint8
*) g_malloc (reassembled_size
);
349 guint8
*output
= (guint8
*) g_malloc (decoded_size
);
350 rs_deinterleave(input
, deinterleaved
, plen
, fcount
);
352 dtvb
= tvb_new_child_real_data(tvb
, deinterleaved
, reassembled_size
, reassembled_size
);
353 add_new_data_source(pinfo
, dtvb
, "Deinterleaved");
354 tvb_set_free_cb(dtvb
, g_free
);
356 decoded
= rs_correct_data(deinterleaved
, output
, c_max
, rsk
, rsz
);
358 proto_tree_add_boolean (tree
, hf_edcp_rs_ok
, tvb
, offset
, 2, decoded
);
360 new_tvb
= tvb_new_child_real_data(dtvb
, output
, decoded_size
, decoded_size
);
361 add_new_data_source(pinfo
, new_tvb
, "RS Error Corrected Data");
362 tvb_set_free_cb(new_tvb
, g_free
);
368 /** Handle a PFT packet which has the fragmentation header. This uses the
369 * standard wireshark methods for reassembling fragments. If FEC is used,
370 * the FEC is handled too. For the moment, all the fragments must be
371 * available but this could be improved.
372 * \param[in,out] tvb The buffer containing the current fragment
373 * \param[in,out] pinfo The packet info structure
374 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
375 * \param[in] findex the fragment count
376 * \param[in] fcount the number of fragments
377 * \param[in] seq the sequence number of the reassembled packet
378 * \param[in] offset the offset into the tvb of the fragment
379 * \param[in] plen the length of each fragment
380 * \param[in] fec is fec used
381 * \param[in] rsk the number of useful bytes in each chunk
382 * \param[in] rsz the number of padding bytes in each chunk
385 dissect_pft_fragmented(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
,
396 gboolean first
, last
;
397 tvbuff_t
*new_tvb
=NULL
;
398 fragment_head
*frag_edcp
= NULL
;
399 pinfo
->fragmented
= TRUE
;
401 last
= fcount
== (findex
+1);
402 frag_edcp
= fragment_add_seq_check (
403 &dcp_reassembly_table
,
410 new_tvb
= dissect_pft_fec_detailed(
411 tvb
, pinfo
, tree
, findex
, fcount
, seq
, offset
, plen
, fec
, rsk
, rsz
, frag_edcp
414 new_tvb
= process_reassembled_data (tvb
, offset
, pinfo
,
415 "Reassembled DCP (ETSI)",
416 frag_edcp
, &dcp_frag_items
,
420 col_append_str (pinfo
->cinfo
, COL_INFO
, " (Message Reassembled)");
423 col_append_str (pinfo
->cinfo
, COL_INFO
, " (Message Reassembly failure)");
425 col_append_fstr (pinfo
->cinfo
, COL_INFO
, " (Message fragment %u)", findex
);
429 col_append_str (pinfo
->cinfo
, COL_INFO
, " (first)");
431 col_append_str (pinfo
->cinfo
, COL_INFO
, " (last)");
435 /** Dissect a PFT packet. Details follow
437 * \param[in,out] tvb The buffer containing the packet
438 * \param[in,out] pinfo The packet info structure
439 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
442 dissect_pft(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
)
446 guint16 seq
, payload_len
;
447 guint32 findex
, fcount
;
448 proto_tree
*pft_tree
;
450 tvbuff_t
*next_tvb
= NULL
;
451 gboolean fec
= FALSE
;
452 guint16 rsk
=0, rsz
=0;
454 pinfo
->current_proto
= "DCP-PFT";
455 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DCP-PFT");
457 ti
= proto_tree_add_item (tree
, proto_pft
, tvb
, 0, -1, ENC_NA
);
458 pft_tree
= proto_item_add_subtree (ti
, ett_pft
);
459 proto_tree_add_item (pft_tree
, hf_edcp_sync
, tvb
, offset
, 2, ENC_ASCII
|ENC_NA
);
462 seq
= tvb_get_ntohs (tvb
, offset
);
463 proto_tree_add_item (pft_tree
, hf_edcp_pseq
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
466 findex
= tvb_get_ntoh24 (tvb
, offset
);
467 proto_tree_add_item (pft_tree
, hf_edcp_findex
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
470 fcount
= tvb_get_ntoh24 (tvb
, offset
);
471 proto_tree_add_item (pft_tree
, hf_edcp_fcount
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
474 plen
= tvb_get_ntohs (tvb
, offset
);
475 payload_len
= plen
& 0x3fff;
476 proto_tree_add_item (pft_tree
, hf_edcp_fecflag
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
477 proto_tree_add_item (pft_tree
, hf_edcp_addrflag
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
478 li
= proto_tree_add_item (pft_tree
, hf_edcp_plen
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
483 rsk
= tvb_get_guint8 (tvb
, offset
);
484 proto_tree_add_item (pft_tree
, hf_edcp_rsk
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
486 rsz
= tvb_get_guint8 (tvb
, offset
);
487 proto_tree_add_item (pft_tree
, hf_edcp_rsz
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
491 proto_tree_add_item (pft_tree
, hf_edcp_source
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
493 proto_tree_add_item (pft_tree
, hf_edcp_dest
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
497 proto_item
*ci
= NULL
;
498 guint header_len
= offset
+2;
499 const char *crc_buf
= (const char *) tvb_get_ptr(tvb
, 0, header_len
);
500 unsigned long c
= crc_drm(crc_buf
, header_len
, 16, 0x11021, 1);
501 ci
= proto_tree_add_item (pft_tree
, hf_edcp_hcrc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
502 proto_item_append_text(ci
, " (%s)", (c
==0xe2f0)?"Ok":"bad");
503 proto_tree_add_boolean(pft_tree
, hf_edcp_hcrc_ok
, tvb
, offset
, 2, c
==0xe2f0);
506 if (fcount
> 1) { /* fragmented*/
507 gboolean save_fragmented
= pinfo
->fragmented
;
508 guint16 real_len
= tvb_length(tvb
)-offset
;
509 proto_tree_add_item (pft_tree
, hf_edcp_pft_payload
, tvb
, offset
, real_len
, ENC_NA
);
510 if(real_len
!= payload_len
|| real_len
== 0) {
511 proto_item_append_text(li
, " (length error (%d))", real_len
);
514 next_tvb
= dissect_pft_fragmented(tvb
, pinfo
, pft_tree
, findex
, fcount
,
515 seq
, offset
, real_len
, fec
, rsk
, rsz
);
517 pinfo
->fragmented
= save_fragmented
;
519 next_tvb
= tvb_new_subset_remaining (tvb
, offset
);
522 dissect_af(next_tvb
, pinfo
, tree
);
526 /** Dissect an AF Packet. Parse an AF packet, checking the CRC if the CRC valid
527 * flag is set and calling any registered sub dissectors on the payload type.
528 * Currently only a payload type 'T' is defined which is the tag packet layer.
529 * If any others are defined then they can register themselves.
530 * \param[in,out] tvb The buffer containing the packet
531 * \param[in,out] pinfo The packet info structure
532 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
535 dissect_af (tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
)
539 proto_item
*li
= NULL
;
544 tvbuff_t
*next_tvb
= NULL
;
546 pinfo
->current_proto
= "DCP-AF";
547 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DCP-AF");
549 ti
= proto_tree_add_item (tree
, proto_af
, tvb
, 0, -1, ENC_NA
);
550 af_tree
= proto_item_add_subtree (ti
, ett_af
);
551 proto_tree_add_item (af_tree
, hf_edcp_sync
, tvb
, offset
, 2, ENC_ASCII
|ENC_NA
);
554 payload_len
= tvb_get_ntohl(tvb
, offset
);
556 guint32 real_payload_len
= tvb_length(tvb
)-12;
557 li
= proto_tree_add_item (af_tree
, hf_edcp_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
558 if(real_payload_len
< payload_len
) {
559 proto_item_append_text (li
, " (wrong len claims %d is %d)",
560 payload_len
, real_payload_len
562 } else if(real_payload_len
> payload_len
) {
563 proto_item_append_text (li
, " (%d bytes in packet after end of AF frame)",
564 real_payload_len
-payload_len
569 proto_tree_add_item (af_tree
, hf_edcp_seq
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
571 ver
= tvb_get_guint8 (tvb
, offset
);
572 proto_tree_add_item (af_tree
, hf_edcp_crcflag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
573 proto_tree_add_item (af_tree
, hf_edcp_maj
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
574 proto_tree_add_item (af_tree
, hf_edcp_min
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
577 pt
= tvb_get_guint8 (tvb
, offset
);
578 proto_tree_add_item (af_tree
, hf_edcp_pt
, tvb
, offset
, 1, ENC_ASCII
|ENC_NA
);
580 next_tvb
= tvb_new_subset (tvb
, offset
, payload_len
, -1);
581 offset
+= payload_len
;
582 ci
= proto_tree_add_item (af_tree
, hf_edcp_crc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
583 if (ver
& 0x80) { /* crc valid */
584 guint len
= offset
+2;
585 const char *crc_buf
= (const char *) tvb_get_ptr(tvb
, 0, len
);
586 unsigned long c
= crc_drm(crc_buf
, len
, 16, 0x11021, 1);
587 proto_item_append_text(ci
, " (%s)", (c
==0xe2f0)?"Ok":"bad");
588 proto_tree_add_boolean(af_tree
, hf_edcp_crc_ok
, tvb
, offset
, 2, c
==0xe2f0);
592 dissector_try_uint(af_dissector_table
, pt
, next_tvb
, pinfo
, tree
);
595 /** Dissect the Tag Packet Layer.
596 * Split the AF packet into its tag items. Each tag item has a 4 character
597 * tag, a length in bits and a value. The *ptr tag is dissected in the routine.
598 * All other tags are listed and may be handled by other dissectors.
599 * Child dissectors are tied to the parent tree, not to this tree, so that
600 * they appear at the same level as DCP.
601 * \param[in,out] tvb The buffer containing the packet
602 * \param[in,out] pinfo The packet info structure
603 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
606 dissect_tpl(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
)
608 proto_tree
*tpl_tree
;
614 pinfo
->current_proto
= "DCP-TPL";
615 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DCP-TPL");
617 ti
= proto_tree_add_item (tree
, proto_tpl
, tvb
, 0, -1, ENC_NA
);
618 tpl_tree
= proto_item_add_subtree (ti
, ett_tpl
);
620 while(offset
<tvb_length(tvb
)) {
623 char *tag
= (char*)tvb_get_string (wmem_packet_scope(), tvb
, offset
, 4); offset
+= 4;
624 bits
= tvb_get_ntohl(tvb
, offset
); offset
+= 4;
629 if(strcmp(tag
, "*ptr")==0) {
630 prot
= (char*)tvb_get_string (wmem_packet_scope(), tvb
, offset
, 4);
631 maj
= tvb_get_ntohs(tvb
, offset
+4);
632 min
= tvb_get_ntohs(tvb
, offset
+6);
633 proto_tree_add_bytes_format(tpl_tree
, hf_tpl_tlv
, tvb
,
634 offset
-8, bytes
+8, tvb_get_ptr(tvb
, offset
, bytes
),
635 "%s %s rev %d.%d", tag
, prot
, maj
, min
);
637 proto_tree_add_bytes_format(tpl_tree
, hf_tpl_tlv
, tvb
,
638 offset
-8, bytes
+8, tvb_get_ptr(tvb
, offset
, bytes
),
639 "%s (%u bits)", tag
, bits
);
645 dissector_try_string(tpl_dissector_table
, prot
, tvb
, pinfo
, tree
->parent
, NULL
);
649 proto_reg_handoff_dcp_etsi (void)
651 dissector_handle_t af_handle
;
652 dissector_handle_t pft_handle
;
653 dissector_handle_t tpl_handle
;
655 af_handle
= create_dissector_handle(dissect_af
, proto_af
);
656 pft_handle
= create_dissector_handle(dissect_pft
, proto_pft
);
657 tpl_handle
= create_dissector_handle(dissect_tpl
, proto_tpl
);
658 heur_dissector_add("udp", dissect_dcp_etsi
, proto_dcp_etsi
);
659 dissector_add_string("dcp-etsi.sync", "AF", af_handle
);
660 dissector_add_string("dcp-etsi.sync", "PF", pft_handle
);
661 /* if there are ever other payload types ...*/
662 dissector_add_uint("dcp-af.pt", 'T', tpl_handle
);
666 proto_register_dcp_etsi (void)
668 static hf_register_info hf_edcp
[] = {
670 {"sync", "dcp-etsi.sync",
671 FT_STRING
, BASE_NONE
, NULL
, 0,
675 static hf_register_info hf_af
[] = {
677 {"length", "dcp-af.len",
678 FT_UINT32
, BASE_DEC
, NULL
, 0,
679 "length in bytes of the payload", HFILL
}
682 {"frame count", "dcp-af.seq",
683 FT_UINT16
, BASE_DEC
, NULL
, 0,
684 "Logical Frame Number", HFILL
}
687 {"crc flag", "dcp-af.crcflag",
688 FT_BOOLEAN
, 8, NULL
, 0x80,
689 "Frame is protected by CRC", HFILL
}
692 {"Major Revision", "dcp-af.maj",
693 FT_UINT8
, BASE_DEC
, NULL
, 0x70,
694 "Major Protocol Revision", HFILL
}
697 {"Minor Revision", "dcp-af.min",
698 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
699 "Minor Protocol Revision", HFILL
}
702 {"Payload Type", "dcp-af.pt",
703 FT_STRING
, BASE_NONE
, NULL
, 0,
704 "T means Tag Packets, all other values reserved", HFILL
}
707 {"CRC", "dcp-af.crc",
708 FT_UINT16
, BASE_HEX
, NULL
, 0,
712 {"CRC OK", "dcp-af.crc_ok",
713 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
718 static hf_register_info hf_pft
[] = {
721 {"Sub-protocol", "dcp-pft.pt",
722 FT_UINT8
, BASE_DEC
, NULL
, 0,
727 {"Sequence No", "dcp-pft.seq",
728 FT_UINT16
, BASE_DEC
, NULL
, 0,
729 "PFT Sequence No", HFILL
}
732 {"Fragment Index", "dcp-pft.findex",
733 FT_UINT24
, BASE_DEC
, NULL
, 0,
734 "Index of the fragment within one AF Packet", HFILL
}
737 {"Fragment Count", "dcp-pft.fcount",
738 FT_UINT24
, BASE_DEC
, NULL
, 0,
739 "Number of fragments produced from this AF Packet", HFILL
}
742 {"FEC", "dcp-pft.fec",
743 FT_BOOLEAN
, 16, NULL
, 0x8000,
744 "When set the optional RS header is present", HFILL
}
747 {"Addr", "dcp-pft.addr",
748 FT_BOOLEAN
, 16, NULL
, 0x4000,
749 "When set the optional transport header is present", HFILL
}
752 {"fragment length", "dcp-pft.len",
753 FT_UINT16
, BASE_DEC
, NULL
, 0x3fff,
754 "length in bytes of the payload of this fragment", HFILL
}
757 {"RSk", "dcp-pft.rsk",
758 FT_UINT8
, BASE_DEC
, NULL
, 0,
759 "The length of the Reed Solomon data word", HFILL
}
762 {"RSz", "dcp-pft.rsz",
763 FT_UINT8
, BASE_DEC
, NULL
, 0,
764 "The number of padding bytes in the last Reed Solomon block", HFILL
}
767 {"source addr", "dcp-pft.source",
768 FT_UINT16
, BASE_DEC
, NULL
, 0,
769 "PFT source identifier", HFILL
}
772 {"dest addr", "dcp-pft.dest",
773 FT_UINT16
, BASE_DEC
, NULL
, 0,
774 "PFT destination identifier", HFILL
}
777 {"header CRC", "dcp-pft.crc",
778 FT_UINT16
, BASE_HEX
, NULL
, 0,
779 "PFT Header CRC", HFILL
}
782 {"PFT CRC OK", "dcp-pft.crc_ok",
783 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
784 "PFT Header CRC OK", HFILL
}
787 {"Message fragments", "dcp-pft.fragments",
788 FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
790 {"Message fragment", "dcp-pft.fragment",
791 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
792 {&hf_edcp_fragment_overlap
,
793 {"Message fragment overlap", "dcp-pft.fragment.overlap",
794 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
795 {&hf_edcp_fragment_overlap_conflicts
,
796 {"Message fragment overlapping with conflicting data",
797 "dcp-pft.fragment.overlap.conflicts",
798 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
799 {&hf_edcp_fragment_multiple_tails
,
800 {"Message has multiple tail fragments",
801 "dcp-pft.fragment.multiple_tails",
802 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
803 {&hf_edcp_fragment_too_long_fragment
,
804 {"Message fragment too long", "dcp-pft.fragment.too_long_fragment",
805 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
806 {&hf_edcp_fragment_error
,
807 {"Message defragmentation error", "dcp-pft.fragment.error",
808 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
809 {&hf_edcp_fragment_count
,
810 {"Message fragment count", "dcp-pft.fragment.count",
811 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
812 {&hf_edcp_reassembled_in
,
813 {"Reassembled in", "dcp-pft.reassembled.in",
814 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
815 {&hf_edcp_reassembled_length
,
816 {"Reassembled DCP (ETSI) length", "dcp-pft.reassembled.length",
817 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
820 {"C max", "dcp-pft.cmax",
821 FT_UINT16
, BASE_DEC
, NULL
, 0,
822 "Maximum number of RS chunks sent", HFILL
}
825 {"Rx min", "dcp-pft.rxmin",
826 FT_UINT16
, BASE_DEC
, NULL
, 0,
827 "Minimum number of fragments needed for RS decode", HFILL
}
829 {&hf_edcp_rs_corrected
,
830 {"RS Symbols Corrected", "dcp-pft.rs_corrected",
831 FT_INT16
, BASE_DEC
, NULL
, 0,
832 "Number of symbols corrected by RS decode or -1 for failure", HFILL
}
836 {"RS decode OK", "dcp-pft.rs_ok",
837 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
838 "successfully decoded RS blocks", HFILL
}
840 {&hf_edcp_pft_payload
,
841 {"payload", "dcp-pft.payload",
842 FT_BYTES
, BASE_NONE
, NULL
, 0,
843 "PFT Payload", HFILL
}
847 static hf_register_info hf_tpl
[] = {
849 {"tag", "dcp-tpl.tlv",
850 FT_BYTES
, BASE_NONE
, NULL
, 0,
855 {"Type", "dcp-tpl.ptr",
856 FT_STRING
, BASE_NONE
, NULL
, 0,
857 "Protocol Type & Revision", HFILL
}
862 /* Setup protocol subtree array */
863 static gint
*ett
[] = {
872 proto_dcp_etsi
= proto_register_protocol ("ETSI Distribution & Communication Protocol (for DRM)", /* name */
873 "DCP (ETSI)", /* short name */
874 "dcp-etsi" /* abbrev */
876 proto_af
= proto_register_protocol ("DCP Application Framing Layer", "DCP-AF", "dcp-af");
877 proto_pft
= proto_register_protocol ("DCP Protection, Fragmentation & Transport Layer", "DCP-PFT", "dcp-pft");
878 proto_tpl
= proto_register_protocol ("DCP Tag Packet Layer", "DCP-TPL", "dcp-tpl");
880 proto_register_field_array (proto_dcp_etsi
, hf_edcp
, array_length (hf_edcp
));
881 proto_register_field_array (proto_af
, hf_af
, array_length (hf_af
));
882 proto_register_field_array (proto_pft
, hf_pft
, array_length (hf_pft
));
883 proto_register_field_array (proto_tpl
, hf_tpl
, array_length (hf_tpl
));
884 proto_register_subtree_array (ett
, array_length (ett
));
886 /* subdissector code */
887 dcp_dissector_table
= register_dissector_table("dcp-etsi.sync",
888 "DCP Sync", FT_STRING
, BASE_NONE
);
889 af_dissector_table
= register_dissector_table("dcp-af.pt",
890 "DCP-AF Payload Type", FT_UINT8
, BASE_DEC
);
892 tpl_dissector_table
= register_dissector_table("dcp-tpl.ptr",
893 "DCP-TPL Protocol Type & Revision", FT_STRING
, BASE_NONE
);
895 register_init_routine(dcp_init_protocol
);
900 * Editor modelines - http://www.wireshark.org/tools/modelines.html
905 * indent-tabs-mode: nil
908 * vi: set shiftwidth=2 tabstop=8 expandtab:
909 * :indentSize=2:tabSize=8:noTabs=true: