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 * Ethereal - Network traffic analyzer
14 * By Gerald Combs <gerald@ethereal.com>
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>
42 #include "packet-iax2.h"
43 #include "iax2_codec_type.h"
45 #define IAX2_PORT 4569
46 #define PROTO_TAG_IAX2 "IAX2"
48 /* #define DEBUG_HASHING */
50 /* Ethereal ID of the IAX2 protocol */
51 static int proto_iax2 = -1;
53 /* The following hf_* variables are used to hold the ethereal IDs of
54 * our header fields; they are filled out when we call
55 * proto_register_field_array() in proto_register_iax2()
57 static int hf_iax2_packet_type = -1;
58 static int hf_iax2_retransmission = -1;
59 static int hf_iax2_scallno = -1;
60 static int hf_iax2_dcallno = -1;
61 static int hf_iax2_ts = -1;
62 static int hf_iax2_minits = -1;
63 static int hf_iax2_minividts = -1;
64 static int hf_iax2_minividmarker = -1;
65 static int hf_iax2_oseqno = -1;
66 static int hf_iax2_iseqno = -1;
67 static int hf_iax2_type = -1;
68 static int hf_iax2_csub = -1;
69 static int hf_iax2_cmd_csub = -1;
70 static int hf_iax2_iax_csub = -1;
71 static int hf_iax2_voice_csub = -1;
72 static int hf_iax2_voice_codec = -1;
73 static int hf_iax2_video_csub = -1;
74 static int hf_iax2_video_codec = -1;
75 static int hf_iax2_marker = -1;
77 static int hf_iax2_cap_g723_1 = -1;
78 static int hf_iax2_cap_gsm = -1;
79 static int hf_iax2_cap_ulaw = -1;
80 static int hf_iax2_cap_alaw = -1;
81 static int hf_iax2_cap_g726 = -1;
82 static int hf_iax2_cap_adpcm = -1;
83 static int hf_iax2_cap_slinear = -1;
84 static int hf_iax2_cap_lpc10 = -1;
85 static int hf_iax2_cap_g729a = -1;
86 static int hf_iax2_cap_speex = -1;
87 static int hf_iax2_cap_ilbc = -1;
88 static int hf_iax2_cap_jpeg = -1;
89 static int hf_iax2_cap_png = -1;
90 static int hf_iax2_cap_h261 = -1;
91 static int hf_iax2_cap_h263 = -1;
93 static int hf_IAX_IE_APPARENTADDR_SINFAMILY = -1;
94 static int hf_IAX_IE_APPARENTADDR_SINPORT = -1;
95 static int hf_IAX_IE_APPARENTADDR_SINADDR = -1;
96 static int hf_IAX_IE_APPARENTADDR_SINZERO = -1;
97 static int hf_IAX_IE_CALLED_NUMBER = -1;
98 static int hf_IAX_IE_CALLING_NUMBER = -1;
99 static int hf_IAX_IE_CALLING_ANI = -1;
100 static int hf_IAX_IE_CALLING_NAME = -1;
101 static int hf_IAX_IE_CALLED_CONTEXT = -1;
102 static int hf_IAX_IE_USERNAME = -1;
103 static int hf_IAX_IE_PASSWORD = -1;
104 static int hf_IAX_IE_CAPABILITY = -1;
105 static int hf_IAX_IE_FORMAT = -1;
106 static int hf_IAX_IE_LANGUAGE = -1;
107 static int hf_IAX_IE_VERSION = -1;
108 static int hf_IAX_IE_ADSICPE = -1;
109 static int hf_IAX_IE_DNID = -1;
110 static int hf_IAX_IE_AUTHMETHODS = -1;
111 static int hf_IAX_IE_CHALLENGE = -1;
112 static int hf_IAX_IE_MD5_RESULT = -1;
113 static int hf_IAX_IE_RSA_RESULT = -1;
114 static int hf_IAX_IE_REFRESH = -1;
115 static int hf_IAX_IE_DPSTATUS = -1;
116 static int hf_IAX_IE_CALLNO = -1;
117 static int hf_IAX_IE_CAUSE = -1;
118 static int hf_IAX_IE_IAX_UNKNOWN = -1;
119 static int hf_IAX_IE_MSGCOUNT = -1;
120 static int hf_IAX_IE_AUTOANSWER = -1;
121 static int hf_IAX_IE_MUSICONHOLD = -1;
122 static int hf_IAX_IE_TRANSFERID = -1;
123 static int hf_IAX_IE_RDNIS = -1;
124 static int hf_IAX_IE_DATAFORMAT = -1;
125 static int hf_IAX_IE_UNKNOWN_BYTE = -1;
126 static int hf_IAX_IE_UNKNOWN_I16 = -1;
127 static int hf_IAX_IE_UNKNOWN_I32 = -1;
128 static int hf_IAX_IE_UNKNOWN_BYTES = -1;
130 /* These are the ids of the subtrees that we may be creating */
131 static gint ett_iax2 = -1;
132 static gint ett_iax2_full_mini_subtree = -1;
133 static gint ett_iax2_type = -1; /* Frame-type specific subtree */
134 static gint ett_iax2_ie = -1; /* single IE */
135 static gint ett_iax2_codecs = -1; /* capabilities IE */
136 static gint ett_iax2_ies_apparent_addr = -1; /* apparent address IE */
138 static dissector_handle_t data_handle;
140 /* data-call subdissectors, AST_DATAFORMAT_* */
141 static dissector_table_t iax2_dataformat_dissector_table;
142 /* voice/video call subdissectors, AST_FORMAT_* */
143 static dissector_table_t iax2_codec_dissector_table;
145 /* IAX2 Full-frame types */
146 static const value_string iax_frame_types[] = {
159 /* Subclasses for IAX packets */
160 static const value_string iax_iax_subclasses[] = {
199 /* Subclassess for Control packets */
200 static const value_string iax_cmd_subclasses[] = {
209 {0xFF, "stop sounds"}, /* sent by app_dial, and not much else */
213 /* Information elements */
214 static const value_string iax_ies_type[] = {
215 {IAX_IE_CALLED_NUMBER, "Number/extension being called"},
216 {IAX_IE_CALLING_NUMBER, "Calling number"},
217 {IAX_IE_CALLING_ANI, "Calling number ANI for billing"},
218 {IAX_IE_CALLING_NAME, "Name of caller"},
219 {IAX_IE_CALLED_CONTEXT, "Context for number"},
220 {IAX_IE_USERNAME, "Username (peer or user) for authentication"},
221 {IAX_IE_PASSWORD, "Password for authentication"},
222 {IAX_IE_CAPABILITY, "Actual codec capability"},
223 {IAX_IE_FORMAT, "Desired codec format"},
224 {IAX_IE_LANGUAGE, "Desired language"},
225 {IAX_IE_VERSION, "Protocol version"},
226 {IAX_IE_ADSICPE, "CPE ADSI capability"},
227 {IAX_IE_DNID, "Originally dialed DNID"},
228 {IAX_IE_AUTHMETHODS, "Authentication method(s)"},
229 {IAX_IE_CHALLENGE, "Challenge data for MD5/RSA"},
230 {IAX_IE_MD5_RESULT, "MD5 challenge result"},
231 {IAX_IE_RSA_RESULT, "RSA challenge result"},
232 {IAX_IE_APPARENT_ADDR, "Apparent address of peer"},
233 {IAX_IE_REFRESH, "When to refresh registration"},
234 {IAX_IE_DPSTATUS, "Dialplan status"},
235 {IAX_IE_CALLNO, "Call number of peer"},
236 {IAX_IE_CAUSE, "Cause"},
237 {IAX_IE_IAX_UNKNOWN, "Unknown IAX command"},
238 {IAX_IE_MSGCOUNT, "How many messages waiting"},
239 {IAX_IE_AUTOANSWER, "Request auto-answering"},
240 {IAX_IE_MUSICONHOLD, "Request musiconhold with QUELCH"},
241 {IAX_IE_TRANSFERID, "Transfer Request Identifier"},
242 {IAX_IE_RDNIS, "Referring DNIS"},
243 {IAX_IE_PROVISIONING, "Provisioning info"},
244 {IAX_IE_AESPROVISIONING, "AES Provisioning info"},
245 {IAX_IE_DATETIME,"Date/Time"},
246 {IAX_IE_DATAFORMAT, "Data call format"},
250 static const value_string codec_types[] = {
251 {AST_FORMAT_G723_1, "G.723.1 compression"},
252 {AST_FORMAT_GSM, "GSM compression"},
253 {AST_FORMAT_ULAW, "Raw mu-law data (G.711)"},
254 {AST_FORMAT_ALAW, "Raw A-law data (G.711)"},
255 {AST_FORMAT_G726, "ADPCM (G.726, 32kbps)"},
256 {AST_FORMAT_ADPCM, "ADPCM (IMA)"},
257 {AST_FORMAT_SLINEAR, "Raw 16-bit Signed Linear (8000 Hz) PCM"},
258 {AST_FORMAT_LPC10, "LPC10, 180 samples/frame"},
259 {AST_FORMAT_G729A, "G.729a Audio"},
260 {AST_FORMAT_SPEEX, "SpeeX Free Compression"},
261 {AST_FORMAT_ILBC, "iLBC Free Compression"},
262 {AST_FORMAT_JPEG, "JPEG Images"},
263 {AST_FORMAT_PNG, "PNG Images"},
264 {AST_FORMAT_H261, "H.261 Video"},
265 {AST_FORMAT_H263, "H.263 Video"},
269 static const value_string iax_dataformats[] = {
270 {AST_DATAFORMAT_NULL, "N/A (analogue call?)"},
271 {AST_DATAFORMAT_V110, "ITU-T V.110 rate adaption"},
272 {AST_DATAFORMAT_H223_H245,"ITU-T H.223/H.245"},
277 IAX2_MINI_VOICE_PACKET,
279 IAX2_MINI_VIDEO_PACKET,
283 static const value_string iax_packet_types[] = {
284 {IAX2_FULL_PACKET, "Full packet"},
285 {IAX2_MINI_VOICE_PACKET, "Mini voice packet"},
286 {IAX2_MINI_VIDEO_PACKET, "Mini video packet"},
287 {IAX2_META_PACKET, "Meta packet"},
292 /* ************************************************************************* */
294 /* In order to track IAX calls, we have a hash table which maps
295 * {addr,port type,port,call} to a unique circuit id.
297 * Each call has two such circuits associated with it (a forward and a
298 * reverse circuit, where 'forward' is defined as the direction the NEW
299 * packet went in), and we maintain an iax_call_data structure for each
300 * call, attached to both circuits with circuit_add_proto_data.
302 * Because {addr,port type,port,call} quadruplets can be reused
303 * (Asterisk reuses call numbers), circuit ids aren't unique to
304 * individual calls and we treat NEW packets somewhat specially. When we
305 * get such a packet, we see if there are any calls with a matching
306 * circuit id, and make sure that its circuits are marked as ended
307 * before that packet.
309 * A second complication is that we only know one quadruplet at the time
310 * the NEW packet is processed: there is therefore cunningness in
311 * iax_lookup_circuit_details() to look for replies to NEW packets and
312 * create the reverse circuit.
316 /* start with a hash of {addr,port type,port,call}->{id} */
326 static GHashTable *iax_circuit_hashtab = NULL;
327 static GMemChunk *iax_circuit_keys = NULL;
328 static GMemChunk *iax_circuit_vals = NULL;
329 static guint circuitcount = 0;
331 /* the number of keys and values to reserve space for in each memory chunk.
332 We assume we won't be tracking many calls at once so this is quite low.
334 #define IAX_INIT_PACKET_COUNT 10
337 static gchar *key_to_str( const iax_circuit_key *key )
340 static gchar *strp, str[3][80];
348 /* why doesn't address_to_str take a const pointer?
349 cast the warnings into oblivion. */
351 sprintf(strp,"{%s:%i,%i}",
352 address_to_str((address *)&key->addr),
360 static gint iax_circuit_equal(gconstpointer v, gconstpointer w)
362 const iax_circuit_key *v1 = (const iax_circuit_key *)v;
363 const iax_circuit_key *v2 = (const iax_circuit_key *)w;
366 result = ( ADDRESSES_EQUAL(&(v1->addr), &(v2->addr)) &&
367 v1->ptype == v2->ptype &&
368 v1->port == v2->port &&
369 v1->callno== v2->callno);
371 g_message( "+++ Comparing for equality: %s, %s: %u",key_to_str(v1), key_to_str(v2), result);
377 static guint iax_circuit_hash (gconstpointer v)
379 const iax_circuit_key *key = (const iax_circuit_key *)v;
384 for (i = 0; i < key->addr.len; i++)
385 hash_val += (guint)(key->addr.data[i]);
387 hash_val += (guint)(key->ptype);
388 hash_val += (guint)(key->port);
389 hash_val += (guint)(key->callno);
392 g_message( "+++ Hashing key: %s, result %#x", key_to_str(key), hash_val );
395 return (guint) hash_val;
398 static guint iax_circuit_lookup(const address *address,
404 guint32 *circuit_id_p;
412 g_message( "+++ looking up key: %s", key_to_str(&key));
415 circuit_id_p = g_hash_table_lookup( iax_circuit_hashtab, &key);
416 if( ! circuit_id_p ) {
417 iax_circuit_key *new_key;
419 new_key = g_mem_chunk_alloc(iax_circuit_keys);
420 COPY_ADDRESS(&new_key->addr, address);
421 new_key->ptype = ptype;
422 new_key->port = port;
423 new_key->callno = callno;
425 circuit_id_p = g_mem_chunk_alloc(iax_circuit_vals);
426 *circuit_id_p = ++circuitcount;
428 g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p);
432 g_message( "+++ Id: %u", *circuit_id_p );
435 return *circuit_id_p;
439 /* ************************************************************************* */
442 /* This is our per-call data structure, which is attached to both the
443 * forward and reverse circuits.
445 typedef struct iax_call_data {
446 /* For this data, src and dst are relative to the original direction under
447 which this call is stored. Obviously if the reversed flag is set true by
448 iax_find_call, src and dst are reversed relative to the direction the
449 actual source and destination of the data.
451 if the codec changes mid-call, we update it here; because we store a codec
452 number with each packet too, we handle going back to earlier packets
456 iax_dataformat_t dataformat;
457 guint32 src_codec, dst_codec;
458 guint32 src_vformat, dst_vformat;
460 guint forward_circuit_id;
461 guint reverse_circuit_id;
466 static guint callcount = 0;
468 static GMemChunk *iax_call_datas = NULL;
470 static void iax_init_hash( void )
472 if (iax_circuit_hashtab)
473 g_hash_table_destroy(iax_circuit_hashtab);
475 if (iax_circuit_keys)
476 g_mem_chunk_destroy(iax_circuit_keys);
477 if (iax_circuit_vals)
478 g_mem_chunk_destroy(iax_circuit_vals);
480 g_mem_chunk_destroy(iax_call_datas);
482 iax_circuit_hashtab = g_hash_table_new(iax_circuit_hash, iax_circuit_equal);
484 iax_circuit_keys = g_mem_chunk_create(iax_circuit_key,
485 2*IAX_INIT_PACKET_COUNT,
487 iax_circuit_vals = g_mem_chunk_create(iax_circuit_key,
488 2*IAX_INIT_PACKET_COUNT,
491 iax_call_datas = g_mem_chunk_create(iax_call_data,
492 IAX_INIT_PACKET_COUNT,
499 static iax_call_data *iax_lookup_circuit_details_from_dest( guint src_circuit_id,
500 guint dst_circuit_id,
502 gboolean *reversed_p,
503 circuit_t **circuit_p)
505 circuit_t *dst_circuit;
506 iax_call_data * iax_call;
507 gboolean reversed = FALSE;
509 dst_circuit = find_circuit( CT_IAX2,
515 g_message( "++ destination circuit not found, must have missed NEW packet" );
521 g_message( "++ found destination circuit" );
524 iax_call = (iax_call_data *)circuit_get_proto_data(dst_circuit,proto_iax2);
526 /* there's no way we can create a CT_IAX2 circuit without adding
527 iax call data to it; assert this */
530 if( dst_circuit_id == iax_call -> forward_circuit_id ) {
532 g_message( "++ destination circuit matches forward_circuit_id of call, "
533 "therefore packet is reversed" );
538 if( iax_call -> reverse_circuit_id == 0 ) {
539 circuit_t *rev_circuit;
541 /* we are going in the reverse direction, and this call
542 doesn't have a reverse circuit associated with it.
545 g_message( "++ reverse_circuit_id of call is zero, need to create a "
546 "new reverse circuit for this call" );
549 iax_call -> reverse_circuit_id = src_circuit_id;
550 rev_circuit = circuit_new(CT_IAX2,
553 circuit_add_proto_data(rev_circuit, proto_iax2, iax_call);
555 /* we should have already set up a subdissector for the forward
556 * circuit. we'll need to copy it to the reverse circuit. */
557 circuit_set_dissector(rev_circuit, circuit_get_dissector(dst_circuit));
559 g_message( "++ done" );
561 } else if( iax_call -> reverse_circuit_id != src_circuit_id ) {
562 g_warning( "IAX Packet %u from circuit ids %u->%u"
563 "conflicts with earlier call with circuit ids %u->%u",
565 src_circuit_id,dst_circuit_id,
566 iax_call->forward_circuit_id,
567 iax_call->reverse_circuit_id);
570 } else if ( dst_circuit_id == iax_call -> reverse_circuit_id ) {
572 g_message( "++ destination circuit matches reverse_circuit_id of call, "
573 "therefore packet is forward" );
577 if( iax_call -> forward_circuit_id != src_circuit_id ) {
578 g_warning( "IAX Packet %u from circuit ids %u->%u"
579 "conflicts with earlier call with circuit ids %u->%u",
581 src_circuit_id,dst_circuit_id,
582 iax_call->forward_circuit_id,
583 iax_call->reverse_circuit_id);
587 g_assert_not_reached();
592 /* by now we've created a new circuit if one was necessary, or
593 bailed out if it looks like a conflict, and we should be able
594 to look up the source circuit without issue */
595 *circuit_p = find_circuit( CT_IAX2,
598 g_assert(*circuit_p);
602 *reversed_p = reversed;
608 /* looks up a circuit_t and an iax_call for this packet */
609 static iax_call_data *iax_lookup_circuit_details( packet_info *pinfo,
612 gboolean *reversed_p,
613 circuit_t **circuit_p)
615 gboolean reversed = FALSE;
616 iax_call_data *iax_call = NULL;
617 guint src_circuit_id;
618 circuit_t *src_circuit = NULL;
621 g_message( "++ iax_lookup_circuit_details: Looking up circuit for frame %u, "
622 "from {%s:%u:%u} to {%s:%u:%u}", pinfo->fd->num,
623 address_to_str(&pinfo->src),pinfo->srcport,scallno,
624 address_to_str(&pinfo->dst),pinfo->destport,dcallno);
628 src_circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
629 pinfo->srcport,scallno);
632 /* the most reliable indicator of call is the destination callno, if
635 guint dst_circuit_id;
637 g_message( "++ dcallno non-zero, looking up destination circuit" );
640 dst_circuit_id = iax_circuit_lookup(&pinfo->dst,pinfo->ptype,
641 pinfo->destport,dcallno);
643 iax_call = iax_lookup_circuit_details_from_dest(src_circuit_id, dst_circuit_id, pinfo->fd->num, &reversed, &src_circuit);
646 /* in all other circumstances, the source circuit should already
647 * exist: its absense indicates that we missed the all-important NEW
651 src_circuit = find_circuit( CT_IAX2,
656 iax_call = (iax_call_data *)circuit_get_proto_data(src_circuit,proto_iax2);
658 /* there's no way we can create a CT_IAX2 circuit without adding
659 iax call data to it; assert this */
662 if( src_circuit_id == iax_call -> forward_circuit_id )
664 else if ( src_circuit_id == iax_call -> reverse_circuit_id )
667 /* there's also no way we can attach an iax_call_data to a circuit
668 without the circuit being either the forward or reverse circuit
669 for that call; assert this too.
671 g_assert_not_reached();
676 if(src_circuit && iax_call) {
677 /* info for subdissectors. We always pass on the forward circuit,
678 * and steal the p2p_dir flag to indicate the direction */
679 pinfo -> ctype = CT_IAX2;
680 pinfo -> circuit_id = (guint32)iax_call->forward_circuit_id;
681 pinfo -> p2p_dir = reversed?P2P_DIR_RECV:P2P_DIR_SENT;
685 *reversed_p = reversed;
688 *circuit_p = src_circuit;
692 g_message( "++ Found call for packet: id %u, reversed=%c", iax_call->callno, reversed?'1':'0' );
694 g_message( "++ Call not found. Must have missed the NEW packet?" );
702 /* handles a NEW packet by creating a new iax call and forward circuit.
703 the reverse circuit is not created until the ACK is received and
704 is created by iax_lookup_circuit_details. */
705 static iax_call_data *iax_new_circuit_details( packet_info *pinfo,
707 circuit_t **circuit_p)
714 g_message( "+ new_circuit: Handling NEW packet, frame %u", pinfo->fd->num );
717 circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
718 pinfo->srcport,scallno);
720 circuit = circuit_new(CT_IAX2,
726 call = g_mem_chunk_alloc(iax_call_datas);
727 call -> dataformat = 0;
728 call -> src_codec = 0;
729 call -> dst_codec = 0;
730 call -> forward_circuit_id = circuit_id;
731 call -> reverse_circuit_id = 0;
732 call -> callno = ++callcount;
735 g_message( "+ new_circuit: Added new circuit for new call %u", call -> callno );
738 circuit_add_proto_data( circuit, proto_iax2, call );
741 *circuit_p = circuit;
747 /* ************************************************************************* */
749 /* per-packet data */
750 typedef struct iax_packet_data {
751 iax_call_data *call_data;
755 static GMemChunk *iax_packets = NULL;
757 static iax_packet_data *iax_new_packet_data(iax_call_data *call)
759 iax_packet_data *p = g_mem_chunk_alloc(iax_packets);
766 /* ************************************************************************* */
768 static guint32 dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
771 proto_tree * iax2_tree,
772 proto_tree * main_tree);
775 static guint32 dissect_minipacket (tvbuff_t * tvb, guint32 offset,
778 proto_tree * iax2_tree,
779 proto_tree * main_tree);
781 static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
784 proto_tree * iax2_tree,
785 proto_tree * main_tree);
787 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
788 packet_info *pinfo, proto_tree *tree,
789 guint32 ts, gboolean video,
790 iax_packet_data *iax_packet);
795 dissect_iax2 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
797 proto_item *iax2_item = NULL;
798 proto_tree *iax2_tree = NULL;
799 proto_tree *full_mini_subtree = NULL;
800 guint32 offset = 0, len;
805 /* set up the protocol and info fields in the summary pane */
806 if (check_col (pinfo->cinfo, COL_PROTOCOL))
808 col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2);
810 if (check_col (pinfo->cinfo, COL_INFO))
812 col_clear (pinfo->cinfo, COL_INFO);
815 /* add the 'iax2' tree to the main tree */
818 iax2_item = proto_tree_add_item (tree, proto_iax2, tvb, offset, -1, FALSE);
819 iax2_tree = proto_item_add_subtree (iax2_item, ett_iax2);
822 stmp = tvb_get_ntohs(tvb, offset);
824 /* starting with 0x0000 indicates either a mini video packet or a 'meta'
825 * packet, whatever that means */
827 stmp = tvb_get_ntohs(tvb, offset);
828 if( stmp & 0x8000 ) {
829 /* mini video packet */
830 type = IAX2_MINI_VIDEO_PACKET;
831 scallno = stmp & 0x7FFF;
835 type = IAX2_META_PACKET;
838 /* The source call/fullpacket flag is common to both mini and full packets */
839 scallno = tvb_get_ntohs(tvb, offset);
841 if( scallno & 0x8000 )
842 type = IAX2_FULL_PACKET;
844 type = IAX2_MINI_VOICE_PACKET;
850 proto_item *full_mini_base;
852 full_mini_base = proto_tree_add_uint(iax2_tree, hf_iax2_packet_type, tvb, 0, offset, type);
853 full_mini_subtree = proto_item_add_subtree(full_mini_base, ett_iax2_full_mini_subtree);
856 proto_tree_add_item (full_mini_subtree, hf_iax2_scallno, tvb, offset-2, 2, FALSE);
860 case IAX2_FULL_PACKET:
861 len = dissect_fullpacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
863 case IAX2_MINI_VOICE_PACKET:
864 len = dissect_minipacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
866 case IAX2_MINI_VIDEO_PACKET:
867 len = dissect_minivideopacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
869 case IAX2_META_PACKET:
870 /* not implemented yet */
877 /* update the 'length' of the main IAX2 header field so that it covers just the headers,
878 not the audio data. */
879 proto_item_set_len(iax2_item, len);
883 /* dissect the information elements in an IAX frame. Returns the updated offset */
884 static guint32 dissect_ies (tvbuff_t * tvb, guint32 offset,
885 proto_tree * iax_tree,
886 iax_call_data *iax_call_data )
888 proto_tree *sockaddr_tree = NULL;
889 proto_item *sockaddr_item = 0;
892 while (offset < tvb_reported_length (tvb)) {
894 int ies_type = tvb_get_guint8(tvb, offset);
895 int ies_len = tvb_get_guint8(tvb, offset + 1);
899 proto_tree *ies_tree;
901 ti = proto_tree_add_text(iax_tree, tvb, offset, ies_len+2,
902 "Information Element: %s (0x%02X)",
903 val_to_str(ies_type, iax_ies_type,
904 "Unknown information element"),
908 ies_tree = proto_item_add_subtree(ti, ett_iax2_ie);
910 proto_tree_add_text(ies_tree, tvb, offset, 1, "IE id: %s (0x%02X)",
911 val_to_str(ies_type, iax_ies_type, "Unknown"),
914 proto_tree_add_text(ies_tree, tvb, offset+1, 1, "Length: %u",ies_len);
918 case IAX_IE_CALLED_NUMBER:
919 proto_tree_add_item (ies_tree, hf_IAX_IE_CALLED_NUMBER, tvb,
920 offset + 2, ies_len, FALSE);
922 case IAX_IE_CALLING_NUMBER:
923 proto_tree_add_item (ies_tree, hf_IAX_IE_CALLING_NUMBER,
924 tvb, offset + 2, ies_len, FALSE);
926 case IAX_IE_CALLING_ANI:
927 proto_tree_add_item (ies_tree, hf_IAX_IE_CALLING_ANI, tvb,
928 offset + 2, ies_len, FALSE);
930 case IAX_IE_CALLING_NAME:
931 proto_tree_add_item (ies_tree, hf_IAX_IE_CALLING_NAME, tvb,
932 offset + 2, ies_len, FALSE);
934 case IAX_IE_CALLED_CONTEXT:
935 proto_tree_add_item (ies_tree, hf_IAX_IE_CALLED_CONTEXT,
936 tvb, offset + 2, ies_len, FALSE);
938 case IAX_IE_USERNAME:
939 proto_tree_add_item (ies_tree, hf_IAX_IE_USERNAME, tvb,
940 offset + 2, ies_len, FALSE);
942 case IAX_IE_PASSWORD:
943 proto_tree_add_item (ies_tree, hf_IAX_IE_PASSWORD, tvb,
944 offset + 2, ies_len, FALSE);
946 case IAX_IE_LANGUAGE:
947 proto_tree_add_item (ies_tree, hf_IAX_IE_LANGUAGE, tvb,
948 offset + 2, ies_len, FALSE);
951 proto_tree_add_item (ies_tree, hf_IAX_IE_DNID, tvb,
952 offset + 2, ies_len, FALSE);
954 case IAX_IE_CHALLENGE:
955 proto_tree_add_item (ies_tree, hf_IAX_IE_CHALLENGE, tvb,
956 offset + 2, ies_len, FALSE);
958 case IAX_IE_MD5_RESULT:
959 proto_tree_add_item (ies_tree, hf_IAX_IE_MD5_RESULT, tvb,
960 offset + 2, ies_len, FALSE);
962 case IAX_IE_RSA_RESULT:
963 proto_tree_add_item (ies_tree, hf_IAX_IE_RSA_RESULT, tvb,
964 offset + 2, ies_len, FALSE);
967 proto_tree_add_item (ies_tree, hf_IAX_IE_RDNIS, tvb,
968 offset + 2, ies_len, FALSE);
970 case IAX_IE_CAPABILITY:
972 proto_tree *codec_tree;
973 proto_item *codec_base;
976 proto_tree_add_item (ies_tree, hf_IAX_IE_CAPABILITY,
977 tvb, offset + 2, ies_len, FALSE);
979 proto_item_add_subtree (codec_base, ett_iax2_codecs);
981 proto_tree_add_item(codec_tree, hf_iax2_cap_g723_1, tvb, offset + 2, ies_len, FALSE );
982 proto_tree_add_item(codec_tree, hf_iax2_cap_gsm, tvb, offset + 2, ies_len, FALSE );
983 proto_tree_add_item(codec_tree, hf_iax2_cap_ulaw, tvb, offset + 2, ies_len, FALSE );
984 proto_tree_add_item(codec_tree, hf_iax2_cap_alaw, tvb, offset + 2, ies_len, FALSE );
985 proto_tree_add_item(codec_tree, hf_iax2_cap_g726, tvb, offset + 2, ies_len, FALSE );
986 proto_tree_add_item(codec_tree, hf_iax2_cap_adpcm, tvb, offset + 2, ies_len, FALSE );
987 proto_tree_add_item(codec_tree, hf_iax2_cap_slinear, tvb, offset + 2, ies_len, FALSE );
988 proto_tree_add_item(codec_tree, hf_iax2_cap_lpc10, tvb, offset + 2, ies_len, FALSE );
989 proto_tree_add_item(codec_tree, hf_iax2_cap_g729a, tvb, offset + 2, ies_len, FALSE );
990 proto_tree_add_item(codec_tree, hf_iax2_cap_speex, tvb, offset + 2, ies_len, FALSE );
991 proto_tree_add_item(codec_tree, hf_iax2_cap_ilbc, tvb, offset + 2, ies_len, FALSE );
992 proto_tree_add_item(codec_tree, hf_iax2_cap_jpeg, tvb, offset + 2, ies_len, FALSE );
993 proto_tree_add_item(codec_tree, hf_iax2_cap_png, tvb, offset + 2, ies_len, FALSE );
994 proto_tree_add_item(codec_tree, hf_iax2_cap_h261, tvb, offset + 2, ies_len, FALSE );
995 proto_tree_add_item(codec_tree, hf_iax2_cap_h263, tvb, offset + 2, ies_len, FALSE );
999 proto_tree_add_item (ies_tree, hf_IAX_IE_FORMAT, tvb,
1000 offset + 2, ies_len, FALSE);
1002 case IAX_IE_VERSION:
1003 proto_tree_add_item (ies_tree, hf_IAX_IE_VERSION, tvb,
1004 offset + 2, ies_len, FALSE);
1006 case IAX_IE_ADSICPE:
1007 proto_tree_add_item (ies_tree, hf_IAX_IE_ADSICPE, tvb,
1008 offset + 2, ies_len, FALSE);
1010 case IAX_IE_AUTHMETHODS:
1011 proto_tree_add_item (ies_tree, hf_IAX_IE_AUTHMETHODS, tvb,
1012 offset + 2, ies_len, FALSE);
1014 case IAX_IE_APPARENT_ADDR:
1015 sockaddr_item = proto_tree_add_text(ies_tree, tvb, offset + 2, 16, "Apparent Address");
1016 sockaddr_tree = proto_item_add_subtree(sockaddr_item, ett_iax2_ies_apparent_addr);
1017 proto_tree_add_item(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINADDR, tvb, offset + 6, 4, FALSE);
1018 proto_tree_add_item(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINPORT, tvb, offset + 4, 2, FALSE);
1020 case IAX_IE_REFRESH:
1021 proto_tree_add_item (ies_tree, hf_IAX_IE_REFRESH, tvb,
1022 offset + 2, ies_len, FALSE);
1024 case IAX_IE_DPSTATUS:
1025 proto_tree_add_item (ies_tree, hf_IAX_IE_DPSTATUS, tvb,
1026 offset + 2, ies_len, FALSE);
1029 proto_tree_add_item (ies_tree, hf_IAX_IE_CALLNO, tvb,
1030 offset + 2, ies_len, FALSE);
1033 proto_tree_add_item (ies_tree, hf_IAX_IE_CAUSE, tvb,
1034 offset + 2, ies_len, FALSE);
1036 case IAX_IE_IAX_UNKNOWN:
1037 proto_tree_add_item (ies_tree, hf_IAX_IE_IAX_UNKNOWN, tvb,
1038 offset + 2, ies_len, FALSE);
1040 case IAX_IE_MSGCOUNT:
1041 proto_tree_add_item (ies_tree, hf_IAX_IE_MSGCOUNT, tvb,
1042 offset + 2, ies_len, FALSE);
1044 case IAX_IE_AUTOANSWER:
1045 proto_tree_add_item (ies_tree, hf_IAX_IE_AUTOANSWER, tvb,
1046 offset + 2, ies_len, FALSE);
1048 case IAX_IE_MUSICONHOLD:
1049 proto_tree_add_item (ies_tree, hf_IAX_IE_MUSICONHOLD, tvb,
1050 offset + 2, ies_len, FALSE);
1052 case IAX_IE_TRANSFERID:
1053 proto_tree_add_item (ies_tree, hf_IAX_IE_TRANSFERID, tvb,
1054 offset + 2, ies_len, FALSE);
1057 case IAX_IE_DATAFORMAT:
1058 proto_tree_add_item (ies_tree, hf_IAX_IE_DATAFORMAT, tvb,
1059 offset + 2, ies_len, FALSE);
1062 iax_call_data -> dataformat = tvb_get_ntohl(tvb, offset+2);
1070 proto_tree_add_item( ies_tree, hf_IAX_IE_UNKNOWN_BYTE, tvb, offset+2, ies_len, FALSE );
1074 proto_tree_add_item( ies_tree, hf_IAX_IE_UNKNOWN_I16, tvb, offset+2, ies_len, FALSE );
1078 proto_tree_add_item( ies_tree, hf_IAX_IE_UNKNOWN_I32, tvb, offset+2, ies_len, FALSE );
1082 proto_tree_add_item( ies_tree, hf_IAX_IE_UNKNOWN_BYTES, tvb, offset+2, ies_len, FALSE );
1087 offset += ies_len + 2;
1092 static guint32 uncompress_subclass(guint8 csub)
1094 /* If the SC_LOG flag is set, return 2^csub otherwise csub */
1096 /* special case for 'compressed' -1 */
1100 return 1 << (csub & 0x1F);
1103 return (guint32)csub;
1108 dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
1110 packet_info * pinfo, proto_tree * iax2_tree,
1111 proto_tree * main_tree)
1113 guint32 retransmission = 0;
1120 proto_tree *packet_type_tree = NULL;
1121 iax_call_data *iax_call;
1122 iax_packet_data *iax_packet;
1124 gboolean rtp_marker;
1129 * remove the top bit for retransmission detection
1131 dcallno = tvb_get_ntohs(tvb, offset);
1132 retransmission = dcallno & 0x8000;
1133 dcallno = dcallno & 0x7FFF;
1134 ts = tvb_get_ntohl(tvb, offset+2);
1135 type = tvb_get_guint8(tvb, offset + 8);
1136 csub = tvb_get_guint8(tvb, offset + 9);
1138 /* see if we've seen this packet before */
1139 iax_packet = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
1141 /* if not, find or create an iax_call info structure for this IAX session. */
1143 if( type == AST_FRAME_IAX && csub == IAX_COMMAND_NEW ) {
1144 /* NEW packets start a new call */
1145 iax_call = iax_new_circuit_details(pinfo,scallno,&circuit);
1148 iax_call = iax_lookup_circuit_details(pinfo, scallno, dcallno,
1149 &reversed, &circuit);
1152 iax_packet = iax_new_packet_data(iax_call);
1153 p_add_proto_data(pinfo->fd,proto_iax2,iax_packet);
1155 iax_call = iax_packet->call_data;
1159 proto_item *packet_type_base;
1161 proto_tree_add_item (iax2_tree, hf_iax2_dcallno, tvb, offset, 2, FALSE );
1162 proto_tree_add_boolean(iax2_tree, hf_iax2_retransmission, tvb, offset, 2, FALSE );
1164 proto_tree_add_uint (iax2_tree, hf_iax2_ts, tvb, offset+2, 4, ts);
1166 proto_tree_add_item (iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1,
1169 proto_tree_add_item (iax2_tree, hf_iax2_iseqno, tvb, offset+7, 1,
1171 packet_type_base = proto_tree_add_uint (iax2_tree, hf_iax2_type, tvb,
1174 /* add the type-specific subtree */
1175 packet_type_tree = proto_item_add_subtree (packet_type_base, ett_iax2_type);
1178 /* add frame type to info line */
1179 if (check_col (pinfo->cinfo, COL_INFO)) {
1180 col_add_fstr (pinfo->cinfo, COL_INFO, "%s, source call# %d, timestamp %ums",
1181 val_to_str (type, iax_frame_types, "Unknown (0x%02x)"),
1187 /* add the subclass */
1188 proto_tree_add_uint (packet_type_tree, hf_iax2_iax_csub, tvb,
1192 if (check_col (pinfo->cinfo, COL_INFO))
1193 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1194 val_to_str (csub, iax_iax_subclasses, "unknown (0x%02x)"));
1196 if (offset < tvb_reported_length (tvb)) {
1197 offset += dissect_ies(tvb, offset, packet_type_tree, iax_call);
1200 if( csub == IAX_COMMAND_NEW && circuit && iax_call ) {
1201 /* if this is a data call, set up a subdissector for the circuit */
1202 dissector_handle_t s;
1203 s = dissector_get_port_handle(iax2_dataformat_dissector_table, iax_call -> dataformat );
1204 circuit_set_dissector( circuit, s );
1208 case AST_FRAME_DTMF:
1209 proto_tree_add_text (packet_type_tree, tvb, offset+9, 1, "DTMF digit: %c", csub);
1212 if (check_col (pinfo->cinfo, COL_INFO))
1213 col_append_fstr (pinfo->cinfo, COL_INFO, " digit %c", csub );
1216 case AST_FRAME_CONTROL:
1217 /* add the subclass */
1218 proto_tree_add_uint (packet_type_tree, hf_iax2_cmd_csub, tvb,
1222 if (check_col (pinfo->cinfo, COL_INFO))
1223 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1224 val_to_str (csub, iax_cmd_subclasses, "unknown (0x%02x)"));
1227 case AST_FRAME_VOICE:
1229 iax_packet -> codec = codec = uncompress_subclass(csub);
1231 if( packet_type_tree ) {
1232 proto_tree_add_item (packet_type_tree, hf_iax2_voice_csub, tvb, offset+9, 1, FALSE);
1233 proto_tree_add_uint (packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, codec);
1240 iax_call->dst_codec = codec;
1242 iax_call->src_codec = codec;
1246 dissect_payload(tvb, offset, pinfo, main_tree, ts, FALSE,iax_packet);
1249 case AST_FRAME_VIDEO:
1250 /* bit 6 of the csub is used to represent the rtp 'marker' bit */
1251 rtp_marker = csub & 0x40 ? TRUE:FALSE;
1252 iax_packet -> codec = codec = uncompress_subclass((guint8) (csub & ~40));
1254 if( packet_type_tree ) {
1255 proto_tree_add_item (packet_type_tree, hf_iax2_video_csub, tvb, offset+9, 1, FALSE);
1256 proto_tree_add_item (packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, FALSE);
1257 proto_tree_add_uint (packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, codec);
1264 iax_call->dst_vformat = codec;
1266 iax_call->src_vformat = codec;
1270 if( rtp_marker && check_col (pinfo->cinfo, COL_INFO))
1271 col_append_fstr (pinfo->cinfo, COL_INFO, ", Mark" );
1274 dissect_payload(tvb, offset, pinfo, main_tree, ts, TRUE, iax_packet);
1279 proto_tree_add_uint (packet_type_tree, hf_iax2_csub, tvb, offset+9,
1283 if (check_col (pinfo->cinfo, COL_INFO))
1284 col_append_fstr (pinfo->cinfo, COL_INFO, " subclass %d", csub );
1291 static iax_packet_data *iax2_get_packet_data_for_minipacket(packet_info * pinfo,
1295 /* see if we've seen this packet before */
1296 iax_packet_data *p = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
1299 /* if not, find or create an iax_call info structure for this IAX session. */
1302 iax_call_data *iax_call;
1304 iax_call = iax_lookup_circuit_details(pinfo, scallno, 0, &reversed, &circuit);
1306 p = iax_new_packet_data(iax_call);
1307 p_add_proto_data(pinfo->fd,proto_iax2,p);
1309 /* set the codec for this frame to be whatever the last full frame used */
1312 p->codec = reversed ? iax_call -> dst_vformat : iax_call -> src_vformat;
1314 p->codec = reversed ? iax_call -> dst_codec : iax_call -> src_codec;
1321 static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
1322 guint16 scallno, packet_info * pinfo,
1323 proto_tree * iax2_tree, proto_tree *main_tree)
1326 iax_packet_data *iax_packet;
1327 gboolean rtp_marker;
1329 ts = tvb_get_ntohs(tvb, offset);
1331 /* bit 15 of the ts is used to represent the rtp 'marker' bit */
1332 rtp_marker = ts & 0x8000 ? TRUE:FALSE;
1337 proto_tree_add_item (iax2_tree, hf_iax2_minividts, tvb, offset, 2, FALSE);
1338 proto_tree_add_item (iax2_tree, hf_iax2_minividmarker, tvb, offset, 2, FALSE);
1343 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, TRUE);
1345 if (check_col (pinfo->cinfo, COL_INFO))
1346 col_add_fstr (pinfo->cinfo, COL_INFO,
1347 "Mini video packet, source call# %d, timestamp %ums%s",
1348 scallno, ts, rtp_marker?", Mark":"");
1351 dissect_payload(tvb, offset, pinfo, main_tree, ts, TRUE, iax_packet);
1357 dissect_minipacket (tvbuff_t * tvb, guint32 offset, guint16 scallno, packet_info * pinfo, proto_tree * iax2_tree,
1358 proto_tree *main_tree)
1361 iax_packet_data *iax_packet;
1363 ts = tvb_get_ntohs(tvb, offset);
1365 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, FALSE);
1367 proto_tree_add_uint (iax2_tree, hf_iax2_minits, tvb, offset, 2,
1371 if (check_col (pinfo->cinfo, COL_INFO))
1372 col_add_fstr (pinfo->cinfo, COL_INFO,
1373 "Mini packet, source call# %d, timestamp %ums",
1377 /* XXX fix the timestamp logic */
1378 dissect_payload(tvb, offset, pinfo, main_tree, ts, FALSE, iax_packet);
1384 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
1385 packet_info *pinfo, proto_tree *tree,
1386 guint32 ts, gboolean video,
1387 iax_packet_data *iax_packet)
1389 gboolean out_of_order = FALSE;
1391 guint32 codec = iax_packet -> codec;
1392 iax_call_data *iax_call = iax_packet -> call_data;
1394 /* keep compiler quiet */
1397 if( offset >= tvb_reported_length (tvb)) {
1398 if (check_col (pinfo->cinfo, COL_INFO))
1399 col_append_fstr (pinfo->cinfo, COL_INFO, ", empty frame" );
1403 sub_tvb = tvb_new_subset(tvb, offset, -1, -1 );
1405 /* XXX shouldn't pass through out-of-order packets. */
1407 if (check_col (pinfo->cinfo, COL_INFO)) {
1408 if( !video && iax_call && iax_call -> dataformat != 0 ) {
1409 col_append_fstr (pinfo->cinfo, COL_INFO, ", data, format %s",
1410 val_to_str (iax_call -> dataformat,
1411 iax_dataformats, "unknown (0x%02x)"));
1414 col_append_fstr (pinfo->cinfo, COL_INFO, " (out-of-order packet)");
1416 col_append_fstr (pinfo->cinfo, COL_INFO, ", %s",
1417 val_to_str (codec, codec_types, "unknown (0x%02x)"));
1421 /* pass the rest of the block to a subdissector */
1422 if( !video && try_circuit_dissector(pinfo->ctype, pinfo->circuit_id, pinfo->fd->num,
1423 sub_tvb, pinfo, tree))
1426 if( codec != 0 && dissector_try_port(iax2_codec_dissector_table, codec, sub_tvb, pinfo, tree ))
1429 /* we don't know how to dissect our data: dissect it as data */
1430 call_dissector(data_handle,sub_tvb, pinfo, tree);
1437 /* called at the start of a capture. We should clear out our static, per-capture
1442 iax_init_protocol(void)
1447 g_mem_chunk_destroy(iax_packets);
1448 iax_packets = g_mem_chunk_create(iax_packet_data,128,G_ALLOC_ONLY);
1453 proto_register_iax2 (void)
1455 /* we use this for displaying which codecs are supported */
1456 static const true_false_string supported_strings = {
1461 /* A header field is something you can search/filter on.
1463 * We create a structure to register our fields. It consists of an
1464 * array of hf_register_info structures, each of which are of the format
1465 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1468 static hf_register_info hf[] = {
1470 {&hf_iax2_packet_type,
1471 {"Packet type", "iax2.type", FT_UINT8, BASE_DEC, VALS(iax_packet_types), 0,
1472 "Full/minivoice/minivideo/meta packet",
1477 {"Source call", "iax2.src_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
1478 "src_call holds the number of this call at the packet source pbx",
1481 /* FIXME could this be turned into a FRAMENUM field? */
1483 {"Destination call", "iax2.dst_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
1484 "dst_call holds the number of this call at the packet destination",
1487 {&hf_iax2_retransmission,
1488 {"Retransmission", "iax2.retransmission", FT_BOOLEAN, 16,
1490 "retransmission is set if this packet is a retransmission of an earlier "
1491 "failed packet", HFILL}},
1494 {"Timestamp", "iax2.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
1495 "timestamp is the time, in ms after the start of this call, at which "
1496 "this packet was transmitted",
1500 {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x0,
1501 "timestamp is the time, in ms after the start of this call, at which "
1502 "this packet was transmitted",
1505 {&hf_iax2_minividts,
1506 {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
1507 "timestamp is the time, in ms after the start of this call, at which "
1508 "this packet was transmitted",
1511 {&hf_iax2_minividmarker,
1512 {"Marker", "iax2.video.marker", FT_UINT16, BASE_DEC, NULL, 0x8000,
1513 "RTP end-of-frame marker",
1517 {"Outbound seq.no.", "iax2.oseqno", FT_UINT16, BASE_DEC, NULL,
1519 "oseqno is the sequence no of this packet. The first packet has "
1520 "oseqno==0, and subsequent packets increment the oseqno by 1",
1524 {"Inbound seq.no.", "iax2.iseqno", FT_UINT16, BASE_DEC, NULL, 0x0,
1525 "iseqno is the sequence no of the last successfully recieved packet",
1529 {"Type", "iax2.type", FT_UINT8, BASE_DEC, VALS (iax_frame_types),
1531 "For full IAX2 frames, type is the type of frame",
1535 {"Sub-class", "iax2.subclass", FT_UINT8, BASE_DEC, NULL, 0x0,
1540 {"Control subclass", "iax2.control.subclass", FT_UINT8, BASE_DEC,
1541 VALS (iax_cmd_subclasses), 0x0,
1542 "This gives the command number for a Control packet.", HFILL}},
1545 {"IAX type", "iax2.iax.subclass", FT_UINT8, BASE_DEC,
1546 VALS (iax_iax_subclasses),
1548 "IAX type gives the command number for IAX signalling packets", HFILL}},
1550 {&hf_iax2_voice_csub,
1551 {"Sub-class", "iax2.voice.subclass", FT_UINT8, BASE_DEC, NULL, 0x0,
1555 {&hf_iax2_voice_codec,
1556 {"CODEC", "iax2.voice.codec", FT_UINT32, BASE_HEX, VALS (codec_types),
1558 "CODEC gives the codec used to encode audio data", HFILL}},
1560 {&hf_iax2_video_csub,
1561 {"Subclass (compressed codec no)", "iax2.video.subclass", FT_UINT8, BASE_DEC, NULL, 0xBF,
1562 "Subclass (compressed codec no)",
1566 {"Marker", "iax2.video.marker", FT_BOOLEAN, 8, NULL, 0x40,
1567 "RTP end-of-frame marker",
1570 {&hf_iax2_video_codec,
1571 {"CODEC", "iax2.video.codec", FT_UINT32, BASE_HEX, VALS (codec_types), 0,
1572 "The codec used to encode video data", HFILL}},
1575 * Decoding for the ies
1578 {&hf_IAX_IE_APPARENTADDR_SINFAMILY,
1579 {"Family", "iax2.iax.app_addr.sinfamily", FT_UINT16, BASE_DEC, NULL, 0, "Family", HFILL }},
1580 {&hf_IAX_IE_APPARENTADDR_SINPORT,
1581 {"Port", "iax2.iax.app_addr.sinport", FT_UINT16, BASE_DEC, NULL, 0, "Port", HFILL }},
1582 {&hf_IAX_IE_APPARENTADDR_SINADDR,
1583 {"Address", "iax2.iax.app_addr.sinaddr", FT_IPv4, BASE_HEX, NULL, 0, "Address", HFILL }},
1584 {&hf_IAX_IE_APPARENTADDR_SINZERO,
1585 {"Zero", "iax2.iax.app_addr.sinzero", FT_BYTES, BASE_HEX, NULL, 0, "Zero", HFILL }},
1587 {&hf_IAX_IE_CALLED_NUMBER,
1588 {"Number/extension being called", "iax2.iax.called_number",
1590 BASE_NONE, NULL, 0x0, "", HFILL}},
1592 {&hf_IAX_IE_CALLING_NUMBER,
1593 {"Calling number", "iax2.iax.calling_number", FT_STRING,
1597 {&hf_IAX_IE_CALLING_ANI,
1598 {"Calling number ANI for billing", "iax2.iax.calling_ani",
1600 BASE_NONE, NULL, 0x0, "", HFILL}},
1602 {&hf_IAX_IE_CALLING_NAME,
1603 {"Name of caller", "iax2.iax.calling_name", FT_STRING, BASE_NONE,
1607 {&hf_IAX_IE_CALLED_CONTEXT,
1608 {"Context for number", "iax2.iax.called_context", FT_STRING,
1610 NULL, 0x0, "", HFILL}},
1612 {&hf_IAX_IE_USERNAME,
1613 {"Username (peer or user) for authentication",
1614 "iax2.iax.username",
1615 FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
1617 {&hf_IAX_IE_PASSWORD,
1618 {"Password for authentication", "iax2.iax.password", FT_STRING,
1619 BASE_NONE, NULL, 0x0, "", HFILL}},
1621 {&hf_IAX_IE_CAPABILITY,
1622 {"Actual codec capability", "iax2.iax.capability", FT_UINT32,
1624 NULL, 0x0, "", HFILL}},
1627 {"Desired codec format", "iax2.iax.format", FT_UINT32, BASE_HEX,
1628 VALS (codec_types), 0x0, "", HFILL}},
1630 {&hf_IAX_IE_LANGUAGE,
1631 {"Desired language", "iax2.iax.language", FT_STRING, BASE_NONE,
1635 {&hf_IAX_IE_VERSION,
1636 {"Protocol version", "iax2.iax.version", FT_UINT16, BASE_HEX, NULL,
1640 {&hf_IAX_IE_ADSICPE,
1641 {"CPE ADSI capability", "iax2.iax.cpe_adsi", FT_UINT16, BASE_HEX,
1646 {"Originally dialed DNID", "iax2.iax.dnid", FT_STRING, BASE_NONE,
1650 {&hf_IAX_IE_AUTHMETHODS,
1651 {"Authentication method(s)", "iax2.iax.auth.methods", FT_UINT16,
1653 NULL, 0x0, "", HFILL}},
1655 {&hf_IAX_IE_CHALLENGE,
1656 {"Challenge data for MD5/RSA", "iax2.iax.auth.challenge",
1658 BASE_NONE, NULL, 0x0, "", HFILL}},
1660 {&hf_IAX_IE_MD5_RESULT,
1661 {"MD5 challenge result", "iax2.iax.auth.md5", FT_STRING,
1665 {&hf_IAX_IE_RSA_RESULT,
1666 {"RSA challenge result", "iax2.iax.auth.rsa", FT_STRING,
1670 {&hf_IAX_IE_REFRESH,
1671 {"When to refresh registration", "iax2.iax.refresh", FT_INT16,
1673 NULL, 0x0, "", HFILL}},
1675 {&hf_IAX_IE_DPSTATUS,
1676 {"Dialplan status", "iax2.iax.dialplan_status", FT_UINT16,
1681 {"Call number of peer", "iax2.iax.call_no", FT_INT16, BASE_DEC,
1686 {"Cause", "iax2.iax.cause", FT_STRING, BASE_NONE, NULL, 0x0, "",
1689 {&hf_IAX_IE_IAX_UNKNOWN,
1690 {"Unknown IAX command", "iax2.iax.iax_unknown", FT_BYTES,
1694 {&hf_IAX_IE_MSGCOUNT,
1695 {"How many messages waiting", "iax2.iax.msg_count", FT_INT16,
1697 NULL, 0x0, "", HFILL}},
1699 {&hf_IAX_IE_AUTOANSWER,
1700 {"Request auto-answering", "iax2.iax.autoanswer", FT_NONE,
1702 NULL, 0x0, "", HFILL}},
1704 {&hf_IAX_IE_MUSICONHOLD,
1705 {"Request musiconhold with QUELCH", "iax2.iax.moh", FT_NONE,
1707 NULL, 0x0, "", HFILL}},
1709 {&hf_IAX_IE_TRANSFERID,
1710 {"Transfer Request Identifier", "iax2.iax.transferid", FT_UINT32,
1711 BASE_HEX, NULL, 0x0, "", HFILL}},
1714 {"Referring DNIS", "iax2.iax.rdnis", FT_STRING, BASE_NONE, NULL,
1718 {&hf_IAX_IE_DATAFORMAT,
1719 {"Data call format", "iax2.iax.dataformat", FT_UINT32, BASE_HEX,
1720 VALS(iax_dataformats), 0x0, "", HFILL}},
1722 {&hf_IAX_IE_UNKNOWN_BYTE,
1723 {"data", "iax2.iax.unknowndata", FT_UINT8, BASE_HEX, NULL,
1724 0x0, "Raw data for unknown IEs",
1726 {&hf_IAX_IE_UNKNOWN_I16,
1727 {"data", "iax2.iax.unknowndata", FT_UINT16, BASE_HEX, NULL,
1728 0x0, "Raw data for unknown IEs",
1730 {&hf_IAX_IE_UNKNOWN_I32,
1731 {"data", "iax2.iax.unknowndata", FT_UINT32, BASE_HEX, NULL,
1732 0x0, "Raw data for unknown IEs",
1734 {&hf_IAX_IE_UNKNOWN_BYTES,
1735 {"data", "iax2.iax.unknowndata", FT_BYTES, BASE_NONE, NULL,
1736 0x0, "Raw data for unknown IEs",
1740 {&hf_iax2_cap_g723_1,
1741 {"G.723.1 compression", "iax2.cap.g723_1", FT_BOOLEAN, 32,
1742 TFS(&supported_strings), AST_FORMAT_G723_1,
1743 "G.723.1 compression", HFILL }},
1746 {"GSM compression", "iax2.cap.gsm", FT_BOOLEAN, 32,
1747 TFS(&supported_strings), AST_FORMAT_GSM,
1748 "GSM compression", HFILL }},
1751 {"Raw mu-law data (G.711)", "iax2.cap.ulaw",FT_BOOLEAN, 32,
1752 TFS(&supported_strings), AST_FORMAT_ULAW,
1753 "Raw mu-law data (G.711)", HFILL }},
1756 {"Raw A-law data (G.711)", "iax2.cap.alaw",FT_BOOLEAN, 32,
1757 TFS(&supported_strings), AST_FORMAT_ALAW,
1758 "Raw A-law data (G.711)", HFILL }},
1761 {"G.726 compression", "iax2.cap.g726",FT_BOOLEAN, 32,
1762 TFS(&supported_strings), AST_FORMAT_G726,
1763 "G.726 compression", HFILL }},
1765 {&hf_iax2_cap_adpcm,
1766 {"ADPCM", "iax2.cap.adpcm", FT_BOOLEAN, 32,
1767 TFS(&supported_strings), AST_FORMAT_ADPCM,
1770 {&hf_iax2_cap_slinear,
1771 {"Raw 16-bit Signed Linear (8000 Hz) PCM", "iax2.cap.slinear",
1772 FT_BOOLEAN, 32, TFS(&supported_strings), AST_FORMAT_SLINEAR,
1773 "Raw 16-bit Signed Linear (8000 Hz) PCM", HFILL }},
1775 {&hf_iax2_cap_lpc10,
1776 {"LPC10, 180 samples/frame", "iax2.cap.lpc10", FT_BOOLEAN, 32,
1777 TFS(&supported_strings), AST_FORMAT_LPC10,
1778 "LPC10, 180 samples/frame", HFILL }},
1780 {&hf_iax2_cap_g729a,
1781 {"G.729a Audio", "iax2.cap.g729a", FT_BOOLEAN, 32,
1782 TFS(&supported_strings), AST_FORMAT_G729A,
1783 "G.729a Audio", HFILL }},
1785 {&hf_iax2_cap_speex,
1786 {"SPEEX Audio", "iax2.cap.speex", FT_BOOLEAN, 32,
1787 TFS(&supported_strings), AST_FORMAT_SPEEX,
1788 "SPEEX Audio", HFILL }},
1791 {"iLBC Free compressed Audio", "iax2.cap.ilbc", FT_BOOLEAN, 32,
1792 TFS(&supported_strings), AST_FORMAT_ILBC,
1793 "iLBC Free compressed Audio", HFILL }},
1796 {"JPEG images", "iax2.cap.jpeg", FT_BOOLEAN, 32,
1797 TFS(&supported_strings), AST_FORMAT_JPEG,
1798 "JPEG images", HFILL }},
1801 {"PNG images", "iax2.cap.png", FT_BOOLEAN, 32,
1802 TFS(&supported_strings), AST_FORMAT_PNG,
1803 "PNG images", HFILL }},
1806 {"H.261 video", "iax2.cap.h261", FT_BOOLEAN, 32,
1807 TFS(&supported_strings), AST_FORMAT_H261,
1808 "H.261 video", HFILL }},
1811 {"H.263 video", "iax2.cap.h263", FT_BOOLEAN, 32,
1812 TFS(&supported_strings), AST_FORMAT_H263,
1813 "H.263 video", HFILL }}
1816 static gint *ett[] = {
1818 &ett_iax2_full_mini_subtree,
1822 &ett_iax2_ies_apparent_addr
1826 proto_register_protocol ("Inter-Asterisk eXchange v2", "IAX2", "iax2");
1827 proto_register_field_array (proto_iax2, hf, array_length (hf));
1828 proto_register_subtree_array (ett, array_length (ett));
1830 register_dissector("iax2", dissect_iax2, proto_iax2);
1832 iax2_codec_dissector_table = register_dissector_table(
1833 "iax2.codec","IAX codec number", FT_UINT32, BASE_HEX);
1834 iax2_dataformat_dissector_table = register_dissector_table(
1835 "iax2.dataformat","IAX dataformat number", FT_UINT32, BASE_HEX);
1837 /* register our init routine to be called at the start of a capture,
1838 to clear out our hash tables etc */
1839 register_init_routine(&iax_init_protocol);
1843 proto_reg_handoff_iax2 (void)
1845 dissector_add("udp.port", IAX2_PORT, find_dissector("iax2"));
1846 dissector_add("iax2.dataformat", AST_DATAFORMAT_V110, find_dissector("v110"));
1847 data_handle = find_dissector("data");
1852 * This sets up the indentation style for this file in emacs.