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