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
14 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
41 #include <epan/circuit.h>
42 #include <epan/packet.h>
43 #include <epan/to_str.h>
44 #include <epan/emem.h>
45 #include <epan/reassemble.h>
46 #include <epan/aftypes.h>
48 #include <epan/tap-voip.h>
50 #include "packet-iax2.h"
51 #include <epan/iax2_codec_type.h>
53 #define IAX2_PORT 4569
54 #define PROTO_TAG_IAX2 "IAX2"
56 /* enough to hold any address in an address_t */
57 #define MAX_ADDRESS 16
59 /* the maximum number of transfers (of each end) we can deal with per call,
61 #define IAX_MAX_TRANSFERS 2
63 /* #define DEBUG_HASHING */
64 /* #define DEBUG_DESEGMENT */
66 /* Wireshark ID of the IAX2 protocol */
67 static int proto_iax2 = -1;
70 static int iax2_tap = -1;
72 /* protocol tap info */
73 static iax2_info_t ii_arr[1];
74 static iax2_info_t *iax2_info = ii_arr;
76 /* The following hf_* variables are used to hold the wireshark IDs of
77 * our header fields; they are filled out when we call
78 * proto_register_field_array() in proto_register_iax2()
80 static int hf_iax2_packet_type = -1;
81 static int hf_iax2_retransmission = -1;
82 static int hf_iax2_callno = -1;
83 static int hf_iax2_scallno = -1;
84 static int hf_iax2_dcallno = -1;
85 static int hf_iax2_ts = -1;
86 static int hf_iax2_minits = -1;
87 static int hf_iax2_minividts = -1;
88 static int hf_iax2_absts = -1;
89 static int hf_iax2_lateness = -1;
90 static int hf_iax2_minividmarker = -1;
91 static int hf_iax2_oseqno = -1;
92 static int hf_iax2_iseqno = -1;
93 static int hf_iax2_type = -1;
94 static int hf_iax2_csub = -1;
95 static int hf_iax2_dtmf_csub = -1;
96 static int hf_iax2_cmd_csub = -1;
97 static int hf_iax2_iax_csub = -1;
98 static int hf_iax2_voice_csub = -1;
99 static int hf_iax2_voice_codec = -1;
100 static int hf_iax2_video_csub = -1;
101 static int hf_iax2_video_codec = -1;
102 static int hf_iax2_marker = -1;
103 static int hf_iax2_modem_csub = -1;
104 static int hf_iax2_trunk_metacmd = -1;
105 static int hf_iax2_trunk_cmddata = -1;
106 static int hf_iax2_trunk_cmddata_ts = -1;
107 static int hf_iax2_trunk_ts = -1;
108 static int hf_iax2_trunk_ncalls = -1;
109 static int hf_iax2_trunk_call_len = -1;
110 static int hf_iax2_trunk_call_scallno = -1;
111 static int hf_iax2_trunk_call_ts = -1;
112 static int hf_iax2_trunk_call_data = -1;
114 static int hf_iax2_cap_g723_1 = -1;
115 static int hf_iax2_cap_gsm = -1;
116 static int hf_iax2_cap_ulaw = -1;
117 static int hf_iax2_cap_alaw = -1;
118 static int hf_iax2_cap_g726_aal2 = -1;
119 static int hf_iax2_cap_adpcm = -1;
120 static int hf_iax2_cap_slinear = -1;
121 static int hf_iax2_cap_lpc10 = -1;
122 static int hf_iax2_cap_g729a = -1;
123 static int hf_iax2_cap_speex = -1;
124 static int hf_iax2_cap_ilbc = -1;
125 static int hf_iax2_cap_g726 = -1;
126 static int hf_iax2_cap_g722 = -1;
127 static int hf_iax2_cap_siren7 = -1;
128 static int hf_iax2_cap_siren14 = -1;
129 static int hf_iax2_cap_slinear16 = -1;
130 static int hf_iax2_cap_jpeg = -1;
131 static int hf_iax2_cap_png = -1;
132 static int hf_iax2_cap_h261 = -1;
133 static int hf_iax2_cap_h263 = -1;
134 static int hf_iax2_cap_h263_plus = -1;
135 static int hf_iax2_cap_h264 = -1;
136 static int hf_iax2_cap_mpeg4 = -1;
138 static int hf_iax2_fragments = -1;
139 static int hf_iax2_fragment = -1;
140 static int hf_iax2_fragment_overlap = -1;
141 static int hf_iax2_fragment_overlap_conflict = -1;
142 static int hf_iax2_fragment_multiple_tails = -1;
143 static int hf_iax2_fragment_too_long_fragment = -1;
144 static int hf_iax2_fragment_error = -1;
145 static int hf_iax2_fragment_count = -1;
146 static int hf_iax2_reassembled_in = -1;
147 static int hf_iax2_reassembled_length = -1;
150 /* hf_iax2_ies is an array of header fields, one per potential Information
151 * Element. It's done this way (rather than having separate variables for each
152 * IE) to make the dissection of information elements clearer and more
155 * To add the ability to dissect a new information element, just add an
156 * appropriate entry to hf[] in proto_register_iax2(); dissect_ies() will then
157 * pick it up automatically.
159 #define NUM_HF_IAX2_IES 256
160 static int hf_iax2_ies[NUM_HF_IAX2_IES];
161 static int hf_iax2_ie_datetime = -1;
162 static int hf_IAX_IE_APPARENTADDR_SINFAMILY = -1;
163 static int hf_IAX_IE_APPARENTADDR_SINPORT = -1;
164 static int hf_IAX_IE_APPARENTADDR_SINADDR = -1;
165 static int hf_IAX_IE_UNKNOWN_BYTE = -1;
166 static int hf_IAX_IE_UNKNOWN_I16 = -1;
167 static int hf_IAX_IE_UNKNOWN_I32 = -1;
168 static int hf_IAX_IE_UNKNOWN_BYTES = -1;
170 /* These are the ids of the subtrees that we may be creating */
171 static gint ett_iax2 = -1;
172 static gint ett_iax2_full_mini_subtree = -1;
173 static gint ett_iax2_type = -1; /* Frame-type specific subtree */
174 static gint ett_iax2_ie = -1; /* single IE */
175 static gint ett_iax2_codecs = -1; /* capabilities IE */
176 static gint ett_iax2_ies_apparent_addr = -1; /* apparent address IE */
177 static gint ett_iax2_fragment = -1;
178 static gint ett_iax2_fragments = -1;
179 static gint ett_iax2_trunk_cmddata = -1;
180 static gint ett_iax2_trunk_call = -1;
182 static const fragment_items iax2_fragment_items = {
187 &hf_iax2_fragment_overlap,
188 &hf_iax2_fragment_overlap_conflict,
189 &hf_iax2_fragment_multiple_tails,
190 &hf_iax2_fragment_too_long_fragment,
191 &hf_iax2_fragment_error,
192 &hf_iax2_fragment_count,
193 &hf_iax2_reassembled_in,
194 &hf_iax2_reassembled_length,
198 static dissector_handle_t data_handle;
200 /* data-call subdissectors, AST_DATAFORMAT_* */
201 static dissector_table_t iax2_dataformat_dissector_table;
202 /* voice/video call subdissectors, AST_FORMAT_* */
203 static dissector_table_t iax2_codec_dissector_table;
206 /* IAX2 Meta trunk packet Command data flags */
207 #define IAX2_TRUNK_TS 1
209 /* IAX2 Full-frame types */
210 static const value_string iax_frame_types[] = {
212 {AST_FRAME_DTMF_END, "DTMF End"},
213 {AST_FRAME_VOICE, "Voice"},
214 {AST_FRAME_VIDEO, "Video"},
215 {AST_FRAME_CONTROL, "Control"},
216 {AST_FRAME_NULL, "NULL"},
217 {AST_FRAME_IAX, "IAX"},
218 {AST_FRAME_TEXT, "Text"},
219 {AST_FRAME_IMAGE, "Image"},
220 {AST_FRAME_HTML, "HTML"},
221 {AST_FRAME_CNG, "Comfort Noise"},
222 {AST_FRAME_MODEM, "Modem"},
223 {AST_FRAME_DTMF_BEGIN, "DTMF Begin"},
227 /* Subclasses for IAX packets */
228 static const value_string iax_iax_subclasses[] = {
273 /* Subclasses for Control packets */
274 static const value_string iax_cmd_subclasses[] = {
283 {0xFF, "stop sounds"}, /* sent by app_dial, and not much else */
287 /* IAX2 to tap-voip call state mapping */
288 static const voip_call_state tap_cmd_voip_state[] = {
290 VOIP_COMPLETED, /*HANGUP*/
291 VOIP_RINGING, /*RING*/
292 VOIP_RINGING, /*RINGING*/
293 VOIP_IN_CALL, /*ANSWER*/
294 VOIP_REJECTED, /*BUSY*/
295 VOIP_UNKNOWN, /*TKOFFHK*/
296 VOIP_UNKNOWN /*OFFHOOK*/
298 #define NUM_TAP_CMD_VOIP_STATES array_length(tap_cmd_voip_state)
300 /* Subclasses for Modem packets */
301 static const value_string iax_modem_subclasses[] = {
308 /* Information elements */
309 static const value_string iax_ies_type[] = {
310 {IAX_IE_CALLED_NUMBER, "Number/extension being called"},
311 {IAX_IE_CALLING_NUMBER, "Calling number"},
312 {IAX_IE_CALLING_ANI, "Calling number ANI for billing"},
313 {IAX_IE_CALLING_NAME, "Name of caller"},
314 {IAX_IE_CALLED_CONTEXT, "Context for number"},
315 {IAX_IE_USERNAME, "Username (peer or user) for authentication"},
316 {IAX_IE_PASSWORD, "Password for authentication"},
317 {IAX_IE_CAPABILITY, "Actual codec capability"},
318 {IAX_IE_FORMAT, "Desired codec format"},
319 {IAX_IE_LANGUAGE, "Desired language"},
320 {IAX_IE_VERSION, "Protocol version"},
321 {IAX_IE_ADSICPE, "CPE ADSI capability"},
322 {IAX_IE_DNID, "Originally dialed DNID"},
323 {IAX_IE_AUTHMETHODS, "Authentication method(s)"},
324 {IAX_IE_CHALLENGE, "Challenge data for MD5/RSA"},
325 {IAX_IE_MD5_RESULT, "MD5 challenge result"},
326 {IAX_IE_RSA_RESULT, "RSA challenge result"},
327 {IAX_IE_APPARENT_ADDR, "Apparent address of peer"},
328 {IAX_IE_REFRESH, "When to refresh registration"},
329 {IAX_IE_DPSTATUS, "Dialplan status"},
330 {IAX_IE_CALLNO, "Call number of peer"},
331 {IAX_IE_CAUSE, "Cause"},
332 {IAX_IE_IAX_UNKNOWN, "Unknown IAX command"},
333 {IAX_IE_MSGCOUNT, "How many messages waiting"},
334 {IAX_IE_AUTOANSWER, "Request auto-answering"},
335 {IAX_IE_MUSICONHOLD, "Request musiconhold with QUELCH"},
336 {IAX_IE_TRANSFERID, "Transfer Request Identifier"},
337 {IAX_IE_RDNIS, "Referring DNIS"},
338 {IAX_IE_PROVISIONING, "Provisioning info"},
339 {IAX_IE_AESPROVISIONING, "AES Provisioning info"},
340 {IAX_IE_DATETIME, "Date/Time"},
341 {IAX_IE_DEVICETYPE, "Device type"},
342 {IAX_IE_SERVICEIDENT, "Service Identifier"},
343 {IAX_IE_FIRMWAREVER, "Firmware revision"},
344 {IAX_IE_FWBLOCKDESC, "Firmware block description"},
345 {IAX_IE_FWBLOCKDATA, "Firmware block of data"},
346 {IAX_IE_PROVVER, "Provisioning version"},
347 {IAX_IE_CALLINGPRES, "Calling presentation"},
348 {IAX_IE_CALLINGTON, "Calling type of number"},
349 {IAX_IE_CALLINGTNS, "Calling transit network select"},
350 {IAX_IE_SAMPLINGRATE, "Supported sampling rates"},
351 {IAX_IE_CAUSECODE, "Hangup cause"},
352 {IAX_IE_ENCRYPTION, "Encryption format"},
353 {IAX_IE_ENCKEY, "Raw encryption key"},
354 {IAX_IE_CODEC_PREFS, "Codec preferences"},
355 {IAX_IE_RR_JITTER, "Received jitter"},
356 {IAX_IE_RR_LOSS, "Received loss"},
357 {IAX_IE_RR_PKTS, "Received frames"},
358 {IAX_IE_RR_DELAY, "Max playout delay in ms for received frames"},
359 {IAX_IE_RR_DROPPED, "Dropped frames"},
360 {IAX_IE_RR_OOO, "Frames received out of order"},
361 {IAX_IE_DATAFORMAT, "Data call format"},
362 {IAX_IE_VARIABLE, "IAX2 variable"},
363 {IAX_IE_OSPTOKEN, "OSP Token"},
364 {IAX_IE_CALLTOKEN, "Call Token"},
365 {IAX_IE_CAPABILITY2, "64-bit codec capability"},
366 {IAX_IE_FORMAT2, "64-bit codec format"},
370 static const value_string codec_types[] = {
371 {AST_FORMAT_G723_1, "G.723.1 compression"},
372 {AST_FORMAT_GSM, "GSM compression"},
373 {AST_FORMAT_ULAW, "Raw mu-law data (G.711)"},
374 {AST_FORMAT_ALAW, "Raw A-law data (G.711)"},
375 {AST_FORMAT_G726_AAL2,"ADPCM (G.726, 32kbps)"},
376 {AST_FORMAT_ADPCM, "ADPCM (IMA)"},
377 {AST_FORMAT_SLINEAR, "Raw 16-bit Signed Linear (8000 Hz) PCM"},
378 {AST_FORMAT_LPC10, "LPC10, 180 samples/frame"},
379 {AST_FORMAT_G729A, "G.729a Audio"},
380 {AST_FORMAT_SPEEX, "SpeeX Free Compression"},
381 {AST_FORMAT_ILBC, "iLBC Free Compression"},
382 {AST_FORMAT_G726, "G.726 compression"},
383 {AST_FORMAT_G722, "G.722 wideband"},
384 {AST_FORMAT_SIREN7, "G.722.1 32k wideband (aka Siren7)"},
385 {AST_FORMAT_SIREN14, "G.722.1 Annex C 48k wideband (aka Siren14)"},
386 {AST_FORMAT_SLINEAR16,"Raw 16kHz signed linear audio"},
387 {AST_FORMAT_JPEG, "JPEG Images"},
388 {AST_FORMAT_PNG, "PNG Images"},
389 {AST_FORMAT_H261, "H.261 Video"},
390 {AST_FORMAT_H263, "H.263 Video"},
391 {AST_FORMAT_H263_PLUS,"H.263+ Video"},
392 {AST_FORMAT_H264, "H.264 Video"},
393 {AST_FORMAT_MP4_VIDEO,"MPEG4 Video"},
397 static const value_string iax_dataformats[] = {
398 {AST_DATAFORMAT_NULL, "N/A (analogue call?)"},
399 {AST_DATAFORMAT_V110, "ITU-T V.110 rate adaption"},
400 {AST_DATAFORMAT_H223_H245,"ITU-T H.223/H.245"},
405 static const value_string iax_packet_types[] = {
406 {IAX2_FULL_PACKET, "Full packet"},
407 {IAX2_MINI_VOICE_PACKET, "Mini voice packet"},
408 {IAX2_MINI_VIDEO_PACKET, "Mini video packet"},
409 {IAX2_TRUNK_PACKET, "Trunk packet"},
413 static const value_string iax_causecodes[] = {
414 {AST_CAUSE_UNALLOCATED, "Unallocated"},
415 {AST_CAUSE_NO_ROUTE_TRANSIT_NET, "No route transit net"},
416 {AST_CAUSE_NO_ROUTE_DESTINATION, "No route to destination"},
417 {AST_CAUSE_MISDIALLED_TRUNK_PREFIX, "Misdialled trunk prefix"},
418 {AST_CAUSE_CHANNEL_UNACCEPTABLE, "Channel unacceptable"},
419 {AST_CAUSE_CALL_AWARDED_DELIVERED, "Call awarded delivered"},
420 {AST_CAUSE_PRE_EMPTED, "Preempted"},
421 {AST_CAUSE_NUMBER_PORTED_NOT_HERE, "Number ported not here"},
422 {AST_CAUSE_NORMAL_CLEARING, "Normal clearing"},
423 {AST_CAUSE_USER_BUSY, "User busy"},
424 {AST_CAUSE_NO_USER_RESPONSE, "No user response"},
425 {AST_CAUSE_NO_ANSWER, "No answer"},
426 {AST_CAUSE_SUBSCRIBER_ABSENT, "Subscriber absent"},
427 {AST_CAUSE_CALL_REJECTED, "Call rejected"},
428 {AST_CAUSE_NUMBER_CHANGED, "Number changed"},
429 {AST_CAUSE_REDIRECTED_TO_NEW_DESTINATION,"Redirected to new destination"},
430 {AST_CAUSE_ANSWERED_ELSEWHERE, "Answered elsewhere"},
431 {AST_CAUSE_DESTINATION_OUT_OF_ORDER, "Destination out of order"},
432 {AST_CAUSE_INVALID_NUMBER_FORMAT, "Invalid number format"},
433 {AST_CAUSE_FACILITY_REJECTED, "Facility rejected"},
434 {AST_CAUSE_RESPONSE_TO_STATUS_ENQUIRY, "Response to status inquiry"},
435 {AST_CAUSE_NORMAL_UNSPECIFIED, "Normal unspecified"},
436 {AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, "Normal circuit congestion"},
437 {AST_CAUSE_NETWORK_OUT_OF_ORDER, "Network out of order"},
438 {AST_CAUSE_NORMAL_TEMPORARY_FAILURE, "Normal temporary failure"},
439 {AST_CAUSE_SWITCH_CONGESTION, "Switch congestion"},
440 {AST_CAUSE_ACCESS_INFO_DISCARDED, "Access info discarded"},
441 {AST_CAUSE_REQUESTED_CHAN_UNAVAIL, "Requested channel unavailable"},
442 {AST_CAUSE_FACILITY_NOT_SUBSCRIBED, "Facility not subscribed"},
443 {AST_CAUSE_OUTGOING_CALL_BARRED, "Outgoing call barred"},
444 {AST_CAUSE_INCOMING_CALL_BARRED, "Incoming call barred"},
445 {AST_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized"},
446 {AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available"},
447 {AST_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented"},
448 {AST_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented"},
449 {AST_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented"},
450 {AST_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference"},
451 {AST_CAUSE_INCOMPATIBLE_DESTINATION, "Incompatible destination"},
452 {AST_CAUSE_INVALID_MSG_UNSPECIFIED, "Invalid message unspecified"},
453 {AST_CAUSE_MANDATORY_IE_MISSING, "Mandatory IE missing"},
454 {AST_CAUSE_MESSAGE_TYPE_NONEXIST, "Message type nonexistent"},
455 {AST_CAUSE_WRONG_MESSAGE, "Wrong message"},
456 {AST_CAUSE_IE_NONEXIST, "IE nonexistent"},
457 {AST_CAUSE_INVALID_IE_CONTENTS, "Invalid IE contents"},
458 {AST_CAUSE_WRONG_CALL_STATE, "Wrong call state"},
459 {AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, "Recovery on timer expire"},
460 {AST_CAUSE_MANDATORY_IE_LENGTH_ERROR, "Mandatory IE length error"},
461 {AST_CAUSE_PROTOCOL_ERROR, "Protocol error"},
462 {AST_CAUSE_INTERWORKING, "Interworking"},
467 /* ************************************************************************* */
469 /* In order to track IAX calls, we have a hash table which maps
470 * {addr,port type,port,call} to a unique circuit id.
472 * Each call has two such circuits associated with it (a forward and a
473 * reverse circuit, where 'forward' is defined as the direction the NEW
474 * packet went in), and we maintain an iax_call_data structure for each
475 * call, attached to both circuits with circuit_add_proto_data.
477 * Because {addr,port type,port,call} quadruplets can be reused
478 * (Asterisk reuses call numbers), circuit ids aren't unique to
479 * individual calls and we treat NEW packets somewhat specially. When we
480 * get such a packet, we see if there are any calls with a matching
481 * circuit id, and make sure that its circuits are marked as ended
482 * before that packet.
484 * A second complication is that we only know one quadruplet at the time
485 * the NEW packet is processed: there is therefore cunningness in
486 * iax_lookup_circuit_details() to look for replies to NEW packets and
487 * create the reverse circuit.
491 /* start with a hash of {addr,port type,port,call}->{id} */
499 /* this is where addr->data points to. it's put in here for easy freeing */
500 guint8 address_data[MAX_ADDRESS];
504 static GHashTable *iax_circuit_hashtab = NULL;
505 static guint circuitcount = 0;
507 /* the number of keys and values to reserve space for in each memory chunk.
508 We assume we won't be tracking many calls at once so this is quite low.
510 #define IAX_INIT_PACKET_COUNT 10
513 static gchar *key_to_str( const iax_circuit_key *key )
516 static gchar *strp, str[3][80];
524 /* why doesn't ep_address_to_str take a const pointer?
525 cast the warnings into oblivion. */
527 /* XXX - is this a case for ep_alloc? */
528 g_snprintf(strp, 80, "{%s:%i,%i}",
529 ep_address_to_str((address *)&key->addr),
537 static gint iax_circuit_equal(gconstpointer v, gconstpointer w)
539 const iax_circuit_key *v1 = (const iax_circuit_key *)v;
540 const iax_circuit_key *v2 = (const iax_circuit_key *)w;
543 result = ( ADDRESSES_EQUAL(&(v1->addr), &(v2->addr)) &&
544 v1->ptype == v2->ptype &&
545 v1->port == v2->port &&
546 v1->callno== v2->callno);
548 g_debug( "+++ Comparing for equality: %s, %s: %u",key_to_str(v1), key_to_str(v2), result);
554 static guint iax_circuit_hash (gconstpointer v)
556 const iax_circuit_key *key = (const iax_circuit_key *)v;
560 ADD_ADDRESS_TO_HASH(hash_val, &key->addr);
561 hash_val += (guint)(key->ptype);
562 hash_val += (guint)(key->port);
563 hash_val += (guint)(key->callno);
566 g_debug( "+++ Hashing key: %s, result %#x", key_to_str(key), hash_val );
569 return (guint) hash_val;
572 /* Find, or create, a circuit for the given
573 {address,porttype,port,call} quadruplet
575 static guint iax_circuit_lookup(const address *address_p,
581 guint32 *circuit_id_p;
583 key.addr = *address_p;
588 circuit_id_p = g_hash_table_lookup( iax_circuit_hashtab, &key);
589 if( ! circuit_id_p ) {
590 iax_circuit_key *new_key;
592 new_key = se_alloc(sizeof(iax_circuit_key));
593 new_key->addr.type = address_p->type;
594 new_key->addr.len = MIN(address_p->len,MAX_ADDRESS);
595 new_key->addr.data = new_key->address_data;
596 memcpy(new_key->address_data,address_p->data,new_key->addr.len);
597 new_key->ptype = ptype;
598 new_key->port = port;
599 new_key->callno = callno;
601 circuit_id_p = se_alloc(sizeof(iax_circuit_key));
602 *circuit_id_p = ++circuitcount;
604 g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p);
607 g_debug("Created new circuit id %u for node %s", *circuit_id_p, key_to_str(new_key));
611 return *circuit_id_p;
615 /* ************************************************************************* */
618 guint32 current_frag_id; /* invalid unless current_frag_bytes > 0 */
619 guint32 current_frag_bytes;
620 guint32 current_frag_minlen;
623 /* This is our per-call data structure, which is attached to both the
624 * forward and reverse circuits.
626 typedef struct iax_call_data {
627 /* For this data, src and dst are relative to the original direction under
628 which this call is stored. Obviously if the reversed flag is set true by
629 iax_find_call, src and dst are reversed relative to the direction the
630 actual source and destination of the data.
632 if the codec changes mid-call, we update it here; because we store a codec
633 number with each packet too, we handle going back to earlier packets
637 iax_dataformat_t dataformat;
638 guint32 src_codec, dst_codec;
639 guint32 src_vformat, dst_vformat;
641 /* when a transfer takes place, we'll get a new circuit id; we assume that we
642 don't try to transfer more than IAX_MAX_TRANSFERS times in a call */
643 guint forward_circuit_ids[IAX_MAX_TRANSFERS];
644 guint reverse_circuit_ids[IAX_MAX_TRANSFERS];
645 guint n_forward_circuit_ids;
646 guint n_reverse_circuit_ids;
648 /* this is the subdissector for the call */
649 dissector_handle_t subdissector;
651 /* the absolute start time of the call */
654 GHashTable *fid_table;
655 GHashTable *fragment_table;
656 iax_call_dirdata dirdata[2];
659 static void iax_init_hash( void )
661 if (iax_circuit_hashtab)
662 g_hash_table_destroy(iax_circuit_hashtab);
664 iax_circuit_hashtab = g_hash_table_new(iax_circuit_hash, iax_circuit_equal);
671 /* creates a new CT_IAX2 circuit with a specified circuit id for a call
673 * typically a call has up to three associated circuits: an original source, an
674 * original destination, and the result of a transfer.
676 * For each endpoint, a CT_IAX2 circuit is created and added to the call_data
679 * 'reversed' should be true if this end is the one which would have _received_
680 * the NEW packet, or it is an endpoint to which the 'destination' is being
684 static circuit_t *iax2_new_circuit_for_call(guint circuit_id, guint framenum, iax_call_data *iax_call,
689 if(( reversed && iax_call->n_reverse_circuit_ids >= IAX_MAX_TRANSFERS) ||
690 ( !reversed && iax_call->n_forward_circuit_ids >= IAX_MAX_TRANSFERS)) {
691 g_warning("Too many transfers for iax_call");
695 res = circuit_new(CT_IAX2,
699 circuit_add_proto_data(res, proto_iax2, iax_call);
702 iax_call -> reverse_circuit_ids[iax_call->n_reverse_circuit_ids++] = circuit_id;
704 iax_call -> forward_circuit_ids[iax_call->n_forward_circuit_ids++] = circuit_id;
710 /* returns true if this circuit id is a "forward" circuit for this call: ie, it
711 * is the point which _sent_ the original 'NEW' packet, or a point to which that
712 * end was subsequently transferred */
713 static gboolean is_forward_circuit(guint circuit_id,
714 const iax_call_data *iax_call)
717 for(i=0;i<iax_call->n_forward_circuit_ids;i++){
718 if(circuit_id == iax_call->forward_circuit_ids[i])
724 /* returns true if this circuit id is a "reverse" circuit for this call: ie, it
725 * is the point which _received_ the original 'NEW' packet, or a point to which that
726 * end was subsequently transferred */
727 static gboolean is_reverse_circuit(guint circuit_id,
728 const iax_call_data *iax_call)
731 for(i=0;i<iax_call->n_reverse_circuit_ids;i++){
732 if(circuit_id == iax_call->reverse_circuit_ids[i])
739 static iax_call_data *iax_lookup_call_from_dest( guint src_circuit_id,
740 guint dst_circuit_id,
742 gboolean *reversed_p)
744 circuit_t *dst_circuit;
745 iax_call_data * iax_call;
746 gboolean reversed = FALSE;
748 dst_circuit = find_circuit( CT_IAX2,
754 g_debug( "++ destination circuit not found, must have missed NEW packet" );
762 g_debug( "++ found destination circuit" );
765 iax_call = (iax_call_data *)circuit_get_proto_data(dst_circuit,proto_iax2);
767 /* there's no way we can create a CT_IAX2 circuit without adding
768 iax call data to it; assert this */
769 DISSECTOR_ASSERT(iax_call);
771 if( is_forward_circuit(dst_circuit_id, iax_call )) {
773 g_debug( "++ destination circuit matches forward_circuit_id of call, "
774 "therefore packet is reversed" );
779 if( iax_call -> n_reverse_circuit_ids == 0 ) {
780 /* we are going in the reverse direction, and this call
781 doesn't have a reverse circuit associated with it.
784 g_debug( "++ reverse_circuit_id of call is zero, need to create a "
785 "new reverse circuit for this call" );
788 iax2_new_circuit_for_call( src_circuit_id, framenum, iax_call, TRUE );
790 g_debug( "++ done" );
792 } else if( !is_reverse_circuit(src_circuit_id, iax_call )) {
793 g_warning( "IAX Packet %u from circuit ids %u->%u "
794 "conflicts with earlier call with circuit ids %u->%u",
796 src_circuit_id,dst_circuit_id,
797 iax_call->forward_circuit_ids[0],
798 iax_call->reverse_circuit_ids[0]);
801 } else if ( is_reverse_circuit(dst_circuit_id, iax_call)) {
803 g_debug( "++ destination circuit matches reverse_circuit_id of call, "
804 "therefore packet is forward" );
808 if( !is_forward_circuit(src_circuit_id, iax_call)) {
809 g_warning( "IAX Packet %u from circuit ids %u->%u "
810 "conflicts with earlier call with circuit ids %u->%u",
812 src_circuit_id,dst_circuit_id,
813 iax_call->forward_circuit_ids[0],
814 iax_call->reverse_circuit_ids[0]);
820 DISSECTOR_ASSERT_NOT_REACHED();
824 *reversed_p = reversed;
830 /* looks up an iax_call for this packet */
831 static iax_call_data *iax_lookup_call( packet_info *pinfo,
834 gboolean *reversed_p)
836 gboolean reversed = FALSE;
837 iax_call_data *iax_call = NULL;
838 guint src_circuit_id;
841 g_debug( "++ iax_lookup_circuit_details: Looking up circuit for frame %u, "
842 "from {%s:%u:%u} to {%s:%u:%u}", pinfo->fd->num,
843 ep_address_to_str(&pinfo->src),pinfo->srcport,scallno,
844 ep_address_to_str(&pinfo->dst),pinfo->destport,dcallno);
848 src_circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
849 pinfo->srcport,scallno);
852 /* the most reliable indicator of call is the destination callno, if
855 guint dst_circuit_id;
857 g_debug( "++ dcallno non-zero, looking up destination circuit" );
860 dst_circuit_id = iax_circuit_lookup(&pinfo->dst,pinfo->ptype,
861 pinfo->destport,dcallno);
863 iax_call = iax_lookup_call_from_dest(src_circuit_id, dst_circuit_id,
864 pinfo->fd->num, &reversed);
866 circuit_t *src_circuit;
868 /* in all other circumstances, the source circuit should already
869 * exist: its absence indicates that we missed the all-important NEW
873 src_circuit = find_circuit( CT_IAX2,
878 iax_call = (iax_call_data *)circuit_get_proto_data(src_circuit,proto_iax2);
880 /* there's no way we can create a CT_IAX2 circuit without adding
881 iax call data to it; assert this */
882 DISSECTOR_ASSERT(iax_call);
884 if( is_forward_circuit(src_circuit_id,iax_call))
886 else if(is_reverse_circuit(src_circuit_id,iax_call))
889 /* there's also no way we can attach an iax_call_data to a circuit
890 without the circuit being either the forward or reverse circuit
891 for that call; assert this too.
893 DISSECTOR_ASSERT_NOT_REACHED();
899 *reversed_p = reversed;
903 g_debug( "++ Found call for packet: id %u, reversed=%c", iax_call->forward_circuit_ids[0], reversed?'1':'0' );
905 g_debug( "++ Call not found. Must have missed the NEW packet?" );
912 /* initialize the per-direction parts of an iax_call_data structure */
913 static void init_dir_data(iax_call_dirdata *dirdata)
915 dirdata -> current_frag_bytes=0;
916 dirdata -> current_frag_minlen=0;
920 /* handles a NEW packet by creating a new iax call and forward circuit.
921 the reverse circuit is not created until the ACK is received and
922 is created by iax_lookup_circuit_details. */
923 static iax_call_data *iax_new_call( packet_info *pinfo,
928 static const nstime_t millisecond = {0, 1000000};
931 g_debug( "+ new_circuit: Handling NEW packet, frame %u", pinfo->fd->num );
934 circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
935 pinfo->srcport,scallno);
937 call = se_alloc(sizeof(iax_call_data));
938 call -> dataformat = 0;
939 call -> src_codec = 0;
940 call -> dst_codec = 0;
941 call -> n_forward_circuit_ids = 0;
942 call -> n_reverse_circuit_ids = 0;
943 call -> subdissector = NULL;
944 call -> start_time = pinfo->fd->abs_ts;
945 nstime_delta(&call -> start_time, &call -> start_time, &millisecond);
946 call -> fid_table = g_hash_table_new(g_direct_hash, g_direct_equal);
947 init_dir_data(&call->dirdata[0]);
948 init_dir_data(&call->dirdata[1]);
949 call->fragment_table = NULL;
950 fragment_table_init(&(call->fragment_table));
952 iax2_new_circuit_for_call(circuit_id,pinfo->fd->num,call,FALSE);
958 /* ************************************************************************* */
960 /* per-packet data */
961 typedef struct iax_packet_data {
962 gboolean first_time; /* we're dissecting this packet for the first time; so
963 things like codec and transfer requests should be
964 propagated into the call data */
965 iax_call_data *call_data;
968 nstime_t abstime; /* the absolute time of this packet, based on its
969 * timestamp and the NEW packet's time (-1 if unknown) */
972 static iax_packet_data *iax_new_packet_data(iax_call_data *call, gboolean reversed)
974 iax_packet_data *p = se_alloc(sizeof(iax_packet_data));
978 p->reversed=reversed;
984 static void iax2_populate_pinfo_from_packet_data(packet_info *pinfo, const iax_packet_data * p)
986 /* info for subdissectors. We always pass on the original forward circuit,
987 * and steal the p2p_dir flag to indicate the direction */
988 if( p->call_data == NULL ) {
989 /* if we missed the NEW packet for this call, call_data will be null. it's
990 * tbd what the best thing to do here is. */
991 pinfo -> ctype = CT_NONE;
993 pinfo -> ctype = CT_IAX2;
994 pinfo -> circuit_id = (guint32)p->call_data->forward_circuit_ids[0];
995 pinfo -> p2p_dir = p->reversed?P2P_DIR_RECV:P2P_DIR_SENT;
997 if (check_col (pinfo->cinfo, COL_IF_DIR))
998 col_set_str (pinfo->cinfo, COL_IF_DIR, p->reversed ? "rev" : "fwd" );
1003 /* ************************************************************************* */
1005 /* this is passed up from the IE dissector to the main dissector */
1008 address peer_address;
1009 port_type peer_ptype;
1011 guint32 peer_callno;
1016 static guint32 dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
1018 packet_info * pinfo,
1019 proto_tree * iax2_tree,
1020 proto_tree * main_tree);
1023 static guint32 dissect_minipacket (tvbuff_t * tvb, guint32 offset,
1025 packet_info * pinfo,
1026 proto_tree * iax2_tree,
1027 proto_tree * main_tree);
1029 static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
1031 packet_info * pinfo,
1032 proto_tree * iax2_tree,
1033 proto_tree * main_tree);
1035 static guint32 dissect_trunkpacket (tvbuff_t * tvb, guint32 offset,
1037 packet_info * pinfo,
1038 proto_tree * iax2_tree,
1039 proto_tree * main_tree);
1041 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
1042 packet_info *pinfo, proto_tree *iax2_tree,
1043 proto_tree *tree, guint32 ts, gboolean video,
1044 iax_packet_data *iax_packet);
1049 dissect_iax2 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1051 proto_item *iax2_item = NULL;
1052 proto_tree *iax2_tree = NULL;
1053 proto_tree *full_mini_subtree = NULL;
1054 guint32 offset = 0, len;
1055 guint16 scallno = 0;
1059 /* set up the protocol and info fields in the summary pane */
1060 col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2);
1061 col_clear(pinfo->cinfo, COL_INFO);
1063 /* add the 'iax2' tree to the main tree */
1066 iax2_item = proto_tree_add_item (tree, proto_iax2, tvb, offset, -1, ENC_NA);
1067 iax2_tree = proto_item_add_subtree (iax2_item, ett_iax2);
1070 stmp = tvb_get_ntohs(tvb, offset);
1072 /* starting with 0x0000 indicates meta packet which can be either a mini
1073 * video packet or a trunk packet */
1075 stmp = tvb_get_ntohs(tvb, offset);
1076 if( stmp & 0x8000 ) {
1077 /* mini video packet */
1078 type = IAX2_MINI_VIDEO_PACKET;
1079 scallno = stmp & 0x7FFF;
1083 type = IAX2_TRUNK_PACKET;
1086 /* The source call/fullpacket flag is common to both mini and full packets */
1087 scallno = tvb_get_ntohs(tvb, offset);
1089 if( scallno & 0x8000 )
1090 type = IAX2_FULL_PACKET;
1092 type = IAX2_MINI_VOICE_PACKET;
1098 proto_item *full_mini_base;
1100 full_mini_base = proto_tree_add_uint(iax2_tree, hf_iax2_packet_type, tvb, 0, offset, type);
1101 full_mini_subtree = proto_item_add_subtree(full_mini_base, ett_iax2_full_mini_subtree);
1104 proto_tree_add_item (full_mini_subtree, hf_iax2_scallno, tvb, offset-2, 2, ENC_BIG_ENDIAN);
1107 iax2_info->ptype = type;
1108 iax2_info->scallno = 0;
1109 iax2_info->dcallno = 0;
1110 iax2_info->ftype = 0;
1111 iax2_info->csub = 0;
1112 iax2_info->payload_len = 0;
1113 iax2_info->timestamp = 0;
1114 iax2_info->callState = VOIP_NO_STATE;
1115 iax2_info->messageName = NULL;
1116 iax2_info->callingParty = NULL;
1117 iax2_info->calledParty = NULL;
1118 iax2_info->payload_data = NULL;
1121 case IAX2_FULL_PACKET:
1122 len = dissect_fullpacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1124 case IAX2_MINI_VOICE_PACKET:
1125 iax2_info->messageName = "MINI_VOICE_PACKET";
1126 len = dissect_minipacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1128 case IAX2_MINI_VIDEO_PACKET:
1129 iax2_info->messageName = "MINI_VIDEO_PACKET";
1130 len = dissect_minivideopacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1132 case IAX2_TRUNK_PACKET:
1133 iax2_info->messageName = "TRUNK_PACKET";
1134 len = dissect_trunkpacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1140 /* update the 'length' of the main IAX2 header field so that it covers just the headers,
1141 not the audio data. */
1142 proto_item_set_len(iax2_item, len);
1143 tap_queue_packet(iax2_tap, pinfo, iax2_info);
1146 static proto_item *dissect_datetime_ie(tvbuff_t *tvb, guint32 offset, proto_tree *ies_tree)
1152 proto_tree_add_item (ies_tree, hf_iax2_ies[IAX_IE_DATETIME], tvb, offset + 2, 4, ENC_BIG_ENDIAN);
1153 ie_val = tvb_get_ntohl(tvb, offset+2);
1155 /* who's crazy idea for a time encoding was this? */
1156 tm.tm_sec = (ie_val & 0x1f) << 1;
1157 tm.tm_min = (ie_val>>5) & 0x3f;
1158 tm.tm_hour = (ie_val>>11) & 0x1f;
1159 tm.tm_mday = (ie_val>>16) & 0x1f;
1160 tm.tm_mon = ((ie_val>>21) & 0xf) - 1;
1161 tm.tm_year = ((ie_val>>25) & 0x7f) + 100;
1162 tm.tm_isdst= -1; /* there's no info on whether DST was in force; assume it's
1163 * the same as currently */
1165 datetime.secs = mktime(&tm);
1167 return proto_tree_add_time (ies_tree, hf_iax2_ie_datetime, tvb, offset+2, 4, &datetime);
1171 /* dissect the information elements in an IAX frame. Returns the updated offset */
1172 static guint32 dissect_ies (tvbuff_t * tvb, guint32 offset,
1173 proto_tree * iax_tree,
1174 iax2_ie_data *ie_data)
1176 DISSECTOR_ASSERT(ie_data);
1178 while (offset < tvb_reported_length (tvb)) {
1180 int ies_type = tvb_get_guint8(tvb, offset);
1181 int ies_len = tvb_get_guint8(tvb, offset + 1);
1182 guint16 apparent_addr_family;
1184 /* do non-tree-dependent stuff first */
1186 case IAX_IE_DATAFORMAT:
1187 if (ies_len != 4) THROW(ReportedBoundsError);
1188 ie_data -> dataformat = tvb_get_ntohl(tvb, offset+2);
1191 case IAX_IE_CALLED_NUMBER:
1192 iax2_info->calledParty = g_strdup(tvb_format_text(tvb, offset+2, ies_len));
1194 case IAX_IE_CALLING_NUMBER:
1195 iax2_info->callingParty = g_strdup(tvb_format_text(tvb, offset+2, ies_len));
1198 case IAX_IE_APPARENT_ADDR:
1199 /* The IAX2 I-D says that the "apparent address" structure
1200 "is the same as the linux struct sockaddr_in", without
1201 bothering to note that the address family field is in
1202 *host* byte order in that structure (the I-D seems to be
1203 assuming that "everything is a Vax^Wx86 or x86-64" with
1204 the address family field being little-endian).
1206 This means the address family values are the Linux
1207 address family values. */
1208 apparent_addr_family = tvb_get_letohs(tvb, offset+2);
1209 switch( apparent_addr_family ) {
1211 /* IAX is always over UDP */
1212 ie_data->peer_ptype = PT_UDP;
1213 ie_data->peer_port = tvb_get_ntohs(tvb, offset+4);
1215 /* the ip address is big-endian, but then so is peer_address.data */
1216 SET_ADDRESS(&ie_data->peer_address,AT_IPv4,4,tvb_get_ptr(tvb,offset+6,4));
1220 g_warning("Not supported in IAX dissector: peer address family of %u", apparent_addr_family);
1227 /* the rest of this stuff only needs doing if we have an iax_tree */
1229 if( iax_tree && ies_type < NUM_HF_IAX2_IES ) {
1230 proto_item *ti, *ie_item = NULL;
1231 proto_tree *ies_tree;
1232 int ie_hf = hf_iax2_ies[ies_type];
1234 ti = proto_tree_add_text(iax_tree, tvb, offset, ies_len+2, " " );
1236 ies_tree = proto_item_add_subtree(ti, ett_iax2_ie);
1238 proto_tree_add_text(ies_tree, tvb, offset, 1, "IE id: %s (0x%02X)",
1239 val_to_str_const(ies_type, iax_ies_type, "Unknown"),
1242 proto_tree_add_text(ies_tree, tvb, offset+1, 1, "Length: %u",ies_len);
1245 /* hf_iax2_ies[] is an array, indexed by IE number, of header-fields, one
1246 per IE. Apart from a couple of special cases which require more
1247 complex decoding, we can just look up an entry from the array, and add
1248 the relevant item, although the encoding value used depends on the
1253 case IAX_IE_DATETIME:
1254 ie_item = dissect_datetime_ie(tvb,offset,ies_tree);
1258 case IAX_IE_CAPABILITY:
1260 proto_tree *codec_tree;
1262 if (ies_len != 4) THROW(ReportedBoundsError);
1265 proto_tree_add_item (ies_tree, ie_hf,
1266 tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1268 proto_item_add_subtree (ie_item, ett_iax2_codecs);
1270 proto_tree_add_item(codec_tree, hf_iax2_cap_g723_1, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1271 proto_tree_add_item(codec_tree, hf_iax2_cap_gsm, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1272 proto_tree_add_item(codec_tree, hf_iax2_cap_ulaw, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1273 proto_tree_add_item(codec_tree, hf_iax2_cap_alaw, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1274 proto_tree_add_item(codec_tree, hf_iax2_cap_g726_aal2, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1275 proto_tree_add_item(codec_tree, hf_iax2_cap_adpcm, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1276 proto_tree_add_item(codec_tree, hf_iax2_cap_slinear, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1277 proto_tree_add_item(codec_tree, hf_iax2_cap_lpc10, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1278 proto_tree_add_item(codec_tree, hf_iax2_cap_g729a, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1279 proto_tree_add_item(codec_tree, hf_iax2_cap_speex, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1280 proto_tree_add_item(codec_tree, hf_iax2_cap_ilbc, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1281 proto_tree_add_item(codec_tree, hf_iax2_cap_g726, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1282 proto_tree_add_item(codec_tree, hf_iax2_cap_g722, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1283 proto_tree_add_item(codec_tree, hf_iax2_cap_siren7, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1284 proto_tree_add_item(codec_tree, hf_iax2_cap_siren14, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1285 proto_tree_add_item(codec_tree, hf_iax2_cap_slinear16, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1286 proto_tree_add_item(codec_tree, hf_iax2_cap_jpeg, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1287 proto_tree_add_item(codec_tree, hf_iax2_cap_png, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1288 proto_tree_add_item(codec_tree, hf_iax2_cap_h261, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1289 proto_tree_add_item(codec_tree, hf_iax2_cap_h263, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1290 proto_tree_add_item(codec_tree, hf_iax2_cap_h263_plus, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1291 proto_tree_add_item(codec_tree, hf_iax2_cap_h264, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1292 proto_tree_add_item(codec_tree, hf_iax2_cap_mpeg4, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN );
1296 case IAX_IE_APPARENT_ADDR:
1298 proto_tree *sockaddr_tree = NULL;
1300 ie_item = proto_tree_add_text(ies_tree, tvb, offset + 2, 16, "Apparent Address");
1301 sockaddr_tree = proto_item_add_subtree(ie_item, ett_iax2_ies_apparent_addr);
1303 /* The IAX2 I-D says that the "apparent address" structure
1304 "is the same as the linux struct sockaddr_in", without
1305 bothering to note that the address family field is in
1306 *host* byte order in that structure (the I-D seems to be
1307 assuming that "everything is a Vax^Wx86 or x86-64" with
1308 the address family field being little-endian).
1310 This means the address family values are the Linux
1311 address family values. */
1312 apparent_addr_family = tvb_get_letohs(tvb, offset+2);
1313 proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINFAMILY, tvb, offset + 2, 2, apparent_addr_family);
1315 switch( apparent_addr_family ) {
1319 proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINPORT, tvb, offset + 4, 2, ie_data->peer_port);
1320 memcpy(&addr, ie_data->peer_address.data, 4);
1321 proto_tree_add_ipv4(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINADDR, tvb, offset + 6, 4, addr);
1330 /* throw an error if the IE isn't the expected length */
1331 enum ftenum type = proto_registrar_get_nth(ie_hf)->type;
1332 gint explen = ftype_length(type);
1333 if(explen != 0 && ies_len != explen)
1334 THROW(ReportedBoundsError);
1348 ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1353 ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_NA);
1358 ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_UTF_8|ENC_NA);
1362 DISSECTOR_ASSERT_NOT_REACHED();
1366 /* we don't understand this ie: add a generic one */
1369 const gchar *ie_name = val_to_str_const(ies_type, iax_ies_type, "Unknown");
1373 value = tvb_get_guint8(tvb, offset + 2);
1375 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTE,
1376 tvb, offset+2, 1, value,
1377 "%s: %#02x", ie_name, value );
1381 value = tvb_get_ntohs(tvb, offset + 2);
1383 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I16,
1384 tvb, offset+2, 2, value,
1385 "%s: %#04x", ie_name, value );
1389 value = tvb_get_ntohl(tvb, offset + 2);
1391 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I32,
1392 tvb, offset+2, 4, value,
1393 "%s: %#08x", ie_name, value );
1397 ptr = tvb_get_ephemeral_string(tvb, offset + 2, ies_len);
1399 proto_tree_add_string_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTES,
1400 tvb, offset+2, ies_len, ptr,
1401 "%s: %s", ie_name, ptr );
1408 /* by now, we *really* ought to have added an item */
1409 DISSECTOR_ASSERT(ie_item != NULL);
1411 /* Retrieve the text from the item we added, and append it to the main IE
1413 if(!PROTO_ITEM_IS_HIDDEN(ti)) {
1414 field_info *ie_finfo = PITEM_FINFO(ie_item);
1416 /* if the representation of the item has already been set, use that;
1417 else we have to allocate a block to put the text into */
1418 if( ie_finfo && ie_finfo->rep != NULL )
1419 proto_item_set_text(ti, "Information Element: %s",
1420 ie_finfo->rep->representation);
1422 guint8 *ie_val = NULL;
1423 ie_val = ep_alloc(ITEM_LABEL_LENGTH);
1424 proto_item_fill_label(ie_finfo, ie_val);
1425 proto_item_set_text(ti, "Information Element: %s",
1431 offset += ies_len + 2;
1436 static guint32 uncompress_subclass(guint8 csub)
1438 /* If the SC_LOG flag is set, return 2^csub otherwise csub */
1440 /* special case for 'compressed' -1 */
1444 return 1 << (csub & 0x1F);
1447 return (guint32)csub;
1450 /* returns the new offset */
1451 static guint32 dissect_iax2_command(tvbuff_t * tvb, guint32 offset,
1452 packet_info * pinfo, proto_tree *tree,
1453 iax_packet_data *iax_packet)
1455 guint8 csub = tvb_get_guint8(tvb, offset);
1456 guint8 address_data[MAX_ADDRESS];
1457 iax2_ie_data ie_data;
1458 iax_call_data *iax_call;
1460 ie_data.peer_address.type = AT_NONE;
1461 ie_data.peer_address.len = 0;
1462 ie_data.peer_address.data = address_data;
1463 ie_data.peer_ptype = 0;
1464 ie_data.peer_port = 0;
1465 ie_data.peer_callno = 0;
1466 ie_data.dataformat = (guint32)-1;
1467 iax_call = iax_packet -> call_data;
1469 /* add the subclass */
1470 proto_tree_add_uint (tree, hf_iax2_iax_csub, tvb, offset, 1, csub);
1473 if (check_col (pinfo->cinfo, COL_INFO))
1474 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1475 val_to_str (csub, iax_iax_subclasses, "unknown (0x%02x)"));
1477 if (offset >= tvb_reported_length (tvb))
1480 offset = dissect_ies(tvb, offset, tree, &ie_data);
1482 /* if this is a data call, set up a subdissector for the circuit */
1483 if(iax_call && ie_data.dataformat != (guint32)-1 && iax_call -> subdissector == NULL) {
1484 iax_call -> subdissector = dissector_get_uint_handle(iax2_dataformat_dissector_table, ie_data.dataformat );
1485 iax_call -> dataformat = ie_data.dataformat;
1488 /* if this is a transfer request, record it in the call data */
1489 if( csub == IAX_COMMAND_TXREQ && iax_packet -> first_time ) {
1490 if( ie_data.peer_address.type != AT_NONE && ie_data.peer_callno != 0 ) {
1491 guint tx_circuit = iax_circuit_lookup(&ie_data.peer_address,
1494 ie_data.peer_callno);
1497 g_debug("found transfer request for call %u->%u, to new id %u",
1498 iax_call->forward_circuit_ids[0],
1499 iax_call->reverse_circuit_ids[0],
1503 iax2_new_circuit_for_call(tx_circuit,pinfo->fd->num,iax_call,iax_packet->reversed);
1510 static void iax2_add_ts_fields(packet_info * pinfo, proto_tree * iax2_tree, iax_packet_data *iax_packet, guint16 shortts)
1512 guint32 longts = shortts;
1516 if(iax_packet->call_data == NULL) {
1517 /* no call info for this frame; perhaps we missed the NEW packet */
1521 if(iax_packet->abstime.secs == -1) {
1522 time_t start_secs = iax_packet->call_data->start_time.secs;
1523 gint32 abs_secs = (gint32) (start_secs + longts/1000);
1525 /* deal with short timestamps by assuming that packets are never more than
1526 * 16 seconds late */
1527 while(abs_secs < pinfo->fd->abs_ts.secs - 16) {
1529 abs_secs = (gint32) (start_secs + longts/1000);
1532 iax_packet->abstime.secs=abs_secs;
1533 iax_packet->abstime.nsecs=iax_packet->call_data->start_time.nsecs + (longts % 1000) * 1000000;
1534 if(iax_packet->abstime.nsecs >= 1000000000) {
1535 iax_packet->abstime.nsecs -= 1000000000;
1536 iax_packet->abstime.secs ++;
1539 iax2_info->timestamp = longts;
1542 item = proto_tree_add_time(iax2_tree, hf_iax2_absts, NULL, 0, 0, &iax_packet->abstime);
1543 PROTO_ITEM_SET_GENERATED(item);
1545 ts = pinfo->fd->abs_ts;
1546 nstime_delta(&ts, &ts, &iax_packet->abstime);
1548 item = proto_tree_add_time(iax2_tree, hf_iax2_lateness, NULL, 0, 0, &ts);
1549 PROTO_ITEM_SET_GENERATED(item);
1553 /* returns the new offset */
1555 dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
1557 packet_info * pinfo, proto_tree * iax2_tree,
1558 proto_tree * main_tree)
1566 proto_tree *packet_type_tree = NULL;
1567 iax_call_data *iax_call;
1568 iax_packet_data *iax_packet;
1570 gboolean rtp_marker;
1573 * remove the top bit for retransmission detection
1575 dcallno = tvb_get_ntohs(tvb, offset) & 0x7FFF;
1576 ts = tvb_get_ntohl(tvb, offset+2);
1577 type = tvb_get_guint8(tvb, offset + 8);
1578 csub = tvb_get_guint8(tvb, offset + 9);
1579 iax2_info->ftype = type;
1580 iax2_info->csub = csub;
1581 iax2_info->scallno = scallno;
1582 iax2_info->dcallno = dcallno;
1584 /* see if we've seen this packet before */
1585 iax_packet = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
1587 /* if not, find or create an iax_call info structure for this IAX session. */
1589 if( type == AST_FRAME_IAX && csub == IAX_COMMAND_NEW ) {
1590 /* NEW packets start a new call */
1591 iax_call = iax_new_call(pinfo,scallno);
1594 iax_call = iax_lookup_call(pinfo, scallno, dcallno,
1598 iax_packet = iax_new_packet_data(iax_call, reversed);
1599 p_add_proto_data(pinfo->fd,proto_iax2,iax_packet);
1601 iax_call = iax_packet->call_data;
1602 reversed = iax_packet->reversed;
1605 iax2_populate_pinfo_from_packet_data(pinfo, iax_packet);
1608 proto_item *packet_type_base;
1610 proto_tree_add_item (iax2_tree, hf_iax2_dcallno, tvb, offset, 2, ENC_BIG_ENDIAN );
1612 proto_tree_add_item(iax2_tree, hf_iax2_retransmission, tvb, offset, 2, ENC_BIG_ENDIAN );
1616 proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1617 iax_call->forward_circuit_ids[0] );
1618 PROTO_ITEM_SET_GENERATED(item);
1621 proto_tree_add_uint (iax2_tree, hf_iax2_ts, tvb, offset+2, 4, ts);
1622 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1624 proto_tree_add_item (iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1,
1627 proto_tree_add_item (iax2_tree, hf_iax2_iseqno, tvb, offset+7, 1,
1629 packet_type_base = proto_tree_add_uint (iax2_tree, hf_iax2_type, tvb,
1632 /* add the type-specific subtree */
1633 packet_type_tree = proto_item_add_subtree (packet_type_base, ett_iax2_type);
1635 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1639 /* add frame type to info line */
1640 if (check_col (pinfo->cinfo, COL_INFO)) {
1641 col_add_fstr (pinfo->cinfo, COL_INFO, "%s, source call# %d, timestamp %ums",
1642 val_to_str (type, iax_frame_types, "Unknown (0x%02x)"),
1645 iax2_info->messageName = val_to_str (type, iax_frame_types, "Unknown (0x%02x)");
1649 offset=dissect_iax2_command(tvb,offset+9,pinfo,packet_type_tree,iax_packet);
1650 iax2_info->messageName = val_to_str (csub, iax_iax_subclasses, "unknown (0x%02x)");
1651 iax2_info->callState = csub;
1654 case AST_FRAME_DTMF_BEGIN:
1655 case AST_FRAME_DTMF_END:
1656 proto_tree_add_item (packet_type_tree, hf_iax2_dtmf_csub, tvb, offset+9, 1, ENC_ASCII|ENC_NA);
1659 if (check_col (pinfo->cinfo, COL_INFO))
1660 col_append_fstr (pinfo->cinfo, COL_INFO, " digit %c", csub );
1663 case AST_FRAME_CONTROL:
1664 /* add the subclass */
1665 proto_tree_add_uint (packet_type_tree, hf_iax2_cmd_csub, tvb,
1669 if (check_col (pinfo->cinfo, COL_INFO))
1670 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1671 val_to_str (csub, iax_cmd_subclasses, "unknown (0x%02x)"));
1672 iax2_info->messageName = val_to_str (csub, iax_cmd_subclasses, "unknown (0x%02x)");
1673 if (csub < NUM_TAP_CMD_VOIP_STATES) iax2_info->callState = tap_cmd_voip_state[csub];
1676 case AST_FRAME_VOICE:
1678 iax_packet -> codec = codec = uncompress_subclass(csub);
1680 if( packet_type_tree ) {
1682 proto_tree_add_item (packet_type_tree, hf_iax2_voice_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1683 item = proto_tree_add_uint (packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, codec);
1684 PROTO_ITEM_SET_GENERATED(item);
1691 iax_call->dst_codec = codec;
1693 iax_call->src_codec = codec;
1697 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, FALSE,iax_packet);
1700 case AST_FRAME_VIDEO:
1701 /* bit 6 of the csub is used to represent the rtp 'marker' bit */
1702 rtp_marker = csub & 0x40 ? TRUE:FALSE;
1703 iax_packet -> codec = codec = uncompress_subclass((guint8) (csub & ~40));
1705 if( packet_type_tree ) {
1707 proto_tree_add_item (packet_type_tree, hf_iax2_video_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1708 proto_tree_add_item (packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1709 item = proto_tree_add_uint (packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, codec);
1710 PROTO_ITEM_SET_GENERATED(item);
1715 if( iax_call && iax_packet -> first_time ) {
1717 iax_call->dst_vformat = codec;
1719 iax_call->src_vformat = codec;
1724 col_append_str (pinfo->cinfo, COL_INFO, ", Mark" );
1727 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, TRUE, iax_packet);
1730 case AST_FRAME_MODEM:
1731 proto_tree_add_item (packet_type_tree, hf_iax2_modem_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1734 if (check_col (pinfo->cinfo, COL_INFO))
1735 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1736 val_to_str (csub, iax_modem_subclasses, "unknown (0x%02x)"));
1739 case AST_FRAME_HTML:
1742 proto_tree_add_uint (packet_type_tree, hf_iax2_csub, tvb, offset+9,
1746 if (check_col (pinfo->cinfo, COL_INFO))
1747 col_append_fstr (pinfo->cinfo, COL_INFO, " subclass %d", csub );
1751 /* next time we come to parse this packet, don't propagate the codec into the
1753 iax_packet->first_time = FALSE;
1758 static iax_packet_data *iax2_get_packet_data_for_minipacket(packet_info * pinfo,
1762 /* see if we've seen this packet before */
1763 iax_packet_data *p = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
1766 /* if not, find or create an iax_call info structure for this IAX session. */
1768 iax_call_data *iax_call;
1770 iax_call = iax_lookup_call(pinfo, scallno, 0, &reversed);
1772 p = iax_new_packet_data(iax_call,reversed);
1773 p_add_proto_data(pinfo->fd,proto_iax2,p);
1775 /* set the codec for this frame to be whatever the last full frame used */
1778 p->codec = reversed ? iax_call -> dst_vformat : iax_call -> src_vformat;
1780 p->codec = reversed ? iax_call -> dst_codec : iax_call -> src_codec;
1784 iax2_populate_pinfo_from_packet_data(pinfo, p);
1789 static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
1790 guint16 scallno, packet_info * pinfo,
1791 proto_tree * iax2_tree, proto_tree *main_tree)
1794 iax_packet_data *iax_packet;
1795 gboolean rtp_marker;
1798 ts = tvb_get_ntohs(tvb, offset);
1800 /* bit 15 of the ts is used to represent the rtp 'marker' bit */
1801 rtp_marker = ts & 0x8000 ? TRUE:FALSE;
1804 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, TRUE);
1807 if( iax_packet->call_data ) {
1809 proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1810 iax_packet->call_data->forward_circuit_ids[0] );
1811 PROTO_ITEM_SET_GENERATED(item);
1814 proto_tree_add_item (iax2_tree, hf_iax2_minividts, tvb, offset, 2, ENC_BIG_ENDIAN);
1815 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1816 proto_tree_add_item (iax2_tree, hf_iax2_minividmarker, tvb, offset, 2, ENC_BIG_ENDIAN);
1818 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1823 if (check_col (pinfo->cinfo, COL_INFO))
1824 col_add_fstr (pinfo->cinfo, COL_INFO,
1825 "Mini video packet, source call# %d, timestamp %ums%s",
1826 scallno, ts, rtp_marker?", Mark":"");
1829 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, TRUE, iax_packet);
1831 /* next time we come to parse this packet, don't propagate the codec into the
1833 iax_packet->first_time = FALSE;
1839 dissect_minipacket (tvbuff_t * tvb, guint32 offset, guint16 scallno, packet_info * pinfo, proto_tree * iax2_tree,
1840 proto_tree *main_tree)
1843 iax_packet_data *iax_packet;
1846 ts = tvb_get_ntohs(tvb, offset);
1848 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, FALSE);
1851 if( iax_packet->call_data ) {
1852 item = proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1853 iax_packet->call_data->forward_circuit_ids[0] );
1854 PROTO_ITEM_SET_GENERATED(item);
1857 proto_tree_add_uint (iax2_tree, hf_iax2_minits, tvb, offset, 2, ts);
1858 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet,(guint16)ts);
1860 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1866 if (check_col (pinfo->cinfo, COL_INFO))
1867 col_add_fstr (pinfo->cinfo, COL_INFO,
1868 "Mini packet, source call# %d, timestamp %ums",
1872 /* XXX fix the timestamp logic */
1873 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, FALSE, iax_packet);
1876 /* next time we come to parse this packet, don't propagate the codec into the
1878 iax_packet->first_time = FALSE;
1884 static guint32 dissect_trunkcall_ts (tvbuff_t * tvb, guint32 offset, proto_tree * iax2_tree, guint16 * scallno)
1886 proto_item *call_item;
1887 proto_tree *call_tree;
1888 guint16 datalen, rlen, ts;
1890 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1891 | Data Length (in octets) |R| Source Call Number |
1892 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1894 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1898 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1900 datalen = tvb_get_ntohs(tvb, offset);
1901 *scallno = tvb_get_ntohs(tvb, offset + 2);
1902 ts = tvb_get_ntohs(tvb, offset + 4);
1904 rlen = MIN(tvb_length(tvb) - offset - 6, datalen);
1907 call_item = proto_tree_add_text(iax2_tree, tvb, offset, rlen + 6, "Trunk call from %u, ts: %u", *scallno, ts);
1908 call_tree = proto_item_add_subtree(call_item, ett_iax2_trunk_call);
1910 proto_tree_add_item(call_tree, hf_iax2_trunk_call_len, tvb, offset, 2, ENC_BIG_ENDIAN);
1911 proto_tree_add_item(call_tree, hf_iax2_trunk_call_scallno, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
1912 proto_tree_add_item(call_tree, hf_iax2_trunk_call_ts, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
1913 proto_tree_add_item(call_tree, hf_iax2_trunk_call_data, tvb, offset + 6, rlen, ENC_NA);
1920 static guint32 dissect_trunkcall_nots (tvbuff_t * tvb, guint32 offset, proto_tree * iax2_tree, guint16 * scallno)
1922 proto_item *call_item;
1923 proto_tree *call_tree;
1924 guint16 datalen, rlen;
1926 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1927 |R| Source Call Number | Data Length (in octets) |
1928 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1932 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1934 *scallno = tvb_get_ntohs(tvb, offset);
1935 datalen = tvb_get_ntohs(tvb, offset + 2);
1937 rlen = MIN(tvb_length(tvb) - offset - 4, datalen);
1940 call_item = proto_tree_add_text(iax2_tree, tvb, offset, rlen + 6, "Trunk call from %u", *scallno);
1941 call_tree = proto_item_add_subtree(call_item, ett_iax2_trunk_call);
1943 proto_tree_add_item(call_tree, hf_iax2_trunk_call_scallno, tvb, offset, 2, ENC_BIG_ENDIAN);
1944 proto_tree_add_item(call_tree, hf_iax2_trunk_call_len, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
1945 proto_tree_add_item(call_tree, hf_iax2_trunk_call_data, tvb, offset + 4, rlen, ENC_NA);
1952 typedef struct _call_list {
1954 struct _call_list *next;
1957 static call_list *call_list_append(call_list *list, guint16 scallno)
1959 call_list *node = ep_alloc0(sizeof(call_list));
1961 node->scallno = scallno;
1964 call_list *cur = list;
1975 static gboolean call_list_find(call_list *list, guint16 scallno)
1977 for (; list; list = list->next) {
1978 if (list->scallno == scallno) {
1985 static guint call_list_length(call_list *list)
1988 for (; list; list = list->next) {
1994 static guint32 dissect_trunkpacket (tvbuff_t * tvb, guint32 offset,
1995 guint16 scallno _U_, packet_info * pinfo,
1996 proto_tree * iax2_tree, proto_tree *main_tree _U_)
1998 guint8 cmddata, trunkts;
1999 guint nframes = 0, ncalls = 0;
2000 /*iax_packet_data *iax_packet;*/
2001 proto_item *cd, *nc = NULL;
2002 proto_tree *field_tree = NULL;
2003 call_list *calls = NULL;
2005 cmddata = tvb_get_guint8(tvb, offset + 1);
2006 trunkts = cmddata & IAX2_TRUNK_TS;
2008 /* 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 */
2009 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
2010 /* |F| Meta Indicator |V|Meta Command | Cmd Data (0) | */
2011 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
2012 /* | time-stamp | */
2013 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
2017 proto_tree_add_item(iax2_tree, hf_iax2_trunk_metacmd, tvb, offset, 1, ENC_BIG_ENDIAN);
2020 cd = proto_tree_add_uint(iax2_tree, hf_iax2_trunk_cmddata, tvb, offset + 1, 1, cmddata);
2021 field_tree = proto_item_add_subtree(cd, ett_iax2_trunk_cmddata);
2023 proto_item_append_text(cd, " (trunk timestamps)");
2025 /* CD -> Trunk timestamp */
2026 proto_tree_add_boolean(field_tree, hf_iax2_trunk_cmddata_ts, tvb, offset + 1, 1, cmddata);
2029 proto_tree_add_item(iax2_tree, hf_iax2_trunk_ts, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
2035 /* Trunk calls with timestamp */
2036 while(tvb_length_remaining(tvb, offset) >= 6) {
2038 offset = dissect_trunkcall_ts (tvb, offset, iax2_tree, &scallno);
2039 if (!call_list_find (calls, scallno)) {
2040 calls = call_list_append (calls, scallno);
2046 /* Trunk calls without timestamp */
2047 while(tvb_length_remaining(tvb, offset) >= 4) {
2049 offset = dissect_trunkcall_nots (tvb, offset, iax2_tree, &scallno);
2050 if (!call_list_find (calls, scallno)) {
2051 calls = call_list_append (calls, scallno);
2057 ncalls = call_list_length (calls);
2060 /* number of items */
2061 nc = proto_tree_add_uint(iax2_tree, hf_iax2_trunk_ncalls, NULL, 0, 0, ncalls);
2062 PROTO_ITEM_SET_GENERATED(nc);
2065 col_add_fstr (pinfo->cinfo, COL_INFO, "Trunk packet with %d media frame%s for %d call%s",
2066 nframes, plurality(nframes, "", "s"),
2067 ncalls, plurality(ncalls, "", "s"));
2073 static void process_iax_pdu( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2074 gboolean video, iax_packet_data *iax_packet )
2076 guint32 codec = iax_packet -> codec;
2077 iax_call_data *iax_call = iax_packet -> call_data;
2079 #ifdef DEBUG_DESEGMENT
2080 g_debug("calling process_iax_pdu; len = %u", tvb_reported_length(tvb));
2083 if( !video && iax_call && iax_call->subdissector ) {
2084 call_dissector(iax_call->subdissector, tvb, pinfo, tree);
2085 }else if( codec != 0 && dissector_try_uint(iax2_codec_dissector_table, codec, tvb, pinfo, tree )) {
2086 /* codec dissector handled our data */
2088 /* we don't know how to dissect our data: dissect it as data */
2089 call_dissector(data_handle,tvb, pinfo, tree);
2092 #ifdef DEBUG_DESEGMENT
2093 g_debug("called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u",
2094 pinfo->desegment_len, pinfo->desegment_offset);
2098 static void desegment_iax(tvbuff_t *tvb, packet_info *pinfo, proto_tree *iax2_tree,
2099 proto_tree *tree, gboolean video, iax_packet_data *iax_packet )
2102 iax_call_data *iax_call = iax_packet -> call_data;
2103 iax_call_dirdata *dirdata;
2104 gpointer value=NULL;
2105 guint32 frag_offset=0;
2106 fragment_data *fd_head;
2107 gboolean must_desegment = FALSE;
2109 DISSECTOR_ASSERT(iax_call);
2111 pinfo->can_desegment = 2;
2112 pinfo->desegment_offset = 0;
2113 pinfo->desegment_len = 0;
2115 #ifdef DEBUG_DESEGMENT
2116 g_debug("dissecting packet %u", pinfo->fd->num);
2119 dirdata = &(iax_call->dirdata[!!(iax_packet->reversed)]);
2121 if((!pinfo->fd->flags.visited && dirdata->current_frag_bytes > 0) ||
2122 (value = g_hash_table_lookup(iax_call->fid_table,
2123 GUINT_TO_POINTER(pinfo->fd->num))) != NULL ) {
2124 /* then we are continuing an already-started pdu */
2126 guint32 frag_len = tvb_reported_length( tvb );
2129 #ifdef DEBUG_DESEGMENT
2130 g_debug("visited: %i; c_f_b: %u; hash: %u->%u", pinfo->fd->flags.visited?1:0,
2131 dirdata->current_frag_bytes, pinfo->fd->num, fid);
2134 if(!pinfo->fd->flags.visited) {
2136 fid = dirdata->current_frag_id;
2137 tot_len = dirdata->current_frag_minlen;
2138 g_hash_table_insert( iax_call->fid_table, GUINT_TO_POINTER(pinfo->fd->num), GUINT_TO_POINTER(fid) );
2139 frag_offset = dirdata->current_frag_bytes;
2140 dirdata->current_frag_bytes += frag_len;
2141 complete = dirdata->current_frag_bytes > tot_len;
2142 #ifdef DEBUG_DESEGMENT
2143 g_debug("hash: %u->%u; frag_offset: %u; c_f_b: %u; totlen: %u",
2144 pinfo->fd->num, fid, frag_offset, dirdata->current_frag_bytes, tot_len );
2147 fid = GPOINTER_TO_UINT(value);
2148 /* these values are unused by fragment_add if pinfo->fd->flags.visited */
2149 dirdata->current_frag_bytes = 0;
2153 /* fragment_add checks for already-added */
2154 fd_head = fragment_add( tvb, 0, pinfo, fid,
2155 iax_call->fragment_table,
2157 frag_len, !complete );
2159 if(fd_head && (pinfo->fd->num == fd_head->reassembled_in)) {
2161 tvbuff_t *next_tvb = tvb_new_child_real_data(tvb, fd_head->data, fd_head->datalen, fd_head->datalen);
2162 add_new_data_source(pinfo, next_tvb, "Reassembled IAX2");
2164 process_iax_pdu(next_tvb,pinfo,tree,video,iax_packet);
2166 /* calculate the amount of data which was available to the higher-level
2167 dissector before we added this segment; if the returned offset is
2168 within that section, the higher-level dissector was unable to find any
2169 pdus; if it's after that, it found one or more complete PDUs.
2171 old_len = (gint32)(tvb_reported_length(next_tvb) - frag_len);
2172 if( pinfo->desegment_len &&
2173 pinfo->desegment_offset < old_len ) {
2174 /* oops, it wasn't actually complete */
2175 fragment_set_partial_reassembly(pinfo, fid, iax_call->fragment_table);
2176 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
2177 /* only one more byte should be enough for a retry */
2178 dirdata->current_frag_minlen = fd_head->datalen + 1;
2180 dirdata->current_frag_minlen = fd_head->datalen + pinfo->desegment_len;
2183 /* we successfully dissected some data; create the proto tree items for
2184 * the fragments, and flag any remaining data for desegmentation */
2186 proto_item *iax_tree_item, *frag_tree_item;
2187 /* this nargery is to insert the fragment tree into the main tree
2188 * between the IAX protocol entry and the subdissector entry */
2189 show_fragment_tree(fd_head, &iax2_fragment_items, tree, pinfo, next_tvb, &frag_tree_item);
2190 iax_tree_item = proto_tree_get_parent( iax2_tree );
2191 if( frag_tree_item && iax_tree_item )
2192 proto_tree_move_item( tree, iax_tree_item, frag_tree_item );
2194 dirdata->current_frag_minlen = dirdata->current_frag_id = dirdata->current_frag_bytes = 0;
2196 if( pinfo->desegment_len ) {
2197 /* there's a bit of data left to desegment */
2198 must_desegment = TRUE;
2199 /* make desegment_offset relative to our tvb */
2200 pinfo->desegment_offset -= old_len;
2203 /* don't add a 'reassembled in' item for this pdu */
2208 /* This segment was not found in our table, so it doesn't
2209 contain a continuation of a higher-level PDU.
2210 Call the normal subdissector.
2213 process_iax_pdu(tvb,pinfo,tree,video,iax_packet);
2215 if(pinfo->desegment_len) {
2216 /* the higher-level dissector has asked for some more data - ie,
2217 the end of this segment does not coincide with the end of a
2218 higher-level PDU. */
2219 must_desegment = TRUE;
2225 /* must_desegment is set if the end of this segment (or the whole of it)
2226 * contained the start of a higher-level PDU; we must add whatever is left of
2227 * this segment (after pinfo->desegment_offset) to a fragment table for disassembly. */
2228 if(must_desegment) {
2229 guint32 fid = pinfo->fd->num; /* a new fragment id */
2230 guint32 deseg_offset = pinfo->desegment_offset;
2231 guint32 frag_len = tvb_reported_length_remaining(tvb,deseg_offset);
2232 dirdata->current_frag_id = fid;
2233 dirdata->current_frag_bytes = frag_len;
2235 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
2236 /* only one more byte should be enough for a retry */
2237 dirdata->current_frag_minlen = frag_len + 1;
2239 dirdata->current_frag_minlen = frag_len + pinfo->desegment_len;
2242 fd_head = fragment_add(tvb, deseg_offset, pinfo, fid,
2243 iax_call->fragment_table,
2244 0, frag_len, TRUE );
2245 #ifdef DEBUG_DESEGMENT
2246 g_debug("Start offset of undissected bytes: %u; "
2247 "Bytes remaining in this segment: %u; min required bytes: %u\n",
2248 deseg_offset, frag_len, frag_len + pinfo->desegment_len);
2252 /* add a 'reassembled in' item if necessary */
2253 if( fd_head != NULL ) {
2254 guint32 deseg_offset = pinfo->desegment_offset;
2255 if( fd_head->reassembled_in != 0 &&
2256 !(fd_head->flags & FD_PARTIAL_REASSEMBLY) ) {
2257 proto_item *iax_tree_item;
2258 iax_tree_item = proto_tree_add_uint( tree, hf_iax2_reassembled_in,
2259 tvb, deseg_offset, tvb_reported_length_remaining(tvb,deseg_offset),
2260 fd_head->reassembled_in);
2261 PROTO_ITEM_SET_GENERATED(iax_tree_item);
2263 /* this fragment is never reassembled */
2264 proto_tree_add_text( tree, tvb, deseg_offset, -1,
2265 "IAX2 fragment, unfinished");
2268 if( pinfo->desegment_offset == 0 ) {
2269 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAX2");
2270 col_set_str(pinfo->cinfo, COL_INFO, "[IAX2 segment of a reassembled PDU]");
2274 pinfo->can_desegment = 0;
2275 pinfo->desegment_offset = 0;
2276 pinfo->desegment_len = 0;
2279 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
2280 packet_info *pinfo, proto_tree *iax2_tree,
2281 proto_tree *tree, guint32 ts _U_, gboolean video,
2282 iax_packet_data *iax_packet)
2285 gboolean out_of_order = FALSE;
2288 guint32 codec = iax_packet -> codec;
2290 iax_call_data *iax_call = iax_packet -> call_data;
2292 if( offset >= tvb_reported_length (tvb)) {
2293 col_append_str (pinfo->cinfo, COL_INFO, ", empty frame" );
2297 sub_tvb = tvb_new_subset_remaining(tvb, offset);
2299 /* XXX shouldn't pass through out-of-order packets. */
2301 if (check_col (pinfo->cinfo, COL_INFO)) {
2302 if( !video && iax_call && iax_call -> dataformat != 0 ) {
2303 col_append_fstr (pinfo->cinfo, COL_INFO, ", data, format %s",
2304 val_to_str (iax_call -> dataformat,
2305 iax_dataformats, "unknown (0x%02x)"));
2308 col_append_str (pinfo->cinfo, COL_INFO, " (out-of-order packet)");
2311 col_append_fstr (pinfo->cinfo, COL_INFO, ", %s",
2312 val_to_str (codec, codec_types, "unknown (0x%02x)"));
2316 nbytes = tvb_reported_length(sub_tvb);
2317 proto_tree_add_text( iax2_tree, sub_tvb, 0, -1,
2318 "IAX2 payload (%u byte%s)", nbytes,
2319 plurality( nbytes, "", "s" ));
2321 iax2_info->payload_len = nbytes;
2322 iax2_info->payload_data = tvb_get_ptr(sub_tvb, 0, -1);
2324 /* pass the rest of the block to a subdissector */
2325 if(iax_packet->call_data)
2326 desegment_iax( sub_tvb, pinfo, iax2_tree, tree, video, iax_packet );
2328 process_iax_pdu(sub_tvb,pinfo,tree,video,iax_packet);
2335 /* called at the start of a capture. We should clear out our static, per-capture
2340 iax_init_protocol(void)
2348 proto_register_iax2 (void)
2350 /* A header field is something you can search/filter on.
2352 * We create a structure to register our fields. It consists of an
2353 * array of hf_register_info structures, each of which are of the format
2354 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
2357 static hf_register_info hf[] = {
2359 {&hf_iax2_packet_type,
2360 {"Packet type", "iax2.packet_type", FT_UINT8, BASE_DEC, VALS(iax_packet_types), 0,
2361 "Full/minivoice/minivideo/trunk packet",
2365 {"Call identifier", "iax2.call", FT_UINT32, BASE_DEC, NULL, 0,
2366 "This is the identifier Wireshark assigns to identify this call. It does not correspond to any real field in the protocol", HFILL }},
2369 {"Source call", "iax2.src_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2370 "src_call holds the number of this call at the packet source pbx",
2373 /* FIXME could this be turned into a FRAMENUM field? */
2375 {"Destination call", "iax2.dst_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2376 "dst_call holds the number of this call at the packet destination",
2379 {&hf_iax2_retransmission,
2380 {"Retransmission", "iax2.retransmission", FT_BOOLEAN, 16,
2382 "retransmission is set if this packet is a retransmission of an earlier failed packet", HFILL}},
2385 {"Timestamp", "iax2.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
2386 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2390 {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x0,
2391 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2394 {&hf_iax2_minividts,
2395 {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2396 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2400 {"Absolute Time", "iax2.abstime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2401 "The absolute time of this packet (calculated by adding the IAX timestamp to the start time of this call)",
2405 {"Lateness", "iax2.lateness", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2406 "The lateness of this packet compared to its timestamp",
2409 {&hf_iax2_minividmarker,
2410 {"Marker", "iax2.video.marker", FT_UINT16, BASE_DEC, NULL, 0x8000,
2411 "RTP end-of-frame marker",
2415 {"Outbound seq.no.", "iax2.oseqno", FT_UINT16, BASE_DEC, NULL,
2417 "oseqno is the sequence no of this packet. The first packet has oseqno==0, and subsequent packets increment the oseqno by 1",
2421 {"Inbound seq.no.", "iax2.iseqno", FT_UINT16, BASE_DEC, NULL, 0x0,
2422 "iseqno is the sequence no of the last successfully received packet",
2426 {"Type", "iax2.type", FT_UINT8, BASE_DEC, VALS (iax_frame_types),
2428 "For full IAX2 frames, type is the type of frame",
2432 {"Unknown subclass", "iax2.subclass", FT_UINT8, BASE_DEC, NULL, 0x0,
2433 "Subclass of unknown type of full IAX2 frame",
2436 {&hf_iax2_dtmf_csub,
2437 {"DTMF subclass (digit)", "iax2.dtmf.subclass", FT_STRINGZ, BASE_NONE, NULL, 0x0,
2438 "DTMF subclass gives the DTMF digit",
2442 {"Control subclass", "iax2.control.subclass", FT_UINT8, BASE_DEC,
2443 VALS (iax_cmd_subclasses), 0x0,
2444 "This gives the command number for a Control packet.", HFILL}},
2447 {"IAX subclass", "iax2.iax.subclass", FT_UINT8, BASE_DEC,
2448 VALS (iax_iax_subclasses),
2450 "IAX subclass gives the command number for IAX signaling packets", HFILL}},
2452 {&hf_iax2_voice_csub,
2453 {"Voice Subclass (compressed codec no)", "iax2.voice.subclass", FT_UINT8, BASE_DEC, NULL, 0x0,
2457 {&hf_iax2_voice_codec,
2458 {"CODEC", "iax2.voice.codec", FT_UINT32, BASE_HEX, VALS (codec_types),
2460 "CODEC gives the codec used to encode audio data", HFILL}},
2462 {&hf_iax2_video_csub,
2463 {"Video Subclass (compressed codec no)", "iax2.video.subclass", FT_UINT8, BASE_DEC, NULL, 0xBF,
2468 {"Marker", "iax2.video.marker", FT_BOOLEAN, 8, NULL, 0x40,
2469 "RTP end-of-frame marker",
2472 {&hf_iax2_video_codec,
2473 {"CODEC", "iax2.video.codec", FT_UINT32, BASE_HEX, VALS (codec_types), 0,
2474 "The codec used to encode video data", HFILL}},
2476 {&hf_iax2_modem_csub,
2477 {"Modem subclass", "iax2.modem.subclass", FT_UINT8, BASE_DEC,
2478 VALS (iax_modem_subclasses),
2480 "Modem subclass gives the type of modem", HFILL}},
2483 {"Timestamp", "iax2.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
2484 "timestamp is the time, in ms after the start of Command data this call, at which this trunk packet was transmitted",
2487 {&hf_iax2_trunk_metacmd,
2488 {"Meta command", "iax2.trunk.metacmd", FT_UINT8, BASE_DEC, NULL, 0x7F,
2489 "Meta command indicates whether or not the Meta Frame is a trunk.", HFILL}},
2491 {&hf_iax2_trunk_cmddata,
2492 {"Command data", "iax2.trunk.cmddata", FT_UINT8, BASE_HEX, NULL, 0x0,
2493 "Flags for options that apply to a trunked call", HFILL}},
2495 {&hf_iax2_trunk_cmddata_ts,
2496 {"Trunk timestamps", "iax2.trunk.cmddata.ts", FT_BOOLEAN, 8, NULL, IAX2_TRUNK_TS,
2497 "True: calls do each include their own timestamp", HFILL}},
2499 {&hf_iax2_trunk_call_len,
2500 {"Data length", "iax2.trunk.call.len", FT_UINT16, BASE_DEC, NULL, 0x0,
2501 "Trunk call data length in octets", HFILL}},
2503 {&hf_iax2_trunk_call_scallno,
2504 {"Source call number", "iax2.trunk.call.scallno", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2505 "Trunk call source call number", HFILL}},
2507 {&hf_iax2_trunk_call_ts,
2508 {"Timestamp", "iax2.trunk.call.ts", FT_UINT16, BASE_DEC, NULL, 0x0,
2509 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2512 {&hf_iax2_trunk_call_data,
2513 {"Data", "iax2.trunk.call.payload", FT_BYTES, BASE_NONE, NULL, 0x0,
2514 "Payload carried by this trunked packet.",
2517 {&hf_iax2_trunk_ncalls,
2518 {"Number of calls", "iax2.trunk.ncalls", FT_UINT16, BASE_DEC, NULL, 0x0,
2519 "Number of calls in this trunk packet",
2523 * Decoding for the ies
2526 {&hf_IAX_IE_APPARENTADDR_SINFAMILY,
2527 {"Family", "iax2.iax.app_addr.sinfamily", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2528 {&hf_IAX_IE_APPARENTADDR_SINPORT,
2529 {"Port", "iax2.iax.app_addr.sinport", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2530 {&hf_IAX_IE_APPARENTADDR_SINADDR,
2531 {"Address", "iax2.iax.app_addr.sinaddr", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
2533 {&hf_iax2_ies[IAX_IE_CALLED_NUMBER],
2534 {"Number/extension being called", "iax2.iax.called_number",
2536 BASE_NONE, NULL, 0x0, NULL, HFILL}},
2538 {&hf_iax2_ies[IAX_IE_CALLING_NUMBER],
2539 {"Calling number", "iax2.iax.calling_number", FT_STRING,
2543 {&hf_iax2_ies[IAX_IE_CALLING_ANI],
2544 {"Calling number ANI for billing", "iax2.iax.calling_ani",
2546 BASE_NONE, NULL, 0x0, NULL, HFILL}},
2548 {&hf_iax2_ies[IAX_IE_CALLING_NAME],
2549 {"Name of caller", "iax2.iax.calling_name", FT_STRING, BASE_NONE,
2553 {&hf_iax2_ies[IAX_IE_CALLED_CONTEXT],
2554 {"Context for number", "iax2.iax.called_context", FT_STRING,
2556 NULL, 0x0, NULL, HFILL}},
2558 {&hf_iax2_ies[IAX_IE_USERNAME],
2559 {"Username (peer or user) for authentication",
2560 "iax2.iax.username",
2561 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2563 {&hf_iax2_ies[IAX_IE_PASSWORD],
2564 {"Password for authentication", "iax2.iax.password", FT_STRING,
2565 BASE_NONE, NULL, 0x0, NULL, HFILL}},
2567 {&hf_iax2_ies[IAX_IE_CAPABILITY],
2568 {"Actual codec capability", "iax2.iax.capability", FT_UINT32,
2570 NULL, 0x0, NULL, HFILL}},
2572 {&hf_iax2_ies[IAX_IE_FORMAT],
2573 {"Desired codec format", "iax2.iax.format", FT_UINT32, BASE_HEX,
2574 VALS (codec_types), 0x0, NULL, HFILL}},
2576 {&hf_iax2_ies[IAX_IE_LANGUAGE],
2577 {"Desired language", "iax2.iax.language", FT_STRING, BASE_NONE,
2581 {&hf_iax2_ies[IAX_IE_VERSION],
2582 {"Protocol version", "iax2.iax.version", FT_UINT16, BASE_HEX, NULL,
2586 {&hf_iax2_ies[IAX_IE_ADSICPE],
2587 {"CPE ADSI capability", "iax2.iax.cpe_adsi", FT_UINT16, BASE_HEX,
2591 {&hf_iax2_ies[IAX_IE_DNID],
2592 {"Originally dialed DNID", "iax2.iax.dnid", FT_STRING, BASE_NONE,
2596 {&hf_iax2_ies[IAX_IE_AUTHMETHODS],
2597 {"Authentication method(s)", "iax2.iax.auth.methods", FT_UINT16,
2599 NULL, 0x0, NULL, HFILL}},
2601 {&hf_iax2_ies[IAX_IE_CHALLENGE],
2602 {"Challenge data for MD5/RSA", "iax2.iax.auth.challenge",
2604 BASE_NONE, NULL, 0x0, NULL, HFILL}},
2606 {&hf_iax2_ies[IAX_IE_MD5_RESULT],
2607 {"MD5 challenge result", "iax2.iax.auth.md5", FT_STRING,
2611 {&hf_iax2_ies[IAX_IE_RSA_RESULT],
2612 {"RSA challenge result", "iax2.iax.auth.rsa", FT_STRING,
2616 {&hf_iax2_ies[IAX_IE_REFRESH],
2617 {"When to refresh registration", "iax2.iax.refresh", FT_INT16,
2619 NULL, 0x0, NULL, HFILL}},
2621 {&hf_iax2_ies[IAX_IE_DPSTATUS],
2622 {"Dialplan status", "iax2.iax.dialplan_status", FT_UINT16,
2626 {&hf_iax2_ies[IAX_IE_CALLNO],
2627 {"Call number of peer", "iax2.iax.call_no", FT_UINT16, BASE_DEC,
2631 {&hf_iax2_ies[IAX_IE_CAUSE],
2632 {"Cause", "iax2.iax.cause", FT_STRING, BASE_NONE, NULL, 0x0, NULL,
2635 {&hf_iax2_ies[IAX_IE_IAX_UNKNOWN],
2636 {"Unknown IAX command", "iax2.iax.iax_unknown", FT_BYTES,
2640 {&hf_iax2_ies[IAX_IE_MSGCOUNT],
2641 {"How many messages waiting", "iax2.iax.msg_count", FT_INT16,
2643 NULL, 0x0, NULL, HFILL}},
2645 {&hf_iax2_ies[IAX_IE_AUTOANSWER],
2646 {"Request auto-answering", "iax2.iax.autoanswer", FT_NONE,
2648 NULL, 0x0, NULL, HFILL}},
2650 {&hf_iax2_ies[IAX_IE_MUSICONHOLD],
2651 {"Request musiconhold with QUELCH", "iax2.iax.moh", FT_NONE,
2653 NULL, 0x0, NULL, HFILL}},
2655 {&hf_iax2_ies[IAX_IE_TRANSFERID],
2656 {"Transfer Request Identifier", "iax2.iax.transferid", FT_UINT32,
2657 BASE_HEX, NULL, 0x0, NULL, HFILL}},
2659 {&hf_iax2_ies[IAX_IE_RDNIS],
2660 {"Referring DNIS", "iax2.iax.rdnis", FT_STRING, BASE_NONE, NULL,
2664 {&hf_iax2_ies[IAX_IE_PROVISIONING],
2665 {"Provisioning info","iax2.iax.provisioning", FT_STRING, BASE_NONE,
2666 NULL, 0x0, NULL, HFILL}},
2668 {&hf_iax2_ies[IAX_IE_AESPROVISIONING],
2669 {"AES Provisioning info","iax2.iax.aesprovisioning", FT_STRING, BASE_NONE,
2670 NULL, 0x0, NULL, HFILL}},
2672 {&hf_iax2_ies[IAX_IE_DATETIME],
2673 {"Date/Time", "iax2.iax.datetime.raw", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2675 {&hf_iax2_ie_datetime,
2676 {"Date/Time", "iax2.iax.datetime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL }},
2678 {&hf_iax2_ies[IAX_IE_DEVICETYPE],
2679 {"Device type", "iax2.iax.devicetype", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2681 {&hf_iax2_ies[IAX_IE_SERVICEIDENT],
2682 {"Service identifier", "iax2.iax.serviceident", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2684 {&hf_iax2_ies[IAX_IE_FIRMWAREVER],
2685 {"Firmware version", "iax2.iax.firmwarever", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2687 {&hf_iax2_ies[IAX_IE_FWBLOCKDESC],
2688 {"Firmware block description", "iax2.iax.fwblockdesc", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2690 {&hf_iax2_ies[IAX_IE_FWBLOCKDATA],
2691 {"Firmware block of data", "iax2.iax.fwblockdata", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2693 {&hf_iax2_ies[IAX_IE_PROVVER],
2694 {"Provisioning version", "iax2.iax.provver", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2696 {&hf_iax2_ies[IAX_IE_CALLINGPRES],
2697 {"Calling presentation", "iax2.iax.callingpres", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2699 {&hf_iax2_ies[IAX_IE_CALLINGTON],
2700 {"Calling type of number", "iax2.iax.callington", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2702 {&hf_iax2_ies[IAX_IE_CALLINGTNS],
2703 {"Calling transit network select", "iax2.iax.callingtns", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2705 {&hf_iax2_ies[IAX_IE_SAMPLINGRATE],
2706 {"Supported sampling rates", "iax2.iax.samplingrate", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2708 {&hf_iax2_ies[IAX_IE_CAUSECODE],
2709 {"Hangup cause", "iax2.iax.causecode", FT_UINT8, BASE_HEX, VALS(iax_causecodes),
2712 {&hf_iax2_ies[IAX_IE_ENCRYPTION],
2713 {"Encryption format", "iax2.iax.encryption", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2715 {&hf_iax2_ies[IAX_IE_ENCKEY],
2716 {"Encryption key", "iax2.iax.enckey", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2718 {&hf_iax2_ies[IAX_IE_CODEC_PREFS],
2719 {"Codec negotiation", "iax2.iax.codecprefs", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2721 {&hf_iax2_ies[IAX_IE_RR_JITTER],
2722 {"Received jitter (as in RFC1889)", "iax2.iax.rrjitter", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2724 {&hf_iax2_ies[IAX_IE_RR_LOSS],
2725 {"Received loss (high byte loss pct, low 24 bits loss count, as in rfc1889)", "iax2.iax.rrloss",
2726 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2728 {&hf_iax2_ies[IAX_IE_RR_PKTS],
2729 {"Total frames received", "iax2.iax.rrpkts", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2731 {&hf_iax2_ies[IAX_IE_RR_DELAY],
2732 {"Max playout delay in ms for received frames", "iax2.iax.rrdelay", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2734 {&hf_iax2_ies[IAX_IE_RR_DROPPED],
2735 {"Dropped frames (presumably by jitterbuffer)", "iax2.iax.rrdropped", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2737 {&hf_iax2_ies[IAX_IE_RR_OOO],
2738 {"Frame received out of order", "iax2.iax.rrooo", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2740 {&hf_iax2_ies[IAX_IE_DATAFORMAT],
2741 {"Data call format", "iax2.iax.dataformat", FT_UINT32, BASE_HEX,
2742 VALS(iax_dataformats), 0x0, NULL, HFILL}},
2744 {&hf_IAX_IE_UNKNOWN_BYTE,
2745 {"Unknown", "iax2.iax.unknownbyte", FT_UINT8, BASE_HEX, NULL,
2746 0x0, "Raw data for unknown IEs",
2748 {&hf_IAX_IE_UNKNOWN_I16,
2749 {"Unknown", "iax2.iax.unknownshort", FT_UINT16, BASE_HEX, NULL,
2750 0x0, "Raw data for unknown IEs",
2752 {&hf_IAX_IE_UNKNOWN_I32,
2753 {"Unknown", "iax2.iax.unknownlong", FT_UINT32, BASE_HEX, NULL,
2754 0x0, "Raw data for unknown IEs",
2756 {&hf_IAX_IE_UNKNOWN_BYTES,
2757 {"Unknown", "iax2.iax.unknownstring", FT_STRING, BASE_NONE, NULL,
2758 0x0, "Raw data for unknown IEs",
2762 {&hf_iax2_cap_g723_1,
2763 {"G.723.1 compression", "iax2.cap.g723_1", FT_BOOLEAN, 32,
2764 TFS(&tfs_supported_not_supported), AST_FORMAT_G723_1,
2768 {"GSM compression", "iax2.cap.gsm", FT_BOOLEAN, 32,
2769 TFS(&tfs_supported_not_supported), AST_FORMAT_GSM,
2773 {"Raw mu-law data (G.711)", "iax2.cap.ulaw",FT_BOOLEAN, 32,
2774 TFS(&tfs_supported_not_supported), AST_FORMAT_ULAW,
2778 {"Raw A-law data (G.711)", "iax2.cap.alaw",FT_BOOLEAN, 32,
2779 TFS(&tfs_supported_not_supported), AST_FORMAT_ALAW,
2782 {&hf_iax2_cap_g726_aal2,
2783 {"G.726 compression (AAL2 packing)", "iax2.cap.g726_aal2",FT_BOOLEAN, 32,
2784 TFS(&tfs_supported_not_supported), AST_FORMAT_G726_AAL2,
2787 {&hf_iax2_cap_adpcm,
2788 {"ADPCM", "iax2.cap.adpcm", FT_BOOLEAN, 32,
2789 TFS(&tfs_supported_not_supported), AST_FORMAT_ADPCM,
2792 {&hf_iax2_cap_slinear,
2793 {"Raw 16-bit Signed Linear (8000 Hz) PCM", "iax2.cap.slinear",
2794 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_SLINEAR,
2797 {&hf_iax2_cap_lpc10,
2798 {"LPC10, 180 samples/frame", "iax2.cap.lpc10", FT_BOOLEAN, 32,
2799 TFS(&tfs_supported_not_supported), AST_FORMAT_LPC10,
2802 {&hf_iax2_cap_g729a,
2803 {"G.729a Audio", "iax2.cap.g729a", FT_BOOLEAN, 32,
2804 TFS(&tfs_supported_not_supported), AST_FORMAT_G729A,
2807 {&hf_iax2_cap_speex,
2808 {"SPEEX Audio", "iax2.cap.speex", FT_BOOLEAN, 32,
2809 TFS(&tfs_supported_not_supported), AST_FORMAT_SPEEX,
2813 {"iLBC Free compressed Audio", "iax2.cap.ilbc", FT_BOOLEAN, 32,
2814 TFS(&tfs_supported_not_supported), AST_FORMAT_ILBC,
2818 {"ADPCM (G.726, 32kbps, RFC3551 codeword packing)", "iax2.cap.g726", FT_BOOLEAN, 32,
2819 TFS(&tfs_supported_not_supported), AST_FORMAT_G726,
2823 {"G.722 wideband audio", "iax2.cap.g722", FT_BOOLEAN, 32,
2824 TFS(&tfs_supported_not_supported), AST_FORMAT_G722,
2827 {&hf_iax2_cap_siren7,
2828 {"G.722.1 (also known as Siren7, 32kbps assumed)", "iax2.cap.siren7", FT_BOOLEAN, 32,
2829 TFS(&tfs_supported_not_supported), AST_FORMAT_SIREN7,
2832 {&hf_iax2_cap_siren14,
2833 {"G.722.1 Annex C (also known as Siren14, 48kbps assumed)", "iax2.cap.siren14", FT_BOOLEAN, 32,
2834 TFS(&tfs_supported_not_supported), AST_FORMAT_SIREN14,
2837 {&hf_iax2_cap_slinear16,
2838 {"Raw 16-bit Signed Linear (16000 Hz) PCM", "iax2.cap.slinear16", FT_BOOLEAN, 32,
2839 TFS(&tfs_supported_not_supported), AST_FORMAT_SLINEAR16,
2843 {"JPEG images", "iax2.cap.jpeg", FT_BOOLEAN, 32,
2844 TFS(&tfs_supported_not_supported), AST_FORMAT_JPEG,
2848 {"PNG images", "iax2.cap.png", FT_BOOLEAN, 32,
2849 TFS(&tfs_supported_not_supported), AST_FORMAT_PNG,
2853 {"H.261 video", "iax2.cap.h261", FT_BOOLEAN, 32,
2854 TFS(&tfs_supported_not_supported), AST_FORMAT_H261,
2858 {"H.263 video", "iax2.cap.h263", FT_BOOLEAN, 32,
2859 TFS(&tfs_supported_not_supported), AST_FORMAT_H263,
2862 {&hf_iax2_cap_h263_plus,
2863 {"H.263+ video", "iax2.cap.h263_plus", FT_BOOLEAN, 32,
2864 TFS(&tfs_supported_not_supported), AST_FORMAT_H263_PLUS,
2868 {"H.264 video", "iax2.cap.h264", FT_BOOLEAN, 32,
2869 TFS(&tfs_supported_not_supported), AST_FORMAT_H264,
2872 {&hf_iax2_cap_mpeg4,
2873 {"MPEG4 video", "iax2.cap.mpeg4", FT_BOOLEAN, 32,
2874 TFS(&tfs_supported_not_supported), AST_FORMAT_MP4_VIDEO,
2877 /* reassembly stuff */
2878 {&hf_iax2_fragments,
2879 {"IAX2 Fragments", "iax2.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2883 {"IAX2 Fragment data", "iax2.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2886 {&hf_iax2_fragment_overlap,
2887 {"Fragment overlap", "iax2.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2888 NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2890 {&hf_iax2_fragment_overlap_conflict,
2891 {"Conflicting data in fragment overlap", "iax2.fragment.overlap.conflict",
2892 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2893 "Overlapping fragments contained conflicting data", HFILL }},
2895 {&hf_iax2_fragment_multiple_tails,
2896 {"Multiple tail fragments found", "iax2.fragment.multipletails",
2897 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2898 "Several tails were found when defragmenting the packet", HFILL }},
2900 {&hf_iax2_fragment_too_long_fragment,
2901 {"Fragment too long", "iax2.fragment.toolongfragment",
2902 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2903 "Fragment contained data past end of packet", HFILL }},
2905 {&hf_iax2_fragment_error,
2906 {"Defragmentation error", "iax2.fragment.error",
2907 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2908 "Defragmentation error due to illegal fragments", HFILL }},
2910 {&hf_iax2_fragment_count,
2911 {"Fragment count", "iax2.fragment.count",
2912 FT_UINT32, BASE_DEC, NULL, 0x0,
2915 {&hf_iax2_reassembled_in,
2916 {"IAX2 fragment, reassembled in frame", "iax2.reassembled_in",
2917 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2918 "This IAX2 packet is reassembled in this frame", HFILL }},
2920 {&hf_iax2_reassembled_length,
2921 {"Reassembled IAX2 length", "iax2.reassembled.length",
2922 FT_UINT32, BASE_DEC, NULL, 0x0,
2923 "The total length of the reassembled payload", HFILL }}
2926 static gint *ett[] = {
2928 &ett_iax2_full_mini_subtree,
2932 &ett_iax2_ies_apparent_addr,
2934 &ett_iax2_fragments,
2935 &ett_iax2_trunk_cmddata,
2936 &ett_iax2_trunk_call
2939 /* initialize the hf_iax2_ies[] array to -1 */
2940 memset(hf_iax2_ies,0xff,sizeof(hf_iax2_ies));
2943 proto_register_protocol ("Inter-Asterisk eXchange v2", "IAX2", "iax2");
2944 proto_register_field_array (proto_iax2, hf, array_length (hf));
2945 proto_register_subtree_array (ett, array_length (ett));
2947 register_dissector("iax2", dissect_iax2, proto_iax2);
2949 iax2_codec_dissector_table = register_dissector_table(
2950 "iax2.codec","IAX codec number", FT_UINT32, BASE_HEX);
2951 iax2_dataformat_dissector_table = register_dissector_table(
2952 "iax2.dataformat","IAX dataformat number", FT_UINT32, BASE_HEX);
2954 /* register our init routine to be called at the start of a capture,
2955 to clear out our hash tables etc */
2956 register_init_routine(&iax_init_protocol);
2957 iax2_tap = register_tap("IAX2");
2961 proto_reg_handoff_iax2 (void)
2963 dissector_handle_t v110_handle = NULL;
2965 dissector_add_uint("udp.port", IAX2_PORT, find_dissector("iax2"));
2966 v110_handle = find_dissector("v110");
2968 dissector_add_uint("iax2.dataformat", AST_DATAFORMAT_V110, v110_handle);
2969 data_handle = find_dissector("data");
2978 * indent-tabs-mode: nil
2981 * ex: set shiftwidth=2 tabstop=8 expandtab:
2982 * :indentSize=2:tabSize=8:noTabs=true: