/src/wireshark/epan/dissectors/packet-dcp-etsi.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-dcp-etsi.c |
2 | | * Routines for ETSI Distribution & Communication Protocol |
3 | | * Copyright 2006, British Broadcasting Corporation |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | * |
11 | | * Protocol info |
12 | | * Ref: ETSI DCP (ETSI TS 102 821) |
13 | | */ |
14 | | |
15 | | #include "config.h" |
16 | | |
17 | | |
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> |
24 | | |
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); |
30 | | |
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; |
35 | | |
36 | | static dissector_table_t dcp_dissector_table; |
37 | | static dissector_table_t af_dissector_table; |
38 | | static dissector_table_t tpl_dissector_table; |
39 | | |
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; |
71 | | |
72 | | static int hf_tpl_tlv; |
73 | | /* static int hf_tpl_ptr; */ |
74 | | |
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; |
85 | | |
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; |
93 | | |
94 | | static expert_field ei_edcp_reassembly; |
95 | | static expert_field ei_edcp_reassembly_info; |
96 | | |
97 | | static reassembly_table dcp_reassembly_table; |
98 | | |
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" |
120 | | }; |
121 | | |
122 | | |
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 |
129 | | */ |
130 | | static int |
131 | | dissect_dcp_etsi(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_) |
132 | 0 | { |
133 | 0 | uint8_t *sync; |
134 | 0 | proto_tree *dcp_tree; |
135 | 0 | proto_item *ti; |
136 | |
|
137 | 0 | if(tvb_captured_length(tvb) < 11) |
138 | 0 | return false; |
139 | | |
140 | | /* Clear out stuff in the info column */ |
141 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
142 | 0 | col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCP (ETSI)"); |
143 | | /*col_append_fstr (pinfo->cinfo, COL_INFO, " tvb %d", tvb_length(tvb));*/ |
144 | |
|
145 | 0 | ti = proto_tree_add_item (tree, proto_dcp_etsi, tvb, 0, -1, ENC_NA); |
146 | 0 | dcp_tree = proto_item_add_subtree (ti, ett_edcp); |
147 | |
|
148 | 0 | sync = tvb_get_string_enc(pinfo->pool, tvb, 0, 2, ENC_ASCII); |
149 | 0 | dissector_try_string_with_data(dcp_dissector_table, (char*)sync, tvb, pinfo, dcp_tree, true, NULL); |
150 | |
|
151 | 0 | return tvb_captured_length(tvb); |
152 | 0 | } |
153 | | |
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 |
159 | | */ |
160 | | static bool |
161 | | dissect_dcp_etsi_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data) |
162 | 1.43k | { |
163 | | /* 6.1 AF packet structure |
164 | | * |
165 | | * AF Header |
166 | | * SYNC LEN SEQ AR PT |
167 | | * 2 bytes 4 bytes 2 bytes 1 byte 1 byte |
168 | | * |
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". |
178 | | * |
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 |
184 | | * |
185 | | * Psync: the ASCII string "PF" is used as the synchronization word for the PFT Layer |
186 | | * |
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. |
189 | | */ |
190 | 1.43k | uint16_t word; |
191 | | |
192 | 1.43k | if(tvb_captured_length(tvb) < 11) |
193 | 460 | return false; |
194 | | |
195 | 974 | word = tvb_get_ntohs(tvb,0); |
196 | | /* Check for 'AF or 'PF' */ |
197 | 974 | if (word == 0x4146) { |
198 | | /* AF - check the version, which is only major 1, minor 0 */ |
199 | 2 | if ((tvb_get_uint8(tvb, 8) & 0x7F) != 0x10) { |
200 | 1 | return false; |
201 | 1 | } |
202 | | /* Tag packets are the only payload type */ |
203 | 1 | if (tvb_get_uint8(tvb, 9) != 'T') { |
204 | 1 | return false; |
205 | 1 | } |
206 | 972 | } else if (word == 0x5046) { |
207 | | /* PFT - header length 14, 16, 18, or 20 depending on options. |
208 | | * Always contains CRC. */ |
209 | 5 | if (tvb_captured_length(tvb) < 14) { |
210 | 1 | return false; |
211 | 1 | } |
212 | 4 | uint16_t plen = tvb_get_ntohs(tvb, 10); |
213 | 4 | unsigned header_len = 14; |
214 | 4 | if (plen & 0x8000) { |
215 | 2 | header_len += 2; |
216 | 2 | } |
217 | 4 | if (plen & 0x4000) { |
218 | 3 | header_len += 4; |
219 | 3 | } |
220 | 4 | if (tvb_captured_length(tvb) < header_len) { |
221 | 2 | return false; |
222 | 2 | } |
223 | 2 | if (crc16_x25_ccitt_tvb(tvb, header_len) != 0x1D0F) { |
224 | 2 | return false; |
225 | 2 | } |
226 | 967 | } else { |
227 | 967 | return false; |
228 | 967 | } |
229 | | |
230 | 0 | dissect_dcp_etsi(tvb, pinfo, tree, data); |
231 | |
|
232 | 0 | return true; |
233 | 974 | } |
234 | | |
235 | 0 | #define PFT_RS_N_MAX 207 |
236 | 0 | #define PFT_RS_K 255 |
237 | 0 | #define PFT_RS_P (PFT_RS_K - PFT_RS_N_MAX) |
238 | | |
239 | | |
240 | | static |
241 | | void rs_deinterleave(const uint8_t *input, uint8_t *output, uint16_t plen, uint32_t fcount) |
242 | 0 | { |
243 | 0 | unsigned fidx; |
244 | 0 | for(fidx=0; fidx<fcount; fidx++) |
245 | 0 | { |
246 | 0 | int r; |
247 | 0 | for (r=0; r<plen; r++) |
248 | 0 | { |
249 | 0 | output[fidx+r*fcount] = input[fidx*plen+r]; |
250 | 0 | } |
251 | 0 | } |
252 | 0 | } |
253 | | |
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_) |
257 | 0 | { |
258 | 0 | uint32_t i, index_coded = 0, index_out = 0; |
259 | 0 | int err_corr; |
260 | 0 | for (i=0; i<c_max; i++) |
261 | 0 | { |
262 | 0 | memcpy(output+index_out, deinterleaved+index_coded, rsk); |
263 | 0 | index_coded += rsk; |
264 | 0 | memcpy(output+index_out+PFT_RS_N_MAX, deinterleaved+index_coded, PFT_RS_P); |
265 | 0 | index_coded += PFT_RS_P; |
266 | 0 | err_corr = eras_dec_rs(output+index_out, NULL, 0); |
267 | 0 | if (err_corr<0) { |
268 | 0 | return false; |
269 | 0 | } |
270 | 0 | index_out += rsk; |
271 | 0 | } |
272 | 0 | return true; |
273 | 0 | } |
274 | | |
275 | | /* Don't attempt reassembly if we have a huge number of fragments. */ |
276 | 0 | #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 | 0 | #define MAX_FRAG_GAP 1000 |
280 | | |
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 |
292 | | ) |
293 | 0 | { |
294 | 0 | uint32_t decoded_size; |
295 | 0 | uint32_t c_max; |
296 | 0 | uint32_t rx_min; |
297 | 0 | tvbuff_t *new_tvb=NULL; |
298 | |
|
299 | 0 | if (fcount > MAX_FRAGMENTS) { |
300 | 0 | proto_tree_add_expert_format(tree, pinfo, &ei_edcp_reassembly, tvb , 0, -1, "[Reassembly of %d fragments not attempted]", fcount); |
301 | 0 | return NULL; |
302 | 0 | } |
303 | | |
304 | 0 | decoded_size = fcount*plen; |
305 | 0 | c_max = fcount*plen/(rsk+PFT_RS_P); /* rounded down */ |
306 | 0 | rx_min = fcount - (c_max*PFT_RS_P/plen); |
307 | 0 | if (fdx) |
308 | 0 | new_tvb = process_reassembled_data (tvb, offset, pinfo, |
309 | 0 | "Reassembled DCP (ETSI)", |
310 | 0 | fdx, &dcp_frag_items, |
311 | 0 | NULL, tree); |
312 | 0 | else { |
313 | 0 | unsigned fragments=0; |
314 | 0 | uint32_t *got; |
315 | 0 | fragment_item *fd; |
316 | 0 | fragment_head *fd_head; |
317 | |
|
318 | 0 | proto_tree_add_expert_format(tree, pinfo, &ei_edcp_reassembly_info, tvb, 0, -1, "want %d, got %d need %d", |
319 | 0 | fcount, fragments, rx_min); |
320 | 0 | got = (uint32_t *)wmem_alloc(pinfo->pool, fcount*sizeof(uint32_t)); |
321 | | |
322 | | /* make a list of the findex (offset) numbers of the fragments we have */ |
323 | 0 | fd_head = fragment_get(&dcp_reassembly_table, pinfo, seq, NULL); |
324 | 0 | if (fd_head) { |
325 | 0 | for (fd = fd_head->next; fd != NULL && fragments < fcount; fd = fd->next) { |
326 | 0 | if(fd->tvb_data) { |
327 | 0 | got[fragments++] = fd->offset; /* this is the findex of the fragment */ |
328 | 0 | } |
329 | 0 | } |
330 | 0 | } |
331 | | /* have we got enough for Reed Solomon to try to correct ? */ |
332 | 0 | if(fragments>=rx_min) { /* yes, in theory */ |
333 | 0 | unsigned i,current_findex; |
334 | 0 | fragment_head *frag=NULL; |
335 | 0 | uint8_t *dummy_data = (uint8_t*) wmem_alloc0 (pinfo->pool, plen); |
336 | 0 | tvbuff_t *dummytvb = tvb_new_real_data(dummy_data, plen, plen); |
337 | | /* try and decode with missing fragments */ |
338 | 0 | proto_tree_add_expert_format(tree, pinfo, &ei_edcp_reassembly_info, tvb, 0, -1, "want %d, got %d need %d", |
339 | 0 | fcount, fragments, rx_min); |
340 | | /* fill the fragment table with empty fragments */ |
341 | 0 | current_findex = 0; |
342 | 0 | for(i=0; i<fragments; i++) { |
343 | 0 | unsigned next_fragment_we_have = got[i]; |
344 | 0 | if (next_fragment_we_have > MAX_FRAGMENTS) { |
345 | 0 | proto_tree_add_expert_format(tree, pinfo, &ei_edcp_reassembly, tvb , 0, -1, "[Reassembly of %d fragments not attempted]", next_fragment_we_have); |
346 | 0 | return NULL; |
347 | 0 | } |
348 | 0 | if (next_fragment_we_have-current_findex > MAX_FRAG_GAP) { |
349 | 0 | proto_tree_add_expert_format(tree, pinfo, &ei_edcp_reassembly, tvb, 0, -1, |
350 | 0 | "[Missing %d consecutive packets. Don't attempt reassembly]", |
351 | 0 | next_fragment_we_have-current_findex); |
352 | 0 | return NULL; |
353 | 0 | } |
354 | 0 | for(; current_findex<next_fragment_we_have; current_findex++) { |
355 | 0 | frag = fragment_add_seq_check (&dcp_reassembly_table, |
356 | 0 | dummytvb, 0, pinfo, seq, NULL, |
357 | 0 | current_findex, plen, (current_findex+1!=fcount)); |
358 | 0 | } |
359 | 0 | current_findex++; /* skip over the fragment we have */ |
360 | 0 | } |
361 | 0 | tvb_free(dummytvb); |
362 | |
|
363 | 0 | if(frag) |
364 | 0 | new_tvb = process_reassembled_data (tvb, offset, pinfo, |
365 | 0 | "Reassembled DCP (ETSI)", |
366 | 0 | frag, &dcp_frag_items, |
367 | 0 | NULL, tree); |
368 | 0 | } |
369 | 0 | } |
370 | 0 | if(new_tvb && tvb_captured_length(new_tvb) > 0) { |
371 | 0 | bool decoded; |
372 | 0 | tvbuff_t *dtvb = NULL; |
373 | 0 | const uint8_t *input = tvb_get_ptr(new_tvb, 0, -1); |
374 | 0 | uint32_t reassembled_size = tvb_captured_length(new_tvb); |
375 | 0 | uint8_t *deinterleaved = (uint8_t*) wmem_alloc(pinfo->pool, reassembled_size); |
376 | 0 | uint8_t *output = (uint8_t*) wmem_alloc(pinfo->pool, decoded_size); |
377 | 0 | rs_deinterleave(input, deinterleaved, plen, fcount); |
378 | |
|
379 | 0 | dtvb = tvb_new_child_real_data(tvb, deinterleaved, reassembled_size, reassembled_size); |
380 | 0 | add_new_data_source(pinfo, dtvb, "Deinterleaved"); |
381 | |
|
382 | 0 | decoded = rs_correct_data(deinterleaved, output, c_max, rsk, rsz); |
383 | 0 | proto_tree_add_boolean (tree, hf_edcp_rs_ok, tvb, offset, 2, decoded); |
384 | |
|
385 | 0 | new_tvb = tvb_new_child_real_data(dtvb, output, decoded_size, decoded_size); |
386 | 0 | add_new_data_source(pinfo, new_tvb, "RS Error Corrected Data"); |
387 | 0 | } |
388 | 0 | return new_tvb; |
389 | 0 | } |
390 | | |
391 | | |
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 |
407 | | */ |
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 |
418 | | ) |
419 | 0 | { |
420 | 0 | bool first, last; |
421 | 0 | tvbuff_t *new_tvb=NULL; |
422 | 0 | fragment_head *frag_edcp = NULL; |
423 | 0 | pinfo->fragmented = true; |
424 | 0 | first = findex == 0; |
425 | 0 | last = fcount == (findex+1); |
426 | 0 | frag_edcp = fragment_add_seq_check ( |
427 | 0 | &dcp_reassembly_table, |
428 | 0 | tvb, offset, |
429 | 0 | pinfo, seq, NULL, |
430 | 0 | findex, |
431 | 0 | plen, |
432 | 0 | !last); |
433 | 0 | if(fec) { |
434 | 0 | new_tvb = dissect_pft_fec_detailed( |
435 | 0 | tvb, pinfo, tree, findex, fcount, seq, offset, plen, fec, rsk, rsz, frag_edcp |
436 | 0 | ); |
437 | 0 | } else { |
438 | 0 | new_tvb = process_reassembled_data (tvb, offset, pinfo, |
439 | 0 | "Reassembled DCP (ETSI)", |
440 | 0 | frag_edcp, &dcp_frag_items, |
441 | 0 | NULL, tree); |
442 | 0 | } |
443 | 0 | if(new_tvb) { |
444 | 0 | col_append_str (pinfo->cinfo, COL_INFO, " (Message Reassembled)"); |
445 | 0 | } else { |
446 | 0 | if(last) { |
447 | 0 | col_append_str (pinfo->cinfo, COL_INFO, " (Message Reassembly failure)"); |
448 | 0 | } else { |
449 | 0 | col_append_fstr (pinfo->cinfo, COL_INFO, " (Message fragment %u)", findex); |
450 | 0 | } |
451 | 0 | } |
452 | 0 | if(first) |
453 | 0 | col_append_str (pinfo->cinfo, COL_INFO, " (first)"); |
454 | 0 | if(last) |
455 | 0 | col_append_str (pinfo->cinfo, COL_INFO, " (last)"); |
456 | 0 | return new_tvb; |
457 | 0 | } |
458 | | |
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. |
464 | | */ |
465 | | static int |
466 | | dissect_pft(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data) |
467 | 0 | { |
468 | 0 | uint16_t plen; |
469 | 0 | int offset = 0; |
470 | 0 | uint16_t seq, payload_len; |
471 | 0 | uint32_t findex, fcount; |
472 | 0 | proto_tree *pft_tree; |
473 | 0 | proto_item *ti, *li; |
474 | 0 | tvbuff_t *next_tvb = NULL; |
475 | 0 | bool fec = false; |
476 | 0 | uint16_t rsk=0, rsz=0; |
477 | |
|
478 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCP-PFT"); |
479 | |
|
480 | 0 | ti = proto_tree_add_item (tree, proto_pft, tvb, 0, -1, ENC_NA); |
481 | 0 | pft_tree = proto_item_add_subtree (ti, ett_pft); |
482 | 0 | proto_tree_add_item (pft_tree, hf_edcp_sync, tvb, offset, 2, ENC_ASCII); |
483 | |
|
484 | 0 | offset += 2; |
485 | 0 | seq = tvb_get_ntohs (tvb, offset); |
486 | 0 | proto_tree_add_item (pft_tree, hf_edcp_pseq, tvb, offset, 2, ENC_BIG_ENDIAN); |
487 | |
|
488 | 0 | offset += 2; |
489 | 0 | findex = tvb_get_ntoh24 (tvb, offset); |
490 | 0 | proto_tree_add_item (pft_tree, hf_edcp_findex, tvb, offset, 3, ENC_BIG_ENDIAN); |
491 | |
|
492 | 0 | offset += 3; |
493 | 0 | fcount = tvb_get_ntoh24 (tvb, offset); |
494 | 0 | proto_tree_add_item (pft_tree, hf_edcp_fcount, tvb, offset, 3, ENC_BIG_ENDIAN); |
495 | |
|
496 | 0 | offset += 3; |
497 | 0 | plen = tvb_get_ntohs (tvb, offset); |
498 | 0 | payload_len = plen & 0x3fff; |
499 | 0 | proto_tree_add_item (pft_tree, hf_edcp_fecflag, tvb, offset, 2, ENC_BIG_ENDIAN); |
500 | 0 | proto_tree_add_item (pft_tree, hf_edcp_addrflag, tvb, offset, 2, ENC_BIG_ENDIAN); |
501 | 0 | li = proto_tree_add_item (pft_tree, hf_edcp_plen, tvb, offset, 2, ENC_BIG_ENDIAN); |
502 | |
|
503 | 0 | offset += 2; |
504 | 0 | if (plen & 0x8000) { |
505 | 0 | fec = true; |
506 | 0 | rsk = tvb_get_uint8 (tvb, offset); |
507 | 0 | proto_tree_add_item (pft_tree, hf_edcp_rsk, tvb, offset, 1, ENC_BIG_ENDIAN); |
508 | 0 | offset += 1; |
509 | 0 | rsz = tvb_get_uint8 (tvb, offset); |
510 | 0 | proto_tree_add_item (pft_tree, hf_edcp_rsz, tvb, offset, 1, ENC_BIG_ENDIAN); |
511 | 0 | offset += 1; |
512 | 0 | } |
513 | 0 | if (plen & 0x4000) { |
514 | 0 | proto_tree_add_item (pft_tree, hf_edcp_source, tvb, offset, 2, ENC_BIG_ENDIAN); |
515 | 0 | offset += 2; |
516 | 0 | proto_tree_add_item (pft_tree, hf_edcp_dest, tvb, offset, 2, ENC_BIG_ENDIAN); |
517 | 0 | offset += 2; |
518 | 0 | } |
519 | 0 | if (tree) { |
520 | 0 | proto_item *ci = NULL; |
521 | 0 | unsigned header_len = offset+2; |
522 | 0 | uint16_t c = crc16_x25_ccitt_tvb(tvb, header_len); |
523 | 0 | ci = proto_tree_add_item (pft_tree, hf_edcp_hcrc, tvb, offset, 2, ENC_BIG_ENDIAN); |
524 | 0 | proto_item_append_text(ci, " (%s)", (c==0x1D0F)?"Ok":"bad"); |
525 | 0 | proto_tree_add_boolean(pft_tree, hf_edcp_hcrc_ok, tvb, offset, 2, c==0x1D0F); |
526 | 0 | } |
527 | 0 | offset += 2; |
528 | 0 | if (fcount > 1) { /* fragmented*/ |
529 | 0 | bool save_fragmented = pinfo->fragmented; |
530 | 0 | uint16_t real_len = tvb_captured_length(tvb)-offset; |
531 | 0 | proto_tree_add_item (pft_tree, hf_edcp_pft_payload, tvb, offset, real_len, ENC_NA); |
532 | 0 | if(real_len != payload_len || real_len == 0) { |
533 | 0 | proto_item_append_text(li, " (length error (%d))", real_len); |
534 | 0 | } |
535 | 0 | else { |
536 | 0 | next_tvb = dissect_pft_fragmented(tvb, pinfo, pft_tree, findex, fcount, |
537 | 0 | seq, offset, real_len, fec, rsk, rsz); |
538 | 0 | } |
539 | 0 | pinfo->fragmented = save_fragmented; |
540 | 0 | } else { |
541 | 0 | next_tvb = tvb_new_subset_remaining (tvb, offset); |
542 | 0 | } |
543 | 0 | if(next_tvb) { |
544 | 0 | dissect_af(next_tvb, pinfo, tree, data); |
545 | 0 | } |
546 | 0 | return tvb_captured_length(tvb); |
547 | 0 | } |
548 | | |
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. |
556 | | */ |
557 | | static int |
558 | | dissect_af (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_) |
559 | 0 | { |
560 | 0 | int offset = 0; |
561 | 0 | proto_item *ti; |
562 | 0 | proto_item *li = NULL; |
563 | 0 | proto_item *ci; |
564 | 0 | proto_tree *af_tree; |
565 | 0 | uint8_t ver, pt; |
566 | 0 | uint32_t payload_len; |
567 | 0 | tvbuff_t *next_tvb = NULL; |
568 | |
|
569 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCP-AF"); |
570 | |
|
571 | 0 | ti = proto_tree_add_item (tree, proto_af, tvb, 0, -1, ENC_NA); |
572 | 0 | af_tree = proto_item_add_subtree (ti, ett_af); |
573 | 0 | proto_tree_add_item (af_tree, hf_edcp_sync, tvb, offset, 2, ENC_ASCII); |
574 | |
|
575 | 0 | offset += 2; |
576 | 0 | payload_len = tvb_get_ntohl(tvb, offset); |
577 | 0 | if (tree) { |
578 | 0 | uint32_t real_payload_len = tvb_captured_length(tvb)-12; |
579 | 0 | li = proto_tree_add_item (af_tree, hf_edcp_len, tvb, offset, 4, ENC_BIG_ENDIAN); |
580 | 0 | if(real_payload_len < payload_len) { |
581 | 0 | proto_item_append_text (li, " (wrong len claims %d is %d)", |
582 | 0 | payload_len, real_payload_len |
583 | 0 | ); |
584 | 0 | } else if(real_payload_len > payload_len) { |
585 | 0 | proto_item_append_text (li, " (%d bytes in packet after end of AF frame)", |
586 | 0 | real_payload_len-payload_len |
587 | 0 | ); |
588 | 0 | } |
589 | 0 | } |
590 | 0 | offset += 4; |
591 | 0 | proto_tree_add_item (af_tree, hf_edcp_seq, tvb, offset, 2, ENC_BIG_ENDIAN); |
592 | 0 | offset += 2; |
593 | 0 | ver = tvb_get_uint8 (tvb, offset); |
594 | 0 | proto_tree_add_item (af_tree, hf_edcp_crcflag, tvb, offset, 1, ENC_BIG_ENDIAN); |
595 | 0 | proto_tree_add_item (af_tree, hf_edcp_maj, tvb, offset, 1, ENC_BIG_ENDIAN); |
596 | 0 | proto_tree_add_item (af_tree, hf_edcp_min, tvb, offset, 1, ENC_BIG_ENDIAN); |
597 | |
|
598 | 0 | offset += 1; |
599 | 0 | pt = tvb_get_uint8 (tvb, offset); |
600 | 0 | proto_tree_add_item (af_tree, hf_edcp_pt, tvb, offset, 1, ENC_ASCII); |
601 | 0 | offset += 1; |
602 | 0 | next_tvb = tvb_new_subset_length(tvb, offset, payload_len); |
603 | 0 | offset += payload_len; |
604 | 0 | ci = proto_tree_add_item (af_tree, hf_edcp_crc, tvb, offset, 2, ENC_BIG_ENDIAN); |
605 | 0 | if (ver & 0x80) { /* crc valid */ |
606 | 0 | unsigned len = offset+2; |
607 | 0 | uint16_t c = crc16_x25_ccitt_tvb(tvb, len); |
608 | 0 | proto_item_append_text(ci, " (%s)", (c==0x1D0F)?"Ok":"bad"); |
609 | 0 | proto_tree_add_boolean(af_tree, hf_edcp_crc_ok, tvb, offset, 2, c==0x1D0F); |
610 | 0 | } |
611 | | /*offset += 2;*/ |
612 | |
|
613 | 0 | dissector_try_uint(af_dissector_table, pt, next_tvb, pinfo, tree); |
614 | 0 | return tvb_captured_length(tvb); |
615 | 0 | } |
616 | | |
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. |
626 | | */ |
627 | | static int |
628 | | dissect_tpl(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_) |
629 | 0 | { |
630 | 0 | proto_tree *tpl_tree; |
631 | 0 | unsigned offset=0; |
632 | 0 | proto_item *ti; |
633 | |
|
634 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCP-TPL"); |
635 | |
|
636 | 0 | ti = proto_tree_add_item (tree, proto_tpl, tvb, 0, -1, ENC_NA); |
637 | 0 | tpl_tree = proto_item_add_subtree (ti, ett_tpl); |
638 | |
|
639 | 0 | while(offset<tvb_reported_length(tvb)) { |
640 | 0 | tvbuff_t *next_tvb; |
641 | 0 | uint32_t bits; |
642 | 0 | uint32_t bytes; |
643 | 0 | char *tag = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, 4, ENC_ASCII); |
644 | 0 | bits = tvb_get_ntohl(tvb, offset+4); |
645 | 0 | bytes = bits / 8; |
646 | 0 | if(bits % 8) |
647 | 0 | bytes++; |
648 | |
|
649 | 0 | proto_tree_add_bytes_format(tpl_tree, hf_tpl_tlv, tvb, |
650 | 0 | offset, 8+bytes, NULL, |
651 | 0 | "%s (%u bits)", tag, bits); |
652 | |
|
653 | 0 | next_tvb = tvb_new_subset_length(tvb, offset+8, bytes); |
654 | 0 | dissector_try_string_with_data(tpl_dissector_table, tag, next_tvb, pinfo, tree, true, NULL); |
655 | |
|
656 | 0 | offset += (8+bytes); |
657 | 0 | } |
658 | |
|
659 | 0 | return tvb_captured_length(tvb); |
660 | 0 | } |
661 | | |
662 | | void |
663 | | proto_reg_handoff_dcp_etsi (void) |
664 | 14 | { |
665 | 14 | heur_dissector_add("udp", dissect_dcp_etsi_heur, "DCP (ETSI) over UDP", "dcp_etsi_udp", proto_dcp_etsi, HEURISTIC_ENABLE); |
666 | 14 | dissector_add_for_decode_as("udp.port", dcp_etsi_handle); |
667 | 14 | dissector_add_string("dcp-etsi.sync", "AF", af_handle); |
668 | 14 | dissector_add_string("dcp-etsi.sync", "PF", pft_handle); |
669 | | /* if there are ever other payload types ...*/ |
670 | 14 | dissector_add_uint("dcp-af.pt", 'T', tpl_handle); |
671 | 14 | } |
672 | | |
673 | | void |
674 | | proto_register_dcp_etsi (void) |
675 | 14 | { |
676 | 14 | static hf_register_info hf_edcp[] = { |
677 | 14 | {&hf_edcp_sync, |
678 | 14 | {"sync", "dcp-etsi.sync", |
679 | 14 | FT_STRING, BASE_NONE, NULL, 0, |
680 | 14 | "AF or PF", HFILL} |
681 | 14 | } |
682 | 14 | }; |
683 | 14 | static hf_register_info hf_af[] = { |
684 | 14 | {&hf_edcp_len, |
685 | 14 | {"length", "dcp-af.len", |
686 | 14 | FT_UINT32, BASE_DEC, NULL, 0, |
687 | 14 | "length in bytes of the payload", HFILL} |
688 | 14 | }, |
689 | 14 | {&hf_edcp_seq, |
690 | 14 | {"frame count", "dcp-af.seq", |
691 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
692 | 14 | "Logical Frame Number", HFILL} |
693 | 14 | }, |
694 | 14 | {&hf_edcp_crcflag, |
695 | 14 | {"crc flag", "dcp-af.crcflag", |
696 | 14 | FT_BOOLEAN, 8, NULL, 0x80, |
697 | 14 | "Frame is protected by CRC", HFILL} |
698 | 14 | }, |
699 | 14 | {&hf_edcp_maj, |
700 | 14 | {"Major Revision", "dcp-af.maj", |
701 | 14 | FT_UINT8, BASE_DEC, NULL, 0x70, |
702 | 14 | "Major Protocol Revision", HFILL} |
703 | 14 | }, |
704 | 14 | {&hf_edcp_min, |
705 | 14 | {"Minor Revision", "dcp-af.min", |
706 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0f, |
707 | 14 | "Minor Protocol Revision", HFILL} |
708 | 14 | }, |
709 | 14 | {&hf_edcp_pt, |
710 | 14 | {"Payload Type", "dcp-af.pt", |
711 | 14 | FT_STRING, BASE_NONE, NULL, 0, |
712 | 14 | "T means Tag Packets, all other values reserved", HFILL} |
713 | 14 | }, |
714 | 14 | {&hf_edcp_crc, |
715 | 14 | {"CRC", "dcp-af.crc", |
716 | 14 | FT_UINT16, BASE_HEX, NULL, 0, |
717 | 14 | NULL, HFILL} |
718 | 14 | }, |
719 | 14 | {&hf_edcp_crc_ok, |
720 | 14 | {"CRC OK", "dcp-af.crc_ok", |
721 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
722 | 14 | "AF CRC OK", HFILL} |
723 | 14 | } |
724 | 14 | }; |
725 | | |
726 | 14 | 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} |
732 | | }, |
733 | | #endif |
734 | 14 | {&hf_edcp_pseq, |
735 | 14 | {"Sequence No", "dcp-pft.seq", |
736 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
737 | 14 | "PFT Sequence No", HFILL} |
738 | 14 | }, |
739 | 14 | {&hf_edcp_findex, |
740 | 14 | {"Fragment Index", "dcp-pft.findex", |
741 | 14 | FT_UINT24, BASE_DEC, NULL, 0, |
742 | 14 | "Index of the fragment within one AF Packet", HFILL} |
743 | 14 | }, |
744 | 14 | {&hf_edcp_fcount, |
745 | 14 | {"Fragment Count", "dcp-pft.fcount", |
746 | 14 | FT_UINT24, BASE_DEC, NULL, 0, |
747 | 14 | "Number of fragments produced from this AF Packet", HFILL} |
748 | 14 | }, |
749 | 14 | {&hf_edcp_fecflag, |
750 | 14 | {"FEC", "dcp-pft.fec", |
751 | 14 | FT_BOOLEAN, 16, NULL, 0x8000, |
752 | 14 | "When set the optional RS header is present", HFILL} |
753 | 14 | }, |
754 | 14 | {&hf_edcp_addrflag, |
755 | 14 | {"Addr", "dcp-pft.addr", |
756 | 14 | FT_BOOLEAN, 16, NULL, 0x4000, |
757 | 14 | "When set the optional transport header is present", HFILL} |
758 | 14 | }, |
759 | 14 | {&hf_edcp_plen, |
760 | 14 | {"fragment length", "dcp-pft.len", |
761 | 14 | FT_UINT16, BASE_DEC, NULL, 0x3fff, |
762 | 14 | "length in bytes of the payload of this fragment", HFILL} |
763 | 14 | }, |
764 | 14 | {&hf_edcp_rsk, |
765 | 14 | {"RSk", "dcp-pft.rsk", |
766 | 14 | FT_UINT8, BASE_DEC, NULL, 0, |
767 | 14 | "The length of the Reed Solomon data word", HFILL} |
768 | 14 | }, |
769 | 14 | {&hf_edcp_rsz, |
770 | 14 | {"RSz", "dcp-pft.rsz", |
771 | 14 | FT_UINT8, BASE_DEC, NULL, 0, |
772 | 14 | "The number of padding bytes in the last Reed Solomon block", HFILL} |
773 | 14 | }, |
774 | 14 | {&hf_edcp_source, |
775 | 14 | {"source addr", "dcp-pft.source", |
776 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
777 | 14 | "PFT source identifier", HFILL} |
778 | 14 | }, |
779 | 14 | {&hf_edcp_dest, |
780 | 14 | {"dest addr", "dcp-pft.dest", |
781 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
782 | 14 | "PFT destination identifier", HFILL} |
783 | 14 | }, |
784 | 14 | {&hf_edcp_hcrc, |
785 | 14 | {"header CRC", "dcp-pft.crc", |
786 | 14 | FT_UINT16, BASE_HEX, NULL, 0, |
787 | 14 | "PFT Header CRC", HFILL} |
788 | 14 | }, |
789 | 14 | {&hf_edcp_hcrc_ok, |
790 | 14 | {"PFT CRC OK", "dcp-pft.crc_ok", |
791 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
792 | 14 | "PFT Header CRC OK", HFILL} |
793 | 14 | }, |
794 | 14 | {&hf_edcp_fragments, |
795 | 14 | {"Message fragments", "dcp-pft.fragments", |
796 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL}}, |
797 | 14 | {&hf_edcp_fragment, |
798 | 14 | {"Message fragment", "dcp-pft.fragment", |
799 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL}}, |
800 | 14 | {&hf_edcp_fragment_overlap, |
801 | 14 | {"Message fragment overlap", "dcp-pft.fragment.overlap", |
802 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
803 | 14 | {&hf_edcp_fragment_overlap_conflicts, |
804 | 14 | {"Message fragment overlapping with conflicting data", |
805 | 14 | "dcp-pft.fragment.overlap.conflicts", |
806 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
807 | 14 | {&hf_edcp_fragment_multiple_tails, |
808 | 14 | {"Message has multiple tail fragments", |
809 | 14 | "dcp-pft.fragment.multiple_tails", |
810 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
811 | 14 | {&hf_edcp_fragment_too_long_fragment, |
812 | 14 | {"Message fragment too long", "dcp-pft.fragment.too_long_fragment", |
813 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
814 | 14 | {&hf_edcp_fragment_error, |
815 | 14 | {"Message defragmentation error", "dcp-pft.fragment.error", |
816 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL}}, |
817 | 14 | {&hf_edcp_fragment_count, |
818 | 14 | {"Message fragment count", "dcp-pft.fragment.count", |
819 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL}}, |
820 | 14 | {&hf_edcp_reassembled_in, |
821 | 14 | {"Reassembled in", "dcp-pft.reassembled.in", |
822 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL}}, |
823 | 14 | {&hf_edcp_reassembled_length, |
824 | 14 | {"Reassembled DCP (ETSI) length", "dcp-pft.reassembled.length", |
825 | 14 | 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} |
831 | | }, |
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} |
836 | | }, |
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} |
841 | | }, |
842 | | #endif |
843 | 14 | {&hf_edcp_rs_ok, |
844 | 14 | {"RS decode OK", "dcp-pft.rs_ok", |
845 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
846 | 14 | "successfully decoded RS blocks", HFILL} |
847 | 14 | }, |
848 | 14 | {&hf_edcp_pft_payload, |
849 | 14 | {"payload", "dcp-pft.payload", |
850 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
851 | 14 | "PFT Payload", HFILL} |
852 | 14 | } |
853 | 14 | }; |
854 | | |
855 | 14 | static hf_register_info hf_tpl[] = { |
856 | 14 | {&hf_tpl_tlv, |
857 | 14 | {"tag", "dcp-tpl.tlv", |
858 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
859 | 14 | "Tag Packet", HFILL} |
860 | 14 | }, |
861 | | #if 0 |
862 | | {&hf_tpl_ptr, |
863 | | {"Type", "dcp-tpl.ptr", |
864 | | FT_STRING, BASE_NONE, NULL, 0, |
865 | | "Protocol Type & Revision", HFILL} |
866 | | } |
867 | | #endif |
868 | 14 | }; |
869 | | |
870 | | /* Setup protocol subtree array */ |
871 | 14 | static int *ett[] = { |
872 | 14 | &ett_edcp, |
873 | 14 | &ett_af, |
874 | 14 | &ett_pft, |
875 | 14 | &ett_tpl, |
876 | 14 | &ett_edcp_fragment, |
877 | 14 | &ett_edcp_fragments |
878 | 14 | }; |
879 | | |
880 | 14 | static ei_register_info ei[] = { |
881 | 14 | { &ei_edcp_reassembly, { "dcp-etsi.reassembly_failed", PI_REASSEMBLE, PI_ERROR, "Reassembly failed", EXPFILL }}, |
882 | 14 | { &ei_edcp_reassembly_info, { "dcp-etsi.reassembly_info", PI_REASSEMBLE, PI_CHAT, "Reassembly information", EXPFILL }}, |
883 | 14 | }; |
884 | | |
885 | 14 | expert_module_t* expert_dcp_etsi; |
886 | | |
887 | 14 | proto_dcp_etsi = proto_register_protocol ("ETSI Distribution & Communication Protocol (for DRM)", /* name */ |
888 | 14 | "DCP (ETSI)", /* short name */ |
889 | 14 | "dcp-etsi" /* abbrev */ |
890 | 14 | ); |
891 | 14 | proto_af = proto_register_protocol ("DCP Application Framing Layer", "DCP-AF", "dcp-af"); |
892 | 14 | proto_pft = proto_register_protocol ("DCP Protection, Fragmentation & Transport Layer", "DCP-PFT", "dcp-pft"); |
893 | 14 | proto_tpl = proto_register_protocol ("DCP Tag Packet Layer", "DCP-TPL", "dcp-tpl"); |
894 | | |
895 | 14 | proto_register_field_array (proto_dcp_etsi, hf_edcp, array_length (hf_edcp)); |
896 | 14 | proto_register_field_array (proto_af, hf_af, array_length (hf_af)); |
897 | 14 | proto_register_field_array (proto_pft, hf_pft, array_length (hf_pft)); |
898 | 14 | proto_register_field_array (proto_tpl, hf_tpl, array_length (hf_tpl)); |
899 | 14 | proto_register_subtree_array (ett, array_length (ett)); |
900 | 14 | expert_dcp_etsi = expert_register_protocol(proto_dcp_etsi); |
901 | 14 | expert_register_field_array(expert_dcp_etsi, ei, array_length(ei)); |
902 | | |
903 | | /* subdissector code */ |
904 | 14 | dcp_dissector_table = register_dissector_table("dcp-etsi.sync", |
905 | 14 | "DCP Sync", proto_dcp_etsi, FT_STRING, STRING_CASE_SENSITIVE); |
906 | 14 | af_dissector_table = register_dissector_table("dcp-af.pt", |
907 | 14 | "DCP-AF Payload Type", proto_dcp_etsi, FT_UINT8, BASE_DEC); |
908 | | |
909 | 14 | tpl_dissector_table = register_dissector_table("dcp-tpl.ptr", |
910 | 14 | "DCP-TPL Protocol Type & Revision", proto_dcp_etsi, FT_STRING, STRING_CASE_SENSITIVE); |
911 | | |
912 | 14 | reassembly_table_register (&dcp_reassembly_table, |
913 | 14 | &addresses_reassembly_table_functions); |
914 | | |
915 | 14 | dcp_etsi_handle = register_dissector("dcp-etsi", dissect_dcp_etsi, proto_dcp_etsi); |
916 | 14 | af_handle = register_dissector("dcp-af", dissect_af, proto_af); |
917 | 14 | pft_handle = register_dissector("dcp-pft", dissect_pft, proto_pft); |
918 | 14 | tpl_handle = register_dissector("dcp-tpl", dissect_tpl, proto_tpl); |
919 | 14 | } |
920 | | |
921 | | /* |
922 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
923 | | * |
924 | | * Local variables: |
925 | | * c-basic-offset: 2 |
926 | | * tab-width: 8 |
927 | | * indent-tabs-mode: nil |
928 | | * End: |
929 | | * |
930 | | * vi: set shiftwidth=2 tabstop=8 expandtab: |
931 | | * :indentSize=2:tabSize=8:noTabs=true: |
932 | | */ |