Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-iax2.c
blob5dbbfd20ee32d4bf9c841dc7a414c11f7e603986
1 /*
2 * packet-iax2.c
4 * Routines for IAX2 packet disassembly
5 * By Alastair Maw <asterisk@almaw.com>
6 * Copyright 2003 Alastair Maw
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.
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * SPDX-License-Identifier: GPL-2.0-or-later
19 #include "config.h"
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>
33 #include "packet-iax2.h"
34 #include <epan/iax2_codec_type.h>
36 void proto_register_iax2(void);
37 void proto_reg_handoff_iax2(void);
39 #define IAX2_PORT 4569
40 #define PROTO_TAG_IAX2 "IAX2"
42 /* enough to hold any address in an address_t */
43 #define MAX_ADDRESS 16
45 /* the maximum number of transfers (of each end) we can deal with per call,
46 * plus one */
47 #define IAX_MAX_TRANSFERS 2
49 /* #define DEBUG_HASHING */
50 /* #define DEBUG_DESEGMENT */
52 /* Wireshark ID of the IAX2 protocol */
53 static int proto_iax2;
55 /* tap register id */
56 static int iax2_tap;
58 /* protocol tap info */
59 static iax2_info_t ii_arr[1];
60 static iax2_info_t *iax2_info = ii_arr;
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()
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;
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;
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
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;
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.
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.
195 #define NUM_HF_IAX2_IES 256
196 static int hf_iax2_ies[NUM_HF_IAX2_IES];
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;
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;
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;
223 static dissector_handle_t iax2_handle;
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,
240 "iax2 fragments"
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;
249 /* IAX2 Meta trunk packet Command data flags */
250 #define IAX2_TRUNK_TS 1
252 /* IAX2 Full-frame types */
253 static const value_string iax_frame_types[] = {
254 {0, "(0?)"},
255 {AST_FRAME_DTMF_END, "DTMF End"},
256 {AST_FRAME_VOICE, "Voice"},
257 {AST_FRAME_VIDEO, "Video"},
258 {AST_FRAME_CONTROL, "Control"},
259 {AST_FRAME_NULL, "NULL"},
260 {AST_FRAME_IAX, "IAX"},
261 {AST_FRAME_TEXT, "Text"},
262 {AST_FRAME_IMAGE, "Image"},
263 {AST_FRAME_HTML, "HTML"},
264 {AST_FRAME_CNG, "Comfort Noise"},
265 {AST_FRAME_MODEM, "Modem"},
266 {AST_FRAME_DTMF_BEGIN, "DTMF Begin"},
267 {0, NULL}
269 static value_string_ext iax_frame_types_ext = VALUE_STRING_EXT_INIT(iax_frame_types);
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}
316 static value_string_ext iax_iax_subclasses_ext = VALUE_STRING_EXT_INIT(iax_iax_subclasses);
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}
331 static value_string_ext iax_cmd_subclasses_ext = VALUE_STRING_EXT_INIT(iax_cmd_subclasses);
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*/
344 #define NUM_TAP_CMD_VOIP_STATES array_length(tap_cmd_voip_state)
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
388 #define NUM_TAP_IAX_VOIP_STATES array_length(tap_iax_voip_state)
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}
398 /* Subclasses for Text packets */
399 static const value_string iax_text_subclasses[] = {
400 {0, "Text"},
401 {0, NULL}
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}
419 /* Information elements */
420 static const value_string iax_ies_type[] = {
421 {IAX_IE_CALLED_NUMBER, "Number/extension being called"},
422 {IAX_IE_CALLING_NUMBER, "Calling number"},
423 {IAX_IE_CALLING_ANI, "Calling number ANI for billing"},
424 {IAX_IE_CALLING_NAME, "Name of caller"},
425 {IAX_IE_CALLED_CONTEXT, "Context for number"},
426 {IAX_IE_USERNAME, "Username (peer or user) for authentication"},
427 {IAX_IE_PASSWORD, "Password for authentication"},
428 {IAX_IE_CAPABILITY, "Actual codec capability"},
429 {IAX_IE_FORMAT, "Desired codec format"},
430 {IAX_IE_LANGUAGE, "Desired language"},
431 {IAX_IE_VERSION, "Protocol version"},
432 {IAX_IE_ADSICPE, "CPE ADSI capability"},
433 {IAX_IE_DNID, "Originally dialed DNID"},
434 {IAX_IE_AUTHMETHODS, "Authentication method(s)"},
435 {IAX_IE_CHALLENGE, "Challenge data for MD5/RSA"},
436 {IAX_IE_MD5_RESULT, "MD5 challenge result"},
437 {IAX_IE_RSA_RESULT, "RSA challenge result"},
438 {IAX_IE_APPARENT_ADDR, "Apparent address of peer"},
439 {IAX_IE_REFRESH, "When to refresh registration"},
440 {IAX_IE_DPSTATUS, "Dialplan status"},
441 {IAX_IE_CALLNO, "Call number of peer"},
442 {IAX_IE_CAUSE, "Cause"},
443 {IAX_IE_IAX_UNKNOWN, "Unknown IAX command"},
444 {IAX_IE_MSGCOUNT, "How many messages waiting"},
445 {IAX_IE_AUTOANSWER, "Request auto-answering"},
446 {IAX_IE_MUSICONHOLD, "Request musiconhold with QUELCH"},
447 {IAX_IE_TRANSFERID, "Transfer Request Identifier"},
448 {IAX_IE_RDNIS, "Referring DNIS"},
449 {IAX_IE_PROVISIONING, "Provisioning info"},
450 {IAX_IE_AESPROVISIONING, "AES Provisioning info"},
451 {IAX_IE_DATETIME, "Date/Time"},
452 {IAX_IE_DEVICETYPE, "Device type"},
453 {IAX_IE_SERVICEIDENT, "Service Identifier"},
454 {IAX_IE_FIRMWAREVER, "Firmware revision"},
455 {IAX_IE_FWBLOCKDESC, "Firmware block description"},
456 {IAX_IE_FWBLOCKDATA, "Firmware block of data"},
457 {IAX_IE_PROVVER, "Provisioning version"},
458 {IAX_IE_CALLINGPRES, "Calling presentation"},
459 {IAX_IE_CALLINGTON, "Calling type of number"},
460 {IAX_IE_CALLINGTNS, "Calling transit network select"},
461 {IAX_IE_SAMPLINGRATE, "Supported sampling rates"},
462 {IAX_IE_CAUSECODE, "Hangup cause"},
463 {IAX_IE_ENCRYPTION, "Encryption format"},
464 {IAX_IE_ENCKEY, "Raw encryption key"},
465 {IAX_IE_CODEC_PREFS, "Codec preferences"},
466 {IAX_IE_RR_JITTER, "Received jitter"},
467 {IAX_IE_RR_LOSS, "Received loss"},
468 {IAX_IE_RR_PKTS, "Received frames"},
469 {IAX_IE_RR_DELAY, "Max playout delay in ms for received frames"},
470 {IAX_IE_RR_DROPPED, "Dropped frames"},
471 {IAX_IE_RR_OOO, "Frames received out of order"},
472 {IAX_IE_VARIABLE, "IAX2 variable"},
473 {IAX_IE_OSPTOKEN, "OSP Token"},
474 {IAX_IE_CALLTOKEN, "Call Token"},
475 {IAX_IE_CAPABILITY2, "64-bit codec capability"},
476 {IAX_IE_FORMAT2, "64-bit codec format"},
477 {IAX_IE_DATAFORMAT, "Data call format"},
478 {0, NULL}
480 static value_string_ext iax_ies_type_ext = VALUE_STRING_EXT_INIT(iax_ies_type);
482 #define CODEC_MASK(codec) ((codec) == (uint32_t)-1 ? 0 : (UINT64_C(1) << (codec)))
484 static const val64_string codec_types[] = {
485 {CODEC_MASK(AST_FORMAT_G723_1), "G.723.1 compression"},
486 {CODEC_MASK(AST_FORMAT_GSM), "GSM compression"},
487 {CODEC_MASK(AST_FORMAT_ULAW), "Raw mu-law data (G.711)"},
488 {CODEC_MASK(AST_FORMAT_ALAW), "Raw A-law data (G.711)"},
489 {CODEC_MASK(AST_FORMAT_G726_AAL2), "ADPCM (G.726), 32kbps, AAL2 codeword packing)"},
490 {CODEC_MASK(AST_FORMAT_ADPCM), "ADPCM (IMA)"},
491 {CODEC_MASK(AST_FORMAT_SLINEAR), "Raw 16-bit Signed Linear (8000 Hz) PCM"},
492 {CODEC_MASK(AST_FORMAT_LPC10), "LPC10, 180 samples/frame"},
493 {CODEC_MASK(AST_FORMAT_G729A), "G.729a Audio"},
494 {CODEC_MASK(AST_FORMAT_SPEEX), "SpeeX Free Compression"},
495 {CODEC_MASK(AST_FORMAT_ILBC), "iLBC Free Compression"},
496 {CODEC_MASK(AST_FORMAT_G726), "ADPCM (G.726, 32kbps, RFC3551 codeword packing)"},
497 {CODEC_MASK(AST_FORMAT_G722), "G.722"},
498 {CODEC_MASK(AST_FORMAT_SIREN7), "G.722.1 (also known as Siren7, 32kbps assumed)"},
499 {CODEC_MASK(AST_FORMAT_SIREN14), "G.722.1 Annex C (also known as Siren14, 48kbps assumed)"},
500 {CODEC_MASK(AST_FORMAT_SLINEAR16), "Raw 16-bit Signed Linear (16000 Hz) PCM"},
501 {CODEC_MASK(AST_FORMAT_JPEG), "JPEG Images"},
502 {CODEC_MASK(AST_FORMAT_PNG), "PNG Images"},
503 {CODEC_MASK(AST_FORMAT_H261), "H.261 Video"},
504 {CODEC_MASK(AST_FORMAT_H263), "H.263 Video"},
505 {CODEC_MASK(AST_FORMAT_H263_PLUS), "H.263+ Video"},
506 {CODEC_MASK(AST_FORMAT_H264), "H.264 Video"},
507 {CODEC_MASK(AST_FORMAT_MP4_VIDEO), "MPEG4 Video"},
508 {CODEC_MASK(AST_FORMAT_VP8), "VP8 Video"},
509 {CODEC_MASK(AST_FORMAT_T140_RED), "T.140 RED Text format RFC 4103"},
510 {CODEC_MASK(AST_FORMAT_T140), "T.140 Text format - ITU T.140, RFC 4103"},
511 {CODEC_MASK(AST_FORMAT_G719), "G.719 (64 kbps assumed)"},
512 {CODEC_MASK(AST_FORMAT_SPEEX16), "SpeeX Wideband (16kHz) Free Compression"},
513 {CODEC_MASK(AST_FORMAT_OPUS), "Opus audio (8kHz, 16kHz, 24kHz, 48Khz)"},
514 {CODEC_MASK(AST_FORMAT_TESTLAW), "Raw testing-law data (G.711)"},
515 {0, NULL}
517 static val64_string_ext codec_types_ext = VAL64_STRING_EXT_INIT(codec_types);
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}
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}
535 static const value_string iax_causecodes[] = {
536 {AST_CAUSE_UNALLOCATED, "Unallocated"},
537 {AST_CAUSE_NO_ROUTE_TRANSIT_NET, "No route transit net"},
538 {AST_CAUSE_NO_ROUTE_DESTINATION, "No route to destination"},
539 {AST_CAUSE_MISDIALLED_TRUNK_PREFIX, "Misdialled trunk prefix"},
540 {AST_CAUSE_CHANNEL_UNACCEPTABLE, "Channel unacceptable"},
541 {AST_CAUSE_CALL_AWARDED_DELIVERED, "Call awarded delivered"},
542 {AST_CAUSE_PRE_EMPTED, "Preempted"},
543 {AST_CAUSE_NUMBER_PORTED_NOT_HERE, "Number ported not here"},
544 {AST_CAUSE_NORMAL_CLEARING, "Normal clearing"},
545 {AST_CAUSE_USER_BUSY, "User busy"},
546 {AST_CAUSE_NO_USER_RESPONSE, "No user response"},
547 {AST_CAUSE_NO_ANSWER, "No answer"},
548 {AST_CAUSE_SUBSCRIBER_ABSENT, "Subscriber absent"},
549 {AST_CAUSE_CALL_REJECTED, "Call rejected"},
550 {AST_CAUSE_NUMBER_CHANGED, "Number changed"},
551 {AST_CAUSE_REDIRECTED_TO_NEW_DESTINATION, "Redirected to new destination"},
552 {AST_CAUSE_ANSWERED_ELSEWHERE, "Answered elsewhere"},
553 {AST_CAUSE_DESTINATION_OUT_OF_ORDER, "Destination out of order"},
554 {AST_CAUSE_INVALID_NUMBER_FORMAT, "Invalid number format"},
555 {AST_CAUSE_FACILITY_REJECTED, "Facility rejected"},
556 {AST_CAUSE_RESPONSE_TO_STATUS_ENQUIRY, "Response to status inquiry"},
557 {AST_CAUSE_NORMAL_UNSPECIFIED, "Normal unspecified"},
558 {AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, "Normal circuit congestion"},
559 {AST_CAUSE_NETWORK_OUT_OF_ORDER, "Network out of order"},
560 {AST_CAUSE_NORMAL_TEMPORARY_FAILURE, "Normal temporary failure"},
561 {AST_CAUSE_SWITCH_CONGESTION, "Switch congestion"},
562 {AST_CAUSE_ACCESS_INFO_DISCARDED, "Access info discarded"},
563 {AST_CAUSE_REQUESTED_CHAN_UNAVAIL, "Requested channel unavailable"},
564 {AST_CAUSE_FACILITY_NOT_SUBSCRIBED, "Facility not subscribed"},
565 {AST_CAUSE_OUTGOING_CALL_BARRED, "Outgoing call barred"},
566 {AST_CAUSE_INCOMING_CALL_BARRED, "Incoming call barred"},
567 {AST_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized"},
568 {AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available"},
569 {AST_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented"},
570 {AST_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented"},
571 {AST_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented"},
572 {AST_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference"},
573 {AST_CAUSE_INCOMPATIBLE_DESTINATION, "Incompatible destination"},
574 {AST_CAUSE_INVALID_MSG_UNSPECIFIED, "Invalid message unspecified"},
575 {AST_CAUSE_MANDATORY_IE_MISSING, "Mandatory IE missing"},
576 {AST_CAUSE_MESSAGE_TYPE_NONEXIST, "Message type nonexistent"},
577 {AST_CAUSE_WRONG_MESSAGE, "Wrong message"},
578 {AST_CAUSE_IE_NONEXIST, "IE nonexistent"},
579 {AST_CAUSE_INVALID_IE_CONTENTS, "Invalid IE contents"},
580 {AST_CAUSE_WRONG_CALL_STATE, "Wrong call state"},
581 {AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, "Recovery on timer expire"},
582 {AST_CAUSE_MANDATORY_IE_LENGTH_ERROR, "Mandatory IE length error"},
583 {AST_CAUSE_PROTOCOL_ERROR, "Protocol error"},
584 {AST_CAUSE_INTERWORKING, "Interworking"},
585 {0, NULL}
587 static value_string_ext iax_causecodes_ext = VALUE_STRING_EXT_INIT(iax_causecodes);
589 /* ************************************************************************* */
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.
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.
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.
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.
613 /* start with a hash of {addr,port type,port,call}->{id} */
615 typedef struct {
616 address addr;
617 port_type ptype;
618 uint32_t port;
619 uint32_t callno;
621 /* this is where addr->data points to. it's put in here for easy freeing */
622 uint8_t address_data[MAX_ADDRESS];
623 } iax_circuit_key;
625 /* tables */
626 static GHashTable *iax_fid_table;
627 static reassembly_table iax_reassembly_table;
629 static GHashTable *iax_circuit_hashtab;
630 static unsigned circuitcount;
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.
635 #define IAX_INIT_PACKET_COUNT 10
637 #ifdef DEBUG_HASHING
638 static char *key_to_str( const iax_circuit_key *key )
640 static int i = 0;
641 static char str[3][80];
642 char *strp;
643 char *addrstr;
645 i++;
646 if (i >= 3) {
647 i = 0;
649 strp = str[i];
651 addrstr = address_to_str(NULL, &key->addr);
652 snprintf(strp, 80, "{%s:%i,%i}",
653 addrstr,
654 key->port,
655 key->callno);
656 wmem_free(NULL, addrstr);
657 return strp;
659 #endif
661 /* Hash Functions */
662 static int iax_circuit_equal(const void *v, const void *w)
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;
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);
674 #endif
676 return result;
679 static unsigned iax_circuit_hash(const void *v)
681 const iax_circuit_key *key = (const iax_circuit_key *)v;
682 unsigned hash_val;
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);
690 #ifdef DEBUG_HASHING
691 ws_debug("+++ Hashing key: %s, result %#x", key_to_str(key), hash_val);
692 #endif
694 return (unsigned)hash_val;
697 /* Find, or create, a circuit for the given
698 {address,porttype,port,call} quadruplet
700 static unsigned iax_circuit_lookup(const address *address_p,
701 port_type ptype,
702 uint32_t port,
703 uint32_t callno)
705 iax_circuit_key key;
706 uint32_t *circuit_id_p;
708 key.addr = *address_p;
709 key.ptype = ptype;
710 key.port = port;
711 key.callno = callno;
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;
717 new_key = wmem_new(wmem_file_scope(), iax_circuit_key);
718 new_key->addr.type = address_p->type;
719 new_key->addr.len = MIN(address_p->len, MAX_ADDRESS);
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;
727 circuit_id_p = (uint32_t *)wmem_new(wmem_file_scope(), iax_circuit_key);
728 *circuit_id_p = ++circuitcount;
730 g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p);
732 #ifdef DEBUG_HASHING
733 ws_debug("Created new circuit id %u for node %s", *circuit_id_p, key_to_str(new_key));
734 #endif
737 return *circuit_id_p;
741 /* ************************************************************************* */
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;
749 /* This is our per-call data structure, which is attached to both the
750 * forward and reverse circuits.
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.
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.
763 iax_dataformat_t dataformat;
764 uint32_t src_codec, dst_codec;
765 uint32_t src_vformat, dst_vformat;
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_TRANSFERS];
770 unsigned reverse_circuit_ids[IAX_MAX_TRANSFERS];
771 unsigned n_forward_circuit_ids;
772 unsigned n_reverse_circuit_ids;
774 /* this is the subdissector for the call */
775 dissector_handle_t subdissector;
777 /* the absolute start time of the call */
778 nstime_t start_time;
780 /* time stamp from last full frame, in the first pass */
781 uint32_t last_full_frame_ts;
783 iax_call_dirdata dirdata[2];
784 } iax_call_data;
788 /* creates a new CONVERSATION_IAX2 circuit with a specified circuit id for a call
790 * typically a call has up to three associated circuits: an original source, an
791 * original destination, and the result of a transfer.
793 * For each endpoint, a CONVERSATION_IAX2 circuit is created and added to the call_data
794 * by this function
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.
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 reversed)
805 conversation_t *conv;
807 if(!iax_call){
808 return NULL;
810 if ((reversed && iax_call->n_reverse_circuit_ids >= IAX_MAX_TRANSFERS) ||
811 (! reversed && iax_call->n_forward_circuit_ids >= IAX_MAX_TRANSFERS)) {
812 expert_add_info(pinfo, item, &ei_iax_too_many_transfers);
813 return NULL;
816 conv = conversation_new_by_id(framenum, CONVERSATION_IAX2,
817 circuit_id);
819 conversation_add_proto_data(conv, proto_iax2, iax_call);
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;
826 return conv;
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 is_forward_circuit(unsigned circuit_id,
834 const iax_call_data *iax_call)
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 true;
841 return false;
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 is_reverse_circuit(unsigned circuit_id,
848 const iax_call_data *iax_call)
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 true;
855 return false;
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 *reversed_p)
865 conversation_t *dst_conv;
866 iax_call_data *iax_call;
867 bool reversed = false;
869 dst_conv = find_conversation_by_id(framenum, CONVERSATION_IAX2, dst_circuit_id);
871 if (!dst_conv) {
872 #ifdef DEBUG_HASHING
873 ws_debug("++ destination circuit not found, must have missed NEW packet");
874 #endif
875 if (reversed_p)
876 *reversed_p = false;
877 return NULL;
880 #ifdef DEBUG_HASHING
881 ws_debug("++ found destination circuit");
882 #endif
884 iax_call = (iax_call_data *)conversation_get_proto_data(dst_conv, proto_iax2);
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);
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, "
893 "therefore packet is reversed");
894 #endif
896 reversed = true;
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 "
904 "new reverse circuit for this call");
905 #endif
907 iax2_new_circuit_for_call(pinfo, item, src_circuit_id, framenum, iax_call, true);
908 #ifdef DEBUG_HASHING
909 ws_debug("++ done");
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;
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, "
923 "therefore packet is forward");
924 #endif
926 reversed = false;
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 = false;
936 return NULL;
938 } else {
939 DISSECTOR_ASSERT_NOT_REACHED();
942 if (reversed_p)
943 *reversed_p = reversed;
945 return iax_call;
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 *reversed_p)
955 bool reversed = false;
956 iax_call_data *iax_call = NULL;
957 unsigned src_circuit_id;
958 #ifdef DEBUG_HASHING
959 char *srcstr, *dststr;
960 #endif
962 #ifdef DEBUG_HASHING
963 srcstr = address_to_str(NULL, &pinfo->src);
964 dststr = address_to_str(NULL, &pinfo->dst);
965 ws_debug("++ iax_lookup_circuit_details: Looking up circuit for frame %u, "
966 "from {%s:%u:%u} to {%s:%u:%u}", pinfo->num,
967 srcstr, pinfo->srcport, scallno,
968 dststr, pinfo->destport, dcallno);
969 wmem_free(NULL, srcstr);
970 wmem_free(NULL, dststr);
971 #endif
974 src_circuit_id = iax_circuit_lookup(&pinfo->src, pinfo->ptype,
975 pinfo->srcport, scallno);
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");
984 #endif
986 dst_circuit_id = iax_circuit_lookup(&pinfo->dst, pinfo->ptype,
987 pinfo->destport, dcallno);
989 iax_call = iax_lookup_call_from_dest(pinfo, NULL, src_circuit_id, dst_circuit_id,
990 pinfo->num, &reversed);
991 } else {
992 conversation_t *src_conv;
994 /* in all other circumstances, the source circuit should already
995 * exist: its absence indicates that we missed the all-important NEW
996 * packet.
999 src_conv = find_conversation_by_id(pinfo->num, CONVERSATION_IAX2, src_circuit_id);
1001 if (src_conv) {
1002 iax_call = (iax_call_data *)conversation_get_proto_data(src_conv, proto_iax2);
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);
1008 if (is_forward_circuit(src_circuit_id, iax_call))
1009 reversed = false;
1010 else if (is_reverse_circuit(src_circuit_id, iax_call))
1011 reversed = true;
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.
1017 DISSECTOR_ASSERT_NOT_REACHED();
1022 if (reversed_p)
1023 *reversed_p = reversed;
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');
1028 } else {
1029 ws_debug("++ Call not found. Must have missed the NEW packet?");
1031 #endif
1033 return iax_call;
1036 /* initialize the per-direction parts of an iax_call_data structure */
1037 static void init_dir_data(iax_call_dirdata *dirdata)
1039 dirdata -> current_frag_bytes=0;
1040 dirdata -> current_frag_minlen=0;
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)
1050 iax_call_data *call;
1051 unsigned circuit_id;
1052 static const nstime_t millisecond = NSTIME_INIT_SECS_MSECS(0, 1);
1054 #ifdef DEBUG_HASHING
1055 ws_debug("+ new_circuit: Handling NEW packet, frame %u", pinfo->num);
1056 #endif
1058 circuit_id = iax_circuit_lookup(&pinfo->src, pinfo->ptype,
1059 pinfo->srcport, scallno);
1061 call = wmem_new(wmem_file_scope(), 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;
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]);
1076 iax2_new_circuit_for_call(pinfo, NULL, circuit_id, pinfo->num, call, false);
1078 return call;
1082 /* ************************************************************************* */
1084 /* per-packet data */
1085 typedef struct iax_packet_data {
1086 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 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;
1096 static iax_packet_data *iax_new_packet_data(iax_call_data *call, bool reversed)
1098 iax_packet_data *p = wmem_new(wmem_file_scope(), iax_packet_data);
1099 p->first_time = true;
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;
1108 static void iax2_populate_pinfo_from_packet_data(packet_info *pinfo, const iax_packet_data *p)
1110 if (p->call_data != NULL) {
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_RECV:P2P_DIR_SENT;
1115 col_set_str(pinfo->cinfo, COL_IF_DIR, p->reversed ? "rev" : "fwd");
1120 /* ************************************************************************* */
1122 /* this is passed up from the IE dissector to the main dissector */
1123 typedef struct
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;
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);
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);
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);
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);
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 video,
1161 iax_packet_data *iax_packet);
1165 static int
1166 dissect_iax2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1168 proto_item *iax2_item;
1169 proto_tree *iax2_tree;
1170 proto_tree *full_mini_subtree = NULL;
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;
1177 /* set up the protocol and info fields in the summary pane */
1178 col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2);
1179 col_clear(pinfo->cinfo, COL_INFO);
1181 /* add the 'iax2' tree to the main tree */
1182 iax2_item = proto_tree_add_item(tree, proto_iax2, tvb, offset, -1, ENC_NA);
1183 iax2_tree = proto_item_add_subtree(iax2_item, ett_iax2);
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;
1197 else {
1198 type = IAX2_TRUNK_PACKET;
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;
1209 scallno &= 0x7FFF;
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);
1215 if (scallno != 0)
1216 proto_tree_add_item(full_mini_subtree, hf_iax2_scallno, tvb, offset-2, 2, ENC_BIG_ENDIAN);
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;
1227 iax2_info->callingParty = NULL;
1228 iax2_info->calledParty = NULL;
1229 iax2_info->payload_data = NULL;
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;
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);
1258 static proto_item *dissect_datetime_ie(tvbuff_t *tvb, uint32_t offset, proto_tree *ies_tree)
1260 struct tm tm;
1261 uint32_t ie_val;
1262 nstime_t datetime;
1264 proto_tree_add_item(ies_tree, hf_iax2_ies[IAX_IE_DATETIME], tvb, offset + 2, 4, ENC_BIG_ENDIAN);
1265 ie_val = tvb_get_ntohl(tvb, offset+2);
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 */
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);
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)
1288 DISSECTOR_ASSERT(ie_data);
1290 while (offset < tvb_reported_length(tvb)) {
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;
1296 /* do non-tree-dependent stuff first */
1297 switch (ies_type) {
1298 case IAX_IE_DATAFORMAT:
1299 if (ies_len != 4) {
1300 proto_tree_add_expert(iax_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1);
1301 break;
1303 ie_data -> dataformat = tvb_get_ntohl(tvb, offset+2);
1304 break;
1306 case IAX_IE_CALLED_NUMBER:
1307 iax2_info->calledParty = tvb_format_text(pinfo->pool, tvb, offset+2, ies_len);
1308 break;
1309 case IAX_IE_CALLING_NUMBER:
1310 iax2_info->callingParty = tvb_format_text(pinfo->pool, tvb, offset+2, ies_len);
1311 break;
1313 case IAX_IE_APPARENT_ADDR:
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).
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_INET:
1326 /* IAX is always over UDP */
1327 ie_data->peer_ptype = PT_UDP;
1328 ie_data->peer_port = tvb_get_ntohs(tvb, offset+4);
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;
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;
1339 break;
1343 /* the rest of this stuff only needs doing if we have an iax_tree */
1345 if (iax_tree && ies_type < NUM_HF_IAX2_IES) {
1346 proto_item *ti, *ie_item = NULL;
1347 proto_tree *ies_tree;
1348 int ie_hf = hf_iax2_ies[ies_type];
1350 ies_tree = proto_tree_add_subtree(iax_tree, tvb, offset, ies_len+2, ett_iax2_ie, &ti, " ");
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);
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.
1363 switch (ies_type) {
1364 case IAX_IE_DATETIME:
1365 ie_item = dissect_datetime_ie(tvb, offset, ies_tree);
1366 break;
1369 case IAX_IE_CAPABILITY:
1371 if (ies_len != 4) {
1372 proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1);
1373 break;
1376 ie_item =
1377 proto_tree_add_bitmask(ies_tree, tvb, offset + 2, ie_hf,
1378 ett_iax2_codecs, hf_iax2_caps, ENC_BIG_ENDIAN);
1379 break;
1383 case IAX_IE_CAPABILITY2:
1385 int version = tvb_get_uint8(tvb, offset + 2);
1387 proto_tree_add_uint(ies_tree, hf_iax2_version, tvb, offset + 2, 1, version);
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;
1395 ie_item =
1396 proto_tree_add_bitmask(ies_tree, tvb, offset + 3, ie_hf,
1397 ett_iax2_codecs, hf_iax2_caps, ENC_BIG_ENDIAN);
1399 break;
1403 case IAX_IE_FORMAT:
1405 if (ies_len != 4) {
1406 proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1);
1407 break;
1410 ie_item =
1411 proto_tree_add_item(ies_tree, ie_hf,
1412 tvb, offset + 2, 4, ENC_BIG_ENDIAN);
1413 break;
1417 case IAX_IE_FORMAT2:
1419 int version = tvb_get_uint8(tvb, offset + 2);
1421 proto_tree_add_uint(ies_tree, hf_iax2_version, tvb, offset + 2, 1, version);
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;
1429 ie_item =
1430 proto_tree_add_item(ies_tree, ie_hf,
1431 tvb, offset + 3, 8, ENC_BIG_ENDIAN);
1433 break;
1437 case IAX_IE_APPARENT_ADDR:
1439 proto_tree *sockaddr_tree;
1441 sockaddr_tree = proto_tree_add_subtree(ies_tree, tvb, offset + 2, 16,
1442 ett_iax2_ies_apparent_addr, &ie_item, "Apparent Address");
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).
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);
1456 if (apparent_addr_family == LINUX_AF_INET) {
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);
1462 break;
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;
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_ENDIAN);
1487 break;
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_NA);
1492 break;
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_8|ENC_NA);
1497 break;
1499 default:
1500 DISSECTOR_ASSERT_NOT_REACHED();
1501 break;
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");
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;
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;
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;
1534 default:
1535 ptr = tvb_get_string_enc(pinfo->pool, tvb, offset + 2, ies_len, ENC_ASCII);
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;
1543 break;
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);
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)
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_LENGTH);
1558 proto_item_fill_label(ie_finfo, ie_val, NULL);
1559 proto_item_set_text(ti, "Information Element: %s",
1560 ie_val);
1565 offset += ies_len + 2;
1567 return offset;
1570 static uint32_t uncompress_subclass(uint8_t csub)
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;
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;
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)
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;
1604 ie_data.peer_address.type = AT_NONE;
1605 ie_data.peer_address.len = 0;
1606 ie_data.peer_address.data = NULL;
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;
1613 /* add the subclass */
1614 ti = proto_tree_add_uint(tree, hf_iax2_iax_csub, tvb, offset, 1, csub);
1615 offset++;
1617 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1618 val_to_str_ext(csub, &iax_iax_subclasses_ext, "unknown (0x%02x)"));
1620 if (offset >= tvb_reported_length(tvb))
1621 return offset;
1623 offset = dissect_ies(tvb, pinfo, offset, tree, ti, &ie_data);
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) {
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;
1631 /* if this is a transfer request, record it in the call data */
1632 if (csub == IAX_COMMAND_TXREQ && 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);
1639 iax2_new_circuit_for_call(pinfo, NULL, tx_circuit, pinfo->num, iax_call, iax_packet->reversed);
1643 return offset;
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)
1648 uint32_t full_relts = relts;
1649 nstime_t lateness;
1650 proto_item *item;
1652 if (iax_packet->call_data == NULL) {
1653 /* no call info for this frame; perhaps we missed the NEW packet */
1654 return;
1657 if (iax_packet->abstime.secs == -1) {
1658 nstime_t rel;
1660 switch (type) {
1661 case IAX2_MINI_VOICE_PACKET:
1662 /* RFC 5456 says
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.
1668 * and, for what it later calls "Mini Frames", by which it means
1669 * what we're calling "mini voice packets", it says:
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.
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.
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;
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.
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;
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":
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.
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.
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.
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;
1730 /* Convert the full relative time stamp to an nstime_t */
1731 rel.secs = full_relts / 1000;
1732 rel.nsecs = (full_relts % 1000) * 1000000;
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);
1737 iax2_info->timestamp = relts; /* raw time stamp; nobody uses it */
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);
1743 nstime_delta(&lateness, &pinfo->abs_ts, &iax_packet->abstime);
1745 item = proto_tree_add_time(iax2_tree, hf_iax2_lateness, tvb, 0, 0, &lateness);
1746 proto_item_set_generated(item);
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)
1757 uint16_t dcallno;
1758 uint32_t ts;
1759 uint8_t type;
1760 uint8_t csub;
1761 uint32_t codec;
1763 proto_tree *packet_type_tree = NULL;
1764 iax_call_data *iax_call;
1765 iax_packet_data *iax_packet;
1766 bool reversed;
1767 bool rtp_marker;
1770 * remove the top bit for retransmission detection
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;
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. */
1786 if (type == AST_FRAME_IAX && csub == IAX_COMMAND_NEW) {
1787 /* NEW packets start a new call */
1788 iax_call = iax_new_call(pinfo, scallno);
1789 reversed = false;
1790 } else {
1791 iax_call = iax_lookup_call(pinfo, scallno, dcallno,
1792 &reversed);
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;
1802 iax2_populate_pinfo_from_packet_data(pinfo, iax_packet);
1804 if (iax2_tree) {
1805 proto_item *packet_type_base;
1807 proto_tree_add_item(iax2_tree, hf_iax2_dcallno, tvb, offset, 2, ENC_BIG_ENDIAN);
1809 proto_tree_add_item(iax2_tree, hf_iax2_retransmission, tvb, offset, 2, ENC_BIG_ENDIAN);
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);
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);
1821 proto_tree_add_item(iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1,
1822 ENC_BIG_ENDIAN);
1824 proto_tree_add_item(iax2_tree, hf_iax2_iseqno, tvb, offset+7, 1,
1825 ENC_BIG_ENDIAN);
1826 packet_type_base = proto_tree_add_uint(iax2_tree, hf_iax2_type, tvb,
1827 offset+8, 1, type);
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);
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(type, &iax_frame_types_ext, "Unknown (0x%02x)"),
1839 scallno, ts);
1841 iax2_info->messageName = val_to_str_ext(type, &iax_frame_types_ext, "Unknown (0x%02x)");
1843 switch (type) {
1844 case AST_FRAME_IAX:
1845 offset=dissect_iax2_command(tvb, offset+9, pinfo, packet_type_tree, iax_packet);
1846 iax2_info->messageName = val_to_str_ext(csub, &iax_iax_subclasses_ext, "unknown (0x%02x)");
1847 if (csub < NUM_TAP_IAX_VOIP_STATES) iax2_info->callState = tap_iax_voip_state[csub];
1848 break;
1850 case AST_FRAME_DTMF_BEGIN:
1851 case AST_FRAME_DTMF_END:
1852 proto_tree_add_item(packet_type_tree, hf_iax2_dtmf_csub, tvb, offset+9, 1, ENC_ASCII);
1853 offset += 10;
1855 col_append_fstr(pinfo->cinfo, COL_INFO, " digit %s", format_char(pinfo->pool, csub));
1856 break;
1858 case AST_FRAME_CONTROL:
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;
1864 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1865 val_to_str_ext(csub, &iax_cmd_subclasses_ext, "unknown (0x%02x)"));
1866 iax2_info->messageName = val_to_str_ext (csub, &iax_cmd_subclasses_ext, "unknown (0x%02x)");
1867 if (csub < NUM_TAP_CMD_VOIP_STATES) iax2_info->callState = tap_cmd_voip_state[csub];
1868 break;
1870 case AST_FRAME_VOICE:
1871 /* add the codec */
1872 iax_packet -> codec = codec = uncompress_subclass(csub);
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_ENDIAN);
1877 item = proto_tree_add_uint64(packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, CODEC_MASK(codec));
1878 proto_item_set_generated(item);
1881 offset += 10;
1883 if (iax_call) {
1884 if (reversed) {
1885 iax_call->dst_codec = codec;
1886 } else {
1887 iax_call->src_codec = codec;
1891 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, false, iax_packet);
1892 break;
1894 case AST_FRAME_VIDEO:
1895 /* bit 6 of the csub is used to represent the rtp 'marker' bit */
1896 rtp_marker = csub & 0x40 ? true:false;
1897 iax_packet -> codec = codec = uncompress_subclass((uint8_t)(csub & ~0x40));
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_ENDIAN);
1902 proto_tree_add_item(packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1903 item = proto_tree_add_uint64(packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, CODEC_MASK(codec));
1904 proto_item_set_generated(item);
1907 offset += 10;
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;
1917 if (rtp_marker)
1918 col_append_str(pinfo->cinfo, COL_INFO, ", Mark");
1921 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, true, iax_packet);
1922 break;
1924 case AST_FRAME_MODEM:
1925 proto_tree_add_item(packet_type_tree, hf_iax2_modem_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1926 offset += 10;
1928 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1929 val_to_str(csub, iax_modem_subclasses, "unknown (0x%02x)"));
1930 break;
1932 case AST_FRAME_TEXT:
1933 proto_tree_add_item(packet_type_tree, hf_iax2_text_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1934 offset += 10;
1937 int textlen = tvb_captured_length_remaining(tvb, offset);
1938 if (textlen > 0)
1940 proto_tree_add_item(packet_type_tree, hf_iax2_text_text, tvb, offset, textlen, ENC_UTF_8);
1941 offset += textlen;
1944 break;
1946 case AST_FRAME_HTML:
1947 proto_tree_add_item(packet_type_tree, hf_iax2_html_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1948 offset += 10;
1950 if (csub == 0x01)
1952 int urllen = tvb_captured_length_remaining(tvb, offset);
1953 if (urllen > 0)
1955 proto_item *pi = proto_tree_add_item(packet_type_tree, hf_iax2_html_url, tvb, offset, urllen, ENC_UTF_8);
1956 proto_item_set_url(pi);
1957 offset += urllen;
1960 break;
1962 case AST_FRAME_CNG:
1963 default:
1964 proto_tree_add_uint(packet_type_tree, hf_iax2_csub, tvb, offset+9,
1965 1, csub);
1966 offset += 10;
1968 col_append_fstr(pinfo->cinfo, COL_INFO, " subclass %d", csub);
1969 break;
1972 /* next time we come to parse this packet, don't propagate the codec into the
1973 * call_data */
1974 iax_packet->first_time = false;
1976 return offset;
1979 static iax_packet_data *iax2_get_packet_data_for_minipacket(packet_info *pinfo,
1980 uint16_t scallno,
1981 bool video)
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);
1986 if (!p) {
1987 /* if not, find or create an iax_call info structure for this IAX session. */
1988 bool reversed;
1989 iax_call_data *iax_call;
1991 iax_call = iax_lookup_call(pinfo, scallno, 0, &reversed);
1993 p = iax_new_packet_data(iax_call, reversed);
1994 p_add_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0, p);
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;
2005 iax2_populate_pinfo_from_packet_data(pinfo, p);
2006 return p;
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)
2014 uint32_t ts;
2015 iax_packet_data *iax_packet;
2016 bool rtp_marker;
2017 proto_item *item;
2019 ts = tvb_get_ntohs(tvb, offset);
2021 /* bit 15 of the ts is used to represent the rtp 'marker' bit */
2022 rtp_marker = ts & 0x8000 ? true:false;
2023 ts &= ~0x8000;
2025 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, true);
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);
2035 proto_tree_add_item(iax2_tree, hf_iax2_minividts, tvb, offset, 2, ENC_BIG_ENDIAN);
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_ENDIAN);
2038 } else {
2039 iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VIDEO_PACKET, ts);
2042 offset += 2;
2044 col_add_fstr(pinfo->cinfo, COL_INFO,
2045 "Mini video packet, source call# %d, timestamp %ums%s",
2046 scallno, ts, rtp_marker?", Mark":"");
2049 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, true, iax_packet);
2051 /* next time we come to parse this packet, don't propagate the codec into the
2052 * call_data */
2053 iax_packet->first_time = false;
2055 return offset;
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)
2062 uint32_t ts;
2063 iax_packet_data *iax_packet;
2064 proto_item *item;
2066 ts = tvb_get_ntohs(tvb, offset);
2068 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, false);
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);
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);
2084 offset += 2;
2086 col_add_fstr(pinfo->cinfo, COL_INFO,
2087 "Mini packet, source call# %d, timestamp %ums",
2088 scallno, ts);
2091 /* XXX fix the timestamp logic */
2092 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, false, iax_packet);
2095 /* next time we come to parse this packet, don't propagate the codec into the
2096 * call_data */
2097 iax_packet->first_time = false;
2099 return offset;
2103 static uint32_t dissect_trunkcall_ts(tvbuff_t *tvb, uint32_t offset, proto_tree *iax2_tree, uint16_t *scallno)
2105 proto_tree *call_tree;
2106 uint16_t datalen, rlen, ts;
2108 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2109 | Data Length (in octets) |R| Source Call Number |
2110 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2111 | time-stamp | |
2112 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
2113 | Data |
2116 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2118 datalen = tvb_get_ntohs(tvb, offset);
2119 *scallno = tvb_get_ntohs(tvb, offset + 2);
2120 ts = tvb_get_ntohs(tvb, offset + 4);
2122 rlen = MIN(tvb_captured_length(tvb) - offset - 6, datalen);
2124 if (iax2_tree) {
2125 call_tree = proto_tree_add_subtree_format(iax2_tree, tvb, offset, rlen + 6,
2126 ett_iax2_trunk_call, NULL, "Trunk call from %u, ts: %u", *scallno, ts);
2128 proto_tree_add_item(call_tree, hf_iax2_trunk_call_len, tvb, offset, 2, ENC_BIG_ENDIAN);
2129 proto_tree_add_item(call_tree, hf_iax2_trunk_call_scallno, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2130 proto_tree_add_item(call_tree, hf_iax2_trunk_call_ts, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
2131 proto_tree_add_item(call_tree, hf_iax2_trunk_call_data, tvb, offset + 6, rlen, ENC_NA);
2133 offset += 6 + rlen;
2135 return offset;
2138 static uint32_t dissect_trunkcall_nots(tvbuff_t *tvb, uint32_t offset, proto_tree *iax2_tree, uint16_t *scallno)
2140 proto_tree *call_tree;
2141 uint16_t datalen, rlen;
2143 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2144 |R| Source Call Number | Data Length (in octets) |
2145 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2147 : Data :
2149 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2151 *scallno = tvb_get_ntohs(tvb, offset);
2152 datalen = tvb_get_ntohs(tvb, offset + 2);
2154 rlen = MIN(tvb_captured_length(tvb) - offset - 4, datalen);
2156 if (iax2_tree) {
2157 call_tree = proto_tree_add_subtree_format(iax2_tree, tvb, offset, rlen + 6,
2158 ett_iax2_trunk_call, NULL, "Trunk call from %u", *scallno);
2160 proto_tree_add_item(call_tree, hf_iax2_trunk_call_scallno, tvb, offset, 2, ENC_BIG_ENDIAN);
2161 proto_tree_add_item(call_tree, hf_iax2_trunk_call_len, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2162 proto_tree_add_item(call_tree, hf_iax2_trunk_call_data, tvb, offset + 4, rlen, ENC_NA);
2164 offset += 4 + rlen;
2166 return offset;
2169 typedef struct _call_list {
2170 uint16_t scallno;
2171 struct _call_list *next;
2172 } call_list;
2174 static call_list *call_list_append(wmem_allocator_t *pool, call_list *list, uint16_t scallno)
2176 call_list *node = wmem_new0(pool, call_list);
2178 node->scallno = scallno;
2180 if (list) {
2181 call_list *cur = list;
2182 while (cur->next) {
2183 cur = cur->next;
2185 cur->next = node;
2186 return list;
2187 } else {
2188 return node;
2192 static bool call_list_find(call_list *list, uint16_t scallno)
2194 for (; list; list = list->next) {
2195 if (list->scallno == scallno) {
2196 return true;
2199 return false;
2202 static unsigned call_list_length(call_list *list)
2204 unsigned count = 0;
2205 for (; list; list = list->next) {
2206 count++;
2208 return count;
2211 static uint32_t dissect_trunkpacket(tvbuff_t *tvb, uint32_t offset,
2212 uint16_t scallno_param _U_, packet_info *pinfo,
2213 proto_tree *iax2_tree, proto_tree *main_tree _U_)
2215 uint8_t cmddata, trunkts;
2216 unsigned nframes = 0, ncalls = 0;
2217 proto_item *cd, *nc = NULL;
2218 proto_tree *field_tree = NULL;
2219 call_list *calls = NULL;
2220 /*iax_packet_data *iax_packet;*/
2222 cmddata = tvb_get_uint8(tvb, offset + 1);
2223 trunkts = cmddata & IAX2_TRUNK_TS;
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 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
2232 if (iax2_tree) {
2233 /* Meta Command */
2234 proto_tree_add_item(iax2_tree, hf_iax2_trunk_metacmd, tvb, offset, 1, ENC_BIG_ENDIAN);
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)");
2242 /* CD -> Trunk timestamp */
2243 proto_tree_add_boolean(field_tree, hf_iax2_trunk_cmddata_ts, tvb, offset + 1, 1, cmddata);
2245 /* Timestamp */
2246 proto_tree_add_item(iax2_tree, hf_iax2_trunk_ts, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
2249 offset += 6;
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);
2259 nframes++;
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);
2270 nframes++;
2274 ncalls = call_list_length(calls);
2276 if (iax2_tree) {
2277 /* number of items */
2278 nc = proto_tree_add_uint(iax2_tree, hf_iax2_trunk_ncalls, NULL, 0, 0, ncalls);
2279 proto_item_set_generated(nc);
2282 col_add_fstr(pinfo->cinfo, COL_INFO, "Trunk packet with %d media frame%s for %d call%s",
2283 nframes, plurality(nframes, "", "s"),
2284 ncalls, plurality(ncalls, "", "s"));
2286 return offset;
2290 static void process_iax_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2291 bool video, iax_packet_data *iax_packet)
2293 uint32_t codec = iax_packet -> codec;
2294 iax_call_data *iax_call = iax_packet -> call_data;
2296 #ifdef DEBUG_DESEGMENT
2297 ws_debug("calling process_iax_pdu; len = %u", tvb_reported_length(tvb));
2298 #endif
2300 if (!video && iax_call && iax_call->subdissector) {
2301 iax2_dissector_info_t dissector_info;
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) {
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];
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);
2322 #ifdef DEBUG_DESEGMENT
2323 ws_debug("called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u",
2324 pinfo->desegment_len, pinfo->desegment_offset);
2325 #endif
2328 static void desegment_iax(tvbuff_t *tvb, packet_info *pinfo, proto_tree *iax2_tree,
2329 proto_tree *tree, bool video, iax_packet_data *iax_packet)
2332 iax_call_data *iax_call = iax_packet -> call_data;
2333 iax_call_dirdata *dirdata;
2334 void * value = NULL;
2335 uint32_t frag_offset = 0;
2336 fragment_head *fd_head;
2337 bool must_desegment = false;
2339 DISSECTOR_ASSERT(iax_call);
2341 pinfo->can_desegment = 2;
2342 pinfo->desegment_offset = 0;
2343 pinfo->desegment_len = 0;
2345 #ifdef DEBUG_DESEGMENT
2346 ws_debug("dissecting packet %u", pinfo->num);
2347 #endif
2349 dirdata = &(iax_call->dirdata[!!(iax_packet->reversed)]);
2351 if ((!pinfo->fd->visited && (dirdata->current_frag_bytes > 0)) ||
2352 ((value = g_hash_table_lookup(iax_fid_table, GUINT_TO_POINTER(pinfo->num))) != NULL)) {
2354 /* then we are continuing an already-started pdu */
2355 uint32_t fid;
2356 uint32_t frag_len = tvb_reported_length(tvb);
2357 bool complete;
2359 #ifdef DEBUG_DESEGMENT
2360 ws_debug("visited: %i; c_f_b: %u; hash: %u->%u", pinfo->fd->visited?1:0,
2361 dirdata->current_frag_bytes, pinfo->num, dirdata->current_frag_id);
2362 #endif
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);
2369 g_hash_table_insert(iax_fid_table, GUINT_TO_POINTER(pinfo->num), GUINT_TO_POINTER(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",
2375 pinfo->num, fid, frag_offset, dirdata->current_frag_bytes, tot_len);
2376 #endif
2377 } else {
2378 fid = GPOINTER_TO_UINT(value);
2379 /* these values are unused by fragment_add if pinfo->fd->visited */
2380 dirdata->current_frag_bytes = 0;
2381 complete = false;
2384 /* fragment_add checks for already-added */
2385 fd_head = fragment_add(&iax_reassembly_table, tvb, 0, pinfo, fid, NULL,
2386 frag_offset,
2387 frag_len, !complete);
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");
2394 process_iax_pdu(next_tvb, pinfo, tree, video, iax_packet);
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.
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);
2406 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
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;
2412 } else {
2413 /* we successfully dissected some data; create the proto tree items for
2414 * the fragments, and flag any remaining data for desegmentation */
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);
2424 dirdata->current_frag_minlen = dirdata->current_frag_id = dirdata->current_frag_bytes = 0;
2426 if (pinfo->desegment_len) {
2427 /* there's a bit of data left to desegment */
2428 must_desegment = true;
2429 /* make desegment_offset relative to our tvb */
2430 pinfo->desegment_offset -= old_len;
2433 /* don't add a 'reassembled in' item for this pdu */
2434 fd_head = NULL;
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.
2443 process_iax_pdu(tvb, pinfo, tree, video, iax_packet);
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 = true;
2452 fd_head = NULL;
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;
2465 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
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;
2472 fd_head = fragment_add(&iax_reassembly_table,
2473 tvb, deseg_offset, pinfo, fid, NULL,
2474 0, frag_len, true);
2475 #ifdef DEBUG_DESEGMENT
2476 ws_debug("Start offset of undissected bytes: %u; "
2477 "Bytes remaining in this segment: %u; min required bytes: %u\n",
2478 deseg_offset, frag_len, frag_len + pinfo->desegment_len);
2479 #endif
2482 /* add a 'reassembled in' item if necessary */
2483 if (fd_head != NULL) {
2484 uint32_t deseg_offset = pinfo->desegment_offset;
2485 if (fd_head->reassembled_in != 0 &&
2486 !(fd_head->flags & FD_PARTIAL_REASSEMBLY)) {
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_NA);
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]");
2503 pinfo->can_desegment = 0;
2504 pinfo->desegment_offset = 0;
2505 pinfo->desegment_len = 0;
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_, bool video,
2511 iax_packet_data *iax_packet)
2513 #if 0
2514 bool out_of_order = false;
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;
2521 if (offset >= tvb_reported_length(tvb)) {
2522 col_append_str(pinfo->cinfo, COL_INFO, ", empty frame");
2523 return;
2526 sub_tvb = tvb_new_subset_remaining(tvb, offset);
2528 /* XXX shouldn't pass through out-of-order packets. */
2530 if (!video && iax_call && iax_call -> dataformat != 0) {
2531 col_append_fstr(pinfo->cinfo, COL_INFO, ", data, format %s",
2532 val_to_str(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(CODEC_MASK(codec), &codec_types_ext, "unknown (0x%04x)"));
2543 nbytes = tvb_reported_length(sub_tvb);
2544 proto_tree_add_item(iax2_tree, hf_iax2_payload_data, sub_tvb, 0, -1, ENC_NA);
2546 iax2_info->payload_len = nbytes;
2547 iax2_info->payload_data = tvb_get_ptr(sub_tvb, 0, -1);
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);
2557 * Init routines
2560 /* called at the start of a capture. We should clear out our static, per-capture
2561 * data.
2564 static void
2565 iax_init_protocol(void)
2567 iax_circuit_hashtab = g_hash_table_new(iax_circuit_hash, iax_circuit_equal);
2568 circuitcount = 0;
2570 iax_fid_table = g_hash_table_new(g_direct_hash, g_direct_equal);
2573 static void
2574 iax_cleanup_protocol(void)
2576 g_hash_table_destroy(iax_circuit_hashtab);
2577 g_hash_table_destroy(iax_fid_table);
2581 void
2582 proto_register_iax2(void)
2584 /* A header field is something you can search/filter on.
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}}.
2591 static hf_register_info hf[] = {
2593 {&hf_iax2_packet_type,
2594 {"Packet type", "iax2.packet_type",
2595 FT_UINT8, BASE_DEC, VALS(iax_packet_types), 0,
2596 "Full/minivoice/minivideo/trunk packet",
2597 HFILL}},
2599 {&hf_iax2_callno,
2600 {"Call identifier", "iax2.call",
2601 FT_UINT32, BASE_DEC, NULL, 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 }},
2606 {&hf_iax2_scallno,
2607 {"Source call", "iax2.src_call",
2608 FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2609 "src_call holds the number of this call at the packet source pbx",
2610 HFILL}},
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, 0x7FFF,
2616 "dst_call holds the number of this call at the packet destination",
2617 HFILL}},
2619 {&hf_iax2_retransmission,
2620 {"Retransmission", "iax2.retransmission",
2621 FT_BOOLEAN, 16, NULL, 0x8000,
2622 "retransmission is set if this packet is a retransmission of an earlier failed packet",
2623 HFILL}},
2625 {&hf_iax2_ts,
2626 {"Timestamp", "iax2.timestamp",
2627 FT_UINT32, BASE_DEC, NULL, 0x0,
2628 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2629 HFILL}},
2631 {&hf_iax2_minits,
2632 {"Timestamp", "iax2.timestamp",
2633 FT_UINT16, BASE_DEC, NULL, 0x0,
2634 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2635 HFILL}},
2637 {&hf_iax2_minividts,
2638 {"Timestamp", "iax2.timestamp",
2639 FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2640 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2641 HFILL}},
2643 {&hf_iax2_absts,
2644 {"Absolute Time", "iax2.abstime",
2645 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2646 "The absolute time of this packet (calculated by adding the IAX timestamp to the start time of this call)",
2647 HFILL}},
2649 {&hf_iax2_lateness,
2650 {"Lateness", "iax2.lateness",
2651 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2652 "The lateness of this packet compared to its timestamp",
2653 HFILL}},
2655 {&hf_iax2_minividmarker,
2656 {"Marker", "iax2.video.mini_marker",
2657 FT_UINT16, BASE_DEC, NULL, 0x8000,
2658 "RTP end-of-frame marker",
2659 HFILL}},
2661 {&hf_iax2_oseqno,
2662 {"Outbound seq.no.", "iax2.oseqno",
2663 FT_UINT16, BASE_DEC, NULL, 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}},
2668 {&hf_iax2_iseqno,
2669 {"Inbound seq.no.", "iax2.iseqno",
2670 FT_UINT16, BASE_DEC, NULL, 0x0,
2671 "iseqno is the sequence no of the last successfully received packet",
2672 HFILL}},
2674 {&hf_iax2_type,
2675 {"Type", "iax2.type",
2676 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &iax_frame_types_ext, 0x0,
2677 "For full IAX2 frames, type is the type of frame",
2678 HFILL}},
2680 {&hf_iax2_csub,
2681 {"Unknown subclass", "iax2.subclass",
2682 FT_UINT8, BASE_DEC, NULL, 0x0,
2683 "Subclass of unknown type of full IAX2 frame",
2684 HFILL}},
2686 {&hf_iax2_dtmf_csub,
2687 {"DTMF subclass (digit)", "iax2.dtmf.subclass",
2688 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2689 "DTMF subclass gives the DTMF digit",
2690 HFILL}},
2692 {&hf_iax2_cmd_csub,
2693 {"Control subclass", "iax2.control.subclass",
2694 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &iax_cmd_subclasses_ext, 0x0,
2695 "This gives the command number for a Control packet.",
2696 HFILL}},
2698 {&hf_iax2_iax_csub,
2699 {"IAX subclass", "iax2.iax.subclass",
2700 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &iax_iax_subclasses_ext, 0x0,
2701 "IAX subclass gives the command number for IAX signaling packets",
2702 HFILL}},
2704 {&hf_iax2_voice_csub,
2705 {"Voice Subclass (compressed codec no)", "iax2.voice.subclass",
2706 FT_UINT8, BASE_DEC, NULL, 0x0,
2707 NULL, HFILL}},
2709 {&hf_iax2_voice_codec,
2710 {"CODEC", "iax2.voice.codec",
2711 FT_UINT64, BASE_HEX | BASE_EXT_STRING | BASE_VAL64_STRING, &codec_types_ext, 0x0,
2712 "CODEC gives the codec used to encode audio data",
2713 HFILL}},
2715 {&hf_iax2_video_csub,
2716 {"Video Subclass (compressed codec no)", "iax2.video.subclass",
2717 FT_UINT8, BASE_DEC, NULL, 0xBF,
2718 NULL, HFILL}},
2720 {&hf_iax2_marker,
2721 {"Marker", "iax2.video.marker",
2722 FT_BOOLEAN, 8, NULL, 0x40,
2723 "RTP end-of-frame marker",
2724 HFILL}},
2726 {&hf_iax2_video_codec,
2727 {"CODEC", "iax2.video.codec",
2728 FT_UINT64, BASE_HEX | BASE_EXT_STRING | BASE_VAL64_STRING, &codec_types_ext, 0,
2729 "The codec used to encode video data",
2730 HFILL}},
2732 {&hf_iax2_modem_csub,
2733 {"Modem subclass", "iax2.modem.subclass",
2734 FT_UINT8, BASE_DEC, VALS(iax_modem_subclasses), 0x0,
2735 "Modem subclass gives the type of modem",
2736 HFILL}},
2738 {&hf_iax2_text_csub,
2739 {"Text subclass", "iax2.text.subclass",
2740 FT_UINT8, BASE_DEC, VALS(iax_text_subclasses), 0x0,
2741 NULL,
2742 HFILL}},
2744 {&hf_iax2_text_text,
2745 {"Text", "iax2.text.text",
2746 FT_STRING, BASE_NONE, NULL, 0x0,
2747 NULL,
2748 HFILL}},
2750 {&hf_iax2_html_csub,
2751 {"HTML subclass", "iax2.html.subclass",
2752 FT_UINT8, BASE_DEC, VALS(iax_html_subclasses), 0x0,
2753 NULL,
2754 HFILL}},
2756 {&hf_iax2_html_url,
2757 {"HTML URL", "iax2.html.url",
2758 FT_STRING, BASE_NONE, NULL, 0x0,
2759 NULL,
2760 HFILL}},
2762 {&hf_iax2_trunk_ts,
2763 {"Timestamp", "iax2.timestamp",
2764 FT_UINT32, BASE_DEC, NULL, 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}},
2769 {&hf_iax2_trunk_metacmd,
2770 {"Meta command", "iax2.trunk.metacmd",
2771 FT_UINT8, BASE_DEC, NULL, 0x7F,
2772 "Meta command indicates whether or not the Meta Frame is a trunk.",
2773 HFILL}},
2775 {&hf_iax2_trunk_cmddata,
2776 {"Command data", "iax2.trunk.cmddata",
2777 FT_UINT8, BASE_HEX, NULL, 0x0,
2778 "Flags for options that apply to a trunked call",
2779 HFILL}},
2781 {&hf_iax2_trunk_cmddata_ts,
2782 {"Trunk timestamps", "iax2.trunk.cmddata.ts",
2783 FT_BOOLEAN, 8, NULL, IAX2_TRUNK_TS,
2784 "True: calls do each include their own timestamp",
2785 HFILL}},
2787 {&hf_iax2_trunk_call_len,
2788 {"Data length", "iax2.trunk.call.len",
2789 FT_UINT16, BASE_DEC, NULL, 0x0,
2790 "Trunk call data length in octets",
2791 HFILL}},
2793 {&hf_iax2_trunk_call_scallno,
2794 {"Source call number", "iax2.trunk.call.scallno",
2795 FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2796 "Trunk call source call number",
2797 HFILL}},
2799 {&hf_iax2_trunk_call_ts,
2800 {"Timestamp", "iax2.trunk.call.ts",
2801 FT_UINT16, BASE_DEC, NULL, 0x0,
2802 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2803 HFILL}},
2805 {&hf_iax2_trunk_call_data,
2806 {"Data", "iax2.trunk.call.payload",
2807 FT_BYTES, BASE_NONE, NULL, 0x0,
2808 "Payload carried by this trunked packet.",
2809 HFILL}},
2811 {&hf_iax2_trunk_ncalls,
2812 {"Number of calls", "iax2.trunk.ncalls",
2813 FT_UINT16, BASE_DEC, NULL, 0x0,
2814 "Number of calls in this trunk packet",
2815 HFILL}},
2818 * Decoding for the ies
2821 {&hf_IAX_IE_APPARENTADDR_SINFAMILY,
2822 {"Family", "iax2.iax.app_addr.sinfamily",
2823 FT_UINT16, BASE_DEC, NULL, 0,
2824 NULL, HFILL }},
2826 {&hf_IAX_IE_APPARENTADDR_SINPORT,
2827 {"Port", "iax2.iax.app_addr.sinport",
2828 FT_UINT16, BASE_DEC, NULL, 0,
2829 NULL, HFILL }},
2831 {&hf_IAX_IE_APPARENTADDR_SINADDR,
2832 {"Address", "iax2.iax.app_addr.sinaddr",
2833 FT_IPv4, BASE_NONE, NULL, 0,
2834 NULL, HFILL }},
2836 {&hf_iax2_ies[IAX_IE_CALLED_NUMBER],
2837 {"Number/extension being called", "iax2.iax.called_number",
2838 FT_STRING,
2839 BASE_NONE, NULL, 0x0, NULL, HFILL}},
2841 {&hf_iax2_ies[IAX_IE_CALLING_NUMBER],
2842 {"Calling number", "iax2.iax.calling_number",
2843 FT_STRING, BASE_NONE, NULL, 0x0,
2844 NULL, HFILL}},
2847 {&hf_iax2_ies[IAX_IE_CALLING_ANI],
2848 {"Calling number ANI for billing", "iax2.iax.calling_ani",
2849 FT_STRING, BASE_NONE, NULL, 0x0,
2850 NULL, HFILL}},
2852 {&hf_iax2_ies[IAX_IE_CALLING_NAME],
2853 {"Name of caller", "iax2.iax.calling_name",
2854 FT_STRING, BASE_NONE, NULL, 0x0,
2855 NULL, HFILL}},
2857 {&hf_iax2_ies[IAX_IE_CALLED_CONTEXT],
2858 {"Context for number", "iax2.iax.called_context",
2859 FT_STRING, BASE_NONE, NULL, 0x0,
2860 NULL, HFILL}},
2862 {&hf_iax2_ies[IAX_IE_USERNAME],
2863 {"Username (peer or user) for authentication", "iax2.iax.username",
2864 FT_STRING, BASE_NONE, NULL, 0x0,
2865 NULL, HFILL}},
2867 {&hf_iax2_ies[IAX_IE_PASSWORD],
2868 {"Password for authentication", "iax2.iax.password",
2869 FT_STRING, BASE_NONE, NULL, 0x0,
2870 NULL, HFILL}},
2872 {&hf_iax2_ies[IAX_IE_CAPABILITY],
2873 {"Actual codec capability", "iax2.iax.capability",
2874 FT_UINT32, BASE_HEX, NULL, 0x0,
2875 NULL, HFILL}},
2877 {&hf_iax2_ies[IAX_IE_FORMAT],
2878 {"Desired codec format", "iax2.iax.format",
2879 FT_UINT64, BASE_HEX | BASE_EXT_STRING | BASE_VAL64_STRING, &codec_types_ext, 0x0,
2880 NULL, HFILL}},
2882 {&hf_iax2_ies[IAX_IE_LANGUAGE],
2883 {"Desired language", "iax2.iax.language",
2884 FT_STRING, BASE_NONE, NULL, 0x0,
2885 NULL, HFILL}},
2887 {&hf_iax2_ies[IAX_IE_VERSION],
2888 {"Protocol version", "iax2.iax.version",
2889 FT_UINT16, BASE_HEX, NULL, 0x0,
2890 NULL, HFILL}},
2892 {&hf_iax2_ies[IAX_IE_ADSICPE],
2893 {"CPE ADSI capability", "iax2.iax.cpe_adsi",
2894 FT_UINT16, BASE_HEX, NULL, 0x0,
2895 NULL, HFILL}},
2897 {&hf_iax2_ies[IAX_IE_DNID],
2898 {"Originally dialed DNID", "iax2.iax.dnid",
2899 FT_STRING, BASE_NONE, NULL, 0x0,
2900 NULL, HFILL}},
2902 {&hf_iax2_ies[IAX_IE_AUTHMETHODS],
2903 {"Authentication method(s)", "iax2.iax.auth.methods",
2904 FT_UINT16, BASE_HEX, NULL, 0x0,
2905 NULL, HFILL}},
2907 {&hf_iax2_ies[IAX_IE_CHALLENGE],
2908 {"Challenge data for MD5/RSA", "iax2.iax.auth.challenge",
2909 FT_STRING, BASE_NONE, NULL, 0x0,
2910 NULL, HFILL}},
2912 {&hf_iax2_ies[IAX_IE_MD5_RESULT],
2913 {"MD5 challenge result", "iax2.iax.auth.md5",
2914 FT_STRING, BASE_NONE, NULL, 0x0,
2915 NULL, HFILL}},
2917 {&hf_iax2_ies[IAX_IE_RSA_RESULT],
2918 {"RSA challenge result", "iax2.iax.auth.rsa",
2919 FT_STRING, BASE_NONE, NULL, 0x0,
2920 NULL, HFILL}},
2922 {&hf_iax2_ies[IAX_IE_REFRESH],
2923 {"When to refresh registration", "iax2.iax.refresh",
2924 FT_INT16, BASE_DEC, NULL, 0x0,
2925 NULL, HFILL}},
2927 {&hf_iax2_ies[IAX_IE_DPSTATUS],
2928 {"Dialplan status", "iax2.iax.dialplan_status",
2929 FT_UINT16, BASE_HEX, NULL, 0x0,
2930 NULL, HFILL}},
2932 {&hf_iax2_ies[IAX_IE_CALLNO],
2933 {"Call number of peer", "iax2.iax.call_no",
2934 FT_UINT16, BASE_DEC, NULL, 0x0,
2935 NULL, HFILL}},
2937 {&hf_iax2_ies[IAX_IE_CAUSE],
2938 {"Cause", "iax2.iax.cause",
2939 FT_STRING, BASE_NONE, NULL, 0x0,
2940 NULL, HFILL}},
2942 {&hf_iax2_ies[IAX_IE_IAX_UNKNOWN],
2943 {"Unknown IAX command", "iax2.iax.iax_unknown",
2944 FT_BYTES, BASE_NONE, NULL, 0x0,
2945 NULL, HFILL}},
2947 {&hf_iax2_ies[IAX_IE_MSGCOUNT],
2948 {"How many messages waiting", "iax2.iax.msg_count",
2949 FT_INT16, BASE_DEC, NULL, 0x0,
2950 NULL, HFILL}},
2952 {&hf_iax2_ies[IAX_IE_AUTOANSWER],
2953 {"Request auto-answering", "iax2.iax.autoanswer",
2954 FT_NONE, BASE_NONE, NULL, 0x0,
2955 NULL, HFILL}},
2957 {&hf_iax2_ies[IAX_IE_MUSICONHOLD],
2958 {"Request musiconhold with QUELCH", "iax2.iax.moh",
2959 FT_NONE, BASE_NONE, NULL, 0x0,
2960 NULL, HFILL}},
2962 {&hf_iax2_ies[IAX_IE_TRANSFERID],
2963 {"Transfer Request Identifier", "iax2.iax.transferid",
2964 FT_UINT32, BASE_HEX, NULL, 0x0,
2965 NULL, HFILL}},
2967 {&hf_iax2_ies[IAX_IE_RDNIS],
2968 {"Referring DNIS", "iax2.iax.rdnis",
2969 FT_STRING, BASE_NONE, NULL, 0x0,
2970 NULL, HFILL}},
2972 {&hf_iax2_ies[IAX_IE_PROVISIONING],
2973 {"Provisioning info", "iax2.iax.provisioning",
2974 FT_STRING, BASE_NONE, NULL, 0x0,
2975 NULL, HFILL}},
2977 {&hf_iax2_ies[IAX_IE_AESPROVISIONING],
2978 {"AES Provisioning info", "iax2.iax.aesprovisioning",
2979 FT_STRING, BASE_NONE, NULL, 0x0,
2980 NULL, HFILL}},
2982 {&hf_iax2_ies[IAX_IE_DATETIME],
2983 {"Date/Time", "iax2.iax.datetime.raw",
2984 FT_UINT32, BASE_DEC, NULL, 0x0,
2985 NULL, HFILL}},
2987 {&hf_iax2_ie_datetime,
2988 {"Date/Time", "iax2.iax.datetime",
2989 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2990 NULL, HFILL }},
2992 {&hf_iax2_ies[IAX_IE_DEVICETYPE],
2993 {"Device type", "iax2.iax.devicetype",
2994 FT_STRING, BASE_NONE, NULL, 0x0,
2995 NULL, HFILL}},
2997 {&hf_iax2_ies[IAX_IE_SERVICEIDENT],
2998 {"Service identifier", "iax2.iax.serviceident",
2999 FT_STRING, BASE_NONE, NULL, 0x0,
3000 NULL, HFILL}},
3002 {&hf_iax2_ies[IAX_IE_FIRMWAREVER],
3003 {"Firmware version", "iax2.iax.firmwarever",
3004 FT_UINT16, BASE_HEX, NULL, 0x0,
3005 NULL, HFILL}},
3007 {&hf_iax2_ies[IAX_IE_FWBLOCKDESC],
3008 {"Firmware block description", "iax2.iax.fwblockdesc",
3009 FT_UINT32, BASE_HEX, NULL, 0x0,
3010 NULL, HFILL}},
3012 {&hf_iax2_ies[IAX_IE_FWBLOCKDATA],
3013 {"Firmware block of data", "iax2.iax.fwblockdata",
3014 FT_STRING, BASE_NONE, NULL, 0x0,
3015 NULL, HFILL}},
3017 {&hf_iax2_ies[IAX_IE_PROVVER],
3018 {"Provisioning version", "iax2.iax.provver",
3019 FT_UINT32, BASE_HEX, NULL, 0x0,
3020 NULL, HFILL}},
3022 {&hf_iax2_ies[IAX_IE_CALLINGPRES],
3023 {"Calling presentation", "iax2.iax.callingpres",
3024 FT_UINT8, BASE_HEX, NULL, 0x0,
3025 NULL, HFILL}},
3027 {&hf_iax2_ies[IAX_IE_CALLINGTON],
3028 {"Calling type of number", "iax2.iax.callington",
3029 FT_UINT8, BASE_HEX, NULL, 0x0,
3030 NULL, HFILL}},
3032 {&hf_iax2_ies[IAX_IE_CALLINGTNS],
3033 {"Calling transit network select", "iax2.iax.callingtns",
3034 FT_UINT16, BASE_HEX, NULL, 0x0,
3035 NULL, HFILL}},
3037 {&hf_iax2_ies[IAX_IE_SAMPLINGRATE],
3038 {"Supported sampling rates", "iax2.iax.samplingrate",
3039 FT_UINT16, BASE_HEX, NULL, 0x0,
3040 NULL, HFILL}},
3042 {&hf_iax2_ies[IAX_IE_CAUSECODE],
3043 {"Hangup cause", "iax2.iax.causecode",
3044 FT_UINT8, BASE_HEX | BASE_EXT_STRING, &iax_causecodes_ext, 0x0,
3045 NULL, HFILL}},
3047 {&hf_iax2_ies[IAX_IE_ENCRYPTION],
3048 {"Encryption format", "iax2.iax.encryption",
3049 FT_UINT16, BASE_HEX, NULL, 0x0,
3050 NULL, HFILL}},
3052 {&hf_iax2_ies[IAX_IE_ENCKEY],
3053 {"Encryption key", "iax2.iax.enckey",
3054 FT_STRING, BASE_NONE, NULL, 0x0,
3055 NULL, HFILL}},
3057 {&hf_iax2_ies[IAX_IE_CODEC_PREFS],
3058 {"Codec negotiation", "iax2.iax.codecprefs",
3059 FT_STRING, BASE_NONE, NULL, 0x0,
3060 NULL, HFILL}},
3062 {&hf_iax2_ies[IAX_IE_RR_JITTER],
3063 {"Received jitter (as in RFC1889)", "iax2.iax.rrjitter",
3064 FT_UINT32, BASE_HEX, NULL, 0x0,
3065 NULL, HFILL}},
3067 {&hf_iax2_ies[IAX_IE_RR_LOSS],
3068 {"Received loss (high byte loss pct, low 24 bits loss count, as in rfc1889)", "iax2.iax.rrloss",
3069 FT_UINT32, BASE_HEX, NULL, 0x0,
3070 NULL, HFILL}},
3072 {&hf_iax2_ies[IAX_IE_RR_PKTS],
3073 {"Total frames received", "iax2.iax.rrpkts",
3074 FT_UINT32, BASE_HEX, NULL, 0x0,
3075 NULL, HFILL}},
3077 {&hf_iax2_ies[IAX_IE_RR_DELAY],
3078 {"Max playout delay in ms for received frames", "iax2.iax.rrdelay",
3079 FT_UINT16, BASE_HEX, NULL, 0x0,
3080 NULL, HFILL}},
3082 {&hf_iax2_ies[IAX_IE_RR_DROPPED],
3083 {"Dropped frames (presumably by jitterbuffer)", "iax2.iax.rrdropped",
3084 FT_UINT32, BASE_HEX, NULL, 0x0,
3085 NULL, HFILL}},
3087 {&hf_iax2_ies[IAX_IE_RR_OOO],
3088 {"Frame received out of order", "iax2.iax.rrooo",
3089 FT_UINT32, BASE_HEX, NULL, 0x0,
3090 NULL, HFILL}},
3092 {&hf_iax2_ies[IAX_IE_CAPABILITY2],
3093 {"64-bit codec capability", "iax2.iax.capability2",
3094 FT_UINT64, BASE_HEX, NULL, 0x0,
3095 NULL, HFILL}},
3097 {&hf_iax2_ies[IAX_IE_FORMAT2],
3098 {"64-bit codec format", "iax2.iax.format2",
3099 FT_UINT64, BASE_HEX | BASE_EXT_STRING | BASE_VAL64_STRING, &codec_types_ext, 0x0,
3100 NULL, HFILL}},
3102 {&hf_iax2_ies[IAX_IE_DATAFORMAT],
3103 {"Data call format", "iax2.iax.dataformat",
3104 FT_UINT32, BASE_HEX, VALS(iax_dataformats), 0x0,
3105 NULL, HFILL}},
3107 {&hf_IAX_IE_UNKNOWN_BYTE,
3108 {"Unknown", "iax2.iax.unknownbyte",
3109 FT_UINT8, BASE_HEX, NULL, 0x0,
3110 "Raw data for unknown IEs", HFILL}},
3112 {&hf_IAX_IE_UNKNOWN_I16,
3113 {"Unknown", "iax2.iax.unknownshort",
3114 FT_UINT16, BASE_HEX, NULL, 0x0,
3115 "Raw data for unknown IEs", HFILL}},
3117 {&hf_IAX_IE_UNKNOWN_I32,
3118 {"Unknown", "iax2.iax.unknownlong",
3119 FT_UINT32, BASE_HEX, NULL, 0x0,
3120 "Raw data for unknown IEs", HFILL}},
3122 {&hf_IAX_IE_UNKNOWN_BYTES,
3123 {"Unknown", "iax2.iax.unknownstring",
3124 FT_STRING, BASE_NONE, NULL, 0x0,
3125 "Raw data for unknown IEs", HFILL}},
3127 {&hf_iax2_ie_id,
3128 {"IE id", "iax2.ie_id",
3129 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &iax_ies_type_ext, 0x0,
3130 NULL, HFILL}},
3132 {&hf_iax2_length,
3133 {"Length", "iax2.length",
3134 FT_UINT8, BASE_DEC, NULL, 0x0,
3135 NULL, HFILL}},
3137 {&hf_iax2_version,
3138 {"Version", "iax2.version",
3139 FT_UINT8, BASE_DEC, NULL, 0x0,
3140 NULL, HFILL}},
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), CODEC_MASK(AST_FORMAT_G723_1),
3146 NULL, HFILL }},
3148 {&hf_iax2_cap_gsm,
3149 {"GSM compression", "iax2.cap.gsm",
3150 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_GSM),
3151 NULL, HFILL }},
3153 {&hf_iax2_cap_ulaw,
3154 {"Raw mu-law data (G.711)", "iax2.cap.ulaw",
3155 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_ULAW),
3156 NULL, HFILL }},
3158 {&hf_iax2_cap_alaw,
3159 {"Raw A-law data (G.711)", "iax2.cap.alaw",
3160 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_ALAW),
3161 NULL, HFILL } },
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), CODEC_MASK(AST_FORMAT_G726_AAL2),
3166 NULL, HFILL }},
3168 {&hf_iax2_cap_adpcm,
3169 {"ADPCM", "iax2.cap.adpcm",
3170 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_ADPCM),
3171 NULL, HFILL }},
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), CODEC_MASK(AST_FORMAT_SLINEAR),
3176 NULL, HFILL }},
3178 {&hf_iax2_cap_lpc10,
3179 {"LPC10, 180 samples/frame", "iax2.cap.lpc10",
3180 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_LPC10),
3181 NULL, HFILL }},
3183 {&hf_iax2_cap_g729a,
3184 {"G.729a Audio", "iax2.cap.g729a",
3185 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_G729A),
3186 NULL, HFILL }},
3188 {&hf_iax2_cap_speex,
3189 {"SpeeX Free Compression", "iax2.cap.speex",
3190 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_SPEEX),
3191 NULL, HFILL }},
3193 {&hf_iax2_cap_ilbc,
3194 {"iLBC Free Compression", "iax2.cap.ilbc",
3195 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_ILBC),
3196 NULL, HFILL }},
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), CODEC_MASK(AST_FORMAT_G726),
3201 NULL, HFILL }},
3203 {&hf_iax2_cap_g722,
3204 {"G.722", "iax2.cap.g722",
3205 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_G722),
3206 NULL, HFILL }},
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), CODEC_MASK(AST_FORMAT_SIREN7),
3211 NULL, HFILL }},
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), CODEC_MASK(AST_FORMAT_SIREN14),
3216 NULL, HFILL }},
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), CODEC_MASK(AST_FORMAT_SLINEAR16),
3221 NULL, HFILL }},
3223 {&hf_iax2_cap_jpeg,
3224 {"JPEG images", "iax2.cap.jpeg",
3225 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_JPEG),
3226 NULL, HFILL }},
3228 {&hf_iax2_cap_png,
3229 {"PNG images", "iax2.cap.png",
3230 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_PNG),
3231 NULL, HFILL }},
3233 {&hf_iax2_cap_h261,
3234 {"H.261 video", "iax2.cap.h261",
3235 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_H261),
3236 NULL, HFILL }},
3238 {&hf_iax2_cap_h263,
3239 {"H.263 video", "iax2.cap.h263",
3240 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_H263),
3241 NULL, HFILL }},
3243 {&hf_iax2_cap_h263_plus,
3244 {"H.263+ video", "iax2.cap.h263_plus",
3245 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_H263_PLUS),
3246 NULL, HFILL }},
3248 {&hf_iax2_cap_h264,
3249 {"H.264 video", "iax2.cap.h264",
3250 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_H264),
3251 NULL, HFILL }},
3253 {&hf_iax2_cap_mpeg4,
3254 {"MPEG4 video", "iax2.cap.mpeg4",
3255 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_MP4_VIDEO),
3256 NULL, HFILL }},
3258 {&hf_iax2_cap_vp8,
3259 {"VP8 video", "iax2.cap.vp8",
3260 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_VP8),
3261 NULL, HFILL }},
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), CODEC_MASK(AST_FORMAT_T140_RED),
3266 NULL, HFILL }},
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), CODEC_MASK(AST_FORMAT_T140),
3271 NULL, HFILL }},
3273 {&hf_iax2_cap_g719,
3274 {"G.719 (64 kbps assumed)", "iax2.cap.g719",
3275 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_G719),
3276 NULL, HFILL }},
3278 {&hf_iax2_cap_speex16,
3279 {"SpeeX Wideband (16kHz) Free Compression", "iax2.cap.speex16",
3280 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_SPEEX16),
3281 NULL, HFILL }},
3283 {&hf_iax2_cap_opus,
3284 {"Opus audio (8kHz, 16kHz, 24kHz, 48Khz)", "iax2.cap.opus",
3285 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_OPUS),
3286 NULL, HFILL }},
3288 {&hf_iax2_cap_testlaw,
3289 {"Raw testing-law data (G.711)", "iax2.cap.testlaw",
3290 FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_TESTLAW),
3291 NULL, HFILL }},
3293 {&hf_iax2_fragment_unfinished,
3294 {"IAX2 fragment, unfinished", "iax2.fragment_unfinished",
3295 FT_BYTES, BASE_NONE, NULL, 0x0,
3296 NULL, HFILL }},
3298 {&hf_iax2_payload_data,
3299 {"IAX2 payload", "iax2.payload_data",
3300 FT_BYTES, BASE_NONE, NULL, 0x0,
3301 NULL, HFILL }},
3303 /* reassembly stuff */
3304 {&hf_iax2_fragments,
3305 {"IAX2 Fragments", "iax2.fragments",
3306 FT_NONE, BASE_NONE, NULL, 0x0,
3307 NULL, HFILL }},
3309 {&hf_iax2_fragment,
3310 {"IAX2 Fragment data", "iax2.fragment",
3311 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3312 NULL, HFILL }},
3314 {&hf_iax2_fragment_overlap,
3315 {"Fragment overlap", "iax2.fragment.overlap",
3316 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3317 "Fragment overlaps with other fragments", HFILL }},
3319 {&hf_iax2_fragment_overlap_conflict,
3320 {"Conflicting data in fragment overlap", "iax2.fragment.overlap.conflict",
3321 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3322 "Overlapping fragments contained conflicting data", HFILL }},
3324 {&hf_iax2_fragment_multiple_tails,
3325 {"Multiple tail fragments found", "iax2.fragment.multipletails",
3326 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3327 "Several tails were found when defragmenting the packet", HFILL }},
3329 {&hf_iax2_fragment_too_long_fragment,
3330 {"Fragment too long", "iax2.fragment.toolongfragment",
3331 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3332 "Fragment contained data past end of packet", HFILL }},
3334 {&hf_iax2_fragment_error,
3335 {"Defragmentation error", "iax2.fragment.error",
3336 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3337 "Defragmentation error due to illegal fragments", HFILL }},
3339 {&hf_iax2_fragment_count,
3340 {"Fragment count", "iax2.fragment.count",
3341 FT_UINT32, BASE_DEC, NULL, 0x0,
3342 NULL, HFILL }},
3344 {&hf_iax2_reassembled_in,
3345 {"IAX2 fragment, reassembled in frame", "iax2.reassembled_in",
3346 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3347 "This IAX2 packet is reassembled in this frame", HFILL }},
3349 {&hf_iax2_reassembled_length,
3350 {"Reassembled IAX2 length", "iax2.reassembled.length",
3351 FT_UINT32, BASE_DEC, NULL, 0x0,
3352 "The total length of the reassembled payload", HFILL }}
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
3368 static ei_register_info ei[] = {
3369 { &ei_iax_too_many_transfers, { "iax2.too_many_transfers", PI_PROTOCOL, PI_WARN, "Too many transfers for iax_call", EXPFILL }},
3370 { &ei_iax_circuit_id_conflict, { "iax2.circuit_id_conflict", PI_PROTOCOL, PI_WARN, "Circuit ID conflict", EXPFILL }},
3371 { &ei_iax_peer_address_unsupported, { "iax2.peer_address_unsupported", PI_PROTOCOL, PI_WARN, "Peer address unsupported", EXPFILL }},
3372 { &ei_iax_invalid_len, { "iax2.invalid_len", PI_PROTOCOL, PI_WARN, "Invalid length", EXPFILL }},
3375 expert_module_t* expert_iax;
3377 proto_iax2 = proto_register_protocol("Inter-Asterisk eXchange v2", "IAX2", "iax2");
3378 proto_register_field_array(proto_iax2, hf, array_length(hf));
3379 proto_register_subtree_array(ett, array_length(ett));
3380 expert_iax = expert_register_protocol(proto_iax2);
3381 expert_register_field_array(expert_iax, ei, array_length(ei));
3383 iax2_handle = register_dissector("iax2", dissect_iax2, proto_iax2);
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);
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);
3397 iax2_tap = register_tap("IAX2");
3400 void
3401 proto_reg_handoff_iax2(void)
3403 dissector_handle_t v110_handle;
3405 dissector_add_uint_with_preference("udp.port", IAX2_PORT, iax2_handle);
3406 v110_handle = find_dissector("v110");
3407 if (v110_handle)
3408 dissector_add_uint("iax2.dataformat", AST_DATAFORMAT_V110, v110_handle);
3412 * Editor modelines
3414 * Local Variables:
3415 * c-basic-offset: 2
3416 * tab-width: 8
3417 * indent-tabs-mode: nil
3418 * End:
3420 * ex: set shiftwidth=2 tabstop=8 expandtab:
3421 * :indentSize=2:tabSize=8:noTabs=true: