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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * Ref: ETSI DCP (ETSI TS 102 821)
34 #include <epan/packet.h>
35 #include <epan/reassemble.h>
36 #include <epan/crcdrm.h>
37 #include <epan/reedsolomon.h>
38 #include <epan/emem.h>
41 /* forward reference */
43 static gboolean dissect_dcp_etsi (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
44 static void dissect_af (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
45 static void dissect_pft (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
46 static void dissect_tpl(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
48 static dissector_table_t dcp_dissector_table;
49 static dissector_table_t af_dissector_table;
50 static dissector_table_t tpl_dissector_table;
52 static int proto_dcp_etsi = -1;
53 static int proto_af = -1;
54 static int proto_pft = -1;
55 static int proto_tpl = -1;
56 static int hf_edcp_sync = -1;
57 static int hf_edcp_len = -1;
58 static int hf_edcp_seq = -1;
59 static int hf_edcp_crcflag = -1;
60 static int hf_edcp_maj = -1;
61 static int hf_edcp_min = -1;
62 static int hf_edcp_pt = -1;
63 static int hf_edcp_crc = -1;
64 static int hf_edcp_crc_ok = -1;
65 static int hf_edcp_pft_pt = -1;
66 static int hf_edcp_pseq = -1;
67 static int hf_edcp_findex = -1;
68 static int hf_edcp_fcount = -1;
69 static int hf_edcp_fecflag = -1;
70 static int hf_edcp_addrflag = -1;
71 static int hf_edcp_plen = -1;
72 static int hf_edcp_rsk = -1;
73 static int hf_edcp_rsz = -1;
74 static int hf_edcp_source = -1;
75 static int hf_edcp_dest = -1;
76 static int hf_edcp_hcrc = -1;
77 static int hf_edcp_hcrc_ok = -1;
78 static int hf_edcp_c_max = -1;
79 static int hf_edcp_rx_min = -1;
80 static int hf_edcp_rs_corrected = -1;
81 static int hf_edcp_rs_ok = -1;
82 static int hf_edcp_pft_payload = -1;
84 static int hf_tpl_tlv = -1;
85 static int hf_tpl_ptr = -1;
87 static int hf_edcp_fragments = -1;
88 static int hf_edcp_fragment = -1;
89 static int hf_edcp_fragment_overlap = -1;
90 static int hf_edcp_fragment_overlap_conflicts = -1;
91 static int hf_edcp_fragment_multiple_tails = -1;
92 static int hf_edcp_fragment_too_long_fragment = -1;
93 static int hf_edcp_fragment_error = -1;
94 static int hf_edcp_reassembled_in = -1;
95 static int hf_edcp_reassembled_length = -1;
97 /* Initialize the subtree pointers */
98 static gint ett_edcp = -1;
99 static gint ett_af = -1;
100 static gint ett_pft = -1;
101 static gint ett_tpl = -1;
102 static gint ett_edcp_fragment = -1;
103 static gint ett_edcp_fragments = -1;
105 static GHashTable *dcp_fragment_table = NULL;
106 static GHashTable *dcp_reassembled_table = NULL;
108 static const fragment_items dcp_frag_items = {
109 /* Fragment subtrees */
112 /* Fragment fields */
115 &hf_edcp_fragment_overlap,
116 &hf_edcp_fragment_overlap_conflicts,
117 &hf_edcp_fragment_multiple_tails,
118 &hf_edcp_fragment_too_long_fragment,
119 &hf_edcp_fragment_error,
120 /* Reassembled in field */
121 &hf_edcp_reassembled_in,
122 /* Reassembled length field */
123 &hf_edcp_reassembled_length,
128 /** initialise the DCP protocol. Details follow
132 dcp_init_protocol(void)
134 fragment_table_init (&dcp_fragment_table);
135 reassembled_table_init (&dcp_reassembled_table);
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)
150 proto_tree *dcp_tree = NULL;
152 /* 6.1 AF packet structure
156 * 2 bytes 4 bytes 2 bytes 1 byte 1 byte
158 * SYNC: two-byte ASCII representation of "AF".
159 * LEN: length of the payload, in bytes.
160 * SEQ: sequence number
161 * AR: AF protocol Revision - a field combining the CF, MAJ and MIN fields
162 * CF: CRC Flag, 0 if the CRC field is not used
163 * MAJ: major revision of the AF protocol in use, see clause 6.2.
164 * MIN: minor revision of the AF protocol in use, see clause 6.2.
165 * Protocol Type (PT): single byte encoding the protocol of the data carried in the payload. For TAG Packets, the value
166 * shall be the ASCII representation of "T".
168 * 7.1 PFT fragment structure
170 * 14, 16, 18 or 20 bytes (depending on options) Optional present if FEC=1 Optional present if Addr = 1
171 * Psync Pseq Findex Fcount FEC HCRC Addr Plen | RSk RSz | Source Dest
172 * 16 bits 16 bits 24 bits 24 bits 1 bit 16 bits 1 bit 14 bits | 8 bits 8 bits | 16 bits 16 bits
174 * Psync: the ASCII string "PF" is used as the synchronization word for the PFT Layer
176 * Don't accept this packet unless at least a full AF header present(10 bytes).
177 * It should be possible to strengthen the heuristic further if need be.
179 if(tvb_length(tvb) < 11)
182 sync = tvb_get_ephemeral_string (tvb, 0, 2);
183 if((sync[0]!='A' && sync[0]!='P') || sync[1]!='F')
186 pinfo->current_proto = "DCP (ETSI)";
188 /* Clear out stuff in the info column */
189 col_clear(pinfo->cinfo, COL_INFO);
190 col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCP (ETSI)");
191 /*col_append_fstr (pinfo->cinfo, COL_INFO, " tvb %d", tvb_length(tvb));*/
194 proto_item *ti = NULL;
195 ti = proto_tree_add_item (tree, proto_dcp_etsi, tvb, 0, -1, FALSE);
196 dcp_tree = proto_item_add_subtree (ti, ett_edcp);
199 dissector_try_string(dcp_dissector_table, (char*)sync, tvb, pinfo, dcp_tree);
203 #define PFT_RS_N_MAX 207
205 #define PFT_RS_P (PFT_RS_K - PFT_RS_N_MAX)
209 void rs_deinterleave(const guint8 *input, guint8 *output, guint16 plen, guint32 fcount)
212 for(fidx=0; fidx<fcount; fidx++)
215 for (r=0; r<plen; r++)
217 output[fidx+r*fcount] = input[fidx*plen+r];
223 gboolean rs_correct_data(guint8 *deinterleaved, guint8 *output,
224 guint32 c_max, guint16 rsk, guint16 rsz _U_)
226 guint32 i, index_coded = 0, index_out = 0;
228 for (i=0; i<c_max; i++)
230 memcpy(output+index_out, deinterleaved+index_coded, rsk);
232 memcpy(output+index_out+PFT_RS_N_MAX, deinterleaved+index_coded, PFT_RS_P);
233 index_coded += PFT_RS_P;
234 err_corr = eras_dec_rs(output+index_out, NULL, 0);
243 /* Don't attempt reassembly if we have a huge number of fragments. */
244 #define MAX_FRAGMENTS ((1 * 1024 * 1024) / sizeof(guint32))
247 dissect_pft_fec_detailed(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
259 guint16 decoded_size;
262 gboolean first, last;
263 tvbuff_t *new_tvb=NULL;
265 if (fcount > MAX_FRAGMENTS) {
267 proto_tree_add_text(tree, tvb , 0, -1, "[Reassembly of %d fragments not attempted]", fcount);
272 last = fcount == (findex+1);
273 decoded_size = fcount*plen;
274 c_max = fcount*plen/(rsk+PFT_RS_P); /* rounded down */
275 rx_min = c_max*rsk/plen;
276 if(rx_min*plen<c_max*rsk)
279 new_tvb = process_reassembled_data (tvb, offset, pinfo,
280 "Reassembled DCP (ETSI)",
281 fdx, &dcp_frag_items,
287 fragment_data *fd_head;
290 proto_tree_add_text (tree, tvb, 0, -1, "want %d, got %d need %d",
291 fcount, fragments, rx_min
293 got = ep_alloc(fcount*sizeof(guint32));
295 /* make a list of the findex (offset) numbers of the fragments we have */
296 fd = fragment_get(pinfo, seq, dcp_fragment_table);
297 for (fd_head = fd; fd_head != NULL; fd_head = fd_head->next) {
299 got[fragments++] = fd_head->offset; /* this is the findex of the fragment */
302 /* put a sentinel at the end */
303 got[fragments++] = fcount;
304 /* have we got enough for Reed Solomon to try to correct ? */
305 if(fragments>=rx_min) { /* yes, in theory */
306 guint i,current_findex;
307 fragment_data *frag=NULL;
308 guint8 *dummy_data = (guint8*) ep_alloc0 (plen);
309 tvbuff_t *dummytvb = tvb_new_real_data(dummy_data, plen, plen);
310 /* try and decode with missing fragments */
312 proto_tree_add_text (tree, tvb, 0, -1, "want %d, got %d need %d",
313 fcount, fragments, rx_min
315 /* fill the fragment table with empty fragments */
317 for(i=0; i<fragments; i++) {
318 guint next_fragment_we_have = got[i];
319 if (next_fragment_we_have > MAX_FRAGMENTS) {
321 proto_tree_add_text(tree, tvb , 0, -1, "[Reassembly of %d fragments not attempted]", next_fragment_we_have);
324 for(; current_findex<next_fragment_we_have; current_findex++) {
325 frag = fragment_add_seq_check (dummytvb, 0, pinfo, seq,
326 dcp_fragment_table, dcp_reassembled_table,
327 current_findex, plen, (current_findex+1!=fcount));
329 current_findex++; /* skip over the fragment we have */
332 new_tvb = process_reassembled_data (tvb, offset, pinfo,
333 "Reassembled DCP (ETSI)",
334 frag, &dcp_frag_items,
339 gboolean decoded = TRUE;
340 tvbuff_t *dtvb = NULL;
341 const guint8 *input = tvb_get_ptr(new_tvb, 0, -1);
342 guint16 reassembled_size = tvb_length(new_tvb);
343 guint8 *deinterleaved = (guint8*) g_malloc (reassembled_size);
344 guint8 *output = (guint8*) g_malloc (decoded_size);
345 rs_deinterleave(input, deinterleaved, plen, fcount);
347 dtvb = tvb_new_child_real_data(tvb, deinterleaved, reassembled_size, reassembled_size);
348 add_new_data_source(pinfo, dtvb, "Deinterleaved");
349 tvb_set_free_cb(dtvb, g_free);
351 decoded = rs_correct_data(deinterleaved, output, c_max, rsk, rsz);
353 proto_tree_add_boolean (tree, hf_edcp_rs_ok, tvb, offset, 2, decoded);
355 new_tvb = tvb_new_child_real_data(dtvb, output, decoded_size, decoded_size);
356 add_new_data_source(pinfo, new_tvb, "RS Error Corrected Data");
357 tvb_set_free_cb(new_tvb, g_free);
363 /** Handle a PFT packet which has the fragmentation header. This uses the
364 * standard wireshark methods for reassembling fragments. If FEC is used,
365 * the FEC is handled too. For the moment, all the fragments must be
366 * available but this could be improved.
367 * \param[in,out] tvb The buffer containing the current fragment
368 * \param[in,out] pinfo The packet info structure
369 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
370 * \param[in] findex the fragment count
371 * \param[in] fcount the number of fragments
372 * \param[in] seq the sequence number of the reassembled packet
373 * \param[in] offset the offset into the tvb of the fragment
374 * \param[in] plen the length of each fragment
375 * \param[in] fec is fec used
376 * \param[in] rsk the number of useful bytes in each chunk
377 * \param[in] rsz the number of padding bytes in each chunk
380 dissect_pft_fragmented(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
391 gboolean first, last;
392 tvbuff_t *new_tvb=NULL;
393 fragment_data *frag_edcp = NULL;
394 pinfo->fragmented = TRUE;
396 last = fcount == (findex+1);
397 frag_edcp = fragment_add_seq_check (
400 dcp_fragment_table, dcp_reassembled_table,
405 new_tvb = dissect_pft_fec_detailed(
406 tvb, pinfo, tree, findex, fcount, seq, offset, plen, fec, rsk, rsz, frag_edcp
409 new_tvb = process_reassembled_data (tvb, offset, pinfo,
410 "Reassembled DCP (ETSI)",
411 frag_edcp, &dcp_frag_items,
414 if (check_col (pinfo->cinfo, COL_INFO)) {
416 col_append_str (pinfo->cinfo, COL_INFO, " (Message Reassembled)");
419 col_append_str (pinfo->cinfo, COL_INFO, " (Message Reassembly failure)");
421 col_append_fstr (pinfo->cinfo, COL_INFO, " (Message fragment %u)", findex);
425 col_append_str (pinfo->cinfo, COL_INFO, " (first)");
427 col_append_str (pinfo->cinfo, COL_INFO, " (last)");
432 /** Dissect a PFT packet. Details follow
434 * \param[in,out] tvb The buffer containing the packet
435 * \param[in,out] pinfo The packet info structure
436 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
439 dissect_pft(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
443 guint16 seq, payload_len, hcrc;
444 guint32 findex, fcount;
445 proto_tree *pft_tree = NULL;
446 proto_item *ti = NULL, *li = NULL;
447 tvbuff_t *next_tvb = NULL;
448 gboolean fec = FALSE;
449 guint16 rsk=0, rsz=0;
451 pinfo->current_proto = "DCP-PFT";
452 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCP-PFT");
454 if (tree) { /* we are being asked for details */
455 ti = proto_tree_add_item (tree, proto_pft, tvb, 0, -1, FALSE);
456 pft_tree = proto_item_add_subtree (ti, ett_pft);
457 proto_tree_add_item (pft_tree, hf_edcp_sync, tvb, offset, 2, FALSE);
460 seq = tvb_get_ntohs (tvb, offset);
462 proto_tree_add_item (pft_tree, hf_edcp_pseq, tvb, offset, 2, FALSE);
465 findex = tvb_get_ntoh24 (tvb, offset);
467 proto_tree_add_item (pft_tree, hf_edcp_findex, tvb, offset, 3, FALSE);
470 fcount = tvb_get_ntoh24 (tvb, offset);
472 proto_tree_add_item (pft_tree, hf_edcp_fcount, tvb, offset, 3, FALSE);
475 plen = tvb_get_ntohs (tvb, offset);
476 payload_len = plen & 0x3fff;
478 proto_tree_add_item (pft_tree, hf_edcp_fecflag, tvb, offset, 2, FALSE);
479 proto_tree_add_item (pft_tree, hf_edcp_addrflag, tvb, offset, 2, FALSE);
480 li = proto_tree_add_item (pft_tree, hf_edcp_plen, tvb, offset, 2, FALSE);
485 rsk = tvb_get_guint8 (tvb, offset);
487 proto_tree_add_item (pft_tree, hf_edcp_rsk, tvb, offset, 1, FALSE);
489 rsz = tvb_get_guint8 (tvb, offset);
491 proto_tree_add_item (pft_tree, hf_edcp_rsz, tvb, offset, 1, FALSE);
496 proto_tree_add_item (pft_tree, hf_edcp_source, tvb, offset, 2, FALSE);
499 proto_tree_add_item (pft_tree, hf_edcp_dest, tvb, offset, 2, FALSE);
503 proto_item *ci = NULL;
504 guint header_len = offset+2;
505 const char *crc_buf = (const char *) tvb_get_ptr(tvb, 0, header_len);
506 unsigned long c = crc_drm(crc_buf, header_len, 16, 0x11021, 1);
507 ci = proto_tree_add_item (pft_tree, hf_edcp_hcrc, tvb, offset, 2, FALSE);
508 proto_item_append_text(ci, " (%s)", (c==0xe2f0)?"Ok":"bad");
509 proto_tree_add_boolean(pft_tree, hf_edcp_hcrc_ok, tvb, offset, 2, c==0xe2f0);
511 hcrc = tvb_get_ntohs (tvb, offset);
513 if (fcount > 1) { /* fragmented*/
514 gboolean save_fragmented = pinfo->fragmented;
515 guint16 real_len = tvb_length(tvb)-offset;
516 proto_tree_add_item (pft_tree, hf_edcp_pft_payload, tvb, offset, real_len, FALSE);
517 if(real_len != payload_len) {
519 proto_item_append_text(li, " (length error (%d))", real_len);
521 next_tvb = dissect_pft_fragmented(tvb, pinfo, pft_tree,
522 findex, fcount, seq, offset, real_len,
525 pinfo->fragmented = save_fragmented;
527 next_tvb = tvb_new_subset_remaining (tvb, offset);
530 dissect_af(next_tvb, pinfo, tree);
534 /** Dissect an AF Packet. Parse an AF packet, checking the CRC if the CRC valid
535 * flag is set and calling any registered sub dissectors on the payload type.
536 * Currently only a payload type 'T' is defined which is the tag packet layer.
537 * If any others are defined then they can register themselves.
538 * \param[in,out] tvb The buffer containing the packet
539 * \param[in,out] pinfo The packet info structure
540 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
543 dissect_af (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
546 proto_item *ti = NULL;
547 proto_item *li = NULL;
548 proto_item *ci = NULL;
549 proto_tree *af_tree = NULL;
552 tvbuff_t *next_tvb = NULL;
554 pinfo->current_proto = "DCP-AF";
555 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCP-AF");
557 if (tree) { /* we are being asked for details */
558 ti = proto_tree_add_item (tree, proto_af, tvb, 0, -1, FALSE);
559 af_tree = proto_item_add_subtree (ti, ett_af);
560 proto_tree_add_item (af_tree, hf_edcp_sync, tvb, offset, 2, FALSE);
563 payload_len = tvb_get_ntohl(tvb, offset);
565 guint32 real_payload_len = tvb_length(tvb)-12;
566 li = proto_tree_add_item (af_tree, hf_edcp_len, tvb, offset, 4, FALSE);
567 if(real_payload_len < payload_len) {
568 proto_item_append_text (li, " (wrong len claims %d is %d)",
569 payload_len, real_payload_len
571 } else if(real_payload_len > payload_len) {
572 proto_item_append_text (li, " (%d bytes in packet after end of AF frame)",
573 real_payload_len-payload_len
579 proto_tree_add_item (af_tree, hf_edcp_seq, tvb, offset, 2, FALSE);
581 ver = tvb_get_guint8 (tvb, offset);
583 proto_tree_add_item (af_tree, hf_edcp_crcflag, tvb, offset, 1, FALSE);
584 proto_tree_add_item (af_tree, hf_edcp_maj, tvb, offset, 1, FALSE);
585 proto_tree_add_item (af_tree, hf_edcp_min, tvb, offset, 1, FALSE);
588 pt = tvb_get_guint8 (tvb, offset);
590 proto_tree_add_item (af_tree, hf_edcp_pt, tvb, offset, 1, FALSE);
592 next_tvb = tvb_new_subset (tvb, offset, payload_len, -1);
593 offset += payload_len;
595 ci = proto_tree_add_item (af_tree, hf_edcp_crc, tvb, offset, 2, FALSE);
596 if (ver & 0x80) { /* crc valid */
597 guint len = offset+2;
598 const char *crc_buf = (const char *) tvb_get_ptr(tvb, 0, len);
599 unsigned long c = crc_drm(crc_buf, len, 16, 0x11021, 1);
601 proto_item_append_text(ci, " (%s)", (c==0xe2f0)?"Ok":"bad");
602 proto_tree_add_boolean(af_tree, hf_edcp_crc_ok, tvb, offset, 2, c==0xe2f0);
606 dissector_try_uint(af_dissector_table, pt, next_tvb, pinfo, tree);
609 /** Dissect the Tag Packet Layer.
610 * Split the AF packet into its tag items. Each tag item has a 4 character
611 * tag, a length in bits and a value. The *ptr tag is dissected in the routine.
612 * All other tags are listed and may be handled by other dissectors.
613 * Child dissectors are tied to the parent tree, not to this tree, so that
614 * they appear at the same level as DCP.
615 * \param[in,out] tvb The buffer containing the packet
616 * \param[in,out] pinfo The packet info structure
617 * \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
620 dissect_tpl(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
622 proto_tree *tpl_tree = NULL;
627 pinfo->current_proto = "DCP-TPL";
628 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCP-TPL");
631 proto_item *ti = NULL;
632 ti = proto_tree_add_item (tree, proto_tpl, tvb, 0, -1, FALSE);
633 tpl_tree = proto_item_add_subtree (ti, ett_tpl);
635 while(offset<tvb_length(tvb)) {
638 char *tag = (char*)tvb_get_ephemeral_string (tvb, offset, 4); offset += 4;
639 bits = tvb_get_ntohl(tvb, offset); offset += 4;
644 proto_item *i = NULL;
645 if(strcmp(tag, "*ptr")==0) {
646 prot = (char*)tvb_get_ephemeral_string (tvb, offset, 4);
647 maj = tvb_get_ntohs(tvb, offset+4);
648 min = tvb_get_ntohs(tvb, offset+6);
649 i = proto_tree_add_bytes_format(tpl_tree, hf_tpl_tlv, tvb,
650 offset-8, bytes+8, tvb_get_ptr(tvb, offset, bytes),
651 "%s %s rev %d.%d", tag, prot, maj, min);
653 i = proto_tree_add_bytes_format(tpl_tree, hf_tpl_tlv, tvb,
654 offset-8, bytes+8, tvb_get_ptr(tvb, offset, bytes),
655 "%s (%u bits)", tag, bits);
660 if(prot) { /* prot is non-NULL only if we have our tree. */
661 dissector_try_string(tpl_dissector_table, prot, tvb, pinfo, tree->parent);
666 proto_reg_handoff_dcp_etsi (void)
668 dissector_handle_t af_handle;
669 dissector_handle_t pft_handle;
670 dissector_handle_t tpl_handle;
672 af_handle = create_dissector_handle(dissect_af, proto_af);
673 pft_handle = create_dissector_handle(dissect_pft, proto_pft);
674 tpl_handle = create_dissector_handle(dissect_tpl, proto_tpl);
675 heur_dissector_add("udp", dissect_dcp_etsi, proto_dcp_etsi);
676 dissector_add_string("dcp-etsi.sync", "AF", af_handle);
677 dissector_add_string("dcp-etsi.sync", "PF", pft_handle);
678 /* if there are ever other payload types ...*/
679 dissector_add_uint("dcp-af.pt", 'T', tpl_handle);
683 proto_register_dcp_etsi (void)
685 static hf_register_info hf_edcp[] = {
687 {"sync", "dcp-etsi.sync",
688 FT_STRING, BASE_NONE, NULL, 0,
692 static hf_register_info hf_af[] = {
694 {"length", "dcp-af.len",
695 FT_UINT32, BASE_DEC, NULL, 0,
696 "length in bytes of the payload", HFILL}
699 {"frame count", "dcp-af.seq",
700 FT_UINT16, BASE_DEC, NULL, 0,
701 "Logical Frame Number", HFILL}
704 {"crc flag", "dcp-af.crcflag",
705 FT_BOOLEAN, 8, NULL, 0x80,
706 "Frame is protected by CRC", HFILL}
709 {"Major Revision", "dcp-af.maj",
710 FT_UINT8, BASE_DEC, NULL, 0x70,
711 "Major Protocol Revision", HFILL}
714 {"Minor Revision", "dcp-af.min",
715 FT_UINT8, BASE_DEC, NULL, 0x0f,
716 "Minor Protocol Revision", HFILL}
719 {"Payload Type", "dcp-af.pt",
720 FT_STRING, BASE_NONE, NULL, 0,
721 "T means Tag Packets, all other values reserved", HFILL}
724 {"CRC", "dcp-af.crc",
725 FT_UINT16, BASE_HEX, NULL, 0,
729 {"CRC OK", "dcp-af.crc_ok",
730 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
735 static hf_register_info hf_pft[] = {
737 {"Sub-protocol", "dcp-pft.pt",
738 FT_UINT8, BASE_DEC, NULL, 0,
742 {"Sequence No", "dcp-pft.seq",
743 FT_UINT16, BASE_DEC, NULL, 0,
744 "PFT Sequence No", HFILL}
747 {"Fragment Index", "dcp-pft.findex",
748 FT_UINT24, BASE_DEC, NULL, 0,
749 "Index of the fragment within one AF Packet", HFILL}
752 {"Fragment Count", "dcp-pft.fcount",
753 FT_UINT24, BASE_DEC, NULL, 0,
754 "Number of fragments produced from this AF Packet", HFILL}
757 {"FEC", "dcp-pft.fec",
758 FT_BOOLEAN, 16, NULL, 0x8000,
759 "When set the optional RS header is present", HFILL}
762 {"Addr", "dcp-pft.addr",
763 FT_BOOLEAN, 16, NULL, 0x4000,
764 "When set the optional transport header is present", HFILL}
767 {"fragment length", "dcp-pft.len",
768 FT_UINT16, BASE_DEC, NULL, 0x3fff,
769 "length in bytes of the payload of this fragment", HFILL}
772 {"RSk", "dcp-pft.rsk",
773 FT_UINT8, BASE_DEC, NULL, 0,
774 "The length of the Reed Solomon data word", HFILL}
777 {"RSz", "dcp-pft.rsz",
778 FT_UINT8, BASE_DEC, NULL, 0,
779 "The number of padding bytes in the last Reed Solomon block", HFILL}
782 {"source addr", "dcp-pft.source",
783 FT_UINT16, BASE_DEC, NULL, 0,
784 "PFT source identifier", HFILL}
787 {"dest addr", "dcp-pft.dest",
788 FT_UINT16, BASE_DEC, NULL, 0,
789 "PFT destination identifier", HFILL}
792 {"header CRC", "dcp-pft.crc",
793 FT_UINT16, BASE_HEX, NULL, 0,
794 "PFT Header CRC", HFILL}
797 {"PFT CRC OK", "dcp-pft.crc_ok",
798 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
799 "PFT Header CRC OK", HFILL}
802 {"Message fragments", "dcp-pft.fragments",
803 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL}},
805 {"Message fragment", "dcp-pft.fragment",
806 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL}},
807 {&hf_edcp_fragment_overlap,
808 {"Message fragment overlap", "dcp-pft.fragment.overlap",
809 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}},
810 {&hf_edcp_fragment_overlap_conflicts,
811 {"Message fragment overlapping with conflicting data",
812 "dcp-pft.fragment.overlap.conflicts",
813 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}},
814 {&hf_edcp_fragment_multiple_tails,
815 {"Message has multiple tail fragments",
816 "dcp-pft.fragment.multiple_tails",
817 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}},
818 {&hf_edcp_fragment_too_long_fragment,
819 {"Message fragment too long", "dcp-pft.fragment.too_long_fragment",
820 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}},
821 {&hf_edcp_fragment_error,
822 {"Message defragmentation error", "dcp-pft.fragment.error",
823 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL}},
824 {&hf_edcp_reassembled_in,
825 {"Reassembled in", "dcp-pft.reassembled.in",
826 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL}},
827 {&hf_edcp_reassembled_length,
828 {"Reassembled DCP (ETSI) length", "dcp-pft.reassembled.length",
829 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL}},
831 {"C max", "dcp-pft.cmax",
832 FT_UINT16, BASE_DEC, NULL, 0,
833 "Maximum number of RS chunks sent", HFILL}
836 {"Rx min", "dcp-pft.rxmin",
837 FT_UINT16, BASE_DEC, NULL, 0,
838 "Minimum number of fragments needed for RS decode", HFILL}
840 {&hf_edcp_rs_corrected,
841 {"RS Symbols Corrected", "dcp-pft.rs_corrected",
842 FT_INT16, BASE_DEC, NULL, 0,
843 "Number of symbols corrected by RS decode or -1 for failure", HFILL}
846 {"RS decode OK", "dcp-pft.rs_ok",
847 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
848 "successfully decoded RS blocks", HFILL}
850 {&hf_edcp_pft_payload,
851 {"payload", "dcp-pft.payload",
852 FT_BYTES, BASE_NONE, NULL, 0,
853 "PFT Payload", HFILL}
857 static hf_register_info hf_tpl[] = {
859 {"tag", "dcp-tpl.tlv",
860 FT_BYTES, BASE_NONE, NULL, 0,
864 {"Type", "dcp-tpl.ptr",
865 FT_STRING, BASE_NONE, NULL, 0,
866 "Protocol Type & Revision", HFILL}
870 /* Setup protocol subtree array */
871 static gint *ett[] = {
880 proto_dcp_etsi = proto_register_protocol ("ETSI Distribution & Communication Protocol (for DRM)", /* name */
881 "DCP (ETSI)", /* short name */
882 "dcp-etsi" /* abbrev */
884 proto_af = proto_register_protocol ("DCP Application Framing Layer", "DCP-AF", "dcp-af");
885 proto_pft = proto_register_protocol ("DCP Protection, Fragmentation & Transport Layer", "DCP-PFT", "dcp-pft");
886 proto_tpl = proto_register_protocol ("DCP Tag Packet Layer", "DCP-TPL", "dcp-tpl");
888 proto_register_field_array (proto_dcp_etsi, hf_edcp, array_length (hf_edcp));
889 proto_register_field_array (proto_af, hf_af, array_length (hf_af));
890 proto_register_field_array (proto_pft, hf_pft, array_length (hf_pft));
891 proto_register_field_array (proto_tpl, hf_tpl, array_length (hf_tpl));
892 proto_register_subtree_array (ett, array_length (ett));
894 /* subdissector code */
895 dcp_dissector_table = register_dissector_table("dcp-etsi.sync",
896 "DCP Sync", FT_STRING, BASE_NONE);
897 af_dissector_table = register_dissector_table("dcp-af.pt",
898 "AF Payload Type", FT_UINT8, BASE_DEC);
900 tpl_dissector_table = register_dissector_table("dcp-tpl.ptr",
901 "AF Payload Type", FT_STRING, BASE_NONE);
903 register_init_routine(dcp_init_protocol);