/src/wireshark/epan/dissectors/packet-h223.c
Line | Count | Source |
1 | | /* packet-h223.c |
2 | | * Routines for H.223 packet dissection |
3 | | * Copyright (c) 2004-5 MX Telecom Ltd <richardv@mxtelecom.com> |
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 | | |
12 | | #include "config.h" |
13 | | |
14 | | |
15 | | #include <epan/packet.h> |
16 | | #include <epan/conversation.h> |
17 | | #include <epan/exceptions.h> |
18 | | #include <epan/expert.h> |
19 | | #include <epan/stream.h> |
20 | | #include <epan/golay.h> |
21 | | #include <epan/show_exception.h> |
22 | | #include <epan/asn1.h> |
23 | | #include <wsutil/bitswap.h> |
24 | | #include <wsutil/wslog.h> |
25 | | |
26 | | #include "packet-h245.h" |
27 | | #include "packet-iax2.h" |
28 | | #include "packet-iax2.h" |
29 | | |
30 | | /* #define DEBUG_H223 */ |
31 | | |
32 | | void proto_register_h223 (void); |
33 | | void proto_reg_handoff_h223(void); |
34 | | |
35 | | /* debug the mux-pdu defragmentation code. warning: verbose output! */ |
36 | | /* #define DEBUG_H223_FRAGMENTATION */ |
37 | | |
38 | 0 | #define PROTO_TAG_H223 "H.223" |
39 | | |
40 | | /* Wireshark ID of the H.223 protocol */ |
41 | | static int proto_h223; |
42 | | static int proto_h223_bitswapped; |
43 | | |
44 | | /* The following hf_* variables are used to hold the Wireshark IDs of |
45 | | * our header fields; they are filled out when we call |
46 | | * proto_register_field_array() in proto_register_h223() |
47 | | */ |
48 | | /* static int hf_h223_non_h223_data; */ |
49 | | static int hf_h223_mux_stuffing_pdu; |
50 | | static int hf_h223_mux_pdu; |
51 | | static int hf_h223_mux_header; |
52 | | static int hf_h223_mux_rawhdr; |
53 | | static int hf_h223_mux_correctedhdr; |
54 | | static int hf_h223_mux_mc; |
55 | | static int hf_h223_mux_mpl; |
56 | | static int hf_h223_mux_deact; |
57 | | static int hf_h223_mux_vc; |
58 | | static int hf_h223_mux_extra; |
59 | | static int hf_h223_mux_hdlc2; |
60 | | static int hf_h223_mux_fragments; |
61 | | static int hf_h223_mux_fragment; |
62 | | static int hf_h223_mux_fragment_overlap; |
63 | | static int hf_h223_mux_fragment_overlap_conflict; |
64 | | static int hf_h223_mux_fragment_multiple_tails; |
65 | | static int hf_h223_mux_fragment_too_long_fragment; |
66 | | static int hf_h223_mux_fragment_error; |
67 | | static int hf_h223_mux_fragment_count; |
68 | | static int hf_h223_mux_reassembled_in; |
69 | | static int hf_h223_mux_reassembled_length; |
70 | | |
71 | | static int hf_h223_al_fragments; |
72 | | static int hf_h223_al_fragment; |
73 | | static int hf_h223_al_fragment_overlap; |
74 | | static int hf_h223_al_fragment_overlap_conflict; |
75 | | static int hf_h223_al_fragment_multiple_tails; |
76 | | static int hf_h223_al_fragment_too_long_fragment; |
77 | | static int hf_h223_al_fragment_error; |
78 | | static int hf_h223_al_fragment_count; |
79 | | static int hf_h223_al_reassembled_in; |
80 | | static int hf_h223_al_reassembled_length; |
81 | | |
82 | | static int hf_h223_al1; |
83 | | static int hf_h223_al1_framed; |
84 | | static int hf_h223_al2; |
85 | | static int hf_h223_al2_sequenced; |
86 | | static int hf_h223_al2_unsequenced; |
87 | | static int hf_h223_al2_seqno; |
88 | | static int hf_h223_al2_crc; |
89 | | static int hf_h223_al2_crc_status; |
90 | | |
91 | | static int hf_h223_al_payload; |
92 | | |
93 | | /* These are the ids of the subtrees that we may be creating */ |
94 | | static int ett_h223; |
95 | | static int ett_h223_non_h223_data; |
96 | | static int ett_h223_mux_stuffing_pdu; |
97 | | static int ett_h223_mux_pdu; |
98 | | static int ett_h223_mux_header; |
99 | | static int ett_h223_mux_deact; |
100 | | static int ett_h223_mux_vc; |
101 | | static int ett_h223_mux_extra; |
102 | | static int ett_h223_mux_fragments; |
103 | | static int ett_h223_mux_fragment; |
104 | | static int ett_h223_al_fragments; |
105 | | static int ett_h223_al_fragment; |
106 | | static int ett_h223_al1; |
107 | | static int ett_h223_al2; |
108 | | static int ett_h223_al_payload; |
109 | | |
110 | | static expert_field ei_h223_al2_crc; |
111 | | |
112 | | /* These are the handles of our subdissectors */ |
113 | | static dissector_handle_t data_handle; |
114 | | static dissector_handle_t srp_handle; |
115 | | static dissector_handle_t h223_bitswapped; |
116 | | |
117 | | static const fragment_items h223_mux_frag_items _U_ = { |
118 | | &ett_h223_mux_fragment, |
119 | | &ett_h223_mux_fragments, |
120 | | &hf_h223_mux_fragments, |
121 | | &hf_h223_mux_fragment, |
122 | | &hf_h223_mux_fragment_overlap, |
123 | | &hf_h223_mux_fragment_overlap_conflict, |
124 | | &hf_h223_mux_fragment_multiple_tails, |
125 | | &hf_h223_mux_fragment_too_long_fragment, |
126 | | &hf_h223_mux_fragment_error, |
127 | | &hf_h223_mux_fragment_count, |
128 | | &hf_h223_mux_reassembled_in, |
129 | | &hf_h223_mux_reassembled_length, |
130 | | /* Reassembled data field */ |
131 | | NULL, |
132 | | "fragments" |
133 | | }; |
134 | | |
135 | | static const fragment_items h223_al_frag_items = { |
136 | | &ett_h223_al_fragment, |
137 | | &ett_h223_al_fragments, |
138 | | &hf_h223_al_fragments, |
139 | | &hf_h223_al_fragment, |
140 | | &hf_h223_al_fragment_overlap, |
141 | | &hf_h223_al_fragment_overlap_conflict, |
142 | | &hf_h223_al_fragment_multiple_tails, |
143 | | &hf_h223_al_fragment_too_long_fragment, |
144 | | &hf_h223_al_fragment_error, |
145 | | &hf_h223_al_fragment_count, |
146 | | &hf_h223_al_reassembled_in, |
147 | | &hf_h223_al_reassembled_length, |
148 | | /* Reassembled data field */ |
149 | | NULL, |
150 | | "fragments" |
151 | | }; |
152 | | |
153 | | /* this is a fudge to pass pdu_offset into add_h223_mux_element() */ |
154 | | static uint32_t pdu_offset; |
155 | | |
156 | | /*************************************************************************** |
157 | | * |
158 | | * virtual circuit number handling |
159 | | * |
160 | | * we have to be able to manage more than one H.223 call at a time, |
161 | | * so have a hash which maps {call,vc} to an integer. |
162 | | */ |
163 | | |
164 | | typedef struct _h223_call_info h223_call_info; |
165 | | |
166 | | typedef struct { |
167 | | const h223_call_info* call; /* h223 call */ |
168 | | uint32_t vc; /* child circuit */ |
169 | | } circuit_chain_key; |
170 | | |
171 | | static wmem_map_t *circuit_chain_hashtable; |
172 | | static unsigned circuit_chain_count = 1; |
173 | | |
174 | | /* Hash Functions */ |
175 | | static int |
176 | | circuit_chain_equal(const void *v, const void *w) |
177 | 0 | { |
178 | 0 | const circuit_chain_key *v1 = (const circuit_chain_key *)v; |
179 | 0 | const circuit_chain_key *v2 = (const circuit_chain_key *)w; |
180 | 0 | int result; |
181 | 0 | result = ( v1->call == v2->call && |
182 | 0 | v1->vc == v2 -> vc ); |
183 | 0 | return result; |
184 | 0 | } |
185 | | |
186 | | static unsigned |
187 | | circuit_chain_hash (const void *v) |
188 | 0 | { |
189 | 0 | const circuit_chain_key *key = (const circuit_chain_key *)v; |
190 | 0 | unsigned hash_val = (GPOINTER_TO_UINT(key->call)) ^ (((uint32_t)key->vc) << 16); |
191 | 0 | return hash_val; |
192 | 0 | } |
193 | | |
194 | | static uint32_t |
195 | | circuit_chain_lookup(const h223_call_info* call_info, uint32_t child_vc) |
196 | 0 | { |
197 | 0 | circuit_chain_key key, *new_key; |
198 | 0 | uint32_t circuit_id; |
199 | 0 | key.call = call_info; |
200 | 0 | key.vc = child_vc; |
201 | 0 | circuit_id = GPOINTER_TO_UINT(wmem_map_lookup( circuit_chain_hashtable, &key )); |
202 | 0 | if( circuit_id == 0 ) { |
203 | 0 | new_key = wmem_new(wmem_file_scope(), circuit_chain_key); |
204 | 0 | *new_key = key; |
205 | 0 | circuit_id = ++circuit_chain_count; |
206 | 0 | wmem_map_insert(circuit_chain_hashtable, new_key, GUINT_TO_POINTER(circuit_id)); |
207 | 0 | } |
208 | 0 | return circuit_id; |
209 | 0 | } |
210 | | |
211 | | static void |
212 | | circuit_chain_init(void) |
213 | 15 | { |
214 | 15 | circuit_chain_count = 1; |
215 | 15 | } |
216 | | |
217 | | |
218 | | /*************************************************************************** |
219 | | * |
220 | | * Call information management |
221 | | * |
222 | | */ |
223 | | |
224 | | /* we keep information on each call in an h223_call_info structure |
225 | | * |
226 | | * We attach the h223_call_info structures to individual calls with |
227 | | * circuit_add_proto_data(). |
228 | | */ |
229 | | |
230 | | typedef struct _h223_mux_element_listitem h223_mux_element_listitem; |
231 | | struct _h223_mux_element_listitem { |
232 | | h223_mux_element *me; |
233 | | uint32_t first_frame; |
234 | | uint32_t pdu_offset; |
235 | | h223_mux_element_listitem *next; |
236 | | }; |
237 | | |
238 | | /* we have this information for each stream */ |
239 | | typedef struct { |
240 | | h223_mux_element_listitem* mux_table[16]; |
241 | | } h223_call_direction_data; |
242 | | |
243 | | |
244 | | struct _h223_call_info { |
245 | | /* H.223 level: 0 for standard H223, 1, 2 or 3 for the enhanced protocols |
246 | | specified in the annexes |
247 | | */ |
248 | | int h223_level; |
249 | | |
250 | | /* for H.223 streams over TCP (as opposed to IAX), this |
251 | | stores the source address and port of the first packet spotted, |
252 | | so that we can differentiate directions. |
253 | | */ |
254 | | address srcaddress; |
255 | | uint32_t srcport; |
256 | | |
257 | | h223_call_direction_data direction_data[2]; |
258 | | }; |
259 | | |
260 | | typedef struct _h223_lc_params_listitem h223_lc_params_listitem; |
261 | | struct _h223_lc_params_listitem |
262 | | { |
263 | | h223_lc_params *lc_params; |
264 | | uint32_t first_frame; |
265 | | uint32_t last_frame; |
266 | | h223_lc_params_listitem *next; |
267 | | }; |
268 | | |
269 | | typedef struct { |
270 | | h223_lc_params_listitem *lc_params[2]; |
271 | | h223_call_info *call_info; |
272 | | } h223_vc_info; |
273 | | |
274 | | static void |
275 | | add_h223_mux_element(h223_call_direction_data *direct, uint8_t mc, h223_mux_element *me, uint32_t framenum) |
276 | 0 | { |
277 | 0 | h223_mux_element_listitem *li; |
278 | 0 | h223_mux_element_listitem **old_li_ptr; |
279 | 0 | h223_mux_element_listitem *old_li; |
280 | |
|
281 | 0 | DISSECTOR_ASSERT(mc < 16); |
282 | |
|
283 | 0 | li = wmem_new(wmem_file_scope(), h223_mux_element_listitem); |
284 | 0 | old_li_ptr = &(direct->mux_table[mc]); |
285 | 0 | old_li = *old_li_ptr; |
286 | 0 | if( !old_li ) { |
287 | 0 | direct->mux_table[mc] = li; |
288 | 0 | } else { |
289 | 0 | while( old_li->next ) { |
290 | 0 | old_li_ptr = &(old_li->next); |
291 | 0 | old_li = *old_li_ptr; |
292 | 0 | } |
293 | 0 | if( framenum < old_li->first_frame || (framenum == old_li->first_frame && pdu_offset < old_li->pdu_offset) ) |
294 | 0 | return; |
295 | 0 | else if ( framenum == old_li->first_frame && pdu_offset == old_li->pdu_offset ) |
296 | 0 | *old_li_ptr = li; /* replace the tail of the list with the new item, since */ |
297 | | /* a single h223 pdu has just set the same MC twice.. */ |
298 | 0 | else |
299 | 0 | old_li->next = li; |
300 | 0 | } |
301 | 0 | li->first_frame = framenum; |
302 | 0 | li->pdu_offset = pdu_offset; |
303 | 0 | li->next = 0; |
304 | 0 | li->me = me; |
305 | 0 | } |
306 | | |
307 | | static h223_mux_element* |
308 | | find_h223_mux_element(h223_call_direction_data* direct, uint8_t mc, uint32_t framenum, uint32_t pkt_offset) |
309 | 0 | { |
310 | 0 | h223_mux_element_listitem* li; |
311 | |
|
312 | 0 | DISSECTOR_ASSERT(mc < 16); |
313 | |
|
314 | 0 | li = direct->mux_table[mc]; |
315 | |
|
316 | 0 | while( li && li->next && li->next->first_frame < framenum ) |
317 | 0 | li = li->next; |
318 | 0 | while( li && li->next && li->next->first_frame == framenum && li->next->pdu_offset < pkt_offset ) |
319 | 0 | li = li->next; |
320 | 0 | if( li ) { |
321 | 0 | return li->me; |
322 | 0 | } else { |
323 | 0 | return NULL; |
324 | 0 | } |
325 | 0 | } |
326 | | |
327 | | static void |
328 | | add_h223_lc_params(h223_vc_info* vc_info, int direction, h223_lc_params *lc_params, uint32_t framenum ) |
329 | 0 | { |
330 | 0 | h223_lc_params_listitem *li = wmem_new(wmem_file_scope(), h223_lc_params_listitem); |
331 | 0 | h223_lc_params_listitem **old_li_ptr = &(vc_info->lc_params[direction ? 0 : 1]); |
332 | 0 | h223_lc_params_listitem *old_li = *old_li_ptr; |
333 | 0 | if( !old_li ) { |
334 | 0 | vc_info->lc_params[direction ? 0 : 1] = li; |
335 | 0 | } else { |
336 | 0 | while( old_li->next ) { |
337 | 0 | old_li_ptr = &(old_li->next); |
338 | 0 | old_li = *old_li_ptr; |
339 | 0 | } |
340 | 0 | if( framenum < old_li->first_frame ) |
341 | 0 | return; |
342 | 0 | else if( framenum == old_li->first_frame ) |
343 | 0 | *old_li_ptr = li; |
344 | 0 | else { |
345 | 0 | old_li->next = li; |
346 | 0 | old_li->last_frame = framenum - 1; |
347 | 0 | } |
348 | 0 | } |
349 | 0 | li->first_frame = framenum; |
350 | 0 | li->last_frame = 0; |
351 | 0 | li->next = 0; |
352 | 0 | li->lc_params = lc_params; |
353 | 0 | } |
354 | | |
355 | | static h223_lc_params* |
356 | | find_h223_lc_params(h223_vc_info* vc_info, int direction, uint32_t framenum) |
357 | 0 | { |
358 | 0 | h223_lc_params_listitem* li = vc_info->lc_params[direction? 0 : 1]; |
359 | 0 | while( li && li->next && li->next->first_frame <= framenum ) |
360 | 0 | li = li->next; |
361 | 0 | if( li ) |
362 | 0 | return li->lc_params; |
363 | 0 | else |
364 | 0 | return NULL; |
365 | 0 | } |
366 | | |
367 | | static void |
368 | | init_direction_data(h223_call_direction_data *direct) |
369 | 0 | { |
370 | 0 | int i; |
371 | 0 | h223_mux_element *mc0_element; |
372 | |
|
373 | 0 | for ( i = 0; i < 16; ++i ) |
374 | 0 | direct->mux_table[i] = NULL; |
375 | | |
376 | | /* set up MC 0 to contain just VC 0 */ |
377 | 0 | mc0_element = wmem_new(wmem_file_scope(), h223_mux_element); |
378 | 0 | add_h223_mux_element( direct, 0, mc0_element, 0 ); |
379 | 0 | mc0_element->sublist = NULL; |
380 | 0 | mc0_element->vc = 0; |
381 | 0 | mc0_element->repeat_count = 0; /* until closing flag */ |
382 | 0 | mc0_element->next = NULL; |
383 | 0 | } |
384 | | |
385 | | static h223_vc_info* |
386 | | h223_vc_info_new( h223_call_info* call_info ) |
387 | 0 | { |
388 | 0 | h223_vc_info *vc_info = wmem_new(wmem_file_scope(), h223_vc_info); |
389 | 0 | vc_info->lc_params[0] = vc_info->lc_params[1] = NULL; |
390 | 0 | vc_info->call_info = call_info; |
391 | 0 | return vc_info; |
392 | 0 | } |
393 | | |
394 | | static void |
395 | | init_logical_channel( uint32_t start_frame, h223_call_info* call_info, int vc, int direction, h223_lc_params* params ) |
396 | 0 | { |
397 | 0 | uint32_t circuit_id = circuit_chain_lookup(call_info, vc); |
398 | 0 | conversation_t *subcircuit; |
399 | 0 | h223_vc_info *vc_info; |
400 | 0 | subcircuit = find_conversation_by_id( start_frame, CONVERSATION_H223, circuit_id); |
401 | |
|
402 | 0 | if( subcircuit == NULL ) { |
403 | 0 | subcircuit = conversation_new_by_id( start_frame, CONVERSATION_H223, circuit_id); |
404 | | #ifdef DEBUG_H223 |
405 | | ws_debug("%d: Created new circuit %d for call %p VC %d", start_frame, circuit_id, call_info, vc); |
406 | | #endif |
407 | 0 | vc_info = h223_vc_info_new( call_info ); |
408 | 0 | conversation_add_proto_data( subcircuit, proto_h223, vc_info ); |
409 | 0 | } else { |
410 | 0 | vc_info = (h223_vc_info *)conversation_get_proto_data( subcircuit, proto_h223 ); |
411 | 0 | } |
412 | 0 | if (vc_info) |
413 | 0 | add_h223_lc_params( vc_info, direction, params, start_frame ); |
414 | 0 | } |
415 | | |
416 | | /* create a brand-new h223_call_info structure */ |
417 | | static h223_call_info * |
418 | | create_call_info( uint32_t start_frame ) |
419 | 0 | { |
420 | 0 | h223_call_info *datax; |
421 | 0 | h223_lc_params *vc0_params; |
422 | |
|
423 | 0 | datax = wmem_new(wmem_file_scope(), h223_call_info); |
424 | | |
425 | | /* initialise the call info */ |
426 | 0 | init_direction_data(&datax -> direction_data[0]); |
427 | 0 | init_direction_data(&datax -> direction_data[1]); |
428 | | |
429 | | /* FIXME shouldn't this be figured out dynamically? */ |
430 | 0 | datax -> h223_level = 2; |
431 | |
|
432 | 0 | vc0_params = wmem_new(wmem_file_scope(), h223_lc_params); |
433 | 0 | vc0_params->al_type = al1Framed; |
434 | 0 | vc0_params->al_params = NULL; |
435 | 0 | vc0_params->segmentable = true; |
436 | 0 | vc0_params->subdissector = srp_handle; |
437 | 0 | init_logical_channel( start_frame, datax, 0, P2P_DIR_SENT, vc0_params ); |
438 | 0 | init_logical_channel( start_frame, datax, 0, P2P_DIR_RECV, vc0_params ); |
439 | 0 | return datax; |
440 | 0 | } |
441 | | |
442 | | /* find or create call_info struct for calls over circuits (eg, IAX) */ |
443 | | static h223_call_info * |
444 | | find_or_create_call_info_circ(packet_info * pinfo, conversation_type ctype, uint32_t circuit_id) |
445 | 0 | { |
446 | 0 | h223_call_info *datax; |
447 | 0 | conversation_t *circ = NULL; |
448 | |
|
449 | 0 | if(ctype != CONVERSATION_NONE) |
450 | 0 | circ = find_conversation_by_id( pinfo->num, ctype, circuit_id); |
451 | 0 | if(circ == NULL) |
452 | 0 | return NULL; |
453 | | |
454 | 0 | datax = (h223_call_info *)conversation_get_proto_data(circ, proto_h223); |
455 | |
|
456 | 0 | if( datax == NULL ) { |
457 | 0 | datax = create_call_info(pinfo->num); |
458 | |
|
459 | | #ifdef DEBUG_H223 |
460 | | ws_debug("%u: Created new call %p for circuit %p ctype %d, id %u", |
461 | | pinfo->num, datax, circ, type, circuit_id); |
462 | | #endif |
463 | 0 | conversation_add_proto_data(circ, proto_h223, datax); |
464 | 0 | } |
465 | | |
466 | | /* work out what direction we're really going in */ |
467 | 0 | if( pinfo->p2p_dir < 0 || pinfo->p2p_dir > 1) |
468 | 0 | pinfo->p2p_dir = P2P_DIR_SENT; |
469 | |
|
470 | 0 | return datax; |
471 | 0 | } |
472 | | |
473 | | /* find or create call_info struct for calls over conversations (eg, RTP) */ |
474 | | static h223_call_info * |
475 | | find_or_create_call_info_conv(packet_info * pinfo) |
476 | 0 | { |
477 | 0 | h223_call_info *datax; |
478 | 0 | conversation_t *conv; |
479 | | |
480 | | /* assume we're running atop TCP or RTP; use the conversation support */ |
481 | 0 | conv = find_conversation_pinfo(pinfo, 0 ); |
482 | | |
483 | | /* both RTP and TCP track their conversations, so just assert here if |
484 | | * we can't find one */ |
485 | 0 | DISSECTOR_ASSERT(conv); |
486 | |
|
487 | 0 | datax = (h223_call_info *)conversation_get_proto_data(conv, proto_h223); |
488 | |
|
489 | 0 | if(datax == NULL && pinfo->ptype == PT_UDP ) { |
490 | 0 | conversation_t *conv2; |
491 | | |
492 | | /* RTP tracks the two sides of the conversation totally separately; |
493 | | * this messes us up totally. |
494 | | * |
495 | | * Look for another converstation, going in the opposite direction. |
496 | | */ |
497 | 0 | conv2 = find_conversation( pinfo->num, |
498 | 0 | &pinfo->dst,&pinfo->src, |
499 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
500 | 0 | pinfo->destport,pinfo->srcport, 0 ); |
501 | 0 | if(conv2 != NULL) |
502 | 0 | datax = (h223_call_info *)conversation_get_proto_data(conv2, proto_h223); |
503 | |
|
504 | 0 | if(datax != NULL) { |
505 | | #ifdef DEBUG_H223 |
506 | | ws_debug("%u: Identified conv %p as reverse of conv %p with call %p and type=%u src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u", |
507 | | pinfo->num, conv, conv2, datax, pinfo->ptype, |
508 | | pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3], |
509 | | pinfo->destport, |
510 | | pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3], |
511 | | pinfo->srcport); |
512 | | #endif |
513 | 0 | conversation_add_proto_data(conv, proto_h223, datax); |
514 | 0 | } |
515 | 0 | } |
516 | | |
517 | | /* we still haven't found any call data - create a new one for this |
518 | | * conversation */ |
519 | 0 | if(datax == NULL) { |
520 | 0 | datax = create_call_info(pinfo->num); |
521 | |
|
522 | | #ifdef DEBUG_H223 |
523 | | ws_debug("%u: Created new call %p for conv %p type=%u src=%u.%u.%u.%u:%u dst=%u.%u.%u.%u:%u", |
524 | | pinfo->num, datax, conv, pinfo->ptype, |
525 | | pinfo->src.data[0], pinfo->src.data[1], pinfo->src.data[2], pinfo->src.data[3], |
526 | | pinfo->srcport, |
527 | | pinfo->dst.data[0], pinfo->dst.data[1], pinfo->dst.data[2], pinfo->dst.data[3], |
528 | | pinfo->destport); |
529 | | #endif |
530 | |
|
531 | 0 | conversation_add_proto_data(conv, proto_h223, datax); |
532 | | /* add the source details so we can distinguish directions |
533 | | * in future */ |
534 | 0 | copy_address_wmem(wmem_file_scope(), &(datax -> srcaddress), &(pinfo->src)); |
535 | 0 | datax -> srcport = pinfo->srcport; |
536 | 0 | } |
537 | | |
538 | | /* work out what direction we're really going in */ |
539 | 0 | if( addresses_equal( &(pinfo->src), &(datax->srcaddress)) |
540 | 0 | && pinfo->srcport == datax->srcport ) |
541 | 0 | pinfo->p2p_dir = P2P_DIR_SENT; |
542 | 0 | else |
543 | 0 | pinfo->p2p_dir = P2P_DIR_RECV; |
544 | |
|
545 | 0 | return datax; |
546 | 0 | } |
547 | | |
548 | | static h223_call_info * |
549 | | find_or_create_call_info ( packet_info * pinfo, conversation_type ctype, uint32_t circuit_id ) |
550 | 0 | { |
551 | 0 | h223_call_info *datax; |
552 | |
|
553 | 0 | datax = find_or_create_call_info_circ(pinfo, ctype, circuit_id); |
554 | 0 | if(datax == NULL) |
555 | 0 | datax = find_or_create_call_info_conv(pinfo); |
556 | 0 | return datax; |
557 | 0 | } |
558 | | |
559 | | /* called from the h245 dissector to handle a MultiplexEntrySend message */ |
560 | | static void |
561 | | h223_set_mc( packet_info* pinfo, uint8_t mc, h223_mux_element* me) |
562 | 0 | { |
563 | 0 | conversation_t *circ = find_conversation_pinfo( pinfo, 0 ); |
564 | 0 | h223_vc_info* vc_info; |
565 | | |
566 | | /* if this h245 pdu packet came from an h223 circuit, add the details on |
567 | | * the new mux entry */ |
568 | 0 | if(circ) { |
569 | 0 | vc_info = (h223_vc_info *)conversation_get_proto_data(circ, proto_h223); |
570 | 0 | if (vc_info != NULL) |
571 | 0 | add_h223_mux_element( &(vc_info->call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, me, pinfo->num ); |
572 | 0 | } |
573 | 0 | } |
574 | | |
575 | | /* called from the h245 dissector to handle an OpenLogicalChannelAck message */ |
576 | | static void |
577 | | h223_add_lc( packet_info* pinfo, uint16_t lc, h223_lc_params* params ) |
578 | 0 | { |
579 | 0 | conversation_t *circ = find_conversation_pinfo( pinfo, 0 ); |
580 | 0 | h223_vc_info* vc_info; |
581 | | |
582 | | /* if this h245 pdu packet came from an h223 circuit, add the details on |
583 | | * the new channel */ |
584 | 0 | if(circ) { |
585 | 0 | vc_info = (h223_vc_info *)conversation_get_proto_data(circ, proto_h223); |
586 | 0 | if (vc_info != NULL) |
587 | 0 | init_logical_channel( pinfo->num, vc_info->call_info, lc, pinfo->p2p_dir, params ); |
588 | 0 | } |
589 | 0 | } |
590 | | |
591 | | /************************************************************************************ |
592 | | * |
593 | | * AL-PDU dissection |
594 | | */ |
595 | | |
596 | | static const uint8_t crctable[256] = { |
597 | | 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, |
598 | | 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, |
599 | | 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43, |
600 | | 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f, |
601 | | 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, |
602 | | 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17, |
603 | | 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33, |
604 | | 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, |
605 | | 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b, |
606 | | 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87, |
607 | | 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, |
608 | | 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf, |
609 | | 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb, |
610 | | 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, |
611 | | 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3, |
612 | | 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf }; |
613 | | |
614 | 0 | static uint8_t h223_al2_crc8bit( tvbuff_t *tvb ) { |
615 | 0 | uint32_t len = tvb_reported_length(tvb) - 1; |
616 | 0 | const uint8_t* datax = tvb_get_ptr( tvb, 0, len ); |
617 | 0 | unsigned char crc = 0; |
618 | 0 | uint32_t pos = 0; |
619 | 0 | DISSECTOR_ASSERT(tvb_reported_length(tvb) >= 1); |
620 | 0 | while ( len-- ) |
621 | 0 | crc = crctable[crc^datax[pos++]]; |
622 | 0 | return crc; |
623 | 0 | } |
624 | | |
625 | | static void |
626 | | dissect_mux_al_pdu( tvbuff_t *tvb, packet_info *pinfo, proto_tree *vc_tree, |
627 | | /* circuit_t* vc_circuit, */ |
628 | | h223_lc_params* lc_params ) |
629 | 0 | { |
630 | 0 | proto_tree *al_tree = NULL; |
631 | 0 | proto_item *al_item, *hidden_item; |
632 | 0 | proto_tree *al_subtree; |
633 | 0 | proto_item *al_subitem = NULL; |
634 | 0 | proto_item *tmp_item; |
635 | 0 | tvbuff_t *next_tvb = NULL; |
636 | 0 | dissector_handle_t subdissector = lc_params->subdissector; |
637 | 0 | uint32_t len = tvb_reported_length(tvb); |
638 | |
|
639 | 0 | uint8_t calc_checksum; |
640 | 0 | uint8_t real_checksum; |
641 | 0 | bool al2_sequenced = false; |
642 | 0 | int data_start; |
643 | |
|
644 | 0 | switch( lc_params->al_type ) { |
645 | 0 | case al1Framed: |
646 | 0 | case al1NotFramed: |
647 | 0 | al_item = proto_tree_add_none_format(vc_tree, hf_h223_al1, tvb, 0, -1, "H.223 AL1 (%sframed)", |
648 | 0 | (lc_params->al_type==al1Framed)?"":"not "); |
649 | 0 | al_tree = proto_item_add_subtree (al_item, ett_h223_al1); |
650 | 0 | if(lc_params->al_type == al1Framed) { |
651 | 0 | hidden_item = proto_tree_add_boolean(al_tree, hf_h223_al1_framed, tvb, 0, 1, true ); |
652 | 0 | proto_item_set_hidden(hidden_item); |
653 | 0 | } |
654 | 0 | next_tvb = tvb; |
655 | 0 | al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, ENC_NA); |
656 | 0 | break; |
657 | | |
658 | 0 | case al2WithSequenceNumbers: |
659 | 0 | al2_sequenced = true; |
660 | | /* fall-through */ |
661 | 0 | case al2WithoutSequenceNumbers: |
662 | 0 | tmp_item = proto_tree_add_boolean(vc_tree, hf_h223_al2, tvb, 0, 0, true ); |
663 | |
|
664 | 0 | al_item = proto_tree_add_item(vc_tree, |
665 | 0 | al2_sequenced?hf_h223_al2_sequenced:hf_h223_al2_unsequenced, |
666 | 0 | tvb, 0, -1, ENC_NA); |
667 | 0 | al_tree = proto_item_add_subtree (al_item, ett_h223_al2); |
668 | |
|
669 | 0 | proto_item_set_generated(tmp_item); |
670 | | |
671 | | /* check minimum payload length */ |
672 | 0 | if(len < (al2_sequenced?2U:1U)) |
673 | 0 | THROW(BoundsError); |
674 | |
|
675 | 0 | data_start = 0; |
676 | 0 | if( al2_sequenced ) { |
677 | 0 | proto_tree_add_item(al_tree, hf_h223_al2_seqno, tvb, 0, 1, ENC_LITTLE_ENDIAN); |
678 | 0 | data_start++; |
679 | 0 | } |
680 | |
|
681 | 0 | next_tvb = tvb_new_subset_length( tvb, data_start, len-1-data_start); |
682 | 0 | al_subitem = proto_tree_add_item(al_tree, hf_h223_al_payload, next_tvb, 0, -1, ENC_NA); |
683 | |
|
684 | 0 | calc_checksum = h223_al2_crc8bit(tvb); |
685 | 0 | real_checksum = tvb_get_uint8(tvb, len - 1); |
686 | |
|
687 | 0 | proto_tree_add_checksum(al_tree, tvb, len - 1, hf_h223_al2_crc, hf_h223_al2_crc_status, &ei_h223_al2_crc, pinfo, calc_checksum, ENC_NA, PROTO_CHECKSUM_VERIFY); |
688 | |
|
689 | 0 | if( calc_checksum != real_checksum ) { |
690 | | /* don't pass pdus which fail checksums on to the subdissector */ |
691 | 0 | subdissector = data_handle; |
692 | 0 | } |
693 | 0 | break; |
694 | 0 | default: |
695 | 0 | call_dissector(data_handle, tvb, pinfo, vc_tree); |
696 | 0 | return; |
697 | 0 | } |
698 | | |
699 | 0 | if (!subdissector) |
700 | 0 | subdissector = data_handle; |
701 | |
|
702 | 0 | al_subtree = proto_item_add_subtree(al_subitem, ett_h223_al_payload); |
703 | 0 | call_dissector(subdissector, next_tvb, pinfo, al_subtree); |
704 | 0 | } |
705 | | |
706 | | /************************************************************************************ |
707 | | * |
708 | | * MUX-PDU dissection |
709 | | */ |
710 | | |
711 | | |
712 | | /* dissect a fragment of a MUX-PDU which belongs to a particular VC |
713 | | * |
714 | | * tvb buffer containing the MUX-PDU fragment |
715 | | * pinfo info on the packet containing the last fragment of the MUX-PDU |
716 | | * pkt_offset offset within the block from the superdissector where the |
717 | | * fragment starts (must increase monotonically for constant pinfo->num) |
718 | | * pdu_tree dissection tree for the PDU; a single item will be added (with |
719 | | * its own subtree) |
720 | | * vc VC for this SDU |
721 | | * end_of_mux_sdu true if this is a segmentable VC and this is the last |
722 | | * fragment in an SDU |
723 | | */ |
724 | | static void |
725 | | dissect_mux_sdu_fragment(tvbuff_t *volatile next_tvb, packet_info *pinfo, |
726 | | uint32_t pkt_offset, proto_tree *pdu_tree, |
727 | | h223_call_info* call_info, uint16_t vc, |
728 | | bool end_of_mux_sdu, conversation_type orig_ctype, |
729 | | uint32_t orig_circuit) |
730 | 0 | { |
731 | 0 | TRY { |
732 | | /* update the circuit details before passing to a subdissector */ |
733 | 0 | uint32_t circuit_id = circuit_chain_lookup(call_info, vc); |
734 | 0 | conversation_set_elements_by_id(pinfo, CONVERSATION_H223, circuit_id); |
735 | |
|
736 | 0 | conversation_t *subcircuit = find_conversation_by_id(pinfo->num, CONVERSATION_H223, circuit_id); |
737 | 0 | proto_tree *vc_tree; |
738 | 0 | proto_item *vc_item; |
739 | 0 | h223_vc_info *vc_info = NULL; |
740 | 0 | h223_lc_params *lc_params = NULL; |
741 | |
|
742 | 0 | vc_item = proto_tree_add_uint(pdu_tree, hf_h223_mux_vc, next_tvb, 0, tvb_reported_length(next_tvb), vc); |
743 | 0 | vc_tree = proto_item_add_subtree (vc_item, ett_h223_mux_vc); |
744 | |
|
745 | 0 | if( subcircuit == NULL ) { |
746 | 0 | ws_message( "Frame %d: Subcircuit id %d not found for call %p VC %d", pinfo->num, |
747 | 0 | circuit_id, (void *)call_info, vc ); |
748 | 0 | } else { |
749 | 0 | vc_info = (h223_vc_info *)conversation_get_proto_data(subcircuit, proto_h223); |
750 | 0 | if( vc_info != NULL ) { |
751 | 0 | lc_params = find_h223_lc_params( vc_info, pinfo->p2p_dir, pinfo->num ); |
752 | 0 | } |
753 | 0 | } |
754 | | |
755 | |
|
756 | 0 | if( lc_params != NULL ) { |
757 | 0 | if( lc_params->segmentable && lc_params->al_type != al1NotFramed ) { |
758 | 0 | stream_t *substream; |
759 | 0 | stream_pdu_fragment_t *frag; |
760 | |
|
761 | 0 | substream = find_stream(subcircuit,pinfo->p2p_dir); |
762 | 0 | if(substream == NULL ) |
763 | 0 | substream = stream_new(subcircuit,pinfo->p2p_dir); |
764 | 0 | frag = stream_find_frag(substream,pinfo->num,pkt_offset); |
765 | |
|
766 | 0 | if(frag == NULL ) { |
767 | | #ifdef DEBUG_H223 |
768 | | ws_debug("%d: New H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d", |
769 | | pinfo->num, orig_circuit, circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu); |
770 | | #endif |
771 | 0 | frag = stream_add_frag(substream,pinfo->num,pkt_offset, |
772 | 0 | next_tvb,pinfo,!end_of_mux_sdu); |
773 | 0 | } else { |
774 | | #ifdef DEBUG_H223 |
775 | | ws_debug("%d: Found H.223 VC fragment: Parent circuit %d; subcircuit %d; offset %d; len %d, end %d", |
776 | | pinfo->num, orig_circuit, circuit_id, pkt_offset, tvb_reported_length(next_tvb), end_of_mux_sdu); |
777 | | #endif |
778 | 0 | } |
779 | |
|
780 | 0 | next_tvb = stream_process_reassembled( |
781 | 0 | next_tvb, 0, pinfo, |
782 | 0 | "Reassembled H.223 AL-PDU", |
783 | 0 | frag, &h223_al_frag_items, |
784 | 0 | NULL, vc_tree); |
785 | 0 | } |
786 | |
|
787 | 0 | if(next_tvb) { |
788 | | /* fudge to pass pkt_offset down to add_h223_mux_element, |
789 | | * should it be called */ |
790 | 0 | pdu_offset = pkt_offset; |
791 | 0 | dissect_mux_al_pdu(next_tvb, pinfo, vc_tree,/* subcircuit,*/ lc_params ); |
792 | 0 | } |
793 | 0 | } else { |
794 | 0 | call_dissector(data_handle,next_tvb,pinfo,vc_tree); |
795 | 0 | } |
796 | 0 | } |
797 | | |
798 | | /* restore the original circuit details for future PDUs */ |
799 | 0 | FINALLY { |
800 | 0 | conversation_set_elements_by_id(pinfo, orig_ctype, orig_circuit); |
801 | 0 | } |
802 | 0 | ENDTRY; |
803 | 0 | } |
804 | | |
805 | | static uint32_t |
806 | | // NOLINTNEXTLINE(misc-no-recursion) |
807 | | mux_element_sublist_size(packet_info *pinfo, h223_mux_element* me) |
808 | 0 | { |
809 | 0 | h223_mux_element *current_me = me->next; |
810 | 0 | uint32_t length = 0; |
811 | 0 | increment_dissection_depth(pinfo); |
812 | 0 | while ( current_me ) { |
813 | 0 | if ( current_me->sublist ) |
814 | 0 | length += current_me->repeat_count * mux_element_sublist_size(pinfo, current_me->sublist); |
815 | 0 | else |
816 | 0 | length += current_me->repeat_count; |
817 | 0 | current_me = current_me->next; |
818 | 0 | } |
819 | 0 | decrement_dissection_depth(pinfo); |
820 | | |
821 | | /* should never happen, but to avoid infinite loops... */ |
822 | 0 | DISSECTOR_ASSERT(length != 0); |
823 | |
|
824 | 0 | return length; |
825 | 0 | } |
826 | | |
827 | | /* dissect part of a MUX-PDU payload according to a multiplex list |
828 | | * |
829 | | * tvb buffer containing entire mux-pdu payload |
830 | | * pinfo info on the packet containing the last fragment of the MUX-PDU |
831 | | * pkt_offset offset within the block from the superdissector where the |
832 | | * MUX-PDU starts (must increase monotonically for constant |
833 | | * pinfo->num) |
834 | | * pdu_tree dissection tree for the PDU |
835 | | * call_info data structure for h223 call |
836 | | * me top of mux list |
837 | | * offset offset within tvb to start work |
838 | | * endOfMuxSdu true if the end-of-sdu flag was set |
839 | | */ |
840 | | static uint32_t |
841 | | // NOLINTNEXTLINE(misc-no-recursion) |
842 | | dissect_mux_payload_by_me_list( tvbuff_t *tvb, packet_info *pinfo, |
843 | | uint32_t pkt_offset, proto_tree *pdu_tree, |
844 | | h223_call_info* call_info, |
845 | | h223_mux_element *me, uint32_t offset, |
846 | | bool endOfMuxSdu, conversation_type ctype, |
847 | | uint32_t circuit_id) |
848 | 0 | { |
849 | 0 | uint32_t len = tvb_reported_length(tvb); |
850 | 0 | uint32_t frag_len; |
851 | 0 | uint32_t sublist_len; |
852 | 0 | int i; |
853 | 0 | increment_dissection_depth(pinfo); |
854 | 0 | while ( me ) { |
855 | 0 | if ( me->sublist ) { |
856 | 0 | if ( me->repeat_count == 0 ) { |
857 | 0 | for(sublist_len = mux_element_sublist_size(pinfo, me->sublist); |
858 | 0 | offset + sublist_len <= len; |
859 | 0 | offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, |
860 | 0 | call_info, me->sublist, offset, endOfMuxSdu, |
861 | 0 | ctype, circuit_id) ); |
862 | 0 | } else { |
863 | 0 | for(i = 0; i < me->repeat_count; ++i) |
864 | 0 | offset = dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, |
865 | 0 | call_info, me->sublist, offset, endOfMuxSdu, |
866 | 0 | ctype, circuit_id); |
867 | 0 | } |
868 | 0 | } else { |
869 | 0 | if ( me->repeat_count == 0 ) |
870 | 0 | frag_len = len - offset; |
871 | 0 | else |
872 | 0 | frag_len = me->repeat_count; |
873 | 0 | if(frag_len > 0) { |
874 | 0 | tvbuff_t *next_tvb; |
875 | 0 | next_tvb = tvb_new_subset_length(tvb, offset, frag_len); |
876 | 0 | dissect_mux_sdu_fragment( next_tvb, pinfo, pkt_offset + offset, pdu_tree, |
877 | 0 | call_info, me->vc, (offset+frag_len==len) && endOfMuxSdu, |
878 | 0 | ctype, circuit_id); |
879 | 0 | offset += frag_len; |
880 | 0 | } |
881 | 0 | } |
882 | 0 | me = me->next; |
883 | 0 | } |
884 | 0 | decrement_dissection_depth(pinfo); |
885 | 0 | return offset; |
886 | 0 | } |
887 | | |
888 | | /* dissect the payload of a MUX-PDU |
889 | | * |
890 | | * tvb buffer containing entire mux-pdu payload |
891 | | * pinfo info on the packet containing the last fragment of the MUX-PDU |
892 | | * pkt_offset offset within the block from the superdissector where the |
893 | | * MUX-PDU starts (must increase monotonically for constant |
894 | | * pinfo->num) |
895 | | * pdu_tree dissection tree for the PDU |
896 | | * call_info data structure for h223 call |
897 | | * mc multiplex code for this PDU |
898 | | * endOfMuxSdu true if the end-of-sdu flag was set |
899 | | */ |
900 | | static void |
901 | | dissect_mux_payload( tvbuff_t *tvb, packet_info *pinfo, uint32_t pkt_offset, |
902 | | proto_tree *pdu_tree, h223_call_info *call_info, |
903 | | uint8_t mc, bool endOfMuxSdu, conversation_type ctype, |
904 | | uint32_t circuit_id ) |
905 | 0 | { |
906 | 0 | uint32_t len = tvb_reported_length(tvb); |
907 | |
|
908 | 0 | h223_mux_element* me = find_h223_mux_element( &(call_info->direction_data[pinfo->p2p_dir ? 0 : 1]), mc, pinfo->num, pkt_offset ); |
909 | |
|
910 | 0 | if( me ) { |
911 | 0 | dissect_mux_payload_by_me_list( tvb, pinfo, pkt_offset, pdu_tree, call_info, me, 0, endOfMuxSdu, ctype, circuit_id ); |
912 | 0 | } else { |
913 | | /* no entry found in mux-table. ignore packet and dissect as data */ |
914 | 0 | proto_tree *vc_tree = NULL; |
915 | |
|
916 | 0 | if(pdu_tree) { |
917 | 0 | proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_deact, tvb, 0, len, ENC_NA); |
918 | 0 | vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact); |
919 | 0 | } |
920 | 0 | call_dissector(data_handle,tvb,pinfo,vc_tree); |
921 | 0 | } |
922 | 0 | } |
923 | | |
924 | | /* dissect a reassembled mux-pdu |
925 | | * |
926 | | * tvb buffer containing mux-pdu, including header and closing flag |
927 | | * pinfo packet info for packet containing the end of the mux-pdu |
928 | | * pkt_offset offset within the block from the superdissector where the |
929 | | * MUX-PDU starts (must increase monotonically for constant |
930 | | * pinfo->num) |
931 | | * h223_tree dissection tree for h223 protocol; a single item will be added |
932 | | * (with a sub-tree) |
933 | | * call_info h223 info structure for this h223 call |
934 | | * pdu_no index of this pdu within the call |
935 | | */ |
936 | | static void |
937 | | dissect_mux_pdu( tvbuff_t *tvb, packet_info *pinfo, uint32_t pkt_offset, |
938 | | proto_tree *h223_tree, h223_call_info *call_info, |
939 | | conversation_type ctype, uint32_t circuit_id) |
940 | 0 | { |
941 | 0 | uint32_t offset = 0; |
942 | | /* actual (as opposed to reported) payload len */ |
943 | 0 | uint32_t len; |
944 | 0 | uint32_t raw_hdr = 0, correct_hdr = 0; |
945 | 0 | int32_t errors = 0; |
946 | 0 | uint16_t closing_flag = 0; |
947 | 0 | uint8_t mc = 0; |
948 | 0 | uint8_t mpl = 0; |
949 | 0 | bool end_of_mux_sdu = false; |
950 | 0 | tvbuff_t *pdu_tvb; |
951 | |
|
952 | 0 | proto_item *pdu_item = NULL; |
953 | 0 | proto_tree *pdu_tree = NULL; |
954 | |
|
955 | | #ifdef DEBUG_H223_FRAGMENTATION |
956 | | ws_debug("%u: dissecting complete H.223 MUX-PDU, pkt_offset %u, len %u", |
957 | | pinfo->num, pkt_offset, tvb_reported_length(tvb)); |
958 | | #endif |
959 | |
|
960 | 0 | switch(call_info->h223_level) { |
961 | 0 | case 0: case 1: |
962 | 0 | raw_hdr = tvb_get_uint8(tvb,0); |
963 | 0 | mc = (uint8_t)((raw_hdr>>1) & 0xf); |
964 | 0 | end_of_mux_sdu = raw_hdr & 1; |
965 | 0 | offset++; |
966 | | /* closing flag is one byte long for h223 level 0, two for level 1 */ |
967 | 0 | len = mpl = tvb_reported_length_remaining(tvb, offset)-(call_info->h223_level+1); |
968 | | |
969 | | /* XXX should ignore pdus with incorrect HECs */ |
970 | 0 | break; |
971 | | |
972 | 0 | case 2: |
973 | 0 | raw_hdr = tvb_get_letoh24(tvb,0); |
974 | 0 | errors = golay_errors(raw_hdr); |
975 | 0 | offset += 3; |
976 | 0 | len = tvb_reported_length_remaining(tvb,offset)-2; |
977 | |
|
978 | 0 | if(errors != -1) { |
979 | 0 | correct_hdr = raw_hdr ^ (uint32_t)errors; |
980 | |
|
981 | 0 | mc = (uint8_t)(correct_hdr & 0xf); |
982 | 0 | mpl = (uint8_t)((correct_hdr >> 4) & 0xff); |
983 | | |
984 | | /* we should never have been called if there's not enough data in |
985 | | * available. */ |
986 | 0 | DISSECTOR_ASSERT(len >= mpl); |
987 | |
|
988 | 0 | closing_flag = tvb_get_ntohs(tvb,offset+len); |
989 | 0 | end_of_mux_sdu = (closing_flag==(0xE14D ^ 0xFFFF)); |
990 | 0 | } else { |
991 | 0 | mc = 0; |
992 | 0 | mpl = len; |
993 | 0 | } |
994 | 0 | break; |
995 | | |
996 | 0 | case 3: |
997 | | /* XXX not implemented */ |
998 | 0 | default: |
999 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
1000 | 0 | } |
1001 | | |
1002 | | |
1003 | 0 | if( h223_tree ) { |
1004 | 0 | if( mpl == 0 ) { |
1005 | 0 | pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_stuffing_pdu, tvb, 0, -1, ENC_NA); |
1006 | 0 | pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_stuffing_pdu); |
1007 | 0 | } else { |
1008 | 0 | pdu_item = proto_tree_add_item (h223_tree, hf_h223_mux_pdu, tvb, 0, -1, ENC_NA); |
1009 | 0 | pdu_tree = proto_item_add_subtree (pdu_item, ett_h223_mux_pdu); |
1010 | 0 | } |
1011 | 0 | } |
1012 | |
|
1013 | 0 | if( pdu_tree ) { |
1014 | 0 | proto_item *item = proto_tree_add_item (pdu_tree, hf_h223_mux_header, tvb, 0, offset, ENC_NA); |
1015 | 0 | proto_tree *hdr_tree = proto_item_add_subtree (item, ett_h223_mux_header); |
1016 | |
|
1017 | 0 | switch(call_info->h223_level) { |
1018 | 0 | case 0: case 1: |
1019 | 0 | proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc); |
1020 | 0 | break; |
1021 | | |
1022 | 0 | case 2: |
1023 | 0 | if( errors == -1 ) { |
1024 | 0 | proto_tree_add_uint_format_value(hdr_tree, hf_h223_mux_rawhdr, tvb, |
1025 | 0 | 0, 3, raw_hdr, |
1026 | 0 | "0x%06x (uncorrectable errors)", raw_hdr ); |
1027 | 0 | } else { |
1028 | | /* B.3.2.1 Header field */ |
1029 | 0 | if( errors == 0 ) { |
1030 | 0 | proto_tree_add_uint_format_value(hdr_tree, hf_h223_mux_rawhdr, tvb, |
1031 | 0 | 0, 3, raw_hdr, |
1032 | 0 | "0x%06x (correct)", raw_hdr ); |
1033 | 0 | } else { |
1034 | 0 | proto_tree_add_uint_format_value(hdr_tree, hf_h223_mux_rawhdr, tvb, |
1035 | 0 | 0, 3, raw_hdr, |
1036 | 0 | "0x%06x (errors are 0x%06x)", raw_hdr, errors ); |
1037 | 0 | } |
1038 | 0 | item = proto_tree_add_uint(hdr_tree,hf_h223_mux_correctedhdr,tvb,0,3, |
1039 | 0 | correct_hdr); |
1040 | 0 | proto_item_set_generated(item); |
1041 | 0 | proto_tree_add_uint(hdr_tree,hf_h223_mux_mc,tvb,0,1,mc); |
1042 | 0 | proto_tree_add_uint(hdr_tree,hf_h223_mux_mpl,tvb,0,2,mpl); |
1043 | 0 | } |
1044 | 0 | break; |
1045 | | |
1046 | 0 | case 3: |
1047 | | /* XXX not implemented */ |
1048 | 0 | default: |
1049 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
1050 | 0 | } |
1051 | 0 | } |
1052 | | |
1053 | 0 | if(mpl > 0) { |
1054 | 0 | pdu_tvb = tvb_new_subset_length(tvb, offset, mpl); |
1055 | 0 | if(errors != -1) { |
1056 | 0 | dissect_mux_payload(pdu_tvb,pinfo,pkt_offset+offset,pdu_tree,call_info,mc,end_of_mux_sdu, ctype, circuit_id); |
1057 | 0 | } else { |
1058 | 0 | call_dissector(data_handle,pdu_tvb,pinfo,pdu_tree); |
1059 | 0 | } |
1060 | 0 | offset += mpl; |
1061 | 0 | } |
1062 | | |
1063 | | /* any extra data in the PDU, beyond that indictated by the mpl, is |
1064 | | dissected as data. */ |
1065 | 0 | len -= mpl; |
1066 | 0 | if( len > 0 ) { |
1067 | 0 | tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, len); |
1068 | 0 | proto_tree *vc_tree = NULL; |
1069 | |
|
1070 | 0 | if( pdu_tree ) { |
1071 | 0 | proto_item *vc_item = proto_tree_add_item(pdu_tree, hf_h223_mux_extra, next_tvb, 0, len, ENC_NA); |
1072 | 0 | vc_tree = proto_item_add_subtree(vc_item, ett_h223_mux_deact); |
1073 | 0 | } |
1074 | 0 | call_dissector(data_handle,next_tvb,pinfo,vc_tree); |
1075 | |
|
1076 | 0 | offset += len; |
1077 | 0 | } |
1078 | | |
1079 | | /* add the closing HDLC flag */ |
1080 | 0 | if( pdu_tree ) |
1081 | 0 | proto_tree_add_item(pdu_tree,hf_h223_mux_hdlc2,tvb,offset,2,ENC_BIG_ENDIAN); |
1082 | 0 | } |
1083 | | |
1084 | | |
1085 | | /************************************************************************************ |
1086 | | * |
1087 | | * MUX-PDU delineation and defragmentation |
1088 | | */ |
1089 | | |
1090 | | /* attempt to parse the header of a mux pdu */ |
1091 | | static bool |
1092 | | attempt_mux_level0_header_parse(uint32_t nbytes _U_, uint32_t hdr _U_, uint32_t *minlen _U_) |
1093 | 0 | { |
1094 | | /* level 0 isn't byte-aligned, so is a complete pain to implement */ |
1095 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
1096 | 0 | return false; |
1097 | 0 | } |
1098 | | |
1099 | | static bool |
1100 | | attempt_mux_level1_header_parse(uint32_t nbytes, uint32_t hdr, uint32_t *minlen ) |
1101 | 0 | { |
1102 | | /* this is untested */ |
1103 | 0 | if(nbytes < 2) |
1104 | 0 | return false; |
1105 | | |
1106 | 0 | hdr &= 0xffff; |
1107 | | /* don't interpret a repeated hdlc as a header */ |
1108 | 0 | if(hdr == 0xE14D) |
1109 | 0 | return false; |
1110 | | |
1111 | | /* + 1 byte of header and 2 bytes of closing HDLC */ |
1112 | 0 | *minlen = (uint8_t)((hdr >> 12) & 0xff) + 3; |
1113 | 0 | return true; |
1114 | 0 | } |
1115 | | |
1116 | | static bool |
1117 | | attempt_mux_level2_3_header_parse(uint32_t nbytes, uint32_t hdr, uint32_t *minlen) |
1118 | 0 | { |
1119 | 0 | int32_t errors; |
1120 | |
|
1121 | 0 | if(nbytes < 3) |
1122 | 0 | return false; |
1123 | | |
1124 | | /* + 3 bytes of header and 2 bytes of closing HDLC */ |
1125 | 0 | *minlen = 5; |
1126 | | |
1127 | | /* bah, we get the header in the wrong order */ |
1128 | 0 | hdr = |
1129 | 0 | ((hdr & 0xFF0000) >> 16) | |
1130 | 0 | (hdr & 0x00FF00) | |
1131 | 0 | ((hdr & 0x0000FF) << 16); |
1132 | |
|
1133 | 0 | errors = golay_errors(hdr); |
1134 | 0 | if(errors != -1) { |
1135 | 0 | hdr ^= errors; |
1136 | 0 | *minlen += ((hdr >> 4) & 0xff); |
1137 | 0 | } |
1138 | |
|
1139 | 0 | return true; |
1140 | 0 | } |
1141 | | |
1142 | | static bool (* const attempt_mux_header_parse[])(uint32_t nbytes, uint32_t header_buf, uint32_t *minlen) = { |
1143 | | attempt_mux_level0_header_parse, |
1144 | | attempt_mux_level1_header_parse, |
1145 | | attempt_mux_level2_3_header_parse, |
1146 | | attempt_mux_level2_3_header_parse |
1147 | | }; |
1148 | | |
1149 | | static bool |
1150 | | h223_mux_check_hdlc(int h223_level, uint32_t nbytes, uint32_t tail_buf) |
1151 | 0 | { |
1152 | 0 | uint32_t masked; |
1153 | |
|
1154 | 0 | switch(h223_level) { |
1155 | 0 | case 0: |
1156 | | /* level 0 isn't byte-aligned, so is a complete pain to implement */ |
1157 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
1158 | 0 | return false; |
1159 | | |
1160 | 0 | case 1: |
1161 | 0 | masked = tail_buf & 0xffff; |
1162 | 0 | return nbytes >= 2 && masked == 0xE14D; |
1163 | | |
1164 | 0 | case 2: case 3: |
1165 | 0 | masked = tail_buf & 0xffff; |
1166 | 0 | return nbytes >= 2 && (masked == 0xE14D || masked == (0xE14D ^ 0xFFFF)); |
1167 | | |
1168 | 0 | default: |
1169 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
1170 | 0 | return false; |
1171 | 0 | } |
1172 | 0 | } |
1173 | | |
1174 | | /* read a pdu (or the start of a pdu) from the tvb, and dissect it |
1175 | | * |
1176 | | * returns the number of bytes processed, or the negative of the number of |
1177 | | * extra bytes needed, or zero if we don't know yet |
1178 | | */ |
1179 | | |
1180 | | static int |
1181 | | dissect_mux_pdu_fragment( tvbuff_t *tvb, uint32_t start_offset, |
1182 | | packet_info *pinfo, proto_tree *h223_tree, |
1183 | | h223_call_info *call_info, conversation_type ctype, |
1184 | | uint32_t circuit_id) |
1185 | 0 | { |
1186 | 0 | tvbuff_t *volatile next_tvb; |
1187 | 0 | volatile uint32_t offset = start_offset; |
1188 | 0 | bool more_frags = true; |
1189 | |
|
1190 | 0 | bool header_parsed = false; |
1191 | 0 | uint32_t header_buf = 0, tail_buf = 0; |
1192 | 0 | uint32_t pdu_minlen = 0; |
1193 | | |
1194 | |
|
1195 | | #ifdef DEBUG_H223_FRAGMENTATION |
1196 | | ws_debug("%d: dissecting H.223 PDU, start_offset %u, %u bytes left", |
1197 | | pinfo->num,start_offset, tvb_reported_length_remaining( tvb, start_offset )); |
1198 | | #endif |
1199 | |
|
1200 | 0 | while( more_frags && offset < tvb_reported_length( tvb )) { |
1201 | 0 | uint8_t byte = tvb_get_uint8(tvb, offset++); |
1202 | | |
1203 | | /* read a byte into the header buf, if necessary */ |
1204 | 0 | if((offset-start_offset) <= 4) { |
1205 | 0 | header_buf <<= 8; |
1206 | 0 | header_buf |= byte; |
1207 | 0 | } |
1208 | | |
1209 | | /* read the byte into the tail buf */ |
1210 | 0 | tail_buf <<= 8; |
1211 | 0 | tail_buf |= byte; |
1212 | | |
1213 | | /* if we haven't parsed the header yet, attempt to do so now */ |
1214 | 0 | if(!header_parsed) |
1215 | | /* this sets current_pdu_header parsed if current_pdu_read == 3 */ |
1216 | 0 | header_parsed = (attempt_mux_header_parse[call_info->h223_level]) |
1217 | 0 | (offset-start_offset,header_buf,&pdu_minlen); |
1218 | | |
1219 | | /* if we have successfully parsed the header, we have sufficient data, |
1220 | | * and we have found the closing hdlc, we are done here */ |
1221 | 0 | if(header_parsed && (offset-start_offset) >= pdu_minlen) { |
1222 | 0 | if(h223_mux_check_hdlc(call_info->h223_level,offset-start_offset,tail_buf)) { |
1223 | 0 | more_frags = false; |
1224 | 0 | } |
1225 | 0 | } |
1226 | 0 | } |
1227 | |
|
1228 | 0 | if( more_frags ) { |
1229 | 0 | if(pdu_minlen <= (offset-start_offset)) { |
1230 | | /* we haven't found the closing hdlc yet, but we don't know how |
1231 | | * much more we need */ |
1232 | | #ifdef DEBUG_H223_FRAGMENTATION |
1233 | | ws_debug("\tBailing, requesting more bytes"); |
1234 | | #endif |
1235 | 0 | return 0; |
1236 | 0 | } else { |
1237 | 0 | uint32_t needed = pdu_minlen-(offset-start_offset); |
1238 | | #ifdef DEBUG_H223_FRAGMENTATION |
1239 | | ws_debug("\tBailing, requesting %i-%i=%u more bytes", pdu_minlen,(offset-start_offset),needed); |
1240 | | #endif |
1241 | 0 | return - (int) needed; |
1242 | 0 | } |
1243 | 0 | } |
1244 | | |
1245 | | /* create a tvb for the fragment */ |
1246 | 0 | next_tvb = tvb_new_subset_length(tvb, start_offset, offset-start_offset); |
1247 | | |
1248 | | /* |
1249 | | * Dissect the PDU. |
1250 | | * |
1251 | | * If it gets an error that means there's no point in dissecting |
1252 | | * any more PDUs, rethrow the exception in question. |
1253 | | * |
1254 | | * If it gets any other error, report it and continue, as that |
1255 | | * means that PDU got an error, but that doesn't mean we should |
1256 | | * stop dissecting PDUs within this frame or chunk of reassembled |
1257 | | * data. |
1258 | | */ |
1259 | 0 | TRY { |
1260 | 0 | dissect_mux_pdu( next_tvb, pinfo, start_offset, h223_tree, call_info, ctype, circuit_id); |
1261 | 0 | } |
1262 | 0 | CATCH_NONFATAL_ERRORS { |
1263 | 0 | show_exception(tvb, pinfo, h223_tree, EXCEPT_CODE, GET_MESSAGE); |
1264 | 0 | } |
1265 | |
|
1266 | 0 | ENDTRY; |
1267 | |
|
1268 | 0 | return (offset-start_offset); |
1269 | 0 | } |
1270 | | |
1271 | | /************************************************************************************ |
1272 | | * |
1273 | | * main dissector entry points |
1274 | | */ |
1275 | | |
1276 | | /* dissects PDUs from the tvb |
1277 | | * |
1278 | | * Updates desegment_offset and desegment_len if the end of the data didn't |
1279 | | * line up with the end of a pdu. |
1280 | | */ |
1281 | | static void |
1282 | | dissect_h223_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, conversation_type ctype, uint32_t circuit_id) |
1283 | 0 | { |
1284 | 0 | proto_tree *h223_tree = NULL; |
1285 | 0 | proto_item *h223_item = NULL; |
1286 | 0 | h223_call_info *call_info = NULL; |
1287 | 0 | uint32_t offset = 0; |
1288 | | |
1289 | | /* set up the protocol and info fields in the summary pane */ |
1290 | 0 | col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_H223); |
1291 | |
|
1292 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
1293 | | |
1294 | | /* find or create the call_info for this call */ |
1295 | 0 | call_info = find_or_create_call_info(pinfo, ctype, circuit_id); |
1296 | | |
1297 | | /* add the 'h223' tree to the main tree */ |
1298 | 0 | if (tree) { |
1299 | 0 | h223_item = proto_tree_add_item (tree, proto_h223, tvb, 0, -1, ENC_NA); |
1300 | 0 | h223_tree = proto_item_add_subtree (h223_item, ett_h223); |
1301 | 0 | } |
1302 | |
|
1303 | 0 | while( offset < tvb_reported_length( tvb )) { |
1304 | 0 | int res = dissect_mux_pdu_fragment( tvb, offset, pinfo, |
1305 | 0 | h223_tree, call_info, ctype, circuit_id); |
1306 | 0 | if(res <= 0) { |
1307 | | /* the end of the tvb held the start of a PDU */ |
1308 | 0 | pinfo->desegment_offset = offset; |
1309 | | |
1310 | | /* if res != 0, we actually know how much more data we need for a |
1311 | | * PDU. |
1312 | | * |
1313 | | * However, if we return that, it means that we get called twice |
1314 | | * for the next packet; this makes it hard to tell how far through |
1315 | | * the stream we are and we have to start messing about with |
1316 | | * getting the seqno from the superdissector's private data. So we |
1317 | | * don't do that. |
1318 | | * |
1319 | | * pinfo->desegment_len = (res == 0 ? DESEGMENT_ONE_MORE_SEGMENT : -res); |
1320 | | */ |
1321 | 0 | pinfo -> desegment_len = DESEGMENT_ONE_MORE_SEGMENT; |
1322 | |
|
1323 | 0 | if(h223_item) { |
1324 | | /* shrink the h223 protocol item such that it only includes the |
1325 | | * bits we dissected */ |
1326 | 0 | proto_item_set_len(h223_item,offset); |
1327 | 0 | } |
1328 | |
|
1329 | 0 | if(offset == 0) { |
1330 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "(No complete PDUs)"); |
1331 | 0 | } |
1332 | 0 | return; |
1333 | 0 | } |
1334 | 0 | offset += res; |
1335 | 0 | } |
1336 | 0 | } |
1337 | | |
1338 | | static int |
1339 | | dissect_h223_circuit_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
1340 | 0 | { |
1341 | 0 | iax2_dissector_info_t circuit_info; |
1342 | |
|
1343 | 0 | DISSECTOR_ASSERT(data); |
1344 | 0 | circuit_info = *((iax2_dissector_info_t*)data); |
1345 | |
|
1346 | 0 | dissect_h223_common(tvb, pinfo, tree, circuit_info.ctype, circuit_info.circuit_id); |
1347 | 0 | return tvb_captured_length(tvb); |
1348 | 0 | } |
1349 | | |
1350 | | static int |
1351 | | dissect_h223(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
1352 | 0 | { |
1353 | 0 | dissect_h223_common(tvb, pinfo, tree, CONVERSATION_NONE, 0); |
1354 | 0 | return tvb_captured_length(tvb); |
1355 | 0 | } |
1356 | | |
1357 | | /* H.223 specifies that the least-significant bit is transmitted first; |
1358 | | * however this is at odds with IAX which transmits bytes with the |
1359 | | * first-received bit as the MSB. |
1360 | | * |
1361 | | * This dissector swaps the ordering of the bits in each byte before using the |
1362 | | * normal entry point. |
1363 | | */ |
1364 | | static void |
1365 | | dissect_h223_bitswapped_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, conversation_type ctype, uint32_t circuit_id) |
1366 | 0 | { |
1367 | 0 | tvbuff_t *reversed_tvb; |
1368 | 0 | uint8_t *datax; |
1369 | 0 | unsigned len; |
1370 | |
|
1371 | 0 | len = tvb_reported_length(tvb); |
1372 | 0 | datax = (uint8_t *) tvb_memdup(pinfo->pool, tvb, 0, len); |
1373 | 0 | bitswap_buf_inplace(datax, len); |
1374 | | |
1375 | | /* |
1376 | | * Add the reversed tvbuff to the list of tvbuffs to which |
1377 | | * the tvbuff we were handed refers, so it'll get |
1378 | | * cleaned up when that tvbuff is cleaned up. |
1379 | | */ |
1380 | 0 | reversed_tvb = tvb_new_child_real_data(tvb, datax,len,tvb_reported_length(tvb)); |
1381 | | |
1382 | | /* Add the reversed data to the data source list. */ |
1383 | 0 | add_new_data_source(pinfo, reversed_tvb, "Bit-swapped H.223 frame" ); |
1384 | |
|
1385 | 0 | dissect_h223_common(reversed_tvb,pinfo,tree,ctype,circuit_id); |
1386 | 0 | } |
1387 | | |
1388 | | static int |
1389 | | dissect_h223_bitswapped_circuit_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
1390 | 0 | { |
1391 | 0 | iax2_dissector_info_t circuit_info; |
1392 | |
|
1393 | 0 | DISSECTOR_ASSERT(data); |
1394 | 0 | circuit_info = *((iax2_dissector_info_t*)data); |
1395 | |
|
1396 | 0 | dissect_h223_bitswapped_common(tvb, pinfo, tree, circuit_info.ctype, circuit_info.circuit_id); |
1397 | 0 | return tvb_captured_length(tvb); |
1398 | 0 | } |
1399 | | |
1400 | | static int |
1401 | | dissect_h223_bitswapped(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
1402 | 0 | { |
1403 | 0 | dissect_h223_bitswapped_common(tvb, pinfo, tree, CONVERSATION_NONE, 0); |
1404 | 0 | return tvb_captured_length(tvb); |
1405 | 0 | } |
1406 | | |
1407 | | /******************************************************************************/ |
1408 | | |
1409 | | |
1410 | | void proto_register_h223 (void) |
1411 | 15 | { |
1412 | | /* A header field is something you can search/filter on. |
1413 | | * |
1414 | | * We create a structure to register our fields. It consists of an |
1415 | | * array of hf_register_info structures, each of which are of the format |
1416 | | * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}. |
1417 | | */ |
1418 | | |
1419 | 15 | static hf_register_info hf[] = { |
1420 | | #if 0 |
1421 | | { &hf_h223_non_h223_data, |
1422 | | { "Non-H.223 data", "h223.non-h223", FT_NONE, BASE_NONE, NULL, 0x0, |
1423 | | "Initial data in stream, not a PDU", HFILL }}, |
1424 | | #endif |
1425 | | |
1426 | 15 | { &hf_h223_mux_stuffing_pdu, |
1427 | 15 | { "H.223 stuffing PDU", "h223.mux.stuffing", FT_NONE, BASE_NONE, NULL, 0x0, |
1428 | 15 | "Empty PDU used for stuffing when no data available", HFILL }}, |
1429 | | |
1430 | 15 | { &hf_h223_mux_pdu, |
1431 | 15 | { "H.223 MUX-PDU", "h223.mux", FT_NONE, BASE_NONE, NULL, 0x0, |
1432 | 15 | NULL, HFILL }}, |
1433 | | |
1434 | 15 | { &hf_h223_mux_header, |
1435 | 15 | { "Header", "h223.mux.header", FT_NONE, BASE_NONE, NULL, 0x0, |
1436 | 15 | "H.223 MUX header", HFILL }}, |
1437 | | |
1438 | 15 | { &hf_h223_mux_rawhdr, |
1439 | 15 | { "Raw value", "h223.mux.rawhdr", FT_UINT24, BASE_HEX, NULL, 0x0, |
1440 | 15 | "Raw header bytes", HFILL }}, |
1441 | | |
1442 | 15 | { &hf_h223_mux_correctedhdr, |
1443 | 15 | { "Corrected value", "h223.mux.correctedhdr", FT_UINT24, BASE_HEX, NULL, 0x0, |
1444 | 15 | "Corrected header bytes", HFILL }}, |
1445 | | |
1446 | 15 | { &hf_h223_mux_mc, |
1447 | 15 | { "Multiplex Code", "h223.mux.mc", FT_UINT8, BASE_DEC, NULL, 0x0f, |
1448 | 15 | "H.223 MUX multiplex code", HFILL }}, |
1449 | | |
1450 | 15 | { &hf_h223_mux_mpl, |
1451 | 15 | { "Multiplex Payload Length", "h223.mux.mpl", FT_UINT16, BASE_DEC, NULL, 0xf00f, |
1452 | 15 | "H.223 MUX multiplex Payload Length", HFILL }}, |
1453 | | |
1454 | 15 | { &hf_h223_mux_deact, |
1455 | 15 | { "Deactivated multiplex table entry", "h223.mux.deactivated", FT_NONE, BASE_NONE, NULL, 0x0, |
1456 | 15 | "mpl refers to an entry in the multiplex table which is not active", HFILL }}, |
1457 | | |
1458 | 15 | { &hf_h223_mux_vc, |
1459 | 15 | { "H.223 virtual circuit", "h223.mux.vc", FT_UINT16, BASE_DEC, NULL, 0x0, |
1460 | 15 | NULL, HFILL }}, |
1461 | | |
1462 | 15 | { &hf_h223_mux_extra, |
1463 | 15 | { "Extraneous data", "h223.mux.extra", FT_NONE, BASE_NONE, NULL, 0x0, |
1464 | 15 | "data beyond mpl", HFILL }}, |
1465 | | |
1466 | 15 | { &hf_h223_mux_hdlc2, |
1467 | 15 | { "HDLC flag", "h223.mux.hdlc", FT_UINT16, BASE_HEX, NULL, 0x0, |
1468 | 15 | "framing flag", HFILL }}, |
1469 | | |
1470 | | /* fields for h.223-mux fragments */ |
1471 | 15 | { &hf_h223_mux_fragment_overlap, |
1472 | 15 | { "Fragment overlap", "h223.mux.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1473 | 15 | "Fragment overlaps with other fragments", HFILL }}, |
1474 | | |
1475 | 15 | { &hf_h223_mux_fragment_overlap_conflict, |
1476 | 15 | { "Conflicting data in fragment overlap", "h223.mux.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1477 | 15 | "Overlapping fragments contained conflicting data", HFILL }}, |
1478 | | |
1479 | 15 | { &hf_h223_mux_fragment_multiple_tails, |
1480 | 15 | { "Multiple tail fragments found", "h223.mux.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1481 | 15 | "Several tails were found when defragmenting the packet", HFILL }}, |
1482 | | |
1483 | 15 | { &hf_h223_mux_fragment_too_long_fragment, |
1484 | 15 | { "Fragment too long", "h223.mux.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1485 | 15 | "Fragment contained data past end of packet", HFILL }}, |
1486 | | |
1487 | 15 | { &hf_h223_mux_fragment_error, |
1488 | 15 | { "Defragmentation error", "h223.mux.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
1489 | 15 | "Defragmentation error due to illegal fragments", HFILL }}, |
1490 | | |
1491 | 15 | { &hf_h223_mux_fragment_count, |
1492 | 15 | { "Fragment count", "h223.mux.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0, |
1493 | 15 | NULL, HFILL }}, |
1494 | | |
1495 | 15 | { &hf_h223_mux_fragment, |
1496 | 15 | { "H.223 MUX-PDU Fragment", "h223.mux.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
1497 | 15 | NULL, HFILL }}, |
1498 | | |
1499 | 15 | { &hf_h223_mux_fragments, |
1500 | 15 | { "H.223 MUX-PDU Fragments", "h223.mux.fragments", FT_NONE, BASE_NONE, NULL, 0x0, |
1501 | 15 | NULL, HFILL }}, |
1502 | | |
1503 | 15 | { &hf_h223_mux_reassembled_in, |
1504 | 15 | { "MUX-PDU fragment, reassembled in frame", "h223.mux.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
1505 | 15 | "This H.223 MUX-PDU packet is reassembled in this frame", HFILL }}, |
1506 | | |
1507 | 15 | { &hf_h223_mux_reassembled_length, |
1508 | 15 | { "Reassembled H.223 MUX-PDU length", "h223.mux.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0, |
1509 | 15 | "The total length of the reassembled payload", HFILL }}, |
1510 | | |
1511 | | /* fields for h.223-al fragments */ |
1512 | 15 | { &hf_h223_al_fragment_overlap, |
1513 | 15 | { "Fragment overlap", "h223.al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1514 | 15 | "Fragment overlaps with other fragments", HFILL }}, |
1515 | | |
1516 | 15 | { &hf_h223_al_fragment_overlap_conflict, |
1517 | 15 | { "Conflicting data in fragment overlap", "h223.al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1518 | 15 | "Overlapping fragments contained conflicting data", HFILL }}, |
1519 | | |
1520 | 15 | { &hf_h223_al_fragment_multiple_tails, |
1521 | 15 | { "Multiple tail fragments found", "h223.al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1522 | 15 | "Several tails were found when defragmenting the packet", HFILL }}, |
1523 | | |
1524 | 15 | { &hf_h223_al_fragment_too_long_fragment, |
1525 | 15 | { "Fragment too long", "h223.al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1526 | 15 | "Fragment contained data past end of packet", HFILL }}, |
1527 | | |
1528 | 15 | { &hf_h223_al_fragment_error, |
1529 | 15 | { "Defragmentation error", "h223.al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
1530 | 15 | "Defragmentation error due to illegal fragments", HFILL }}, |
1531 | | |
1532 | 15 | { &hf_h223_al_fragment_count, |
1533 | 15 | { "Fragment count", "h223.al.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0, |
1534 | 15 | NULL, HFILL }}, |
1535 | | |
1536 | 15 | { &hf_h223_al_fragment, |
1537 | 15 | { "H.223 AL-PDU Fragment", "h223.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
1538 | 15 | NULL, HFILL }}, |
1539 | | |
1540 | 15 | { &hf_h223_al_fragments, |
1541 | 15 | { "H.223 AL-PDU Fragments", "h223.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0, |
1542 | 15 | NULL, HFILL }}, |
1543 | | |
1544 | 15 | { &hf_h223_al_reassembled_in, |
1545 | 15 | { "AL-PDU fragment, reassembled in frame", "h223.al.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
1546 | 15 | "This H.223 AL-PDU packet is reassembled in this frame", HFILL }}, |
1547 | | |
1548 | 15 | { &hf_h223_al_reassembled_length, |
1549 | 15 | { "Reassembled H.223 AL-PDU length", "h223.al.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0, |
1550 | 15 | "The total length of the reassembled payload", HFILL }}, |
1551 | | |
1552 | | /* h223-als */ |
1553 | | |
1554 | 15 | { &hf_h223_al1, |
1555 | 15 | { "H.223 AL1", "h223.al1", FT_NONE, BASE_NONE, NULL, 0x0, |
1556 | 15 | "H.223 AL-PDU using AL1", HFILL }}, |
1557 | | |
1558 | 15 | { &hf_h223_al1_framed, |
1559 | 15 | { "H.223 AL1 framing", "h223.al1.framed", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1560 | 15 | NULL, HFILL }}, |
1561 | | |
1562 | 15 | { &hf_h223_al2, |
1563 | 15 | { "H.223 AL2", "h223.al2", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1564 | 15 | "H.223 AL-PDU using AL2", HFILL }}, |
1565 | | |
1566 | 15 | { &hf_h223_al2_sequenced, |
1567 | 15 | { "H.223 sequenced AL2", "h223.sequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0, |
1568 | 15 | "H.223 AL-PDU using AL2 with sequence numbers", HFILL }}, |
1569 | | |
1570 | 15 | { &hf_h223_al2_unsequenced, |
1571 | 15 | { "H.223 unsequenced AL2", "h223.unsequenced_al2", FT_NONE, BASE_NONE, NULL, 0x0, |
1572 | 15 | "H.223 AL-PDU using AL2 without sequence numbers", HFILL }}, |
1573 | | |
1574 | 15 | { &hf_h223_al2_seqno, |
1575 | 15 | { "Sequence Number", "h223.al2.seqno", FT_UINT8, BASE_DEC, NULL, 0x0, |
1576 | 15 | "H.223 AL2 sequence number", HFILL }}, |
1577 | | |
1578 | 15 | { &hf_h223_al2_crc, |
1579 | 15 | { "CRC", "h223.al2.crc", FT_UINT8, BASE_HEX, NULL, 0x0, |
1580 | 15 | NULL, HFILL }}, |
1581 | | |
1582 | 15 | { &hf_h223_al2_crc_status, |
1583 | 15 | { "CRC Status","h223.al2.crc.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, |
1584 | 15 | NULL, HFILL }}, |
1585 | | |
1586 | 15 | { &hf_h223_al_payload, |
1587 | 15 | { "H.223 AL Payload", "h223.al.payload", FT_NONE, BASE_NONE, NULL, 0x0, |
1588 | 15 | "H.223 AL-PDU Payload", HFILL }}, |
1589 | | |
1590 | 15 | }; |
1591 | | |
1592 | 15 | static int *ett[] = { |
1593 | 15 | &ett_h223, |
1594 | 15 | &ett_h223_non_h223_data, |
1595 | 15 | &ett_h223_mux_stuffing_pdu, |
1596 | 15 | &ett_h223_mux_pdu, |
1597 | 15 | &ett_h223_mux_header, |
1598 | 15 | &ett_h223_mux_deact, |
1599 | 15 | &ett_h223_mux_vc, |
1600 | 15 | &ett_h223_mux_extra, |
1601 | 15 | &ett_h223_mux_fragments, |
1602 | 15 | &ett_h223_mux_fragment, |
1603 | 15 | &ett_h223_al_fragments, |
1604 | 15 | &ett_h223_al_fragment, |
1605 | 15 | &ett_h223_al1, |
1606 | 15 | &ett_h223_al2, |
1607 | 15 | &ett_h223_al_payload |
1608 | 15 | }; |
1609 | | |
1610 | 15 | static ei_register_info ei[] = { |
1611 | 15 | { &ei_h223_al2_crc, { "h223.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, |
1612 | 15 | }; |
1613 | | |
1614 | 15 | expert_module_t* expert_h223; |
1615 | | |
1616 | 15 | proto_h223 = |
1617 | 15 | proto_register_protocol ("ITU-T Recommendation H.223", "H.223", "h223"); |
1618 | | /* Create a H.223 "placeholder" to remove confusion with Decode As" */ |
1619 | 15 | proto_h223_bitswapped = |
1620 | 15 | proto_register_protocol_in_name_only ("ITU-T Recommendation H.223 (Bitswapped)", "H.223 (Bitswapped)", "h223_bitswapped", proto_h223, FT_PROTOCOL); |
1621 | | |
1622 | 15 | proto_register_field_array (proto_h223, hf, array_length (hf)); |
1623 | 15 | proto_register_subtree_array (ett, array_length (ett)); |
1624 | 15 | expert_h223 = expert_register_protocol(proto_h223); |
1625 | 15 | expert_register_field_array(expert_h223, ei, array_length(ei)); |
1626 | | |
1627 | 15 | register_dissector("h223", dissect_h223_circuit_data, proto_h223); |
1628 | 15 | h223_bitswapped = register_dissector("h223_bitswapped", dissect_h223_bitswapped, proto_h223_bitswapped); |
1629 | | |
1630 | | /* register our init routine to be called at the start of a capture, |
1631 | | to clear out our hash tables etc */ |
1632 | 15 | register_init_routine(&circuit_chain_init); |
1633 | | |
1634 | 15 | circuit_chain_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), circuit_chain_hash, circuit_chain_equal); |
1635 | | |
1636 | 15 | h245_set_h223_set_mc_handle( &h223_set_mc ); |
1637 | 15 | h245_set_h223_add_lc_handle( &h223_add_lc ); |
1638 | 15 | } |
1639 | | |
1640 | | void proto_reg_handoff_h223(void) |
1641 | 15 | { |
1642 | 15 | data_handle = find_dissector("data"); |
1643 | 15 | srp_handle = find_dissector("srp"); |
1644 | | |
1645 | 15 | dissector_add_for_decode_as_with_preference("tcp.port", create_dissector_handle( dissect_h223, proto_h223)); |
1646 | 15 | dissector_add_for_decode_as_with_preference("tcp.port", h223_bitswapped); |
1647 | 15 | dissector_add_string("rtp_dyn_payload_type","CLEARMODE", h223_bitswapped); |
1648 | 15 | dissector_add_for_decode_as("rtp.pt", h223_bitswapped); |
1649 | 15 | dissector_add_uint("iax2.dataformat", AST_DATAFORMAT_H223_H245, create_dissector_handle(dissect_h223_bitswapped_circuit_data, proto_h223_bitswapped)); |
1650 | 15 | } |
1651 | | |
1652 | | /* |
1653 | | * Editor modelines |
1654 | | * |
1655 | | * Local Variables: |
1656 | | * c-basic-offset: 4 |
1657 | | * tab-width: 8 |
1658 | | * indent-tabs-mode: nil |
1659 | | * End: |
1660 | | * |
1661 | | * ex: set shiftwidth=4 tabstop=8 expandtab: |
1662 | | * :indentSize=4:tabSize=8:noTabs=true: |
1663 | | */ |