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.
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2 of the License, or (at your
20 * option) any later version. This program is distributed in the hope
21 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
22 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
23 * PURPOSE. See the GNU General Public License for more details. You
24 * should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #include <epan/circuit.h>
39 #include <epan/packet.h>
40 #include <epan/to_str.h>
41 #include <epan/emem.h>
42 #include <epan/reassemble.h>
44 #include "packet-iax2.h"
45 #include <epan/iax2_codec_type.h>
47 #define IAX2_PORT 4569
48 #define PROTO_TAG_IAX2 "IAX2"
50 /* enough to hold any address in an address_t */
51 #define MAX_ADDRESS 16
53 /* the maximum number of transfers (of each end) we can deal with per call,
55 #define IAX_MAX_TRANSFERS 2
57 /* #define DEBUG_HASHING */
58 /* #define DEBUG_DESEGMENT */
60 /* Wireshark ID of the IAX2 protocol */
61 static int proto_iax2 = -1;
63 /* The following hf_* variables are used to hold the wireshark IDs of
64 * our header fields; they are filled out when we call
65 * proto_register_field_array() in proto_register_iax2()
67 static int hf_iax2_packet_type = -1;
68 static int hf_iax2_retransmission = -1;
69 static int hf_iax2_callno = -1;
70 static int hf_iax2_scallno = -1;
71 static int hf_iax2_dcallno = -1;
72 static int hf_iax2_ts = -1;
73 static int hf_iax2_minits = -1;
74 static int hf_iax2_minividts = -1;
75 static int hf_iax2_absts = -1;
76 static int hf_iax2_lateness = -1;
77 static int hf_iax2_minividmarker = -1;
78 static int hf_iax2_oseqno = -1;
79 static int hf_iax2_iseqno = -1;
80 static int hf_iax2_type = -1;
81 static int hf_iax2_csub = -1;
82 static int hf_iax2_dtmf_csub = -1;
83 static int hf_iax2_cmd_csub = -1;
84 static int hf_iax2_iax_csub = -1;
85 static int hf_iax2_voice_csub = -1;
86 static int hf_iax2_voice_codec = -1;
87 static int hf_iax2_video_csub = -1;
88 static int hf_iax2_video_codec = -1;
89 static int hf_iax2_marker = -1;
91 static int hf_iax2_cap_g723_1 = -1;
92 static int hf_iax2_cap_gsm = -1;
93 static int hf_iax2_cap_ulaw = -1;
94 static int hf_iax2_cap_alaw = -1;
95 static int hf_iax2_cap_g726 = -1;
96 static int hf_iax2_cap_adpcm = -1;
97 static int hf_iax2_cap_slinear = -1;
98 static int hf_iax2_cap_lpc10 = -1;
99 static int hf_iax2_cap_g729a = -1;
100 static int hf_iax2_cap_speex = -1;
101 static int hf_iax2_cap_ilbc = -1;
102 static int hf_iax2_cap_jpeg = -1;
103 static int hf_iax2_cap_png = -1;
104 static int hf_iax2_cap_h261 = -1;
105 static int hf_iax2_cap_h263 = -1;
107 static int hf_iax2_fragments = -1;
108 static int hf_iax2_fragment = -1;
109 static int hf_iax2_fragment_overlap = -1;
110 static int hf_iax2_fragment_overlap_conflict = -1;
111 static int hf_iax2_fragment_multiple_tails = -1;
112 static int hf_iax2_fragment_too_long_fragment = -1;
113 static int hf_iax2_fragment_error = -1;
114 static int hf_iax2_reassembled_in = -1;
117 /* hf_iax2_ies is an array of header fields, one per potential Information
118 * Element. It's done this way (rather than having separate variables for each
119 * IE) to make the dissection of information elements clearer and more
122 * To add the ability to dissect a new information element, just add an
123 * appropriate entry to hf[] in proto_register_iax2(); dissect_ies() will then
124 * pick it up automatically.
126 static int hf_iax2_ies[256];
127 static int hf_iax2_ie_datetime = -1;
128 static int hf_IAX_IE_APPARENTADDR_SINFAMILY = -1;
129 static int hf_IAX_IE_APPARENTADDR_SINPORT = -1;
130 static int hf_IAX_IE_APPARENTADDR_SINADDR = -1;
131 static int hf_IAX_IE_UNKNOWN_BYTE = -1;
132 static int hf_IAX_IE_UNKNOWN_I16 = -1;
133 static int hf_IAX_IE_UNKNOWN_I32 = -1;
134 static int hf_IAX_IE_UNKNOWN_BYTES = -1;
136 /* These are the ids of the subtrees that we may be creating */
137 static gint ett_iax2 = -1;
138 static gint ett_iax2_full_mini_subtree = -1;
139 static gint ett_iax2_type = -1; /* Frame-type specific subtree */
140 static gint ett_iax2_ie = -1; /* single IE */
141 static gint ett_iax2_codecs = -1; /* capabilities IE */
142 static gint ett_iax2_ies_apparent_addr = -1; /* apparent address IE */
143 static gint ett_iax2_fragment = -1;
144 static gint ett_iax2_fragments = -1;
146 static const fragment_items iax2_fragment_items = {
151 &hf_iax2_fragment_overlap,
152 &hf_iax2_fragment_overlap_conflict,
153 &hf_iax2_fragment_multiple_tails,
154 &hf_iax2_fragment_too_long_fragment,
155 &hf_iax2_fragment_error,
156 &hf_iax2_reassembled_in,
160 static dissector_handle_t data_handle;
162 /* data-call subdissectors, AST_DATAFORMAT_* */
163 static dissector_table_t iax2_dataformat_dissector_table;
164 /* voice/video call subdissectors, AST_FORMAT_* */
165 static dissector_table_t iax2_codec_dissector_table;
167 /* IAX2 Full-frame types */
168 static const value_string iax_frame_types[] = {
181 /* Subclasses for IAX packets */
182 static const value_string iax_iax_subclasses[] = {
224 /* Subclassess for Control packets */
225 static const value_string iax_cmd_subclasses[] = {
234 {0xFF, "stop sounds"}, /* sent by app_dial, and not much else */
238 /* Information elements */
239 static const value_string iax_ies_type[] = {
240 {IAX_IE_CALLED_NUMBER, "Number/extension being called"},
241 {IAX_IE_CALLING_NUMBER, "Calling number"},
242 {IAX_IE_CALLING_ANI, "Calling number ANI for billing"},
243 {IAX_IE_CALLING_NAME, "Name of caller"},
244 {IAX_IE_CALLED_CONTEXT, "Context for number"},
245 {IAX_IE_USERNAME, "Username (peer or user) for authentication"},
246 {IAX_IE_PASSWORD, "Password for authentication"},
247 {IAX_IE_CAPABILITY, "Actual codec capability"},
248 {IAX_IE_FORMAT, "Desired codec format"},
249 {IAX_IE_LANGUAGE, "Desired language"},
250 {IAX_IE_VERSION, "Protocol version"},
251 {IAX_IE_ADSICPE, "CPE ADSI capability"},
252 {IAX_IE_DNID, "Originally dialed DNID"},
253 {IAX_IE_AUTHMETHODS, "Authentication method(s)"},
254 {IAX_IE_CHALLENGE, "Challenge data for MD5/RSA"},
255 {IAX_IE_MD5_RESULT, "MD5 challenge result"},
256 {IAX_IE_RSA_RESULT, "RSA challenge result"},
257 {IAX_IE_APPARENT_ADDR, "Apparent address of peer"},
258 {IAX_IE_REFRESH, "When to refresh registration"},
259 {IAX_IE_DPSTATUS, "Dialplan status"},
260 {IAX_IE_CALLNO, "Call number of peer"},
261 {IAX_IE_CAUSE, "Cause"},
262 {IAX_IE_IAX_UNKNOWN, "Unknown IAX command"},
263 {IAX_IE_MSGCOUNT, "How many messages waiting"},
264 {IAX_IE_AUTOANSWER, "Request auto-answering"},
265 {IAX_IE_MUSICONHOLD, "Request musiconhold with QUELCH"},
266 {IAX_IE_TRANSFERID, "Transfer Request Identifier"},
267 {IAX_IE_RDNIS, "Referring DNIS"},
268 {IAX_IE_PROVISIONING, "Provisioning info"},
269 {IAX_IE_AESPROVISIONING, "AES Provisioning info"},
270 {IAX_IE_DATETIME,"Date/Time"},
271 {IAX_IE_DEVICETYPE, "Device type"},
272 {IAX_IE_SERVICEIDENT, "Service Identifier"},
273 {IAX_IE_FIRMWAREVER, "Firmware revision"},
274 {IAX_IE_FWBLOCKDESC, "Firmware block description"},
275 {IAX_IE_FWBLOCKDATA, "Firmware block of data"},
276 {IAX_IE_PROVVER, "Provisioning version"},
277 {IAX_IE_CALLINGPRES, "Calling presentation"},
278 {IAX_IE_CALLINGTON, "Calling type of number"},
279 {IAX_IE_CALLINGTNS, "Calling transit network select"},
280 {IAX_IE_SAMPLINGRATE, "Supported sampling rates"},
281 {IAX_IE_CAUSECODE, "Hangup cause"},
282 {IAX_IE_ENCRYPTION, "Encryption format"},
283 {IAX_IE_ENCKEY, "Raw encryption key"},
284 {IAX_IE_CODEC_PREFS, "Codec preferences"},
285 {IAX_IE_RR_JITTER, "Received jitter"},
286 {IAX_IE_RR_LOSS, "Received loss"},
287 {IAX_IE_RR_PKTS, "Received frames"},
288 {IAX_IE_RR_DELAY, "Max playout delay in ms for received frames"},
289 {IAX_IE_RR_DROPPED, "Dropped frames"},
290 {IAX_IE_RR_OOO, "Frames received out of order"},
291 {IAX_IE_DATAFORMAT, "Data call format"},
295 static const value_string codec_types[] = {
296 {AST_FORMAT_G723_1, "G.723.1 compression"},
297 {AST_FORMAT_GSM, "GSM compression"},
298 {AST_FORMAT_ULAW, "Raw mu-law data (G.711)"},
299 {AST_FORMAT_ALAW, "Raw A-law data (G.711)"},
300 {AST_FORMAT_G726, "ADPCM (G.726, 32kbps)"},
301 {AST_FORMAT_ADPCM, "ADPCM (IMA)"},
302 {AST_FORMAT_SLINEAR, "Raw 16-bit Signed Linear (8000 Hz) PCM"},
303 {AST_FORMAT_LPC10, "LPC10, 180 samples/frame"},
304 {AST_FORMAT_G729A, "G.729a Audio"},
305 {AST_FORMAT_SPEEX, "SpeeX Free Compression"},
306 {AST_FORMAT_ILBC, "iLBC Free Compression"},
307 {AST_FORMAT_JPEG, "JPEG Images"},
308 {AST_FORMAT_PNG, "PNG Images"},
309 {AST_FORMAT_H261, "H.261 Video"},
310 {AST_FORMAT_H263, "H.263 Video"},
314 static const value_string iax_dataformats[] = {
315 {AST_DATAFORMAT_NULL, "N/A (analogue call?)"},
316 {AST_DATAFORMAT_V110, "ITU-T V.110 rate adaption"},
317 {AST_DATAFORMAT_H223_H245,"ITU-T H.223/H.245"},
322 IAX2_MINI_VOICE_PACKET,
324 IAX2_MINI_VIDEO_PACKET,
328 static const value_string iax_packet_types[] = {
329 {IAX2_FULL_PACKET, "Full packet"},
330 {IAX2_MINI_VOICE_PACKET, "Mini voice packet"},
331 {IAX2_MINI_VIDEO_PACKET, "Mini video packet"},
332 {IAX2_META_PACKET, "Meta packet"},
336 static const value_string iax_causecodes[] = {
337 {AST_CAUSE_UNALLOCATED, "Unallocated"},
338 {AST_CAUSE_NO_ROUTE_TRANSIT_NET, "No route transit net"},
339 {AST_CAUSE_NO_ROUTE_DESTINATION, "No route to destination"},
340 {AST_CAUSE_CHANNEL_UNACCEPTABLE, "Channel unacceptable"},
341 {AST_CAUSE_CALL_AWARDED_DELIVERED, "Call awarded delivered"},
342 {AST_CAUSE_NORMAL_CLEARING, "Normal clearing"},
343 {AST_CAUSE_USER_BUSY, "User busy"},
344 {AST_CAUSE_NO_USER_RESPONSE, "No user response"},
345 {AST_CAUSE_NO_ANSWER, "No answer"},
346 {AST_CAUSE_CALL_REJECTED, "Call rejected"},
347 {AST_CAUSE_NUMBER_CHANGED, "Number changed"},
348 {AST_CAUSE_DESTINATION_OUT_OF_ORDER, "Destination out of order"},
349 {AST_CAUSE_INVALID_NUMBER_FORMAT, "Invalid number format"},
350 {AST_CAUSE_FACILITY_REJECTED, "Facility rejected"},
351 {AST_CAUSE_RESPONSE_TO_STATUS_ENQUIRY, "Response to status inquiry"},
352 {AST_CAUSE_NORMAL_UNSPECIFIED, "Normal unspecified"},
353 {AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, "Normal circuit congestion"},
354 {AST_CAUSE_NETWORK_OUT_OF_ORDER, "Network out of order"},
355 {AST_CAUSE_NORMAL_TEMPORARY_FAILURE, "Normal temporary failure"},
356 {AST_CAUSE_SWITCH_CONGESTION, "Switch congestion"},
357 {AST_CAUSE_ACCESS_INFO_DISCARDED, "Access info discarded"},
358 {AST_CAUSE_REQUESTED_CHAN_UNAVAIL, "Requested channel unavailable"},
359 {AST_CAUSE_PRE_EMPTED, "Preempted"},
360 {AST_CAUSE_FACILITY_NOT_SUBSCRIBED, "Facility not subscribed"},
361 {AST_CAUSE_OUTGOING_CALL_BARRED, "Outgoing call barred"},
362 {AST_CAUSE_INCOMING_CALL_BARRED, "Incoming call barred"},
363 {AST_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized"},
364 {AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available"},
365 {AST_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented"},
366 {AST_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented"},
367 {AST_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented"},
368 {AST_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference"},
369 {AST_CAUSE_INCOMPATIBLE_DESTINATION, "Incompatible destination"},
370 {AST_CAUSE_INVALID_MSG_UNSPECIFIED, "Invalid message unspecified"},
371 {AST_CAUSE_MANDATORY_IE_MISSING, "Mandatory IE missing"},
372 {AST_CAUSE_MESSAGE_TYPE_NONEXIST, "Message type nonexistent"},
373 {AST_CAUSE_WRONG_MESSAGE, "Wrong message"},
374 {AST_CAUSE_IE_NONEXIST, "IE nonexistent"},
375 {AST_CAUSE_INVALID_IE_CONTENTS, "Invalid IE contents"},
376 {AST_CAUSE_WRONG_CALL_STATE, "Wrong call state"},
377 {AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, "Recovery on timer expire"},
378 {AST_CAUSE_MANDATORY_IE_LENGTH_ERROR, "Mandatory IE length error"},
379 {AST_CAUSE_PROTOCOL_ERROR, "Protocol error"},
380 {AST_CAUSE_INTERWORKING, "Interworking"},
385 /* ************************************************************************* */
387 /* In order to track IAX calls, we have a hash table which maps
388 * {addr,port type,port,call} to a unique circuit id.
390 * Each call has two such circuits associated with it (a forward and a
391 * reverse circuit, where 'forward' is defined as the direction the NEW
392 * packet went in), and we maintain an iax_call_data structure for each
393 * call, attached to both circuits with circuit_add_proto_data.
395 * Because {addr,port type,port,call} quadruplets can be reused
396 * (Asterisk reuses call numbers), circuit ids aren't unique to
397 * individual calls and we treat NEW packets somewhat specially. When we
398 * get such a packet, we see if there are any calls with a matching
399 * circuit id, and make sure that its circuits are marked as ended
400 * before that packet.
402 * A second complication is that we only know one quadruplet at the time
403 * the NEW packet is processed: there is therefore cunningness in
404 * iax_lookup_circuit_details() to look for replies to NEW packets and
405 * create the reverse circuit.
409 /* start with a hash of {addr,port type,port,call}->{id} */
417 /* this is where addr->data points to. it's put in here for easy freeing */
418 guint8 address_data[MAX_ADDRESS];
422 static GHashTable *iax_circuit_hashtab = NULL;
423 static guint circuitcount = 0;
425 /* the number of keys and values to reserve space for in each memory chunk.
426 We assume we won't be tracking many calls at once so this is quite low.
428 #define IAX_INIT_PACKET_COUNT 10
431 static gchar *key_to_str( const iax_circuit_key *key )
434 static gchar *strp, str[3][80];
442 /* why doesn't address_to_str take a const pointer?
443 cast the warnings into oblivion. */
445 /* XXX - is this a case for ep_alloc? */
446 g_snprintf(strp, 80, "{%s:%i,%i}",
447 address_to_str((address *)&key->addr),
455 static gint iax_circuit_equal(gconstpointer v, gconstpointer w)
457 const iax_circuit_key *v1 = (const iax_circuit_key *)v;
458 const iax_circuit_key *v2 = (const iax_circuit_key *)w;
461 result = ( ADDRESSES_EQUAL(&(v1->addr), &(v2->addr)) &&
462 v1->ptype == v2->ptype &&
463 v1->port == v2->port &&
464 v1->callno== v2->callno);
466 g_debug( "+++ Comparing for equality: %s, %s: %u",key_to_str(v1), key_to_str(v2), result);
472 static guint iax_circuit_hash (gconstpointer v)
474 const iax_circuit_key *key = (const iax_circuit_key *)v;
479 for (i = 0; i < key->addr.len; i++)
480 hash_val += (guint)(key->addr.data[i]);
482 hash_val += (guint)(key->ptype);
483 hash_val += (guint)(key->port);
484 hash_val += (guint)(key->callno);
487 g_debug( "+++ Hashing key: %s, result %#x", key_to_str(key), hash_val );
490 return (guint) hash_val;
493 /* Find, or create, a circuit for the given
494 {address,porttype,port,call} quadruplet
496 static guint iax_circuit_lookup(const address *address,
502 guint32 *circuit_id_p;
509 circuit_id_p = g_hash_table_lookup( iax_circuit_hashtab, &key);
510 if( ! circuit_id_p ) {
511 iax_circuit_key *new_key;
513 new_key = se_alloc(sizeof(iax_circuit_key));
514 new_key->addr.type = address->type;
515 new_key->addr.len = MIN(address->len,MAX_ADDRESS);
516 new_key->addr.data = new_key->address_data;
517 memmove(new_key->address_data,address->data,new_key->addr.len);
518 new_key->ptype = ptype;
519 new_key->port = port;
520 new_key->callno = callno;
522 circuit_id_p = se_alloc(sizeof(iax_circuit_key));
523 *circuit_id_p = ++circuitcount;
525 g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p);
528 g_debug("Created new circuit id %u for node %s", *circuit_id_p, key_to_str(new_key));
532 return *circuit_id_p;
536 /* ************************************************************************* */
539 guint32 current_frag_id; /* invalid unless current_frag_bytes > 0 */
540 guint32 current_frag_bytes;
541 guint32 current_frag_minlen;
544 /* This is our per-call data structure, which is attached to both the
545 * forward and reverse circuits.
547 typedef struct iax_call_data {
548 /* For this data, src and dst are relative to the original direction under
549 which this call is stored. Obviously if the reversed flag is set true by
550 iax_find_call, src and dst are reversed relative to the direction the
551 actual source and destination of the data.
553 if the codec changes mid-call, we update it here; because we store a codec
554 number with each packet too, we handle going back to earlier packets
558 iax_dataformat_t dataformat;
559 guint32 src_codec, dst_codec;
560 guint32 src_vformat, dst_vformat;
562 /* when a transfer takes place, we'll get a new circuit id; we assume that we
563 don't try to transfer more than IAX_MAX_TRANSFERS times in a call */
564 guint forward_circuit_ids[IAX_MAX_TRANSFERS];
565 guint reverse_circuit_ids[IAX_MAX_TRANSFERS];
566 guint n_forward_circuit_ids;
567 guint n_reverse_circuit_ids;
569 /* this is the subdissector for the call */
570 dissector_handle_t subdissector;
572 /* the absolute start time of the call */
575 GHashTable *fid_table;
576 GHashTable *fragment_table;
577 iax_call_dirdata dirdata[2];
580 static void iax_init_hash( void )
582 if (iax_circuit_hashtab)
583 g_hash_table_destroy(iax_circuit_hashtab);
585 iax_circuit_hashtab = g_hash_table_new(iax_circuit_hash, iax_circuit_equal);
592 /* creates a new CT_IAX2 circuit with a specified circuit id for a call
594 * typically a call has up to three associated circuits: an original source, an
595 * original destination, and the result of a transfer.
597 * For each endpoint, a CT_IAX2 circuit is created and added to the call_data
600 * 'reversed' should be true if this end is the one which would have _received_
601 * the NEW packet, or it is an endpoint to which the 'destination' is being
605 static circuit_t *iax2_new_circuit_for_call(guint circuit_id, guint framenum, iax_call_data *iax_call,
610 if(( reversed && iax_call->n_reverse_circuit_ids >= IAX_MAX_TRANSFERS) ||
611 ( !reversed && iax_call->n_forward_circuit_ids >= IAX_MAX_TRANSFERS)) {
612 g_warning("Too many transfers for iax_call");
616 res = circuit_new(CT_IAX2,
620 circuit_add_proto_data(res, proto_iax2, iax_call);
623 iax_call -> reverse_circuit_ids[iax_call->n_reverse_circuit_ids++] = circuit_id;
625 iax_call -> forward_circuit_ids[iax_call->n_forward_circuit_ids++] = circuit_id;
631 /* returns true if this circuit id is a "forward" circuit for this call: ie, it
632 * is the point which _sent_ the original 'NEW' packet, or a point to which that
633 * end was subsequently transferred */
634 static gboolean is_forward_circuit(guint circuit_id,
635 const iax_call_data *iax_call)
638 for(i=0;i<iax_call->n_forward_circuit_ids;i++){
639 if(circuit_id == iax_call->forward_circuit_ids[i])
645 /* returns true if this circuit id is a "reverse" circuit for this call: ie, it
646 * is the point which _received_ the original 'NEW' packet, or a point to which that
647 * end was subsequently transferred */
648 static gboolean is_reverse_circuit(guint circuit_id,
649 const iax_call_data *iax_call)
652 for(i=0;i<iax_call->n_reverse_circuit_ids;i++){
653 if(circuit_id == iax_call->reverse_circuit_ids[i])
660 static iax_call_data *iax_lookup_call_from_dest( guint src_circuit_id,
661 guint dst_circuit_id,
663 gboolean *reversed_p)
665 circuit_t *dst_circuit;
666 iax_call_data * iax_call;
667 gboolean reversed = FALSE;
669 dst_circuit = find_circuit( CT_IAX2,
675 g_debug( "++ destination circuit not found, must have missed NEW packet" );
683 g_debug( "++ found destination circuit" );
686 iax_call = (iax_call_data *)circuit_get_proto_data(dst_circuit,proto_iax2);
688 /* there's no way we can create a CT_IAX2 circuit without adding
689 iax call data to it; assert this */
690 DISSECTOR_ASSERT(iax_call);
692 if( is_forward_circuit(dst_circuit_id, iax_call )) {
694 g_debug( "++ destination circuit matches forward_circuit_id of call, "
695 "therefore packet is reversed" );
700 if( iax_call -> n_reverse_circuit_ids == 0 ) {
701 /* we are going in the reverse direction, and this call
702 doesn't have a reverse circuit associated with it.
705 g_debug( "++ reverse_circuit_id of call is zero, need to create a "
706 "new reverse circuit for this call" );
709 iax2_new_circuit_for_call( src_circuit_id, framenum, iax_call, TRUE );
711 g_debug( "++ done" );
713 } else if( !is_reverse_circuit(src_circuit_id, iax_call )) {
714 g_warning( "IAX Packet %u from circuit ids %u->%u "
715 "conflicts with earlier call with circuit ids %u->%u",
717 src_circuit_id,dst_circuit_id,
718 iax_call->forward_circuit_ids[0],
719 iax_call->reverse_circuit_ids[0]);
722 } else if ( is_reverse_circuit(dst_circuit_id, iax_call)) {
724 g_debug( "++ destination circuit matches reverse_circuit_id of call, "
725 "therefore packet is forward" );
729 if( !is_forward_circuit(src_circuit_id, iax_call)) {
730 g_warning( "IAX Packet %u from circuit ids %u->%u "
731 "conflicts with earlier call with circuit ids %u->%u",
733 src_circuit_id,dst_circuit_id,
734 iax_call->forward_circuit_ids[0],
735 iax_call->reverse_circuit_ids[0]);
741 DISSECTOR_ASSERT_NOT_REACHED();
745 *reversed_p = reversed;
751 /* looks up an iax_call for this packet */
752 static iax_call_data *iax_lookup_call( packet_info *pinfo,
755 gboolean *reversed_p)
757 gboolean reversed = FALSE;
758 iax_call_data *iax_call = NULL;
759 guint src_circuit_id;
762 g_debug( "++ iax_lookup_circuit_details: Looking up circuit for frame %u, "
763 "from {%s:%u:%u} to {%s:%u:%u}", pinfo->fd->num,
764 address_to_str(&pinfo->src),pinfo->srcport,scallno,
765 address_to_str(&pinfo->dst),pinfo->destport,dcallno);
769 src_circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
770 pinfo->srcport,scallno);
773 /* the most reliable indicator of call is the destination callno, if
776 guint dst_circuit_id;
778 g_debug( "++ dcallno non-zero, looking up destination circuit" );
781 dst_circuit_id = iax_circuit_lookup(&pinfo->dst,pinfo->ptype,
782 pinfo->destport,dcallno);
784 iax_call = iax_lookup_call_from_dest(src_circuit_id, dst_circuit_id,
785 pinfo->fd->num, &reversed);
787 circuit_t *src_circuit;
789 /* in all other circumstances, the source circuit should already
790 * exist: its absense indicates that we missed the all-important NEW
794 src_circuit = find_circuit( CT_IAX2,
799 iax_call = (iax_call_data *)circuit_get_proto_data(src_circuit,proto_iax2);
801 /* there's no way we can create a CT_IAX2 circuit without adding
802 iax call data to it; assert this */
803 DISSECTOR_ASSERT(iax_call);
805 if( is_forward_circuit(src_circuit_id,iax_call))
807 else if(is_reverse_circuit(src_circuit_id,iax_call))
810 /* there's also no way we can attach an iax_call_data to a circuit
811 without the circuit being either the forward or reverse circuit
812 for that call; assert this too.
814 DISSECTOR_ASSERT_NOT_REACHED();
820 *reversed_p = reversed;
824 g_debug( "++ Found call for packet: id %u, reversed=%c", iax_call->forward_circuit_ids[0], reversed?'1':'0' );
826 g_debug( "++ Call not found. Must have missed the NEW packet?" );
833 /* initialise the per-direction parts of an iax_call_data structure */
834 static void init_dir_data(iax_call_dirdata *dirdata)
836 dirdata -> current_frag_bytes=0;
837 dirdata -> current_frag_minlen=0;
841 /* handles a NEW packet by creating a new iax call and forward circuit.
842 the reverse circuit is not created until the ACK is received and
843 is created by iax_lookup_circuit_details. */
844 static iax_call_data *iax_new_call( packet_info *pinfo,
849 static const nstime_t millisecond = {0, 1000000};
852 g_debug( "+ new_circuit: Handling NEW packet, frame %u", pinfo->fd->num );
855 circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
856 pinfo->srcport,scallno);
858 call = se_alloc(sizeof(iax_call_data));
859 call -> dataformat = 0;
860 call -> src_codec = 0;
861 call -> dst_codec = 0;
862 call -> n_forward_circuit_ids = 0;
863 call -> n_reverse_circuit_ids = 0;
864 call -> subdissector = NULL;
865 call -> start_time = pinfo->fd->abs_ts;
866 nstime_delta(&call -> start_time, &call -> start_time, &millisecond);
867 call -> fid_table = g_hash_table_new(g_direct_hash, g_direct_equal);
868 init_dir_data(&call->dirdata[0]);
869 init_dir_data(&call->dirdata[1]);
870 call->fragment_table = NULL;
871 fragment_table_init(&(call->fragment_table));
873 iax2_new_circuit_for_call(circuit_id,pinfo->fd->num,call,FALSE);
879 /* ************************************************************************* */
881 /* per-packet data */
882 typedef struct iax_packet_data {
883 gboolean first_time; /* we're dissecting this packet for the first time; so
884 things like codec and transfer requests should be
885 propogated into the call data */
886 iax_call_data *call_data;
889 nstime_t abstime; /* the absolute time of this packet, based on its
890 * timestamp and the NEW packet's time (-1 if unknown) */
893 static iax_packet_data *iax_new_packet_data(iax_call_data *call, gboolean reversed)
895 iax_packet_data *p = se_alloc(sizeof(iax_packet_data));
899 p->reversed=reversed;
905 static void iax2_populate_pinfo_from_packet_data(packet_info *pinfo, const iax_packet_data * p)
907 /* info for subdissectors. We always pass on the original forward circuit,
908 * and steal the p2p_dir flag to indicate the direction */
909 if( p->call_data == NULL ) {
910 /* if we missed the NEW packet for this call, call_data will be null. it's
911 * tbd what the best thing to do here is. */
912 pinfo -> ctype = CT_NONE;
914 pinfo -> ctype = CT_IAX2;
915 pinfo -> circuit_id = (guint32)p->call_data->forward_circuit_ids[0];
916 pinfo -> p2p_dir = p->reversed?P2P_DIR_RECV:P2P_DIR_SENT;
918 if (check_col (pinfo->cinfo, COL_CIRCUIT_ID)) {
919 col_set_str (pinfo->cinfo, COL_CIRCUIT_ID, "" );
920 col_add_fstr(pinfo->cinfo, COL_CIRCUIT_ID, "%u", pinfo->circuit_id);
922 if (check_col (pinfo->cinfo, COL_IF_DIR))
923 col_set_str (pinfo->cinfo, COL_IF_DIR, p->reversed ? "rev" : "fwd" );
928 /* ************************************************************************* */
930 /* this is passed up from the IE dissector to the main dissector */
933 address peer_address;
934 port_type peer_ptype;
941 static guint32 dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
944 proto_tree * iax2_tree,
945 proto_tree * main_tree);
948 static guint32 dissect_minipacket (tvbuff_t * tvb, guint32 offset,
951 proto_tree * iax2_tree,
952 proto_tree * main_tree);
954 static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
957 proto_tree * iax2_tree,
958 proto_tree * main_tree);
960 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
961 packet_info *pinfo, proto_tree *iax2_tree,
962 proto_tree *tree, guint32 ts, gboolean video,
963 iax_packet_data *iax_packet);
968 dissect_iax2 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
970 proto_item *iax2_item = NULL;
971 proto_tree *iax2_tree = NULL;
972 proto_tree *full_mini_subtree = NULL;
973 guint32 offset = 0, len;
978 /* set up the protocol and info fields in the summary pane */
979 if (check_col (pinfo->cinfo, COL_PROTOCOL))
981 col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2);
983 if (check_col (pinfo->cinfo, COL_INFO))
985 col_clear (pinfo->cinfo, COL_INFO);
988 /* add the 'iax2' tree to the main tree */
991 iax2_item = proto_tree_add_item (tree, proto_iax2, tvb, offset, -1, FALSE);
992 iax2_tree = proto_item_add_subtree (iax2_item, ett_iax2);
995 stmp = tvb_get_ntohs(tvb, offset);
997 /* starting with 0x0000 indicates either a mini video packet or a 'meta'
998 * packet, whatever that means */
1000 stmp = tvb_get_ntohs(tvb, offset);
1001 if( stmp & 0x8000 ) {
1002 /* mini video packet */
1003 type = IAX2_MINI_VIDEO_PACKET;
1004 scallno = stmp & 0x7FFF;
1008 type = IAX2_META_PACKET;
1011 /* The source call/fullpacket flag is common to both mini and full packets */
1012 scallno = tvb_get_ntohs(tvb, offset);
1014 if( scallno & 0x8000 )
1015 type = IAX2_FULL_PACKET;
1017 type = IAX2_MINI_VOICE_PACKET;
1023 proto_item *full_mini_base;
1025 full_mini_base = proto_tree_add_uint(iax2_tree, hf_iax2_packet_type, tvb, 0, offset, type);
1026 full_mini_subtree = proto_item_add_subtree(full_mini_base, ett_iax2_full_mini_subtree);
1029 proto_tree_add_item (full_mini_subtree, hf_iax2_scallno, tvb, offset-2, 2, FALSE);
1033 case IAX2_FULL_PACKET:
1034 len = dissect_fullpacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1036 case IAX2_MINI_VOICE_PACKET:
1037 len = dissect_minipacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1039 case IAX2_MINI_VIDEO_PACKET:
1040 len = dissect_minivideopacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1042 case IAX2_META_PACKET:
1043 /* not implemented yet */
1050 /* update the 'length' of the main IAX2 header field so that it covers just the headers,
1051 not the audio data. */
1052 proto_item_set_len(iax2_item, len);
1055 static proto_item *dissect_datetime_ie(tvbuff_t *tvb, guint32 offset, proto_tree *ies_tree)
1061 proto_tree_add_item (ies_tree, hf_iax2_ies[IAX_IE_DATETIME], tvb, offset + 2, 4, FALSE);
1062 ie_val = tvb_get_ntohl(tvb, offset+2);
1064 /* who's crazy idea for a time encoding was this? */
1065 tm.tm_sec = (ie_val & 0x1f) << 1;
1066 tm.tm_min = (ie_val>>5) & 0x3f;
1067 tm.tm_hour = (ie_val>>11) & 0x1f;
1068 tm.tm_mday = (ie_val>>16) & 0x1f;
1069 tm.tm_mon = ((ie_val>>21) & 0xf) - 1;
1070 tm.tm_year = ((ie_val>>25) & 0x7f) + 100;
1071 tm.tm_isdst= -1; /* there's no info on whether DST was in force; assume it's
1072 * the same as currently */
1074 datetime.secs = mktime(&tm);
1076 return proto_tree_add_time (ies_tree, hf_iax2_ie_datetime, tvb, offset+2, 4, &datetime);
1080 /* dissect the information elements in an IAX frame. Returns the updated offset */
1081 static guint32 dissect_ies (tvbuff_t * tvb, guint32 offset,
1082 proto_tree * iax_tree,
1083 iax2_ie_data *ie_data)
1085 DISSECTOR_ASSERT(ie_data);
1087 while (offset < tvb_reported_length (tvb)) {
1089 int ies_type = tvb_get_guint8(tvb, offset);
1090 int ies_len = tvb_get_guint8(tvb, offset + 1);
1093 proto_item *ti, *ie_item = NULL;
1094 proto_tree *ies_tree;
1095 int ie_hf = hf_iax2_ies[ies_type];
1097 ti = proto_tree_add_text(iax_tree, tvb, offset, ies_len+2, " " );
1099 ies_tree = proto_item_add_subtree(ti, ett_iax2_ie);
1101 proto_tree_add_text(ies_tree, tvb, offset, 1, "IE id: %s (0x%02X)",
1102 val_to_str(ies_type, iax_ies_type, "Unknown"),
1105 proto_tree_add_text(ies_tree, tvb, offset+1, 1, "Length: %u",ies_len);
1108 /* hf_iax2_ies[] is an array, indexed by IE number, of header-fields, one
1109 per IE. Apart from a couple of special cases which require more
1110 complex decoding, we can just look up an entry from the array, and add
1115 case IAX_IE_DATETIME:
1116 ie_item = dissect_datetime_ie(tvb,offset,ies_tree);
1120 case IAX_IE_CAPABILITY:
1122 proto_tree *codec_tree;
1124 if (ies_len != 4) THROW(ReportedBoundsError);
1127 proto_tree_add_item (ies_tree, ie_hf,
1128 tvb, offset + 2, ies_len, FALSE);
1130 proto_item_add_subtree (ie_item, ett_iax2_codecs);
1132 proto_tree_add_item(codec_tree, hf_iax2_cap_g723_1, tvb, offset + 2, ies_len, FALSE );
1133 proto_tree_add_item(codec_tree, hf_iax2_cap_gsm, tvb, offset + 2, ies_len, FALSE );
1134 proto_tree_add_item(codec_tree, hf_iax2_cap_ulaw, tvb, offset + 2, ies_len, FALSE );
1135 proto_tree_add_item(codec_tree, hf_iax2_cap_alaw, tvb, offset + 2, ies_len, FALSE );
1136 proto_tree_add_item(codec_tree, hf_iax2_cap_g726, tvb, offset + 2, ies_len, FALSE );
1137 proto_tree_add_item(codec_tree, hf_iax2_cap_adpcm, tvb, offset + 2, ies_len, FALSE );
1138 proto_tree_add_item(codec_tree, hf_iax2_cap_slinear, tvb, offset + 2, ies_len, FALSE );
1139 proto_tree_add_item(codec_tree, hf_iax2_cap_lpc10, tvb, offset + 2, ies_len, FALSE );
1140 proto_tree_add_item(codec_tree, hf_iax2_cap_g729a, tvb, offset + 2, ies_len, FALSE );
1141 proto_tree_add_item(codec_tree, hf_iax2_cap_speex, tvb, offset + 2, ies_len, FALSE );
1142 proto_tree_add_item(codec_tree, hf_iax2_cap_ilbc, tvb, offset + 2, ies_len, FALSE );
1143 proto_tree_add_item(codec_tree, hf_iax2_cap_jpeg, tvb, offset + 2, ies_len, FALSE );
1144 proto_tree_add_item(codec_tree, hf_iax2_cap_png, tvb, offset + 2, ies_len, FALSE );
1145 proto_tree_add_item(codec_tree, hf_iax2_cap_h261, tvb, offset + 2, ies_len, FALSE );
1146 proto_tree_add_item(codec_tree, hf_iax2_cap_h263, tvb, offset + 2, ies_len, FALSE );
1150 case IAX_IE_APPARENT_ADDR:
1152 proto_tree *sockaddr_tree = NULL;
1155 ie_item = proto_tree_add_text(ies_tree, tvb, offset + 2, 16, "Apparent Address");
1156 sockaddr_tree = proto_item_add_subtree(ie_item, ett_iax2_ies_apparent_addr);
1158 /* the family is little-endian. That's probably broken, given
1159 everything else is big-endian, but that's not our fault.
1161 family = tvb_get_letohs(tvb, offset+2);
1162 proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINFAMILY, tvb, offset + 2, 2, family);
1165 /* these come from linux/socket.h */
1166 case 2: /* AF_INET */
1170 /* IAX is always over UDP */
1171 ie_data->peer_ptype = PT_UDP;
1172 ie_data->peer_port = tvb_get_ntohs(tvb, offset+4);
1173 proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINPORT, tvb, offset + 4, 2, ie_data->peer_port);
1174 /* the ip address is big-endian, but then so is address.data */
1175 SET_ADDRESS(&ie_data->peer_address,AT_IPv4,4,tvb_get_ptr(tvb,offset+6,4));
1176 memcpy(&addr, ie_data->peer_address.data, 4);
1177 proto_tree_add_ipv4(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINADDR, tvb, offset + 6, 4, addr);
1182 g_warning("Not supported in IAX dissector: peer address family of %u", family);
1188 case IAX_IE_DATAFORMAT:
1189 if (ies_len != 4) THROW(ReportedBoundsError);
1190 ie_item = proto_tree_add_item (ies_tree, ie_hf, tvb,
1191 offset + 2, ies_len, FALSE);
1192 ie_data -> dataformat = tvb_get_ntohl(tvb, offset+2);
1197 /* throw an error if the IE isn't the expected length */
1198 gint explen = ftype_length(proto_registrar_get_nth(ie_hf)->type);
1199 if(explen != 0 && ies_len != explen)
1200 THROW(ReportedBoundsError);
1201 ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, FALSE);
1203 /* we don't understand this ie: add a generic one */
1206 const guint8 *ie_name = (guint8*)val_to_str(ies_type, iax_ies_type, "Unknown");
1210 value = tvb_get_guint8(tvb, offset + 2);
1212 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTE,
1213 tvb, offset+2, 1, value,
1214 "%s: %#02x", ie_name, value );
1218 value = tvb_get_ntohs(tvb, offset + 2);
1220 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I16,
1221 tvb, offset+2, 2, value,
1222 "%s: %#04x", ie_name, value );
1226 value = tvb_get_ntohl(tvb, offset + 2);
1228 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I32,
1229 tvb, offset+2, 4, value,
1230 "%s: %#08x", ie_name, value );
1234 ptr = tvb_get_ptr(tvb, offset + 2, ies_len);
1236 proto_tree_add_string_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTES,
1237 tvb, offset+2, ies_len, (char*)ptr,
1238 "%s: %s", ie_name, ptr );
1245 /* by now, we *really* ought to have added an item */
1246 DISSECTOR_ASSERT(ie_item != NULL);
1248 /* Retrieve the text from the item we added, and append it to the main IE
1250 if(!PROTO_ITEM_IS_HIDDEN(ti)) {
1251 field_info *ie_finfo = PITEM_FINFO(ie_item);
1253 /* if the representation of the item has already been set, use that;
1254 else we have to allocate a block to put the text into */
1255 if( ie_finfo -> rep != NULL )
1256 proto_item_set_text(ti, "Information Element: %s",
1257 ie_finfo->rep->representation);
1259 guint8 *ie_val = NULL;
1260 ie_val = g_malloc(ITEM_LABEL_LENGTH);
1261 proto_item_fill_label(ie_finfo, (gchar*)ie_val);
1262 proto_item_set_text(ti, "Information Element: %s",
1269 offset += ies_len + 2;
1274 static guint32 uncompress_subclass(guint8 csub)
1276 /* If the SC_LOG flag is set, return 2^csub otherwise csub */
1278 /* special case for 'compressed' -1 */
1282 return 1 << (csub & 0x1F);
1285 return (guint32)csub;
1288 /* returns the new offset */
1289 static guint32 dissect_iax2_command(tvbuff_t * tvb, guint32 offset,
1290 packet_info * pinfo, proto_tree *tree,
1291 iax_packet_data *iax_packet)
1293 guint8 csub = tvb_get_guint8(tvb, offset);
1294 guint8 address_data[MAX_ADDRESS];
1295 iax2_ie_data ie_data;
1296 iax_call_data *iax_call;
1298 ie_data.peer_address.type = AT_NONE;
1299 ie_data.peer_address.len = 0;
1300 ie_data.peer_address.data = address_data;
1301 ie_data.peer_ptype = 0;
1302 ie_data.peer_port = 0;
1303 ie_data.peer_callno = 0;
1304 ie_data.dataformat = (guint32)-1;
1305 iax_call = iax_packet -> call_data;
1307 /* add the subclass */
1308 proto_tree_add_uint (tree, hf_iax2_iax_csub, tvb, offset, 1, csub);
1311 if (check_col (pinfo->cinfo, COL_INFO))
1312 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1313 val_to_str (csub, iax_iax_subclasses, "unknown (0x%02x)"));
1315 if (offset >= tvb_reported_length (tvb))
1318 offset += dissect_ies(tvb, offset, tree, &ie_data);
1320 /* if this is a data call, set up a subdissector for the circuit */
1321 if(iax_call && ie_data.dataformat != (guint32)-1 && iax_call -> subdissector == NULL) {
1322 iax_call -> subdissector = dissector_get_port_handle(iax2_dataformat_dissector_table, ie_data.dataformat );
1323 iax_call -> dataformat = ie_data.dataformat;
1326 /* if this is a transfer request, record it in the call data */
1327 if( csub == IAX_COMMAND_TXREQ && iax_packet -> first_time ) {
1328 if( ie_data.peer_address.type != AT_NONE && ie_data.peer_callno != 0 ) {
1329 guint tx_circuit = iax_circuit_lookup(&ie_data.peer_address,
1332 ie_data.peer_callno);
1335 g_debug("found transfer request for call %u->%u, to new id %u",
1336 iax_call->forward_circuit_ids[0],
1337 iax_call->reverse_circuit_ids[0],
1341 iax2_new_circuit_for_call(tx_circuit,pinfo->fd->num,iax_call,iax_packet->reversed);
1348 static void iax2_add_ts_fields(packet_info * pinfo, proto_tree * iax2_tree, iax_packet_data *iax_packet, guint16 shortts)
1350 guint32 longts = shortts;
1354 if(iax_packet->call_data == NULL) {
1355 /* no call info for this frame; perhaps we missed the NEW packet */
1359 if(iax_packet->abstime.secs == -1) {
1360 time_t start_secs = iax_packet->call_data->start_time.secs;
1361 gint32 abs_secs = (gint32) (start_secs + longts/1000);
1363 /* deal with short timestamps by assuming that packets are never more than
1364 * 16 seconds late */
1365 while(abs_secs < pinfo->fd->abs_ts.secs - 16) {
1367 abs_secs = (gint32) (start_secs + longts/1000);
1370 iax_packet->abstime.secs=abs_secs;
1371 iax_packet->abstime.nsecs=iax_packet->call_data->start_time.nsecs + (longts % 1000) * 1000000;
1372 if(iax_packet->abstime.nsecs >= 1000000000) {
1373 iax_packet->abstime.nsecs -= 1000000000;
1374 iax_packet->abstime.secs ++;
1378 item = proto_tree_add_time(iax2_tree, hf_iax2_absts, NULL, 0, 0, &iax_packet->abstime);
1379 PROTO_ITEM_SET_GENERATED(item);
1381 ts = pinfo->fd->abs_ts;
1382 nstime_delta(&ts, &ts, &iax_packet->abstime);
1384 item = proto_tree_add_time(iax2_tree, hf_iax2_lateness, NULL, 0, 0, &ts);
1385 PROTO_ITEM_SET_GENERATED(item);
1388 /* returns the new offset */
1390 dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
1392 packet_info * pinfo, proto_tree * iax2_tree,
1393 proto_tree * main_tree)
1395 guint32 retransmission = 0;
1402 proto_tree *packet_type_tree = NULL;
1403 iax_call_data *iax_call;
1404 iax_packet_data *iax_packet;
1406 gboolean rtp_marker;
1409 * remove the top bit for retransmission detection
1411 dcallno = tvb_get_ntohs(tvb, offset);
1412 retransmission = dcallno & 0x8000;
1413 dcallno = dcallno & 0x7FFF;
1414 ts = tvb_get_ntohl(tvb, offset+2);
1415 type = tvb_get_guint8(tvb, offset + 8);
1416 csub = tvb_get_guint8(tvb, offset + 9);
1418 /* see if we've seen this packet before */
1419 iax_packet = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
1421 /* if not, find or create an iax_call info structure for this IAX session. */
1423 if( type == AST_FRAME_IAX && csub == IAX_COMMAND_NEW ) {
1424 /* NEW packets start a new call */
1425 iax_call = iax_new_call(pinfo,scallno);
1428 iax_call = iax_lookup_call(pinfo, scallno, dcallno,
1432 iax_packet = iax_new_packet_data(iax_call, reversed);
1433 p_add_proto_data(pinfo->fd,proto_iax2,iax_packet);
1435 iax_call = iax_packet->call_data;
1436 reversed = iax_packet->reversed;
1439 iax2_populate_pinfo_from_packet_data(pinfo, iax_packet);
1442 proto_item *packet_type_base;
1444 proto_tree_add_item (iax2_tree, hf_iax2_dcallno, tvb, offset, 2, FALSE );
1446 proto_tree_add_boolean(iax2_tree, hf_iax2_retransmission, tvb, offset, 2, FALSE );
1450 proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1451 iax_call->forward_circuit_ids[0] );
1452 PROTO_ITEM_SET_GENERATED(item);
1455 proto_tree_add_uint (iax2_tree, hf_iax2_ts, tvb, offset+2, 4, ts);
1456 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1458 proto_tree_add_item (iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1,
1461 proto_tree_add_item (iax2_tree, hf_iax2_iseqno, tvb, offset+7, 1,
1463 packet_type_base = proto_tree_add_uint (iax2_tree, hf_iax2_type, tvb,
1466 /* add the type-specific subtree */
1467 packet_type_tree = proto_item_add_subtree (packet_type_base, ett_iax2_type);
1470 /* add frame type to info line */
1471 if (check_col (pinfo->cinfo, COL_INFO)) {
1472 col_add_fstr (pinfo->cinfo, COL_INFO, "%s, source call# %d, timestamp %ums",
1473 val_to_str (type, iax_frame_types, "Unknown (0x%02x)"),
1479 offset=dissect_iax2_command(tvb,offset+9,pinfo,packet_type_tree,iax_packet);
1482 case AST_FRAME_DTMF:
1483 proto_tree_add_item (packet_type_tree, hf_iax2_dtmf_csub, tvb, offset+9, 1, FALSE);
1486 if (check_col (pinfo->cinfo, COL_INFO))
1487 col_append_fstr (pinfo->cinfo, COL_INFO, " digit %c", csub );
1490 case AST_FRAME_CONTROL:
1491 /* add the subclass */
1492 proto_tree_add_uint (packet_type_tree, hf_iax2_cmd_csub, tvb,
1496 if (check_col (pinfo->cinfo, COL_INFO))
1497 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1498 val_to_str (csub, iax_cmd_subclasses, "unknown (0x%02x)"));
1501 case AST_FRAME_VOICE:
1503 iax_packet -> codec = codec = uncompress_subclass(csub);
1505 if( packet_type_tree ) {
1507 proto_tree_add_item (packet_type_tree, hf_iax2_voice_csub, tvb, offset+9, 1, FALSE);
1508 item = proto_tree_add_uint (packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, codec);
1509 PROTO_ITEM_SET_GENERATED(item);
1516 iax_call->dst_codec = codec;
1518 iax_call->src_codec = codec;
1522 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, FALSE,iax_packet);
1525 case AST_FRAME_VIDEO:
1526 /* bit 6 of the csub is used to represent the rtp 'marker' bit */
1527 rtp_marker = csub & 0x40 ? TRUE:FALSE;
1528 iax_packet -> codec = codec = uncompress_subclass((guint8) (csub & ~40));
1530 if( packet_type_tree ) {
1532 proto_tree_add_item (packet_type_tree, hf_iax2_video_csub, tvb, offset+9, 1, FALSE);
1533 proto_tree_add_item (packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, FALSE);
1534 item = proto_tree_add_uint (packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, codec);
1535 PROTO_ITEM_SET_GENERATED(item);
1540 if( iax_call && iax_packet -> first_time ) {
1542 iax_call->dst_vformat = codec;
1544 iax_call->src_vformat = codec;
1548 if( rtp_marker && check_col (pinfo->cinfo, COL_INFO))
1549 col_append_fstr (pinfo->cinfo, COL_INFO, ", Mark" );
1552 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, TRUE, iax_packet);
1557 proto_tree_add_uint (packet_type_tree, hf_iax2_csub, tvb, offset+9,
1561 if (check_col (pinfo->cinfo, COL_INFO))
1562 col_append_fstr (pinfo->cinfo, COL_INFO, " subclass %d", csub );
1566 /* next time we come to parse this packet, don't propogate the codec into the
1568 iax_packet->first_time = FALSE;
1573 static iax_packet_data *iax2_get_packet_data_for_minipacket(packet_info * pinfo,
1577 /* see if we've seen this packet before */
1578 iax_packet_data *p = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
1581 /* if not, find or create an iax_call info structure for this IAX session. */
1583 iax_call_data *iax_call;
1585 iax_call = iax_lookup_call(pinfo, scallno, 0, &reversed);
1587 p = iax_new_packet_data(iax_call,reversed);
1588 p_add_proto_data(pinfo->fd,proto_iax2,p);
1590 /* set the codec for this frame to be whatever the last full frame used */
1593 p->codec = reversed ? iax_call -> dst_vformat : iax_call -> src_vformat;
1595 p->codec = reversed ? iax_call -> dst_codec : iax_call -> src_codec;
1599 iax2_populate_pinfo_from_packet_data(pinfo, p);
1604 static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
1605 guint16 scallno, packet_info * pinfo,
1606 proto_tree * iax2_tree, proto_tree *main_tree)
1609 iax_packet_data *iax_packet;
1610 gboolean rtp_marker;
1613 ts = tvb_get_ntohs(tvb, offset);
1615 /* bit 15 of the ts is used to represent the rtp 'marker' bit */
1616 rtp_marker = ts & 0x8000 ? TRUE:FALSE;
1619 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, TRUE);
1622 if( iax_packet->call_data ) {
1624 proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1625 iax_packet->call_data->forward_circuit_ids[0] );
1626 PROTO_ITEM_SET_GENERATED(item);
1629 proto_tree_add_item (iax2_tree, hf_iax2_minividts, tvb, offset, 2, FALSE);
1630 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1631 proto_tree_add_item (iax2_tree, hf_iax2_minividmarker, tvb, offset, 2, FALSE);
1636 if (check_col (pinfo->cinfo, COL_INFO))
1637 col_add_fstr (pinfo->cinfo, COL_INFO,
1638 "Mini video packet, source call# %d, timestamp %ums%s",
1639 scallno, ts, rtp_marker?", Mark":"");
1642 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, TRUE, iax_packet);
1644 /* next time we come to parse this packet, don't propogate the codec into the
1646 iax_packet->first_time = FALSE;
1652 dissect_minipacket (tvbuff_t * tvb, guint32 offset, guint16 scallno, packet_info * pinfo, proto_tree * iax2_tree,
1653 proto_tree *main_tree)
1656 iax_packet_data *iax_packet;
1659 ts = tvb_get_ntohs(tvb, offset);
1661 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, FALSE);
1664 if( iax_packet->call_data ) {
1665 item = proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1666 iax_packet->call_data->forward_circuit_ids[0] );
1667 PROTO_ITEM_SET_GENERATED(item);
1670 proto_tree_add_uint (iax2_tree, hf_iax2_minits, tvb, offset, 2, ts);
1671 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet,(guint16)ts);
1676 if (check_col (pinfo->cinfo, COL_INFO))
1677 col_add_fstr (pinfo->cinfo, COL_INFO,
1678 "Mini packet, source call# %d, timestamp %ums",
1682 /* XXX fix the timestamp logic */
1683 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, FALSE, iax_packet);
1686 /* next time we come to parse this packet, don't propogate the codec into the
1688 iax_packet->first_time = FALSE;
1693 static void process_iax_pdu( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1694 gboolean video, iax_packet_data *iax_packet )
1696 guint32 codec = iax_packet -> codec;
1697 iax_call_data *iax_call = iax_packet -> call_data;
1699 #ifdef DEBUG_DESEGMENT
1700 g_debug("calling process_iax_pdu; len = %u", tvb_reported_length(tvb));
1703 if( !video && iax_call && iax_call->subdissector ) {
1704 call_dissector(iax_call->subdissector, tvb, pinfo, tree);
1705 }else if( codec != 0 && dissector_try_port(iax2_codec_dissector_table, codec, tvb, pinfo, tree )) {
1706 /* codec dissector handled our data */
1708 /* we don't know how to dissect our data: dissect it as data */
1709 call_dissector(data_handle,tvb, pinfo, tree);
1712 #ifdef DEBUG_DESEGMENT
1713 g_debug("called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u",
1714 pinfo->desegment_len, pinfo->desegment_offset);
1718 static void desegment_iax(tvbuff_t *tvb, packet_info *pinfo, proto_tree *iax2_tree,
1719 proto_tree *tree, gboolean video, iax_packet_data *iax_packet )
1722 iax_call_data *iax_call = iax_packet -> call_data;
1723 iax_call_dirdata *dirdata;
1724 gpointer value=NULL;
1725 guint32 frag_offset=0;
1726 fragment_data *fd_head;
1727 gboolean must_desegment = FALSE;
1729 DISSECTOR_ASSERT(iax_call);
1731 pinfo->can_desegment = 2;
1732 pinfo->desegment_offset = 0;
1733 pinfo->desegment_len = 0;
1735 #ifdef DEBUG_DESEGMENT
1736 g_debug("dissecting packet %u", pinfo->fd->num);
1739 dirdata = &(iax_call->dirdata[!!(iax_packet->reversed)]);
1741 if((!pinfo->fd->flags.visited && dirdata->current_frag_bytes > 0) ||
1742 (value = g_hash_table_lookup(iax_call->fid_table,
1743 GUINT_TO_POINTER(pinfo->fd->num))) != NULL ) {
1744 /* then we are continuing an already-started pdu */
1746 guint32 frag_len = tvb_reported_length( tvb );
1749 #ifdef DEBUG_DESEGMENT
1750 g_debug("visited: %i; c_f_b: %u; hash: %u->%u", pinfo->fd->flags.visited?1:0,
1751 dirdata->current_frag_bytes, pinfo->fd->num, fid);
1754 if(!pinfo->fd->flags.visited) {
1756 fid = dirdata->current_frag_id;
1757 tot_len = dirdata->current_frag_minlen;
1758 g_hash_table_insert( iax_call->fid_table, GUINT_TO_POINTER(pinfo->fd->num), GUINT_TO_POINTER(fid) );
1759 frag_offset = dirdata->current_frag_bytes;
1760 dirdata->current_frag_bytes += frag_len;
1761 complete = dirdata->current_frag_bytes > tot_len;
1762 #ifdef DEBUG_DESEGMENT
1763 g_debug("hash: %u->%u; frag_offset: %u; c_f_b: %u; totlen: %u",
1764 pinfo->fd->num, fid, frag_offset, dirdata->current_frag_bytes, tot_len );
1767 fid = GPOINTER_TO_UINT(value);
1768 /* these values are unused by fragment_add if pinfo->fd->flags.visited */
1769 dirdata->current_frag_bytes = 0;
1773 /* fragment_add checks for already-added */
1774 fd_head = fragment_add( tvb, 0, pinfo, fid,
1775 iax_call->fragment_table,
1777 frag_len, !complete );
1779 if(fd_head && (pinfo->fd->num == fd_head->reassembled_in)) {
1781 tvbuff_t *next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
1782 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1783 add_new_data_source(pinfo, next_tvb, "Reassembled IAX2");
1785 process_iax_pdu(next_tvb,pinfo,tree,video,iax_packet);
1787 /* calculate the amount of data which was available to the higher-level
1788 dissector before we added this segment; if the returned offset is
1789 within that section, the higher-level dissector was unable to find any
1790 pdus; if it's after that, it found one or more complete PDUs.
1792 old_len = (gint32)(tvb_reported_length(next_tvb) - frag_len);
1793 if( pinfo->desegment_len &&
1794 pinfo->desegment_offset < old_len ) {
1795 /* oops, it wasn't actually complete */
1796 fragment_set_partial_reassembly(pinfo, fid, iax_call->fragment_table);
1797 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1798 /* only one more byte should be enough for a retry */
1799 dirdata->current_frag_minlen = fd_head->datalen + 1;
1801 dirdata->current_frag_minlen = fd_head->datalen + pinfo->desegment_len;
1804 /* we successfully dissected some data; create the proto tree items for
1805 * the fragments, and flag any remaining data for desegmentation */
1807 proto_item *iax_tree_item, *frag_tree_item;
1808 /* this nargery is to insert the fragment tree into the main tree
1809 * between the IAX protocol entry and the subdissector entry */
1810 show_fragment_tree(fd_head, &iax2_fragment_items, tree, pinfo, next_tvb, &frag_tree_item);
1811 iax_tree_item = proto_item_get_parent( proto_tree_get_parent( iax2_tree ));
1812 if( frag_tree_item && iax_tree_item )
1813 proto_tree_move_item( tree, iax_tree_item, frag_tree_item );
1815 dirdata->current_frag_minlen = dirdata->current_frag_id = dirdata->current_frag_bytes = 0;
1817 if( pinfo->desegment_len ) {
1818 /* there's a bit of data left to desegment */
1819 must_desegment = TRUE;
1820 /* make desegment_offset relative to our tvb */
1821 pinfo->desegment_offset -= old_len;
1824 /* don't add a 'reassembled in' item for this pdu */
1829 /* This segment was not found in our table, so it doesn't
1830 contain a continuation of a higher-level PDU.
1831 Call the normal subdissector.
1834 process_iax_pdu(tvb,pinfo,tree,video,iax_packet);
1836 if(pinfo->desegment_len) {
1837 /* the higher-level dissector has asked for some more data - ie,
1838 the end of this segment does not coincide with the end of a
1839 higher-level PDU. */
1840 must_desegment = TRUE;
1846 /* must_desegment is set if the end of this segment (or the whole of it)
1847 * contained the start of a higher-level PDU; we must add whatever is left of
1848 * this segment (after pinfo->desegment_offset) to a fragment table for disassembly. */
1849 if(must_desegment) {
1850 guint32 fid = pinfo->fd->num; /* a new fragment id */
1851 guint32 deseg_offset = pinfo->desegment_offset;
1852 guint32 frag_len = tvb_reported_length_remaining(tvb,deseg_offset);
1853 dirdata->current_frag_id = fid;
1854 dirdata->current_frag_bytes = frag_len;
1856 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1857 /* only one more byte should be enough for a retry */
1858 dirdata->current_frag_minlen = frag_len + 1;
1860 dirdata->current_frag_minlen = frag_len + pinfo->desegment_len;
1863 fd_head = fragment_add(tvb, deseg_offset, pinfo, fid,
1864 iax_call->fragment_table,
1865 0, frag_len, TRUE );
1866 #ifdef DEBUG_DESEGMENT
1867 g_debug("Start offset of undissected bytes: %u; "
1868 "Bytes remaining in this segment: %u; min required bytes: %u\n",
1869 deseg_offset, frag_len, frag_len + pinfo->desegment_len);
1873 /* add a 'reassembled in' item if necessary */
1874 if( fd_head != NULL ) {
1875 guint32 deseg_offset = pinfo->desegment_offset;
1876 if( fd_head->reassembled_in != 0 &&
1877 !(fd_head->flags & FD_PARTIAL_REASSEMBLY) ) {
1878 proto_item *iax_tree_item;
1879 iax_tree_item = proto_tree_add_uint( tree, hf_iax2_reassembled_in,
1880 tvb, deseg_offset, tvb_reported_length_remaining(tvb,deseg_offset),
1881 fd_head->reassembled_in);
1882 PROTO_ITEM_SET_GENERATED(iax_tree_item);
1884 /* this fragment is never reassembled */
1885 proto_tree_add_text( tree, tvb, deseg_offset, -1,
1886 "IAX2 fragment, unfinished");
1889 if( pinfo->desegment_offset == 0 ) {
1890 if (check_col(pinfo->cinfo, COL_PROTOCOL)){
1891 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAX2");
1893 if (check_col(pinfo->cinfo, COL_INFO)){
1894 col_set_str(pinfo->cinfo, COL_INFO, "[IAX2 segment of a reassembled PDU]");
1899 pinfo->can_desegment = 0;
1900 pinfo->desegment_offset = 0;
1901 pinfo->desegment_len = 0;
1904 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
1905 packet_info *pinfo, proto_tree *iax2_tree,
1906 proto_tree *tree, guint32 ts, gboolean video,
1907 iax_packet_data *iax_packet)
1910 gboolean out_of_order = FALSE;
1913 guint32 codec = iax_packet -> codec;
1915 iax_call_data *iax_call = iax_packet -> call_data;
1917 /* keep compiler quiet */
1920 if( offset >= tvb_reported_length (tvb)) {
1921 if (check_col (pinfo->cinfo, COL_INFO))
1922 col_append_fstr (pinfo->cinfo, COL_INFO, ", empty frame" );
1926 sub_tvb = tvb_new_subset(tvb, offset, -1, -1 );
1928 /* XXX shouldn't pass through out-of-order packets. */
1930 if (check_col (pinfo->cinfo, COL_INFO)) {
1931 if( !video && iax_call && iax_call -> dataformat != 0 ) {
1932 col_append_fstr (pinfo->cinfo, COL_INFO, ", data, format %s",
1933 val_to_str (iax_call -> dataformat,
1934 iax_dataformats, "unknown (0x%02x)"));
1937 col_append_fstr (pinfo->cinfo, COL_INFO, " (out-of-order packet)");
1940 col_append_fstr (pinfo->cinfo, COL_INFO, ", %s",
1941 val_to_str (codec, codec_types, "unknown (0x%02x)"));
1945 nbytes = tvb_reported_length(sub_tvb);
1946 proto_tree_add_text( iax2_tree, sub_tvb, 0, -1,
1947 "IAX2 payload (%u byte%s)", nbytes,
1948 plurality( nbytes, "", "s" ));
1950 /* pass the rest of the block to a subdissector */
1951 if(iax_packet->call_data)
1952 desegment_iax( sub_tvb, pinfo, iax2_tree, tree, video, iax_packet );
1954 process_iax_pdu(sub_tvb,pinfo,tree,video,iax_packet);
1961 /* called at the start of a capture. We should clear out our static, per-capture
1966 iax_init_protocol(void)
1974 proto_register_iax2 (void)
1976 /* we use this for displaying which codecs are supported */
1977 static const true_false_string supported_strings = {
1982 /* A header field is something you can search/filter on.
1984 * We create a structure to register our fields. It consists of an
1985 * array of hf_register_info structures, each of which are of the format
1986 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1989 static hf_register_info hf[] = {
1991 {&hf_iax2_packet_type,
1992 {"Packet type", "iax2.packet_type", FT_UINT8, BASE_DEC, VALS(iax_packet_types), 0,
1993 "Full/minivoice/minivideo/meta packet",
1997 {"Call identifier", "iax2.call", FT_UINT32, BASE_DEC, NULL, 0,
1998 "This is the identifier Wireshark assigns to identify this call. It does "
1999 "not correspond to any real field in the protocol", HFILL }},
2002 {"Source call", "iax2.src_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2003 "src_call holds the number of this call at the packet source pbx",
2006 /* FIXME could this be turned into a FRAMENUM field? */
2008 {"Destination call", "iax2.dst_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2009 "dst_call holds the number of this call at the packet destination",
2012 {&hf_iax2_retransmission,
2013 {"Retransmission", "iax2.retransmission", FT_BOOLEAN, 16,
2015 "retransmission is set if this packet is a retransmission of an earlier "
2016 "failed packet", HFILL}},
2019 {"Timestamp", "iax2.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
2020 "timestamp is the time, in ms after the start of this call, at which "
2021 "this packet was transmitted",
2025 {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x0,
2026 "timestamp is the time, in ms after the start of this call, at which "
2027 "this packet was transmitted",
2030 {&hf_iax2_minividts,
2031 {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2032 "timestamp is the time, in ms after the start of this call, at which "
2033 "this packet was transmitted",
2037 {"Absolute Time", "iax2.abstime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
2038 "The absoulte time of this packet (calculated by adding the IAX timestamp to "
2039 " the start time of this call)",
2043 {"Lateness", "iax2.lateness", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2044 "The lateness of this packet compared to its timestamp",
2047 {&hf_iax2_minividmarker,
2048 {"Marker", "iax2.video.marker", FT_UINT16, BASE_DEC, NULL, 0x8000,
2049 "RTP end-of-frame marker",
2053 {"Outbound seq.no.", "iax2.oseqno", FT_UINT16, BASE_DEC, NULL,
2055 "oseqno is the sequence no of this packet. The first packet has "
2056 "oseqno==0, and subsequent packets increment the oseqno by 1",
2060 {"Inbound seq.no.", "iax2.iseqno", FT_UINT16, BASE_DEC, NULL, 0x0,
2061 "iseqno is the sequence no of the last successfully received packet",
2065 {"Type", "iax2.type", FT_UINT8, BASE_DEC, VALS (iax_frame_types),
2067 "For full IAX2 frames, type is the type of frame",
2071 {"Unknown subclass", "iax2.subclass", FT_UINT8, BASE_DEC, NULL, 0x0,
2072 "Subclass of unknown type of full IAX2 frame",
2075 {&hf_iax2_dtmf_csub,
2076 {"DTMF subclass (digit)", "iax2.dtmf.subclass", FT_STRINGZ, BASE_NONE, NULL, 0x0,
2077 "DTMF subclass gives the DTMF digit",
2081 {"Control subclass", "iax2.control.subclass", FT_UINT8, BASE_DEC,
2082 VALS (iax_cmd_subclasses), 0x0,
2083 "This gives the command number for a Control packet.", HFILL}},
2086 {"IAX subclass", "iax2.iax.subclass", FT_UINT8, BASE_DEC,
2087 VALS (iax_iax_subclasses),
2089 "IAX subclass gives the command number for IAX signalling packets", HFILL}},
2091 {&hf_iax2_voice_csub,
2092 {"Voice Subclass (compressed codec no)", "iax2.voice.subclass", FT_UINT8, BASE_DEC, NULL, 0x0,
2093 "Voice Subclass (compressed codec no)",
2096 {&hf_iax2_voice_codec,
2097 {"CODEC", "iax2.voice.codec", FT_UINT32, BASE_HEX, VALS (codec_types),
2099 "CODEC gives the codec used to encode audio data", HFILL}},
2101 {&hf_iax2_video_csub,
2102 {"Video Subclass (compressed codec no)", "iax2.video.subclass", FT_UINT8, BASE_DEC, NULL, 0xBF,
2103 "Video Subclass (compressed codec no)",
2107 {"Marker", "iax2.video.marker", FT_BOOLEAN, 8, NULL, 0x40,
2108 "RTP end-of-frame marker",
2111 {&hf_iax2_video_codec,
2112 {"CODEC", "iax2.video.codec", FT_UINT32, BASE_HEX, VALS (codec_types), 0,
2113 "The codec used to encode video data", HFILL}},
2116 * Decoding for the ies
2119 {&hf_IAX_IE_APPARENTADDR_SINFAMILY,
2120 {"Family", "iax2.iax.app_addr.sinfamily", FT_UINT16, BASE_DEC, NULL, 0, "Family", HFILL }},
2121 {&hf_IAX_IE_APPARENTADDR_SINPORT,
2122 {"Port", "iax2.iax.app_addr.sinport", FT_UINT16, BASE_DEC, NULL, 0, "Port", HFILL }},
2123 {&hf_IAX_IE_APPARENTADDR_SINADDR,
2124 {"Address", "iax2.iax.app_addr.sinaddr", FT_IPv4, BASE_HEX, NULL, 0, "Address", HFILL }},
2126 {&hf_iax2_ies[IAX_IE_CALLED_NUMBER],
2127 {"Number/extension being called", "iax2.iax.called_number",
2129 BASE_NONE, NULL, 0x0, "", HFILL}},
2131 {&hf_iax2_ies[IAX_IE_CALLING_NUMBER],
2132 {"Calling number", "iax2.iax.calling_number", FT_STRING,
2136 {&hf_iax2_ies[IAX_IE_CALLING_ANI],
2137 {"Calling number ANI for billing", "iax2.iax.calling_ani",
2139 BASE_NONE, NULL, 0x0, "", HFILL}},
2141 {&hf_iax2_ies[IAX_IE_CALLING_NAME],
2142 {"Name of caller", "iax2.iax.calling_name", FT_STRING, BASE_NONE,
2146 {&hf_iax2_ies[IAX_IE_CALLED_CONTEXT],
2147 {"Context for number", "iax2.iax.called_context", FT_STRING,
2149 NULL, 0x0, "", HFILL}},
2151 {&hf_iax2_ies[IAX_IE_USERNAME],
2152 {"Username (peer or user) for authentication",
2153 "iax2.iax.username",
2154 FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2156 {&hf_iax2_ies[IAX_IE_PASSWORD],
2157 {"Password for authentication", "iax2.iax.password", FT_STRING,
2158 BASE_NONE, NULL, 0x0, "", HFILL}},
2160 {&hf_iax2_ies[IAX_IE_CAPABILITY],
2161 {"Actual codec capability", "iax2.iax.capability", FT_UINT32,
2163 NULL, 0x0, "", HFILL}},
2165 {&hf_iax2_ies[IAX_IE_FORMAT],
2166 {"Desired codec format", "iax2.iax.format", FT_UINT32, BASE_HEX,
2167 VALS (codec_types), 0x0, "", HFILL}},
2169 {&hf_iax2_ies[IAX_IE_LANGUAGE],
2170 {"Desired language", "iax2.iax.language", FT_STRING, BASE_NONE,
2174 {&hf_iax2_ies[IAX_IE_VERSION],
2175 {"Protocol version", "iax2.iax.version", FT_UINT16, BASE_HEX, NULL,
2179 {&hf_iax2_ies[IAX_IE_ADSICPE],
2180 {"CPE ADSI capability", "iax2.iax.cpe_adsi", FT_UINT16, BASE_HEX,
2184 {&hf_iax2_ies[IAX_IE_DNID],
2185 {"Originally dialed DNID", "iax2.iax.dnid", FT_STRING, BASE_NONE,
2189 {&hf_iax2_ies[IAX_IE_AUTHMETHODS],
2190 {"Authentication method(s)", "iax2.iax.auth.methods", FT_UINT16,
2192 NULL, 0x0, "", HFILL}},
2194 {&hf_iax2_ies[IAX_IE_CHALLENGE],
2195 {"Challenge data for MD5/RSA", "iax2.iax.auth.challenge",
2197 BASE_NONE, NULL, 0x0, "", HFILL}},
2199 {&hf_iax2_ies[IAX_IE_MD5_RESULT],
2200 {"MD5 challenge result", "iax2.iax.auth.md5", FT_STRING,
2204 {&hf_iax2_ies[IAX_IE_RSA_RESULT],
2205 {"RSA challenge result", "iax2.iax.auth.rsa", FT_STRING,
2209 {&hf_iax2_ies[IAX_IE_REFRESH],
2210 {"When to refresh registration", "iax2.iax.refresh", FT_INT16,
2212 NULL, 0x0, "", HFILL}},
2214 {&hf_iax2_ies[IAX_IE_DPSTATUS],
2215 {"Dialplan status", "iax2.iax.dialplan_status", FT_UINT16,
2219 {&hf_iax2_ies[IAX_IE_CALLNO],
2220 {"Call number of peer", "iax2.iax.call_no", FT_UINT16, BASE_DEC,
2224 {&hf_iax2_ies[IAX_IE_CAUSE],
2225 {"Cause", "iax2.iax.cause", FT_STRING, BASE_NONE, NULL, 0x0, "",
2228 {&hf_iax2_ies[IAX_IE_IAX_UNKNOWN],
2229 {"Unknown IAX command", "iax2.iax.iax_unknown", FT_BYTES,
2233 {&hf_iax2_ies[IAX_IE_MSGCOUNT],
2234 {"How many messages waiting", "iax2.iax.msg_count", FT_INT16,
2236 NULL, 0x0, "", HFILL}},
2238 {&hf_iax2_ies[IAX_IE_AUTOANSWER],
2239 {"Request auto-answering", "iax2.iax.autoanswer", FT_NONE,
2241 NULL, 0x0, "", HFILL}},
2243 {&hf_iax2_ies[IAX_IE_MUSICONHOLD],
2244 {"Request musiconhold with QUELCH", "iax2.iax.moh", FT_NONE,
2246 NULL, 0x0, "", HFILL}},
2248 {&hf_iax2_ies[IAX_IE_TRANSFERID],
2249 {"Transfer Request Identifier", "iax2.iax.transferid", FT_UINT32,
2250 BASE_HEX, NULL, 0x0, "", HFILL}},
2252 {&hf_iax2_ies[IAX_IE_RDNIS],
2253 {"Referring DNIS", "iax2.iax.rdnis", FT_STRING, BASE_NONE, NULL,
2257 {&hf_iax2_ies[IAX_IE_PROVISIONING],
2258 {"Provisioning info","iax2.iax.provisioning", FT_STRING, BASE_NONE,
2259 NULL, 0x0, "", HFILL}},
2261 {&hf_iax2_ies[IAX_IE_AESPROVISIONING],
2262 {"AES Provisioning info","iax2.iax.aesprovisioning", FT_STRING, BASE_NONE,
2263 NULL, 0x0, "", HFILL}},
2265 {&hf_iax2_ies[IAX_IE_DATETIME],
2266 {"Date/Time", "iax2.iax.datetime.raw", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
2268 {&hf_iax2_ie_datetime,
2269 {"Date/Time", "iax2.iax.datetime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, "", HFILL }},
2271 {&hf_iax2_ies[IAX_IE_DEVICETYPE],
2272 {"Device type", "iax2.iax.devicetype", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2274 {&hf_iax2_ies[IAX_IE_SERVICEIDENT],
2275 {"Service identifier", "iax2.iax.serviceident", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2277 {&hf_iax2_ies[IAX_IE_FIRMWAREVER],
2278 {"Firmware version", "iax2.iax.firmwarever", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
2280 {&hf_iax2_ies[IAX_IE_FWBLOCKDESC],
2281 {"Firmware block description", "iax2.iax.fwblockdesc", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2283 {&hf_iax2_ies[IAX_IE_FWBLOCKDATA],
2284 {"Firmware block of data", "iax2.iax.fwblockdata", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2286 {&hf_iax2_ies[IAX_IE_PROVVER],
2287 {"Provisioning version", "iax2.iax.provver", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2289 {&hf_iax2_ies[IAX_IE_CALLINGPRES],
2290 {"Calling presentation", "iax2.iax.callingpres", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
2292 {&hf_iax2_ies[IAX_IE_CALLINGTON],
2293 {"Calling type of number", "iax2.iax.callington", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
2295 {&hf_iax2_ies[IAX_IE_CALLINGTNS],
2296 {"Calling transit network select", "iax2.iax.callingtns", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
2298 {&hf_iax2_ies[IAX_IE_SAMPLINGRATE],
2299 {"Supported sampling rates", "iax2.iax.samplingrate", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
2301 {&hf_iax2_ies[IAX_IE_CAUSECODE],
2302 {"Hangup cause", "iax2.iax.causecode", FT_UINT8, BASE_HEX, VALS(iax_causecodes),
2305 {&hf_iax2_ies[IAX_IE_ENCRYPTION],
2306 {"Encryption format", "iax2.iax.encryption", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
2308 {&hf_iax2_ies[IAX_IE_ENCKEY],
2309 {"Encryption key", "iax2.iax.enckey", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2311 {&hf_iax2_ies[IAX_IE_CODEC_PREFS],
2312 {"Codec negotiation", "iax2.iax.codecprefs", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2314 {&hf_iax2_ies[IAX_IE_RR_JITTER],
2315 {"Received jitter (as in RFC1889)", "iax2.iax.rrjitter", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2317 {&hf_iax2_ies[IAX_IE_RR_LOSS],
2318 {"Received loss (high byte loss pct, low 24 bits loss count, as in rfc1889)", "iax2.iax.rrloss",
2319 FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2321 {&hf_iax2_ies[IAX_IE_RR_PKTS],
2322 {"Total frames received", "iax2.iax.rrpkts", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2324 {&hf_iax2_ies[IAX_IE_RR_DELAY],
2325 {"Max playout delay in ms for received frames", "iax2.iax.rrdelay", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
2327 {&hf_iax2_ies[IAX_IE_RR_DROPPED],
2328 {"Dropped frames (presumably by jitterbuffer)", "iax2.iax.rrdropped", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2330 {&hf_iax2_ies[IAX_IE_RR_OOO],
2331 {"Frame received out of order", "iax2.iax.rrooo", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2333 {&hf_iax2_ies[IAX_IE_DATAFORMAT],
2334 {"Data call format", "iax2.iax.dataformat", FT_UINT32, BASE_HEX,
2335 VALS(iax_dataformats), 0x0, "", HFILL}},
2337 {&hf_IAX_IE_UNKNOWN_BYTE,
2338 {"Unknown", "iax2.iax.unknownbyte", FT_UINT8, BASE_HEX, NULL,
2339 0x0, "Raw data for unknown IEs",
2341 {&hf_IAX_IE_UNKNOWN_I16,
2342 {"Unknown", "iax2.iax.unknownshort", FT_UINT16, BASE_HEX, NULL,
2343 0x0, "Raw data for unknown IEs",
2345 {&hf_IAX_IE_UNKNOWN_I32,
2346 {"Unknown", "iax2.iax.unknownlong", FT_UINT32, BASE_HEX, NULL,
2347 0x0, "Raw data for unknown IEs",
2349 {&hf_IAX_IE_UNKNOWN_BYTES,
2350 {"Unknown", "iax2.iax.unknownstring", FT_STRING, BASE_NONE, NULL,
2351 0x0, "Raw data for unknown IEs",
2355 {&hf_iax2_cap_g723_1,
2356 {"G.723.1 compression", "iax2.cap.g723_1", FT_BOOLEAN, 32,
2357 TFS(&supported_strings), AST_FORMAT_G723_1,
2358 "G.723.1 compression", HFILL }},
2361 {"GSM compression", "iax2.cap.gsm", FT_BOOLEAN, 32,
2362 TFS(&supported_strings), AST_FORMAT_GSM,
2363 "GSM compression", HFILL }},
2366 {"Raw mu-law data (G.711)", "iax2.cap.ulaw",FT_BOOLEAN, 32,
2367 TFS(&supported_strings), AST_FORMAT_ULAW,
2368 "Raw mu-law data (G.711)", HFILL }},
2371 {"Raw A-law data (G.711)", "iax2.cap.alaw",FT_BOOLEAN, 32,
2372 TFS(&supported_strings), AST_FORMAT_ALAW,
2373 "Raw A-law data (G.711)", HFILL }},
2376 {"G.726 compression", "iax2.cap.g726",FT_BOOLEAN, 32,
2377 TFS(&supported_strings), AST_FORMAT_G726,
2378 "G.726 compression", HFILL }},
2380 {&hf_iax2_cap_adpcm,
2381 {"ADPCM", "iax2.cap.adpcm", FT_BOOLEAN, 32,
2382 TFS(&supported_strings), AST_FORMAT_ADPCM,
2385 {&hf_iax2_cap_slinear,
2386 {"Raw 16-bit Signed Linear (8000 Hz) PCM", "iax2.cap.slinear",
2387 FT_BOOLEAN, 32, TFS(&supported_strings), AST_FORMAT_SLINEAR,
2388 "Raw 16-bit Signed Linear (8000 Hz) PCM", HFILL }},
2390 {&hf_iax2_cap_lpc10,
2391 {"LPC10, 180 samples/frame", "iax2.cap.lpc10", FT_BOOLEAN, 32,
2392 TFS(&supported_strings), AST_FORMAT_LPC10,
2393 "LPC10, 180 samples/frame", HFILL }},
2395 {&hf_iax2_cap_g729a,
2396 {"G.729a Audio", "iax2.cap.g729a", FT_BOOLEAN, 32,
2397 TFS(&supported_strings), AST_FORMAT_G729A,
2398 "G.729a Audio", HFILL }},
2400 {&hf_iax2_cap_speex,
2401 {"SPEEX Audio", "iax2.cap.speex", FT_BOOLEAN, 32,
2402 TFS(&supported_strings), AST_FORMAT_SPEEX,
2403 "SPEEX Audio", HFILL }},
2406 {"iLBC Free compressed Audio", "iax2.cap.ilbc", FT_BOOLEAN, 32,
2407 TFS(&supported_strings), AST_FORMAT_ILBC,
2408 "iLBC Free compressed Audio", HFILL }},
2411 {"JPEG images", "iax2.cap.jpeg", FT_BOOLEAN, 32,
2412 TFS(&supported_strings), AST_FORMAT_JPEG,
2413 "JPEG images", HFILL }},
2416 {"PNG images", "iax2.cap.png", FT_BOOLEAN, 32,
2417 TFS(&supported_strings), AST_FORMAT_PNG,
2418 "PNG images", HFILL }},
2421 {"H.261 video", "iax2.cap.h261", FT_BOOLEAN, 32,
2422 TFS(&supported_strings), AST_FORMAT_H261,
2423 "H.261 video", HFILL }},
2426 {"H.263 video", "iax2.cap.h263", FT_BOOLEAN, 32,
2427 TFS(&supported_strings), AST_FORMAT_H263,
2428 "H.263 video", HFILL }},
2430 /* reassembly stuff */
2431 {&hf_iax2_fragments,
2432 {"IAX2 Fragments", "iax2.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2433 "IAX2 Fragments", HFILL }},
2436 {"IAX2 Fragment data", "iax2.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2437 "IAX2 Fragment data", HFILL }},
2439 {&hf_iax2_fragment_overlap,
2440 {"Fragment overlap", "iax2.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2441 NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2443 {&hf_iax2_fragment_overlap_conflict,
2444 {"Conflicting data in fragment overlap", "iax2.fragment.overlap.conflict",
2445 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2446 "Overlapping fragments contained conflicting data", HFILL }},
2448 {&hf_iax2_fragment_multiple_tails,
2449 {"Multiple tail fragments found", "iax2.fragment.multipletails",
2450 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2451 "Several tails were found when defragmenting the packet", HFILL }},
2453 {&hf_iax2_fragment_too_long_fragment,
2454 {"Fragment too long", "iax2.fragment.toolongfragment",
2455 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2456 "Fragment contained data past end of packet", HFILL }},
2458 {&hf_iax2_fragment_error,
2459 {"Defragmentation error", "iax2.fragment.error",
2460 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2461 "Defragmentation error due to illegal fragments", HFILL }},
2463 {&hf_iax2_reassembled_in,
2464 {"IAX2 fragment, reassembled in frame", "iax2.reassembled_in",
2465 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2466 "This IAX2 packet is reassembled in this frame", HFILL }}
2469 static gint *ett[] = {
2471 &ett_iax2_full_mini_subtree,
2475 &ett_iax2_ies_apparent_addr,
2480 /* initialise the hf_iax2_ies[] array to -1 */
2481 memset(hf_iax2_ies,0xff,sizeof(hf_iax2_ies));
2484 proto_register_protocol ("Inter-Asterisk eXchange v2", "IAX2", "iax2");
2485 proto_register_field_array (proto_iax2, hf, array_length (hf));
2486 proto_register_subtree_array (ett, array_length (ett));
2488 register_dissector("iax2", dissect_iax2, proto_iax2);
2490 iax2_codec_dissector_table = register_dissector_table(
2491 "iax2.codec","IAX codec number", FT_UINT32, BASE_HEX);
2492 iax2_dataformat_dissector_table = register_dissector_table(
2493 "iax2.dataformat","IAX dataformat number", FT_UINT32, BASE_HEX);
2495 /* register our init routine to be called at the start of a capture,
2496 to clear out our hash tables etc */
2497 register_init_routine(&iax_init_protocol);
2501 proto_reg_handoff_iax2 (void)
2503 dissector_add("udp.port", IAX2_PORT, find_dissector("iax2"));
2504 dissector_add("iax2.dataformat", AST_DATAFORMAT_V110, find_dissector("v110"));
2505 data_handle = find_dissector("data");
2510 * This sets up the indentation style for this file in emacs.
2517 * vim:set ts=8 sts=2 sw=2 noet: