epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-dcp-etsi.c
blob111512620394a2b26c7f03c51c4612e511f5773e
1 /* packet-dcp-etsi.c
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
11 * Protocol info
12 * Ref: ETSI DCP (ETSI TS 102 821)
15 #include "config.h"
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;
40 static int proto_af;
41 static int proto_pft;
42 static int proto_tpl;
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 */
86 static int ett_edcp;
87 static int ett_af;
88 static int ett_pft;
89 static int ett_tpl;
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 */
100 &ett_edcp_fragment,
101 &ett_edcp_fragments,
102 /* Fragment fields */
103 &hf_edcp_fragments,
104 &hf_edcp_fragment,
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 */
116 NULL,
117 /* Tag */
118 "Message fragments"
122 /** Dissect a DCP packet. Details follow
123 * here.
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.
127 static void
129 static int
130 dissect_dcp_etsi(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
132 uint8_t *sync;
133 proto_tree *dcp_tree;
134 proto_item *ti;
136 if(tvb_captured_length(tvb) < 11)
137 return false;
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.
157 static void
159 static bool
160 dissect_dcp_etsi_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data)
162 /* 6.1 AF packet structure
164 * AF Header
165 * SYNC LEN SEQ AR PT
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
179 * PFT Header
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.
189 uint16_t word;
191 if(tvb_captured_length(tvb) < 11)
192 return false;
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) {
199 return false;
201 /* Tag packets are the only payload type */
202 if (tvb_get_uint8(tvb, 9) != 'T') {
203 return false;
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) {
209 return false;
211 uint16_t plen = tvb_get_ntohs(tvb, 10);
212 unsigned header_len = 14;
213 if (plen & 0x8000) {
214 header_len += 2;
216 if (plen & 0x4000) {
217 header_len += 4;
219 if (tvb_captured_length(tvb) < header_len) {
220 return false;
222 if (crc16_x25_ccitt_tvb(tvb, header_len) != 0x1D0F) {
223 return false;
225 } else {
226 return false;
229 dissect_dcp_etsi(tvb, pinfo, tree, data);
231 return true;
234 #define PFT_RS_N_MAX 207
235 #define PFT_RS_K 255
236 #define PFT_RS_P (PFT_RS_K - PFT_RS_N_MAX)
239 static
240 void rs_deinterleave(const uint8_t *input, uint8_t *output, uint16_t plen, uint32_t fcount)
242 unsigned fidx;
243 for(fidx=0; fidx<fcount; fidx++)
245 int r;
246 for (r=0; r<plen; r++)
248 output[fidx+r*fcount] = input[fidx*plen+r];
253 static
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;
258 int err_corr;
259 for (i=0; i<c_max; i++)
261 memcpy(output+index_out, deinterleaved+index_coded, rsk);
262 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);
266 if (err_corr<0) {
267 return false;
269 index_out += rsk;
271 return true;
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
280 static tvbuff_t *
281 dissect_pft_fec_detailed(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
282 uint32_t findex _U_,
283 uint32_t fcount,
284 uint16_t seq,
285 int offset,
286 uint16_t plen,
287 bool fec _U_,
288 uint16_t rsk,
289 uint16_t rsz,
290 fragment_head *fdx
293 uint32_t decoded_size;
294 uint32_t c_max;
295 uint32_t rx_min;
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);
300 return NULL;
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);
306 if (fdx)
307 new_tvb = process_reassembled_data (tvb, offset, pinfo,
308 "Reassembled DCP (ETSI)",
309 fdx, &dcp_frag_items,
310 NULL, tree);
311 else {
312 unsigned fragments=0;
313 uint32_t *got;
314 fragment_item *fd;
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);
323 if (fd_head) {
324 for (fd = fd_head->next; fd != NULL && fragments < fcount; fd = fd->next) {
325 if(fd->tvb_data) {
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 */
340 current_findex = 0;
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);
345 return NULL;
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);
351 return NULL;
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 */
360 tvb_free(dummytvb);
362 if(frag)
363 new_tvb = process_reassembled_data (tvb, offset, pinfo,
364 "Reassembled DCP (ETSI)",
365 frag, &dcp_frag_items,
366 NULL, tree);
369 if(new_tvb && tvb_captured_length(new_tvb) > 0) {
370 bool decoded;
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");
387 return new_tvb;
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
407 static tvbuff_t *
408 dissect_pft_fragmented(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
409 uint32_t findex,
410 uint32_t fcount,
411 uint16_t seq,
412 int offset,
413 uint16_t plen,
414 bool fec,
415 uint16_t rsk,
416 uint16_t rsz
419 bool first, last;
420 tvbuff_t *new_tvb=NULL;
421 fragment_head *frag_edcp = NULL;
422 pinfo->fragmented = true;
423 first = findex == 0;
424 last = fcount == (findex+1);
425 frag_edcp = fragment_add_seq_check (
426 &dcp_reassembly_table,
427 tvb, offset,
428 pinfo, seq, NULL,
429 findex,
430 plen,
431 !last);
432 if(fec) {
433 new_tvb = dissect_pft_fec_detailed(
434 tvb, pinfo, tree, findex, fcount, seq, offset, plen, fec, rsk, rsz, frag_edcp
436 } else {
437 new_tvb = process_reassembled_data (tvb, offset, pinfo,
438 "Reassembled DCP (ETSI)",
439 frag_edcp, &dcp_frag_items,
440 NULL, tree);
442 if(new_tvb) {
443 col_append_str (pinfo->cinfo, COL_INFO, " (Message Reassembled)");
444 } else {
445 if(last) {
446 col_append_str (pinfo->cinfo, COL_INFO, " (Message Reassembly failure)");
447 } else {
448 col_append_fstr (pinfo->cinfo, COL_INFO, " (Message fragment %u)", findex);
451 if(first)
452 col_append_str (pinfo->cinfo, COL_INFO, " (first)");
453 if(last)
454 col_append_str (pinfo->cinfo, COL_INFO, " (last)");
455 return new_tvb;
458 /** Dissect a PFT packet. Details follow
459 * here.
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.
464 static int
465 dissect_pft(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data)
467 uint16_t plen;
468 int offset = 0;
469 uint16_t seq, payload_len;
470 uint32_t findex, fcount;
471 proto_tree *pft_tree;
472 proto_item *ti, *li;
473 tvbuff_t *next_tvb = NULL;
474 bool fec = false;
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);
483 offset += 2;
484 seq = tvb_get_ntohs (tvb, offset);
485 proto_tree_add_item (pft_tree, hf_edcp_pseq, tvb, offset, 2, ENC_BIG_ENDIAN);
487 offset += 2;
488 findex = tvb_get_ntoh24 (tvb, offset);
489 proto_tree_add_item (pft_tree, hf_edcp_findex, tvb, offset, 3, ENC_BIG_ENDIAN);
491 offset += 3;
492 fcount = tvb_get_ntoh24 (tvb, offset);
493 proto_tree_add_item (pft_tree, hf_edcp_fcount, tvb, offset, 3, ENC_BIG_ENDIAN);
495 offset += 3;
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);
502 offset += 2;
503 if (plen & 0x8000) {
504 fec = true;
505 rsk = tvb_get_uint8 (tvb, offset);
506 proto_tree_add_item (pft_tree, hf_edcp_rsk, tvb, offset, 1, ENC_BIG_ENDIAN);
507 offset += 1;
508 rsz = tvb_get_uint8 (tvb, offset);
509 proto_tree_add_item (pft_tree, hf_edcp_rsz, tvb, offset, 1, ENC_BIG_ENDIAN);
510 offset += 1;
512 if (plen & 0x4000) {
513 proto_tree_add_item (pft_tree, hf_edcp_source, tvb, offset, 2, ENC_BIG_ENDIAN);
514 offset += 2;
515 proto_tree_add_item (pft_tree, hf_edcp_dest, tvb, offset, 2, ENC_BIG_ENDIAN);
516 offset += 2;
518 if (tree) {
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);
526 offset += 2;
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);
534 else {
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;
539 } else {
540 next_tvb = tvb_new_subset_remaining (tvb, offset);
542 if(next_tvb) {
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.
556 static int
557 dissect_af (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_)
559 int offset = 0;
560 proto_item *ti;
561 proto_item *li = NULL;
562 proto_item *ci;
563 proto_tree *af_tree;
564 uint8_t ver, pt;
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);
574 offset += 2;
575 payload_len = tvb_get_ntohl(tvb, offset);
576 if (tree) {
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
589 offset += 4;
590 proto_tree_add_item (af_tree, hf_edcp_seq, tvb, offset, 2, ENC_BIG_ENDIAN);
591 offset += 2;
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);
597 offset += 1;
598 pt = tvb_get_uint8 (tvb, offset);
599 proto_tree_add_item (af_tree, hf_edcp_pt, tvb, offset, 1, ENC_ASCII);
600 offset += 1;
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);
610 /*offset += 2;*/
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.
626 static int
627 dissect_tpl(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_)
629 proto_tree *tpl_tree;
630 unsigned offset=0;
631 proto_item *ti;
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)) {
639 tvbuff_t *next_tvb;
640 uint32_t bits;
641 uint32_t bytes;
642 char *tag = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, 4, ENC_ASCII);
643 bits = tvb_get_ntohl(tvb, offset+4);
644 bytes = bits / 8;
645 if(bits % 8)
646 bytes++;
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);
655 offset += (8+bytes);
658 return tvb_captured_length(tvb);
661 void
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);
672 void
673 proto_register_dcp_etsi (void)
675 static hf_register_info hf_edcp[] = {
676 {&hf_edcp_sync,
677 {"sync", "dcp-etsi.sync",
678 FT_STRING, BASE_NONE, NULL, 0,
679 "AF or PF", HFILL}
682 static hf_register_info hf_af[] = {
683 {&hf_edcp_len,
684 {"length", "dcp-af.len",
685 FT_UINT32, BASE_DEC, NULL, 0,
686 "length in bytes of the payload", HFILL}
688 {&hf_edcp_seq,
689 {"frame count", "dcp-af.seq",
690 FT_UINT16, BASE_DEC, NULL, 0,
691 "Logical Frame Number", HFILL}
693 {&hf_edcp_crcflag,
694 {"crc flag", "dcp-af.crcflag",
695 FT_BOOLEAN, 8, NULL, 0x80,
696 "Frame is protected by CRC", HFILL}
698 {&hf_edcp_maj,
699 {"Major Revision", "dcp-af.maj",
700 FT_UINT8, BASE_DEC, NULL, 0x70,
701 "Major Protocol Revision", HFILL}
703 {&hf_edcp_min,
704 {"Minor Revision", "dcp-af.min",
705 FT_UINT8, BASE_DEC, NULL, 0x0f,
706 "Minor Protocol Revision", HFILL}
708 {&hf_edcp_pt,
709 {"Payload Type", "dcp-af.pt",
710 FT_STRING, BASE_NONE, NULL, 0,
711 "T means Tag Packets, all other values reserved", HFILL}
713 {&hf_edcp_crc,
714 {"CRC", "dcp-af.crc",
715 FT_UINT16, BASE_HEX, NULL, 0,
716 NULL, HFILL}
718 {&hf_edcp_crc_ok,
719 {"CRC OK", "dcp-af.crc_ok",
720 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
721 "AF CRC OK", HFILL}
725 static hf_register_info hf_pft[] = {
726 #if 0
727 {&hf_edcp_pft_pt,
728 {"Sub-protocol", "dcp-pft.pt",
729 FT_UINT8, BASE_DEC, NULL, 0,
730 "Always AF", HFILL}
732 #endif
733 {&hf_edcp_pseq,
734 {"Sequence No", "dcp-pft.seq",
735 FT_UINT16, BASE_DEC, NULL, 0,
736 "PFT Sequence No", HFILL}
738 {&hf_edcp_findex,
739 {"Fragment Index", "dcp-pft.findex",
740 FT_UINT24, BASE_DEC, NULL, 0,
741 "Index of the fragment within one AF Packet", HFILL}
743 {&hf_edcp_fcount,
744 {"Fragment Count", "dcp-pft.fcount",
745 FT_UINT24, BASE_DEC, NULL, 0,
746 "Number of fragments produced from this AF Packet", HFILL}
748 {&hf_edcp_fecflag,
749 {"FEC", "dcp-pft.fec",
750 FT_BOOLEAN, 16, NULL, 0x8000,
751 "When set the optional RS header is present", HFILL}
753 {&hf_edcp_addrflag,
754 {"Addr", "dcp-pft.addr",
755 FT_BOOLEAN, 16, NULL, 0x4000,
756 "When set the optional transport header is present", HFILL}
758 {&hf_edcp_plen,
759 {"fragment length", "dcp-pft.len",
760 FT_UINT16, BASE_DEC, NULL, 0x3fff,
761 "length in bytes of the payload of this fragment", HFILL}
763 {&hf_edcp_rsk,
764 {"RSk", "dcp-pft.rsk",
765 FT_UINT8, BASE_DEC, NULL, 0,
766 "The length of the Reed Solomon data word", HFILL}
768 {&hf_edcp_rsz,
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}
773 {&hf_edcp_source,
774 {"source addr", "dcp-pft.source",
775 FT_UINT16, BASE_DEC, NULL, 0,
776 "PFT source identifier", HFILL}
778 {&hf_edcp_dest,
779 {"dest addr", "dcp-pft.dest",
780 FT_UINT16, BASE_DEC, NULL, 0,
781 "PFT destination identifier", HFILL}
783 {&hf_edcp_hcrc,
784 {"header CRC", "dcp-pft.crc",
785 FT_UINT16, BASE_HEX, NULL, 0,
786 "PFT Header CRC", HFILL}
788 {&hf_edcp_hcrc_ok,
789 {"PFT CRC OK", "dcp-pft.crc_ok",
790 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
791 "PFT Header CRC OK", HFILL}
793 {&hf_edcp_fragments,
794 {"Message fragments", "dcp-pft.fragments",
795 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL}},
796 {&hf_edcp_fragment,
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}},
825 #if 0
826 {&hf_edcp_c_max,
827 {"C max", "dcp-pft.cmax",
828 FT_UINT16, BASE_DEC, NULL, 0,
829 "Maximum number of RS chunks sent", HFILL}
831 {&hf_edcp_rx_min,
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}
841 #endif
842 {&hf_edcp_rs_ok,
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[] = {
855 {&hf_tpl_tlv,
856 {"tag", "dcp-tpl.tlv",
857 FT_BYTES, BASE_NONE, NULL, 0,
858 "Tag Packet", HFILL}
860 #if 0
861 {&hf_tpl_ptr,
862 {"Type", "dcp-tpl.ptr",
863 FT_STRING, BASE_NONE, NULL, 0,
864 "Protocol Type & Revision", HFILL}
866 #endif
869 /* Setup protocol subtree array */
870 static int *ett[] = {
871 &ett_edcp,
872 &ett_af,
873 &ett_pft,
874 &ett_tpl,
875 &ett_edcp_fragment,
876 &ett_edcp_fragments
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
923 * Local variables:
924 * c-basic-offset: 2
925 * tab-width: 8
926 * indent-tabs-mode: nil
927 * End:
929 * vi: set shiftwidth=2 tabstop=8 expandtab:
930 * :indentSize=2:tabSize=8:noTabs=true: