File: | epan/dissectors/packet-iax2.c |
Warning: | line 1459, column 13 Null pointer passed to 2nd parameter expecting 'nonnull' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * packet-iax2.c | |||
3 | * | |||
4 | * Routines for IAX2 packet disassembly | |||
5 | * By Alastair Maw <[email protected]> | |||
6 | * Copyright 2003 Alastair Maw | |||
7 | * | |||
8 | * IAX2 is a VoIP protocol for the open source PBX Asterisk. Please see | |||
9 | * http://www.asterisk.org for more information; see RFC 5456 for the | |||
10 | * protocol. | |||
11 | * | |||
12 | * Wireshark - Network traffic analyzer | |||
13 | * By Gerald Combs <[email protected]> | |||
14 | * Copyright 1998 Gerald Combs | |||
15 | * | |||
16 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
17 | */ | |||
18 | ||||
19 | #include "config.h" | |||
20 | ||||
21 | ||||
22 | #include <epan/packet.h> | |||
23 | #include <epan/conversation.h> | |||
24 | #include <epan/reassemble.h> | |||
25 | #include <epan/expert.h> | |||
26 | #include <epan/aftypes.h> | |||
27 | #include <epan/tap.h> | |||
28 | #include <epan/proto_data.h> | |||
29 | #include <epan/tfs.h> | |||
30 | #include <wsutil/array.h> | |||
31 | #include <wsutil/str_util.h> | |||
32 | ||||
33 | #include "packet-iax2.h" | |||
34 | #include <epan/iax2_codec_type.h> | |||
35 | ||||
36 | void proto_register_iax2(void); | |||
37 | void proto_reg_handoff_iax2(void); | |||
38 | ||||
39 | #define IAX2_PORT4569 4569 | |||
40 | #define PROTO_TAG_IAX2"IAX2" "IAX2" | |||
41 | ||||
42 | /* enough to hold any address in an address_t */ | |||
43 | #define MAX_ADDRESS16 16 | |||
44 | ||||
45 | /* the maximum number of transfers (of each end) we can deal with per call, | |||
46 | * plus one */ | |||
47 | #define IAX_MAX_TRANSFERS2 2 | |||
48 | ||||
49 | /* #define DEBUG_HASHING */ | |||
50 | /* #define DEBUG_DESEGMENT */ | |||
51 | ||||
52 | /* Wireshark ID of the IAX2 protocol */ | |||
53 | static int proto_iax2; | |||
54 | ||||
55 | /* tap register id */ | |||
56 | static int iax2_tap; | |||
57 | ||||
58 | /* protocol tap info */ | |||
59 | static iax2_info_t ii_arr[1]; | |||
60 | static iax2_info_t *iax2_info = ii_arr; | |||
61 | ||||
62 | /* The following hf_* variables are used to hold the wireshark IDs of | |||
63 | * our header fields; they are filled out when we call | |||
64 | * proto_register_field_array() in proto_register_iax2() | |||
65 | */ | |||
66 | static int hf_iax2_packet_type; | |||
67 | static int hf_iax2_retransmission; | |||
68 | static int hf_iax2_callno; | |||
69 | static int hf_iax2_scallno; | |||
70 | static int hf_iax2_dcallno; | |||
71 | static int hf_iax2_ts; | |||
72 | static int hf_iax2_minits; | |||
73 | static int hf_iax2_minividts; | |||
74 | static int hf_iax2_absts; | |||
75 | static int hf_iax2_lateness; | |||
76 | static int hf_iax2_minividmarker; | |||
77 | static int hf_iax2_oseqno; | |||
78 | static int hf_iax2_iseqno; | |||
79 | static int hf_iax2_type; | |||
80 | static int hf_iax2_csub; | |||
81 | static int hf_iax2_dtmf_csub; | |||
82 | static int hf_iax2_cmd_csub; | |||
83 | static int hf_iax2_iax_csub; | |||
84 | static int hf_iax2_voice_csub; | |||
85 | static int hf_iax2_voice_codec; | |||
86 | static int hf_iax2_video_csub; | |||
87 | static int hf_iax2_video_codec; | |||
88 | static int hf_iax2_marker; | |||
89 | static int hf_iax2_modem_csub; | |||
90 | static int hf_iax2_text_csub; | |||
91 | static int hf_iax2_text_text; | |||
92 | static int hf_iax2_html_csub; | |||
93 | static int hf_iax2_html_url; | |||
94 | static int hf_iax2_trunk_metacmd; | |||
95 | static int hf_iax2_trunk_cmddata; | |||
96 | static int hf_iax2_trunk_cmddata_ts; | |||
97 | static int hf_iax2_trunk_ts; | |||
98 | static int hf_iax2_trunk_ncalls; | |||
99 | static int hf_iax2_trunk_call_len; | |||
100 | static int hf_iax2_trunk_call_scallno; | |||
101 | static int hf_iax2_trunk_call_ts; | |||
102 | static int hf_iax2_trunk_call_data; | |||
103 | ||||
104 | static int hf_iax2_ie_id; | |||
105 | static int hf_iax2_length; | |||
106 | static int hf_iax2_version; | |||
107 | static int hf_iax2_cap_g723_1; | |||
108 | static int hf_iax2_cap_gsm; | |||
109 | static int hf_iax2_cap_ulaw; | |||
110 | static int hf_iax2_cap_alaw; | |||
111 | static int hf_iax2_cap_g726_aal2; | |||
112 | static int hf_iax2_cap_adpcm; | |||
113 | static int hf_iax2_cap_slinear; | |||
114 | static int hf_iax2_cap_lpc10; | |||
115 | static int hf_iax2_cap_g729a; | |||
116 | static int hf_iax2_cap_speex; | |||
117 | static int hf_iax2_cap_ilbc; | |||
118 | static int hf_iax2_cap_g726; | |||
119 | static int hf_iax2_cap_g722; | |||
120 | static int hf_iax2_cap_siren7; | |||
121 | static int hf_iax2_cap_siren14; | |||
122 | static int hf_iax2_cap_slinear16; | |||
123 | static int hf_iax2_cap_jpeg; | |||
124 | static int hf_iax2_cap_png; | |||
125 | static int hf_iax2_cap_h261; | |||
126 | static int hf_iax2_cap_h263; | |||
127 | static int hf_iax2_cap_h263_plus; | |||
128 | static int hf_iax2_cap_h264; | |||
129 | static int hf_iax2_cap_mpeg4; | |||
130 | static int hf_iax2_cap_vp8; | |||
131 | static int hf_iax2_cap_t140_red; | |||
132 | static int hf_iax2_cap_t140; | |||
133 | static int hf_iax2_cap_g719; | |||
134 | static int hf_iax2_cap_speex16; | |||
135 | static int hf_iax2_cap_opus; | |||
136 | static int hf_iax2_cap_testlaw; | |||
137 | ||||
138 | static int * const hf_iax2_caps[] = { | |||
139 | &hf_iax2_cap_g723_1, | |||
140 | &hf_iax2_cap_gsm, | |||
141 | &hf_iax2_cap_ulaw, | |||
142 | &hf_iax2_cap_alaw, | |||
143 | &hf_iax2_cap_g726_aal2, | |||
144 | &hf_iax2_cap_adpcm, | |||
145 | &hf_iax2_cap_slinear, | |||
146 | &hf_iax2_cap_lpc10, | |||
147 | &hf_iax2_cap_g729a, | |||
148 | &hf_iax2_cap_speex, | |||
149 | &hf_iax2_cap_ilbc, | |||
150 | &hf_iax2_cap_g726, | |||
151 | &hf_iax2_cap_g722, | |||
152 | &hf_iax2_cap_siren7, | |||
153 | &hf_iax2_cap_siren14, | |||
154 | &hf_iax2_cap_slinear16, | |||
155 | &hf_iax2_cap_jpeg, | |||
156 | &hf_iax2_cap_png, | |||
157 | &hf_iax2_cap_h261, | |||
158 | &hf_iax2_cap_h263, | |||
159 | &hf_iax2_cap_h263_plus, | |||
160 | &hf_iax2_cap_h264, | |||
161 | &hf_iax2_cap_mpeg4, | |||
162 | &hf_iax2_cap_vp8, | |||
163 | &hf_iax2_cap_t140_red, | |||
164 | &hf_iax2_cap_t140, | |||
165 | &hf_iax2_cap_g719, | |||
166 | &hf_iax2_cap_speex16, | |||
167 | &hf_iax2_cap_opus, | |||
168 | &hf_iax2_cap_testlaw, | |||
169 | NULL((void*)0) | |||
170 | }; | |||
171 | ||||
172 | static int hf_iax2_fragment_unfinished; | |||
173 | static int hf_iax2_payload_data; | |||
174 | static int hf_iax2_fragments; | |||
175 | static int hf_iax2_fragment; | |||
176 | static int hf_iax2_fragment_overlap; | |||
177 | static int hf_iax2_fragment_overlap_conflict; | |||
178 | static int hf_iax2_fragment_multiple_tails; | |||
179 | static int hf_iax2_fragment_too_long_fragment; | |||
180 | static int hf_iax2_fragment_error; | |||
181 | static int hf_iax2_fragment_count; | |||
182 | static int hf_iax2_reassembled_in; | |||
183 | static int hf_iax2_reassembled_length; | |||
184 | ||||
185 | ||||
186 | /* hf_iax2_ies is an array of header fields, one per potential Information | |||
187 | * Element. It's done this way (rather than having separate variables for each | |||
188 | * IE) to make the dissection of information elements clearer and more | |||
189 | * orthogonal. | |||
190 | * | |||
191 | * To add the ability to dissect a new information element, just add an | |||
192 | * appropriate entry to hf[] in proto_register_iax2(); dissect_ies() will then | |||
193 | * pick it up automatically. | |||
194 | */ | |||
195 | #define NUM_HF_IAX2_IES256 256 | |||
196 | static int hf_iax2_ies[NUM_HF_IAX2_IES256]; | |||
197 | static int hf_iax2_ie_datetime; | |||
198 | static int hf_IAX_IE_APPARENTADDR_SINFAMILY; | |||
199 | static int hf_IAX_IE_APPARENTADDR_SINPORT; | |||
200 | static int hf_IAX_IE_APPARENTADDR_SINADDR; | |||
201 | static int hf_IAX_IE_UNKNOWN_BYTE; | |||
202 | static int hf_IAX_IE_UNKNOWN_I16; | |||
203 | static int hf_IAX_IE_UNKNOWN_I32; | |||
204 | static int hf_IAX_IE_UNKNOWN_BYTES; | |||
205 | ||||
206 | /* These are the ids of the subtrees that we may be creating */ | |||
207 | static int ett_iax2; | |||
208 | static int ett_iax2_full_mini_subtree; | |||
209 | static int ett_iax2_type; /* Frame-type specific subtree */ | |||
210 | static int ett_iax2_ie; /* single IE */ | |||
211 | static int ett_iax2_codecs; /* capabilities IE */ | |||
212 | static int ett_iax2_ies_apparent_addr; /* apparent address IE */ | |||
213 | static int ett_iax2_fragment; | |||
214 | static int ett_iax2_fragments; | |||
215 | static int ett_iax2_trunk_cmddata; | |||
216 | static int ett_iax2_trunk_call; | |||
217 | ||||
218 | static expert_field ei_iax_too_many_transfers; | |||
219 | static expert_field ei_iax_circuit_id_conflict; | |||
220 | static expert_field ei_iax_peer_address_unsupported; | |||
221 | static expert_field ei_iax_invalid_len; | |||
222 | ||||
223 | static dissector_handle_t iax2_handle; | |||
224 | ||||
225 | static const fragment_items iax2_fragment_items = { | |||
226 | &ett_iax2_fragment, | |||
227 | &ett_iax2_fragments, | |||
228 | &hf_iax2_fragments, | |||
229 | &hf_iax2_fragment, | |||
230 | &hf_iax2_fragment_overlap, | |||
231 | &hf_iax2_fragment_overlap_conflict, | |||
232 | &hf_iax2_fragment_multiple_tails, | |||
233 | &hf_iax2_fragment_too_long_fragment, | |||
234 | &hf_iax2_fragment_error, | |||
235 | &hf_iax2_fragment_count, | |||
236 | &hf_iax2_reassembled_in, | |||
237 | &hf_iax2_reassembled_length, | |||
238 | /* Reassembled data field */ | |||
239 | NULL((void*)0), | |||
240 | "iax2 fragments" | |||
241 | }; | |||
242 | ||||
243 | /* data-call subdissectors, AST_DATAFORMAT_* */ | |||
244 | static dissector_table_t iax2_dataformat_dissector_table; | |||
245 | /* voice/video call subdissectors, AST_FORMAT_* */ | |||
246 | static dissector_table_t iax2_codec_dissector_table; | |||
247 | ||||
248 | ||||
249 | /* IAX2 Meta trunk packet Command data flags */ | |||
250 | #define IAX2_TRUNK_TS1 1 | |||
251 | ||||
252 | /* IAX2 Full-frame types */ | |||
253 | static const value_string iax_frame_types[] = { | |||
254 | {0, "(0?)"}, | |||
255 | {AST_FRAME_DTMF_END1, "DTMF End"}, | |||
256 | {AST_FRAME_VOICE2, "Voice"}, | |||
257 | {AST_FRAME_VIDEO3, "Video"}, | |||
258 | {AST_FRAME_CONTROL4, "Control"}, | |||
259 | {AST_FRAME_NULL5, "NULL"}, | |||
260 | {AST_FRAME_IAX6, "IAX"}, | |||
261 | {AST_FRAME_TEXT7, "Text"}, | |||
262 | {AST_FRAME_IMAGE8, "Image"}, | |||
263 | {AST_FRAME_HTML9, "HTML"}, | |||
264 | {AST_FRAME_CNG10, "Comfort Noise"}, | |||
265 | {AST_FRAME_MODEM11, "Modem"}, | |||
266 | {AST_FRAME_DTMF_BEGIN12, "DTMF Begin"}, | |||
267 | {0, NULL((void*)0)} | |||
268 | }; | |||
269 | static value_string_ext iax_frame_types_ext = VALUE_STRING_EXT_INIT(iax_frame_types){ _try_val_to_str_ext_init, 0, (sizeof (iax_frame_types) / sizeof ((iax_frame_types)[0]))-1, iax_frame_types, "iax_frame_types" , ((void*)0) }; | |||
270 | ||||
271 | /* Subclasses for IAX packets */ | |||
272 | static const value_string iax_iax_subclasses[] = { | |||
273 | { 0, "(0?)"}, | |||
274 | { 1, "NEW"}, | |||
275 | { 2, "PING"}, | |||
276 | { 3, "PONG"}, | |||
277 | { 4, "ACK"}, | |||
278 | { 5, "HANGUP"}, | |||
279 | { 6, "REJECT"}, | |||
280 | { 7, "ACCEPT"}, | |||
281 | { 8, "AUTHREQ"}, | |||
282 | { 9, "AUTHREP"}, | |||
283 | {10, "INVAL"}, | |||
284 | {11, "LAGRQ"}, | |||
285 | {12, "LAGRP"}, | |||
286 | {13, "REGREQ"}, | |||
287 | {14, "REGAUTH"}, | |||
288 | {15, "REGACK"}, | |||
289 | {16, "REGREJ"}, | |||
290 | {17, "REGREL"}, | |||
291 | {18, "VNAK"}, | |||
292 | {19, "DPREQ"}, | |||
293 | {20, "DPREP"}, | |||
294 | {21, "DIAL"}, | |||
295 | {22, "TXREQ"}, | |||
296 | {23, "TXCNT"}, | |||
297 | {24, "TXACC"}, | |||
298 | {25, "TXREADY"}, | |||
299 | {26, "TXREL"}, | |||
300 | {27, "TXREJ"}, | |||
301 | {28, "QUELCH"}, | |||
302 | {29, "UNQULCH"}, | |||
303 | {30, "POKE"}, | |||
304 | {31, "PAGE"}, | |||
305 | {32, "MWI"}, | |||
306 | {33, "UNSUPPORTED"}, | |||
307 | {34, "TRANSFER"}, | |||
308 | {35, "PROVISION"}, | |||
309 | {36, "FWDOWNL"}, | |||
310 | {37, "FWDATA"}, | |||
311 | {38, "TXMEDIA"}, | |||
312 | {39, "RTKEY"}, | |||
313 | {40, "CALLTOKEN"}, | |||
314 | {0, NULL((void*)0)} | |||
315 | }; | |||
316 | static value_string_ext iax_iax_subclasses_ext = VALUE_STRING_EXT_INIT(iax_iax_subclasses){ _try_val_to_str_ext_init, 0, (sizeof (iax_iax_subclasses) / sizeof ((iax_iax_subclasses)[0]))-1, iax_iax_subclasses, "iax_iax_subclasses" , ((void*)0) }; | |||
317 | ||||
318 | /* Subclasses for Control packets */ | |||
319 | static const value_string iax_cmd_subclasses[] = { | |||
320 | {0, "(0?)"}, | |||
321 | {1, "HANGUP"}, | |||
322 | {2, "RING"}, | |||
323 | {3, "RINGING"}, | |||
324 | {4, "ANSWER"}, | |||
325 | {5, "BUSY"}, | |||
326 | {6, "TKOFFHK"}, | |||
327 | {7, "OFFHOOK"}, | |||
328 | {0xFF, "stop sounds"}, /* sent by app_dial, and not much else */ | |||
329 | {0, NULL((void*)0)} | |||
330 | }; | |||
331 | static value_string_ext iax_cmd_subclasses_ext = VALUE_STRING_EXT_INIT(iax_cmd_subclasses){ _try_val_to_str_ext_init, 0, (sizeof (iax_cmd_subclasses) / sizeof ((iax_cmd_subclasses)[0]))-1, iax_cmd_subclasses, "iax_cmd_subclasses" , ((void*)0) }; | |||
332 | ||||
333 | /* IAX2 to tap-voip call state mapping for command frames */ | |||
334 | static const voip_call_state tap_cmd_voip_state[] = { | |||
335 | VOIP_NO_STATE, | |||
336 | VOIP_COMPLETED, /*HANGUP*/ | |||
337 | VOIP_RINGING, /*RING*/ | |||
338 | VOIP_RINGING, /*RINGING*/ | |||
339 | VOIP_IN_CALL, /*ANSWER*/ | |||
340 | VOIP_REJECTED, /*BUSY*/ | |||
341 | VOIP_UNKNOWN, /*TKOFFHK*/ | |||
342 | VOIP_UNKNOWN /*OFFHOOK*/ | |||
343 | }; | |||
344 | #define NUM_TAP_CMD_VOIP_STATES(sizeof (tap_cmd_voip_state) / sizeof (tap_cmd_voip_state)[0] ) array_length(tap_cmd_voip_state)(sizeof (tap_cmd_voip_state) / sizeof (tap_cmd_voip_state)[0] ) | |||
345 | ||||
346 | /* IAX2 to tap-voip call state mapping for IAX frames */ | |||
347 | static const voip_call_state tap_iax_voip_state[] = { | |||
348 | VOIP_NO_STATE, | |||
349 | VOIP_CALL_SETUP, /*NEW*/ | |||
350 | VOIP_NO_STATE, | |||
351 | VOIP_NO_STATE, | |||
352 | VOIP_COMPLETED, /*HANGUP*/ | |||
353 | VOIP_REJECTED, /*REJECT*/ | |||
354 | VOIP_RINGING, /*ACCEPT*/ | |||
355 | VOIP_NO_STATE, | |||
356 | VOIP_NO_STATE, | |||
357 | VOIP_NO_STATE, | |||
358 | VOIP_NO_STATE, | |||
359 | VOIP_NO_STATE, | |||
360 | VOIP_NO_STATE, | |||
361 | VOIP_NO_STATE, | |||
362 | VOIP_NO_STATE, | |||
363 | VOIP_NO_STATE, | |||
364 | VOIP_NO_STATE, | |||
365 | VOIP_NO_STATE, | |||
366 | VOIP_NO_STATE, | |||
367 | VOIP_NO_STATE, | |||
368 | VOIP_NO_STATE, | |||
369 | VOIP_CALL_SETUP, /*DIAL*/ | |||
370 | VOIP_NO_STATE, | |||
371 | VOIP_NO_STATE, | |||
372 | VOIP_NO_STATE, | |||
373 | VOIP_NO_STATE, | |||
374 | VOIP_NO_STATE, | |||
375 | VOIP_NO_STATE, | |||
376 | VOIP_NO_STATE, | |||
377 | VOIP_NO_STATE, | |||
378 | VOIP_NO_STATE, | |||
379 | VOIP_NO_STATE, | |||
380 | VOIP_NO_STATE, | |||
381 | VOIP_NO_STATE, | |||
382 | VOIP_NO_STATE, | |||
383 | VOIP_NO_STATE, | |||
384 | VOIP_NO_STATE, | |||
385 | VOIP_NO_STATE | |||
386 | }; | |||
387 | ||||
388 | #define NUM_TAP_IAX_VOIP_STATES(sizeof (tap_iax_voip_state) / sizeof (tap_iax_voip_state)[0] ) array_length(tap_iax_voip_state)(sizeof (tap_iax_voip_state) / sizeof (tap_iax_voip_state)[0] ) | |||
389 | ||||
390 | /* Subclasses for Modem packets */ | |||
391 | static const value_string iax_modem_subclasses[] = { | |||
392 | {0, "(0?)"}, | |||
393 | {1, "T.38"}, | |||
394 | {2, "V.150"}, | |||
395 | {0, NULL((void*)0)} | |||
396 | }; | |||
397 | ||||
398 | /* Subclasses for Text packets */ | |||
399 | static const value_string iax_text_subclasses[] = { | |||
400 | {0, "Text"}, | |||
401 | {0, NULL((void*)0)} | |||
402 | }; | |||
403 | ||||
404 | /* Subclasses for HTML packets */ | |||
405 | static const value_string iax_html_subclasses[] = { | |||
406 | {0x01, "Sending a URL"}, | |||
407 | {0x02, "Data frame"}, | |||
408 | {0x04, "Beginning frame"}, | |||
409 | {0x08, "End frame"}, | |||
410 | {0x10, "Load is complete"}, | |||
411 | {0x11, "Peer does not support HTML"}, | |||
412 | {0x12, "Link URL"}, | |||
413 | {0x13, "Unlink URL"}, | |||
414 | {0x14, "Reject Link URL"}, | |||
415 | {0, NULL((void*)0)} | |||
416 | }; | |||
417 | ||||
418 | ||||
419 | /* Information elements */ | |||
420 | static const value_string iax_ies_type[] = { | |||
421 | {IAX_IE_CALLED_NUMBER1, "Number/extension being called"}, | |||
422 | {IAX_IE_CALLING_NUMBER2, "Calling number"}, | |||
423 | {IAX_IE_CALLING_ANI3, "Calling number ANI for billing"}, | |||
424 | {IAX_IE_CALLING_NAME4, "Name of caller"}, | |||
425 | {IAX_IE_CALLED_CONTEXT5, "Context for number"}, | |||
426 | {IAX_IE_USERNAME6, "Username (peer or user) for authentication"}, | |||
427 | {IAX_IE_PASSWORD7, "Password for authentication"}, | |||
428 | {IAX_IE_CAPABILITY8, "Actual codec capability"}, | |||
429 | {IAX_IE_FORMAT9, "Desired codec format"}, | |||
430 | {IAX_IE_LANGUAGE10, "Desired language"}, | |||
431 | {IAX_IE_VERSION11, "Protocol version"}, | |||
432 | {IAX_IE_ADSICPE12, "CPE ADSI capability"}, | |||
433 | {IAX_IE_DNID13, "Originally dialed DNID"}, | |||
434 | {IAX_IE_AUTHMETHODS14, "Authentication method(s)"}, | |||
435 | {IAX_IE_CHALLENGE15, "Challenge data for MD5/RSA"}, | |||
436 | {IAX_IE_MD5_RESULT16, "MD5 challenge result"}, | |||
437 | {IAX_IE_RSA_RESULT17, "RSA challenge result"}, | |||
438 | {IAX_IE_APPARENT_ADDR18, "Apparent address of peer"}, | |||
439 | {IAX_IE_REFRESH19, "When to refresh registration"}, | |||
440 | {IAX_IE_DPSTATUS20, "Dialplan status"}, | |||
441 | {IAX_IE_CALLNO21, "Call number of peer"}, | |||
442 | {IAX_IE_CAUSE22, "Cause"}, | |||
443 | {IAX_IE_IAX_UNKNOWN23, "Unknown IAX command"}, | |||
444 | {IAX_IE_MSGCOUNT24, "How many messages waiting"}, | |||
445 | {IAX_IE_AUTOANSWER25, "Request auto-answering"}, | |||
446 | {IAX_IE_MUSICONHOLD26, "Request musiconhold with QUELCH"}, | |||
447 | {IAX_IE_TRANSFERID27, "Transfer Request Identifier"}, | |||
448 | {IAX_IE_RDNIS28, "Referring DNIS"}, | |||
449 | {IAX_IE_PROVISIONING29, "Provisioning info"}, | |||
450 | {IAX_IE_AESPROVISIONING30, "AES Provisioning info"}, | |||
451 | {IAX_IE_DATETIME31, "Date/Time"}, | |||
452 | {IAX_IE_DEVICETYPE32, "Device type"}, | |||
453 | {IAX_IE_SERVICEIDENT33, "Service Identifier"}, | |||
454 | {IAX_IE_FIRMWAREVER34, "Firmware revision"}, | |||
455 | {IAX_IE_FWBLOCKDESC35, "Firmware block description"}, | |||
456 | {IAX_IE_FWBLOCKDATA36, "Firmware block of data"}, | |||
457 | {IAX_IE_PROVVER37, "Provisioning version"}, | |||
458 | {IAX_IE_CALLINGPRES38, "Calling presentation"}, | |||
459 | {IAX_IE_CALLINGTON39, "Calling type of number"}, | |||
460 | {IAX_IE_CALLINGTNS40, "Calling transit network select"}, | |||
461 | {IAX_IE_SAMPLINGRATE41, "Supported sampling rates"}, | |||
462 | {IAX_IE_CAUSECODE42, "Hangup cause"}, | |||
463 | {IAX_IE_ENCRYPTION43, "Encryption format"}, | |||
464 | {IAX_IE_ENCKEY44, "Raw encryption key"}, | |||
465 | {IAX_IE_CODEC_PREFS45, "Codec preferences"}, | |||
466 | {IAX_IE_RR_JITTER46, "Received jitter"}, | |||
467 | {IAX_IE_RR_LOSS47, "Received loss"}, | |||
468 | {IAX_IE_RR_PKTS48, "Received frames"}, | |||
469 | {IAX_IE_RR_DELAY49, "Max playout delay in ms for received frames"}, | |||
470 | {IAX_IE_RR_DROPPED50, "Dropped frames"}, | |||
471 | {IAX_IE_RR_OOO51, "Frames received out of order"}, | |||
472 | {IAX_IE_VARIABLE52, "IAX2 variable"}, | |||
473 | {IAX_IE_OSPTOKEN53, "OSP Token"}, | |||
474 | {IAX_IE_CALLTOKEN54, "Call Token"}, | |||
475 | {IAX_IE_CAPABILITY255, "64-bit codec capability"}, | |||
476 | {IAX_IE_FORMAT256, "64-bit codec format"}, | |||
477 | {IAX_IE_DATAFORMAT255, "Data call format"}, | |||
478 | {0, NULL((void*)0)} | |||
479 | }; | |||
480 | static value_string_ext iax_ies_type_ext = VALUE_STRING_EXT_INIT(iax_ies_type){ _try_val_to_str_ext_init, 0, (sizeof (iax_ies_type) / sizeof ((iax_ies_type)[0]))-1, iax_ies_type, "iax_ies_type", ((void *)0) }; | |||
481 | ||||
482 | #define CODEC_MASK(codec)((codec) == (uint32_t)-1 ? 0 : (1UL << (codec))) ((codec) == (uint32_t)-1 ? 0 : (UINT64_C(1)1UL << (codec))) | |||
483 | ||||
484 | static const val64_string codec_types[] = { | |||
485 | {CODEC_MASK(AST_FORMAT_G723_1)((0) == (uint32_t)-1 ? 0 : (1UL << (0))), "G.723.1 compression"}, | |||
486 | {CODEC_MASK(AST_FORMAT_GSM)((1) == (uint32_t)-1 ? 0 : (1UL << (1))), "GSM compression"}, | |||
487 | {CODEC_MASK(AST_FORMAT_ULAW)((2) == (uint32_t)-1 ? 0 : (1UL << (2))), "Raw mu-law data (G.711)"}, | |||
488 | {CODEC_MASK(AST_FORMAT_ALAW)((3) == (uint32_t)-1 ? 0 : (1UL << (3))), "Raw A-law data (G.711)"}, | |||
489 | {CODEC_MASK(AST_FORMAT_G726_AAL2)((4) == (uint32_t)-1 ? 0 : (1UL << (4))), "ADPCM (G.726), 32kbps, AAL2 codeword packing)"}, | |||
490 | {CODEC_MASK(AST_FORMAT_ADPCM)((5) == (uint32_t)-1 ? 0 : (1UL << (5))), "ADPCM (IMA)"}, | |||
491 | {CODEC_MASK(AST_FORMAT_SLINEAR)((6) == (uint32_t)-1 ? 0 : (1UL << (6))), "Raw 16-bit Signed Linear (8000 Hz) PCM"}, | |||
492 | {CODEC_MASK(AST_FORMAT_LPC10)((7) == (uint32_t)-1 ? 0 : (1UL << (7))), "LPC10, 180 samples/frame"}, | |||
493 | {CODEC_MASK(AST_FORMAT_G729A)((8) == (uint32_t)-1 ? 0 : (1UL << (8))), "G.729a Audio"}, | |||
494 | {CODEC_MASK(AST_FORMAT_SPEEX)((9) == (uint32_t)-1 ? 0 : (1UL << (9))), "SpeeX Free Compression"}, | |||
495 | {CODEC_MASK(AST_FORMAT_ILBC)((10) == (uint32_t)-1 ? 0 : (1UL << (10))), "iLBC Free Compression"}, | |||
496 | {CODEC_MASK(AST_FORMAT_G726)((11) == (uint32_t)-1 ? 0 : (1UL << (11))), "ADPCM (G.726, 32kbps, RFC3551 codeword packing)"}, | |||
497 | {CODEC_MASK(AST_FORMAT_G722)((12) == (uint32_t)-1 ? 0 : (1UL << (12))), "G.722"}, | |||
498 | {CODEC_MASK(AST_FORMAT_SIREN7)((13) == (uint32_t)-1 ? 0 : (1UL << (13))), "G.722.1 (also known as Siren7, 32kbps assumed)"}, | |||
499 | {CODEC_MASK(AST_FORMAT_SIREN14)((14) == (uint32_t)-1 ? 0 : (1UL << (14))), "G.722.1 Annex C (also known as Siren14, 48kbps assumed)"}, | |||
500 | {CODEC_MASK(AST_FORMAT_SLINEAR16)((15) == (uint32_t)-1 ? 0 : (1UL << (15))), "Raw 16-bit Signed Linear (16000 Hz) PCM"}, | |||
501 | {CODEC_MASK(AST_FORMAT_JPEG)((16) == (uint32_t)-1 ? 0 : (1UL << (16))), "JPEG Images"}, | |||
502 | {CODEC_MASK(AST_FORMAT_PNG)((17) == (uint32_t)-1 ? 0 : (1UL << (17))), "PNG Images"}, | |||
503 | {CODEC_MASK(AST_FORMAT_H261)((18) == (uint32_t)-1 ? 0 : (1UL << (18))), "H.261 Video"}, | |||
504 | {CODEC_MASK(AST_FORMAT_H263)((19) == (uint32_t)-1 ? 0 : (1UL << (19))), "H.263 Video"}, | |||
505 | {CODEC_MASK(AST_FORMAT_H263_PLUS)((20) == (uint32_t)-1 ? 0 : (1UL << (20))), "H.263+ Video"}, | |||
506 | {CODEC_MASK(AST_FORMAT_H264)((21) == (uint32_t)-1 ? 0 : (1UL << (21))), "H.264 Video"}, | |||
507 | {CODEC_MASK(AST_FORMAT_MP4_VIDEO)((22) == (uint32_t)-1 ? 0 : (1UL << (22))), "MPEG4 Video"}, | |||
508 | {CODEC_MASK(AST_FORMAT_VP8)((23) == (uint32_t)-1 ? 0 : (1UL << (23))), "VP8 Video"}, | |||
509 | {CODEC_MASK(AST_FORMAT_T140_RED)((26) == (uint32_t)-1 ? 0 : (1UL << (26))), "T.140 RED Text format RFC 4103"}, | |||
510 | {CODEC_MASK(AST_FORMAT_T140)((27) == (uint32_t)-1 ? 0 : (1UL << (27))), "T.140 Text format - ITU T.140, RFC 4103"}, | |||
511 | {CODEC_MASK(AST_FORMAT_G719)((32) == (uint32_t)-1 ? 0 : (1UL << (32))), "G.719 (64 kbps assumed)"}, | |||
512 | {CODEC_MASK(AST_FORMAT_SPEEX16)((33) == (uint32_t)-1 ? 0 : (1UL << (33))), "SpeeX Wideband (16kHz) Free Compression"}, | |||
513 | {CODEC_MASK(AST_FORMAT_OPUS)((34) == (uint32_t)-1 ? 0 : (1UL << (34))), "Opus audio (8kHz, 16kHz, 24kHz, 48Khz)"}, | |||
514 | {CODEC_MASK(AST_FORMAT_TESTLAW)((47) == (uint32_t)-1 ? 0 : (1UL << (47))), "Raw testing-law data (G.711)"}, | |||
515 | {0, NULL((void*)0)} | |||
516 | }; | |||
517 | static val64_string_ext codec_types_ext = VAL64_STRING_EXT_INIT(codec_types){ _try_val64_to_str_ext_init, 0, (sizeof (codec_types) / sizeof ((codec_types)[0]))-1, codec_types, "codec_types", ((void*)0 ) }; | |||
518 | ||||
519 | static const value_string iax_dataformats[] = { | |||
520 | {AST_DATAFORMAT_NULL, "N/A (analogue call?)"}, | |||
521 | {AST_DATAFORMAT_V110, "ITU-T V.110 rate adaption"}, | |||
522 | {AST_DATAFORMAT_H223_H245, "ITU-T H.223/H.245"}, | |||
523 | {0, NULL((void*)0)} | |||
524 | }; | |||
525 | ||||
526 | ||||
527 | static const value_string iax_packet_types[] = { | |||
528 | {IAX2_FULL_PACKET, "Full packet"}, | |||
529 | {IAX2_MINI_VOICE_PACKET, "Mini voice packet"}, | |||
530 | {IAX2_MINI_VIDEO_PACKET, "Mini video packet"}, | |||
531 | {IAX2_TRUNK_PACKET, "Trunk packet"}, | |||
532 | {0, NULL((void*)0)} | |||
533 | }; | |||
534 | ||||
535 | static const value_string iax_causecodes[] = { | |||
536 | {AST_CAUSE_UNALLOCATED1, "Unallocated"}, | |||
537 | {AST_CAUSE_NO_ROUTE_TRANSIT_NET2, "No route transit net"}, | |||
538 | {AST_CAUSE_NO_ROUTE_DESTINATION3, "No route to destination"}, | |||
539 | {AST_CAUSE_MISDIALLED_TRUNK_PREFIX5, "Misdialled trunk prefix"}, | |||
540 | {AST_CAUSE_CHANNEL_UNACCEPTABLE6, "Channel unacceptable"}, | |||
541 | {AST_CAUSE_CALL_AWARDED_DELIVERED7, "Call awarded delivered"}, | |||
542 | {AST_CAUSE_PRE_EMPTED8, "Preempted"}, | |||
543 | {AST_CAUSE_NUMBER_PORTED_NOT_HERE14, "Number ported not here"}, | |||
544 | {AST_CAUSE_NORMAL_CLEARING16, "Normal clearing"}, | |||
545 | {AST_CAUSE_USER_BUSY17, "User busy"}, | |||
546 | {AST_CAUSE_NO_USER_RESPONSE18, "No user response"}, | |||
547 | {AST_CAUSE_NO_ANSWER19, "No answer"}, | |||
548 | {AST_CAUSE_SUBSCRIBER_ABSENT20, "Subscriber absent"}, | |||
549 | {AST_CAUSE_CALL_REJECTED21, "Call rejected"}, | |||
550 | {AST_CAUSE_NUMBER_CHANGED22, "Number changed"}, | |||
551 | {AST_CAUSE_REDIRECTED_TO_NEW_DESTINATION23, "Redirected to new destination"}, | |||
552 | {AST_CAUSE_ANSWERED_ELSEWHERE26, "Answered elsewhere"}, | |||
553 | {AST_CAUSE_DESTINATION_OUT_OF_ORDER27, "Destination out of order"}, | |||
554 | {AST_CAUSE_INVALID_NUMBER_FORMAT28, "Invalid number format"}, | |||
555 | {AST_CAUSE_FACILITY_REJECTED29, "Facility rejected"}, | |||
556 | {AST_CAUSE_RESPONSE_TO_STATUS_ENQUIRY30, "Response to status inquiry"}, | |||
557 | {AST_CAUSE_NORMAL_UNSPECIFIED31, "Normal unspecified"}, | |||
558 | {AST_CAUSE_NORMAL_CIRCUIT_CONGESTION34, "Normal circuit congestion"}, | |||
559 | {AST_CAUSE_NETWORK_OUT_OF_ORDER38, "Network out of order"}, | |||
560 | {AST_CAUSE_NORMAL_TEMPORARY_FAILURE41, "Normal temporary failure"}, | |||
561 | {AST_CAUSE_SWITCH_CONGESTION42, "Switch congestion"}, | |||
562 | {AST_CAUSE_ACCESS_INFO_DISCARDED43, "Access info discarded"}, | |||
563 | {AST_CAUSE_REQUESTED_CHAN_UNAVAIL44, "Requested channel unavailable"}, | |||
564 | {AST_CAUSE_FACILITY_NOT_SUBSCRIBED50, "Facility not subscribed"}, | |||
565 | {AST_CAUSE_OUTGOING_CALL_BARRED52, "Outgoing call barred"}, | |||
566 | {AST_CAUSE_INCOMING_CALL_BARRED54, "Incoming call barred"}, | |||
567 | {AST_CAUSE_BEARERCAPABILITY_NOTAUTH57, "Bearer capability not authorized"}, | |||
568 | {AST_CAUSE_BEARERCAPABILITY_NOTAVAIL58, "Bearer capability not available"}, | |||
569 | {AST_CAUSE_BEARERCAPABILITY_NOTIMPL65, "Bearer capability not implemented"}, | |||
570 | {AST_CAUSE_CHAN_NOT_IMPLEMENTED66, "Channel not implemented"}, | |||
571 | {AST_CAUSE_FACILITY_NOT_IMPLEMENTED69, "Facility not implemented"}, | |||
572 | {AST_CAUSE_INVALID_CALL_REFERENCE81, "Invalid call reference"}, | |||
573 | {AST_CAUSE_INCOMPATIBLE_DESTINATION88, "Incompatible destination"}, | |||
574 | {AST_CAUSE_INVALID_MSG_UNSPECIFIED95, "Invalid message unspecified"}, | |||
575 | {AST_CAUSE_MANDATORY_IE_MISSING96, "Mandatory IE missing"}, | |||
576 | {AST_CAUSE_MESSAGE_TYPE_NONEXIST97, "Message type nonexistent"}, | |||
577 | {AST_CAUSE_WRONG_MESSAGE98, "Wrong message"}, | |||
578 | {AST_CAUSE_IE_NONEXIST99, "IE nonexistent"}, | |||
579 | {AST_CAUSE_INVALID_IE_CONTENTS100, "Invalid IE contents"}, | |||
580 | {AST_CAUSE_WRONG_CALL_STATE101, "Wrong call state"}, | |||
581 | {AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE102, "Recovery on timer expire"}, | |||
582 | {AST_CAUSE_MANDATORY_IE_LENGTH_ERROR103, "Mandatory IE length error"}, | |||
583 | {AST_CAUSE_PROTOCOL_ERROR111, "Protocol error"}, | |||
584 | {AST_CAUSE_INTERWORKING127, "Interworking"}, | |||
585 | {0, NULL((void*)0)} | |||
586 | }; | |||
587 | static value_string_ext iax_causecodes_ext = VALUE_STRING_EXT_INIT(iax_causecodes){ _try_val_to_str_ext_init, 0, (sizeof (iax_causecodes) / sizeof ((iax_causecodes)[0]))-1, iax_causecodes, "iax_causecodes", ( (void*)0) }; | |||
588 | ||||
589 | /* ************************************************************************* */ | |||
590 | ||||
591 | /* In order to track IAX calls, we have a hash table which maps | |||
592 | * {addr,port type,port,call} to a unique circuit id. | |||
593 | * | |||
594 | * Each call has two such circuits associated with it (a forward and a | |||
595 | * reverse circuit, where 'forward' is defined as the direction the NEW | |||
596 | * packet went in), and we maintain an iax_call_data structure for each | |||
597 | * call, attached to both circuits with circuit_add_proto_data. | |||
598 | * | |||
599 | * Because {addr,port type,port,call} quadruplets can be reused | |||
600 | * (Asterisk reuses call numbers), circuit ids aren't unique to | |||
601 | * individual calls and we treat NEW packets somewhat specially. When we | |||
602 | * get such a packet, we see if there are any calls with a matching | |||
603 | * circuit id, and make sure that its circuits are marked as ended | |||
604 | * before that packet. | |||
605 | * | |||
606 | * A second complication is that we only know one quadruplet at the time | |||
607 | * the NEW packet is processed: there is therefore cunningness in | |||
608 | * iax_lookup_circuit_details() to look for replies to NEW packets and | |||
609 | * create the reverse circuit. | |||
610 | */ | |||
611 | ||||
612 | ||||
613 | /* start with a hash of {addr,port type,port,call}->{id} */ | |||
614 | ||||
615 | typedef struct { | |||
616 | address addr; | |||
617 | port_type ptype; | |||
618 | uint32_t port; | |||
619 | uint32_t callno; | |||
620 | ||||
621 | /* this is where addr->data points to. it's put in here for easy freeing */ | |||
622 | uint8_t address_data[MAX_ADDRESS16]; | |||
623 | } iax_circuit_key; | |||
624 | ||||
625 | /* tables */ | |||
626 | static GHashTable *iax_fid_table; | |||
627 | static reassembly_table iax_reassembly_table; | |||
628 | ||||
629 | static GHashTable *iax_circuit_hashtab; | |||
630 | static unsigned circuitcount; | |||
631 | ||||
632 | /* the number of keys and values to reserve space for in each memory chunk. | |||
633 | We assume we won't be tracking many calls at once so this is quite low. | |||
634 | */ | |||
635 | #define IAX_INIT_PACKET_COUNT10 10 | |||
636 | ||||
637 | #ifdef DEBUG_HASHING | |||
638 | static char *key_to_str( const iax_circuit_key *key ) | |||
639 | { | |||
640 | static int i = 0; | |||
641 | static char str[3][80]; | |||
642 | char *strp; | |||
643 | char *addrstr; | |||
644 | ||||
645 | i++; | |||
646 | if (i >= 3) { | |||
647 | i = 0; | |||
648 | } | |||
649 | strp = str[i]; | |||
650 | ||||
651 | addrstr = address_to_str(NULL((void*)0), &key->addr); | |||
652 | snprintf(strp, 80, "{%s:%i,%i}", | |||
653 | addrstr, | |||
654 | key->port, | |||
655 | key->callno); | |||
656 | wmem_free(NULL((void*)0), addrstr); | |||
657 | return strp; | |||
658 | } | |||
659 | #endif | |||
660 | ||||
661 | /* Hash Functions */ | |||
662 | static int iax_circuit_equal(const void *v, const void *w) | |||
663 | { | |||
664 | const iax_circuit_key *v1 = (const iax_circuit_key *)v; | |||
665 | const iax_circuit_key *v2 = (const iax_circuit_key *)w; | |||
666 | int result; | |||
667 | ||||
668 | result = (addresses_equal(&(v1->addr), &(v2->addr)) && | |||
669 | v1->ptype == v2->ptype && | |||
670 | v1->port == v2->port && | |||
671 | v1->callno== v2->callno); | |||
672 | #ifdef DEBUG_HASHING | |||
673 | ws_debug("+++ Comparing for equality: %s, %s: %u", key_to_str(v1), key_to_str(v2), result)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 673, __func__, "+++ Comparing for equality: %s, %s: %u", key_to_str (v1), key_to_str(v2), result); } } while (0); | |||
674 | #endif | |||
675 | ||||
676 | return result; | |||
677 | } | |||
678 | ||||
679 | static unsigned iax_circuit_hash(const void *v) | |||
680 | { | |||
681 | const iax_circuit_key *key = (const iax_circuit_key *)v; | |||
682 | unsigned hash_val; | |||
683 | ||||
684 | hash_val = 0; | |||
685 | hash_val = add_address_to_hash(hash_val, &key->addr); | |||
686 | hash_val += (unsigned)(key->ptype); | |||
687 | hash_val += (unsigned)(key->port); | |||
688 | hash_val += (unsigned)(key->callno); | |||
689 | ||||
690 | #ifdef DEBUG_HASHING | |||
691 | ws_debug("+++ Hashing key: %s, result %#x", key_to_str(key), hash_val)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 691, __func__, "+++ Hashing key: %s, result %#x", key_to_str (key), hash_val); } } while (0); | |||
692 | #endif | |||
693 | ||||
694 | return (unsigned)hash_val; | |||
695 | } | |||
696 | ||||
697 | /* Find, or create, a circuit for the given | |||
698 | {address,porttype,port,call} quadruplet | |||
699 | */ | |||
700 | static unsigned iax_circuit_lookup(const address *address_p, | |||
701 | port_type ptype, | |||
702 | uint32_t port, | |||
703 | uint32_t callno) | |||
704 | { | |||
705 | iax_circuit_key key; | |||
706 | uint32_t *circuit_id_p; | |||
707 | ||||
708 | key.addr = *address_p; | |||
709 | key.ptype = ptype; | |||
710 | key.port = port; | |||
711 | key.callno = callno; | |||
712 | ||||
713 | circuit_id_p = (uint32_t *)g_hash_table_lookup(iax_circuit_hashtab, &key); | |||
714 | if (! circuit_id_p) { | |||
715 | iax_circuit_key *new_key; | |||
716 | ||||
717 | new_key = wmem_new(wmem_file_scope(), iax_circuit_key)((iax_circuit_key*)wmem_alloc((wmem_file_scope()), sizeof(iax_circuit_key ))); | |||
718 | new_key->addr.type = address_p->type; | |||
719 | new_key->addr.len = MIN(address_p->len, MAX_ADDRESS)(((address_p->len) < (16)) ? (address_p->len) : (16) ); | |||
720 | new_key->addr.data = new_key->address_data; | |||
721 | if (new_key->addr.len > 0) | |||
722 | memcpy(new_key->address_data, address_p->data, new_key->addr.len); | |||
723 | new_key->ptype = ptype; | |||
724 | new_key->port = port; | |||
725 | new_key->callno = callno; | |||
726 | ||||
727 | circuit_id_p = (uint32_t *)wmem_new(wmem_file_scope(), iax_circuit_key)((iax_circuit_key*)wmem_alloc((wmem_file_scope()), sizeof(iax_circuit_key ))); | |||
728 | *circuit_id_p = ++circuitcount; | |||
729 | ||||
730 | g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p); | |||
731 | ||||
732 | #ifdef DEBUG_HASHING | |||
733 | ws_debug("Created new circuit id %u for node %s", *circuit_id_p, key_to_str(new_key))do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 733, __func__, "Created new circuit id %u for node %s", *circuit_id_p , key_to_str(new_key)); } } while (0); | |||
734 | #endif | |||
735 | } | |||
736 | ||||
737 | return *circuit_id_p; | |||
738 | } | |||
739 | ||||
740 | ||||
741 | /* ************************************************************************* */ | |||
742 | ||||
743 | typedef struct { | |||
744 | uint32_t current_frag_id; /* invalid unless current_frag_bytes > 0 */ | |||
745 | uint32_t current_frag_bytes; | |||
746 | uint32_t current_frag_minlen; | |||
747 | } iax_call_dirdata; | |||
748 | ||||
749 | /* This is our per-call data structure, which is attached to both the | |||
750 | * forward and reverse circuits. | |||
751 | */ | |||
752 | typedef struct iax_call_data { | |||
753 | /* For this data, src and dst are relative to the original direction under | |||
754 | which this call is stored. Obviously if the reversed flag is set true by | |||
755 | iax_find_call, src and dst are reversed relative to the direction the | |||
756 | actual source and destination of the data. | |||
757 | ||||
758 | if the codec changes mid-call, we update it here; because we store a codec | |||
759 | number with each packet too, we handle going back to earlier packets | |||
760 | without problem. | |||
761 | */ | |||
762 | ||||
763 | iax_dataformat_t dataformat; | |||
764 | uint32_t src_codec, dst_codec; | |||
765 | uint32_t src_vformat, dst_vformat; | |||
766 | ||||
767 | /* when a transfer takes place, we'll get a new circuit id; we assume that we | |||
768 | don't try to transfer more than IAX_MAX_TRANSFERS times in a call */ | |||
769 | unsigned forward_circuit_ids[IAX_MAX_TRANSFERS2]; | |||
770 | unsigned reverse_circuit_ids[IAX_MAX_TRANSFERS2]; | |||
771 | unsigned n_forward_circuit_ids; | |||
772 | unsigned n_reverse_circuit_ids; | |||
773 | ||||
774 | /* this is the subdissector for the call */ | |||
775 | dissector_handle_t subdissector; | |||
776 | ||||
777 | /* the absolute start time of the call */ | |||
778 | nstime_t start_time; | |||
779 | ||||
780 | /* time stamp from last full frame, in the first pass */ | |||
781 | uint32_t last_full_frame_ts; | |||
782 | ||||
783 | iax_call_dirdata dirdata[2]; | |||
784 | } iax_call_data; | |||
785 | ||||
786 | ||||
787 | ||||
788 | /* creates a new CONVERSATION_IAX2 circuit with a specified circuit id for a call | |||
789 | * | |||
790 | * typically a call has up to three associated circuits: an original source, an | |||
791 | * original destination, and the result of a transfer. | |||
792 | * | |||
793 | * For each endpoint, a CONVERSATION_IAX2 circuit is created and added to the call_data | |||
794 | * by this function | |||
795 | * | |||
796 | * 'reversed' should be true if this end is the one which would have _received_ | |||
797 | * the NEW packet, or it is an endpoint to which the 'destination' is being | |||
798 | * transferred. | |||
799 | * | |||
800 | */ | |||
801 | static conversation_t *iax2_new_circuit_for_call(packet_info *pinfo, proto_item * item, | |||
802 | unsigned circuit_id, unsigned framenum, | |||
803 | iax_call_data *iax_call, bool_Bool reversed) | |||
804 | { | |||
805 | conversation_t *conv; | |||
806 | ||||
807 | if(!iax_call){ | |||
808 | return NULL((void*)0); | |||
809 | } | |||
810 | if ((reversed && iax_call->n_reverse_circuit_ids >= IAX_MAX_TRANSFERS2) || | |||
811 | (! reversed && iax_call->n_forward_circuit_ids >= IAX_MAX_TRANSFERS2)) { | |||
812 | expert_add_info(pinfo, item, &ei_iax_too_many_transfers); | |||
813 | return NULL((void*)0); | |||
814 | } | |||
815 | ||||
816 | conv = conversation_new_by_id(framenum, CONVERSATION_IAX2, | |||
817 | circuit_id); | |||
818 | ||||
819 | conversation_add_proto_data(conv, proto_iax2, iax_call); | |||
820 | ||||
821 | if (reversed) | |||
822 | iax_call -> reverse_circuit_ids[iax_call->n_reverse_circuit_ids++] = circuit_id; | |||
823 | else | |||
824 | iax_call -> forward_circuit_ids[iax_call->n_forward_circuit_ids++] = circuit_id; | |||
825 | ||||
826 | return conv; | |||
827 | } | |||
828 | ||||
829 | ||||
830 | /* returns true if this circuit id is a "forward" circuit for this call: ie, it | |||
831 | * is the point which _sent_ the original 'NEW' packet, or a point to which that | |||
832 | * end was subsequently transferred */ | |||
833 | static bool_Bool is_forward_circuit(unsigned circuit_id, | |||
834 | const iax_call_data *iax_call) | |||
835 | { | |||
836 | unsigned i; | |||
837 | for(i=0; i<iax_call->n_forward_circuit_ids; i++) { | |||
838 | if (circuit_id == iax_call->forward_circuit_ids[i]) | |||
839 | return true1; | |||
840 | } | |||
841 | return false0; | |||
842 | } | |||
843 | ||||
844 | /* returns true if this circuit id is a "reverse" circuit for this call: ie, it | |||
845 | * is the point which _received_ the original 'NEW' packet, or a point to which that | |||
846 | * end was subsequently transferred */ | |||
847 | static bool_Bool is_reverse_circuit(unsigned circuit_id, | |||
848 | const iax_call_data *iax_call) | |||
849 | { | |||
850 | unsigned i; | |||
851 | for(i=0; i<iax_call->n_reverse_circuit_ids; i++){ | |||
852 | if (circuit_id == iax_call->reverse_circuit_ids[i]) | |||
853 | return true1; | |||
854 | } | |||
855 | return false0; | |||
856 | } | |||
857 | ||||
858 | ||||
859 | static iax_call_data *iax_lookup_call_from_dest(packet_info *pinfo, proto_item * item, | |||
860 | unsigned src_circuit_id, | |||
861 | unsigned dst_circuit_id, | |||
862 | unsigned framenum, | |||
863 | bool_Bool *reversed_p) | |||
864 | { | |||
865 | conversation_t *dst_conv; | |||
866 | iax_call_data *iax_call; | |||
867 | bool_Bool reversed = false0; | |||
868 | ||||
869 | dst_conv = find_conversation_by_id(framenum, CONVERSATION_IAX2, dst_circuit_id); | |||
870 | ||||
871 | if (!dst_conv) { | |||
872 | #ifdef DEBUG_HASHING | |||
873 | ws_debug("++ destination circuit not found, must have missed NEW packet")do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 873, __func__, "++ destination circuit not found, must have missed NEW packet" ); } } while (0); | |||
874 | #endif | |||
875 | if (reversed_p) | |||
876 | *reversed_p = false0; | |||
877 | return NULL((void*)0); | |||
878 | } | |||
879 | ||||
880 | #ifdef DEBUG_HASHING | |||
881 | ws_debug("++ found destination circuit")do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 881, __func__, "++ found destination circuit"); } } while ( 0); | |||
882 | #endif | |||
883 | ||||
884 | iax_call = (iax_call_data *)conversation_get_proto_data(dst_conv, proto_iax2); | |||
885 | ||||
886 | /* there's no way we can create a CONVERSATION_IAX2 circuit without adding | |||
887 | iax call data to it; assert this */ | |||
888 | DISSECTOR_ASSERT(iax_call)((void) ((iax_call) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-iax2.c", 888, "iax_call")))); | |||
889 | ||||
890 | if (is_forward_circuit(dst_circuit_id, iax_call)) { | |||
891 | #ifdef DEBUG_HASHING | |||
892 | ws_debug("++ destination circuit matches forward_circuit_id of call, "do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 893, __func__, "++ destination circuit matches forward_circuit_id of call, " "therefore packet is reversed"); } } while (0) | |||
893 | "therefore packet is reversed")do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 893, __func__, "++ destination circuit matches forward_circuit_id of call, " "therefore packet is reversed"); } } while (0); | |||
894 | #endif | |||
895 | ||||
896 | reversed = true1; | |||
897 | ||||
898 | if (iax_call -> n_reverse_circuit_ids == 0) { | |||
899 | /* we are going in the reverse direction, and this call | |||
900 | doesn't have a reverse circuit associated with it. | |||
901 | create one now. */ | |||
902 | #ifdef DEBUG_HASHING | |||
903 | ws_debug("++ reverse_circuit_id of call is zero, need to create a "do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 904, __func__, "++ reverse_circuit_id of call is zero, need to create a " "new reverse circuit for this call"); } } while (0) | |||
904 | "new reverse circuit for this call")do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 904, __func__, "++ reverse_circuit_id of call is zero, need to create a " "new reverse circuit for this call"); } } while (0); | |||
905 | #endif | |||
906 | ||||
907 | iax2_new_circuit_for_call(pinfo, item, src_circuit_id, framenum, iax_call, true1); | |||
908 | #ifdef DEBUG_HASHING | |||
909 | ws_debug("++ done")do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 909, __func__, "++ done"); } } while (0); | |||
910 | #endif | |||
911 | } else if (!is_reverse_circuit(src_circuit_id, iax_call)) { | |||
912 | expert_add_info_format(pinfo, item, &ei_iax_circuit_id_conflict, | |||
913 | "IAX Packet %u from circuit ids %u->%u conflicts with earlier call with circuit ids %u->%u", | |||
914 | framenum, | |||
915 | src_circuit_id, dst_circuit_id, | |||
916 | iax_call->forward_circuit_ids[0], | |||
917 | iax_call->reverse_circuit_ids[0]); | |||
918 | return NULL((void*)0); | |||
919 | } | |||
920 | } else if (is_reverse_circuit(dst_circuit_id, iax_call)) { | |||
921 | #ifdef DEBUG_HASHING | |||
922 | ws_debug("++ destination circuit matches reverse_circuit_id of call, "do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 923, __func__, "++ destination circuit matches reverse_circuit_id of call, " "therefore packet is forward"); } } while (0) | |||
923 | "therefore packet is forward")do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 923, __func__, "++ destination circuit matches reverse_circuit_id of call, " "therefore packet is forward"); } } while (0); | |||
924 | #endif | |||
925 | ||||
926 | reversed = false0; | |||
927 | if (!is_forward_circuit(src_circuit_id, iax_call)) { | |||
928 | expert_add_info_format(pinfo, item, &ei_iax_circuit_id_conflict, | |||
929 | "IAX Packet %u from circuit ids %u->%u conflicts with earlier call with circuit ids %u->%u", | |||
930 | framenum, | |||
931 | src_circuit_id, dst_circuit_id, | |||
932 | iax_call->forward_circuit_ids[0], | |||
933 | iax_call->reverse_circuit_ids[0]); | |||
934 | if (reversed_p) | |||
935 | *reversed_p = false0; | |||
936 | return NULL((void*)0); | |||
937 | } | |||
938 | } else { | |||
939 | DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\"" , "epan/dissectors/packet-iax2.c", 939)); | |||
940 | } | |||
941 | ||||
942 | if (reversed_p) | |||
943 | *reversed_p = reversed; | |||
944 | ||||
945 | return iax_call; | |||
946 | } | |||
947 | ||||
948 | ||||
949 | /* looks up an iax_call for this packet */ | |||
950 | static iax_call_data *iax_lookup_call( packet_info *pinfo, | |||
951 | uint32_t scallno, | |||
952 | uint32_t dcallno, | |||
953 | bool_Bool *reversed_p) | |||
954 | { | |||
955 | bool_Bool reversed = false0; | |||
956 | iax_call_data *iax_call = NULL((void*)0); | |||
957 | unsigned src_circuit_id; | |||
958 | #ifdef DEBUG_HASHING | |||
959 | char *srcstr, *dststr; | |||
960 | #endif | |||
961 | ||||
962 | #ifdef DEBUG_HASHING | |||
963 | srcstr = address_to_str(NULL((void*)0), &pinfo->src); | |||
964 | dststr = address_to_str(NULL((void*)0), &pinfo->dst); | |||
965 | ws_debug("++ iax_lookup_circuit_details: Looking up circuit for frame %u, "do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 968, __func__, "++ iax_lookup_circuit_details: Looking up circuit for frame %u, " "from {%s:%u:%u} to {%s:%u:%u}", pinfo->num, srcstr, pinfo ->srcport, scallno, dststr, pinfo->destport, dcallno); } } while (0) | |||
966 | "from {%s:%u:%u} to {%s:%u:%u}", pinfo->num,do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 968, __func__, "++ iax_lookup_circuit_details: Looking up circuit for frame %u, " "from {%s:%u:%u} to {%s:%u:%u}", pinfo->num, srcstr, pinfo ->srcport, scallno, dststr, pinfo->destport, dcallno); } } while (0) | |||
967 | srcstr, pinfo->srcport, scallno,do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 968, __func__, "++ iax_lookup_circuit_details: Looking up circuit for frame %u, " "from {%s:%u:%u} to {%s:%u:%u}", pinfo->num, srcstr, pinfo ->srcport, scallno, dststr, pinfo->destport, dcallno); } } while (0) | |||
968 | dststr, pinfo->destport, dcallno)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 968, __func__, "++ iax_lookup_circuit_details: Looking up circuit for frame %u, " "from {%s:%u:%u} to {%s:%u:%u}", pinfo->num, srcstr, pinfo ->srcport, scallno, dststr, pinfo->destport, dcallno); } } while (0); | |||
969 | wmem_free(NULL((void*)0), srcstr); | |||
970 | wmem_free(NULL((void*)0), dststr); | |||
971 | #endif | |||
972 | ||||
973 | ||||
974 | src_circuit_id = iax_circuit_lookup(&pinfo->src, pinfo->ptype, | |||
975 | pinfo->srcport, scallno); | |||
976 | ||||
977 | ||||
978 | /* the most reliable indicator of call is the destination callno, if | |||
979 | we have one */ | |||
980 | if (dcallno != 0) { | |||
981 | unsigned dst_circuit_id; | |||
982 | #ifdef DEBUG_HASHING | |||
983 | ws_debug("++ dcallno non-zero, looking up destination circuit")do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 983, __func__, "++ dcallno non-zero, looking up destination circuit" ); } } while (0); | |||
984 | #endif | |||
985 | ||||
986 | dst_circuit_id = iax_circuit_lookup(&pinfo->dst, pinfo->ptype, | |||
987 | pinfo->destport, dcallno); | |||
988 | ||||
989 | iax_call = iax_lookup_call_from_dest(pinfo, NULL((void*)0), src_circuit_id, dst_circuit_id, | |||
990 | pinfo->num, &reversed); | |||
991 | } else { | |||
992 | conversation_t *src_conv; | |||
993 | ||||
994 | /* in all other circumstances, the source circuit should already | |||
995 | * exist: its absence indicates that we missed the all-important NEW | |||
996 | * packet. | |||
997 | */ | |||
998 | ||||
999 | src_conv = find_conversation_by_id(pinfo->num, CONVERSATION_IAX2, src_circuit_id); | |||
1000 | ||||
1001 | if (src_conv) { | |||
1002 | iax_call = (iax_call_data *)conversation_get_proto_data(src_conv, proto_iax2); | |||
1003 | ||||
1004 | /* there's no way we can create a CONVERSATION_IAX2 circuit without adding | |||
1005 | iax call data to it; assert this */ | |||
1006 | DISSECTOR_ASSERT(iax_call)((void) ((iax_call) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-iax2.c", 1006, "iax_call")))); | |||
1007 | ||||
1008 | if (is_forward_circuit(src_circuit_id, iax_call)) | |||
1009 | reversed = false0; | |||
1010 | else if (is_reverse_circuit(src_circuit_id, iax_call)) | |||
1011 | reversed = true1; | |||
1012 | else { | |||
1013 | /* there's also no way we can attach an iax_call_data to a circuit | |||
1014 | without the circuit being either the forward or reverse circuit | |||
1015 | for that call; assert this too. | |||
1016 | */ | |||
1017 | DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\"" , "epan/dissectors/packet-iax2.c", 1017)); | |||
1018 | } | |||
1019 | } | |||
1020 | } | |||
1021 | ||||
1022 | if (reversed_p) | |||
1023 | *reversed_p = reversed; | |||
1024 | ||||
1025 | #ifdef DEBUG_HASHING | |||
1026 | if (iax_call) { | |||
1027 | ws_debug("++ Found call for packet: id %u, reversed=%c", iax_call->forward_circuit_ids[0], reversed?'1':'0')do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 1027, __func__, "++ Found call for packet: id %u, reversed=%c" , iax_call->forward_circuit_ids[0], reversed?'1':'0'); } } while (0); | |||
1028 | } else { | |||
1029 | ws_debug("++ Call not found. Must have missed the NEW packet?")do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 1029, __func__, "++ Call not found. Must have missed the NEW packet?" ); } } while (0); | |||
1030 | } | |||
1031 | #endif | |||
1032 | ||||
1033 | return iax_call; | |||
1034 | } | |||
1035 | ||||
1036 | /* initialize the per-direction parts of an iax_call_data structure */ | |||
1037 | static void init_dir_data(iax_call_dirdata *dirdata) | |||
1038 | { | |||
1039 | dirdata -> current_frag_bytes=0; | |||
1040 | dirdata -> current_frag_minlen=0; | |||
1041 | } | |||
1042 | ||||
1043 | ||||
1044 | /* handles a NEW packet by creating a new iax call and forward circuit. | |||
1045 | the reverse circuit is not created until the ACK is received and | |||
1046 | is created by iax_lookup_circuit_details. */ | |||
1047 | static iax_call_data *iax_new_call( packet_info *pinfo, | |||
1048 | uint32_t scallno) | |||
1049 | { | |||
1050 | iax_call_data *call; | |||
1051 | unsigned circuit_id; | |||
1052 | static const nstime_t millisecond = NSTIME_INIT_SECS_MSECS(0, 1){0, 1*1000000}; | |||
1053 | ||||
1054 | #ifdef DEBUG_HASHING | |||
1055 | ws_debug("+ new_circuit: Handling NEW packet, frame %u", pinfo->num)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 1055, __func__, "+ new_circuit: Handling NEW packet, frame %u" , pinfo->num); } } while (0); | |||
1056 | #endif | |||
1057 | ||||
1058 | circuit_id = iax_circuit_lookup(&pinfo->src, pinfo->ptype, | |||
1059 | pinfo->srcport, scallno); | |||
1060 | ||||
1061 | call = wmem_new(wmem_file_scope(), iax_call_data)((iax_call_data*)wmem_alloc((wmem_file_scope()), sizeof(iax_call_data ))); | |||
1062 | call -> dataformat = AST_DATAFORMAT_NULL; | |||
1063 | call -> src_codec = 0; | |||
1064 | call -> dst_codec = 0; | |||
1065 | call -> src_vformat = 0; | |||
1066 | call -> dst_vformat = 0; | |||
1067 | call -> n_forward_circuit_ids = 0; | |||
1068 | call -> n_reverse_circuit_ids = 0; | |||
1069 | call -> subdissector = NULL((void*)0); | |||
1070 | call -> start_time = pinfo->abs_ts; | |||
1071 | call -> last_full_frame_ts = 0; | |||
1072 | nstime_delta(&call -> start_time, &call -> start_time, &millisecond); | |||
1073 | init_dir_data(&call->dirdata[0]); | |||
1074 | init_dir_data(&call->dirdata[1]); | |||
1075 | ||||
1076 | iax2_new_circuit_for_call(pinfo, NULL((void*)0), circuit_id, pinfo->num, call, false0); | |||
1077 | ||||
1078 | return call; | |||
1079 | } | |||
1080 | ||||
1081 | ||||
1082 | /* ************************************************************************* */ | |||
1083 | ||||
1084 | /* per-packet data */ | |||
1085 | typedef struct iax_packet_data { | |||
1086 | bool_Bool first_time; /* we're dissecting this packet for the first time; so | |||
1087 | * things like codec and transfer requests should be | |||
1088 | * propagated into the call data */ | |||
1089 | iax_call_data *call_data; | |||
1090 | uint32_t codec; | |||
1091 | bool_Bool reversed; | |||
1092 | nstime_t abstime; /* the absolute time of this packet, based on its | |||
1093 | * timestamp and the NEW packet's time (-1 if unknown) */ | |||
1094 | } iax_packet_data; | |||
1095 | ||||
1096 | static iax_packet_data *iax_new_packet_data(iax_call_data *call, bool_Bool reversed) | |||
1097 | { | |||
1098 | iax_packet_data *p = wmem_new(wmem_file_scope(), iax_packet_data)((iax_packet_data*)wmem_alloc((wmem_file_scope()), sizeof(iax_packet_data ))); | |||
1099 | p->first_time = true1; | |||
1100 | p->call_data = call; | |||
1101 | p->codec = 0; | |||
1102 | p->reversed = reversed; | |||
1103 | p->abstime.secs = -1; | |||
1104 | p->abstime.nsecs = -1; | |||
1105 | return p; | |||
1106 | } | |||
1107 | ||||
1108 | static void iax2_populate_pinfo_from_packet_data(packet_info *pinfo, const iax_packet_data *p) | |||
1109 | { | |||
1110 | if (p->call_data != NULL((void*)0)) { | |||
1111 | /* if we missed the NEW packet for this call, call_data will be null. it's | |||
1112 | * tbd what the best thing to do here is. */ | |||
1113 | pinfo->p2p_dir = p->reversed?P2P_DIR_RECV1:P2P_DIR_SENT0; | |||
1114 | ||||
1115 | col_set_str(pinfo->cinfo, COL_IF_DIR, p->reversed ? "rev" : "fwd"); | |||
1116 | } | |||
1117 | } | |||
1118 | ||||
1119 | ||||
1120 | /* ************************************************************************* */ | |||
1121 | ||||
1122 | /* this is passed up from the IE dissector to the main dissector */ | |||
1123 | typedef struct | |||
1124 | { | |||
1125 | address peer_address; | |||
1126 | port_type peer_ptype; | |||
1127 | uint32_t peer_port; | |||
1128 | uint32_t peer_callno; | |||
1129 | uint32_t dataformat; | |||
1130 | } iax2_ie_data; | |||
1131 | ||||
1132 | ||||
1133 | static uint32_t dissect_fullpacket(tvbuff_t *tvb, uint32_t offset, | |||
1134 | uint16_t scallno, | |||
1135 | packet_info *pinfo, | |||
1136 | proto_tree *iax2_tree, | |||
1137 | proto_tree *main_tree); | |||
1138 | ||||
1139 | ||||
1140 | static uint32_t dissect_minipacket(tvbuff_t *tvb, uint32_t offset, | |||
1141 | uint16_t scallno, | |||
1142 | packet_info *pinfo, | |||
1143 | proto_tree *iax2_tree, | |||
1144 | proto_tree *main_tree); | |||
1145 | ||||
1146 | static uint32_t dissect_minivideopacket(tvbuff_t *tvb, uint32_t offset, | |||
1147 | uint16_t scallno, | |||
1148 | packet_info *pinfo, | |||
1149 | proto_tree *iax2_tree, | |||
1150 | proto_tree *main_tree); | |||
1151 | ||||
1152 | static uint32_t dissect_trunkpacket(tvbuff_t *tvb, uint32_t offset, | |||
1153 | uint16_t scallno, | |||
1154 | packet_info *pinfo, | |||
1155 | proto_tree *iax2_tree, | |||
1156 | proto_tree *main_tree); | |||
1157 | ||||
1158 | static void dissect_payload(tvbuff_t *tvb, uint32_t offset, | |||
1159 | packet_info *pinfo, proto_tree *iax2_tree, | |||
1160 | proto_tree *tree, uint32_t ts, bool_Bool video, | |||
1161 | iax_packet_data *iax_packet); | |||
1162 | ||||
1163 | ||||
1164 | ||||
1165 | static int | |||
1166 | dissect_iax2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) | |||
1167 | { | |||
1168 | proto_item *iax2_item; | |||
1169 | proto_tree *iax2_tree; | |||
1170 | proto_tree *full_mini_subtree = NULL((void*)0); | |||
1171 | uint32_t offset = 0, len; | |||
1172 | uint16_t scallno = 0; | |||
1173 | uint16_t stmp; | |||
1174 | packet_type type; | |||
1175 | proto_item *full_mini_base; | |||
1176 | ||||
1177 | /* set up the protocol and info fields in the summary pane */ | |||
1178 | col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2"IAX2"); | |||
1179 | col_clear(pinfo->cinfo, COL_INFO); | |||
1180 | ||||
1181 | /* add the 'iax2' tree to the main tree */ | |||
1182 | iax2_item = proto_tree_add_item(tree, proto_iax2, tvb, offset, -1, ENC_NA0x00000000); | |||
1183 | iax2_tree = proto_item_add_subtree(iax2_item, ett_iax2); | |||
1184 | ||||
1185 | stmp = tvb_get_ntohs(tvb, offset); | |||
1186 | if (stmp == 0) { | |||
| ||||
1187 | /* starting with 0x0000 indicates meta packet which can be either a mini | |||
1188 | * video packet or a trunk packet */ | |||
1189 | offset+=2; | |||
1190 | stmp = tvb_get_ntohs(tvb, offset); | |||
1191 | if (stmp & 0x8000) { | |||
1192 | /* mini video packet */ | |||
1193 | type = IAX2_MINI_VIDEO_PACKET; | |||
1194 | scallno = stmp & 0x7FFF; | |||
1195 | offset += 2; | |||
1196 | } | |||
1197 | else { | |||
1198 | type = IAX2_TRUNK_PACKET; | |||
1199 | } | |||
1200 | } else { | |||
1201 | /* The source call/fullpacket flag is common to both mini and full packets */ | |||
1202 | scallno = tvb_get_ntohs(tvb, offset); | |||
1203 | offset += 2; | |||
1204 | if (scallno & 0x8000) | |||
1205 | type = IAX2_FULL_PACKET; | |||
1206 | else { | |||
1207 | type = IAX2_MINI_VOICE_PACKET; | |||
1208 | } | |||
1209 | scallno &= 0x7FFF; | |||
1210 | } | |||
1211 | ||||
1212 | full_mini_base = proto_tree_add_uint(iax2_tree, hf_iax2_packet_type, tvb, 0, offset, type); | |||
1213 | full_mini_subtree = proto_item_add_subtree(full_mini_base, ett_iax2_full_mini_subtree); | |||
1214 | ||||
1215 | if (scallno != 0) | |||
1216 | proto_tree_add_item(full_mini_subtree, hf_iax2_scallno, tvb, offset-2, 2, ENC_BIG_ENDIAN0x00000000); | |||
1217 | ||||
1218 | iax2_info->ptype = type; | |||
1219 | iax2_info->scallno = 0; | |||
1220 | iax2_info->dcallno = 0; | |||
1221 | iax2_info->ftype = 0; | |||
1222 | iax2_info->csub = 0; | |||
1223 | iax2_info->payload_len = 0; | |||
1224 | iax2_info->timestamp = 0; | |||
1225 | iax2_info->callState = VOIP_NO_STATE; | |||
1226 | iax2_info->messageName = NULL((void*)0); | |||
1227 | iax2_info->callingParty = NULL((void*)0); | |||
1228 | iax2_info->calledParty = NULL((void*)0); | |||
1229 | iax2_info->payload_data = NULL((void*)0); | |||
1230 | ||||
1231 | switch (type) { | |||
1232 | case IAX2_FULL_PACKET: | |||
1233 | len = dissect_fullpacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree); | |||
1234 | break; | |||
1235 | case IAX2_MINI_VOICE_PACKET: | |||
1236 | iax2_info->messageName = "MINI_VOICE_PACKET"; | |||
1237 | len = dissect_minipacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree); | |||
1238 | break; | |||
1239 | case IAX2_MINI_VIDEO_PACKET: | |||
1240 | iax2_info->messageName = "MINI_VIDEO_PACKET"; | |||
1241 | len = dissect_minivideopacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree); | |||
1242 | break; | |||
1243 | case IAX2_TRUNK_PACKET: | |||
1244 | iax2_info->messageName = "TRUNK_PACKET"; | |||
1245 | len = dissect_trunkpacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree); | |||
1246 | break; | |||
1247 | default: | |||
1248 | len = 0; | |||
1249 | } | |||
1250 | ||||
1251 | /* update the 'length' of the main IAX2 header field so that it covers just the headers, | |||
1252 | not the audio data. */ | |||
1253 | proto_item_set_len(iax2_item, len); | |||
1254 | tap_queue_packet(iax2_tap, pinfo, iax2_info); | |||
1255 | return tvb_captured_length(tvb); | |||
1256 | } | |||
1257 | ||||
1258 | static proto_item *dissect_datetime_ie(tvbuff_t *tvb, uint32_t offset, proto_tree *ies_tree) | |||
1259 | { | |||
1260 | struct tm tm; | |||
1261 | uint32_t ie_val; | |||
1262 | nstime_t datetime; | |||
1263 | ||||
1264 | proto_tree_add_item(ies_tree, hf_iax2_ies[IAX_IE_DATETIME31], tvb, offset + 2, 4, ENC_BIG_ENDIAN0x00000000); | |||
1265 | ie_val = tvb_get_ntohl(tvb, offset+2); | |||
1266 | ||||
1267 | /* who's crazy idea for a time encoding was this? */ | |||
1268 | tm.tm_sec = (ie_val & 0x1f) << 1; | |||
1269 | tm.tm_min = (ie_val>>5) & 0x3f; | |||
1270 | tm.tm_hour = (ie_val>>11) & 0x1f; | |||
1271 | tm.tm_mday = (ie_val>>16) & 0x1f; | |||
1272 | tm.tm_mon = ((ie_val>>21) & 0x0f) - 1; | |||
1273 | tm.tm_year = ((ie_val>>25) & 0x7f) + 100; | |||
1274 | tm.tm_isdst= -1; /* there's no info on whether DST was in force; assume it's | |||
1275 | * the same as currently */ | |||
1276 | ||||
1277 | datetime.secs = mktime(&tm); | |||
1278 | datetime.nsecs = 0; | |||
1279 | return proto_tree_add_time(ies_tree, hf_iax2_ie_datetime, tvb, offset+2, 4, &datetime); | |||
1280 | } | |||
1281 | ||||
1282 | ||||
1283 | /* dissect the information elements in an IAX frame. Returns the updated offset */ | |||
1284 | static uint32_t dissect_ies(tvbuff_t *tvb, packet_info *pinfo, uint32_t offset, | |||
1285 | proto_tree *iax_tree, proto_item * iax_item, | |||
1286 | iax2_ie_data *ie_data) | |||
1287 | { | |||
1288 | DISSECTOR_ASSERT(ie_data)((void) ((ie_data) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-iax2.c", 1288, "ie_data")))); | |||
1289 | ||||
1290 | while (offset < tvb_reported_length(tvb)) { | |||
1291 | ||||
1292 | int ies_type = tvb_get_uint8(tvb, offset); | |||
1293 | int ies_len = tvb_get_uint8(tvb, offset + 1); | |||
1294 | uint16_t apparent_addr_family; | |||
1295 | ||||
1296 | /* do non-tree-dependent stuff first */ | |||
1297 | switch (ies_type) { | |||
1298 | case IAX_IE_DATAFORMAT255: | |||
1299 | if (ies_len != 4) { | |||
1300 | proto_tree_add_expert(iax_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1); | |||
1301 | break; | |||
1302 | } | |||
1303 | ie_data -> dataformat = tvb_get_ntohl(tvb, offset+2); | |||
1304 | break; | |||
1305 | ||||
1306 | case IAX_IE_CALLED_NUMBER1: | |||
1307 | iax2_info->calledParty = tvb_format_text(pinfo->pool, tvb, offset+2, ies_len); | |||
1308 | break; | |||
1309 | case IAX_IE_CALLING_NUMBER2: | |||
1310 | iax2_info->callingParty = tvb_format_text(pinfo->pool, tvb, offset+2, ies_len); | |||
1311 | break; | |||
1312 | ||||
1313 | case IAX_IE_APPARENT_ADDR18: | |||
1314 | /* The IAX2 I-D says that the "apparent address" structure | |||
1315 | "is the same as the linux struct sockaddr_in", without | |||
1316 | bothering to note that the address family field is in | |||
1317 | *host* byte order in that structure (the I-D seems to be | |||
1318 | assuming that "everything is a Vax^Wx86 or x86-64" with | |||
1319 | the address family field being little-endian). | |||
1320 | ||||
1321 | This means the address family values are the Linux | |||
1322 | address family values. */ | |||
1323 | apparent_addr_family = tvb_get_letohs(tvb, offset+2); | |||
1324 | switch (apparent_addr_family) { | |||
1325 | case LINUX_AF_INET2: | |||
1326 | /* IAX is always over UDP */ | |||
1327 | ie_data->peer_ptype = PT_UDP; | |||
1328 | ie_data->peer_port = tvb_get_ntohs(tvb, offset+4); | |||
1329 | ||||
1330 | /* the ip address is big-endian, but then so is peer_address.data */ | |||
1331 | set_address_tvb(&ie_data->peer_address, AT_IPv4, 4, tvb, offset+6); | |||
1332 | break; | |||
1333 | ||||
1334 | default: | |||
1335 | expert_add_info_format(pinfo, iax_item, &ei_iax_peer_address_unsupported, | |||
1336 | "Not supported in IAX dissector: peer address family of %u", apparent_addr_family); | |||
1337 | break; | |||
1338 | } | |||
1339 | break; | |||
1340 | } | |||
1341 | ||||
1342 | ||||
1343 | /* the rest of this stuff only needs doing if we have an iax_tree */ | |||
1344 | ||||
1345 | if (iax_tree && ies_type
| |||
1346 | proto_item *ti, *ie_item = NULL((void*)0); | |||
1347 | proto_tree *ies_tree; | |||
1348 | int ie_hf = hf_iax2_ies[ies_type]; | |||
1349 | ||||
1350 | ies_tree = proto_tree_add_subtree(iax_tree, tvb, offset, ies_len+2, ett_iax2_ie, &ti, " "); | |||
1351 | ||||
1352 | proto_tree_add_uint(ies_tree, hf_iax2_ie_id, tvb, offset, 1, ies_type); | |||
1353 | proto_tree_add_uint(ies_tree, hf_iax2_length, tvb, offset + 1, 1, ies_len); | |||
1354 | ||||
1355 | ||||
1356 | /* hf_iax2_ies[] is an array, indexed by IE number, of header-fields, one | |||
1357 | per IE. Apart from a couple of special cases which require more | |||
1358 | complex decoding, we can just look up an entry from the array, and add | |||
1359 | the relevant item, although the encoding value used depends on the | |||
1360 | type of the item. | |||
1361 | */ | |||
1362 | ||||
1363 | switch (ies_type) { | |||
1364 | case IAX_IE_DATETIME31: | |||
1365 | ie_item = dissect_datetime_ie(tvb, offset, ies_tree); | |||
1366 | break; | |||
1367 | ||||
1368 | ||||
1369 | case IAX_IE_CAPABILITY8: | |||
1370 | { | |||
1371 | if (ies_len != 4) { | |||
1372 | proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1); | |||
1373 | break; | |||
1374 | } | |||
1375 | ||||
1376 | ie_item = | |||
1377 | proto_tree_add_bitmask(ies_tree, tvb, offset + 2, ie_hf, | |||
1378 | ett_iax2_codecs, hf_iax2_caps, ENC_BIG_ENDIAN0x00000000); | |||
1379 | break; | |||
1380 | } | |||
1381 | ||||
1382 | ||||
1383 | case IAX_IE_CAPABILITY255: | |||
1384 | { | |||
1385 | int version = tvb_get_uint8(tvb, offset + 2); | |||
1386 | ||||
1387 | proto_tree_add_uint(ies_tree, hf_iax2_version, tvb, offset + 2, 1, version); | |||
1388 | ||||
1389 | if (version == 0) { | |||
1390 | if (ies_len != 9) { | |||
1391 | proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1); | |||
1392 | break; | |||
1393 | } | |||
1394 | ||||
1395 | ie_item = | |||
1396 | proto_tree_add_bitmask(ies_tree, tvb, offset + 3, ie_hf, | |||
1397 | ett_iax2_codecs, hf_iax2_caps, ENC_BIG_ENDIAN0x00000000); | |||
1398 | } | |||
1399 | break; | |||
1400 | } | |||
1401 | ||||
1402 | ||||
1403 | case IAX_IE_FORMAT9: | |||
1404 | { | |||
1405 | if (ies_len != 4) { | |||
1406 | proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1); | |||
1407 | break; | |||
1408 | } | |||
1409 | ||||
1410 | ie_item = | |||
1411 | proto_tree_add_item(ies_tree, ie_hf, | |||
1412 | tvb, offset + 2, 4, ENC_BIG_ENDIAN0x00000000); | |||
1413 | break; | |||
1414 | } | |||
1415 | ||||
1416 | ||||
1417 | case IAX_IE_FORMAT256: | |||
1418 | { | |||
1419 | int version = tvb_get_uint8(tvb, offset + 2); | |||
1420 | ||||
1421 | proto_tree_add_uint(ies_tree, hf_iax2_version, tvb, offset + 2, 1, version); | |||
1422 | ||||
1423 | if (version == 0) { | |||
1424 | if (ies_len != 9) { | |||
1425 | proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1); | |||
1426 | break; | |||
1427 | } | |||
1428 | ||||
1429 | ie_item = | |||
1430 | proto_tree_add_item(ies_tree, ie_hf, | |||
1431 | tvb, offset + 3, 8, ENC_BIG_ENDIAN0x00000000); | |||
1432 | } | |||
1433 | break; | |||
1434 | } | |||
1435 | ||||
1436 | ||||
1437 | case IAX_IE_APPARENT_ADDR18: | |||
1438 | { | |||
1439 | proto_tree *sockaddr_tree; | |||
1440 | ||||
1441 | sockaddr_tree = proto_tree_add_subtree(ies_tree, tvb, offset + 2, 16, | |||
1442 | ett_iax2_ies_apparent_addr, &ie_item, "Apparent Address"); | |||
1443 | ||||
1444 | /* The IAX2 I-D says that the "apparent address" structure | |||
1445 | "is the same as the linux struct sockaddr_in", without | |||
1446 | bothering to note that the address family field is in | |||
1447 | *host* byte order in that structure (the I-D seems to be | |||
1448 | assuming that "everything is a Vax^Wx86 or x86-64" with | |||
1449 | the address family field being little-endian). | |||
1450 | ||||
1451 | This means the address family values are the Linux | |||
1452 | address family values. */ | |||
1453 | apparent_addr_family = tvb_get_letohs(tvb, offset+2); | |||
1454 | proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINFAMILY, tvb, offset + 2, 2, apparent_addr_family); | |||
1455 | ||||
1456 | if (apparent_addr_family == LINUX_AF_INET2) { | |||
1457 | uint32_t addr; | |||
1458 | proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINPORT, tvb, offset + 4, 2, ie_data->peer_port); | |||
1459 | memcpy(&addr, ie_data->peer_address.data, 4); | |||
| ||||
1460 | proto_tree_add_ipv4(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINADDR, tvb, offset + 6, 4, addr); | |||
1461 | } | |||
1462 | break; | |||
1463 | } | |||
1464 | ||||
1465 | default: | |||
1466 | if (ie_hf != 0) { | |||
1467 | int explen = proto_registrar_get_length(ie_hf); | |||
1468 | if (explen != 0 && ies_len != explen) { | |||
1469 | proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1); | |||
1470 | break; | |||
1471 | } | |||
1472 | ||||
1473 | switch (proto_registrar_get_ftype(ie_hf)) { | |||
1474 | case FT_UINT8: | |||
1475 | case FT_UINT16: | |||
1476 | case FT_UINT24: | |||
1477 | case FT_UINT32: | |||
1478 | case FT_UINT64: | |||
1479 | case FT_INT8: | |||
1480 | case FT_INT16: | |||
1481 | case FT_INT24: | |||
1482 | case FT_INT32: | |||
1483 | case FT_INT64: | |||
1484 | case FT_BOOLEAN: | |||
1485 | case FT_IPv4: | |||
1486 | ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN0x00000000); | |||
1487 | break; | |||
1488 | ||||
1489 | case FT_BYTES: | |||
1490 | case FT_NONE: | |||
1491 | ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_NA0x00000000); | |||
1492 | break; | |||
1493 | ||||
1494 | case FT_STRING: | |||
1495 | case FT_STRINGZ: | |||
1496 | ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_UTF_80x00000002|ENC_NA0x00000000); | |||
1497 | break; | |||
1498 | ||||
1499 | default: | |||
1500 | DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\"" , "epan/dissectors/packet-iax2.c", 1500)); | |||
1501 | break; | |||
1502 | } | |||
1503 | } else { | |||
1504 | /* we don't understand this ie: add a generic one */ | |||
1505 | uint32_t value; | |||
1506 | const uint8_t *ptr; | |||
1507 | const char *ie_name = val_to_str_ext_const(ies_type, &iax_ies_type_ext, "Unknown"); | |||
1508 | ||||
1509 | switch (ies_len) { | |||
1510 | case 1: | |||
1511 | value = tvb_get_uint8(tvb, offset + 2); | |||
1512 | ie_item = | |||
1513 | proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTE, | |||
1514 | tvb, offset+2, 1, value, | |||
1515 | "%s: %#02x", ie_name, value); | |||
1516 | break; | |||
1517 | ||||
1518 | case 2: | |||
1519 | value = tvb_get_ntohs(tvb, offset + 2); | |||
1520 | ie_item = | |||
1521 | proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I16, | |||
1522 | tvb, offset+2, 2, value, | |||
1523 | "%s: %#04x", ie_name, value); | |||
1524 | break; | |||
1525 | ||||
1526 | case 4: | |||
1527 | value = tvb_get_ntohl(tvb, offset + 2); | |||
1528 | ie_item = | |||
1529 | proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I32, | |||
1530 | tvb, offset+2, 4, value, | |||
1531 | "%s: %#08x", ie_name, value); | |||
1532 | break; | |||
1533 | ||||
1534 | default: | |||
1535 | ptr = tvb_get_string_enc(pinfo->pool, tvb, offset + 2, ies_len, ENC_ASCII0x00000000); | |||
1536 | ie_item = | |||
1537 | proto_tree_add_string_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTES, | |||
1538 | tvb, offset+2, ies_len, ptr, | |||
1539 | "%s: %s", ie_name, ptr); | |||
1540 | break; | |||
1541 | } | |||
1542 | } | |||
1543 | break; | |||
1544 | } | |||
1545 | ||||
1546 | /* Retrieve the text from the item we added, and append it to the main IE | |||
1547 | * item */ | |||
1548 | if (ie_item && !proto_item_is_hidden(ti)) { | |||
1549 | field_info *ie_finfo = PITEM_FINFO(ie_item)((ie_item)->finfo); | |||
1550 | ||||
1551 | /* if the representation of the item has already been set, use that; | |||
1552 | else we have to allocate a block to put the text into */ | |||
1553 | if (ie_finfo && ie_finfo->rep != NULL((void*)0)) | |||
1554 | proto_item_set_text(ti, "Information Element: %s", | |||
1555 | ie_finfo->rep->representation); | |||
1556 | else { | |||
1557 | uint8_t *ie_val = (uint8_t *)wmem_alloc(pinfo->pool, ITEM_LABEL_LENGTH240); | |||
1558 | proto_item_fill_label(ie_finfo, ie_val, NULL((void*)0)); | |||
1559 | proto_item_set_text(ti, "Information Element: %s", | |||
1560 | ie_val); | |||
1561 | } | |||
1562 | } | |||
1563 | } | |||
1564 | ||||
1565 | offset += ies_len + 2; | |||
1566 | } | |||
1567 | return offset; | |||
1568 | } | |||
1569 | ||||
1570 | static uint32_t uncompress_subclass(uint8_t csub) | |||
1571 | { | |||
1572 | /* If the SC_LOG flag is set, return 2^csub otherwise csub */ | |||
1573 | if (csub & 0x80) { | |||
1574 | /* special case for 'compressed' -1 */ | |||
1575 | if (csub == 0xff) | |||
1576 | return (uint32_t)-1; | |||
1577 | else | |||
1578 | return csub & 0x3F; | |||
1579 | } | |||
1580 | else { | |||
1581 | switch (csub) { | |||
1582 | case 0x01: return 0; | |||
1583 | case 0x02: return 1; | |||
1584 | case 0x04: return 2; | |||
1585 | case 0x08: return 3; | |||
1586 | case 0x10: return 4; | |||
1587 | case 0x20: return 5; | |||
1588 | case 0x40: return 6; | |||
1589 | default: return (uint32_t)-1; | |||
1590 | } | |||
1591 | } | |||
1592 | } | |||
1593 | ||||
1594 | /* returns the new offset */ | |||
1595 | static uint32_t dissect_iax2_command(tvbuff_t *tvb, uint32_t offset, | |||
1596 | packet_info *pinfo, proto_tree *tree, | |||
1597 | iax_packet_data *iax_packet) | |||
1598 | { | |||
1599 | uint8_t csub = tvb_get_uint8(tvb, offset); | |||
1600 | proto_item* ti; | |||
1601 | iax2_ie_data ie_data; | |||
1602 | iax_call_data *iax_call; | |||
1603 | ||||
1604 | ie_data.peer_address.type = AT_NONE; | |||
1605 | ie_data.peer_address.len = 0; | |||
1606 | ie_data.peer_address.data = NULL((void*)0); | |||
1607 | ie_data.peer_ptype = PT_NONE; | |||
1608 | ie_data.peer_port = 0; | |||
1609 | ie_data.peer_callno = 0; | |||
1610 | ie_data.dataformat = (uint32_t)-1; | |||
1611 | iax_call = iax_packet -> call_data; | |||
1612 | ||||
1613 | /* add the subclass */ | |||
1614 | ti = proto_tree_add_uint(tree, hf_iax2_iax_csub, tvb, offset, 1, csub); | |||
1615 | offset++; | |||
1616 | ||||
1617 | col_append_fstr(pinfo->cinfo, COL_INFO, " %s", | |||
1618 | val_to_str_ext(pinfo->pool, csub, &iax_iax_subclasses_ext, "unknown (0x%02x)")); | |||
1619 | ||||
1620 | if (offset >= tvb_reported_length(tvb)) | |||
1621 | return offset; | |||
1622 | ||||
1623 | offset = dissect_ies(tvb, pinfo, offset, tree, ti, &ie_data); | |||
1624 | ||||
1625 | /* if this is a data call, set up a subdissector for the circuit */ | |||
1626 | if (iax_call && ie_data.dataformat != (uint32_t)-1 && iax_call -> subdissector == NULL((void*)0)) { | |||
1627 | iax_call -> subdissector = dissector_get_uint_handle(iax2_dataformat_dissector_table, ie_data.dataformat); | |||
1628 | iax_call -> dataformat = (iax_dataformat_t)ie_data.dataformat; | |||
1629 | } | |||
1630 | ||||
1631 | /* if this is a transfer request, record it in the call data */ | |||
1632 | if (csub == IAX_COMMAND_TXREQ22 && iax_packet -> first_time) { | |||
1633 | if (ie_data.peer_address.type != AT_NONE && ie_data.peer_callno != 0) { | |||
1634 | unsigned tx_circuit = iax_circuit_lookup(&ie_data.peer_address, | |||
1635 | ie_data.peer_ptype, | |||
1636 | ie_data.peer_port, | |||
1637 | ie_data.peer_callno); | |||
1638 | ||||
1639 | iax2_new_circuit_for_call(pinfo, NULL((void*)0), tx_circuit, pinfo->num, iax_call, iax_packet->reversed); | |||
1640 | } | |||
1641 | } | |||
1642 | ||||
1643 | return offset; | |||
1644 | } | |||
1645 | ||||
1646 | static void iax2_add_ts_fields(packet_info *pinfo, proto_tree *iax2_tree, tvbuff_t *tvb, iax_packet_data *iax_packet, packet_type type, uint32_t relts) | |||
1647 | { | |||
1648 | uint32_t full_relts = relts; | |||
1649 | nstime_t lateness; | |||
1650 | proto_item *item; | |||
1651 | ||||
1652 | if (iax_packet->call_data == NULL((void*)0)) { | |||
1653 | /* no call info for this frame; perhaps we missed the NEW packet */ | |||
1654 | return; | |||
1655 | } | |||
1656 | ||||
1657 | if (iax_packet->abstime.secs == -1) { | |||
1658 | nstime_t rel; | |||
1659 | ||||
1660 | switch (type) { | |||
1661 | case IAX2_MINI_VOICE_PACKET: | |||
1662 | /* RFC 5456 says | |||
1663 | * | |||
1664 | * Abbreviated 'Mini Frames' are normally used for audio and | |||
1665 | * video; however, each time the time-stamp is a multiple of | |||
1666 | * 32,768 (0x8000 hex), a standard or 'Full Frame' MUST be sent. | |||
1667 | * | |||
1668 | * and, for what it later calls "Mini Frames", by which it means | |||
1669 | * what we're calling "mini voice packets", it says: | |||
1670 | * | |||
1671 | * Mini frames carry a 16-bit time-stamp, which is the lower 16 bits | |||
1672 | * of the transmitting peer's full 32-bit time-stamp for the call. | |||
1673 | * The time-stamp allows synchronization of incoming frames so that | |||
1674 | * they MAY be processed in chronological order instead of the | |||
1675 | * (possibly different) order in which they are received. The 16-bit | |||
1676 | * time-stamp wraps after 65.536 seconds, at which point a full frame | |||
1677 | * SHOULD be sent to notify the remote peer that its time-stamp has | |||
1678 | * been reset. A call MUST continue to send mini frames starting | |||
1679 | * with time-stamp 0 even if acknowledgment of the resynchronization | |||
1680 | * is not received. | |||
1681 | * | |||
1682 | * *If* we see all the full frames, that means we *should* be able | |||
1683 | * to convert the 16-bit time stamp to a full 32-bit time stamp by | |||
1684 | * ORing the upper 16 bits of the last full frame time stamp we saw | |||
1685 | * in above the 16-bit time stamp. | |||
1686 | * | |||
1687 | * XXX - what, if anything, should we do about full frames we've | |||
1688 | * missed? */ | |||
1689 | full_relts = (iax_packet->call_data->last_full_frame_ts & 0xFFFF0000) | relts; | |||
1690 | break; | |||
1691 | ||||
1692 | case IAX2_FULL_PACKET: | |||
1693 | case IAX2_TRUNK_PACKET: | |||
1694 | /* Timestamps have the full 32 bits of the timestamp. | |||
1695 | * Save it, to add to the mini-packet time stamps. | |||
1696 | * | |||
1697 | * XXX - that's a maximum of 4294967296 milliseconds | |||
1698 | * or about 4294967 seconds or about 49 days. | |||
1699 | * Do we need to worry about that overflowing? */ | |||
1700 | full_relts = relts; | |||
1701 | iax_packet->call_data->last_full_frame_ts = full_relts; | |||
1702 | break; | |||
1703 | ||||
1704 | case IAX2_MINI_VIDEO_PACKET: | |||
1705 | /* See the comment above in the IAX2_MINI_VOICE_PACKET case. | |||
1706 | * Note also that RFC 5456 says, in section 8.1.3.1 "Meta Video | |||
1707 | * Frames", which covers what we're calling "mini video packets": | |||
1708 | * | |||
1709 | * Meta video frames carry a 16-bit time-stamp, which is the lower 16 | |||
1710 | * bits of the transmitting peer's full 32-bit time-stamp for the | |||
1711 | * call. When this time-stamp wraps, a Full Frame SHOULD be sent to | |||
1712 | * notify the remote peer that the time-stamp has been reset to 0. | |||
1713 | * | |||
1714 | * *but* it also shows the uppermost bit of that time stamp as "?", | |||
1715 | * with a 15-bit time stamp, in the ASCII-art packet diagram after | |||
1716 | * it. dissect_minivideopacket() says "bit 15 of the ts is used to | |||
1717 | * represent the rtp 'marker' bit"; presumably that's what's going | |||
1718 | * on, but the RFC doesn't say that. | |||
1719 | * | |||
1720 | * So we assume that the time stamp is only 15 bits, and that the | |||
1721 | * upper *17* bits of the last full frame's time stamp need to be | |||
1722 | * ORed in above the 15 bits of time stamp. | |||
1723 | * | |||
1724 | * XXX - do we need to worry about overflows or missed packets | |||
1725 | * with full timestamps? */ | |||
1726 | full_relts = (iax_packet->call_data->last_full_frame_ts & 0xFFFF8000) | relts; | |||
1727 | break; | |||
1728 | } | |||
1729 | ||||
1730 | /* Convert the full relative time stamp to an nstime_t */ | |||
1731 | rel.secs = full_relts / 1000; | |||
1732 | rel.nsecs = (full_relts % 1000) * 1000000; | |||
1733 | ||||
1734 | /* Add it to the start time to get the absolute time. */ | |||
1735 | nstime_sum(&iax_packet->abstime, &iax_packet->call_data->start_time, &rel); | |||
1736 | } | |||
1737 | iax2_info->timestamp = relts; /* raw time stamp; nobody uses it */ | |||
1738 | ||||
1739 | if (iax2_tree) { | |||
1740 | item = proto_tree_add_time(iax2_tree, hf_iax2_absts, tvb, 0, 0, &iax_packet->abstime); | |||
1741 | proto_item_set_generated(item); | |||
1742 | ||||
1743 | nstime_delta(&lateness, &pinfo->abs_ts, &iax_packet->abstime); | |||
1744 | ||||
1745 | item = proto_tree_add_time(iax2_tree, hf_iax2_lateness, tvb, 0, 0, &lateness); | |||
1746 | proto_item_set_generated(item); | |||
1747 | } | |||
1748 | } | |||
1749 | ||||
1750 | /* returns the new offset */ | |||
1751 | static uint32_t | |||
1752 | dissect_fullpacket(tvbuff_t *tvb, uint32_t offset, | |||
1753 | uint16_t scallno, | |||
1754 | packet_info *pinfo, proto_tree *iax2_tree, | |||
1755 | proto_tree *main_tree) | |||
1756 | { | |||
1757 | uint16_t dcallno; | |||
1758 | uint32_t ts; | |||
1759 | uint8_t type; | |||
1760 | uint8_t csub; | |||
1761 | uint32_t codec; | |||
1762 | ||||
1763 | proto_tree *packet_type_tree = NULL((void*)0); | |||
1764 | iax_call_data *iax_call; | |||
1765 | iax_packet_data *iax_packet; | |||
1766 | bool_Bool reversed; | |||
1767 | bool_Bool rtp_marker; | |||
1768 | ||||
1769 | /* | |||
1770 | * remove the top bit for retransmission detection | |||
1771 | */ | |||
1772 | dcallno = tvb_get_ntohs(tvb, offset) & 0x7FFF; | |||
1773 | ts = tvb_get_ntohl(tvb, offset + 2); | |||
1774 | type = tvb_get_uint8(tvb, offset + 8); | |||
1775 | csub = tvb_get_uint8(tvb, offset + 9); | |||
1776 | iax2_info->ftype = type; | |||
1777 | iax2_info->csub = csub; | |||
1778 | iax2_info->scallno = scallno; | |||
1779 | iax2_info->dcallno = dcallno; | |||
1780 | ||||
1781 | /* see if we've seen this packet before */ | |||
1782 | iax_packet = (iax_packet_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0); | |||
1783 | if (!iax_packet) { | |||
1784 | /* if not, find or create an iax_call info structure for this IAX session. */ | |||
1785 | ||||
1786 | if (type == AST_FRAME_IAX6 && csub == IAX_COMMAND_NEW1) { | |||
1787 | /* NEW packets start a new call */ | |||
1788 | iax_call = iax_new_call(pinfo, scallno); | |||
1789 | reversed = false0; | |||
1790 | } else { | |||
1791 | iax_call = iax_lookup_call(pinfo, scallno, dcallno, | |||
1792 | &reversed); | |||
1793 | } | |||
1794 | ||||
1795 | iax_packet = iax_new_packet_data(iax_call, reversed); | |||
1796 | p_add_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0, iax_packet); | |||
1797 | } else { | |||
1798 | iax_call = iax_packet->call_data; | |||
1799 | reversed = iax_packet->reversed; | |||
1800 | } | |||
1801 | ||||
1802 | iax2_populate_pinfo_from_packet_data(pinfo, iax_packet); | |||
1803 | ||||
1804 | if (iax2_tree) { | |||
1805 | proto_item *packet_type_base; | |||
1806 | ||||
1807 | proto_tree_add_item(iax2_tree, hf_iax2_dcallno, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); | |||
1808 | ||||
1809 | proto_tree_add_item(iax2_tree, hf_iax2_retransmission, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); | |||
1810 | ||||
1811 | if (iax_call
| |||
1812 | proto_item *item = | |||
1813 | proto_tree_add_uint(iax2_tree, hf_iax2_callno, tvb, 0, 4, | |||
1814 | iax_call->forward_circuit_ids[0]); | |||
1815 | proto_item_set_generated(item); | |||
1816 | } | |||
1817 | ||||
1818 | proto_tree_add_uint(iax2_tree, hf_iax2_ts, tvb, offset+2, 4, ts); | |||
1819 | iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_FULL_PACKET, ts); | |||
1820 | ||||
1821 | proto_tree_add_item(iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1, | |||
1822 | ENC_BIG_ENDIAN0x00000000); | |||
1823 | ||||
1824 | proto_tree_add_item(iax2_tree, hf_iax2_iseqno, tvb, offset+7, 1, | |||
1825 | ENC_BIG_ENDIAN0x00000000); | |||
1826 | packet_type_base = proto_tree_add_uint(iax2_tree, hf_iax2_type, tvb, | |||
1827 | offset+8, 1, type); | |||
1828 | ||||
1829 | /* add the type-specific subtree */ | |||
1830 | packet_type_tree = proto_item_add_subtree(packet_type_base, ett_iax2_type); | |||
1831 | } else { | |||
1832 | iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_FULL_PACKET, ts); | |||
1833 | } | |||
1834 | ||||
1835 | ||||
1836 | /* add frame type to info line */ | |||
1837 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s, source call# %d, timestamp %ums", | |||
1838 | val_to_str_ext(pinfo->pool, type, &iax_frame_types_ext, "Unknown (0x%02x)"), | |||
1839 | scallno, ts); | |||
1840 | ||||
1841 | iax2_info->messageName = val_to_str_ext(pinfo->pool, type, &iax_frame_types_ext, "Unknown (0x%02x)"); | |||
1842 | ||||
1843 | switch (type) { | |||
1844 | case AST_FRAME_IAX6: | |||
1845 | offset=dissect_iax2_command(tvb, offset+9, pinfo, packet_type_tree, iax_packet); | |||
1846 | iax2_info->messageName = val_to_str_ext(pinfo->pool, csub, &iax_iax_subclasses_ext, "unknown (0x%02x)"); | |||
1847 | if (csub < NUM_TAP_IAX_VOIP_STATES(sizeof (tap_iax_voip_state) / sizeof (tap_iax_voip_state)[0] )) iax2_info->callState = tap_iax_voip_state[csub]; | |||
1848 | break; | |||
1849 | ||||
1850 | case AST_FRAME_DTMF_BEGIN12: | |||
1851 | case AST_FRAME_DTMF_END1: | |||
1852 | proto_tree_add_item(packet_type_tree, hf_iax2_dtmf_csub, tvb, offset+9, 1, ENC_ASCII0x00000000); | |||
1853 | offset += 10; | |||
1854 | ||||
1855 | col_append_fstr(pinfo->cinfo, COL_INFO, " digit %s", format_char(pinfo->pool, csub)); | |||
1856 | break; | |||
1857 | ||||
1858 | case AST_FRAME_CONTROL4: | |||
1859 | /* add the subclass */ | |||
1860 | proto_tree_add_uint(packet_type_tree, hf_iax2_cmd_csub, tvb, | |||
1861 | offset+9, 1, csub); | |||
1862 | offset += 10; | |||
1863 | ||||
1864 | col_append_fstr(pinfo->cinfo, COL_INFO, " %s", | |||
1865 | val_to_str_ext(pinfo->pool, csub, &iax_cmd_subclasses_ext, "unknown (0x%02x)")); | |||
1866 | iax2_info->messageName = val_to_str_ext(pinfo->pool, csub, &iax_cmd_subclasses_ext, "unknown (0x%02x)"); | |||
1867 | if (csub < NUM_TAP_CMD_VOIP_STATES(sizeof (tap_cmd_voip_state) / sizeof (tap_cmd_voip_state)[0] )) iax2_info->callState = tap_cmd_voip_state[csub]; | |||
1868 | break; | |||
1869 | ||||
1870 | case AST_FRAME_VOICE2: | |||
1871 | /* add the codec */ | |||
1872 | iax_packet -> codec = codec = uncompress_subclass(csub); | |||
1873 | ||||
1874 | if (packet_type_tree) { | |||
1875 | proto_item *item; | |||
1876 | proto_tree_add_item(packet_type_tree, hf_iax2_voice_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN0x00000000); | |||
1877 | item = proto_tree_add_uint64(packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, CODEC_MASK(codec)((codec) == (uint32_t)-1 ? 0 : (1UL << (codec)))); | |||
1878 | proto_item_set_generated(item); | |||
1879 | } | |||
1880 | ||||
1881 | offset += 10; | |||
1882 | ||||
1883 | if (iax_call) { | |||
1884 | if (reversed) { | |||
1885 | iax_call->dst_codec = codec; | |||
1886 | } else { | |||
1887 | iax_call->src_codec = codec; | |||
1888 | } | |||
1889 | } | |||
1890 | ||||
1891 | dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, false0, iax_packet); | |||
1892 | break; | |||
1893 | ||||
1894 | case AST_FRAME_VIDEO3: | |||
1895 | /* bit 6 of the csub is used to represent the rtp 'marker' bit */ | |||
1896 | rtp_marker = csub & 0x40 ? true1:false0; | |||
1897 | iax_packet -> codec = codec = uncompress_subclass((uint8_t)(csub & ~0x40)); | |||
1898 | ||||
1899 | if (packet_type_tree) { | |||
1900 | proto_item *item; | |||
1901 | proto_tree_add_item(packet_type_tree, hf_iax2_video_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN0x00000000); | |||
1902 | proto_tree_add_item(packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, ENC_BIG_ENDIAN0x00000000); | |||
1903 | item = proto_tree_add_uint64(packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, CODEC_MASK(codec)((codec) == (uint32_t)-1 ? 0 : (1UL << (codec)))); | |||
1904 | proto_item_set_generated(item); | |||
1905 | } | |||
1906 | ||||
1907 | offset += 10; | |||
1908 | ||||
1909 | if (iax_call && iax_packet -> first_time) { | |||
1910 | if (reversed) { | |||
1911 | iax_call->dst_vformat = codec; | |||
1912 | } else { | |||
1913 | iax_call->src_vformat = codec; | |||
1914 | } | |||
1915 | } | |||
1916 | ||||
1917 | if (rtp_marker) | |||
1918 | col_append_str(pinfo->cinfo, COL_INFO, ", Mark"); | |||
1919 | ||||
1920 | ||||
1921 | dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, true1, iax_packet); | |||
1922 | break; | |||
1923 | ||||
1924 | case AST_FRAME_MODEM11: | |||
1925 | proto_tree_add_item(packet_type_tree, hf_iax2_modem_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN0x00000000); | |||
1926 | offset += 10; | |||
1927 | ||||
1928 | col_append_fstr(pinfo->cinfo, COL_INFO, " %s", | |||
1929 | val_to_str(pinfo->pool, csub, iax_modem_subclasses, "unknown (0x%02x)")); | |||
1930 | break; | |||
1931 | ||||
1932 | case AST_FRAME_TEXT7: | |||
1933 | proto_tree_add_item(packet_type_tree, hf_iax2_text_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN0x00000000); | |||
1934 | offset += 10; | |||
1935 | ||||
1936 | { | |||
1937 | int textlen = tvb_captured_length_remaining(tvb, offset); | |||
1938 | if (textlen > 0) | |||
1939 | { | |||
1940 | proto_tree_add_item(packet_type_tree, hf_iax2_text_text, tvb, offset, textlen, ENC_UTF_80x00000002); | |||
1941 | offset += textlen; | |||
1942 | } | |||
1943 | } | |||
1944 | break; | |||
1945 | ||||
1946 | case AST_FRAME_HTML9: | |||
1947 | proto_tree_add_item(packet_type_tree, hf_iax2_html_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN0x00000000); | |||
1948 | offset += 10; | |||
1949 | ||||
1950 | if (csub == 0x01) | |||
1951 | { | |||
1952 | int urllen = tvb_captured_length_remaining(tvb, offset); | |||
1953 | if (urllen > 0) | |||
1954 | { | |||
1955 | proto_item *pi = proto_tree_add_item(packet_type_tree, hf_iax2_html_url, tvb, offset, urllen, ENC_UTF_80x00000002); | |||
1956 | proto_item_set_url(pi); | |||
1957 | offset += urllen; | |||
1958 | } | |||
1959 | } | |||
1960 | break; | |||
1961 | ||||
1962 | case AST_FRAME_CNG10: | |||
1963 | default: | |||
1964 | proto_tree_add_uint(packet_type_tree, hf_iax2_csub, tvb, offset+9, | |||
1965 | 1, csub); | |||
1966 | offset += 10; | |||
1967 | ||||
1968 | col_append_fstr(pinfo->cinfo, COL_INFO, " subclass %d", csub); | |||
1969 | break; | |||
1970 | } | |||
1971 | ||||
1972 | /* next time we come to parse this packet, don't propagate the codec into the | |||
1973 | * call_data */ | |||
1974 | iax_packet->first_time = false0; | |||
1975 | ||||
1976 | return offset; | |||
1977 | } | |||
1978 | ||||
1979 | static iax_packet_data *iax2_get_packet_data_for_minipacket(packet_info *pinfo, | |||
1980 | uint16_t scallno, | |||
1981 | bool_Bool video) | |||
1982 | { | |||
1983 | /* see if we've seen this packet before */ | |||
1984 | iax_packet_data *p = (iax_packet_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0); | |||
1985 | ||||
1986 | if (!p) { | |||
1987 | /* if not, find or create an iax_call info structure for this IAX session. */ | |||
1988 | bool_Bool reversed; | |||
1989 | iax_call_data *iax_call; | |||
1990 | ||||
1991 | iax_call = iax_lookup_call(pinfo, scallno, 0, &reversed); | |||
1992 | ||||
1993 | p = iax_new_packet_data(iax_call, reversed); | |||
1994 | p_add_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0, p); | |||
1995 | ||||
1996 | /* set the codec for this frame to be whatever the last full frame used */ | |||
1997 | if (iax_call) { | |||
1998 | if (video) | |||
1999 | p->codec = reversed ? iax_call -> dst_vformat : iax_call -> src_vformat; | |||
2000 | else | |||
2001 | p->codec = reversed ? iax_call -> dst_codec : iax_call -> src_codec; | |||
2002 | } | |||
2003 | } | |||
2004 | ||||
2005 | iax2_populate_pinfo_from_packet_data(pinfo, p); | |||
2006 | return p; | |||
2007 | } | |||
2008 | ||||
2009 | ||||
2010 | static uint32_t dissect_minivideopacket(tvbuff_t *tvb, uint32_t offset, | |||
2011 | uint16_t scallno, packet_info *pinfo, | |||
2012 | proto_tree *iax2_tree, proto_tree *main_tree) | |||
2013 | { | |||
2014 | uint32_t ts; | |||
2015 | iax_packet_data *iax_packet; | |||
2016 | bool_Bool rtp_marker; | |||
2017 | proto_item *item; | |||
2018 | ||||
2019 | ts = tvb_get_ntohs(tvb, offset); | |||
2020 | ||||
2021 | /* bit 15 of the ts is used to represent the rtp 'marker' bit */ | |||
2022 | rtp_marker = ts & 0x8000 ? true1:false0; | |||
2023 | ts &= ~0x8000; | |||
2024 | ||||
2025 | iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, true1); | |||
2026 | ||||
2027 | if (iax2_tree) { | |||
2028 | if (iax_packet->call_data) { | |||
2029 | item = | |||
2030 | proto_tree_add_uint(iax2_tree, hf_iax2_callno, tvb, 0, 4, | |||
2031 | iax_packet->call_data->forward_circuit_ids[0]); | |||
2032 | proto_item_set_generated(item); | |||
2033 | } | |||
2034 | ||||
2035 | proto_tree_add_item(iax2_tree, hf_iax2_minividts, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); | |||
2036 | iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VIDEO_PACKET, ts); | |||
2037 | proto_tree_add_item(iax2_tree, hf_iax2_minividmarker, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); | |||
2038 | } else { | |||
2039 | iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VIDEO_PACKET, ts); | |||
2040 | } | |||
2041 | ||||
2042 | offset += 2; | |||
2043 | ||||
2044 | col_add_fstr(pinfo->cinfo, COL_INFO, | |||
2045 | "Mini video packet, source call# %d, timestamp %ums%s", | |||
2046 | scallno, ts, rtp_marker?", Mark":""); | |||
2047 | ||||
2048 | ||||
2049 | dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, true1, iax_packet); | |||
2050 | ||||
2051 | /* next time we come to parse this packet, don't propagate the codec into the | |||
2052 | * call_data */ | |||
2053 | iax_packet->first_time = false0; | |||
2054 | ||||
2055 | return offset; | |||
2056 | } | |||
2057 | ||||
2058 | static uint32_t dissect_minipacket(tvbuff_t *tvb, uint32_t offset, uint16_t scallno, | |||
2059 | packet_info *pinfo, proto_tree *iax2_tree, | |||
2060 | proto_tree *main_tree) | |||
2061 | { | |||
2062 | uint32_t ts; | |||
2063 | iax_packet_data *iax_packet; | |||
2064 | proto_item *item; | |||
2065 | ||||
2066 | ts = tvb_get_ntohs(tvb, offset); | |||
2067 | ||||
2068 | iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, false0); | |||
2069 | ||||
2070 | if (iax2_tree) { | |||
2071 | if (iax_packet->call_data) { | |||
2072 | item = proto_tree_add_uint(iax2_tree, hf_iax2_callno, tvb, 0, 4, | |||
2073 | iax_packet->call_data->forward_circuit_ids[0]); | |||
2074 | proto_item_set_generated(item); | |||
2075 | } | |||
2076 | ||||
2077 | proto_tree_add_uint(iax2_tree, hf_iax2_minits, tvb, offset, 2, ts); | |||
2078 | iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VOICE_PACKET, ts); | |||
2079 | } else { | |||
2080 | iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VOICE_PACKET, ts); | |||
2081 | } | |||
2082 | ||||
2083 | ||||
2084 | offset += 2; | |||
2085 | ||||
2086 | col_add_fstr(pinfo->cinfo, COL_INFO, | |||
2087 | "Mini packet, source call# %d, timestamp %ums", | |||
2088 | scallno, ts); | |||
2089 | ||||
2090 | ||||
2091 | /* XXX fix the timestamp logic */ | |||
2092 | dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, false0, iax_packet); | |||
2093 | ||||
2094 | ||||
2095 | /* next time we come to parse this packet, don't propagate the codec into the | |||
2096 | * call_data */ | |||
2097 | iax_packet->first_time = false0; | |||
2098 | ||||
2099 | return offset; | |||
2100 | } | |||
2101 | ||||
2102 | ||||
2103 | static uint32_t dissect_trunkcall_ts(tvbuff_t *tvb, uint32_t offset, proto_tree *iax2_tree, uint16_t *scallno) | |||
2104 | { | |||
2105 | proto_tree *call_tree; | |||
2106 | uint16_t datalen, rlen, ts; | |||
2107 | /* | |||
2108 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
2109 | | Data Length (in octets) |R| Source Call Number | | |||
2110 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
2111 | | time-stamp | | | |||
2112 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | |||
2113 | | Data | | |||
2114 | : : | |||
2115 | | | | |||
2116 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
2117 | */ | |||
2118 | datalen = tvb_get_ntohs(tvb, offset); | |||
2119 | *scallno = tvb_get_ntohs(tvb, offset + 2); | |||
2120 | ts = tvb_get_ntohs(tvb, offset + 4); | |||
2121 | ||||
2122 | rlen = MIN(tvb_captured_length(tvb) - offset - 6, datalen)(((tvb_captured_length(tvb) - offset - 6) < (datalen)) ? ( tvb_captured_length(tvb) - offset - 6) : (datalen)); | |||
2123 | ||||
2124 | if (iax2_tree) { | |||
2125 | call_tree = proto_tree_add_subtree_format(iax2_tree, tvb, offset, rlen + 6, | |||
2126 | ett_iax2_trunk_call, NULL((void*)0), "Trunk call from %u, ts: %u", *scallno, ts); | |||
2127 | ||||
2128 | proto_tree_add_item(call_tree, hf_iax2_trunk_call_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); | |||
2129 | proto_tree_add_item(call_tree, hf_iax2_trunk_call_scallno, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000); | |||
2130 | proto_tree_add_item(call_tree, hf_iax2_trunk_call_ts, tvb, offset + 4, 2, ENC_BIG_ENDIAN0x00000000); | |||
2131 | proto_tree_add_item(call_tree, hf_iax2_trunk_call_data, tvb, offset + 6, rlen, ENC_NA0x00000000); | |||
2132 | } | |||
2133 | offset += 6 + rlen; | |||
2134 | ||||
2135 | return offset; | |||
2136 | } | |||
2137 | ||||
2138 | static uint32_t dissect_trunkcall_nots(tvbuff_t *tvb, uint32_t offset, proto_tree *iax2_tree, uint16_t *scallno) | |||
2139 | { | |||
2140 | proto_tree *call_tree; | |||
2141 | uint16_t datalen, rlen; | |||
2142 | /* | |||
2143 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
2144 | |R| Source Call Number | Data Length (in octets) | | |||
2145 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
2146 | | | | |||
2147 | : Data : | |||
2148 | | | | |||
2149 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
2150 | */ | |||
2151 | *scallno = tvb_get_ntohs(tvb, offset); | |||
2152 | datalen = tvb_get_ntohs(tvb, offset + 2); | |||
2153 | ||||
2154 | rlen = MIN(tvb_captured_length(tvb) - offset - 4, datalen)(((tvb_captured_length(tvb) - offset - 4) < (datalen)) ? ( tvb_captured_length(tvb) - offset - 4) : (datalen)); | |||
2155 | ||||
2156 | if (iax2_tree) { | |||
2157 | call_tree = proto_tree_add_subtree_format(iax2_tree, tvb, offset, rlen + 6, | |||
2158 | ett_iax2_trunk_call, NULL((void*)0), "Trunk call from %u", *scallno); | |||
2159 | ||||
2160 | proto_tree_add_item(call_tree, hf_iax2_trunk_call_scallno, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); | |||
2161 | proto_tree_add_item(call_tree, hf_iax2_trunk_call_len, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000); | |||
2162 | proto_tree_add_item(call_tree, hf_iax2_trunk_call_data, tvb, offset + 4, rlen, ENC_NA0x00000000); | |||
2163 | } | |||
2164 | offset += 4 + rlen; | |||
2165 | ||||
2166 | return offset; | |||
2167 | } | |||
2168 | ||||
2169 | typedef struct _call_list { | |||
2170 | uint16_t scallno; | |||
2171 | struct _call_list *next; | |||
2172 | } call_list; | |||
2173 | ||||
2174 | static call_list *call_list_append(wmem_allocator_t *pool, call_list *list, uint16_t scallno) | |||
2175 | { | |||
2176 | call_list *node = wmem_new0(pool, call_list)((call_list*)wmem_alloc0((pool), sizeof(call_list))); | |||
2177 | ||||
2178 | node->scallno = scallno; | |||
2179 | ||||
2180 | if (list) { | |||
2181 | call_list *cur = list; | |||
2182 | while (cur->next) { | |||
2183 | cur = cur->next; | |||
2184 | } | |||
2185 | cur->next = node; | |||
2186 | return list; | |||
2187 | } else { | |||
2188 | return node; | |||
2189 | } | |||
2190 | } | |||
2191 | ||||
2192 | static bool_Bool call_list_find(call_list *list, uint16_t scallno) | |||
2193 | { | |||
2194 | for (; list; list = list->next) { | |||
2195 | if (list->scallno == scallno) { | |||
2196 | return true1; | |||
2197 | } | |||
2198 | } | |||
2199 | return false0; | |||
2200 | } | |||
2201 | ||||
2202 | static unsigned call_list_length(call_list *list) | |||
2203 | { | |||
2204 | unsigned count = 0; | |||
2205 | for (; list; list = list->next) { | |||
2206 | count++; | |||
2207 | } | |||
2208 | return count; | |||
2209 | } | |||
2210 | ||||
2211 | static uint32_t dissect_trunkpacket(tvbuff_t *tvb, uint32_t offset, | |||
2212 | uint16_t scallno_param _U___attribute__((unused)), packet_info *pinfo, | |||
2213 | proto_tree *iax2_tree, proto_tree *main_tree _U___attribute__((unused))) | |||
2214 | { | |||
2215 | uint8_t cmddata, trunkts; | |||
2216 | unsigned nframes = 0, ncalls = 0; | |||
2217 | proto_item *cd, *nc = NULL((void*)0); | |||
2218 | proto_tree *field_tree = NULL((void*)0); | |||
2219 | call_list *calls = NULL((void*)0); | |||
2220 | /*iax_packet_data *iax_packet;*/ | |||
2221 | ||||
2222 | cmddata = tvb_get_uint8(tvb, offset + 1); | |||
2223 | trunkts = cmddata & IAX2_TRUNK_TS1; | |||
2224 | ||||
2225 | /* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 */ | |||
2226 | /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ | |||
2227 | /* |F| Meta Indicator |V|Meta Command | Cmd Data (0) | */ | |||
2228 | /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ | |||
2229 | /* | time-stamp | */ | |||
2230 | /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ | |||
2231 | ||||
2232 | if (iax2_tree) { | |||
2233 | /* Meta Command */ | |||
2234 | proto_tree_add_item(iax2_tree, hf_iax2_trunk_metacmd, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); | |||
2235 | ||||
2236 | /* Command data */ | |||
2237 | cd = proto_tree_add_uint(iax2_tree, hf_iax2_trunk_cmddata, tvb, offset + 1, 1, cmddata); | |||
2238 | field_tree = proto_item_add_subtree(cd, ett_iax2_trunk_cmddata); | |||
2239 | if (trunkts) | |||
2240 | proto_item_append_text(cd, " (trunk timestamps)"); | |||
2241 | ||||
2242 | /* CD -> Trunk timestamp */ | |||
2243 | proto_tree_add_boolean(field_tree, hf_iax2_trunk_cmddata_ts, tvb, offset + 1, 1, cmddata); | |||
2244 | ||||
2245 | /* Timestamp */ | |||
2246 | proto_tree_add_item(iax2_tree, hf_iax2_trunk_ts, tvb, offset + 2, 4, ENC_BIG_ENDIAN0x00000000); | |||
2247 | } | |||
2248 | ||||
2249 | offset += 6; | |||
2250 | ||||
2251 | if (trunkts) { | |||
2252 | /* Trunk calls with timestamp */ | |||
2253 | while(tvb_captured_length_remaining(tvb, offset) >= 6) { | |||
2254 | uint16_t scallno; | |||
2255 | offset = dissect_trunkcall_ts(tvb, offset, iax2_tree, &scallno); | |||
2256 | if (!call_list_find(calls, scallno)) { | |||
2257 | calls = call_list_append(pinfo->pool, calls, scallno); | |||
2258 | } | |||
2259 | nframes++; | |||
2260 | } | |||
2261 | } | |||
2262 | else { | |||
2263 | /* Trunk calls without timestamp */ | |||
2264 | while(tvb_captured_length_remaining(tvb, offset) >= 4) { | |||
2265 | uint16_t scallno; | |||
2266 | offset = dissect_trunkcall_nots(tvb, offset, iax2_tree, &scallno); | |||
2267 | if (!call_list_find(calls, scallno)) { | |||
2268 | calls = call_list_append(pinfo->pool, calls, scallno); | |||
2269 | } | |||
2270 | nframes++; | |||
2271 | } | |||
2272 | } | |||
2273 | ||||
2274 | ncalls = call_list_length(calls); | |||
2275 | ||||
2276 | if (iax2_tree) { | |||
2277 | /* number of items */ | |||
2278 | nc = proto_tree_add_uint(iax2_tree, hf_iax2_trunk_ncalls, NULL((void*)0), 0, 0, ncalls); | |||
2279 | proto_item_set_generated(nc); | |||
2280 | } | |||
2281 | ||||
2282 | col_add_fstr(pinfo->cinfo, COL_INFO, "Trunk packet with %d media frame%s for %d call%s", | |||
2283 | nframes, plurality(nframes, "", "s")((nframes) == 1 ? ("") : ("s")), | |||
2284 | ncalls, plurality(ncalls, "", "s")((ncalls) == 1 ? ("") : ("s"))); | |||
2285 | ||||
2286 | return offset; | |||
2287 | } | |||
2288 | ||||
2289 | ||||
2290 | static void process_iax_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, | |||
2291 | bool_Bool video, iax_packet_data *iax_packet) | |||
2292 | { | |||
2293 | uint32_t codec = iax_packet -> codec; | |||
2294 | iax_call_data *iax_call = iax_packet -> call_data; | |||
2295 | ||||
2296 | #ifdef DEBUG_DESEGMENT | |||
2297 | ws_debug("calling process_iax_pdu; len = %u", tvb_reported_length(tvb))do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2297, __func__, "calling process_iax_pdu; len = %u", tvb_reported_length (tvb)); } } while (0); | |||
2298 | #endif | |||
2299 | ||||
2300 | if (!video && iax_call && iax_call->subdissector) { | |||
2301 | iax2_dissector_info_t dissector_info; | |||
2302 | ||||
2303 | /* info for subdissectors. We always pass on the original forward circuit, | |||
2304 | * and steal the p2p_dir flag to indicate the direction */ | |||
2305 | if (iax_packet->call_data == NULL((void*)0)) { | |||
2306 | /* if we missed the NEW packet for this call, call_data will be null. it's | |||
2307 | * tbd what the best thing to do here is. */ | |||
2308 | memset(&dissector_info, 0, sizeof(dissector_info)); | |||
2309 | } else { | |||
2310 | dissector_info.ctype = CONVERSATION_IAX2; | |||
2311 | dissector_info.circuit_id = (uint32_t)iax_packet->call_data->forward_circuit_ids[0]; | |||
2312 | } | |||
2313 | ||||
2314 | call_dissector_with_data(iax_call->subdissector, tvb, pinfo, tree, &dissector_info); | |||
2315 | } else if (codec != 0 && dissector_try_uint(iax2_codec_dissector_table, codec, tvb, pinfo, tree)) { | |||
2316 | /* codec dissector handled our data */ | |||
2317 | } else { | |||
2318 | /* we don't know how to dissect our data: dissect it as data */ | |||
2319 | call_data_dissector(tvb, pinfo, tree); | |||
2320 | } | |||
2321 | ||||
2322 | #ifdef DEBUG_DESEGMENT | |||
2323 | ws_debug("called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u",do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2324, __func__, "called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u" , pinfo->desegment_len, pinfo->desegment_offset); } } while (0) | |||
2324 | pinfo->desegment_len, pinfo->desegment_offset)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2324, __func__, "called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u" , pinfo->desegment_len, pinfo->desegment_offset); } } while (0); | |||
2325 | #endif | |||
2326 | } | |||
2327 | ||||
2328 | static void desegment_iax(tvbuff_t *tvb, packet_info *pinfo, proto_tree *iax2_tree, | |||
2329 | proto_tree *tree, bool_Bool video, iax_packet_data *iax_packet) | |||
2330 | { | |||
2331 | ||||
2332 | iax_call_data *iax_call = iax_packet -> call_data; | |||
2333 | iax_call_dirdata *dirdata; | |||
2334 | void * value = NULL((void*)0); | |||
2335 | uint32_t frag_offset = 0; | |||
2336 | fragment_head *fd_head; | |||
2337 | bool_Bool must_desegment = false0; | |||
2338 | ||||
2339 | DISSECTOR_ASSERT(iax_call)((void) ((iax_call) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-iax2.c", 2339, "iax_call")))); | |||
2340 | ||||
2341 | pinfo->can_desegment = 2; | |||
2342 | pinfo->desegment_offset = 0; | |||
2343 | pinfo->desegment_len = 0; | |||
2344 | ||||
2345 | #ifdef DEBUG_DESEGMENT | |||
2346 | ws_debug("dissecting packet %u", pinfo->num)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2346, __func__, "dissecting packet %u", pinfo->num); } } while (0); | |||
2347 | #endif | |||
2348 | ||||
2349 | dirdata = &(iax_call->dirdata[!!(iax_packet->reversed)]); | |||
2350 | ||||
2351 | if ((!pinfo->fd->visited && (dirdata->current_frag_bytes > 0)) || | |||
2352 | ((value = g_hash_table_lookup(iax_fid_table, GUINT_TO_POINTER(pinfo->num)((gpointer) (gulong) (pinfo->num)))) != NULL((void*)0))) { | |||
2353 | ||||
2354 | /* then we are continuing an already-started pdu */ | |||
2355 | uint32_t fid; | |||
2356 | uint32_t frag_len = tvb_reported_length(tvb); | |||
2357 | bool_Bool complete; | |||
2358 | ||||
2359 | #ifdef DEBUG_DESEGMENT | |||
2360 | ws_debug("visited: %i; c_f_b: %u; hash: %u->%u", pinfo->fd->visited?1:0,do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2361, __func__, "visited: %i; c_f_b: %u; hash: %u->%u", pinfo ->fd->visited?1:0, dirdata->current_frag_bytes, pinfo ->num, dirdata->current_frag_id); } } while (0) | |||
2361 | dirdata->current_frag_bytes, pinfo->num, dirdata->current_frag_id)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2361, __func__, "visited: %i; c_f_b: %u; hash: %u->%u", pinfo ->fd->visited?1:0, dirdata->current_frag_bytes, pinfo ->num, dirdata->current_frag_id); } } while (0); | |||
2362 | #endif | |||
2363 | ||||
2364 | if (!pinfo->fd->visited) { | |||
2365 | uint32_t tot_len; | |||
2366 | fid = dirdata->current_frag_id; | |||
2367 | tot_len = dirdata->current_frag_minlen; | |||
2368 | DISSECTOR_ASSERT(g_hash_table_lookup(iax_fid_table, GUINT_TO_POINTER(pinfo->num)) == NULL)((void) ((g_hash_table_lookup(iax_fid_table, ((gpointer) (gulong ) (pinfo->num))) == ((void*)0)) ? (void)0 : (proto_report_dissector_bug ("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-iax2.c" , 2368, "g_hash_table_lookup(iax_fid_table, ((gpointer) (gulong) (pinfo->num))) == ((void*)0)" )))); | |||
2369 | g_hash_table_insert(iax_fid_table, GUINT_TO_POINTER(pinfo->num)((gpointer) (gulong) (pinfo->num)), GUINT_TO_POINTER(fid)((gpointer) (gulong) (fid))); | |||
2370 | frag_offset = dirdata->current_frag_bytes; | |||
2371 | dirdata->current_frag_bytes += frag_len; | |||
2372 | complete = dirdata->current_frag_bytes > tot_len; | |||
2373 | #ifdef DEBUG_DESEGMENT | |||
2374 | ws_debug("hash: %u->%u; frag_offset: %u; c_f_b: %u; totlen: %u",do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2375, __func__, "hash: %u->%u; frag_offset: %u; c_f_b: %u; totlen: %u" , pinfo->num, fid, frag_offset, dirdata->current_frag_bytes , tot_len); } } while (0) | |||
2375 | pinfo->num, fid, frag_offset, dirdata->current_frag_bytes, tot_len)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2375, __func__, "hash: %u->%u; frag_offset: %u; c_f_b: %u; totlen: %u" , pinfo->num, fid, frag_offset, dirdata->current_frag_bytes , tot_len); } } while (0); | |||
2376 | #endif | |||
2377 | } else { | |||
2378 | fid = GPOINTER_TO_UINT(value)((guint) (gulong) (value)); | |||
2379 | /* these values are unused by fragment_add if pinfo->fd->visited */ | |||
2380 | dirdata->current_frag_bytes = 0; | |||
2381 | complete = false0; | |||
2382 | } | |||
2383 | ||||
2384 | /* fragment_add checks for already-added */ | |||
2385 | fd_head = fragment_add(&iax_reassembly_table, tvb, 0, pinfo, fid, NULL((void*)0), | |||
2386 | frag_offset, | |||
2387 | frag_len, !complete); | |||
2388 | ||||
2389 | if (fd_head && (pinfo->num == fd_head->reassembled_in)) { | |||
2390 | int32_t old_len; | |||
2391 | tvbuff_t *next_tvb = tvb_new_chain(tvb, fd_head->tvb_data); | |||
2392 | add_new_data_source(pinfo, next_tvb, "Reassembled IAX2"); | |||
2393 | ||||
2394 | process_iax_pdu(next_tvb, pinfo, tree, video, iax_packet); | |||
2395 | ||||
2396 | /* calculate the amount of data which was available to the higher-level | |||
2397 | dissector before we added this segment; if the returned offset is | |||
2398 | within that section, the higher-level dissector was unable to find any | |||
2399 | pdus; if it's after that, it found one or more complete PDUs. | |||
2400 | */ | |||
2401 | old_len = (int32_t)(tvb_reported_length(next_tvb) - frag_len); | |||
2402 | if (pinfo->desegment_len && | |||
2403 | (pinfo->desegment_offset < old_len)) { | |||
2404 | /* oops, it wasn't actually complete */ | |||
2405 | fragment_set_partial_reassembly(&iax_reassembly_table, pinfo, fid, NULL((void*)0)); | |||
2406 | if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT0x0fffffff) { | |||
2407 | /* only one more byte should be enough for a retry */ | |||
2408 | dirdata->current_frag_minlen = fd_head->datalen + 1; | |||
2409 | } else { | |||
2410 | dirdata->current_frag_minlen = fd_head->datalen + pinfo->desegment_len; | |||
2411 | } | |||
2412 | } else { | |||
2413 | /* we successfully dissected some data; create the proto tree items for | |||
2414 | * the fragments, and flag any remaining data for desegmentation */ | |||
2415 | ||||
2416 | proto_item *iax_tree_item, *frag_tree_item; | |||
2417 | /* this nargery is to insert the fragment tree into the main tree | |||
2418 | * between the IAX protocol entry and the subdissector entry */ | |||
2419 | show_fragment_tree(fd_head, &iax2_fragment_items, tree, pinfo, next_tvb, &frag_tree_item); | |||
2420 | iax_tree_item = proto_item_get_parent(proto_tree_get_parent(iax2_tree)); | |||
2421 | if (frag_tree_item && iax_tree_item) | |||
2422 | proto_tree_move_item(tree, iax_tree_item, frag_tree_item); | |||
2423 | ||||
2424 | dirdata->current_frag_minlen = dirdata->current_frag_id = dirdata->current_frag_bytes = 0; | |||
2425 | ||||
2426 | if (pinfo->desegment_len) { | |||
2427 | /* there's a bit of data left to desegment */ | |||
2428 | must_desegment = true1; | |||
2429 | /* make desegment_offset relative to our tvb */ | |||
2430 | pinfo->desegment_offset -= old_len; | |||
2431 | } | |||
2432 | ||||
2433 | /* don't add a 'reassembled in' item for this pdu */ | |||
2434 | fd_head = NULL((void*)0); | |||
2435 | } | |||
2436 | } | |||
2437 | } else { | |||
2438 | /* This segment was not found in our table, so it doesn't | |||
2439 | contain a continuation of a higher-level PDU. | |||
2440 | Call the normal subdissector. | |||
2441 | */ | |||
2442 | ||||
2443 | process_iax_pdu(tvb, pinfo, tree, video, iax_packet); | |||
2444 | ||||
2445 | if (pinfo->desegment_len) { | |||
2446 | /* the higher-level dissector has asked for some more data - ie, | |||
2447 | the end of this segment does not coincide with the end of a | |||
2448 | higher-level PDU. */ | |||
2449 | must_desegment = true1; | |||
2450 | } | |||
2451 | ||||
2452 | fd_head = NULL((void*)0); | |||
2453 | } | |||
2454 | ||||
2455 | /* must_desegment is set if the end of this segment (or the whole of it) | |||
2456 | * contained the start of a higher-level PDU; we must add whatever is left of | |||
2457 | * this segment (after pinfo->desegment_offset) to a fragment table for disassembly. */ | |||
2458 | if (must_desegment) { | |||
2459 | uint32_t fid = pinfo->num; /* a new fragment id */ | |||
2460 | uint32_t deseg_offset = pinfo->desegment_offset; | |||
2461 | uint32_t frag_len = tvb_reported_length_remaining(tvb, deseg_offset); | |||
2462 | dirdata->current_frag_id = fid; | |||
2463 | dirdata->current_frag_bytes = frag_len; | |||
2464 | ||||
2465 | if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT0x0fffffff) { | |||
2466 | /* only one more byte should be enough for a retry */ | |||
2467 | dirdata->current_frag_minlen = frag_len + 1; | |||
2468 | } else { | |||
2469 | dirdata->current_frag_minlen = frag_len + pinfo->desegment_len; | |||
2470 | } | |||
2471 | ||||
2472 | fd_head = fragment_add(&iax_reassembly_table, | |||
2473 | tvb, deseg_offset, pinfo, fid, NULL((void*)0), | |||
2474 | 0, frag_len, true1); | |||
2475 | #ifdef DEBUG_DESEGMENT | |||
2476 | ws_debug("Start offset of undissected bytes: %u; "do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2478, __func__, "Start offset of undissected bytes: %u; " "Bytes remaining in this segment: %u; min required bytes: %u\n" , deseg_offset, frag_len, frag_len + pinfo->desegment_len) ; } } while (0) | |||
2477 | "Bytes remaining in this segment: %u; min required bytes: %u\n",do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2478, __func__, "Start offset of undissected bytes: %u; " "Bytes remaining in this segment: %u; min required bytes: %u\n" , deseg_offset, frag_len, frag_len + pinfo->desegment_len) ; } } while (0) | |||
2478 | deseg_offset, frag_len, frag_len + pinfo->desegment_len)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-iax2.c" , 2478, __func__, "Start offset of undissected bytes: %u; " "Bytes remaining in this segment: %u; min required bytes: %u\n" , deseg_offset, frag_len, frag_len + pinfo->desegment_len) ; } } while (0); | |||
2479 | #endif | |||
2480 | } | |||
2481 | ||||
2482 | /* add a 'reassembled in' item if necessary */ | |||
2483 | if (fd_head != NULL((void*)0)) { | |||
2484 | uint32_t deseg_offset = pinfo->desegment_offset; | |||
2485 | if (fd_head->reassembled_in != 0 && | |||
2486 | !(fd_head->flags & FD_PARTIAL_REASSEMBLY0x0040)) { | |||
2487 | proto_item *iax_tree_item; | |||
2488 | iax_tree_item = proto_tree_add_uint(tree, hf_iax2_reassembled_in, | |||
2489 | tvb, deseg_offset, tvb_reported_length_remaining(tvb, deseg_offset), | |||
2490 | fd_head->reassembled_in); | |||
2491 | proto_item_set_generated(iax_tree_item); | |||
2492 | } else { | |||
2493 | /* this fragment is never reassembled */ | |||
2494 | proto_tree_add_item(tree, hf_iax2_fragment_unfinished, tvb, deseg_offset, -1, ENC_NA0x00000000); | |||
2495 | } | |||
2496 | ||||
2497 | if (pinfo->desegment_offset == 0) { | |||
2498 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAX2"); | |||
2499 | col_set_str(pinfo->cinfo, COL_INFO, "[IAX2 segment of a reassembled PDU]"); | |||
2500 | } | |||
2501 | } | |||
2502 | ||||
2503 | pinfo->can_desegment = 0; | |||
2504 | pinfo->desegment_offset = 0; | |||
2505 | pinfo->desegment_len = 0; | |||
2506 | } | |||
2507 | ||||
2508 | static void dissect_payload(tvbuff_t *tvb, uint32_t offset, | |||
2509 | packet_info *pinfo, proto_tree *iax2_tree, | |||
2510 | proto_tree *tree, uint32_t ts _U___attribute__((unused)), bool_Bool video, | |||
2511 | iax_packet_data *iax_packet) | |||
2512 | { | |||
2513 | #if 0 | |||
2514 | bool_Bool out_of_order = false0; | |||
2515 | #endif | |||
2516 | tvbuff_t *sub_tvb; | |||
2517 | uint32_t codec = iax_packet -> codec; | |||
2518 | uint32_t nbytes; | |||
2519 | iax_call_data *iax_call = iax_packet -> call_data; | |||
2520 | ||||
2521 | if (offset >= tvb_reported_length(tvb)) { | |||
2522 | col_append_str(pinfo->cinfo, COL_INFO, ", empty frame"); | |||
2523 | return; | |||
2524 | } | |||
2525 | ||||
2526 | sub_tvb = tvb_new_subset_remaining(tvb, offset); | |||
2527 | ||||
2528 | /* XXX shouldn't pass through out-of-order packets. */ | |||
2529 | ||||
2530 | if (!video && iax_call && iax_call -> dataformat != 0) { | |||
2531 | col_append_fstr(pinfo->cinfo, COL_INFO, ", data, format %s", | |||
2532 | val_to_str(pinfo->pool, iax_call -> dataformat, | |||
2533 | iax_dataformats, "unknown (0x%02x)")); | |||
2534 | #if 0 | |||
2535 | if (out_of_order) | |||
2536 | col_append_str(pinfo->cinfo, COL_INFO, " (out-of-order packet)"); | |||
2537 | #endif | |||
2538 | } else { | |||
2539 | col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", | |||
2540 | val64_to_str_ext_wmem(pinfo->pool, CODEC_MASK(codec)((codec) == (uint32_t)-1 ? 0 : (1UL << (codec))), &codec_types_ext, "unknown (0x%04x)")); | |||
2541 | } | |||
2542 | ||||
2543 | nbytes = tvb_reported_length(sub_tvb); | |||
2544 | proto_tree_add_item(iax2_tree, hf_iax2_payload_data, sub_tvb, 0, -1, ENC_NA0x00000000); | |||
2545 | ||||
2546 | iax2_info->payload_len = nbytes; | |||
2547 | iax2_info->payload_data = tvb_get_ptr(sub_tvb, 0, -1); | |||
2548 | ||||
2549 | /* pass the rest of the block to a subdissector */ | |||
2550 | if (iax_packet->call_data) | |||
2551 | desegment_iax(sub_tvb, pinfo, iax2_tree, tree, video, iax_packet); | |||
2552 | else | |||
2553 | process_iax_pdu(sub_tvb, pinfo, tree, video, iax_packet); | |||
2554 | } | |||
2555 | ||||
2556 | /* | |||
2557 | * Init routines | |||
2558 | */ | |||
2559 | ||||
2560 | /* called at the start of a capture. We should clear out our static, per-capture | |||
2561 | * data. | |||
2562 | */ | |||
2563 | ||||
2564 | static void | |||
2565 | iax_init_protocol(void) | |||
2566 | { | |||
2567 | iax_circuit_hashtab = g_hash_table_new(iax_circuit_hash, iax_circuit_equal); | |||
2568 | circuitcount = 0; | |||
2569 | ||||
2570 | iax_fid_table = g_hash_table_new(g_direct_hash, g_direct_equal); | |||
2571 | } | |||
2572 | ||||
2573 | static void | |||
2574 | iax_cleanup_protocol(void) | |||
2575 | { | |||
2576 | g_hash_table_destroy(iax_circuit_hashtab); | |||
2577 | g_hash_table_destroy(iax_fid_table); | |||
2578 | } | |||
2579 | ||||
2580 | ||||
2581 | void | |||
2582 | proto_register_iax2(void) | |||
2583 | { | |||
2584 | /* A header field is something you can search/filter on. | |||
2585 | * | |||
2586 | * We create a structure to register our fields. It consists of an | |||
2587 | * array of hf_register_info structures, each of which are of the format | |||
2588 | * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}. | |||
2589 | */ | |||
2590 | ||||
2591 | static hf_register_info hf[] = { | |||
2592 | ||||
2593 | {&hf_iax2_packet_type, | |||
2594 | {"Packet type", "iax2.packet_type", | |||
2595 | FT_UINT8, BASE_DEC, VALS(iax_packet_types)((0 ? (const struct _value_string*)0 : ((iax_packet_types)))), 0, | |||
2596 | "Full/minivoice/minivideo/trunk packet", | |||
2597 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2598 | ||||
2599 | {&hf_iax2_callno, | |||
2600 | {"Call identifier", "iax2.call", | |||
2601 | FT_UINT32, BASE_DEC, NULL((void*)0), 0, | |||
2602 | "This is the identifier Wireshark assigns to identify this call." | |||
2603 | " It does not correspond to any real field in the protocol", | |||
2604 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
2605 | ||||
2606 | {&hf_iax2_scallno, | |||
2607 | {"Source call", "iax2.src_call", | |||
2608 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x7FFF, | |||
2609 | "src_call holds the number of this call at the packet source pbx", | |||
2610 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2611 | ||||
2612 | /* FIXME could this be turned into a FRAMENUM field? */ | |||
2613 | {&hf_iax2_dcallno, | |||
2614 | {"Destination call", "iax2.dst_call", | |||
2615 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x7FFF, | |||
2616 | "dst_call holds the number of this call at the packet destination", | |||
2617 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2618 | ||||
2619 | {&hf_iax2_retransmission, | |||
2620 | {"Retransmission", "iax2.retransmission", | |||
2621 | FT_BOOLEAN, 16, NULL((void*)0), 0x8000, | |||
2622 | "retransmission is set if this packet is a retransmission of an earlier failed packet", | |||
2623 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2624 | ||||
2625 | {&hf_iax2_ts, | |||
2626 | {"Timestamp", "iax2.timestamp", | |||
2627 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, | |||
2628 | "timestamp is the time, in ms after the start of this call, at which this packet was transmitted", | |||
2629 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2630 | ||||
2631 | {&hf_iax2_minits, | |||
2632 | {"Timestamp", "iax2.timestamp", | |||
2633 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, | |||
2634 | "timestamp is the time, in ms after the start of this call, at which this packet was transmitted", | |||
2635 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2636 | ||||
2637 | {&hf_iax2_minividts, | |||
2638 | {"Timestamp", "iax2.timestamp", | |||
2639 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x7FFF, | |||
2640 | "timestamp is the time, in ms after the start of this call, at which this packet was transmitted", | |||
2641 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2642 | ||||
2643 | {&hf_iax2_absts, | |||
2644 | {"Absolute Time", "iax2.abstime", | |||
2645 | FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL((void*)0), 0x0, | |||
2646 | "The absolute time of this packet (calculated by adding the IAX timestamp to the start time of this call)", | |||
2647 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2648 | ||||
2649 | {&hf_iax2_lateness, | |||
2650 | {"Lateness", "iax2.lateness", | |||
2651 | FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0, | |||
2652 | "The lateness of this packet compared to its timestamp", | |||
2653 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2654 | ||||
2655 | {&hf_iax2_minividmarker, | |||
2656 | {"Marker", "iax2.video.mini_marker", | |||
2657 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x8000, | |||
2658 | "RTP end-of-frame marker", | |||
2659 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2660 | ||||
2661 | {&hf_iax2_oseqno, | |||
2662 | {"Outbound seq.no.", "iax2.oseqno", | |||
2663 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, | |||
2664 | "oseqno is the sequence no of this packet. The first packet has oseqno==0," | |||
2665 | " and subsequent packets increment the oseqno by 1", | |||
2666 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2667 | ||||
2668 | {&hf_iax2_iseqno, | |||
2669 | {"Inbound seq.no.", "iax2.iseqno", | |||
2670 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, | |||
2671 | "iseqno is the sequence no of the last successfully received packet", | |||
2672 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2673 | ||||
2674 | {&hf_iax2_type, | |||
2675 | {"Type", "iax2.type", | |||
2676 | FT_UINT8, BASE_DEC | BASE_EXT_STRING0x00000200, &iax_frame_types_ext, 0x0, | |||
2677 | "For full IAX2 frames, type is the type of frame", | |||
2678 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2679 | ||||
2680 | {&hf_iax2_csub, | |||
2681 | {"Unknown subclass", "iax2.subclass", | |||
2682 | FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, | |||
2683 | "Subclass of unknown type of full IAX2 frame", | |||
2684 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2685 | ||||
2686 | {&hf_iax2_dtmf_csub, | |||
2687 | {"DTMF subclass (digit)", "iax2.dtmf.subclass", | |||
2688 | FT_STRINGZ, BASE_NONE, NULL((void*)0), 0x0, | |||
2689 | "DTMF subclass gives the DTMF digit", | |||
2690 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2691 | ||||
2692 | {&hf_iax2_cmd_csub, | |||
2693 | {"Control subclass", "iax2.control.subclass", | |||
2694 | FT_UINT8, BASE_DEC | BASE_EXT_STRING0x00000200, &iax_cmd_subclasses_ext, 0x0, | |||
2695 | "This gives the command number for a Control packet.", | |||
2696 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2697 | ||||
2698 | {&hf_iax2_iax_csub, | |||
2699 | {"IAX subclass", "iax2.iax.subclass", | |||
2700 | FT_UINT8, BASE_DEC | BASE_EXT_STRING0x00000200, &iax_iax_subclasses_ext, 0x0, | |||
2701 | "IAX subclass gives the command number for IAX signaling packets", | |||
2702 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2703 | ||||
2704 | {&hf_iax2_voice_csub, | |||
2705 | {"Voice Subclass (compressed codec no)", "iax2.voice.subclass", | |||
2706 | FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, | |||
2707 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2708 | ||||
2709 | {&hf_iax2_voice_codec, | |||
2710 | {"CODEC", "iax2.voice.codec", | |||
2711 | FT_UINT64, BASE_HEX | BASE_EXT_STRING0x00000200 | BASE_VAL64_STRING0x00000400, &codec_types_ext, 0x0, | |||
2712 | "CODEC gives the codec used to encode audio data", | |||
2713 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2714 | ||||
2715 | {&hf_iax2_video_csub, | |||
2716 | {"Video Subclass (compressed codec no)", "iax2.video.subclass", | |||
2717 | FT_UINT8, BASE_DEC, NULL((void*)0), 0xBF, | |||
2718 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2719 | ||||
2720 | {&hf_iax2_marker, | |||
2721 | {"Marker", "iax2.video.marker", | |||
2722 | FT_BOOLEAN, 8, NULL((void*)0), 0x40, | |||
2723 | "RTP end-of-frame marker", | |||
2724 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2725 | ||||
2726 | {&hf_iax2_video_codec, | |||
2727 | {"CODEC", "iax2.video.codec", | |||
2728 | FT_UINT64, BASE_HEX | BASE_EXT_STRING0x00000200 | BASE_VAL64_STRING0x00000400, &codec_types_ext, 0, | |||
2729 | "The codec used to encode video data", | |||
2730 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2731 | ||||
2732 | {&hf_iax2_modem_csub, | |||
2733 | {"Modem subclass", "iax2.modem.subclass", | |||
2734 | FT_UINT8, BASE_DEC, VALS(iax_modem_subclasses)((0 ? (const struct _value_string*)0 : ((iax_modem_subclasses )))), 0x0, | |||
2735 | "Modem subclass gives the type of modem", | |||
2736 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2737 | ||||
2738 | {&hf_iax2_text_csub, | |||
2739 | {"Text subclass", "iax2.text.subclass", | |||
2740 | FT_UINT8, BASE_DEC, VALS(iax_text_subclasses)((0 ? (const struct _value_string*)0 : ((iax_text_subclasses) ))), 0x0, | |||
2741 | NULL((void*)0), | |||
2742 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2743 | ||||
2744 | {&hf_iax2_text_text, | |||
2745 | {"Text", "iax2.text.text", | |||
2746 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2747 | NULL((void*)0), | |||
2748 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2749 | ||||
2750 | {&hf_iax2_html_csub, | |||
2751 | {"HTML subclass", "iax2.html.subclass", | |||
2752 | FT_UINT8, BASE_DEC, VALS(iax_html_subclasses)((0 ? (const struct _value_string*)0 : ((iax_html_subclasses) ))), 0x0, | |||
2753 | NULL((void*)0), | |||
2754 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2755 | ||||
2756 | {&hf_iax2_html_url, | |||
2757 | {"HTML URL", "iax2.html.url", | |||
2758 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2759 | NULL((void*)0), | |||
2760 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2761 | ||||
2762 | {&hf_iax2_trunk_ts, | |||
2763 | {"Timestamp", "iax2.timestamp", | |||
2764 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, | |||
2765 | "timestamp is the time, in ms after the start of Command data this call," | |||
2766 | " at which this trunk packet was transmitted", | |||
2767 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2768 | ||||
2769 | {&hf_iax2_trunk_metacmd, | |||
2770 | {"Meta command", "iax2.trunk.metacmd", | |||
2771 | FT_UINT8, BASE_DEC, NULL((void*)0), 0x7F, | |||
2772 | "Meta command indicates whether or not the Meta Frame is a trunk.", | |||
2773 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2774 | ||||
2775 | {&hf_iax2_trunk_cmddata, | |||
2776 | {"Command data", "iax2.trunk.cmddata", | |||
2777 | FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, | |||
2778 | "Flags for options that apply to a trunked call", | |||
2779 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2780 | ||||
2781 | {&hf_iax2_trunk_cmddata_ts, | |||
2782 | {"Trunk timestamps", "iax2.trunk.cmddata.ts", | |||
2783 | FT_BOOLEAN, 8, NULL((void*)0), IAX2_TRUNK_TS1, | |||
2784 | "True: calls do each include their own timestamp", | |||
2785 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2786 | ||||
2787 | {&hf_iax2_trunk_call_len, | |||
2788 | {"Data length", "iax2.trunk.call.len", | |||
2789 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, | |||
2790 | "Trunk call data length in octets", | |||
2791 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2792 | ||||
2793 | {&hf_iax2_trunk_call_scallno, | |||
2794 | {"Source call number", "iax2.trunk.call.scallno", | |||
2795 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x7FFF, | |||
2796 | "Trunk call source call number", | |||
2797 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2798 | ||||
2799 | {&hf_iax2_trunk_call_ts, | |||
2800 | {"Timestamp", "iax2.trunk.call.ts", | |||
2801 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, | |||
2802 | "timestamp is the time, in ms after the start of this call, at which this packet was transmitted", | |||
2803 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2804 | ||||
2805 | {&hf_iax2_trunk_call_data, | |||
2806 | {"Data", "iax2.trunk.call.payload", | |||
2807 | FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, | |||
2808 | "Payload carried by this trunked packet.", | |||
2809 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2810 | ||||
2811 | {&hf_iax2_trunk_ncalls, | |||
2812 | {"Number of calls", "iax2.trunk.ncalls", | |||
2813 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, | |||
2814 | "Number of calls in this trunk packet", | |||
2815 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2816 | ||||
2817 | /* | |||
2818 | * Decoding for the ies | |||
2819 | */ | |||
2820 | ||||
2821 | {&hf_IAX_IE_APPARENTADDR_SINFAMILY, | |||
2822 | {"Family", "iax2.iax.app_addr.sinfamily", | |||
2823 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
2824 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
2825 | ||||
2826 | {&hf_IAX_IE_APPARENTADDR_SINPORT, | |||
2827 | {"Port", "iax2.iax.app_addr.sinport", | |||
2828 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
2829 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
2830 | ||||
2831 | {&hf_IAX_IE_APPARENTADDR_SINADDR, | |||
2832 | {"Address", "iax2.iax.app_addr.sinaddr", | |||
2833 | FT_IPv4, BASE_NONE, NULL((void*)0), 0, | |||
2834 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
2835 | ||||
2836 | {&hf_iax2_ies[IAX_IE_CALLED_NUMBER1], | |||
2837 | {"Number/extension being called", "iax2.iax.called_number", | |||
2838 | FT_STRING, | |||
2839 | BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2840 | ||||
2841 | {&hf_iax2_ies[IAX_IE_CALLING_NUMBER2], | |||
2842 | {"Calling number", "iax2.iax.calling_number", | |||
2843 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2844 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2845 | ||||
2846 | ||||
2847 | {&hf_iax2_ies[IAX_IE_CALLING_ANI3], | |||
2848 | {"Calling number ANI for billing", "iax2.iax.calling_ani", | |||
2849 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2850 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2851 | ||||
2852 | {&hf_iax2_ies[IAX_IE_CALLING_NAME4], | |||
2853 | {"Name of caller", "iax2.iax.calling_name", | |||
2854 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2855 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2856 | ||||
2857 | {&hf_iax2_ies[IAX_IE_CALLED_CONTEXT5], | |||
2858 | {"Context for number", "iax2.iax.called_context", | |||
2859 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2860 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2861 | ||||
2862 | {&hf_iax2_ies[IAX_IE_USERNAME6], | |||
2863 | {"Username (peer or user) for authentication", "iax2.iax.username", | |||
2864 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2865 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2866 | ||||
2867 | {&hf_iax2_ies[IAX_IE_PASSWORD7], | |||
2868 | {"Password for authentication", "iax2.iax.password", | |||
2869 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2870 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2871 | ||||
2872 | {&hf_iax2_ies[IAX_IE_CAPABILITY8], | |||
2873 | {"Actual codec capability", "iax2.iax.capability", | |||
2874 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, | |||
2875 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2876 | ||||
2877 | {&hf_iax2_ies[IAX_IE_FORMAT9], | |||
2878 | {"Desired codec format", "iax2.iax.format", | |||
2879 | FT_UINT64, BASE_HEX | BASE_EXT_STRING0x00000200 | BASE_VAL64_STRING0x00000400, &codec_types_ext, 0x0, | |||
2880 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2881 | ||||
2882 | {&hf_iax2_ies[IAX_IE_LANGUAGE10], | |||
2883 | {"Desired language", "iax2.iax.language", | |||
2884 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2885 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2886 | ||||
2887 | {&hf_iax2_ies[IAX_IE_VERSION11], | |||
2888 | {"Protocol version", "iax2.iax.version", | |||
2889 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, | |||
2890 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2891 | ||||
2892 | {&hf_iax2_ies[IAX_IE_ADSICPE12], | |||
2893 | {"CPE ADSI capability", "iax2.iax.cpe_adsi", | |||
2894 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, | |||
2895 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2896 | ||||
2897 | {&hf_iax2_ies[IAX_IE_DNID13], | |||
2898 | {"Originally dialed DNID", "iax2.iax.dnid", | |||
2899 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2900 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2901 | ||||
2902 | {&hf_iax2_ies[IAX_IE_AUTHMETHODS14], | |||
2903 | {"Authentication method(s)", "iax2.iax.auth.methods", | |||
2904 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, | |||
2905 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2906 | ||||
2907 | {&hf_iax2_ies[IAX_IE_CHALLENGE15], | |||
2908 | {"Challenge data for MD5/RSA", "iax2.iax.auth.challenge", | |||
2909 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2910 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2911 | ||||
2912 | {&hf_iax2_ies[IAX_IE_MD5_RESULT16], | |||
2913 | {"MD5 challenge result", "iax2.iax.auth.md5", | |||
2914 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2915 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2916 | ||||
2917 | {&hf_iax2_ies[IAX_IE_RSA_RESULT17], | |||
2918 | {"RSA challenge result", "iax2.iax.auth.rsa", | |||
2919 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2920 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2921 | ||||
2922 | {&hf_iax2_ies[IAX_IE_REFRESH19], | |||
2923 | {"When to refresh registration", "iax2.iax.refresh", | |||
2924 | FT_INT16, BASE_DEC, NULL((void*)0), 0x0, | |||
2925 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2926 | ||||
2927 | {&hf_iax2_ies[IAX_IE_DPSTATUS20], | |||
2928 | {"Dialplan status", "iax2.iax.dialplan_status", | |||
2929 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, | |||
2930 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2931 | ||||
2932 | {&hf_iax2_ies[IAX_IE_CALLNO21], | |||
2933 | {"Call number of peer", "iax2.iax.call_no", | |||
2934 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, | |||
2935 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2936 | ||||
2937 | {&hf_iax2_ies[IAX_IE_CAUSE22], | |||
2938 | {"Cause", "iax2.iax.cause", | |||
2939 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2940 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2941 | ||||
2942 | {&hf_iax2_ies[IAX_IE_IAX_UNKNOWN23], | |||
2943 | {"Unknown IAX command", "iax2.iax.iax_unknown", | |||
2944 | FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, | |||
2945 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2946 | ||||
2947 | {&hf_iax2_ies[IAX_IE_MSGCOUNT24], | |||
2948 | {"How many messages waiting", "iax2.iax.msg_count", | |||
2949 | FT_INT16, BASE_DEC, NULL((void*)0), 0x0, | |||
2950 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2951 | ||||
2952 | {&hf_iax2_ies[IAX_IE_AUTOANSWER25], | |||
2953 | {"Request auto-answering", "iax2.iax.autoanswer", | |||
2954 | FT_NONE, BASE_NONE, NULL((void*)0), 0x0, | |||
2955 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2956 | ||||
2957 | {&hf_iax2_ies[IAX_IE_MUSICONHOLD26], | |||
2958 | {"Request musiconhold with QUELCH", "iax2.iax.moh", | |||
2959 | FT_NONE, BASE_NONE, NULL((void*)0), 0x0, | |||
2960 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2961 | ||||
2962 | {&hf_iax2_ies[IAX_IE_TRANSFERID27], | |||
2963 | {"Transfer Request Identifier", "iax2.iax.transferid", | |||
2964 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, | |||
2965 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2966 | ||||
2967 | {&hf_iax2_ies[IAX_IE_RDNIS28], | |||
2968 | {"Referring DNIS", "iax2.iax.rdnis", | |||
2969 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2970 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2971 | ||||
2972 | {&hf_iax2_ies[IAX_IE_PROVISIONING29], | |||
2973 | {"Provisioning info", "iax2.iax.provisioning", | |||
2974 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2975 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2976 | ||||
2977 | {&hf_iax2_ies[IAX_IE_AESPROVISIONING30], | |||
2978 | {"AES Provisioning info", "iax2.iax.aesprovisioning", | |||
2979 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2980 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2981 | ||||
2982 | {&hf_iax2_ies[IAX_IE_DATETIME31], | |||
2983 | {"Date/Time", "iax2.iax.datetime.raw", | |||
2984 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, | |||
2985 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2986 | ||||
2987 | {&hf_iax2_ie_datetime, | |||
2988 | {"Date/Time", "iax2.iax.datetime", | |||
2989 | FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL((void*)0), 0x0, | |||
2990 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
2991 | ||||
2992 | {&hf_iax2_ies[IAX_IE_DEVICETYPE32], | |||
2993 | {"Device type", "iax2.iax.devicetype", | |||
2994 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
2995 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
2996 | ||||
2997 | {&hf_iax2_ies[IAX_IE_SERVICEIDENT33], | |||
2998 | {"Service identifier", "iax2.iax.serviceident", | |||
2999 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
3000 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3001 | ||||
3002 | {&hf_iax2_ies[IAX_IE_FIRMWAREVER34], | |||
3003 | {"Firmware version", "iax2.iax.firmwarever", | |||
3004 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, | |||
3005 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3006 | ||||
3007 | {&hf_iax2_ies[IAX_IE_FWBLOCKDESC35], | |||
3008 | {"Firmware block description", "iax2.iax.fwblockdesc", | |||
3009 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, | |||
3010 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3011 | ||||
3012 | {&hf_iax2_ies[IAX_IE_FWBLOCKDATA36], | |||
3013 | {"Firmware block of data", "iax2.iax.fwblockdata", | |||
3014 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
3015 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3016 | ||||
3017 | {&hf_iax2_ies[IAX_IE_PROVVER37], | |||
3018 | {"Provisioning version", "iax2.iax.provver", | |||
3019 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, | |||
3020 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3021 | ||||
3022 | {&hf_iax2_ies[IAX_IE_CALLINGPRES38], | |||
3023 | {"Calling presentation", "iax2.iax.callingpres", | |||
3024 | FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, | |||
3025 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3026 | ||||
3027 | {&hf_iax2_ies[IAX_IE_CALLINGTON39], | |||
3028 | {"Calling type of number", "iax2.iax.callington", | |||
3029 | FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, | |||
3030 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3031 | ||||
3032 | {&hf_iax2_ies[IAX_IE_CALLINGTNS40], | |||
3033 | {"Calling transit network select", "iax2.iax.callingtns", | |||
3034 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, | |||
3035 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3036 | ||||
3037 | {&hf_iax2_ies[IAX_IE_SAMPLINGRATE41], | |||
3038 | {"Supported sampling rates", "iax2.iax.samplingrate", | |||
3039 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, | |||
3040 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3041 | ||||
3042 | {&hf_iax2_ies[IAX_IE_CAUSECODE42], | |||
3043 | {"Hangup cause", "iax2.iax.causecode", | |||
3044 | FT_UINT8, BASE_HEX | BASE_EXT_STRING0x00000200, &iax_causecodes_ext, 0x0, | |||
3045 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3046 | ||||
3047 | {&hf_iax2_ies[IAX_IE_ENCRYPTION43], | |||
3048 | {"Encryption format", "iax2.iax.encryption", | |||
3049 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, | |||
3050 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3051 | ||||
3052 | {&hf_iax2_ies[IAX_IE_ENCKEY44], | |||
3053 | {"Encryption key", "iax2.iax.enckey", | |||
3054 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
3055 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3056 | ||||
3057 | {&hf_iax2_ies[IAX_IE_CODEC_PREFS45], | |||
3058 | {"Codec negotiation", "iax2.iax.codecprefs", | |||
3059 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
3060 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3061 | ||||
3062 | {&hf_iax2_ies[IAX_IE_RR_JITTER46], | |||
3063 | {"Received jitter (as in RFC1889)", "iax2.iax.rrjitter", | |||
3064 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, | |||
3065 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3066 | ||||
3067 | {&hf_iax2_ies[IAX_IE_RR_LOSS47], | |||
3068 | {"Received loss (high byte loss pct, low 24 bits loss count, as in rfc1889)", "iax2.iax.rrloss", | |||
3069 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, | |||
3070 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3071 | ||||
3072 | {&hf_iax2_ies[IAX_IE_RR_PKTS48], | |||
3073 | {"Total frames received", "iax2.iax.rrpkts", | |||
3074 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, | |||
3075 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3076 | ||||
3077 | {&hf_iax2_ies[IAX_IE_RR_DELAY49], | |||
3078 | {"Max playout delay in ms for received frames", "iax2.iax.rrdelay", | |||
3079 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, | |||
3080 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3081 | ||||
3082 | {&hf_iax2_ies[IAX_IE_RR_DROPPED50], | |||
3083 | {"Dropped frames (presumably by jitterbuffer)", "iax2.iax.rrdropped", | |||
3084 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, | |||
3085 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3086 | ||||
3087 | {&hf_iax2_ies[IAX_IE_RR_OOO51], | |||
3088 | {"Frame received out of order", "iax2.iax.rrooo", | |||
3089 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, | |||
3090 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3091 | ||||
3092 | {&hf_iax2_ies[IAX_IE_CAPABILITY255], | |||
3093 | {"64-bit codec capability", "iax2.iax.capability2", | |||
3094 | FT_UINT64, BASE_HEX, NULL((void*)0), 0x0, | |||
3095 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3096 | ||||
3097 | {&hf_iax2_ies[IAX_IE_FORMAT256], | |||
3098 | {"64-bit codec format", "iax2.iax.format2", | |||
3099 | FT_UINT64, BASE_HEX | BASE_EXT_STRING0x00000200 | BASE_VAL64_STRING0x00000400, &codec_types_ext, 0x0, | |||
3100 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3101 | ||||
3102 | {&hf_iax2_ies[IAX_IE_DATAFORMAT255], | |||
3103 | {"Data call format", "iax2.iax.dataformat", | |||
3104 | FT_UINT32, BASE_HEX, VALS(iax_dataformats)((0 ? (const struct _value_string*)0 : ((iax_dataformats)))), 0x0, | |||
3105 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3106 | ||||
3107 | {&hf_IAX_IE_UNKNOWN_BYTE, | |||
3108 | {"Unknown", "iax2.iax.unknownbyte", | |||
3109 | FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, | |||
3110 | "Raw data for unknown IEs", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3111 | ||||
3112 | {&hf_IAX_IE_UNKNOWN_I16, | |||
3113 | {"Unknown", "iax2.iax.unknownshort", | |||
3114 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, | |||
3115 | "Raw data for unknown IEs", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3116 | ||||
3117 | {&hf_IAX_IE_UNKNOWN_I32, | |||
3118 | {"Unknown", "iax2.iax.unknownlong", | |||
3119 | FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, | |||
3120 | "Raw data for unknown IEs", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3121 | ||||
3122 | {&hf_IAX_IE_UNKNOWN_BYTES, | |||
3123 | {"Unknown", "iax2.iax.unknownstring", | |||
3124 | FT_STRING, BASE_NONE, NULL((void*)0), 0x0, | |||
3125 | "Raw data for unknown IEs", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3126 | ||||
3127 | {&hf_iax2_ie_id, | |||
3128 | {"IE id", "iax2.ie_id", | |||
3129 | FT_UINT8, BASE_DEC|BASE_EXT_STRING0x00000200, &iax_ies_type_ext, 0x0, | |||
3130 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3131 | ||||
3132 | {&hf_iax2_length, | |||
3133 | {"Length", "iax2.length", | |||
3134 | FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, | |||
3135 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3136 | ||||
3137 | {&hf_iax2_version, | |||
3138 | {"Version", "iax2.version", | |||
3139 | FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, | |||
3140 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
3141 | ||||
3142 | /* capabilities */ | |||
3143 | {&hf_iax2_cap_g723_1, | |||
3144 | {"G.723.1 compression", "iax2.cap.g723_1", | |||
3145 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_G723_1)((0) == (uint32_t)-1 ? 0 : (1UL << (0))), | |||
3146 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3147 | ||||
3148 | {&hf_iax2_cap_gsm, | |||
3149 | {"GSM compression", "iax2.cap.gsm", | |||
3150 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_GSM)((1) == (uint32_t)-1 ? 0 : (1UL << (1))), | |||
3151 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3152 | ||||
3153 | {&hf_iax2_cap_ulaw, | |||
3154 | {"Raw mu-law data (G.711)", "iax2.cap.ulaw", | |||
3155 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_ULAW)((2) == (uint32_t)-1 ? 0 : (1UL << (2))), | |||
3156 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3157 | ||||
3158 | {&hf_iax2_cap_alaw, | |||
3159 | {"Raw A-law data (G.711)", "iax2.cap.alaw", | |||
3160 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_ALAW)((3) == (uint32_t)-1 ? 0 : (1UL << (3))), | |||
3161 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, | |||
3162 | ||||
3163 | {&hf_iax2_cap_g726_aal2, | |||
3164 | {"ADPCM (G.726, 32kbps, AAL2 codeword packing)", "iax2.cap.g726_aal2", | |||
3165 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_G726_AAL2)((4) == (uint32_t)-1 ? 0 : (1UL << (4))), | |||
3166 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3167 | ||||
3168 | {&hf_iax2_cap_adpcm, | |||
3169 | {"ADPCM", "iax2.cap.adpcm", | |||
3170 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_ADPCM)((5) == (uint32_t)-1 ? 0 : (1UL << (5))), | |||
3171 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3172 | ||||
3173 | {&hf_iax2_cap_slinear, | |||
3174 | {"Raw 16-bit Signed Linear (8000 Hz) PCM", "iax2.cap.slinear", | |||
3175 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_SLINEAR)((6) == (uint32_t)-1 ? 0 : (1UL << (6))), | |||
3176 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3177 | ||||
3178 | {&hf_iax2_cap_lpc10, | |||
3179 | {"LPC10, 180 samples/frame", "iax2.cap.lpc10", | |||
3180 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_LPC10)((7) == (uint32_t)-1 ? 0 : (1UL << (7))), | |||
3181 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3182 | ||||
3183 | {&hf_iax2_cap_g729a, | |||
3184 | {"G.729a Audio", "iax2.cap.g729a", | |||
3185 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_G729A)((8) == (uint32_t)-1 ? 0 : (1UL << (8))), | |||
3186 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3187 | ||||
3188 | {&hf_iax2_cap_speex, | |||
3189 | {"SpeeX Free Compression", "iax2.cap.speex", | |||
3190 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_SPEEX)((9) == (uint32_t)-1 ? 0 : (1UL << (9))), | |||
3191 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3192 | ||||
3193 | {&hf_iax2_cap_ilbc, | |||
3194 | {"iLBC Free Compression", "iax2.cap.ilbc", | |||
3195 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_ILBC)((10) == (uint32_t)-1 ? 0 : (1UL << (10))), | |||
3196 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3197 | ||||
3198 | {&hf_iax2_cap_g726, | |||
3199 | {"ADPCM (G.726, 32kbps, RFC3551 codeword packing)", "iax2.cap.g726", | |||
3200 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_G726)((11) == (uint32_t)-1 ? 0 : (1UL << (11))), | |||
3201 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3202 | ||||
3203 | {&hf_iax2_cap_g722, | |||
3204 | {"G.722", "iax2.cap.g722", | |||
3205 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_G722)((12) == (uint32_t)-1 ? 0 : (1UL << (12))), | |||
3206 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3207 | ||||
3208 | {&hf_iax2_cap_siren7, | |||
3209 | {"G.722.1 (also known as Siren7, 32kbps assumed)", "iax2.cap.siren7", | |||
3210 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_SIREN7)((13) == (uint32_t)-1 ? 0 : (1UL << (13))), | |||
3211 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3212 | ||||
3213 | {&hf_iax2_cap_siren14, | |||
3214 | {"G.722.1 Annex C (also known as Siren14, 48kbps assumed)", "iax2.cap.siren14", | |||
3215 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_SIREN14)((14) == (uint32_t)-1 ? 0 : (1UL << (14))), | |||
3216 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3217 | ||||
3218 | {&hf_iax2_cap_slinear16, | |||
3219 | {"Raw 16-bit Signed Linear (16000 Hz) PCM", "iax2.cap.slinear16", | |||
3220 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_SLINEAR16)((15) == (uint32_t)-1 ? 0 : (1UL << (15))), | |||
3221 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3222 | ||||
3223 | {&hf_iax2_cap_jpeg, | |||
3224 | {"JPEG images", "iax2.cap.jpeg", | |||
3225 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_JPEG)((16) == (uint32_t)-1 ? 0 : (1UL << (16))), | |||
3226 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3227 | ||||
3228 | {&hf_iax2_cap_png, | |||
3229 | {"PNG images", "iax2.cap.png", | |||
3230 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_PNG)((17) == (uint32_t)-1 ? 0 : (1UL << (17))), | |||
3231 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3232 | ||||
3233 | {&hf_iax2_cap_h261, | |||
3234 | {"H.261 video", "iax2.cap.h261", | |||
3235 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_H261)((18) == (uint32_t)-1 ? 0 : (1UL << (18))), | |||
3236 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3237 | ||||
3238 | {&hf_iax2_cap_h263, | |||
3239 | {"H.263 video", "iax2.cap.h263", | |||
3240 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_H263)((19) == (uint32_t)-1 ? 0 : (1UL << (19))), | |||
3241 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3242 | ||||
3243 | {&hf_iax2_cap_h263_plus, | |||
3244 | {"H.263+ video", "iax2.cap.h263_plus", | |||
3245 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_H263_PLUS)((20) == (uint32_t)-1 ? 0 : (1UL << (20))), | |||
3246 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3247 | ||||
3248 | {&hf_iax2_cap_h264, | |||
3249 | {"H.264 video", "iax2.cap.h264", | |||
3250 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_H264)((21) == (uint32_t)-1 ? 0 : (1UL << (21))), | |||
3251 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3252 | ||||
3253 | {&hf_iax2_cap_mpeg4, | |||
3254 | {"MPEG4 video", "iax2.cap.mpeg4", | |||
3255 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_MP4_VIDEO)((22) == (uint32_t)-1 ? 0 : (1UL << (22))), | |||
3256 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3257 | ||||
3258 | {&hf_iax2_cap_vp8, | |||
3259 | {"VP8 video", "iax2.cap.vp8", | |||
3260 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_VP8)((23) == (uint32_t)-1 ? 0 : (1UL << (23))), | |||
3261 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3262 | ||||
3263 | {&hf_iax2_cap_t140_red, | |||
3264 | {"T.140 RED Text format RFC 4103", "iax2.cap.t140_red", | |||
3265 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_T140_RED)((26) == (uint32_t)-1 ? 0 : (1UL << (26))), | |||
3266 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3267 | ||||
3268 | {&hf_iax2_cap_t140, | |||
3269 | {"T.140 Text format - ITU T.140, RFC 4103", "iax2.cap.t140", | |||
3270 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_T140)((27) == (uint32_t)-1 ? 0 : (1UL << (27))), | |||
3271 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3272 | ||||
3273 | {&hf_iax2_cap_g719, | |||
3274 | {"G.719 (64 kbps assumed)", "iax2.cap.g719", | |||
3275 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_G719)((32) == (uint32_t)-1 ? 0 : (1UL << (32))), | |||
3276 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3277 | ||||
3278 | {&hf_iax2_cap_speex16, | |||
3279 | {"SpeeX Wideband (16kHz) Free Compression", "iax2.cap.speex16", | |||
3280 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_SPEEX16)((33) == (uint32_t)-1 ? 0 : (1UL << (33))), | |||
3281 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3282 | ||||
3283 | {&hf_iax2_cap_opus, | |||
3284 | {"Opus audio (8kHz, 16kHz, 24kHz, 48Khz)", "iax2.cap.opus", | |||
3285 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_OPUS)((34) == (uint32_t)-1 ? 0 : (1UL << (34))), | |||
3286 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3287 | ||||
3288 | {&hf_iax2_cap_testlaw, | |||
3289 | {"Raw testing-law data (G.711)", "iax2.cap.testlaw", | |||
3290 | FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported)((0 ? (const struct true_false_string*)0 : ((&tfs_supported_not_supported )))), CODEC_MASK(AST_FORMAT_TESTLAW)((47) == (uint32_t)-1 ? 0 : (1UL << (47))), | |||
3291 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3292 | ||||
3293 | {&hf_iax2_fragment_unfinished, | |||
3294 | {"IAX2 fragment, unfinished", "iax2.fragment_unfinished", | |||
3295 | FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, | |||
3296 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3297 | ||||
3298 | {&hf_iax2_payload_data, | |||
3299 | {"IAX2 payload", "iax2.payload_data", | |||
3300 | FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, | |||
3301 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3302 | ||||
3303 | /* reassembly stuff */ | |||
3304 | {&hf_iax2_fragments, | |||
3305 | {"IAX2 Fragments", "iax2.fragments", | |||
3306 | FT_NONE, BASE_NONE, NULL((void*)0), 0x0, | |||
3307 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3308 | ||||
3309 | {&hf_iax2_fragment, | |||
3310 | {"IAX2 Fragment data", "iax2.fragment", | |||
3311 | FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0, | |||
3312 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3313 | ||||
3314 | {&hf_iax2_fragment_overlap, | |||
3315 | {"Fragment overlap", "iax2.fragment.overlap", | |||
3316 | FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0, | |||
3317 | "Fragment overlaps with other fragments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3318 | ||||
3319 | {&hf_iax2_fragment_overlap_conflict, | |||
3320 | {"Conflicting data in fragment overlap", "iax2.fragment.overlap.conflict", | |||
3321 | FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0, | |||
3322 | "Overlapping fragments contained conflicting data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3323 | ||||
3324 | {&hf_iax2_fragment_multiple_tails, | |||
3325 | {"Multiple tail fragments found", "iax2.fragment.multipletails", | |||
3326 | FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0, | |||
3327 | "Several tails were found when defragmenting the packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3328 | ||||
3329 | {&hf_iax2_fragment_too_long_fragment, | |||
3330 | {"Fragment too long", "iax2.fragment.toolongfragment", | |||
3331 | FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0, | |||
3332 | "Fragment contained data past end of packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3333 | ||||
3334 | {&hf_iax2_fragment_error, | |||
3335 | {"Defragmentation error", "iax2.fragment.error", | |||
3336 | FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0, | |||
3337 | "Defragmentation error due to illegal fragments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3338 | ||||
3339 | {&hf_iax2_fragment_count, | |||
3340 | {"Fragment count", "iax2.fragment.count", | |||
3341 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, | |||
3342 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3343 | ||||
3344 | {&hf_iax2_reassembled_in, | |||
3345 | {"IAX2 fragment, reassembled in frame", "iax2.reassembled_in", | |||
3346 | FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0, | |||
3347 | "This IAX2 packet is reassembled in this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
3348 | ||||
3349 | {&hf_iax2_reassembled_length, | |||
3350 | {"Reassembled IAX2 length", "iax2.reassembled.length", | |||
3351 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, | |||
3352 | "The total length of the reassembled payload", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }} | |||
3353 | }; | |||
3354 | ||||
3355 | static int *ett[] = { | |||
3356 | &ett_iax2, | |||
3357 | &ett_iax2_full_mini_subtree, | |||
3358 | &ett_iax2_type, | |||
3359 | &ett_iax2_ie, | |||
3360 | &ett_iax2_codecs, | |||
3361 | &ett_iax2_ies_apparent_addr, | |||
3362 | &ett_iax2_fragment, | |||
3363 | &ett_iax2_fragments, | |||
3364 | &ett_iax2_trunk_cmddata, | |||
3365 | &ett_iax2_trunk_call | |||
3366 | }; | |||
3367 | ||||
3368 | static ei_register_info ei[] = { | |||
3369 | { &ei_iax_too_many_transfers, { "iax2.too_many_transfers", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Too many transfers for iax_call", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, | |||
3370 | { &ei_iax_circuit_id_conflict, { "iax2.circuit_id_conflict", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Circuit ID conflict", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, | |||
3371 | { &ei_iax_peer_address_unsupported, { "iax2.peer_address_unsupported", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Peer address unsupported", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, | |||
3372 | { &ei_iax_invalid_len, { "iax2.invalid_len", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Invalid length", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, | |||
3373 | }; | |||
3374 | ||||
3375 | expert_module_t* expert_iax; | |||
3376 | ||||
3377 | proto_iax2 = proto_register_protocol("Inter-Asterisk eXchange v2", "IAX2", "iax2"); | |||
3378 | proto_register_field_array(proto_iax2, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0])); | |||
3379 | proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0])); | |||
3380 | expert_iax = expert_register_protocol(proto_iax2); | |||
3381 | expert_register_field_array(expert_iax, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0])); | |||
3382 | ||||
3383 | iax2_handle = register_dissector("iax2", dissect_iax2, proto_iax2); | |||
3384 | ||||
3385 | iax2_codec_dissector_table = register_dissector_table( | |||
3386 | "iax2.codec", "IAX codec number", proto_iax2, FT_UINT32, BASE_HEX); | |||
3387 | iax2_dataformat_dissector_table = register_dissector_table( | |||
3388 | "iax2.dataformat", "IAX dataformat number", proto_iax2, FT_UINT32, BASE_HEX); | |||
3389 | ||||
3390 | /* register our init routine to be called at the start of a capture, | |||
3391 | to clear out our hash tables etc */ | |||
3392 | register_init_routine(&iax_init_protocol); | |||
3393 | register_cleanup_routine(&iax_cleanup_protocol); | |||
3394 | reassembly_table_register(&iax_reassembly_table, | |||
3395 | &addresses_reassembly_table_functions); | |||
3396 | ||||
3397 | iax2_tap = register_tap("IAX2"); | |||
3398 | } | |||
3399 | ||||
3400 | void | |||
3401 | proto_reg_handoff_iax2(void) | |||
3402 | { | |||
3403 | dissector_handle_t v110_handle; | |||
3404 | ||||
3405 | dissector_add_uint_with_preference("udp.port", IAX2_PORT4569, iax2_handle); | |||
3406 | v110_handle = find_dissector("v110"); | |||
3407 | if (v110_handle) | |||
3408 | dissector_add_uint("iax2.dataformat", AST_DATAFORMAT_V110, v110_handle); | |||
3409 | } | |||
3410 | ||||
3411 | /* | |||
3412 | * Editor modelines | |||
3413 | * | |||
3414 | * Local Variables: | |||
3415 | * c-basic-offset: 2 | |||
3416 | * tab-width: 8 | |||
3417 | * indent-tabs-mode: nil | |||
3418 | * End: | |||
3419 | * | |||
3420 | * ex: set shiftwidth=2 tabstop=8 expandtab: | |||
3421 | * :indentSize=2:tabSize=8:noTabs=true: | |||
3422 | */ |