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
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37 #include <epan/circuit.h>
38 #include <epan/packet.h>
39 #include <epan/exceptions.h>
40 #include <epan/to_str.h>
41 #include <epan/wmem/wmem.h>
42 #include <epan/reassemble.h>
43 #include <epan/expert.h>
44 #include <epan/aftypes.h>
46 #include <epan/tap-voip.h>
48 #include "packet-iax2.h"
49 #include <epan/iax2_codec_type.h>
51 void proto_register_iax2(void);
52 void proto_reg_handoff_iax2(void);
54 #define IAX2_PORT 4569
55 #define PROTO_TAG_IAX2 "IAX2"
57 /* enough to hold any address in an address_t */
58 #define MAX_ADDRESS 16
60 /* the maximum number of transfers (of each end) we can deal with per call,
62 #define IAX_MAX_TRANSFERS 2
64 /* #define DEBUG_HASHING */
65 /* #define DEBUG_DESEGMENT */
67 /* Wireshark ID of the IAX2 protocol */
68 static int proto_iax2 = -1;
71 static int iax2_tap = -1;
73 /* protocol tap info */
74 static iax2_info_t ii_arr[1];
75 static iax2_info_t *iax2_info = ii_arr;
77 /* The following hf_* variables are used to hold the wireshark IDs of
78 * our header fields; they are filled out when we call
79 * proto_register_field_array() in proto_register_iax2()
81 static int hf_iax2_packet_type = -1;
82 static int hf_iax2_retransmission = -1;
83 static int hf_iax2_callno = -1;
84 static int hf_iax2_scallno = -1;
85 static int hf_iax2_dcallno = -1;
86 static int hf_iax2_ts = -1;
87 static int hf_iax2_minits = -1;
88 static int hf_iax2_minividts = -1;
89 static int hf_iax2_absts = -1;
90 static int hf_iax2_lateness = -1;
91 static int hf_iax2_minividmarker = -1;
92 static int hf_iax2_oseqno = -1;
93 static int hf_iax2_iseqno = -1;
94 static int hf_iax2_type = -1;
95 static int hf_iax2_csub = -1;
96 static int hf_iax2_dtmf_csub = -1;
97 static int hf_iax2_cmd_csub = -1;
98 static int hf_iax2_iax_csub = -1;
99 static int hf_iax2_voice_csub = -1;
100 static int hf_iax2_voice_codec = -1;
101 static int hf_iax2_video_csub = -1;
102 static int hf_iax2_video_codec = -1;
103 static int hf_iax2_marker = -1;
104 static int hf_iax2_modem_csub = -1;
105 static int hf_iax2_text_csub = -1;
106 static int hf_iax2_text_text = -1;
107 static int hf_iax2_html_csub = -1;
108 static int hf_iax2_html_url = -1;
109 static int hf_iax2_trunk_metacmd = -1;
110 static int hf_iax2_trunk_cmddata = -1;
111 static int hf_iax2_trunk_cmddata_ts = -1;
112 static int hf_iax2_trunk_ts = -1;
113 static int hf_iax2_trunk_ncalls = -1;
114 static int hf_iax2_trunk_call_len = -1;
115 static int hf_iax2_trunk_call_scallno = -1;
116 static int hf_iax2_trunk_call_ts = -1;
117 static int hf_iax2_trunk_call_data = -1;
119 static int hf_iax2_cap_g723_1 = -1;
120 static int hf_iax2_cap_gsm = -1;
121 static int hf_iax2_cap_ulaw = -1;
122 static int hf_iax2_cap_alaw = -1;
123 static int hf_iax2_cap_g726_aal2 = -1;
124 static int hf_iax2_cap_adpcm = -1;
125 static int hf_iax2_cap_slinear = -1;
126 static int hf_iax2_cap_lpc10 = -1;
127 static int hf_iax2_cap_g729a = -1;
128 static int hf_iax2_cap_speex = -1;
129 static int hf_iax2_cap_ilbc = -1;
130 static int hf_iax2_cap_g726 = -1;
131 static int hf_iax2_cap_g722 = -1;
132 static int hf_iax2_cap_siren7 = -1;
133 static int hf_iax2_cap_siren14 = -1;
134 static int hf_iax2_cap_slinear16 = -1;
135 static int hf_iax2_cap_jpeg = -1;
136 static int hf_iax2_cap_png = -1;
137 static int hf_iax2_cap_h261 = -1;
138 static int hf_iax2_cap_h263 = -1;
139 static int hf_iax2_cap_h263_plus = -1;
140 static int hf_iax2_cap_h264 = -1;
141 static int hf_iax2_cap_mpeg4 = -1;
143 static int hf_iax2_fragments = -1;
144 static int hf_iax2_fragment = -1;
145 static int hf_iax2_fragment_overlap = -1;
146 static int hf_iax2_fragment_overlap_conflict = -1;
147 static int hf_iax2_fragment_multiple_tails = -1;
148 static int hf_iax2_fragment_too_long_fragment = -1;
149 static int hf_iax2_fragment_error = -1;
150 static int hf_iax2_fragment_count = -1;
151 static int hf_iax2_reassembled_in = -1;
152 static int hf_iax2_reassembled_length = -1;
155 /* hf_iax2_ies is an array of header fields, one per potential Information
156 * Element. It's done this way (rather than having separate variables for each
157 * IE) to make the dissection of information elements clearer and more
160 * To add the ability to dissect a new information element, just add an
161 * appropriate entry to hf[] in proto_register_iax2(); dissect_ies() will then
162 * pick it up automatically.
164 #define NUM_HF_IAX2_IES 256
165 static int hf_iax2_ies[NUM_HF_IAX2_IES];
166 static int hf_iax2_ie_datetime = -1;
167 static int hf_IAX_IE_APPARENTADDR_SINFAMILY = -1;
168 static int hf_IAX_IE_APPARENTADDR_SINPORT = -1;
169 static int hf_IAX_IE_APPARENTADDR_SINADDR = -1;
170 static int hf_IAX_IE_UNKNOWN_BYTE = -1;
171 static int hf_IAX_IE_UNKNOWN_I16 = -1;
172 static int hf_IAX_IE_UNKNOWN_I32 = -1;
173 static int hf_IAX_IE_UNKNOWN_BYTES = -1;
175 /* These are the ids of the subtrees that we may be creating */
176 static gint ett_iax2 = -1;
177 static gint ett_iax2_full_mini_subtree = -1;
178 static gint ett_iax2_type = -1; /* Frame-type specific subtree */
179 static gint ett_iax2_ie = -1; /* single IE */
180 static gint ett_iax2_codecs = -1; /* capabilities IE */
181 static gint ett_iax2_ies_apparent_addr = -1; /* apparent address IE */
182 static gint ett_iax2_fragment = -1;
183 static gint ett_iax2_fragments = -1;
184 static gint ett_iax2_trunk_cmddata = -1;
185 static gint ett_iax2_trunk_call = -1;
187 static expert_field ei_iax_too_many_transfers = EI_INIT;
188 static expert_field ei_iax_circuit_id_conflict = EI_INIT;
189 static expert_field ei_iax_peer_address_unsupported = EI_INIT;
191 static const fragment_items iax2_fragment_items = {
196 &hf_iax2_fragment_overlap,
197 &hf_iax2_fragment_overlap_conflict,
198 &hf_iax2_fragment_multiple_tails,
199 &hf_iax2_fragment_too_long_fragment,
200 &hf_iax2_fragment_error,
201 &hf_iax2_fragment_count,
202 &hf_iax2_reassembled_in,
203 &hf_iax2_reassembled_length,
204 /* Reassembled data field */
209 static dissector_handle_t data_handle;
211 /* data-call subdissectors, AST_DATAFORMAT_* */
212 static dissector_table_t iax2_dataformat_dissector_table;
213 /* voice/video call subdissectors, AST_FORMAT_* */
214 static dissector_table_t iax2_codec_dissector_table;
217 /* IAX2 Meta trunk packet Command data flags */
218 #define IAX2_TRUNK_TS 1
220 /* IAX2 Full-frame types */
221 static const value_string iax_frame_types[] = {
223 {AST_FRAME_DTMF_END, "DTMF End"},
224 {AST_FRAME_VOICE, "Voice"},
225 {AST_FRAME_VIDEO, "Video"},
226 {AST_FRAME_CONTROL, "Control"},
227 {AST_FRAME_NULL, "NULL"},
228 {AST_FRAME_IAX, "IAX"},
229 {AST_FRAME_TEXT, "Text"},
230 {AST_FRAME_IMAGE, "Image"},
231 {AST_FRAME_HTML, "HTML"},
232 {AST_FRAME_CNG, "Comfort Noise"},
233 {AST_FRAME_MODEM, "Modem"},
234 {AST_FRAME_DTMF_BEGIN, "DTMF Begin"},
237 static value_string_ext iax_frame_types_ext = VALUE_STRING_EXT_INIT(iax_frame_types);
239 /* Subclasses for IAX packets */
240 static const value_string iax_iax_subclasses[] = {
284 static value_string_ext iax_iax_subclasses_ext = VALUE_STRING_EXT_INIT(iax_iax_subclasses);
286 /* Subclasses for Control packets */
287 static const value_string iax_cmd_subclasses[] = {
296 {0xFF, "stop sounds"}, /* sent by app_dial, and not much else */
299 static value_string_ext iax_cmd_subclasses_ext = VALUE_STRING_EXT_INIT(iax_cmd_subclasses);
301 /* IAX2 to tap-voip call state mapping for command frames */
302 static const voip_call_state tap_cmd_voip_state[] = {
304 VOIP_COMPLETED, /*HANGUP*/
305 VOIP_RINGING, /*RING*/
306 VOIP_RINGING, /*RINGING*/
307 VOIP_IN_CALL, /*ANSWER*/
308 VOIP_REJECTED, /*BUSY*/
309 VOIP_UNKNOWN, /*TKOFFHK*/
310 VOIP_UNKNOWN /*OFFHOOK*/
312 #define NUM_TAP_CMD_VOIP_STATES array_length(tap_cmd_voip_state)
314 /* IAX2 to tap-voip call state mapping for IAX frames */
315 static const voip_call_state tap_iax_voip_state[] = {
317 VOIP_CALL_SETUP, /*NEW*/
320 VOIP_COMPLETED, /*HANGUP*/
321 VOIP_REJECTED, /*REJECT*/
322 VOIP_RINGING, /*ACCEPT*/
337 VOIP_CALL_SETUP, /*DIAL*/
356 #define NUM_TAP_IAX_VOIP_STATES array_length(tap_iax_voip_state)
358 /* Subclasses for Modem packets */
359 static const value_string iax_modem_subclasses[] = {
366 /* Subclasses for Text packets */
367 static const value_string iax_text_subclasses[] = {
372 /* Subclasses for HTML packets */
373 static const value_string iax_html_subclasses[] = {
374 {0x01, "Sending a URL"},
375 {0x02, "Data frame"},
376 {0x04, "Beginning frame"},
378 {0x10, "Load is complete"},
379 {0x11, "Peer does not support HTML"},
381 {0x13, "Unlink URL"},
382 {0x14, "Reject Link URL"},
387 /* Information elements */
388 static const value_string iax_ies_type[] = {
389 {IAX_IE_CALLED_NUMBER, "Number/extension being called"},
390 {IAX_IE_CALLING_NUMBER, "Calling number"},
391 {IAX_IE_CALLING_ANI, "Calling number ANI for billing"},
392 {IAX_IE_CALLING_NAME, "Name of caller"},
393 {IAX_IE_CALLED_CONTEXT, "Context for number"},
394 {IAX_IE_USERNAME, "Username (peer or user) for authentication"},
395 {IAX_IE_PASSWORD, "Password for authentication"},
396 {IAX_IE_CAPABILITY, "Actual codec capability"},
397 {IAX_IE_FORMAT, "Desired codec format"},
398 {IAX_IE_LANGUAGE, "Desired language"},
399 {IAX_IE_VERSION, "Protocol version"},
400 {IAX_IE_ADSICPE, "CPE ADSI capability"},
401 {IAX_IE_DNID, "Originally dialed DNID"},
402 {IAX_IE_AUTHMETHODS, "Authentication method(s)"},
403 {IAX_IE_CHALLENGE, "Challenge data for MD5/RSA"},
404 {IAX_IE_MD5_RESULT, "MD5 challenge result"},
405 {IAX_IE_RSA_RESULT, "RSA challenge result"},
406 {IAX_IE_APPARENT_ADDR, "Apparent address of peer"},
407 {IAX_IE_REFRESH, "When to refresh registration"},
408 {IAX_IE_DPSTATUS, "Dialplan status"},
409 {IAX_IE_CALLNO, "Call number of peer"},
410 {IAX_IE_CAUSE, "Cause"},
411 {IAX_IE_IAX_UNKNOWN, "Unknown IAX command"},
412 {IAX_IE_MSGCOUNT, "How many messages waiting"},
413 {IAX_IE_AUTOANSWER, "Request auto-answering"},
414 {IAX_IE_MUSICONHOLD, "Request musiconhold with QUELCH"},
415 {IAX_IE_TRANSFERID, "Transfer Request Identifier"},
416 {IAX_IE_RDNIS, "Referring DNIS"},
417 {IAX_IE_PROVISIONING, "Provisioning info"},
418 {IAX_IE_AESPROVISIONING, "AES Provisioning info"},
419 {IAX_IE_DATETIME, "Date/Time"},
420 {IAX_IE_DEVICETYPE, "Device type"},
421 {IAX_IE_SERVICEIDENT, "Service Identifier"},
422 {IAX_IE_FIRMWAREVER, "Firmware revision"},
423 {IAX_IE_FWBLOCKDESC, "Firmware block description"},
424 {IAX_IE_FWBLOCKDATA, "Firmware block of data"},
425 {IAX_IE_PROVVER, "Provisioning version"},
426 {IAX_IE_CALLINGPRES, "Calling presentation"},
427 {IAX_IE_CALLINGTON, "Calling type of number"},
428 {IAX_IE_CALLINGTNS, "Calling transit network select"},
429 {IAX_IE_SAMPLINGRATE, "Supported sampling rates"},
430 {IAX_IE_CAUSECODE, "Hangup cause"},
431 {IAX_IE_ENCRYPTION, "Encryption format"},
432 {IAX_IE_ENCKEY, "Raw encryption key"},
433 {IAX_IE_CODEC_PREFS, "Codec preferences"},
434 {IAX_IE_RR_JITTER, "Received jitter"},
435 {IAX_IE_RR_LOSS, "Received loss"},
436 {IAX_IE_RR_PKTS, "Received frames"},
437 {IAX_IE_RR_DELAY, "Max playout delay in ms for received frames"},
438 {IAX_IE_RR_DROPPED, "Dropped frames"},
439 {IAX_IE_RR_OOO, "Frames received out of order"},
440 {IAX_IE_VARIABLE, "IAX2 variable"},
441 {IAX_IE_OSPTOKEN, "OSP Token"},
442 {IAX_IE_CALLTOKEN, "Call Token"},
443 {IAX_IE_CAPABILITY2, "64-bit codec capability"},
444 {IAX_IE_FORMAT2, "64-bit codec format"},
445 {IAX_IE_DATAFORMAT, "Data call format"},
448 static value_string_ext iax_ies_type_ext = VALUE_STRING_EXT_INIT(iax_ies_type);
450 static const value_string codec_types[] = {
451 {AST_FORMAT_G723_1, "G.723.1 compression"},
452 {AST_FORMAT_GSM, "GSM compression"},
453 {AST_FORMAT_ULAW, "Raw mu-law data (G.711)"},
454 {AST_FORMAT_ALAW, "Raw A-law data (G.711)"},
455 {AST_FORMAT_G726_AAL2, "ADPCM (G.726, 32kbps)"},
456 {AST_FORMAT_ADPCM, "ADPCM (IMA)"},
457 {AST_FORMAT_SLINEAR, "Raw 16-bit Signed Linear (8000 Hz) PCM"},
458 {AST_FORMAT_LPC10, "LPC10, 180 samples/frame"},
459 {AST_FORMAT_G729A, "G.729a Audio"},
460 {AST_FORMAT_SPEEX, "SpeeX Free Compression"},
461 {AST_FORMAT_ILBC, "iLBC Free Compression"},
462 {AST_FORMAT_G726, "G.726 compression"},
463 {AST_FORMAT_G722, "G.722 wideband"},
464 {AST_FORMAT_SIREN7, "G.722.1 32k wideband (aka Siren7)"},
465 {AST_FORMAT_SIREN14, "G.722.1 Annex C 48k wideband (aka Siren14)"},
466 {AST_FORMAT_SLINEAR16, "Raw 16kHz signed linear audio"},
467 {AST_FORMAT_JPEG, "JPEG Images"},
468 {AST_FORMAT_PNG, "PNG Images"},
469 {AST_FORMAT_H261, "H.261 Video"},
470 {AST_FORMAT_H263, "H.263 Video"},
471 {AST_FORMAT_H263_PLUS, "H.263+ Video"},
472 {AST_FORMAT_H264, "H.264 Video"},
473 {AST_FORMAT_MP4_VIDEO, "MPEG4 Video"},
476 static value_string_ext codec_types_ext = VALUE_STRING_EXT_INIT(codec_types);
478 static const value_string iax_dataformats[] = {
479 {AST_DATAFORMAT_NULL, "N/A (analogue call?)"},
480 {AST_DATAFORMAT_V110, "ITU-T V.110 rate adaption"},
481 {AST_DATAFORMAT_H223_H245, "ITU-T H.223/H.245"},
486 static const value_string iax_packet_types[] = {
487 {IAX2_FULL_PACKET, "Full packet"},
488 {IAX2_MINI_VOICE_PACKET, "Mini voice packet"},
489 {IAX2_MINI_VIDEO_PACKET, "Mini video packet"},
490 {IAX2_TRUNK_PACKET, "Trunk packet"},
494 static const value_string iax_causecodes[] = {
495 {AST_CAUSE_UNALLOCATED, "Unallocated"},
496 {AST_CAUSE_NO_ROUTE_TRANSIT_NET, "No route transit net"},
497 {AST_CAUSE_NO_ROUTE_DESTINATION, "No route to destination"},
498 {AST_CAUSE_MISDIALLED_TRUNK_PREFIX, "Misdialled trunk prefix"},
499 {AST_CAUSE_CHANNEL_UNACCEPTABLE, "Channel unacceptable"},
500 {AST_CAUSE_CALL_AWARDED_DELIVERED, "Call awarded delivered"},
501 {AST_CAUSE_PRE_EMPTED, "Preempted"},
502 {AST_CAUSE_NUMBER_PORTED_NOT_HERE, "Number ported not here"},
503 {AST_CAUSE_NORMAL_CLEARING, "Normal clearing"},
504 {AST_CAUSE_USER_BUSY, "User busy"},
505 {AST_CAUSE_NO_USER_RESPONSE, "No user response"},
506 {AST_CAUSE_NO_ANSWER, "No answer"},
507 {AST_CAUSE_SUBSCRIBER_ABSENT, "Subscriber absent"},
508 {AST_CAUSE_CALL_REJECTED, "Call rejected"},
509 {AST_CAUSE_NUMBER_CHANGED, "Number changed"},
510 {AST_CAUSE_REDIRECTED_TO_NEW_DESTINATION, "Redirected to new destination"},
511 {AST_CAUSE_ANSWERED_ELSEWHERE, "Answered elsewhere"},
512 {AST_CAUSE_DESTINATION_OUT_OF_ORDER, "Destination out of order"},
513 {AST_CAUSE_INVALID_NUMBER_FORMAT, "Invalid number format"},
514 {AST_CAUSE_FACILITY_REJECTED, "Facility rejected"},
515 {AST_CAUSE_RESPONSE_TO_STATUS_ENQUIRY, "Response to status inquiry"},
516 {AST_CAUSE_NORMAL_UNSPECIFIED, "Normal unspecified"},
517 {AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, "Normal circuit congestion"},
518 {AST_CAUSE_NETWORK_OUT_OF_ORDER, "Network out of order"},
519 {AST_CAUSE_NORMAL_TEMPORARY_FAILURE, "Normal temporary failure"},
520 {AST_CAUSE_SWITCH_CONGESTION, "Switch congestion"},
521 {AST_CAUSE_ACCESS_INFO_DISCARDED, "Access info discarded"},
522 {AST_CAUSE_REQUESTED_CHAN_UNAVAIL, "Requested channel unavailable"},
523 {AST_CAUSE_FACILITY_NOT_SUBSCRIBED, "Facility not subscribed"},
524 {AST_CAUSE_OUTGOING_CALL_BARRED, "Outgoing call barred"},
525 {AST_CAUSE_INCOMING_CALL_BARRED, "Incoming call barred"},
526 {AST_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized"},
527 {AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available"},
528 {AST_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented"},
529 {AST_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented"},
530 {AST_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented"},
531 {AST_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference"},
532 {AST_CAUSE_INCOMPATIBLE_DESTINATION, "Incompatible destination"},
533 {AST_CAUSE_INVALID_MSG_UNSPECIFIED, "Invalid message unspecified"},
534 {AST_CAUSE_MANDATORY_IE_MISSING, "Mandatory IE missing"},
535 {AST_CAUSE_MESSAGE_TYPE_NONEXIST, "Message type nonexistent"},
536 {AST_CAUSE_WRONG_MESSAGE, "Wrong message"},
537 {AST_CAUSE_IE_NONEXIST, "IE nonexistent"},
538 {AST_CAUSE_INVALID_IE_CONTENTS, "Invalid IE contents"},
539 {AST_CAUSE_WRONG_CALL_STATE, "Wrong call state"},
540 {AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, "Recovery on timer expire"},
541 {AST_CAUSE_MANDATORY_IE_LENGTH_ERROR, "Mandatory IE length error"},
542 {AST_CAUSE_PROTOCOL_ERROR, "Protocol error"},
543 {AST_CAUSE_INTERWORKING, "Interworking"},
546 static value_string_ext iax_causecodes_ext = VALUE_STRING_EXT_INIT(iax_causecodes);
548 /* ************************************************************************* */
550 /* In order to track IAX calls, we have a hash table which maps
551 * {addr,port type,port,call} to a unique circuit id.
553 * Each call has two such circuits associated with it (a forward and a
554 * reverse circuit, where 'forward' is defined as the direction the NEW
555 * packet went in), and we maintain an iax_call_data structure for each
556 * call, attached to both circuits with circuit_add_proto_data.
558 * Because {addr,port type,port,call} quadruplets can be reused
559 * (Asterisk reuses call numbers), circuit ids aren't unique to
560 * individual calls and we treat NEW packets somewhat specially. When we
561 * get such a packet, we see if there are any calls with a matching
562 * circuit id, and make sure that its circuits are marked as ended
563 * before that packet.
565 * A second complication is that we only know one quadruplet at the time
566 * the NEW packet is processed: there is therefore cunningness in
567 * iax_lookup_circuit_details() to look for replies to NEW packets and
568 * create the reverse circuit.
572 /* start with a hash of {addr,port type,port,call}->{id} */
580 /* this is where addr->data points to. it's put in here for easy freeing */
581 guint8 address_data[MAX_ADDRESS];
585 static GHashTable *iax_fid_table = NULL;
586 static reassembly_table iax_reassembly_table;
588 static GHashTable *iax_circuit_hashtab = NULL;
589 static guint circuitcount = 0;
591 /* the number of keys and values to reserve space for in each memory chunk.
592 We assume we won't be tracking many calls at once so this is quite low.
594 #define IAX_INIT_PACKET_COUNT 10
597 static gchar *key_to_str( const iax_circuit_key *key )
600 static gchar *strp, str[3][80];
608 /* why doesn't ep_address_to_str take a const pointer?
609 cast the warnings into oblivion. */
611 /* XXX - is this a case for wmem_packet_scope()? */
612 g_snprintf(strp, 80, "{%s:%i,%i}",
613 ep_address_to_str((address *)&key->addr),
621 static gint iax_circuit_equal(gconstpointer v, gconstpointer w)
623 const iax_circuit_key *v1 = (const iax_circuit_key *)v;
624 const iax_circuit_key *v2 = (const iax_circuit_key *)w;
627 result = (ADDRESSES_EQUAL(&(v1->addr), &(v2->addr)) &&
628 v1->ptype == v2->ptype &&
629 v1->port == v2->port &&
630 v1->callno== v2->callno);
632 g_debug("+++ Comparing for equality: %s, %s: %u", key_to_str(v1), key_to_str(v2), result);
638 static guint iax_circuit_hash(gconstpointer v)
640 const iax_circuit_key *key = (const iax_circuit_key *)v;
644 ADD_ADDRESS_TO_HASH(hash_val, &key->addr);
645 hash_val += (guint)(key->ptype);
646 hash_val += (guint)(key->port);
647 hash_val += (guint)(key->callno);
650 g_debug("+++ Hashing key: %s, result %#x", key_to_str(key), hash_val);
653 return (guint)hash_val;
656 /* Find, or create, a circuit for the given
657 {address,porttype,port,call} quadruplet
659 static guint iax_circuit_lookup(const address *address_p,
665 guint32 *circuit_id_p;
667 key.addr = *address_p;
672 circuit_id_p = (guint32 *)g_hash_table_lookup(iax_circuit_hashtab, &key);
673 if (! circuit_id_p) {
674 iax_circuit_key *new_key;
676 new_key = wmem_new(wmem_file_scope(), iax_circuit_key);
677 new_key->addr.type = address_p->type;
678 new_key->addr.len = MIN(address_p->len, MAX_ADDRESS);
679 new_key->addr.data = new_key->address_data;
680 memcpy(new_key->address_data, address_p->data, new_key->addr.len);
681 new_key->ptype = ptype;
682 new_key->port = port;
683 new_key->callno = callno;
685 circuit_id_p = (guint32 *)wmem_new(wmem_file_scope(), iax_circuit_key);
686 *circuit_id_p = ++circuitcount;
688 g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p);
691 g_debug("Created new circuit id %u for node %s", *circuit_id_p, key_to_str(new_key));
695 return *circuit_id_p;
699 /* ************************************************************************* */
702 guint32 current_frag_id; /* invalid unless current_frag_bytes > 0 */
703 guint32 current_frag_bytes;
704 guint32 current_frag_minlen;
707 /* This is our per-call data structure, which is attached to both the
708 * forward and reverse circuits.
710 typedef struct iax_call_data {
711 /* For this data, src and dst are relative to the original direction under
712 which this call is stored. Obviously if the reversed flag is set true by
713 iax_find_call, src and dst are reversed relative to the direction the
714 actual source and destination of the data.
716 if the codec changes mid-call, we update it here; because we store a codec
717 number with each packet too, we handle going back to earlier packets
721 iax_dataformat_t dataformat;
722 guint32 src_codec, dst_codec;
723 guint32 src_vformat, dst_vformat;
725 /* when a transfer takes place, we'll get a new circuit id; we assume that we
726 don't try to transfer more than IAX_MAX_TRANSFERS times in a call */
727 guint forward_circuit_ids[IAX_MAX_TRANSFERS];
728 guint reverse_circuit_ids[IAX_MAX_TRANSFERS];
729 guint n_forward_circuit_ids;
730 guint n_reverse_circuit_ids;
732 /* this is the subdissector for the call */
733 dissector_handle_t subdissector;
735 /* the absolute start time of the call */
738 iax_call_dirdata dirdata[2];
741 static void iax_init_hash( void )
743 if (iax_circuit_hashtab)
744 g_hash_table_destroy(iax_circuit_hashtab);
745 iax_circuit_hashtab = g_hash_table_new(iax_circuit_hash, iax_circuit_equal);
749 g_hash_table_destroy(iax_fid_table);
750 iax_fid_table = g_hash_table_new(g_direct_hash, g_direct_equal);
752 reassembly_table_init(&iax_reassembly_table,
753 &addresses_reassembly_table_functions);
758 /* creates a new CT_IAX2 circuit with a specified circuit id for a call
760 * typically a call has up to three associated circuits: an original source, an
761 * original destination, and the result of a transfer.
763 * For each endpoint, a CT_IAX2 circuit is created and added to the call_data
766 * 'reversed' should be true if this end is the one which would have _received_
767 * the NEW packet, or it is an endpoint to which the 'destination' is being
771 static circuit_t *iax2_new_circuit_for_call(packet_info *pinfo, proto_item * item,
772 guint circuit_id, guint framenum,
773 iax_call_data *iax_call, gboolean reversed)
780 if ((reversed && iax_call->n_reverse_circuit_ids >= IAX_MAX_TRANSFERS) ||
781 (! reversed && iax_call->n_forward_circuit_ids >= IAX_MAX_TRANSFERS)) {
782 expert_add_info(pinfo, item, &ei_iax_too_many_transfers);
786 res = circuit_new(CT_IAX2,
790 circuit_add_proto_data(res, proto_iax2, iax_call);
793 iax_call -> reverse_circuit_ids[iax_call->n_reverse_circuit_ids++] = circuit_id;
795 iax_call -> forward_circuit_ids[iax_call->n_forward_circuit_ids++] = circuit_id;
801 /* returns true if this circuit id is a "forward" circuit for this call: ie, it
802 * is the point which _sent_ the original 'NEW' packet, or a point to which that
803 * end was subsequently transferred */
804 static gboolean is_forward_circuit(guint circuit_id,
805 const iax_call_data *iax_call)
808 for(i=0; i<iax_call->n_forward_circuit_ids; i++) {
809 if (circuit_id == iax_call->forward_circuit_ids[i])
815 /* returns true if this circuit id is a "reverse" circuit for this call: ie, it
816 * is the point which _received_ the original 'NEW' packet, or a point to which that
817 * end was subsequently transferred */
818 static gboolean is_reverse_circuit(guint circuit_id,
819 const iax_call_data *iax_call)
822 for(i=0; i<iax_call->n_reverse_circuit_ids; i++){
823 if (circuit_id == iax_call->reverse_circuit_ids[i])
830 static iax_call_data *iax_lookup_call_from_dest(packet_info *pinfo, proto_item * item,
831 guint src_circuit_id,
832 guint dst_circuit_id,
834 gboolean *reversed_p)
836 circuit_t *dst_circuit;
837 iax_call_data *iax_call;
838 gboolean reversed = FALSE;
840 dst_circuit = find_circuit(CT_IAX2,
846 g_debug("++ destination circuit not found, must have missed NEW packet");
854 g_debug("++ found destination circuit");
857 iax_call = (iax_call_data *)circuit_get_proto_data(dst_circuit, proto_iax2);
859 /* there's no way we can create a CT_IAX2 circuit without adding
860 iax call data to it; assert this */
861 DISSECTOR_ASSERT(iax_call);
863 if (is_forward_circuit(dst_circuit_id, iax_call)) {
865 g_debug("++ destination circuit matches forward_circuit_id of call, "
866 "therefore packet is reversed");
871 if (iax_call -> n_reverse_circuit_ids == 0) {
872 /* we are going in the reverse direction, and this call
873 doesn't have a reverse circuit associated with it.
876 g_debug("++ reverse_circuit_id of call is zero, need to create a "
877 "new reverse circuit for this call");
880 iax2_new_circuit_for_call(pinfo, item, src_circuit_id, framenum, iax_call, TRUE);
884 } else if (!is_reverse_circuit(src_circuit_id, iax_call)) {
885 expert_add_info_format(pinfo, item, &ei_iax_circuit_id_conflict,
886 "IAX Packet %u from circuit ids %u->%u conflicts with earlier call with circuit ids %u->%u",
888 src_circuit_id, dst_circuit_id,
889 iax_call->forward_circuit_ids[0],
890 iax_call->reverse_circuit_ids[0]);
893 } else if (is_reverse_circuit(dst_circuit_id, iax_call)) {
895 g_debug("++ destination circuit matches reverse_circuit_id of call, "
896 "therefore packet is forward");
900 if (!is_forward_circuit(src_circuit_id, iax_call)) {
901 expert_add_info_format(pinfo, item, &ei_iax_circuit_id_conflict,
902 "IAX Packet %u from circuit ids %u->%u conflicts with earlier call with circuit ids %u->%u",
904 src_circuit_id, dst_circuit_id,
905 iax_call->forward_circuit_ids[0],
906 iax_call->reverse_circuit_ids[0]);
912 DISSECTOR_ASSERT_NOT_REACHED();
916 *reversed_p = reversed;
922 /* looks up an iax_call for this packet */
923 static iax_call_data *iax_lookup_call( packet_info *pinfo,
926 gboolean *reversed_p)
928 gboolean reversed = FALSE;
929 iax_call_data *iax_call = NULL;
930 guint src_circuit_id;
933 g_debug("++ iax_lookup_circuit_details: Looking up circuit for frame %u, "
934 "from {%s:%u:%u} to {%s:%u:%u}", pinfo->fd->num,
935 ep_address_to_str(&pinfo->src), pinfo->srcport, scallno,
936 ep_address_to_str(&pinfo->dst), pinfo->destport, dcallno);
940 src_circuit_id = iax_circuit_lookup(&pinfo->src, pinfo->ptype,
941 pinfo->srcport, scallno);
944 /* the most reliable indicator of call is the destination callno, if
947 guint dst_circuit_id;
949 g_debug("++ dcallno non-zero, looking up destination circuit");
952 dst_circuit_id = iax_circuit_lookup(&pinfo->dst, pinfo->ptype,
953 pinfo->destport, dcallno);
955 iax_call = iax_lookup_call_from_dest(pinfo, NULL, src_circuit_id, dst_circuit_id,
956 pinfo->fd->num, &reversed);
958 circuit_t *src_circuit;
960 /* in all other circumstances, the source circuit should already
961 * exist: its absence indicates that we missed the all-important NEW
965 src_circuit = find_circuit(CT_IAX2,
970 iax_call = (iax_call_data *)circuit_get_proto_data(src_circuit, proto_iax2);
972 /* there's no way we can create a CT_IAX2 circuit without adding
973 iax call data to it; assert this */
974 DISSECTOR_ASSERT(iax_call);
976 if (is_forward_circuit(src_circuit_id, iax_call))
978 else if (is_reverse_circuit(src_circuit_id, iax_call))
981 /* there's also no way we can attach an iax_call_data to a circuit
982 without the circuit being either the forward or reverse circuit
983 for that call; assert this too.
985 DISSECTOR_ASSERT_NOT_REACHED();
991 *reversed_p = reversed;
995 g_debug("++ Found call for packet: id %u, reversed=%c", iax_call->forward_circuit_ids[0], reversed?'1':'0');
997 g_debug("++ Call not found. Must have missed the NEW packet?");
1004 /* initialize the per-direction parts of an iax_call_data structure */
1005 static void init_dir_data(iax_call_dirdata *dirdata)
1007 dirdata -> current_frag_bytes=0;
1008 dirdata -> current_frag_minlen=0;
1012 /* handles a NEW packet by creating a new iax call and forward circuit.
1013 the reverse circuit is not created until the ACK is received and
1014 is created by iax_lookup_circuit_details. */
1015 static iax_call_data *iax_new_call( packet_info *pinfo,
1018 iax_call_data *call;
1020 static const nstime_t millisecond = {0, 1000000};
1022 #ifdef DEBUG_HASHING
1023 g_debug("+ new_circuit: Handling NEW packet, frame %u", pinfo->fd->num);
1026 circuit_id = iax_circuit_lookup(&pinfo->src, pinfo->ptype,
1027 pinfo->srcport, scallno);
1029 call = wmem_new(wmem_file_scope(), iax_call_data);
1030 call -> dataformat = AST_DATAFORMAT_NULL;
1031 call -> src_codec = 0;
1032 call -> dst_codec = 0;
1033 call -> n_forward_circuit_ids = 0;
1034 call -> n_reverse_circuit_ids = 0;
1035 call -> subdissector = NULL;
1036 call -> start_time = pinfo->fd->abs_ts;
1037 nstime_delta(&call -> start_time, &call -> start_time, &millisecond);
1038 init_dir_data(&call->dirdata[0]);
1039 init_dir_data(&call->dirdata[1]);
1041 iax2_new_circuit_for_call(pinfo, NULL, circuit_id, pinfo->fd->num, call, FALSE);
1047 /* ************************************************************************* */
1049 /* per-packet data */
1050 typedef struct iax_packet_data {
1051 gboolean first_time; /* we're dissecting this packet for the first time; so
1052 * things like codec and transfer requests should be
1053 * propagated into the call data */
1054 iax_call_data *call_data;
1057 nstime_t abstime; /* the absolute time of this packet, based on its
1058 * timestamp and the NEW packet's time (-1 if unknown) */
1061 static iax_packet_data *iax_new_packet_data(iax_call_data *call, gboolean reversed)
1063 iax_packet_data *p = wmem_new(wmem_file_scope(), iax_packet_data);
1064 p->first_time = TRUE;
1065 p->call_data = call;
1067 p->reversed = reversed;
1068 p->abstime.secs = -1;
1069 p->abstime.nsecs = -1;
1073 static void iax2_populate_pinfo_from_packet_data(packet_info *pinfo, const iax_packet_data *p)
1075 /* info for subdissectors. We always pass on the original forward circuit,
1076 * and steal the p2p_dir flag to indicate the direction */
1077 if (p->call_data == NULL) {
1078 /* if we missed the NEW packet for this call, call_data will be null. it's
1079 * tbd what the best thing to do here is. */
1080 pinfo -> ctype = CT_NONE;
1082 pinfo -> ctype = CT_IAX2;
1083 pinfo -> circuit_id = (guint32)p->call_data->forward_circuit_ids[0];
1084 pinfo -> p2p_dir = p->reversed?P2P_DIR_RECV:P2P_DIR_SENT;
1086 col_set_str(pinfo->cinfo, COL_IF_DIR, p->reversed ? "rev" : "fwd");
1091 /* ************************************************************************* */
1093 /* this is passed up from the IE dissector to the main dissector */
1096 address peer_address;
1097 port_type peer_ptype;
1099 guint32 peer_callno;
1104 static guint32 dissect_fullpacket(tvbuff_t *tvb, guint32 offset,
1107 proto_tree *iax2_tree,
1108 proto_tree *main_tree);
1111 static guint32 dissect_minipacket(tvbuff_t *tvb, guint32 offset,
1114 proto_tree *iax2_tree,
1115 proto_tree *main_tree);
1117 static guint32 dissect_minivideopacket(tvbuff_t *tvb, guint32 offset,
1120 proto_tree *iax2_tree,
1121 proto_tree *main_tree);
1123 static guint32 dissect_trunkpacket(tvbuff_t *tvb, guint32 offset,
1126 proto_tree *iax2_tree,
1127 proto_tree *main_tree);
1129 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
1130 packet_info *pinfo, proto_tree *iax2_tree,
1131 proto_tree *tree, guint32 ts, gboolean video,
1132 iax_packet_data *iax_packet);
1137 dissect_iax2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1139 proto_item *iax2_item;
1140 proto_tree *iax2_tree;
1141 proto_tree *full_mini_subtree = NULL;
1142 guint32 offset = 0, len;
1143 guint16 scallno = 0;
1146 proto_item *full_mini_base;
1148 /* set up the protocol and info fields in the summary pane */
1149 col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2);
1150 col_clear(pinfo->cinfo, COL_INFO);
1152 /* add the 'iax2' tree to the main tree */
1153 iax2_item = proto_tree_add_item(tree, proto_iax2, tvb, offset, -1, ENC_NA);
1154 iax2_tree = proto_item_add_subtree(iax2_item, ett_iax2);
1156 stmp = tvb_get_ntohs(tvb, offset);
1158 /* starting with 0x0000 indicates meta packet which can be either a mini
1159 * video packet or a trunk packet */
1161 stmp = tvb_get_ntohs(tvb, offset);
1162 if (stmp & 0x8000) {
1163 /* mini video packet */
1164 type = IAX2_MINI_VIDEO_PACKET;
1165 scallno = stmp & 0x7FFF;
1169 type = IAX2_TRUNK_PACKET;
1172 /* The source call/fullpacket flag is common to both mini and full packets */
1173 scallno = tvb_get_ntohs(tvb, offset);
1175 if (scallno & 0x8000)
1176 type = IAX2_FULL_PACKET;
1178 type = IAX2_MINI_VOICE_PACKET;
1183 full_mini_base = proto_tree_add_uint(iax2_tree, hf_iax2_packet_type, tvb, 0, offset, type);
1184 full_mini_subtree = proto_item_add_subtree(full_mini_base, ett_iax2_full_mini_subtree);
1187 proto_tree_add_item(full_mini_subtree, hf_iax2_scallno, tvb, offset-2, 2, ENC_BIG_ENDIAN);
1189 iax2_info->ptype = type;
1190 iax2_info->scallno = 0;
1191 iax2_info->dcallno = 0;
1192 iax2_info->ftype = 0;
1193 iax2_info->csub = 0;
1194 iax2_info->payload_len = 0;
1195 iax2_info->timestamp = 0;
1196 iax2_info->callState = VOIP_NO_STATE;
1197 iax2_info->messageName = NULL;
1198 iax2_info->callingParty = NULL;
1199 iax2_info->calledParty = NULL;
1200 iax2_info->payload_data = NULL;
1203 case IAX2_FULL_PACKET:
1204 len = dissect_fullpacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree);
1206 case IAX2_MINI_VOICE_PACKET:
1207 iax2_info->messageName = "MINI_VOICE_PACKET";
1208 len = dissect_minipacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree);
1210 case IAX2_MINI_VIDEO_PACKET:
1211 iax2_info->messageName = "MINI_VIDEO_PACKET";
1212 len = dissect_minivideopacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree);
1214 case IAX2_TRUNK_PACKET:
1215 iax2_info->messageName = "TRUNK_PACKET";
1216 len = dissect_trunkpacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree);
1222 /* update the 'length' of the main IAX2 header field so that it covers just the headers,
1223 not the audio data. */
1224 proto_item_set_len(iax2_item, len);
1225 tap_queue_packet(iax2_tap, pinfo, iax2_info);
1228 static proto_item *dissect_datetime_ie(tvbuff_t *tvb, guint32 offset, proto_tree *ies_tree)
1234 proto_tree_add_item(ies_tree, hf_iax2_ies[IAX_IE_DATETIME], tvb, offset + 2, 4, ENC_BIG_ENDIAN);
1235 ie_val = tvb_get_ntohl(tvb, offset+2);
1237 /* who's crazy idea for a time encoding was this? */
1238 tm.tm_sec = (ie_val & 0x1f) << 1;
1239 tm.tm_min = (ie_val>>5) & 0x3f;
1240 tm.tm_hour = (ie_val>>11) & 0x1f;
1241 tm.tm_mday = (ie_val>>16) & 0x1f;
1242 tm.tm_mon = ((ie_val>>21) & 0x0f) - 1;
1243 tm.tm_year = ((ie_val>>25) & 0x7f) + 100;
1244 tm.tm_isdst= -1; /* there's no info on whether DST was in force; assume it's
1245 * the same as currently */
1247 datetime.secs = mktime(&tm);
1249 return proto_tree_add_time(ies_tree, hf_iax2_ie_datetime, tvb, offset+2, 4, &datetime);
1253 /* dissect the information elements in an IAX frame. Returns the updated offset */
1254 static guint32 dissect_ies(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
1255 proto_tree *iax_tree, proto_item * iax_item,
1256 iax2_ie_data *ie_data)
1258 DISSECTOR_ASSERT(ie_data);
1260 while (offset < tvb_reported_length(tvb)) {
1262 int ies_type = tvb_get_guint8(tvb, offset);
1263 int ies_len = tvb_get_guint8(tvb, offset + 1);
1264 guint16 apparent_addr_family;
1266 /* do non-tree-dependent stuff first */
1268 case IAX_IE_DATAFORMAT:
1269 if (ies_len != 4) THROW(ReportedBoundsError);
1270 ie_data -> dataformat = tvb_get_ntohl(tvb, offset+2);
1273 case IAX_IE_CALLED_NUMBER:
1274 iax2_info->calledParty = wmem_strdup(wmem_packet_scope(), tvb_format_text(tvb, offset+2, ies_len));
1276 case IAX_IE_CALLING_NUMBER:
1277 iax2_info->callingParty = wmem_strdup(wmem_packet_scope(), tvb_format_text(tvb, offset+2, ies_len));
1280 case IAX_IE_APPARENT_ADDR:
1281 /* The IAX2 I-D says that the "apparent address" structure
1282 "is the same as the linux struct sockaddr_in", without
1283 bothering to note that the address family field is in
1284 *host* byte order in that structure (the I-D seems to be
1285 assuming that "everything is a Vax^Wx86 or x86-64" with
1286 the address family field being little-endian).
1288 This means the address family values are the Linux
1289 address family values. */
1290 apparent_addr_family = tvb_get_letohs(tvb, offset+2);
1291 switch (apparent_addr_family) {
1293 /* IAX is always over UDP */
1294 ie_data->peer_ptype = PT_UDP;
1295 ie_data->peer_port = tvb_get_ntohs(tvb, offset+4);
1297 /* the ip address is big-endian, but then so is peer_address.data */
1298 TVB_SET_ADDRESS(&ie_data->peer_address, AT_IPv4, tvb, offset+6, 4);
1302 expert_add_info_format(pinfo, iax_item, &ei_iax_peer_address_unsupported,
1303 "Not supported in IAX dissector: peer address family of %u", apparent_addr_family);
1310 /* the rest of this stuff only needs doing if we have an iax_tree */
1312 if (iax_tree && ies_type < NUM_HF_IAX2_IES) {
1313 proto_item *ti, *ie_item = NULL;
1314 proto_tree *ies_tree;
1315 int ie_hf = hf_iax2_ies[ies_type];
1317 ti = proto_tree_add_text(iax_tree, tvb, offset, ies_len+2, " ");
1319 ies_tree = proto_item_add_subtree(ti, ett_iax2_ie);
1321 proto_tree_add_text(ies_tree, tvb, offset, 1, "IE id: %s (0x%02X)",
1322 val_to_str_ext_const(ies_type, &iax_ies_type_ext, "Unknown"),
1325 proto_tree_add_text(ies_tree, tvb, offset + 1, 1, "Length: %u", ies_len);
1328 /* hf_iax2_ies[] is an array, indexed by IE number, of header-fields, one
1329 per IE. Apart from a couple of special cases which require more
1330 complex decoding, we can just look up an entry from the array, and add
1331 the relevant item, although the encoding value used depends on the
1336 case IAX_IE_DATETIME:
1337 ie_item = dissect_datetime_ie(tvb, offset, ies_tree);
1341 case IAX_IE_CAPABILITY:
1343 proto_tree *codec_tree;
1345 if (ies_len != 4) THROW(ReportedBoundsError);
1348 proto_tree_add_item(ies_tree, ie_hf,
1349 tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1351 proto_item_add_subtree(ie_item, ett_iax2_codecs);
1353 proto_tree_add_item(codec_tree, hf_iax2_cap_g723_1, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1354 proto_tree_add_item(codec_tree, hf_iax2_cap_gsm, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1355 proto_tree_add_item(codec_tree, hf_iax2_cap_ulaw, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1356 proto_tree_add_item(codec_tree, hf_iax2_cap_alaw, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1357 proto_tree_add_item(codec_tree, hf_iax2_cap_g726_aal2, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1358 proto_tree_add_item(codec_tree, hf_iax2_cap_adpcm, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1359 proto_tree_add_item(codec_tree, hf_iax2_cap_slinear, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1360 proto_tree_add_item(codec_tree, hf_iax2_cap_lpc10, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1361 proto_tree_add_item(codec_tree, hf_iax2_cap_g729a, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1362 proto_tree_add_item(codec_tree, hf_iax2_cap_speex, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1363 proto_tree_add_item(codec_tree, hf_iax2_cap_ilbc, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1364 proto_tree_add_item(codec_tree, hf_iax2_cap_g726, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1365 proto_tree_add_item(codec_tree, hf_iax2_cap_g722, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1366 proto_tree_add_item(codec_tree, hf_iax2_cap_siren7, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1367 proto_tree_add_item(codec_tree, hf_iax2_cap_siren14, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1368 proto_tree_add_item(codec_tree, hf_iax2_cap_slinear16, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1369 proto_tree_add_item(codec_tree, hf_iax2_cap_jpeg, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1370 proto_tree_add_item(codec_tree, hf_iax2_cap_png, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1371 proto_tree_add_item(codec_tree, hf_iax2_cap_h261, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1372 proto_tree_add_item(codec_tree, hf_iax2_cap_h263, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1373 proto_tree_add_item(codec_tree, hf_iax2_cap_h263_plus, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1374 proto_tree_add_item(codec_tree, hf_iax2_cap_h264, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1375 proto_tree_add_item(codec_tree, hf_iax2_cap_mpeg4, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1379 case IAX_IE_APPARENT_ADDR:
1381 proto_tree *sockaddr_tree = NULL;
1383 ie_item = proto_tree_add_text(ies_tree, tvb, offset + 2, 16, "Apparent Address");
1384 sockaddr_tree = proto_item_add_subtree(ie_item, ett_iax2_ies_apparent_addr);
1386 /* The IAX2 I-D says that the "apparent address" structure
1387 "is the same as the linux struct sockaddr_in", without
1388 bothering to note that the address family field is in
1389 *host* byte order in that structure (the I-D seems to be
1390 assuming that "everything is a Vax^Wx86 or x86-64" with
1391 the address family field being little-endian).
1393 This means the address family values are the Linux
1394 address family values. */
1395 apparent_addr_family = tvb_get_letohs(tvb, offset+2);
1396 proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINFAMILY, tvb, offset + 2, 2, apparent_addr_family);
1398 switch (apparent_addr_family) {
1402 proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINPORT, tvb, offset + 4, 2, ie_data->peer_port);
1403 memcpy(&addr, ie_data->peer_address.data, 4);
1404 proto_tree_add_ipv4(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINADDR, tvb, offset + 6, 4, addr);
1413 /* throw an error if the IE isn't the expected length */
1414 enum ftenum type = proto_registrar_get_nth(ie_hf)->type;
1415 gint explen = ftype_length(type);
1416 if (explen != 0 && ies_len != explen)
1417 THROW(ReportedBoundsError);
1431 ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1436 ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_NA);
1441 ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_UTF_8|ENC_NA);
1445 DISSECTOR_ASSERT_NOT_REACHED();
1449 /* we don't understand this ie: add a generic one */
1452 const gchar *ie_name = val_to_str_ext_const(ies_type, &iax_ies_type_ext, "Unknown");
1456 value = tvb_get_guint8(tvb, offset + 2);
1458 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTE,
1459 tvb, offset+2, 1, value,
1460 "%s: %#02x", ie_name, value);
1464 value = tvb_get_ntohs(tvb, offset + 2);
1466 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I16,
1467 tvb, offset+2, 2, value,
1468 "%s: %#04x", ie_name, value);
1472 value = tvb_get_ntohl(tvb, offset + 2);
1474 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I32,
1475 tvb, offset+2, 4, value,
1476 "%s: %#08x", ie_name, value);
1480 ptr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 2, ies_len, ENC_ASCII);
1482 proto_tree_add_string_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTES,
1483 tvb, offset+2, ies_len, ptr,
1484 "%s: %s", ie_name, ptr);
1491 /* by now, we *really* ought to have added an item */
1492 DISSECTOR_ASSERT(ie_item != NULL);
1494 /* Retrieve the text from the item we added, and append it to the main IE
1496 if (!PROTO_ITEM_IS_HIDDEN(ti)) {
1497 field_info *ie_finfo = PITEM_FINFO(ie_item);
1499 /* if the representation of the item has already been set, use that;
1500 else we have to allocate a block to put the text into */
1501 if (ie_finfo && ie_finfo->rep != NULL)
1502 proto_item_set_text(ti, "Information Element: %s",
1503 ie_finfo->rep->representation);
1505 guint8 *ie_val = NULL;
1506 ie_val = (guint8 *)wmem_alloc(wmem_packet_scope(), ITEM_LABEL_LENGTH);
1507 proto_item_fill_label(ie_finfo, ie_val);
1508 proto_item_set_text(ti, "Information Element: %s",
1514 offset += ies_len + 2;
1519 static guint32 uncompress_subclass(guint8 csub)
1521 /* If the SC_LOG flag is set, return 2^csub otherwise csub */
1523 /* special case for 'compressed' -1 */
1527 return 1 << (csub & 0x1F);
1530 return (guint32)csub;
1533 /* returns the new offset */
1534 static guint32 dissect_iax2_command(tvbuff_t *tvb, guint32 offset,
1535 packet_info *pinfo, proto_tree *tree,
1536 iax_packet_data *iax_packet)
1538 guint8 csub = tvb_get_guint8(tvb, offset);
1539 guint8 address_data[MAX_ADDRESS];
1541 iax2_ie_data ie_data;
1542 iax_call_data *iax_call;
1544 ie_data.peer_address.type = AT_NONE;
1545 ie_data.peer_address.len = 0;
1546 ie_data.peer_address.data = address_data;
1547 ie_data.peer_ptype = PT_NONE;
1548 ie_data.peer_port = 0;
1549 ie_data.peer_callno = 0;
1550 ie_data.dataformat = (guint32)-1;
1551 iax_call = iax_packet -> call_data;
1553 /* add the subclass */
1554 ti = proto_tree_add_uint(tree, hf_iax2_iax_csub, tvb, offset, 1, csub);
1557 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1558 val_to_str_ext(csub, &iax_iax_subclasses_ext, "unknown (0x%02x)"));
1560 if (offset >= tvb_reported_length(tvb))
1563 offset = dissect_ies(tvb, pinfo, offset, tree, ti, &ie_data);
1565 /* if this is a data call, set up a subdissector for the circuit */
1566 if (iax_call && ie_data.dataformat != (guint32)-1 && iax_call -> subdissector == NULL) {
1567 iax_call -> subdissector = dissector_get_uint_handle(iax2_dataformat_dissector_table, ie_data.dataformat);
1568 iax_call -> dataformat = (iax_dataformat_t)ie_data.dataformat;
1571 /* if this is a transfer request, record it in the call data */
1572 if (csub == IAX_COMMAND_TXREQ && iax_packet -> first_time) {
1573 if (ie_data.peer_address.type != AT_NONE && ie_data.peer_callno != 0) {
1574 guint tx_circuit = iax_circuit_lookup(&ie_data.peer_address,
1577 ie_data.peer_callno);
1579 iax2_new_circuit_for_call(pinfo, NULL, tx_circuit, pinfo->fd->num, iax_call, iax_packet->reversed);
1586 static void iax2_add_ts_fields(packet_info *pinfo, proto_tree *iax2_tree, iax_packet_data *iax_packet, guint16 shortts)
1588 guint32 longts =shortts;
1592 if (iax_packet->call_data == NULL) {
1593 /* no call info for this frame; perhaps we missed the NEW packet */
1597 if (iax_packet->abstime.secs == -1) {
1598 time_t start_secs = iax_packet->call_data->start_time.secs;
1599 gint32 abs_secs = (gint32)(start_secs + longts/1000);
1601 /* deal with short timestamps by assuming that packets are never more than
1602 * 16 seconds late */
1603 while(abs_secs < pinfo->fd->abs_ts.secs - 16) {
1605 abs_secs = (gint32)(start_secs + longts/1000);
1608 iax_packet->abstime.secs=abs_secs;
1609 iax_packet->abstime.nsecs=iax_packet->call_data->start_time.nsecs + (longts % 1000) * 1000000;
1610 if (iax_packet->abstime.nsecs >= 1000000000) {
1611 iax_packet->abstime.nsecs -= 1000000000;
1612 iax_packet->abstime.secs ++;
1615 iax2_info->timestamp = longts;
1618 item = proto_tree_add_time(iax2_tree, hf_iax2_absts, NULL, 0, 0, &iax_packet->abstime);
1619 PROTO_ITEM_SET_GENERATED(item);
1621 ts = pinfo->fd->abs_ts;
1622 nstime_delta(&ts, &ts, &iax_packet->abstime);
1624 item = proto_tree_add_time(iax2_tree, hf_iax2_lateness, NULL, 0, 0, &ts);
1625 PROTO_ITEM_SET_GENERATED(item);
1629 /* returns the new offset */
1631 dissect_fullpacket(tvbuff_t *tvb, guint32 offset,
1633 packet_info *pinfo, proto_tree *iax2_tree,
1634 proto_tree *main_tree)
1642 proto_tree *packet_type_tree = NULL;
1643 iax_call_data *iax_call;
1644 iax_packet_data *iax_packet;
1646 gboolean rtp_marker;
1649 * remove the top bit for retransmission detection
1651 dcallno = tvb_get_ntohs(tvb, offset) & 0x7FFF;
1652 ts = tvb_get_ntohl(tvb, offset + 2);
1653 type = tvb_get_guint8(tvb, offset + 8);
1654 csub = tvb_get_guint8(tvb, offset + 9);
1655 iax2_info->ftype = type;
1656 iax2_info->csub = csub;
1657 iax2_info->scallno = scallno;
1658 iax2_info->dcallno = dcallno;
1660 /* see if we've seen this packet before */
1661 iax_packet = (iax_packet_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0);
1663 /* if not, find or create an iax_call info structure for this IAX session. */
1665 if (type == AST_FRAME_IAX && csub == IAX_COMMAND_NEW) {
1666 /* NEW packets start a new call */
1667 iax_call = iax_new_call(pinfo, scallno);
1670 iax_call = iax_lookup_call(pinfo, scallno, dcallno,
1674 iax_packet = iax_new_packet_data(iax_call, reversed);
1675 p_add_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0, iax_packet);
1677 iax_call = iax_packet->call_data;
1678 reversed = iax_packet->reversed;
1681 iax2_populate_pinfo_from_packet_data(pinfo, iax_packet);
1684 proto_item *packet_type_base;
1686 proto_tree_add_item(iax2_tree, hf_iax2_dcallno, tvb, offset, 2, ENC_BIG_ENDIAN);
1688 proto_tree_add_item(iax2_tree, hf_iax2_retransmission, tvb, offset, 2, ENC_BIG_ENDIAN);
1692 proto_tree_add_uint(iax2_tree, hf_iax2_callno, tvb, 0, 4,
1693 iax_call->forward_circuit_ids[0]);
1694 PROTO_ITEM_SET_GENERATED(item);
1697 proto_tree_add_uint(iax2_tree, hf_iax2_ts, tvb, offset+2, 4, ts);
1698 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1700 proto_tree_add_item(iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1,
1703 proto_tree_add_item(iax2_tree, hf_iax2_iseqno, tvb, offset+7, 1,
1705 packet_type_base = proto_tree_add_uint(iax2_tree, hf_iax2_type, tvb,
1708 /* add the type-specific subtree */
1709 packet_type_tree = proto_item_add_subtree(packet_type_base, ett_iax2_type);
1711 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1715 /* add frame type to info line */
1716 col_add_fstr(pinfo->cinfo, COL_INFO, "%s, source call# %d, timestamp %ums",
1717 val_to_str_ext(type, &iax_frame_types_ext, "Unknown (0x%02x)"),
1720 iax2_info->messageName = val_to_str_ext(type, &iax_frame_types_ext, "Unknown (0x%02x)");
1724 offset=dissect_iax2_command(tvb, offset+9, pinfo, packet_type_tree, iax_packet);
1725 iax2_info->messageName = val_to_str_ext(csub, &iax_iax_subclasses_ext, "unknown (0x%02x)");
1726 if (csub < NUM_TAP_IAX_VOIP_STATES) iax2_info->callState = tap_iax_voip_state[csub];
1729 case AST_FRAME_DTMF_BEGIN:
1730 case AST_FRAME_DTMF_END:
1731 proto_tree_add_item(packet_type_tree, hf_iax2_dtmf_csub, tvb, offset+9, 1, ENC_ASCII|ENC_NA);
1734 col_append_fstr(pinfo->cinfo, COL_INFO, " digit %c", csub);
1737 case AST_FRAME_CONTROL:
1738 /* add the subclass */
1739 proto_tree_add_uint(packet_type_tree, hf_iax2_cmd_csub, tvb,
1743 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1744 val_to_str_ext(csub, &iax_cmd_subclasses_ext, "unknown (0x%02x)"));
1745 iax2_info->messageName = val_to_str_ext (csub, &iax_cmd_subclasses_ext, "unknown (0x%02x)");
1746 if (csub < NUM_TAP_CMD_VOIP_STATES) iax2_info->callState = tap_cmd_voip_state[csub];
1749 case AST_FRAME_VOICE:
1751 iax_packet -> codec = codec = uncompress_subclass(csub);
1753 if (packet_type_tree) {
1755 proto_tree_add_item(packet_type_tree, hf_iax2_voice_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1756 item = proto_tree_add_uint(packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, codec);
1757 PROTO_ITEM_SET_GENERATED(item);
1764 iax_call->dst_codec = codec;
1766 iax_call->src_codec = codec;
1770 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, FALSE, iax_packet);
1773 case AST_FRAME_VIDEO:
1774 /* bit 6 of the csub is used to represent the rtp 'marker' bit */
1775 rtp_marker = csub & 0x40 ? TRUE:FALSE;
1776 iax_packet -> codec = codec = uncompress_subclass((guint8)(csub & ~40));
1778 if (packet_type_tree) {
1780 proto_tree_add_item(packet_type_tree, hf_iax2_video_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1781 proto_tree_add_item(packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1782 item = proto_tree_add_uint(packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, codec);
1783 PROTO_ITEM_SET_GENERATED(item);
1788 if (iax_call && iax_packet -> first_time) {
1790 iax_call->dst_vformat = codec;
1792 iax_call->src_vformat = codec;
1797 col_append_str(pinfo->cinfo, COL_INFO, ", Mark");
1800 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, TRUE, iax_packet);
1803 case AST_FRAME_MODEM:
1804 proto_tree_add_item(packet_type_tree, hf_iax2_modem_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1807 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1808 val_to_str(csub, iax_modem_subclasses, "unknown (0x%02x)"));
1811 case AST_FRAME_TEXT:
1812 proto_tree_add_item(packet_type_tree, hf_iax2_text_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1816 int textlen = tvb_captured_length_remaining(tvb, offset);
1819 proto_tree_add_item(packet_type_tree, hf_iax2_text_text, tvb, offset, textlen, ENC_UTF_8|ENC_NA);
1825 case AST_FRAME_HTML:
1826 proto_tree_add_item(packet_type_tree, hf_iax2_html_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1831 int urllen = tvb_captured_length_remaining(tvb, offset);
1834 proto_item *pi = proto_tree_add_item(packet_type_tree, hf_iax2_html_url, tvb, offset, urllen, ENC_UTF_8|ENC_NA);
1835 PROTO_ITEM_SET_URL(pi);
1843 proto_tree_add_uint(packet_type_tree, hf_iax2_csub, tvb, offset+9,
1847 col_append_fstr(pinfo->cinfo, COL_INFO, " subclass %d", csub);
1851 /* next time we come to parse this packet, don't propagate the codec into the
1853 iax_packet->first_time = FALSE;
1858 static iax_packet_data *iax2_get_packet_data_for_minipacket(packet_info *pinfo,
1862 /* see if we've seen this packet before */
1863 iax_packet_data *p = (iax_packet_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0);
1866 /* if not, find or create an iax_call info structure for this IAX session. */
1868 iax_call_data *iax_call;
1870 iax_call = iax_lookup_call(pinfo, scallno, 0, &reversed);
1872 p = iax_new_packet_data(iax_call, reversed);
1873 p_add_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0, p);
1875 /* set the codec for this frame to be whatever the last full frame used */
1878 p->codec = reversed ? iax_call -> dst_vformat : iax_call -> src_vformat;
1880 p->codec = reversed ? iax_call -> dst_codec : iax_call -> src_codec;
1884 iax2_populate_pinfo_from_packet_data(pinfo, p);
1889 static guint32 dissect_minivideopacket(tvbuff_t *tvb, guint32 offset,
1890 guint16 scallno, packet_info *pinfo,
1891 proto_tree *iax2_tree, proto_tree *main_tree)
1894 iax_packet_data *iax_packet;
1895 gboolean rtp_marker;
1898 ts = tvb_get_ntohs(tvb, offset);
1900 /* bit 15 of the ts is used to represent the rtp 'marker' bit */
1901 rtp_marker = ts & 0x8000 ? TRUE:FALSE;
1904 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, TRUE);
1907 if (iax_packet->call_data) {
1909 proto_tree_add_uint(iax2_tree, hf_iax2_callno, tvb, 0, 4,
1910 iax_packet->call_data->forward_circuit_ids[0]);
1911 PROTO_ITEM_SET_GENERATED(item);
1914 proto_tree_add_item(iax2_tree, hf_iax2_minividts, tvb, offset, 2, ENC_BIG_ENDIAN);
1915 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1916 proto_tree_add_item(iax2_tree, hf_iax2_minividmarker, tvb, offset, 2, ENC_BIG_ENDIAN);
1918 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1923 col_add_fstr(pinfo->cinfo, COL_INFO,
1924 "Mini video packet, source call# %d, timestamp %ums%s",
1925 scallno, ts, rtp_marker?", Mark":"");
1928 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, TRUE, iax_packet);
1930 /* next time we come to parse this packet, don't propagate the codec into the
1932 iax_packet->first_time = FALSE;
1937 static guint32 dissect_minipacket(tvbuff_t *tvb, guint32 offset, guint16 scallno,
1938 packet_info *pinfo, proto_tree *iax2_tree,
1939 proto_tree *main_tree)
1942 iax_packet_data *iax_packet;
1945 ts = tvb_get_ntohs(tvb, offset);
1947 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, FALSE);
1950 if (iax_packet->call_data) {
1951 item = proto_tree_add_uint(iax2_tree, hf_iax2_callno, tvb, 0, 4,
1952 iax_packet->call_data->forward_circuit_ids[0]);
1953 PROTO_ITEM_SET_GENERATED(item);
1956 proto_tree_add_uint(iax2_tree, hf_iax2_minits, tvb, offset, 2, ts);
1957 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1959 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1965 col_add_fstr(pinfo->cinfo, COL_INFO,
1966 "Mini packet, source call# %d, timestamp %ums",
1970 /* XXX fix the timestamp logic */
1971 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, FALSE, iax_packet);
1974 /* next time we come to parse this packet, don't propagate the codec into the
1976 iax_packet->first_time = FALSE;
1982 static guint32 dissect_trunkcall_ts(tvbuff_t *tvb, guint32 offset, proto_tree *iax2_tree, guint16 *scallno)
1984 proto_item *call_item;
1985 proto_tree *call_tree;
1986 guint16 datalen, rlen, ts;
1988 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1989 | Data Length (in octets) |R| Source Call Number |
1990 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1992 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1996 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1998 datalen = tvb_get_ntohs(tvb, offset);
1999 *scallno = tvb_get_ntohs(tvb, offset + 2);
2000 ts = tvb_get_ntohs(tvb, offset + 4);
2002 rlen = MIN(tvb_length(tvb) - offset - 6, datalen);
2005 call_item = proto_tree_add_text(iax2_tree, tvb, offset, rlen + 6, "Trunk call from %u, ts: %u", *scallno, ts);
2006 call_tree = proto_item_add_subtree(call_item, ett_iax2_trunk_call);
2008 proto_tree_add_item(call_tree, hf_iax2_trunk_call_len, tvb, offset, 2, ENC_BIG_ENDIAN);
2009 proto_tree_add_item(call_tree, hf_iax2_trunk_call_scallno, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2010 proto_tree_add_item(call_tree, hf_iax2_trunk_call_ts, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
2011 proto_tree_add_item(call_tree, hf_iax2_trunk_call_data, tvb, offset + 6, rlen, ENC_NA);
2018 static guint32 dissect_trunkcall_nots(tvbuff_t *tvb, guint32 offset, proto_tree *iax2_tree, guint16 *scallno)
2020 proto_item *call_item;
2021 proto_tree *call_tree;
2022 guint16 datalen, rlen;
2024 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2025 |R| Source Call Number | Data Length (in octets) |
2026 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2030 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2032 *scallno = tvb_get_ntohs(tvb, offset);
2033 datalen = tvb_get_ntohs(tvb, offset + 2);
2035 rlen = MIN(tvb_length(tvb) - offset - 4, datalen);
2038 call_item = proto_tree_add_text(iax2_tree, tvb, offset, rlen + 6, "Trunk call from %u", *scallno);
2039 call_tree = proto_item_add_subtree(call_item, ett_iax2_trunk_call);
2041 proto_tree_add_item(call_tree, hf_iax2_trunk_call_scallno, tvb, offset, 2, ENC_BIG_ENDIAN);
2042 proto_tree_add_item(call_tree, hf_iax2_trunk_call_len, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2043 proto_tree_add_item(call_tree, hf_iax2_trunk_call_data, tvb, offset + 4, rlen, ENC_NA);
2050 typedef struct _call_list {
2052 struct _call_list *next;
2055 static call_list *call_list_append(call_list *list, guint16 scallno)
2057 call_list *node = wmem_new0(wmem_packet_scope(), call_list);
2059 node->scallno = scallno;
2062 call_list *cur = list;
2073 static gboolean call_list_find(call_list *list, guint16 scallno)
2075 for (; list; list = list->next) {
2076 if (list->scallno == scallno) {
2083 static guint call_list_length(call_list *list)
2086 for (; list; list = list->next) {
2092 static guint32 dissect_trunkpacket(tvbuff_t *tvb, guint32 offset,
2093 guint16 scallno_param _U_, packet_info *pinfo,
2094 proto_tree *iax2_tree, proto_tree *main_tree _U_)
2096 guint8 cmddata, trunkts;
2097 guint nframes = 0, ncalls = 0;
2098 proto_item *cd, *nc = NULL;
2099 proto_tree *field_tree = NULL;
2100 call_list *calls = NULL;
2101 /*iax_packet_data *iax_packet;*/
2103 cmddata = tvb_get_guint8(tvb, offset + 1);
2104 trunkts = cmddata & IAX2_TRUNK_TS;
2106 /* 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 */
2107 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
2108 /* |F| Meta Indicator |V|Meta Command | Cmd Data (0) | */
2109 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
2110 /* | time-stamp | */
2111 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
2115 proto_tree_add_item(iax2_tree, hf_iax2_trunk_metacmd, tvb, offset, 1, ENC_BIG_ENDIAN);
2118 cd = proto_tree_add_uint(iax2_tree, hf_iax2_trunk_cmddata, tvb, offset + 1, 1, cmddata);
2119 field_tree = proto_item_add_subtree(cd, ett_iax2_trunk_cmddata);
2121 proto_item_append_text(cd, " (trunk timestamps)");
2123 /* CD -> Trunk timestamp */
2124 proto_tree_add_boolean(field_tree, hf_iax2_trunk_cmddata_ts, tvb, offset + 1, 1, cmddata);
2127 proto_tree_add_item(iax2_tree, hf_iax2_trunk_ts, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
2133 /* Trunk calls with timestamp */
2134 while(tvb_length_remaining(tvb, offset) >= 6) {
2136 offset = dissect_trunkcall_ts(tvb, offset, iax2_tree, &scallno);
2137 if (!call_list_find(calls, scallno)) {
2138 calls = call_list_append(calls, scallno);
2144 /* Trunk calls without timestamp */
2145 while(tvb_length_remaining(tvb, offset) >= 4) {
2147 offset = dissect_trunkcall_nots(tvb, offset, iax2_tree, &scallno);
2148 if (!call_list_find(calls, scallno)) {
2149 calls = call_list_append(calls, scallno);
2155 ncalls = call_list_length(calls);
2158 /* number of items */
2159 nc = proto_tree_add_uint(iax2_tree, hf_iax2_trunk_ncalls, NULL, 0, 0, ncalls);
2160 PROTO_ITEM_SET_GENERATED(nc);
2163 col_add_fstr(pinfo->cinfo, COL_INFO, "Trunk packet with %d media frame%s for %d call%s",
2164 nframes, plurality(nframes, "", "s"),
2165 ncalls, plurality(ncalls, "", "s"));
2171 static void process_iax_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2172 gboolean video, iax_packet_data *iax_packet)
2174 guint32 codec = iax_packet -> codec;
2175 iax_call_data *iax_call = iax_packet -> call_data;
2177 #ifdef DEBUG_DESEGMENT
2178 g_debug("calling process_iax_pdu; len = %u", tvb_reported_length(tvb));
2181 if (!video && iax_call && iax_call->subdissector) {
2182 call_dissector(iax_call->subdissector, tvb, pinfo, tree);
2183 } else if (codec != 0 && dissector_try_uint(iax2_codec_dissector_table, codec, tvb, pinfo, tree)) {
2184 /* codec dissector handled our data */
2186 /* we don't know how to dissect our data: dissect it as data */
2187 call_dissector(data_handle, tvb, pinfo, tree);
2190 #ifdef DEBUG_DESEGMENT
2191 g_debug("called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u",
2192 pinfo->desegment_len, pinfo->desegment_offset);
2196 static void desegment_iax(tvbuff_t *tvb, packet_info *pinfo, proto_tree *iax2_tree,
2197 proto_tree *tree, gboolean video, iax_packet_data *iax_packet)
2200 iax_call_data *iax_call = iax_packet -> call_data;
2201 iax_call_dirdata *dirdata;
2202 gpointer value = NULL;
2203 guint32 frag_offset = 0;
2204 fragment_head *fd_head;
2205 gboolean must_desegment = FALSE;
2207 DISSECTOR_ASSERT(iax_call);
2209 pinfo->can_desegment = 2;
2210 pinfo->desegment_offset = 0;
2211 pinfo->desegment_len = 0;
2213 #ifdef DEBUG_DESEGMENT
2214 g_debug("dissecting packet %u", pinfo->fd->num);
2217 dirdata = &(iax_call->dirdata[!!(iax_packet->reversed)]);
2219 if ((!pinfo->fd->flags.visited && (dirdata->current_frag_bytes > 0)) ||
2220 ((value = g_hash_table_lookup(iax_fid_table, GUINT_TO_POINTER(pinfo->fd->num))) != NULL)) {
2222 /* then we are continuing an already-started pdu */
2224 guint32 frag_len = tvb_reported_length(tvb);
2227 #ifdef DEBUG_DESEGMENT
2228 g_debug("visited: %i; c_f_b: %u; hash: %u->%u", pinfo->fd->flags.visited?1:0,
2229 dirdata->current_frag_bytes, pinfo->fd->num, dirdata->current_frag_id);
2232 if (!pinfo->fd->flags.visited) {
2234 fid = dirdata->current_frag_id;
2235 tot_len = dirdata->current_frag_minlen;
2236 DISSECTOR_ASSERT(g_hash_table_lookup(iax_fid_table, GUINT_TO_POINTER(pinfo->fd->num)) == NULL);
2237 g_hash_table_insert(iax_fid_table, GUINT_TO_POINTER(pinfo->fd->num), GUINT_TO_POINTER(fid));
2238 frag_offset = dirdata->current_frag_bytes;
2239 dirdata->current_frag_bytes += frag_len;
2240 complete = dirdata->current_frag_bytes > tot_len;
2241 #ifdef DEBUG_DESEGMENT
2242 g_debug("hash: %u->%u; frag_offset: %u; c_f_b: %u; totlen: %u",
2243 pinfo->fd->num, fid, frag_offset, dirdata->current_frag_bytes, tot_len);
2246 fid = GPOINTER_TO_UINT(value);
2247 /* these values are unused by fragment_add if pinfo->fd->flags.visited */
2248 dirdata->current_frag_bytes = 0;
2252 /* fragment_add checks for already-added */
2253 fd_head = fragment_add(&iax_reassembly_table, tvb, 0, pinfo, fid, NULL,
2255 frag_len, !complete);
2257 if (fd_head && (pinfo->fd->num == fd_head->reassembled_in)) {
2259 tvbuff_t *next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
2260 add_new_data_source(pinfo, next_tvb, "Reassembled IAX2");
2262 process_iax_pdu(next_tvb, pinfo, tree, video, iax_packet);
2264 /* calculate the amount of data which was available to the higher-level
2265 dissector before we added this segment; if the returned offset is
2266 within that section, the higher-level dissector was unable to find any
2267 pdus; if it's after that, it found one or more complete PDUs.
2269 old_len = (gint32)(tvb_reported_length(next_tvb) - frag_len);
2270 if (pinfo->desegment_len &&
2271 (pinfo->desegment_offset < old_len)) {
2272 /* oops, it wasn't actually complete */
2273 fragment_set_partial_reassembly(&iax_reassembly_table, pinfo, fid, NULL);
2274 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
2275 /* only one more byte should be enough for a retry */
2276 dirdata->current_frag_minlen = fd_head->datalen + 1;
2278 dirdata->current_frag_minlen = fd_head->datalen + pinfo->desegment_len;
2281 /* we successfully dissected some data; create the proto tree items for
2282 * the fragments, and flag any remaining data for desegmentation */
2284 proto_item *iax_tree_item, *frag_tree_item;
2285 /* this nargery is to insert the fragment tree into the main tree
2286 * between the IAX protocol entry and the subdissector entry */
2287 show_fragment_tree(fd_head, &iax2_fragment_items, tree, pinfo, next_tvb, &frag_tree_item);
2288 iax_tree_item = proto_item_get_parent(proto_tree_get_parent(iax2_tree));
2289 if (frag_tree_item && iax_tree_item)
2290 proto_tree_move_item(tree, iax_tree_item, frag_tree_item);
2292 dirdata->current_frag_minlen = dirdata->current_frag_id = dirdata->current_frag_bytes = 0;
2294 if (pinfo->desegment_len) {
2295 /* there's a bit of data left to desegment */
2296 must_desegment = TRUE;
2297 /* make desegment_offset relative to our tvb */
2298 pinfo->desegment_offset -= old_len;
2301 /* don't add a 'reassembled in' item for this pdu */
2306 /* This segment was not found in our table, so it doesn't
2307 contain a continuation of a higher-level PDU.
2308 Call the normal subdissector.
2311 process_iax_pdu(tvb, pinfo, tree, video, iax_packet);
2313 if (pinfo->desegment_len) {
2314 /* the higher-level dissector has asked for some more data - ie,
2315 the end of this segment does not coincide with the end of a
2316 higher-level PDU. */
2317 must_desegment = TRUE;
2323 /* must_desegment is set if the end of this segment (or the whole of it)
2324 * contained the start of a higher-level PDU; we must add whatever is left of
2325 * this segment (after pinfo->desegment_offset) to a fragment table for disassembly. */
2326 if (must_desegment) {
2327 guint32 fid = pinfo->fd->num; /* a new fragment id */
2328 guint32 deseg_offset = pinfo->desegment_offset;
2329 guint32 frag_len = tvb_reported_length_remaining(tvb, deseg_offset);
2330 dirdata->current_frag_id = fid;
2331 dirdata->current_frag_bytes = frag_len;
2333 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
2334 /* only one more byte should be enough for a retry */
2335 dirdata->current_frag_minlen = frag_len + 1;
2337 dirdata->current_frag_minlen = frag_len + pinfo->desegment_len;
2340 fd_head = fragment_add(&iax_reassembly_table,
2341 tvb, deseg_offset, pinfo, fid, NULL,
2343 #ifdef DEBUG_DESEGMENT
2344 g_debug("Start offset of undissected bytes: %u; "
2345 "Bytes remaining in this segment: %u; min required bytes: %u\n",
2346 deseg_offset, frag_len, frag_len + pinfo->desegment_len);
2350 /* add a 'reassembled in' item if necessary */
2351 if (fd_head != NULL) {
2352 guint32 deseg_offset = pinfo->desegment_offset;
2353 if (fd_head->reassembled_in != 0 &&
2354 !(fd_head->flags & FD_PARTIAL_REASSEMBLY)) {
2355 proto_item *iax_tree_item;
2356 iax_tree_item = proto_tree_add_uint(tree, hf_iax2_reassembled_in,
2357 tvb, deseg_offset, tvb_reported_length_remaining(tvb, deseg_offset),
2358 fd_head->reassembled_in);
2359 PROTO_ITEM_SET_GENERATED(iax_tree_item);
2361 /* this fragment is never reassembled */
2362 proto_tree_add_text(tree, tvb, deseg_offset, -1,
2363 "IAX2 fragment, unfinished");
2366 if (pinfo->desegment_offset == 0) {
2367 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAX2");
2368 col_set_str(pinfo->cinfo, COL_INFO, "[IAX2 segment of a reassembled PDU]");
2372 pinfo->can_desegment = 0;
2373 pinfo->desegment_offset = 0;
2374 pinfo->desegment_len = 0;
2377 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
2378 packet_info *pinfo, proto_tree *iax2_tree,
2379 proto_tree *tree, guint32 ts _U_, gboolean video,
2380 iax_packet_data *iax_packet)
2383 gboolean out_of_order = FALSE;
2386 guint32 codec = iax_packet -> codec;
2388 iax_call_data *iax_call = iax_packet -> call_data;
2390 if (offset >= tvb_reported_length(tvb)) {
2391 col_append_str(pinfo->cinfo, COL_INFO, ", empty frame");
2395 sub_tvb = tvb_new_subset_remaining(tvb, offset);
2397 /* XXX shouldn't pass through out-of-order packets. */
2399 if (!video && iax_call && iax_call -> dataformat != 0) {
2400 col_append_fstr(pinfo->cinfo, COL_INFO, ", data, format %s",
2401 val_to_str(iax_call -> dataformat,
2402 iax_dataformats, "unknown (0x%02x)"));
2405 col_append_str(pinfo->cinfo, COL_INFO, " (out-of-order packet)");
2408 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
2409 val_to_str_ext(codec, &codec_types_ext, "unknown (0x%02x)"));
2412 nbytes = tvb_reported_length(sub_tvb);
2413 proto_tree_add_text(iax2_tree, sub_tvb, 0, -1,
2414 "IAX2 payload (%u byte%s)", nbytes,
2415 plurality(nbytes, "", "s"));
2417 iax2_info->payload_len = nbytes;
2418 iax2_info->payload_data = tvb_get_ptr(sub_tvb, 0, -1);
2420 /* pass the rest of the block to a subdissector */
2421 if (iax_packet->call_data)
2422 desegment_iax(sub_tvb, pinfo, iax2_tree, tree, video, iax_packet);
2424 process_iax_pdu(sub_tvb, pinfo, tree, video, iax_packet);
2431 /* called at the start of a capture. We should clear out our static, per-capture
2436 iax_init_protocol(void)
2443 proto_register_iax2(void)
2445 /* A header field is something you can search/filter on.
2447 * We create a structure to register our fields. It consists of an
2448 * array of hf_register_info structures, each of which are of the format
2449 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
2452 static hf_register_info hf[] = {
2454 {&hf_iax2_packet_type,
2455 {"Packet type", "iax2.packet_type",
2456 FT_UINT8, BASE_DEC, VALS(iax_packet_types), 0,
2457 "Full/minivoice/minivideo/trunk packet",
2461 {"Call identifier", "iax2.call",
2462 FT_UINT32, BASE_DEC, NULL, 0,
2463 "This is the identifier Wireshark assigns to identify this call."
2464 " It does not correspond to any real field in the protocol",
2468 {"Source call", "iax2.src_call",
2469 FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2470 "src_call holds the number of this call at the packet source pbx",
2473 /* FIXME could this be turned into a FRAMENUM field? */
2475 {"Destination call", "iax2.dst_call",
2476 FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2477 "dst_call holds the number of this call at the packet destination",
2480 {&hf_iax2_retransmission,
2481 {"Retransmission", "iax2.retransmission",
2482 FT_BOOLEAN, 16, NULL, 0x8000,
2483 "retransmission is set if this packet is a retransmission of an earlier failed packet",
2487 {"Timestamp", "iax2.timestamp",
2488 FT_UINT32, BASE_DEC, NULL, 0x0,
2489 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2493 {"Timestamp", "iax2.timestamp",
2494 FT_UINT16, BASE_DEC, NULL, 0x0,
2495 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2498 {&hf_iax2_minividts,
2499 {"Timestamp", "iax2.timestamp",
2500 FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2501 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2505 {"Absolute Time", "iax2.abstime",
2506 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2507 "The absolute time of this packet (calculated by adding the IAX timestamp to the start time of this call)",
2511 {"Lateness", "iax2.lateness",
2512 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2513 "The lateness of this packet compared to its timestamp",
2516 {&hf_iax2_minividmarker,
2517 {"Marker", "iax2.video.marker",
2518 FT_UINT16, BASE_DEC, NULL, 0x8000,
2519 "RTP end-of-frame marker",
2523 {"Outbound seq.no.", "iax2.oseqno",
2524 FT_UINT16, BASE_DEC, NULL, 0x0,
2525 "oseqno is the sequence no of this packet. The first packet has oseqno==0,"
2526 " and subsequent packets increment the oseqno by 1",
2530 {"Inbound seq.no.", "iax2.iseqno",
2531 FT_UINT16, BASE_DEC, NULL, 0x0,
2532 "iseqno is the sequence no of the last successfully received packet",
2536 {"Type", "iax2.type",
2537 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &iax_frame_types_ext, 0x0,
2538 "For full IAX2 frames, type is the type of frame",
2542 {"Unknown subclass", "iax2.subclass",
2543 FT_UINT8, BASE_DEC, NULL, 0x0,
2544 "Subclass of unknown type of full IAX2 frame",
2547 {&hf_iax2_dtmf_csub,
2548 {"DTMF subclass (digit)", "iax2.dtmf.subclass",
2549 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2550 "DTMF subclass gives the DTMF digit",
2554 {"Control subclass", "iax2.control.subclass",
2555 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &iax_cmd_subclasses_ext, 0x0,
2556 "This gives the command number for a Control packet.",
2560 {"IAX subclass", "iax2.iax.subclass",
2561 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &iax_iax_subclasses_ext, 0x0,
2562 "IAX subclass gives the command number for IAX signaling packets",
2565 {&hf_iax2_voice_csub,
2566 {"Voice Subclass (compressed codec no)", "iax2.voice.subclass",
2567 FT_UINT8, BASE_DEC, NULL, 0x0,
2570 {&hf_iax2_voice_codec,
2571 {"CODEC", "iax2.voice.codec",
2572 FT_UINT32, BASE_HEX | BASE_EXT_STRING, &codec_types_ext, 0x0,
2573 "CODEC gives the codec used to encode audio data",
2576 {&hf_iax2_video_csub,
2577 {"Video Subclass (compressed codec no)", "iax2.video.subclass",
2578 FT_UINT8, BASE_DEC, NULL, 0xBF,
2582 {"Marker", "iax2.video.marker",
2583 FT_BOOLEAN, 8, NULL, 0x40,
2584 "RTP end-of-frame marker",
2587 {&hf_iax2_video_codec,
2588 {"CODEC", "iax2.video.codec",
2589 FT_UINT32, BASE_HEX | BASE_EXT_STRING, &codec_types_ext, 0,
2590 "The codec used to encode video data",
2593 {&hf_iax2_modem_csub,
2594 {"Modem subclass", "iax2.modem.subclass",
2595 FT_UINT8, BASE_DEC, VALS(iax_modem_subclasses), 0x0,
2596 "Modem subclass gives the type of modem",
2599 {&hf_iax2_text_csub,
2600 {"Text subclass", "iax2.text.subclass",
2601 FT_UINT8, BASE_DEC, VALS(iax_text_subclasses), 0x0,
2605 {&hf_iax2_text_text,
2606 {"Text", "iax2.text.text",
2607 FT_STRING, BASE_NONE, NULL, 0x0,
2611 {&hf_iax2_html_csub,
2612 {"HTML subclass", "iax2.html.subclass",
2613 FT_UINT8, BASE_DEC, VALS(iax_html_subclasses), 0x0,
2618 {"HTML URL", "iax2.html.url",
2619 FT_STRING, BASE_NONE, NULL, 0x0,
2624 {"Timestamp", "iax2.timestamp",
2625 FT_UINT32, BASE_DEC, NULL, 0x0,
2626 "timestamp is the time, in ms after the start of Command data this call,"
2627 " at which this trunk packet was transmitted",
2630 {&hf_iax2_trunk_metacmd,
2631 {"Meta command", "iax2.trunk.metacmd",
2632 FT_UINT8, BASE_DEC, NULL, 0x7F,
2633 "Meta command indicates whether or not the Meta Frame is a trunk.",
2636 {&hf_iax2_trunk_cmddata,
2637 {"Command data", "iax2.trunk.cmddata",
2638 FT_UINT8, BASE_HEX, NULL, 0x0,
2639 "Flags for options that apply to a trunked call",
2642 {&hf_iax2_trunk_cmddata_ts,
2643 {"Trunk timestamps", "iax2.trunk.cmddata.ts",
2644 FT_BOOLEAN, 8, NULL, IAX2_TRUNK_TS,
2645 "True: calls do each include their own timestamp",
2648 {&hf_iax2_trunk_call_len,
2649 {"Data length", "iax2.trunk.call.len",
2650 FT_UINT16, BASE_DEC, NULL, 0x0,
2651 "Trunk call data length in octets",
2654 {&hf_iax2_trunk_call_scallno,
2655 {"Source call number", "iax2.trunk.call.scallno",
2656 FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2657 "Trunk call source call number",
2660 {&hf_iax2_trunk_call_ts,
2661 {"Timestamp", "iax2.trunk.call.ts",
2662 FT_UINT16, BASE_DEC, NULL, 0x0,
2663 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2666 {&hf_iax2_trunk_call_data,
2667 {"Data", "iax2.trunk.call.payload",
2668 FT_BYTES, BASE_NONE, NULL, 0x0,
2669 "Payload carried by this trunked packet.",
2672 {&hf_iax2_trunk_ncalls,
2673 {"Number of calls", "iax2.trunk.ncalls",
2674 FT_UINT16, BASE_DEC, NULL, 0x0,
2675 "Number of calls in this trunk packet",
2679 * Decoding for the ies
2682 {&hf_IAX_IE_APPARENTADDR_SINFAMILY,
2683 {"Family", "iax2.iax.app_addr.sinfamily",
2684 FT_UINT16, BASE_DEC, NULL, 0,
2687 {&hf_IAX_IE_APPARENTADDR_SINPORT,
2688 {"Port", "iax2.iax.app_addr.sinport",
2689 FT_UINT16, BASE_DEC, NULL, 0,
2692 {&hf_IAX_IE_APPARENTADDR_SINADDR,
2693 {"Address", "iax2.iax.app_addr.sinaddr",
2694 FT_IPv4, BASE_NONE, NULL, 0,
2697 {&hf_iax2_ies[IAX_IE_CALLED_NUMBER],
2698 {"Number/extension being called", "iax2.iax.called_number",
2700 BASE_NONE, NULL, 0x0, NULL, HFILL}},
2702 {&hf_iax2_ies[IAX_IE_CALLING_NUMBER],
2703 {"Calling number", "iax2.iax.calling_number",
2704 FT_STRING, BASE_NONE, NULL, 0x0,
2708 {&hf_iax2_ies[IAX_IE_CALLING_ANI],
2709 {"Calling number ANI for billing", "iax2.iax.calling_ani",
2710 FT_STRING, BASE_NONE, NULL, 0x0,
2713 {&hf_iax2_ies[IAX_IE_CALLING_NAME],
2714 {"Name of caller", "iax2.iax.calling_name",
2715 FT_STRING, BASE_NONE, NULL, 0x0,
2718 {&hf_iax2_ies[IAX_IE_CALLED_CONTEXT],
2719 {"Context for number", "iax2.iax.called_context",
2720 FT_STRING, BASE_NONE, NULL, 0x0,
2723 {&hf_iax2_ies[IAX_IE_USERNAME],
2724 {"Username (peer or user) for authentication", "iax2.iax.username",
2725 FT_STRING, BASE_NONE, NULL, 0x0,
2728 {&hf_iax2_ies[IAX_IE_PASSWORD],
2729 {"Password for authentication", "iax2.iax.password",
2730 FT_STRING, BASE_NONE, NULL, 0x0,
2733 {&hf_iax2_ies[IAX_IE_CAPABILITY],
2734 {"Actual codec capability", "iax2.iax.capability",
2735 FT_UINT32, BASE_HEX, NULL, 0x0,
2738 {&hf_iax2_ies[IAX_IE_FORMAT],
2739 {"Desired codec format", "iax2.iax.format",
2740 FT_UINT32, BASE_HEX | BASE_EXT_STRING, &codec_types_ext, 0x0,
2743 {&hf_iax2_ies[IAX_IE_LANGUAGE],
2744 {"Desired language", "iax2.iax.language",
2745 FT_STRING, BASE_NONE, NULL, 0x0,
2748 {&hf_iax2_ies[IAX_IE_VERSION],
2749 {"Protocol version", "iax2.iax.version",
2750 FT_UINT16, BASE_HEX, NULL, 0x0,
2753 {&hf_iax2_ies[IAX_IE_ADSICPE],
2754 {"CPE ADSI capability", "iax2.iax.cpe_adsi",
2755 FT_UINT16, BASE_HEX, NULL, 0x0,
2758 {&hf_iax2_ies[IAX_IE_DNID],
2759 {"Originally dialed DNID", "iax2.iax.dnid",
2760 FT_STRING, BASE_NONE, NULL, 0x0,
2763 {&hf_iax2_ies[IAX_IE_AUTHMETHODS],
2764 {"Authentication method(s)", "iax2.iax.auth.methods",
2765 FT_UINT16, BASE_HEX, NULL, 0x0,
2768 {&hf_iax2_ies[IAX_IE_CHALLENGE],
2769 {"Challenge data for MD5/RSA", "iax2.iax.auth.challenge",
2770 FT_STRING, BASE_NONE, NULL, 0x0,
2773 {&hf_iax2_ies[IAX_IE_MD5_RESULT],
2774 {"MD5 challenge result", "iax2.iax.auth.md5",
2775 FT_STRING, BASE_NONE, NULL, 0x0,
2778 {&hf_iax2_ies[IAX_IE_RSA_RESULT],
2779 {"RSA challenge result", "iax2.iax.auth.rsa",
2780 FT_STRING, BASE_NONE, NULL, 0x0,
2783 {&hf_iax2_ies[IAX_IE_REFRESH],
2784 {"When to refresh registration", "iax2.iax.refresh",
2785 FT_INT16, BASE_DEC, NULL, 0x0,
2788 {&hf_iax2_ies[IAX_IE_DPSTATUS],
2789 {"Dialplan status", "iax2.iax.dialplan_status",
2790 FT_UINT16, BASE_HEX, NULL, 0x0,
2793 {&hf_iax2_ies[IAX_IE_CALLNO],
2794 {"Call number of peer", "iax2.iax.call_no",
2795 FT_UINT16, BASE_DEC, NULL, 0x0,
2798 {&hf_iax2_ies[IAX_IE_CAUSE],
2799 {"Cause", "iax2.iax.cause",
2800 FT_STRING, BASE_NONE, NULL, 0x0,
2803 {&hf_iax2_ies[IAX_IE_IAX_UNKNOWN],
2804 {"Unknown IAX command", "iax2.iax.iax_unknown",
2805 FT_BYTES, BASE_NONE, NULL, 0x0,
2808 {&hf_iax2_ies[IAX_IE_MSGCOUNT],
2809 {"How many messages waiting", "iax2.iax.msg_count",
2810 FT_INT16, BASE_DEC, NULL, 0x0,
2813 {&hf_iax2_ies[IAX_IE_AUTOANSWER],
2814 {"Request auto-answering", "iax2.iax.autoanswer",
2815 FT_NONE, BASE_NONE, NULL, 0x0,
2818 {&hf_iax2_ies[IAX_IE_MUSICONHOLD],
2819 {"Request musiconhold with QUELCH", "iax2.iax.moh",
2820 FT_NONE, BASE_NONE, NULL, 0x0,
2823 {&hf_iax2_ies[IAX_IE_TRANSFERID],
2824 {"Transfer Request Identifier", "iax2.iax.transferid",
2825 FT_UINT32, BASE_HEX, NULL, 0x0,
2828 {&hf_iax2_ies[IAX_IE_RDNIS],
2829 {"Referring DNIS", "iax2.iax.rdnis",
2830 FT_STRING, BASE_NONE, NULL, 0x0,
2833 {&hf_iax2_ies[IAX_IE_PROVISIONING],
2834 {"Provisioning info", "iax2.iax.provisioning",
2835 FT_STRING, BASE_NONE, NULL, 0x0,
2838 {&hf_iax2_ies[IAX_IE_AESPROVISIONING],
2839 {"AES Provisioning info", "iax2.iax.aesprovisioning",
2840 FT_STRING, BASE_NONE, NULL, 0x0,
2843 {&hf_iax2_ies[IAX_IE_DATETIME],
2844 {"Date/Time", "iax2.iax.datetime.raw",
2845 FT_UINT32, BASE_DEC, NULL, 0x0,
2848 {&hf_iax2_ie_datetime,
2849 {"Date/Time", "iax2.iax.datetime",
2850 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2853 {&hf_iax2_ies[IAX_IE_DEVICETYPE],
2854 {"Device type", "iax2.iax.devicetype",
2855 FT_STRING, BASE_NONE, NULL, 0x0,
2858 {&hf_iax2_ies[IAX_IE_SERVICEIDENT],
2859 {"Service identifier", "iax2.iax.serviceident",
2860 FT_STRING, BASE_NONE, NULL, 0x0,
2863 {&hf_iax2_ies[IAX_IE_FIRMWAREVER],
2864 {"Firmware version", "iax2.iax.firmwarever",
2865 FT_UINT16, BASE_HEX, NULL, 0x0,
2868 {&hf_iax2_ies[IAX_IE_FWBLOCKDESC],
2869 {"Firmware block description", "iax2.iax.fwblockdesc",
2870 FT_UINT32, BASE_HEX, NULL, 0x0,
2873 {&hf_iax2_ies[IAX_IE_FWBLOCKDATA],
2874 {"Firmware block of data", "iax2.iax.fwblockdata",
2875 FT_STRING, BASE_NONE, NULL, 0x0,
2878 {&hf_iax2_ies[IAX_IE_PROVVER],
2879 {"Provisioning version", "iax2.iax.provver",
2880 FT_UINT32, BASE_HEX, NULL, 0x0,
2883 {&hf_iax2_ies[IAX_IE_CALLINGPRES],
2884 {"Calling presentation", "iax2.iax.callingpres",
2885 FT_UINT8, BASE_HEX, NULL, 0x0,
2888 {&hf_iax2_ies[IAX_IE_CALLINGTON],
2889 {"Calling type of number", "iax2.iax.callington",
2890 FT_UINT8, BASE_HEX, NULL, 0x0,
2893 {&hf_iax2_ies[IAX_IE_CALLINGTNS],
2894 {"Calling transit network select", "iax2.iax.callingtns",
2895 FT_UINT16, BASE_HEX, NULL, 0x0,
2898 {&hf_iax2_ies[IAX_IE_SAMPLINGRATE],
2899 {"Supported sampling rates", "iax2.iax.samplingrate",
2900 FT_UINT16, BASE_HEX, NULL, 0x0,
2903 {&hf_iax2_ies[IAX_IE_CAUSECODE],
2904 {"Hangup cause", "iax2.iax.causecode",
2905 FT_UINT8, BASE_HEX | BASE_EXT_STRING, &iax_causecodes_ext, 0x0,
2908 {&hf_iax2_ies[IAX_IE_ENCRYPTION],
2909 {"Encryption format", "iax2.iax.encryption",
2910 FT_UINT16, BASE_HEX, NULL, 0x0,
2913 {&hf_iax2_ies[IAX_IE_ENCKEY],
2914 {"Encryption key", "iax2.iax.enckey",
2915 FT_STRING, BASE_NONE, NULL, 0x0,
2918 {&hf_iax2_ies[IAX_IE_CODEC_PREFS],
2919 {"Codec negotiation", "iax2.iax.codecprefs",
2920 FT_STRING, BASE_NONE, NULL, 0x0,
2923 {&hf_iax2_ies[IAX_IE_RR_JITTER],
2924 {"Received jitter (as in RFC1889)", "iax2.iax.rrjitter",
2925 FT_UINT32, BASE_HEX, NULL, 0x0,
2928 {&hf_iax2_ies[IAX_IE_RR_LOSS],
2929 {"Received loss (high byte loss pct, low 24 bits loss count, as in rfc1889)", "iax2.iax.rrloss",
2930 FT_UINT32, BASE_HEX, NULL, 0x0,
2933 {&hf_iax2_ies[IAX_IE_RR_PKTS],
2934 {"Total frames received", "iax2.iax.rrpkts",
2935 FT_UINT32, BASE_HEX, NULL, 0x0,
2938 {&hf_iax2_ies[IAX_IE_RR_DELAY],
2939 {"Max playout delay in ms for received frames", "iax2.iax.rrdelay",
2940 FT_UINT16, BASE_HEX, NULL, 0x0,
2943 {&hf_iax2_ies[IAX_IE_RR_DROPPED],
2944 {"Dropped frames (presumably by jitterbuffer)", "iax2.iax.rrdropped",
2945 FT_UINT32, BASE_HEX, NULL, 0x0,
2948 {&hf_iax2_ies[IAX_IE_RR_OOO],
2949 {"Frame received out of order", "iax2.iax.rrooo",
2950 FT_UINT32, BASE_HEX, NULL, 0x0,
2953 {&hf_iax2_ies[IAX_IE_DATAFORMAT],
2954 {"Data call format", "iax2.iax.dataformat",
2955 FT_UINT32, BASE_HEX, VALS(iax_dataformats), 0x0,
2958 {&hf_IAX_IE_UNKNOWN_BYTE,
2959 {"Unknown", "iax2.iax.unknownbyte",
2960 FT_UINT8, BASE_HEX, NULL, 0x0,
2961 "Raw data for unknown IEs", HFILL}},
2963 {&hf_IAX_IE_UNKNOWN_I16,
2964 {"Unknown", "iax2.iax.unknownshort",
2965 FT_UINT16, BASE_HEX, NULL, 0x0,
2966 "Raw data for unknown IEs", HFILL}},
2968 {&hf_IAX_IE_UNKNOWN_I32,
2969 {"Unknown", "iax2.iax.unknownlong",
2970 FT_UINT32, BASE_HEX, NULL, 0x0,
2971 "Raw data for unknown IEs", HFILL}},
2973 {&hf_IAX_IE_UNKNOWN_BYTES,
2974 {"Unknown", "iax2.iax.unknownstring",
2975 FT_STRING, BASE_NONE, NULL, 0x0,
2976 "Raw data for unknown IEs", HFILL}},
2979 {&hf_iax2_cap_g723_1,
2980 {"G.723.1 compression", "iax2.cap.g723_1",
2981 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_G723_1,
2985 {"GSM compression", "iax2.cap.gsm",
2986 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_GSM,
2990 {"Raw mu-law data (G.711)", "iax2.cap.ulaw",
2991 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_ULAW,
2995 {"Raw A-law data (G.711)", "iax2.cap.alaw",
2996 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_ALAW,
2999 {&hf_iax2_cap_g726_aal2,
3000 {"G.726 compression (AAL2 packing)", "iax2.cap.g726_aal2",
3001 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_G726_AAL2,
3004 {&hf_iax2_cap_adpcm,
3005 {"ADPCM", "iax2.cap.adpcm",
3006 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_ADPCM,
3009 {&hf_iax2_cap_slinear,
3010 {"Raw 16-bit Signed Linear (8000 Hz) PCM", "iax2.cap.slinear",
3011 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_SLINEAR,
3014 {&hf_iax2_cap_lpc10,
3015 {"LPC10, 180 samples/frame",
3016 "iax2.cap.lpc10", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported),
3017 AST_FORMAT_LPC10, NULL, HFILL }},
3019 {&hf_iax2_cap_g729a,
3020 {"G.729a Audio", "iax2.cap.g729a",
3021 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_G729A,
3024 {&hf_iax2_cap_speex,
3025 {"SPEEX Audio", "iax2.cap.speex",
3026 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_SPEEX,
3030 {"iLBC Free compressed Audio", "iax2.cap.ilbc",
3031 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_ILBC,
3035 {"ADPCM (G.726, 32kbps, RFC3551 codeword packing)", "iax2.cap.g726",
3036 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_G726,
3040 {"G.722 wideband audio", "iax2.cap.g722",
3041 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_G722,
3044 {&hf_iax2_cap_siren7,
3045 {"G.722.1 (also known as Siren7, 32kbps assumed)", "iax2.cap.siren7",
3046 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_SIREN7,
3049 {&hf_iax2_cap_siren14,
3050 {"G.722.1 Annex C (also known as Siren14, 48kbps assumed)", "iax2.cap.siren14",
3051 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_SIREN14,
3054 {&hf_iax2_cap_slinear16,
3055 {"Raw 16-bit Signed Linear (16000 Hz) PCM", "iax2.cap.slinear16",
3056 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_SLINEAR16,
3060 {"JPEG images", "iax2.cap.jpeg",
3061 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_JPEG,
3065 {"PNG images", "iax2.cap.png",
3066 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_PNG,
3070 {"H.261 video", "iax2.cap.h261",
3071 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_H261,
3075 {"H.263 video", "iax2.cap.h263",
3076 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_H263,
3079 {&hf_iax2_cap_h263_plus,
3080 {"H.263+ video", "iax2.cap.h263_plus",
3081 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_H263_PLUS,
3085 {"H.264 video", "iax2.cap.h264",
3086 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_H264,
3089 {&hf_iax2_cap_mpeg4,
3090 {"MPEG4 video", "iax2.cap.mpeg4",
3091 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_MP4_VIDEO,
3094 /* reassembly stuff */
3095 {&hf_iax2_fragments,
3096 {"IAX2 Fragments", "iax2.fragments",
3097 FT_NONE, BASE_NONE, NULL, 0x0,
3101 {"IAX2 Fragment data", "iax2.fragment",
3102 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3105 {&hf_iax2_fragment_overlap,
3106 {"Fragment overlap", "iax2.fragment.overlap",
3107 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3108 "Fragment overlaps with other fragments", HFILL }},
3110 {&hf_iax2_fragment_overlap_conflict,
3111 {"Conflicting data in fragment overlap", "iax2.fragment.overlap.conflict",
3112 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3113 "Overlapping fragments contained conflicting data", HFILL }},
3115 {&hf_iax2_fragment_multiple_tails,
3116 {"Multiple tail fragments found", "iax2.fragment.multipletails",
3117 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3118 "Several tails were found when defragmenting the packet", HFILL }},
3120 {&hf_iax2_fragment_too_long_fragment,
3121 {"Fragment too long", "iax2.fragment.toolongfragment",
3122 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3123 "Fragment contained data past end of packet", HFILL }},
3125 {&hf_iax2_fragment_error,
3126 {"Defragmentation error", "iax2.fragment.error",
3127 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3128 "Defragmentation error due to illegal fragments", HFILL }},
3130 {&hf_iax2_fragment_count,
3131 {"Fragment count", "iax2.fragment.count",
3132 FT_UINT32, BASE_DEC, NULL, 0x0,
3135 {&hf_iax2_reassembled_in,
3136 {"IAX2 fragment, reassembled in frame", "iax2.reassembled_in",
3137 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3138 "This IAX2 packet is reassembled in this frame", HFILL }},
3140 {&hf_iax2_reassembled_length,
3141 {"Reassembled IAX2 length", "iax2.reassembled.length",
3142 FT_UINT32, BASE_DEC, NULL, 0x0,
3143 "The total length of the reassembled payload", HFILL }}
3146 static gint *ett[] = {
3148 &ett_iax2_full_mini_subtree,
3152 &ett_iax2_ies_apparent_addr,
3154 &ett_iax2_fragments,
3155 &ett_iax2_trunk_cmddata,
3156 &ett_iax2_trunk_call
3159 static ei_register_info ei[] = {
3160 { &ei_iax_too_many_transfers, { "iax2.too_many_transfers", PI_PROTOCOL, PI_WARN, "Too many transfers for iax_call", EXPFILL }},
3161 { &ei_iax_circuit_id_conflict, { "iax2.circuit_id_conflict", PI_PROTOCOL, PI_WARN, "Circuit ID conflict", EXPFILL }},
3162 { &ei_iax_peer_address_unsupported, { "iax2.peer_address_unsupported", PI_PROTOCOL, PI_WARN, "Peer address unsupported", EXPFILL }},
3165 expert_module_t* expert_iax;
3167 /* initialize the hf_iax2_ies[] array to -1 */
3168 memset(hf_iax2_ies, 0xff, sizeof(hf_iax2_ies));
3171 proto_register_protocol("Inter-Asterisk eXchange v2", "IAX2", "iax2");
3172 proto_register_field_array(proto_iax2, hf, array_length(hf));
3173 proto_register_subtree_array(ett, array_length(ett));
3174 expert_iax = expert_register_protocol(proto_iax2);
3175 expert_register_field_array(expert_iax, ei, array_length(ei));
3177 register_dissector("iax2", dissect_iax2, proto_iax2);
3179 iax2_codec_dissector_table = register_dissector_table(
3180 "iax2.codec", "IAX codec number", FT_UINT32, BASE_HEX);
3181 iax2_dataformat_dissector_table = register_dissector_table(
3182 "iax2.dataformat", "IAX dataformat number", FT_UINT32, BASE_HEX);
3184 /* register our init routine to be called at the start of a capture,
3185 to clear out our hash tables etc */
3186 register_init_routine(&iax_init_protocol);
3187 iax2_tap = register_tap("IAX2");
3191 proto_reg_handoff_iax2(void)
3193 dissector_handle_t v110_handle;
3195 dissector_add_uint("udp.port", IAX2_PORT, find_dissector("iax2"));
3196 v110_handle = find_dissector("v110");
3198 dissector_add_uint("iax2.dataformat", AST_DATAFORMAT_V110, v110_handle);
3199 data_handle = find_dissector("data");
3208 * indent-tabs-mode: nil
3211 * ex: set shiftwidth=2 tabstop=8 expandtab:
3212 * :indentSize=2:tabSize=8:noTabs=true: