4 * Routines for IAX2 packet disassembly
5 * By Alastair Maw <asterisk@almaw.com>
6 * Copyright 2003 Alastair Maw
8 * IAX2 is a VoIP protocol for the open source PBX Asterisk. Please see
9 * http://www.asterisk.org for more information; see
11 * http://www.ietf.org/internet-drafts/draft-guy-iax-04.txt
13 * for the current Internet-Draft for IAX2.
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
19 * Copyright 1998 Gerald Combs
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 #include <epan/circuit.h>
45 #include <epan/packet.h>
46 #include <epan/to_str.h>
47 #include <epan/emem.h>
48 #include <epan/reassemble.h>
49 #include <epan/aftypes.h>
51 #include <epan/tap-voip.h>
53 #include "packet-iax2.h"
54 #include <epan/iax2_codec_type.h>
56 #define IAX2_PORT 4569
57 #define PROTO_TAG_IAX2 "IAX2"
59 /* enough to hold any address in an address_t */
60 #define MAX_ADDRESS 16
62 /* the maximum number of transfers (of each end) we can deal with per call,
64 #define IAX_MAX_TRANSFERS 2
66 /* #define DEBUG_HASHING */
67 /* #define DEBUG_DESEGMENT */
69 /* Wireshark ID of the IAX2 protocol */
70 static int proto_iax2 = -1;
73 static int iax2_tap = -1;
75 /* protocol tap info */
76 static iax2_info_t ii_arr[1];
77 static iax2_info_t *iax2_info = ii_arr;
79 /* The following hf_* variables are used to hold the wireshark IDs of
80 * our header fields; they are filled out when we call
81 * proto_register_field_array() in proto_register_iax2()
83 static int hf_iax2_packet_type = -1;
84 static int hf_iax2_retransmission = -1;
85 static int hf_iax2_callno = -1;
86 static int hf_iax2_scallno = -1;
87 static int hf_iax2_dcallno = -1;
88 static int hf_iax2_ts = -1;
89 static int hf_iax2_minits = -1;
90 static int hf_iax2_minividts = -1;
91 static int hf_iax2_absts = -1;
92 static int hf_iax2_lateness = -1;
93 static int hf_iax2_minividmarker = -1;
94 static int hf_iax2_oseqno = -1;
95 static int hf_iax2_iseqno = -1;
96 static int hf_iax2_type = -1;
97 static int hf_iax2_csub = -1;
98 static int hf_iax2_dtmf_csub = -1;
99 static int hf_iax2_cmd_csub = -1;
100 static int hf_iax2_iax_csub = -1;
101 static int hf_iax2_voice_csub = -1;
102 static int hf_iax2_voice_codec = -1;
103 static int hf_iax2_video_csub = -1;
104 static int hf_iax2_video_codec = -1;
105 static int hf_iax2_marker = -1;
106 static int hf_iax2_modem_csub = -1;
108 static int hf_iax2_cap_g723_1 = -1;
109 static int hf_iax2_cap_gsm = -1;
110 static int hf_iax2_cap_ulaw = -1;
111 static int hf_iax2_cap_alaw = -1;
112 static int hf_iax2_cap_g726 = -1;
113 static int hf_iax2_cap_adpcm = -1;
114 static int hf_iax2_cap_slinear = -1;
115 static int hf_iax2_cap_lpc10 = -1;
116 static int hf_iax2_cap_g729a = -1;
117 static int hf_iax2_cap_speex = -1;
118 static int hf_iax2_cap_ilbc = -1;
119 static int hf_iax2_cap_jpeg = -1;
120 static int hf_iax2_cap_png = -1;
121 static int hf_iax2_cap_h261 = -1;
122 static int hf_iax2_cap_h263 = -1;
124 static int hf_iax2_fragments = -1;
125 static int hf_iax2_fragment = -1;
126 static int hf_iax2_fragment_overlap = -1;
127 static int hf_iax2_fragment_overlap_conflict = -1;
128 static int hf_iax2_fragment_multiple_tails = -1;
129 static int hf_iax2_fragment_too_long_fragment = -1;
130 static int hf_iax2_fragment_error = -1;
131 static int hf_iax2_reassembled_in = -1;
134 /* hf_iax2_ies is an array of header fields, one per potential Information
135 * Element. It's done this way (rather than having separate variables for each
136 * IE) to make the dissection of information elements clearer and more
139 * To add the ability to dissect a new information element, just add an
140 * appropriate entry to hf[] in proto_register_iax2(); dissect_ies() will then
141 * pick it up automatically.
143 static int hf_iax2_ies[256];
144 static int hf_iax2_ie_datetime = -1;
145 static int hf_IAX_IE_APPARENTADDR_SINFAMILY = -1;
146 static int hf_IAX_IE_APPARENTADDR_SINPORT = -1;
147 static int hf_IAX_IE_APPARENTADDR_SINADDR = -1;
148 static int hf_IAX_IE_UNKNOWN_BYTE = -1;
149 static int hf_IAX_IE_UNKNOWN_I16 = -1;
150 static int hf_IAX_IE_UNKNOWN_I32 = -1;
151 static int hf_IAX_IE_UNKNOWN_BYTES = -1;
153 /* These are the ids of the subtrees that we may be creating */
154 static gint ett_iax2 = -1;
155 static gint ett_iax2_full_mini_subtree = -1;
156 static gint ett_iax2_type = -1; /* Frame-type specific subtree */
157 static gint ett_iax2_ie = -1; /* single IE */
158 static gint ett_iax2_codecs = -1; /* capabilities IE */
159 static gint ett_iax2_ies_apparent_addr = -1; /* apparent address IE */
160 static gint ett_iax2_fragment = -1;
161 static gint ett_iax2_fragments = -1;
163 static const fragment_items iax2_fragment_items = {
168 &hf_iax2_fragment_overlap,
169 &hf_iax2_fragment_overlap_conflict,
170 &hf_iax2_fragment_multiple_tails,
171 &hf_iax2_fragment_too_long_fragment,
172 &hf_iax2_fragment_error,
173 &hf_iax2_reassembled_in,
177 static dissector_handle_t data_handle;
179 /* data-call subdissectors, AST_DATAFORMAT_* */
180 static dissector_table_t iax2_dataformat_dissector_table;
181 /* voice/video call subdissectors, AST_FORMAT_* */
182 static dissector_table_t iax2_codec_dissector_table;
184 /* IAX2 Full-frame types */
185 static const value_string iax_frame_types[] = {
187 {AST_FRAME_DTMF_END, "DTMF End"},
188 {AST_FRAME_VOICE, "Voice"},
189 {AST_FRAME_VIDEO, "Video"},
190 {AST_FRAME_CONTROL, "Control"},
191 {AST_FRAME_NULL, "NULL"},
192 {AST_FRAME_IAX, "IAX"},
193 {AST_FRAME_TEXT, "Text"},
194 {AST_FRAME_IMAGE, "Image"},
195 {AST_FRAME_HTML, "HTML"},
196 {AST_FRAME_CNG, "Comfort Noise"},
197 {AST_FRAME_MODEM, "Modem"},
198 {AST_FRAME_DTMF_BEGIN, "DTMF Begin"},
202 /* Subclasses for IAX packets */
203 static const value_string iax_iax_subclasses[] = {
245 /* Subclassess for Control packets */
246 static const value_string iax_cmd_subclasses[] = {
255 {0xFF, "stop sounds"}, /* sent by app_dial, and not much else */
259 /* IAX2 to tap-voip call state mapping */
260 static const voip_call_state tap_cmd_voip_state[] = {
262 VOIP_COMPLETED, /*HANGUP*/
263 VOIP_RINGING, /*RING*/
264 VOIP_RINGING, /*RINGING*/
265 VOIP_IN_CALL, /*ANSWER*/
266 VOIP_REJECTED, /*BUSY*/
267 VOIP_UNKNOWN, /*TKOFFHK*/
268 VOIP_UNKNOWN /*OFFHOOK*/
272 /* Subclassess for Modem packets */
273 static const value_string iax_modem_subclasses[] = {
280 /* Information elements */
281 static const value_string iax_ies_type[] = {
282 {IAX_IE_CALLED_NUMBER, "Number/extension being called"},
283 {IAX_IE_CALLING_NUMBER, "Calling number"},
284 {IAX_IE_CALLING_ANI, "Calling number ANI for billing"},
285 {IAX_IE_CALLING_NAME, "Name of caller"},
286 {IAX_IE_CALLED_CONTEXT, "Context for number"},
287 {IAX_IE_USERNAME, "Username (peer or user) for authentication"},
288 {IAX_IE_PASSWORD, "Password for authentication"},
289 {IAX_IE_CAPABILITY, "Actual codec capability"},
290 {IAX_IE_FORMAT, "Desired codec format"},
291 {IAX_IE_LANGUAGE, "Desired language"},
292 {IAX_IE_VERSION, "Protocol version"},
293 {IAX_IE_ADSICPE, "CPE ADSI capability"},
294 {IAX_IE_DNID, "Originally dialed DNID"},
295 {IAX_IE_AUTHMETHODS, "Authentication method(s)"},
296 {IAX_IE_CHALLENGE, "Challenge data for MD5/RSA"},
297 {IAX_IE_MD5_RESULT, "MD5 challenge result"},
298 {IAX_IE_RSA_RESULT, "RSA challenge result"},
299 {IAX_IE_APPARENT_ADDR, "Apparent address of peer"},
300 {IAX_IE_REFRESH, "When to refresh registration"},
301 {IAX_IE_DPSTATUS, "Dialplan status"},
302 {IAX_IE_CALLNO, "Call number of peer"},
303 {IAX_IE_CAUSE, "Cause"},
304 {IAX_IE_IAX_UNKNOWN, "Unknown IAX command"},
305 {IAX_IE_MSGCOUNT, "How many messages waiting"},
306 {IAX_IE_AUTOANSWER, "Request auto-answering"},
307 {IAX_IE_MUSICONHOLD, "Request musiconhold with QUELCH"},
308 {IAX_IE_TRANSFERID, "Transfer Request Identifier"},
309 {IAX_IE_RDNIS, "Referring DNIS"},
310 {IAX_IE_PROVISIONING, "Provisioning info"},
311 {IAX_IE_AESPROVISIONING, "AES Provisioning info"},
312 {IAX_IE_DATETIME,"Date/Time"},
313 {IAX_IE_DEVICETYPE, "Device type"},
314 {IAX_IE_SERVICEIDENT, "Service Identifier"},
315 {IAX_IE_FIRMWAREVER, "Firmware revision"},
316 {IAX_IE_FWBLOCKDESC, "Firmware block description"},
317 {IAX_IE_FWBLOCKDATA, "Firmware block of data"},
318 {IAX_IE_PROVVER, "Provisioning version"},
319 {IAX_IE_CALLINGPRES, "Calling presentation"},
320 {IAX_IE_CALLINGTON, "Calling type of number"},
321 {IAX_IE_CALLINGTNS, "Calling transit network select"},
322 {IAX_IE_SAMPLINGRATE, "Supported sampling rates"},
323 {IAX_IE_CAUSECODE, "Hangup cause"},
324 {IAX_IE_ENCRYPTION, "Encryption format"},
325 {IAX_IE_ENCKEY, "Raw encryption key"},
326 {IAX_IE_CODEC_PREFS, "Codec preferences"},
327 {IAX_IE_RR_JITTER, "Received jitter"},
328 {IAX_IE_RR_LOSS, "Received loss"},
329 {IAX_IE_RR_PKTS, "Received frames"},
330 {IAX_IE_RR_DELAY, "Max playout delay in ms for received frames"},
331 {IAX_IE_RR_DROPPED, "Dropped frames"},
332 {IAX_IE_RR_OOO, "Frames received out of order"},
333 {IAX_IE_DATAFORMAT, "Data call format"},
337 static const value_string codec_types[] = {
338 {AST_FORMAT_G723_1, "G.723.1 compression"},
339 {AST_FORMAT_GSM, "GSM compression"},
340 {AST_FORMAT_ULAW, "Raw mu-law data (G.711)"},
341 {AST_FORMAT_ALAW, "Raw A-law data (G.711)"},
342 {AST_FORMAT_G726, "ADPCM (G.726, 32kbps)"},
343 {AST_FORMAT_ADPCM, "ADPCM (IMA)"},
344 {AST_FORMAT_SLINEAR, "Raw 16-bit Signed Linear (8000 Hz) PCM"},
345 {AST_FORMAT_LPC10, "LPC10, 180 samples/frame"},
346 {AST_FORMAT_G729A, "G.729a Audio"},
347 {AST_FORMAT_SPEEX, "SpeeX Free Compression"},
348 {AST_FORMAT_ILBC, "iLBC Free Compression"},
349 {AST_FORMAT_JPEG, "JPEG Images"},
350 {AST_FORMAT_PNG, "PNG Images"},
351 {AST_FORMAT_H261, "H.261 Video"},
352 {AST_FORMAT_H263, "H.263 Video"},
356 static const value_string iax_dataformats[] = {
357 {AST_DATAFORMAT_NULL, "N/A (analogue call?)"},
358 {AST_DATAFORMAT_V110, "ITU-T V.110 rate adaption"},
359 {AST_DATAFORMAT_H223_H245,"ITU-T H.223/H.245"},
364 static const value_string iax_packet_types[] = {
365 {IAX2_FULL_PACKET, "Full packet"},
366 {IAX2_MINI_VOICE_PACKET, "Mini voice packet"},
367 {IAX2_MINI_VIDEO_PACKET, "Mini video packet"},
368 {IAX2_META_PACKET, "Meta packet"},
372 static const value_string iax_causecodes[] = {
373 {AST_CAUSE_UNALLOCATED, "Unallocated"},
374 {AST_CAUSE_NO_ROUTE_TRANSIT_NET, "No route transit net"},
375 {AST_CAUSE_NO_ROUTE_DESTINATION, "No route to destination"},
376 {AST_CAUSE_CHANNEL_UNACCEPTABLE, "Channel unacceptable"},
377 {AST_CAUSE_CALL_AWARDED_DELIVERED, "Call awarded delivered"},
378 {AST_CAUSE_NORMAL_CLEARING, "Normal clearing"},
379 {AST_CAUSE_USER_BUSY, "User busy"},
380 {AST_CAUSE_NO_USER_RESPONSE, "No user response"},
381 {AST_CAUSE_NO_ANSWER, "No answer"},
382 {AST_CAUSE_CALL_REJECTED, "Call rejected"},
383 {AST_CAUSE_NUMBER_CHANGED, "Number changed"},
384 {AST_CAUSE_DESTINATION_OUT_OF_ORDER, "Destination out of order"},
385 {AST_CAUSE_INVALID_NUMBER_FORMAT, "Invalid number format"},
386 {AST_CAUSE_FACILITY_REJECTED, "Facility rejected"},
387 {AST_CAUSE_RESPONSE_TO_STATUS_ENQUIRY, "Response to status inquiry"},
388 {AST_CAUSE_NORMAL_UNSPECIFIED, "Normal unspecified"},
389 {AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, "Normal circuit congestion"},
390 {AST_CAUSE_NETWORK_OUT_OF_ORDER, "Network out of order"},
391 {AST_CAUSE_NORMAL_TEMPORARY_FAILURE, "Normal temporary failure"},
392 {AST_CAUSE_SWITCH_CONGESTION, "Switch congestion"},
393 {AST_CAUSE_ACCESS_INFO_DISCARDED, "Access info discarded"},
394 {AST_CAUSE_REQUESTED_CHAN_UNAVAIL, "Requested channel unavailable"},
395 {AST_CAUSE_PRE_EMPTED, "Preempted"},
396 {AST_CAUSE_FACILITY_NOT_SUBSCRIBED, "Facility not subscribed"},
397 {AST_CAUSE_OUTGOING_CALL_BARRED, "Outgoing call barred"},
398 {AST_CAUSE_INCOMING_CALL_BARRED, "Incoming call barred"},
399 {AST_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized"},
400 {AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available"},
401 {AST_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented"},
402 {AST_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented"},
403 {AST_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented"},
404 {AST_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference"},
405 {AST_CAUSE_INCOMPATIBLE_DESTINATION, "Incompatible destination"},
406 {AST_CAUSE_INVALID_MSG_UNSPECIFIED, "Invalid message unspecified"},
407 {AST_CAUSE_MANDATORY_IE_MISSING, "Mandatory IE missing"},
408 {AST_CAUSE_MESSAGE_TYPE_NONEXIST, "Message type nonexistent"},
409 {AST_CAUSE_WRONG_MESSAGE, "Wrong message"},
410 {AST_CAUSE_IE_NONEXIST, "IE nonexistent"},
411 {AST_CAUSE_INVALID_IE_CONTENTS, "Invalid IE contents"},
412 {AST_CAUSE_WRONG_CALL_STATE, "Wrong call state"},
413 {AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, "Recovery on timer expire"},
414 {AST_CAUSE_MANDATORY_IE_LENGTH_ERROR, "Mandatory IE length error"},
415 {AST_CAUSE_PROTOCOL_ERROR, "Protocol error"},
416 {AST_CAUSE_INTERWORKING, "Interworking"},
421 /* ************************************************************************* */
423 /* In order to track IAX calls, we have a hash table which maps
424 * {addr,port type,port,call} to a unique circuit id.
426 * Each call has two such circuits associated with it (a forward and a
427 * reverse circuit, where 'forward' is defined as the direction the NEW
428 * packet went in), and we maintain an iax_call_data structure for each
429 * call, attached to both circuits with circuit_add_proto_data.
431 * Because {addr,port type,port,call} quadruplets can be reused
432 * (Asterisk reuses call numbers), circuit ids aren't unique to
433 * individual calls and we treat NEW packets somewhat specially. When we
434 * get such a packet, we see if there are any calls with a matching
435 * circuit id, and make sure that its circuits are marked as ended
436 * before that packet.
438 * A second complication is that we only know one quadruplet at the time
439 * the NEW packet is processed: there is therefore cunningness in
440 * iax_lookup_circuit_details() to look for replies to NEW packets and
441 * create the reverse circuit.
445 /* start with a hash of {addr,port type,port,call}->{id} */
453 /* this is where addr->data points to. it's put in here for easy freeing */
454 guint8 address_data[MAX_ADDRESS];
458 static GHashTable *iax_circuit_hashtab = NULL;
459 static guint circuitcount = 0;
461 /* the number of keys and values to reserve space for in each memory chunk.
462 We assume we won't be tracking many calls at once so this is quite low.
464 #define IAX_INIT_PACKET_COUNT 10
467 static gchar *key_to_str( const iax_circuit_key *key )
470 static gchar *strp, str[3][80];
478 /* why doesn't address_to_str take a const pointer?
479 cast the warnings into oblivion. */
481 /* XXX - is this a case for ep_alloc? */
482 g_snprintf(strp, 80, "{%s:%i,%i}",
483 address_to_str((address *)&key->addr),
491 static gint iax_circuit_equal(gconstpointer v, gconstpointer w)
493 const iax_circuit_key *v1 = (const iax_circuit_key *)v;
494 const iax_circuit_key *v2 = (const iax_circuit_key *)w;
497 result = ( ADDRESSES_EQUAL(&(v1->addr), &(v2->addr)) &&
498 v1->ptype == v2->ptype &&
499 v1->port == v2->port &&
500 v1->callno== v2->callno);
502 g_debug( "+++ Comparing for equality: %s, %s: %u",key_to_str(v1), key_to_str(v2), result);
508 static guint iax_circuit_hash (gconstpointer v)
510 const iax_circuit_key *key = (const iax_circuit_key *)v;
514 ADD_ADDRESS_TO_HASH(hash_val, &key->addr);
515 hash_val += (guint)(key->ptype);
516 hash_val += (guint)(key->port);
517 hash_val += (guint)(key->callno);
520 g_debug( "+++ Hashing key: %s, result %#x", key_to_str(key), hash_val );
523 return (guint) hash_val;
526 /* Find, or create, a circuit for the given
527 {address,porttype,port,call} quadruplet
529 static guint iax_circuit_lookup(const address *address_p,
535 guint32 *circuit_id_p;
537 key.addr = *address_p;
542 circuit_id_p = g_hash_table_lookup( iax_circuit_hashtab, &key);
543 if( ! circuit_id_p ) {
544 iax_circuit_key *new_key;
546 new_key = se_alloc(sizeof(iax_circuit_key));
547 new_key->addr.type = address_p->type;
548 new_key->addr.len = MIN(address_p->len,MAX_ADDRESS);
549 new_key->addr.data = new_key->address_data;
550 memcpy(new_key->address_data,address_p->data,new_key->addr.len);
551 new_key->ptype = ptype;
552 new_key->port = port;
553 new_key->callno = callno;
555 circuit_id_p = se_alloc(sizeof(iax_circuit_key));
556 *circuit_id_p = ++circuitcount;
558 g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p);
561 g_debug("Created new circuit id %u for node %s", *circuit_id_p, key_to_str(new_key));
565 return *circuit_id_p;
569 /* ************************************************************************* */
572 guint32 current_frag_id; /* invalid unless current_frag_bytes > 0 */
573 guint32 current_frag_bytes;
574 guint32 current_frag_minlen;
577 /* This is our per-call data structure, which is attached to both the
578 * forward and reverse circuits.
580 typedef struct iax_call_data {
581 /* For this data, src and dst are relative to the original direction under
582 which this call is stored. Obviously if the reversed flag is set true by
583 iax_find_call, src and dst are reversed relative to the direction the
584 actual source and destination of the data.
586 if the codec changes mid-call, we update it here; because we store a codec
587 number with each packet too, we handle going back to earlier packets
591 iax_dataformat_t dataformat;
592 guint32 src_codec, dst_codec;
593 guint32 src_vformat, dst_vformat;
595 /* when a transfer takes place, we'll get a new circuit id; we assume that we
596 don't try to transfer more than IAX_MAX_TRANSFERS times in a call */
597 guint forward_circuit_ids[IAX_MAX_TRANSFERS];
598 guint reverse_circuit_ids[IAX_MAX_TRANSFERS];
599 guint n_forward_circuit_ids;
600 guint n_reverse_circuit_ids;
602 /* this is the subdissector for the call */
603 dissector_handle_t subdissector;
605 /* the absolute start time of the call */
608 GHashTable *fid_table;
609 GHashTable *fragment_table;
610 iax_call_dirdata dirdata[2];
613 static void iax_init_hash( void )
615 if (iax_circuit_hashtab)
616 g_hash_table_destroy(iax_circuit_hashtab);
618 iax_circuit_hashtab = g_hash_table_new(iax_circuit_hash, iax_circuit_equal);
625 /* creates a new CT_IAX2 circuit with a specified circuit id for a call
627 * typically a call has up to three associated circuits: an original source, an
628 * original destination, and the result of a transfer.
630 * For each endpoint, a CT_IAX2 circuit is created and added to the call_data
633 * 'reversed' should be true if this end is the one which would have _received_
634 * the NEW packet, or it is an endpoint to which the 'destination' is being
638 static circuit_t *iax2_new_circuit_for_call(guint circuit_id, guint framenum, iax_call_data *iax_call,
643 if(( reversed && iax_call->n_reverse_circuit_ids >= IAX_MAX_TRANSFERS) ||
644 ( !reversed && iax_call->n_forward_circuit_ids >= IAX_MAX_TRANSFERS)) {
645 g_warning("Too many transfers for iax_call");
649 res = circuit_new(CT_IAX2,
653 circuit_add_proto_data(res, proto_iax2, iax_call);
656 iax_call -> reverse_circuit_ids[iax_call->n_reverse_circuit_ids++] = circuit_id;
658 iax_call -> forward_circuit_ids[iax_call->n_forward_circuit_ids++] = circuit_id;
664 /* returns true if this circuit id is a "forward" circuit for this call: ie, it
665 * is the point which _sent_ the original 'NEW' packet, or a point to which that
666 * end was subsequently transferred */
667 static gboolean is_forward_circuit(guint circuit_id,
668 const iax_call_data *iax_call)
671 for(i=0;i<iax_call->n_forward_circuit_ids;i++){
672 if(circuit_id == iax_call->forward_circuit_ids[i])
678 /* returns true if this circuit id is a "reverse" circuit for this call: ie, it
679 * is the point which _received_ the original 'NEW' packet, or a point to which that
680 * end was subsequently transferred */
681 static gboolean is_reverse_circuit(guint circuit_id,
682 const iax_call_data *iax_call)
685 for(i=0;i<iax_call->n_reverse_circuit_ids;i++){
686 if(circuit_id == iax_call->reverse_circuit_ids[i])
693 static iax_call_data *iax_lookup_call_from_dest( guint src_circuit_id,
694 guint dst_circuit_id,
696 gboolean *reversed_p)
698 circuit_t *dst_circuit;
699 iax_call_data * iax_call;
700 gboolean reversed = FALSE;
702 dst_circuit = find_circuit( CT_IAX2,
708 g_debug( "++ destination circuit not found, must have missed NEW packet" );
716 g_debug( "++ found destination circuit" );
719 iax_call = (iax_call_data *)circuit_get_proto_data(dst_circuit,proto_iax2);
721 /* there's no way we can create a CT_IAX2 circuit without adding
722 iax call data to it; assert this */
723 DISSECTOR_ASSERT(iax_call);
725 if( is_forward_circuit(dst_circuit_id, iax_call )) {
727 g_debug( "++ destination circuit matches forward_circuit_id of call, "
728 "therefore packet is reversed" );
733 if( iax_call -> n_reverse_circuit_ids == 0 ) {
734 /* we are going in the reverse direction, and this call
735 doesn't have a reverse circuit associated with it.
738 g_debug( "++ reverse_circuit_id of call is zero, need to create a "
739 "new reverse circuit for this call" );
742 iax2_new_circuit_for_call( src_circuit_id, framenum, iax_call, TRUE );
744 g_debug( "++ done" );
746 } else if( !is_reverse_circuit(src_circuit_id, iax_call )) {
747 g_warning( "IAX Packet %u from circuit ids %u->%u "
748 "conflicts with earlier call with circuit ids %u->%u",
750 src_circuit_id,dst_circuit_id,
751 iax_call->forward_circuit_ids[0],
752 iax_call->reverse_circuit_ids[0]);
755 } else if ( is_reverse_circuit(dst_circuit_id, iax_call)) {
757 g_debug( "++ destination circuit matches reverse_circuit_id of call, "
758 "therefore packet is forward" );
762 if( !is_forward_circuit(src_circuit_id, iax_call)) {
763 g_warning( "IAX Packet %u from circuit ids %u->%u "
764 "conflicts with earlier call with circuit ids %u->%u",
766 src_circuit_id,dst_circuit_id,
767 iax_call->forward_circuit_ids[0],
768 iax_call->reverse_circuit_ids[0]);
774 DISSECTOR_ASSERT_NOT_REACHED();
778 *reversed_p = reversed;
784 /* looks up an iax_call for this packet */
785 static iax_call_data *iax_lookup_call( packet_info *pinfo,
788 gboolean *reversed_p)
790 gboolean reversed = FALSE;
791 iax_call_data *iax_call = NULL;
792 guint src_circuit_id;
795 g_debug( "++ iax_lookup_circuit_details: Looking up circuit for frame %u, "
796 "from {%s:%u:%u} to {%s:%u:%u}", pinfo->fd->num,
797 address_to_str(&pinfo->src),pinfo->srcport,scallno,
798 address_to_str(&pinfo->dst),pinfo->destport,dcallno);
802 src_circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
803 pinfo->srcport,scallno);
806 /* the most reliable indicator of call is the destination callno, if
809 guint dst_circuit_id;
811 g_debug( "++ dcallno non-zero, looking up destination circuit" );
814 dst_circuit_id = iax_circuit_lookup(&pinfo->dst,pinfo->ptype,
815 pinfo->destport,dcallno);
817 iax_call = iax_lookup_call_from_dest(src_circuit_id, dst_circuit_id,
818 pinfo->fd->num, &reversed);
820 circuit_t *src_circuit;
822 /* in all other circumstances, the source circuit should already
823 * exist: its absense indicates that we missed the all-important NEW
827 src_circuit = find_circuit( CT_IAX2,
832 iax_call = (iax_call_data *)circuit_get_proto_data(src_circuit,proto_iax2);
834 /* there's no way we can create a CT_IAX2 circuit without adding
835 iax call data to it; assert this */
836 DISSECTOR_ASSERT(iax_call);
838 if( is_forward_circuit(src_circuit_id,iax_call))
840 else if(is_reverse_circuit(src_circuit_id,iax_call))
843 /* there's also no way we can attach an iax_call_data to a circuit
844 without the circuit being either the forward or reverse circuit
845 for that call; assert this too.
847 DISSECTOR_ASSERT_NOT_REACHED();
853 *reversed_p = reversed;
857 g_debug( "++ Found call for packet: id %u, reversed=%c", iax_call->forward_circuit_ids[0], reversed?'1':'0' );
859 g_debug( "++ Call not found. Must have missed the NEW packet?" );
866 /* initialise the per-direction parts of an iax_call_data structure */
867 static void init_dir_data(iax_call_dirdata *dirdata)
869 dirdata -> current_frag_bytes=0;
870 dirdata -> current_frag_minlen=0;
874 /* handles a NEW packet by creating a new iax call and forward circuit.
875 the reverse circuit is not created until the ACK is received and
876 is created by iax_lookup_circuit_details. */
877 static iax_call_data *iax_new_call( packet_info *pinfo,
882 static const nstime_t millisecond = {0, 1000000};
885 g_debug( "+ new_circuit: Handling NEW packet, frame %u", pinfo->fd->num );
888 circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
889 pinfo->srcport,scallno);
891 call = se_alloc(sizeof(iax_call_data));
892 call -> dataformat = 0;
893 call -> src_codec = 0;
894 call -> dst_codec = 0;
895 call -> n_forward_circuit_ids = 0;
896 call -> n_reverse_circuit_ids = 0;
897 call -> subdissector = NULL;
898 call -> start_time = pinfo->fd->abs_ts;
899 nstime_delta(&call -> start_time, &call -> start_time, &millisecond);
900 call -> fid_table = g_hash_table_new(g_direct_hash, g_direct_equal);
901 init_dir_data(&call->dirdata[0]);
902 init_dir_data(&call->dirdata[1]);
903 call->fragment_table = NULL;
904 fragment_table_init(&(call->fragment_table));
906 iax2_new_circuit_for_call(circuit_id,pinfo->fd->num,call,FALSE);
912 /* ************************************************************************* */
914 /* per-packet data */
915 typedef struct iax_packet_data {
916 gboolean first_time; /* we're dissecting this packet for the first time; so
917 things like codec and transfer requests should be
918 propogated into the call data */
919 iax_call_data *call_data;
922 nstime_t abstime; /* the absolute time of this packet, based on its
923 * timestamp and the NEW packet's time (-1 if unknown) */
926 static iax_packet_data *iax_new_packet_data(iax_call_data *call, gboolean reversed)
928 iax_packet_data *p = se_alloc(sizeof(iax_packet_data));
932 p->reversed=reversed;
938 static void iax2_populate_pinfo_from_packet_data(packet_info *pinfo, const iax_packet_data * p)
940 /* info for subdissectors. We always pass on the original forward circuit,
941 * and steal the p2p_dir flag to indicate the direction */
942 if( p->call_data == NULL ) {
943 /* if we missed the NEW packet for this call, call_data will be null. it's
944 * tbd what the best thing to do here is. */
945 pinfo -> ctype = CT_NONE;
947 pinfo -> ctype = CT_IAX2;
948 pinfo -> circuit_id = (guint32)p->call_data->forward_circuit_ids[0];
949 pinfo -> p2p_dir = p->reversed?P2P_DIR_RECV:P2P_DIR_SENT;
951 if (check_col (pinfo->cinfo, COL_CIRCUIT_ID)) {
952 col_set_str (pinfo->cinfo, COL_CIRCUIT_ID, "" );
953 col_add_fstr(pinfo->cinfo, COL_CIRCUIT_ID, "%u", pinfo->circuit_id);
955 if (check_col (pinfo->cinfo, COL_IF_DIR))
956 col_set_str (pinfo->cinfo, COL_IF_DIR, p->reversed ? "rev" : "fwd" );
961 /* ************************************************************************* */
963 /* this is passed up from the IE dissector to the main dissector */
966 address peer_address;
967 port_type peer_ptype;
974 static guint32 dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
977 proto_tree * iax2_tree,
978 proto_tree * main_tree);
981 static guint32 dissect_minipacket (tvbuff_t * tvb, guint32 offset,
984 proto_tree * iax2_tree,
985 proto_tree * main_tree);
987 static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
990 proto_tree * iax2_tree,
991 proto_tree * main_tree);
993 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
994 packet_info *pinfo, proto_tree *iax2_tree,
995 proto_tree *tree, guint32 ts, gboolean video,
996 iax_packet_data *iax_packet);
1001 dissect_iax2 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1003 proto_item *iax2_item = NULL;
1004 proto_tree *iax2_tree = NULL;
1005 proto_tree *full_mini_subtree = NULL;
1006 guint32 offset = 0, len;
1007 guint16 scallno = 0;
1011 /* set up the protocol and info fields in the summary pane */
1012 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1014 col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2);
1016 col_clear(pinfo->cinfo, COL_INFO);
1018 /* add the 'iax2' tree to the main tree */
1021 iax2_item = proto_tree_add_item (tree, proto_iax2, tvb, offset, -1, FALSE);
1022 iax2_tree = proto_item_add_subtree (iax2_item, ett_iax2);
1025 stmp = tvb_get_ntohs(tvb, offset);
1027 /* starting with 0x0000 indicates either a mini video packet or a 'meta'
1028 * packet, whatever that means */
1030 stmp = tvb_get_ntohs(tvb, offset);
1031 if( stmp & 0x8000 ) {
1032 /* mini video packet */
1033 type = IAX2_MINI_VIDEO_PACKET;
1034 scallno = stmp & 0x7FFF;
1038 type = IAX2_META_PACKET;
1041 /* The source call/fullpacket flag is common to both mini and full packets */
1042 scallno = tvb_get_ntohs(tvb, offset);
1044 if( scallno & 0x8000 )
1045 type = IAX2_FULL_PACKET;
1047 type = IAX2_MINI_VOICE_PACKET;
1053 proto_item *full_mini_base;
1055 full_mini_base = proto_tree_add_uint(iax2_tree, hf_iax2_packet_type, tvb, 0, offset, type);
1056 full_mini_subtree = proto_item_add_subtree(full_mini_base, ett_iax2_full_mini_subtree);
1059 proto_tree_add_item (full_mini_subtree, hf_iax2_scallno, tvb, offset-2, 2, FALSE);
1062 iax2_info->ptype = type;
1063 iax2_info->scallno = 0;
1064 iax2_info->dcallno = 0;
1065 iax2_info->ftype = 0;
1066 iax2_info->csub = 0;
1067 iax2_info->payload_len = 0;
1068 iax2_info->timestamp = 0;
1069 iax2_info->callState = VOIP_NO_STATE;
1070 iax2_info->messageName = NULL;
1071 iax2_info->callingParty = NULL;
1072 iax2_info->calledParty = NULL;
1073 iax2_info->payload_data = NULL;
1076 case IAX2_FULL_PACKET:
1077 len = dissect_fullpacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1079 case IAX2_MINI_VOICE_PACKET:
1080 iax2_info->messageName = "MINI_VOICE_PACKET";
1081 len = dissect_minipacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1083 case IAX2_MINI_VIDEO_PACKET:
1084 iax2_info->messageName = "MINI_VIDEO_PACKET";
1085 len = dissect_minivideopacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1087 case IAX2_META_PACKET:
1088 /* not implemented yet */
1089 iax2_info->messageName = "META_PACKET";
1096 /* update the 'length' of the main IAX2 header field so that it covers just the headers,
1097 not the audio data. */
1098 proto_item_set_len(iax2_item, len);
1099 tap_queue_packet(iax2_tap, pinfo, iax2_info);
1102 static proto_item *dissect_datetime_ie(tvbuff_t *tvb, guint32 offset, proto_tree *ies_tree)
1108 proto_tree_add_item (ies_tree, hf_iax2_ies[IAX_IE_DATETIME], tvb, offset + 2, 4, FALSE);
1109 ie_val = tvb_get_ntohl(tvb, offset+2);
1111 /* who's crazy idea for a time encoding was this? */
1112 tm.tm_sec = (ie_val & 0x1f) << 1;
1113 tm.tm_min = (ie_val>>5) & 0x3f;
1114 tm.tm_hour = (ie_val>>11) & 0x1f;
1115 tm.tm_mday = (ie_val>>16) & 0x1f;
1116 tm.tm_mon = ((ie_val>>21) & 0xf) - 1;
1117 tm.tm_year = ((ie_val>>25) & 0x7f) + 100;
1118 tm.tm_isdst= -1; /* there's no info on whether DST was in force; assume it's
1119 * the same as currently */
1121 datetime.secs = mktime(&tm);
1123 return proto_tree_add_time (ies_tree, hf_iax2_ie_datetime, tvb, offset+2, 4, &datetime);
1127 /* dissect the information elements in an IAX frame. Returns the updated offset */
1128 static guint32 dissect_ies (tvbuff_t * tvb, guint32 offset,
1129 proto_tree * iax_tree,
1130 iax2_ie_data *ie_data)
1132 DISSECTOR_ASSERT(ie_data);
1134 while (offset < tvb_reported_length (tvb)) {
1136 int ies_type = tvb_get_guint8(tvb, offset);
1137 int ies_len = tvb_get_guint8(tvb, offset + 1);
1138 guint16 apparent_addr_family;
1140 /* do non-tree-dependent stuff first */
1142 case IAX_IE_DATAFORMAT:
1143 if (ies_len != 4) THROW(ReportedBoundsError);
1144 ie_data -> dataformat = tvb_get_ntohl(tvb, offset+2);
1147 case IAX_IE_CALLED_NUMBER:
1148 iax2_info->calledParty = g_strdup(tvb_format_text(tvb, offset+2, ies_len));
1150 case IAX_IE_CALLING_NUMBER:
1151 iax2_info->callingParty = g_strdup(tvb_format_text(tvb, offset+2, ies_len));
1154 case IAX_IE_APPARENT_ADDR:
1155 /* The IAX2 I-D says that the "apparent address" structure
1156 "is the same as the linux struct sockaddr_in", without
1157 bothering to note that the address family field is in
1158 *host* byte order in that structure (the I-D seems to be
1159 assuming that "everything is a Vax^Wx86 or x86-64" with
1160 the address family field being little-endian).
1162 This means the address family values are the Linux
1163 address family values. */
1164 apparent_addr_family = tvb_get_letohs(tvb, offset+2);
1165 switch( apparent_addr_family ) {
1167 /* IAX is always over UDP */
1168 ie_data->peer_ptype = PT_UDP;
1169 ie_data->peer_port = tvb_get_ntohs(tvb, offset+4);
1171 /* the ip address is big-endian, but then so is peer_address.data */
1172 SET_ADDRESS(&ie_data->peer_address,AT_IPv4,4,tvb_get_ptr(tvb,offset+6,4));
1176 g_warning("Not supported in IAX dissector: peer address family of %u", apparent_addr_family);
1183 /* the rest of this stuff only needs doing if we have an iax_tree */
1186 proto_item *ti, *ie_item = NULL;
1187 proto_tree *ies_tree;
1188 int ie_hf = hf_iax2_ies[ies_type];
1190 ti = proto_tree_add_text(iax_tree, tvb, offset, ies_len+2, " " );
1192 ies_tree = proto_item_add_subtree(ti, ett_iax2_ie);
1194 proto_tree_add_text(ies_tree, tvb, offset, 1, "IE id: %s (0x%02X)",
1195 val_to_str(ies_type, iax_ies_type, "Unknown"),
1198 proto_tree_add_text(ies_tree, tvb, offset+1, 1, "Length: %u",ies_len);
1201 /* hf_iax2_ies[] is an array, indexed by IE number, of header-fields, one
1202 per IE. Apart from a couple of special cases which require more
1203 complex decoding, we can just look up an entry from the array, and add
1208 case IAX_IE_DATETIME:
1209 ie_item = dissect_datetime_ie(tvb,offset,ies_tree);
1213 case IAX_IE_CAPABILITY:
1215 proto_tree *codec_tree;
1217 if (ies_len != 4) THROW(ReportedBoundsError);
1220 proto_tree_add_item (ies_tree, ie_hf,
1221 tvb, offset + 2, ies_len, FALSE);
1223 proto_item_add_subtree (ie_item, ett_iax2_codecs);
1225 proto_tree_add_item(codec_tree, hf_iax2_cap_g723_1, tvb, offset + 2, ies_len, FALSE );
1226 proto_tree_add_item(codec_tree, hf_iax2_cap_gsm, tvb, offset + 2, ies_len, FALSE );
1227 proto_tree_add_item(codec_tree, hf_iax2_cap_ulaw, tvb, offset + 2, ies_len, FALSE );
1228 proto_tree_add_item(codec_tree, hf_iax2_cap_alaw, tvb, offset + 2, ies_len, FALSE );
1229 proto_tree_add_item(codec_tree, hf_iax2_cap_g726, tvb, offset + 2, ies_len, FALSE );
1230 proto_tree_add_item(codec_tree, hf_iax2_cap_adpcm, tvb, offset + 2, ies_len, FALSE );
1231 proto_tree_add_item(codec_tree, hf_iax2_cap_slinear, tvb, offset + 2, ies_len, FALSE );
1232 proto_tree_add_item(codec_tree, hf_iax2_cap_lpc10, tvb, offset + 2, ies_len, FALSE );
1233 proto_tree_add_item(codec_tree, hf_iax2_cap_g729a, tvb, offset + 2, ies_len, FALSE );
1234 proto_tree_add_item(codec_tree, hf_iax2_cap_speex, tvb, offset + 2, ies_len, FALSE );
1235 proto_tree_add_item(codec_tree, hf_iax2_cap_ilbc, tvb, offset + 2, ies_len, FALSE );
1236 proto_tree_add_item(codec_tree, hf_iax2_cap_jpeg, tvb, offset + 2, ies_len, FALSE );
1237 proto_tree_add_item(codec_tree, hf_iax2_cap_png, tvb, offset + 2, ies_len, FALSE );
1238 proto_tree_add_item(codec_tree, hf_iax2_cap_h261, tvb, offset + 2, ies_len, FALSE );
1239 proto_tree_add_item(codec_tree, hf_iax2_cap_h263, tvb, offset + 2, ies_len, FALSE );
1243 case IAX_IE_APPARENT_ADDR:
1245 proto_tree *sockaddr_tree = NULL;
1247 ie_item = proto_tree_add_text(ies_tree, tvb, offset + 2, 16, "Apparent Address");
1248 sockaddr_tree = proto_item_add_subtree(ie_item, ett_iax2_ies_apparent_addr);
1250 /* The IAX2 I-D says that the "apparent address" structure
1251 "is the same as the linux struct sockaddr_in", without
1252 bothering to note that the address family field is in
1253 *host* byte order in that structure (the I-D seems to be
1254 assuming that "everything is a Vax^Wx86 or x86-64" with
1255 the address family field being little-endian).
1257 This means the address family values are the Linux
1258 address family values. */
1259 apparent_addr_family = tvb_get_letohs(tvb, offset+2);
1260 proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINFAMILY, tvb, offset + 2, 2, apparent_addr_family);
1262 switch( apparent_addr_family ) {
1266 proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINPORT, tvb, offset + 4, 2, ie_data->peer_port);
1267 memcpy(&addr, ie_data->peer_address.data, 4);
1268 proto_tree_add_ipv4(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINADDR, tvb, offset + 6, 4, addr);
1277 /* throw an error if the IE isn't the expected length */
1278 gint explen = ftype_length(proto_registrar_get_nth(ie_hf)->type);
1279 if(explen != 0 && ies_len != explen)
1280 THROW(ReportedBoundsError);
1281 ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, FALSE);
1283 /* we don't understand this ie: add a generic one */
1286 const gchar *ie_name = val_to_str(ies_type, iax_ies_type, "Unknown");
1290 value = tvb_get_guint8(tvb, offset + 2);
1292 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTE,
1293 tvb, offset+2, 1, value,
1294 "%s: %#02x", ie_name, value );
1298 value = tvb_get_ntohs(tvb, offset + 2);
1300 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I16,
1301 tvb, offset+2, 2, value,
1302 "%s: %#04x", ie_name, value );
1306 value = tvb_get_ntohl(tvb, offset + 2);
1308 proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I32,
1309 tvb, offset+2, 4, value,
1310 "%s: %#08x", ie_name, value );
1314 ptr = tvb_get_ptr(tvb, offset + 2, ies_len);
1316 proto_tree_add_string_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTES,
1317 tvb, offset+2, ies_len, ptr,
1318 "%s: %s", ie_name, ptr );
1325 /* by now, we *really* ought to have added an item */
1326 DISSECTOR_ASSERT(ie_item != NULL);
1328 /* Retrieve the text from the item we added, and append it to the main IE
1330 if(!PROTO_ITEM_IS_HIDDEN(ti)) {
1331 field_info *ie_finfo = PITEM_FINFO(ie_item);
1333 /* if the representation of the item has already been set, use that;
1334 else we have to allocate a block to put the text into */
1335 if( ie_finfo -> rep != NULL )
1336 proto_item_set_text(ti, "Information Element: %s",
1337 ie_finfo->rep->representation);
1339 guint8 *ie_val = NULL;
1340 ie_val = g_malloc(ITEM_LABEL_LENGTH);
1341 proto_item_fill_label(ie_finfo, ie_val);
1342 proto_item_set_text(ti, "Information Element: %s",
1349 offset += ies_len + 2;
1354 static guint32 uncompress_subclass(guint8 csub)
1356 /* If the SC_LOG flag is set, return 2^csub otherwise csub */
1358 /* special case for 'compressed' -1 */
1362 return 1 << (csub & 0x1F);
1365 return (guint32)csub;
1368 /* returns the new offset */
1369 static guint32 dissect_iax2_command(tvbuff_t * tvb, guint32 offset,
1370 packet_info * pinfo, proto_tree *tree,
1371 iax_packet_data *iax_packet)
1373 guint8 csub = tvb_get_guint8(tvb, offset);
1374 guint8 address_data[MAX_ADDRESS];
1375 iax2_ie_data ie_data;
1376 iax_call_data *iax_call;
1378 ie_data.peer_address.type = AT_NONE;
1379 ie_data.peer_address.len = 0;
1380 ie_data.peer_address.data = address_data;
1381 ie_data.peer_ptype = 0;
1382 ie_data.peer_port = 0;
1383 ie_data.peer_callno = 0;
1384 ie_data.dataformat = (guint32)-1;
1385 iax_call = iax_packet -> call_data;
1387 /* add the subclass */
1388 proto_tree_add_uint (tree, hf_iax2_iax_csub, tvb, offset, 1, csub);
1391 if (check_col (pinfo->cinfo, COL_INFO))
1392 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1393 val_to_str (csub, iax_iax_subclasses, "unknown (0x%02x)"));
1395 if (offset >= tvb_reported_length (tvb))
1398 offset += dissect_ies(tvb, offset, tree, &ie_data);
1400 /* if this is a data call, set up a subdissector for the circuit */
1401 if(iax_call && ie_data.dataformat != (guint32)-1 && iax_call -> subdissector == NULL) {
1402 iax_call -> subdissector = dissector_get_port_handle(iax2_dataformat_dissector_table, ie_data.dataformat );
1403 iax_call -> dataformat = ie_data.dataformat;
1406 /* if this is a transfer request, record it in the call data */
1407 if( csub == IAX_COMMAND_TXREQ && iax_packet -> first_time ) {
1408 if( ie_data.peer_address.type != AT_NONE && ie_data.peer_callno != 0 ) {
1409 guint tx_circuit = iax_circuit_lookup(&ie_data.peer_address,
1412 ie_data.peer_callno);
1415 g_debug("found transfer request for call %u->%u, to new id %u",
1416 iax_call->forward_circuit_ids[0],
1417 iax_call->reverse_circuit_ids[0],
1421 iax2_new_circuit_for_call(tx_circuit,pinfo->fd->num,iax_call,iax_packet->reversed);
1428 static void iax2_add_ts_fields(packet_info * pinfo, proto_tree * iax2_tree, iax_packet_data *iax_packet, guint16 shortts)
1430 guint32 longts = shortts;
1434 if(iax_packet->call_data == NULL) {
1435 /* no call info for this frame; perhaps we missed the NEW packet */
1439 if(iax_packet->abstime.secs == -1) {
1440 time_t start_secs = iax_packet->call_data->start_time.secs;
1441 gint32 abs_secs = (gint32) (start_secs + longts/1000);
1443 /* deal with short timestamps by assuming that packets are never more than
1444 * 16 seconds late */
1445 while(abs_secs < pinfo->fd->abs_ts.secs - 16) {
1447 abs_secs = (gint32) (start_secs + longts/1000);
1450 iax_packet->abstime.secs=abs_secs;
1451 iax_packet->abstime.nsecs=iax_packet->call_data->start_time.nsecs + (longts % 1000) * 1000000;
1452 if(iax_packet->abstime.nsecs >= 1000000000) {
1453 iax_packet->abstime.nsecs -= 1000000000;
1454 iax_packet->abstime.secs ++;
1457 iax2_info->timestamp = longts;
1460 item = proto_tree_add_time(iax2_tree, hf_iax2_absts, NULL, 0, 0, &iax_packet->abstime);
1461 PROTO_ITEM_SET_GENERATED(item);
1463 ts = pinfo->fd->abs_ts;
1464 nstime_delta(&ts, &ts, &iax_packet->abstime);
1466 item = proto_tree_add_time(iax2_tree, hf_iax2_lateness, NULL, 0, 0, &ts);
1467 PROTO_ITEM_SET_GENERATED(item);
1471 /* returns the new offset */
1473 dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
1475 packet_info * pinfo, proto_tree * iax2_tree,
1476 proto_tree * main_tree)
1478 guint32 retransmission = 0;
1485 proto_tree *packet_type_tree = NULL;
1486 iax_call_data *iax_call;
1487 iax_packet_data *iax_packet;
1489 gboolean rtp_marker;
1492 * remove the top bit for retransmission detection
1494 dcallno = tvb_get_ntohs(tvb, offset);
1495 retransmission = dcallno & 0x8000;
1496 dcallno = dcallno & 0x7FFF;
1497 ts = tvb_get_ntohl(tvb, offset+2);
1498 type = tvb_get_guint8(tvb, offset + 8);
1499 csub = tvb_get_guint8(tvb, offset + 9);
1500 iax2_info->ftype = type;
1501 iax2_info->csub = csub;
1502 iax2_info->scallno = scallno;
1503 iax2_info->dcallno = dcallno;
1505 /* see if we've seen this packet before */
1506 iax_packet = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
1508 /* if not, find or create an iax_call info structure for this IAX session. */
1510 if( type == AST_FRAME_IAX && csub == IAX_COMMAND_NEW ) {
1511 /* NEW packets start a new call */
1512 iax_call = iax_new_call(pinfo,scallno);
1515 iax_call = iax_lookup_call(pinfo, scallno, dcallno,
1519 iax_packet = iax_new_packet_data(iax_call, reversed);
1520 p_add_proto_data(pinfo->fd,proto_iax2,iax_packet);
1522 iax_call = iax_packet->call_data;
1523 reversed = iax_packet->reversed;
1526 iax2_populate_pinfo_from_packet_data(pinfo, iax_packet);
1529 proto_item *packet_type_base;
1531 proto_tree_add_item (iax2_tree, hf_iax2_dcallno, tvb, offset, 2, FALSE );
1533 proto_tree_add_item(iax2_tree, hf_iax2_retransmission, tvb, offset, 2, FALSE );
1537 proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1538 iax_call->forward_circuit_ids[0] );
1539 PROTO_ITEM_SET_GENERATED(item);
1542 proto_tree_add_uint (iax2_tree, hf_iax2_ts, tvb, offset+2, 4, ts);
1543 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1545 proto_tree_add_item (iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1,
1548 proto_tree_add_item (iax2_tree, hf_iax2_iseqno, tvb, offset+7, 1,
1550 packet_type_base = proto_tree_add_uint (iax2_tree, hf_iax2_type, tvb,
1553 /* add the type-specific subtree */
1554 packet_type_tree = proto_item_add_subtree (packet_type_base, ett_iax2_type);
1556 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1560 /* add frame type to info line */
1561 if (check_col (pinfo->cinfo, COL_INFO)) {
1562 col_add_fstr (pinfo->cinfo, COL_INFO, "%s, source call# %d, timestamp %ums",
1563 val_to_str (type, iax_frame_types, "Unknown (0x%02x)"),
1566 iax2_info->messageName = val_to_str (type, iax_frame_types, "Unknown (0x%02x)");
1570 offset=dissect_iax2_command(tvb,offset+9,pinfo,packet_type_tree,iax_packet);
1571 iax2_info->messageName = val_to_str (csub, iax_iax_subclasses, "unknown (0x%02x)");
1572 iax2_info->callState = csub;
1575 case AST_FRAME_DTMF_BEGIN:
1576 case AST_FRAME_DTMF_END:
1577 proto_tree_add_item (packet_type_tree, hf_iax2_dtmf_csub, tvb, offset+9, 1, FALSE);
1580 if (check_col (pinfo->cinfo, COL_INFO))
1581 col_append_fstr (pinfo->cinfo, COL_INFO, " digit %c", csub );
1584 case AST_FRAME_CONTROL:
1585 /* add the subclass */
1586 proto_tree_add_uint (packet_type_tree, hf_iax2_cmd_csub, tvb,
1590 if (check_col (pinfo->cinfo, COL_INFO))
1591 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1592 val_to_str (csub, iax_cmd_subclasses, "unknown (0x%02x)"));
1593 iax2_info->messageName = val_to_str (csub, iax_cmd_subclasses, "unknown (0x%02x)");
1594 if (csub <= 8) iax2_info->callState = tap_cmd_voip_state[csub];
1597 case AST_FRAME_VOICE:
1599 iax_packet -> codec = codec = uncompress_subclass(csub);
1601 if( packet_type_tree ) {
1603 proto_tree_add_item (packet_type_tree, hf_iax2_voice_csub, tvb, offset+9, 1, FALSE);
1604 item = proto_tree_add_uint (packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, codec);
1605 PROTO_ITEM_SET_GENERATED(item);
1612 iax_call->dst_codec = codec;
1614 iax_call->src_codec = codec;
1618 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, FALSE,iax_packet);
1621 case AST_FRAME_VIDEO:
1622 /* bit 6 of the csub is used to represent the rtp 'marker' bit */
1623 rtp_marker = csub & 0x40 ? TRUE:FALSE;
1624 iax_packet -> codec = codec = uncompress_subclass((guint8) (csub & ~40));
1626 if( packet_type_tree ) {
1628 proto_tree_add_item (packet_type_tree, hf_iax2_video_csub, tvb, offset+9, 1, FALSE);
1629 proto_tree_add_item (packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, FALSE);
1630 item = proto_tree_add_uint (packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, codec);
1631 PROTO_ITEM_SET_GENERATED(item);
1636 if( iax_call && iax_packet -> first_time ) {
1638 iax_call->dst_vformat = codec;
1640 iax_call->src_vformat = codec;
1644 if( rtp_marker && check_col (pinfo->cinfo, COL_INFO))
1645 col_append_str (pinfo->cinfo, COL_INFO, ", Mark" );
1648 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, TRUE, iax_packet);
1651 case AST_FRAME_MODEM:
1652 proto_tree_add_item (packet_type_tree, hf_iax2_modem_csub, tvb, offset+9, 1, FALSE);
1655 if (check_col (pinfo->cinfo, COL_INFO))
1656 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1657 val_to_str (csub, iax_modem_subclasses, "unknown (0x%02x)"));
1660 case AST_FRAME_HTML:
1663 proto_tree_add_uint (packet_type_tree, hf_iax2_csub, tvb, offset+9,
1667 if (check_col (pinfo->cinfo, COL_INFO))
1668 col_append_fstr (pinfo->cinfo, COL_INFO, " subclass %d", csub );
1672 /* next time we come to parse this packet, don't propogate the codec into the
1674 iax_packet->first_time = FALSE;
1679 static iax_packet_data *iax2_get_packet_data_for_minipacket(packet_info * pinfo,
1683 /* see if we've seen this packet before */
1684 iax_packet_data *p = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
1687 /* if not, find or create an iax_call info structure for this IAX session. */
1689 iax_call_data *iax_call;
1691 iax_call = iax_lookup_call(pinfo, scallno, 0, &reversed);
1693 p = iax_new_packet_data(iax_call,reversed);
1694 p_add_proto_data(pinfo->fd,proto_iax2,p);
1696 /* set the codec for this frame to be whatever the last full frame used */
1699 p->codec = reversed ? iax_call -> dst_vformat : iax_call -> src_vformat;
1701 p->codec = reversed ? iax_call -> dst_codec : iax_call -> src_codec;
1705 iax2_populate_pinfo_from_packet_data(pinfo, p);
1710 static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
1711 guint16 scallno, packet_info * pinfo,
1712 proto_tree * iax2_tree, proto_tree *main_tree)
1715 iax_packet_data *iax_packet;
1716 gboolean rtp_marker;
1719 ts = tvb_get_ntohs(tvb, offset);
1721 /* bit 15 of the ts is used to represent the rtp 'marker' bit */
1722 rtp_marker = ts & 0x8000 ? TRUE:FALSE;
1725 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, TRUE);
1728 if( iax_packet->call_data ) {
1730 proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1731 iax_packet->call_data->forward_circuit_ids[0] );
1732 PROTO_ITEM_SET_GENERATED(item);
1735 proto_tree_add_item (iax2_tree, hf_iax2_minividts, tvb, offset, 2, FALSE);
1736 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1737 proto_tree_add_item (iax2_tree, hf_iax2_minividmarker, tvb, offset, 2, FALSE);
1739 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1744 if (check_col (pinfo->cinfo, COL_INFO))
1745 col_add_fstr (pinfo->cinfo, COL_INFO,
1746 "Mini video packet, source call# %d, timestamp %ums%s",
1747 scallno, ts, rtp_marker?", Mark":"");
1750 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, TRUE, iax_packet);
1752 /* next time we come to parse this packet, don't propogate the codec into the
1754 iax_packet->first_time = FALSE;
1760 dissect_minipacket (tvbuff_t * tvb, guint32 offset, guint16 scallno, packet_info * pinfo, proto_tree * iax2_tree,
1761 proto_tree *main_tree)
1764 iax_packet_data *iax_packet;
1767 ts = tvb_get_ntohs(tvb, offset);
1769 iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, FALSE);
1772 if( iax_packet->call_data ) {
1773 item = proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1774 iax_packet->call_data->forward_circuit_ids[0] );
1775 PROTO_ITEM_SET_GENERATED(item);
1778 proto_tree_add_uint (iax2_tree, hf_iax2_minits, tvb, offset, 2, ts);
1779 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet,(guint16)ts);
1781 iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1787 if (check_col (pinfo->cinfo, COL_INFO))
1788 col_add_fstr (pinfo->cinfo, COL_INFO,
1789 "Mini packet, source call# %d, timestamp %ums",
1793 /* XXX fix the timestamp logic */
1794 dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, FALSE, iax_packet);
1797 /* next time we come to parse this packet, don't propogate the codec into the
1799 iax_packet->first_time = FALSE;
1804 static void process_iax_pdu( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1805 gboolean video, iax_packet_data *iax_packet )
1807 guint32 codec = iax_packet -> codec;
1808 iax_call_data *iax_call = iax_packet -> call_data;
1810 #ifdef DEBUG_DESEGMENT
1811 g_debug("calling process_iax_pdu; len = %u", tvb_reported_length(tvb));
1814 if( !video && iax_call && iax_call->subdissector ) {
1815 call_dissector(iax_call->subdissector, tvb, pinfo, tree);
1816 }else if( codec != 0 && dissector_try_port(iax2_codec_dissector_table, codec, tvb, pinfo, tree )) {
1817 /* codec dissector handled our data */
1819 /* we don't know how to dissect our data: dissect it as data */
1820 call_dissector(data_handle,tvb, pinfo, tree);
1823 #ifdef DEBUG_DESEGMENT
1824 g_debug("called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u",
1825 pinfo->desegment_len, pinfo->desegment_offset);
1829 static void desegment_iax(tvbuff_t *tvb, packet_info *pinfo, proto_tree *iax2_tree,
1830 proto_tree *tree, gboolean video, iax_packet_data *iax_packet )
1833 iax_call_data *iax_call = iax_packet -> call_data;
1834 iax_call_dirdata *dirdata;
1835 gpointer value=NULL;
1836 guint32 frag_offset=0;
1837 fragment_data *fd_head;
1838 gboolean must_desegment = FALSE;
1840 DISSECTOR_ASSERT(iax_call);
1842 pinfo->can_desegment = 2;
1843 pinfo->desegment_offset = 0;
1844 pinfo->desegment_len = 0;
1846 #ifdef DEBUG_DESEGMENT
1847 g_debug("dissecting packet %u", pinfo->fd->num);
1850 dirdata = &(iax_call->dirdata[!!(iax_packet->reversed)]);
1852 if((!pinfo->fd->flags.visited && dirdata->current_frag_bytes > 0) ||
1853 (value = g_hash_table_lookup(iax_call->fid_table,
1854 GUINT_TO_POINTER(pinfo->fd->num))) != NULL ) {
1855 /* then we are continuing an already-started pdu */
1857 guint32 frag_len = tvb_reported_length( tvb );
1860 #ifdef DEBUG_DESEGMENT
1861 g_debug("visited: %i; c_f_b: %u; hash: %u->%u", pinfo->fd->flags.visited?1:0,
1862 dirdata->current_frag_bytes, pinfo->fd->num, fid);
1865 if(!pinfo->fd->flags.visited) {
1867 fid = dirdata->current_frag_id;
1868 tot_len = dirdata->current_frag_minlen;
1869 g_hash_table_insert( iax_call->fid_table, GUINT_TO_POINTER(pinfo->fd->num), GUINT_TO_POINTER(fid) );
1870 frag_offset = dirdata->current_frag_bytes;
1871 dirdata->current_frag_bytes += frag_len;
1872 complete = dirdata->current_frag_bytes > tot_len;
1873 #ifdef DEBUG_DESEGMENT
1874 g_debug("hash: %u->%u; frag_offset: %u; c_f_b: %u; totlen: %u",
1875 pinfo->fd->num, fid, frag_offset, dirdata->current_frag_bytes, tot_len );
1878 fid = GPOINTER_TO_UINT(value);
1879 /* these values are unused by fragment_add if pinfo->fd->flags.visited */
1880 dirdata->current_frag_bytes = 0;
1884 /* fragment_add checks for already-added */
1885 fd_head = fragment_add( tvb, 0, pinfo, fid,
1886 iax_call->fragment_table,
1888 frag_len, !complete );
1890 if(fd_head && (pinfo->fd->num == fd_head->reassembled_in)) {
1892 tvbuff_t *next_tvb = tvb_new_child_real_data(tvb, fd_head->data, fd_head->datalen, fd_head->datalen);
1893 add_new_data_source(pinfo, next_tvb, "Reassembled IAX2");
1895 process_iax_pdu(next_tvb,pinfo,tree,video,iax_packet);
1897 /* calculate the amount of data which was available to the higher-level
1898 dissector before we added this segment; if the returned offset is
1899 within that section, the higher-level dissector was unable to find any
1900 pdus; if it's after that, it found one or more complete PDUs.
1902 old_len = (gint32)(tvb_reported_length(next_tvb) - frag_len);
1903 if( pinfo->desegment_len &&
1904 pinfo->desegment_offset < old_len ) {
1905 /* oops, it wasn't actually complete */
1906 fragment_set_partial_reassembly(pinfo, fid, iax_call->fragment_table);
1907 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1908 /* only one more byte should be enough for a retry */
1909 dirdata->current_frag_minlen = fd_head->datalen + 1;
1911 dirdata->current_frag_minlen = fd_head->datalen + pinfo->desegment_len;
1914 /* we successfully dissected some data; create the proto tree items for
1915 * the fragments, and flag any remaining data for desegmentation */
1917 proto_item *iax_tree_item, *frag_tree_item;
1918 /* this nargery is to insert the fragment tree into the main tree
1919 * between the IAX protocol entry and the subdissector entry */
1920 show_fragment_tree(fd_head, &iax2_fragment_items, tree, pinfo, next_tvb, &frag_tree_item);
1921 iax_tree_item = proto_item_get_parent( proto_tree_get_parent( iax2_tree ));
1922 if( frag_tree_item && iax_tree_item )
1923 proto_tree_move_item( tree, iax_tree_item, frag_tree_item );
1925 dirdata->current_frag_minlen = dirdata->current_frag_id = dirdata->current_frag_bytes = 0;
1927 if( pinfo->desegment_len ) {
1928 /* there's a bit of data left to desegment */
1929 must_desegment = TRUE;
1930 /* make desegment_offset relative to our tvb */
1931 pinfo->desegment_offset -= old_len;
1934 /* don't add a 'reassembled in' item for this pdu */
1939 /* This segment was not found in our table, so it doesn't
1940 contain a continuation of a higher-level PDU.
1941 Call the normal subdissector.
1944 process_iax_pdu(tvb,pinfo,tree,video,iax_packet);
1946 if(pinfo->desegment_len) {
1947 /* the higher-level dissector has asked for some more data - ie,
1948 the end of this segment does not coincide with the end of a
1949 higher-level PDU. */
1950 must_desegment = TRUE;
1956 /* must_desegment is set if the end of this segment (or the whole of it)
1957 * contained the start of a higher-level PDU; we must add whatever is left of
1958 * this segment (after pinfo->desegment_offset) to a fragment table for disassembly. */
1959 if(must_desegment) {
1960 guint32 fid = pinfo->fd->num; /* a new fragment id */
1961 guint32 deseg_offset = pinfo->desegment_offset;
1962 guint32 frag_len = tvb_reported_length_remaining(tvb,deseg_offset);
1963 dirdata->current_frag_id = fid;
1964 dirdata->current_frag_bytes = frag_len;
1966 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1967 /* only one more byte should be enough for a retry */
1968 dirdata->current_frag_minlen = frag_len + 1;
1970 dirdata->current_frag_minlen = frag_len + pinfo->desegment_len;
1973 fd_head = fragment_add(tvb, deseg_offset, pinfo, fid,
1974 iax_call->fragment_table,
1975 0, frag_len, TRUE );
1976 #ifdef DEBUG_DESEGMENT
1977 g_debug("Start offset of undissected bytes: %u; "
1978 "Bytes remaining in this segment: %u; min required bytes: %u\n",
1979 deseg_offset, frag_len, frag_len + pinfo->desegment_len);
1983 /* add a 'reassembled in' item if necessary */
1984 if( fd_head != NULL ) {
1985 guint32 deseg_offset = pinfo->desegment_offset;
1986 if( fd_head->reassembled_in != 0 &&
1987 !(fd_head->flags & FD_PARTIAL_REASSEMBLY) ) {
1988 proto_item *iax_tree_item;
1989 iax_tree_item = proto_tree_add_uint( tree, hf_iax2_reassembled_in,
1990 tvb, deseg_offset, tvb_reported_length_remaining(tvb,deseg_offset),
1991 fd_head->reassembled_in);
1992 PROTO_ITEM_SET_GENERATED(iax_tree_item);
1994 /* this fragment is never reassembled */
1995 proto_tree_add_text( tree, tvb, deseg_offset, -1,
1996 "IAX2 fragment, unfinished");
1999 if( pinfo->desegment_offset == 0 ) {
2000 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAX2");
2001 col_set_str(pinfo->cinfo, COL_INFO, "[IAX2 segment of a reassembled PDU]");
2005 pinfo->can_desegment = 0;
2006 pinfo->desegment_offset = 0;
2007 pinfo->desegment_len = 0;
2010 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
2011 packet_info *pinfo, proto_tree *iax2_tree,
2012 proto_tree *tree, guint32 ts, gboolean video,
2013 iax_packet_data *iax_packet)
2016 gboolean out_of_order = FALSE;
2019 guint32 codec = iax_packet -> codec;
2021 iax_call_data *iax_call = iax_packet -> call_data;
2023 /* keep compiler quiet */
2026 if( offset >= tvb_reported_length (tvb)) {
2027 if (check_col (pinfo->cinfo, COL_INFO))
2028 col_append_str (pinfo->cinfo, COL_INFO, ", empty frame" );
2032 sub_tvb = tvb_new_subset_remaining(tvb, offset);
2034 /* XXX shouldn't pass through out-of-order packets. */
2036 if (check_col (pinfo->cinfo, COL_INFO)) {
2037 if( !video && iax_call && iax_call -> dataformat != 0 ) {
2038 col_append_fstr (pinfo->cinfo, COL_INFO, ", data, format %s",
2039 val_to_str (iax_call -> dataformat,
2040 iax_dataformats, "unknown (0x%02x)"));
2043 col_append_str (pinfo->cinfo, COL_INFO, " (out-of-order packet)");
2046 col_append_fstr (pinfo->cinfo, COL_INFO, ", %s",
2047 val_to_str (codec, codec_types, "unknown (0x%02x)"));
2051 nbytes = tvb_reported_length(sub_tvb);
2052 proto_tree_add_text( iax2_tree, sub_tvb, 0, -1,
2053 "IAX2 payload (%u byte%s)", nbytes,
2054 plurality( nbytes, "", "s" ));
2056 iax2_info->payload_len = nbytes;
2057 iax2_info->payload_data = tvb_get_ptr(sub_tvb, 0, -1);
2059 /* pass the rest of the block to a subdissector */
2060 if(iax_packet->call_data)
2061 desegment_iax( sub_tvb, pinfo, iax2_tree, tree, video, iax_packet );
2063 process_iax_pdu(sub_tvb,pinfo,tree,video,iax_packet);
2070 /* called at the start of a capture. We should clear out our static, per-capture
2075 iax_init_protocol(void)
2083 proto_register_iax2 (void)
2085 /* A header field is something you can search/filter on.
2087 * We create a structure to register our fields. It consists of an
2088 * array of hf_register_info structures, each of which are of the format
2089 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
2092 static hf_register_info hf[] = {
2094 {&hf_iax2_packet_type,
2095 {"Packet type", "iax2.packet_type", FT_UINT8, BASE_DEC, VALS(iax_packet_types), 0,
2096 "Full/minivoice/minivideo/meta packet",
2100 {"Call identifier", "iax2.call", FT_UINT32, BASE_DEC, NULL, 0,
2101 "This is the identifier Wireshark assigns to identify this call. It does not correspond to any real field in the protocol", HFILL }},
2104 {"Source call", "iax2.src_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2105 "src_call holds the number of this call at the packet source pbx",
2108 /* FIXME could this be turned into a FRAMENUM field? */
2110 {"Destination call", "iax2.dst_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2111 "dst_call holds the number of this call at the packet destination",
2114 {&hf_iax2_retransmission,
2115 {"Retransmission", "iax2.retransmission", FT_BOOLEAN, 16,
2117 "retransmission is set if this packet is a retransmission of an earlier failed packet", HFILL}},
2120 {"Timestamp", "iax2.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
2121 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2125 {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x0,
2126 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2129 {&hf_iax2_minividts,
2130 {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2131 "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2135 {"Absolute Time", "iax2.abstime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
2136 "The absoulte time of this packet (calculated by adding the IAX timestamp to the start time of this call)",
2140 {"Lateness", "iax2.lateness", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2141 "The lateness of this packet compared to its timestamp",
2144 {&hf_iax2_minividmarker,
2145 {"Marker", "iax2.video.marker", FT_UINT16, BASE_DEC, NULL, 0x8000,
2146 "RTP end-of-frame marker",
2150 {"Outbound seq.no.", "iax2.oseqno", FT_UINT16, BASE_DEC, NULL,
2152 "oseqno is the sequence no of this packet. The first packet has oseqno==0, and subsequent packets increment the oseqno by 1",
2156 {"Inbound seq.no.", "iax2.iseqno", FT_UINT16, BASE_DEC, NULL, 0x0,
2157 "iseqno is the sequence no of the last successfully received packet",
2161 {"Type", "iax2.type", FT_UINT8, BASE_DEC, VALS (iax_frame_types),
2163 "For full IAX2 frames, type is the type of frame",
2167 {"Unknown subclass", "iax2.subclass", FT_UINT8, BASE_DEC, NULL, 0x0,
2168 "Subclass of unknown type of full IAX2 frame",
2171 {&hf_iax2_dtmf_csub,
2172 {"DTMF subclass (digit)", "iax2.dtmf.subclass", FT_STRINGZ, BASE_NONE, NULL, 0x0,
2173 "DTMF subclass gives the DTMF digit",
2177 {"Control subclass", "iax2.control.subclass", FT_UINT8, BASE_DEC,
2178 VALS (iax_cmd_subclasses), 0x0,
2179 "This gives the command number for a Control packet.", HFILL}},
2182 {"IAX subclass", "iax2.iax.subclass", FT_UINT8, BASE_DEC,
2183 VALS (iax_iax_subclasses),
2185 "IAX subclass gives the command number for IAX signalling packets", HFILL}},
2187 {&hf_iax2_voice_csub,
2188 {"Voice Subclass (compressed codec no)", "iax2.voice.subclass", FT_UINT8, BASE_DEC, NULL, 0x0,
2192 {&hf_iax2_voice_codec,
2193 {"CODEC", "iax2.voice.codec", FT_UINT32, BASE_HEX, VALS (codec_types),
2195 "CODEC gives the codec used to encode audio data", HFILL}},
2197 {&hf_iax2_video_csub,
2198 {"Video Subclass (compressed codec no)", "iax2.video.subclass", FT_UINT8, BASE_DEC, NULL, 0xBF,
2203 {"Marker", "iax2.video.marker", FT_BOOLEAN, 8, NULL, 0x40,
2204 "RTP end-of-frame marker",
2207 {&hf_iax2_video_codec,
2208 {"CODEC", "iax2.video.codec", FT_UINT32, BASE_HEX, VALS (codec_types), 0,
2209 "The codec used to encode video data", HFILL}},
2211 {&hf_iax2_modem_csub,
2212 {"Modem subclass", "iax2.modem.subclass", FT_UINT8, BASE_DEC,
2213 VALS (iax_modem_subclasses),
2215 "Modem subclass gives the type of modem", HFILL}},
2218 * Decoding for the ies
2221 {&hf_IAX_IE_APPARENTADDR_SINFAMILY,
2222 {"Family", "iax2.iax.app_addr.sinfamily", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2223 {&hf_IAX_IE_APPARENTADDR_SINPORT,
2224 {"Port", "iax2.iax.app_addr.sinport", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2225 {&hf_IAX_IE_APPARENTADDR_SINADDR,
2226 {"Address", "iax2.iax.app_addr.sinaddr", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
2228 {&hf_iax2_ies[IAX_IE_CALLED_NUMBER],
2229 {"Number/extension being called", "iax2.iax.called_number",
2231 BASE_NONE, NULL, 0x0, NULL, HFILL}},
2233 {&hf_iax2_ies[IAX_IE_CALLING_NUMBER],
2234 {"Calling number", "iax2.iax.calling_number", FT_STRING,
2238 {&hf_iax2_ies[IAX_IE_CALLING_ANI],
2239 {"Calling number ANI for billing", "iax2.iax.calling_ani",
2241 BASE_NONE, NULL, 0x0, NULL, HFILL}},
2243 {&hf_iax2_ies[IAX_IE_CALLING_NAME],
2244 {"Name of caller", "iax2.iax.calling_name", FT_STRING, BASE_NONE,
2248 {&hf_iax2_ies[IAX_IE_CALLED_CONTEXT],
2249 {"Context for number", "iax2.iax.called_context", FT_STRING,
2251 NULL, 0x0, NULL, HFILL}},
2253 {&hf_iax2_ies[IAX_IE_USERNAME],
2254 {"Username (peer or user) for authentication",
2255 "iax2.iax.username",
2256 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2258 {&hf_iax2_ies[IAX_IE_PASSWORD],
2259 {"Password for authentication", "iax2.iax.password", FT_STRING,
2260 BASE_NONE, NULL, 0x0, NULL, HFILL}},
2262 {&hf_iax2_ies[IAX_IE_CAPABILITY],
2263 {"Actual codec capability", "iax2.iax.capability", FT_UINT32,
2265 NULL, 0x0, NULL, HFILL}},
2267 {&hf_iax2_ies[IAX_IE_FORMAT],
2268 {"Desired codec format", "iax2.iax.format", FT_UINT32, BASE_HEX,
2269 VALS (codec_types), 0x0, NULL, HFILL}},
2271 {&hf_iax2_ies[IAX_IE_LANGUAGE],
2272 {"Desired language", "iax2.iax.language", FT_STRING, BASE_NONE,
2276 {&hf_iax2_ies[IAX_IE_VERSION],
2277 {"Protocol version", "iax2.iax.version", FT_UINT16, BASE_HEX, NULL,
2281 {&hf_iax2_ies[IAX_IE_ADSICPE],
2282 {"CPE ADSI capability", "iax2.iax.cpe_adsi", FT_UINT16, BASE_HEX,
2286 {&hf_iax2_ies[IAX_IE_DNID],
2287 {"Originally dialed DNID", "iax2.iax.dnid", FT_STRING, BASE_NONE,
2291 {&hf_iax2_ies[IAX_IE_AUTHMETHODS],
2292 {"Authentication method(s)", "iax2.iax.auth.methods", FT_UINT16,
2294 NULL, 0x0, NULL, HFILL}},
2296 {&hf_iax2_ies[IAX_IE_CHALLENGE],
2297 {"Challenge data for MD5/RSA", "iax2.iax.auth.challenge",
2299 BASE_NONE, NULL, 0x0, NULL, HFILL}},
2301 {&hf_iax2_ies[IAX_IE_MD5_RESULT],
2302 {"MD5 challenge result", "iax2.iax.auth.md5", FT_STRING,
2306 {&hf_iax2_ies[IAX_IE_RSA_RESULT],
2307 {"RSA challenge result", "iax2.iax.auth.rsa", FT_STRING,
2311 {&hf_iax2_ies[IAX_IE_REFRESH],
2312 {"When to refresh registration", "iax2.iax.refresh", FT_INT16,
2314 NULL, 0x0, NULL, HFILL}},
2316 {&hf_iax2_ies[IAX_IE_DPSTATUS],
2317 {"Dialplan status", "iax2.iax.dialplan_status", FT_UINT16,
2321 {&hf_iax2_ies[IAX_IE_CALLNO],
2322 {"Call number of peer", "iax2.iax.call_no", FT_UINT16, BASE_DEC,
2326 {&hf_iax2_ies[IAX_IE_CAUSE],
2327 {"Cause", "iax2.iax.cause", FT_STRING, BASE_NONE, NULL, 0x0, NULL,
2330 {&hf_iax2_ies[IAX_IE_IAX_UNKNOWN],
2331 {"Unknown IAX command", "iax2.iax.iax_unknown", FT_BYTES,
2335 {&hf_iax2_ies[IAX_IE_MSGCOUNT],
2336 {"How many messages waiting", "iax2.iax.msg_count", FT_INT16,
2338 NULL, 0x0, NULL, HFILL}},
2340 {&hf_iax2_ies[IAX_IE_AUTOANSWER],
2341 {"Request auto-answering", "iax2.iax.autoanswer", FT_NONE,
2343 NULL, 0x0, NULL, HFILL}},
2345 {&hf_iax2_ies[IAX_IE_MUSICONHOLD],
2346 {"Request musiconhold with QUELCH", "iax2.iax.moh", FT_NONE,
2348 NULL, 0x0, NULL, HFILL}},
2350 {&hf_iax2_ies[IAX_IE_TRANSFERID],
2351 {"Transfer Request Identifier", "iax2.iax.transferid", FT_UINT32,
2352 BASE_HEX, NULL, 0x0, NULL, HFILL}},
2354 {&hf_iax2_ies[IAX_IE_RDNIS],
2355 {"Referring DNIS", "iax2.iax.rdnis", FT_STRING, BASE_NONE, NULL,
2359 {&hf_iax2_ies[IAX_IE_PROVISIONING],
2360 {"Provisioning info","iax2.iax.provisioning", FT_STRING, BASE_NONE,
2361 NULL, 0x0, NULL, HFILL}},
2363 {&hf_iax2_ies[IAX_IE_AESPROVISIONING],
2364 {"AES Provisioning info","iax2.iax.aesprovisioning", FT_STRING, BASE_NONE,
2365 NULL, 0x0, NULL, HFILL}},
2367 {&hf_iax2_ies[IAX_IE_DATETIME],
2368 {"Date/Time", "iax2.iax.datetime.raw", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2370 {&hf_iax2_ie_datetime,
2371 {"Date/Time", "iax2.iax.datetime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2373 {&hf_iax2_ies[IAX_IE_DEVICETYPE],
2374 {"Device type", "iax2.iax.devicetype", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2376 {&hf_iax2_ies[IAX_IE_SERVICEIDENT],
2377 {"Service identifier", "iax2.iax.serviceident", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2379 {&hf_iax2_ies[IAX_IE_FIRMWAREVER],
2380 {"Firmware version", "iax2.iax.firmwarever", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2382 {&hf_iax2_ies[IAX_IE_FWBLOCKDESC],
2383 {"Firmware block description", "iax2.iax.fwblockdesc", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2385 {&hf_iax2_ies[IAX_IE_FWBLOCKDATA],
2386 {"Firmware block of data", "iax2.iax.fwblockdata", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2388 {&hf_iax2_ies[IAX_IE_PROVVER],
2389 {"Provisioning version", "iax2.iax.provver", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2391 {&hf_iax2_ies[IAX_IE_CALLINGPRES],
2392 {"Calling presentation", "iax2.iax.callingpres", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2394 {&hf_iax2_ies[IAX_IE_CALLINGTON],
2395 {"Calling type of number", "iax2.iax.callington", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2397 {&hf_iax2_ies[IAX_IE_CALLINGTNS],
2398 {"Calling transit network select", "iax2.iax.callingtns", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2400 {&hf_iax2_ies[IAX_IE_SAMPLINGRATE],
2401 {"Supported sampling rates", "iax2.iax.samplingrate", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2403 {&hf_iax2_ies[IAX_IE_CAUSECODE],
2404 {"Hangup cause", "iax2.iax.causecode", FT_UINT8, BASE_HEX, VALS(iax_causecodes),
2407 {&hf_iax2_ies[IAX_IE_ENCRYPTION],
2408 {"Encryption format", "iax2.iax.encryption", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2410 {&hf_iax2_ies[IAX_IE_ENCKEY],
2411 {"Encryption key", "iax2.iax.enckey", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2413 {&hf_iax2_ies[IAX_IE_CODEC_PREFS],
2414 {"Codec negotiation", "iax2.iax.codecprefs", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2416 {&hf_iax2_ies[IAX_IE_RR_JITTER],
2417 {"Received jitter (as in RFC1889)", "iax2.iax.rrjitter", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2419 {&hf_iax2_ies[IAX_IE_RR_LOSS],
2420 {"Received loss (high byte loss pct, low 24 bits loss count, as in rfc1889)", "iax2.iax.rrloss",
2421 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2423 {&hf_iax2_ies[IAX_IE_RR_PKTS],
2424 {"Total frames received", "iax2.iax.rrpkts", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2426 {&hf_iax2_ies[IAX_IE_RR_DELAY],
2427 {"Max playout delay in ms for received frames", "iax2.iax.rrdelay", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2429 {&hf_iax2_ies[IAX_IE_RR_DROPPED],
2430 {"Dropped frames (presumably by jitterbuffer)", "iax2.iax.rrdropped", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2432 {&hf_iax2_ies[IAX_IE_RR_OOO],
2433 {"Frame received out of order", "iax2.iax.rrooo", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2435 {&hf_iax2_ies[IAX_IE_DATAFORMAT],
2436 {"Data call format", "iax2.iax.dataformat", FT_UINT32, BASE_HEX,
2437 VALS(iax_dataformats), 0x0, NULL, HFILL}},
2439 {&hf_IAX_IE_UNKNOWN_BYTE,
2440 {"Unknown", "iax2.iax.unknownbyte", FT_UINT8, BASE_HEX, NULL,
2441 0x0, "Raw data for unknown IEs",
2443 {&hf_IAX_IE_UNKNOWN_I16,
2444 {"Unknown", "iax2.iax.unknownshort", FT_UINT16, BASE_HEX, NULL,
2445 0x0, "Raw data for unknown IEs",
2447 {&hf_IAX_IE_UNKNOWN_I32,
2448 {"Unknown", "iax2.iax.unknownlong", FT_UINT32, BASE_HEX, NULL,
2449 0x0, "Raw data for unknown IEs",
2451 {&hf_IAX_IE_UNKNOWN_BYTES,
2452 {"Unknown", "iax2.iax.unknownstring", FT_STRING, BASE_NONE, NULL,
2453 0x0, "Raw data for unknown IEs",
2457 {&hf_iax2_cap_g723_1,
2458 {"G.723.1 compression", "iax2.cap.g723_1", FT_BOOLEAN, 32,
2459 TFS(&tfs_supported_not_supported), AST_FORMAT_G723_1,
2463 {"GSM compression", "iax2.cap.gsm", FT_BOOLEAN, 32,
2464 TFS(&tfs_supported_not_supported), AST_FORMAT_GSM,
2468 {"Raw mu-law data (G.711)", "iax2.cap.ulaw",FT_BOOLEAN, 32,
2469 TFS(&tfs_supported_not_supported), AST_FORMAT_ULAW,
2473 {"Raw A-law data (G.711)", "iax2.cap.alaw",FT_BOOLEAN, 32,
2474 TFS(&tfs_supported_not_supported), AST_FORMAT_ALAW,
2478 {"G.726 compression", "iax2.cap.g726",FT_BOOLEAN, 32,
2479 TFS(&tfs_supported_not_supported), AST_FORMAT_G726,
2482 {&hf_iax2_cap_adpcm,
2483 {"ADPCM", "iax2.cap.adpcm", FT_BOOLEAN, 32,
2484 TFS(&tfs_supported_not_supported), AST_FORMAT_ADPCM,
2487 {&hf_iax2_cap_slinear,
2488 {"Raw 16-bit Signed Linear (8000 Hz) PCM", "iax2.cap.slinear",
2489 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), AST_FORMAT_SLINEAR,
2492 {&hf_iax2_cap_lpc10,
2493 {"LPC10, 180 samples/frame", "iax2.cap.lpc10", FT_BOOLEAN, 32,
2494 TFS(&tfs_supported_not_supported), AST_FORMAT_LPC10,
2497 {&hf_iax2_cap_g729a,
2498 {"G.729a Audio", "iax2.cap.g729a", FT_BOOLEAN, 32,
2499 TFS(&tfs_supported_not_supported), AST_FORMAT_G729A,
2502 {&hf_iax2_cap_speex,
2503 {"SPEEX Audio", "iax2.cap.speex", FT_BOOLEAN, 32,
2504 TFS(&tfs_supported_not_supported), AST_FORMAT_SPEEX,
2508 {"iLBC Free compressed Audio", "iax2.cap.ilbc", FT_BOOLEAN, 32,
2509 TFS(&tfs_supported_not_supported), AST_FORMAT_ILBC,
2513 {"JPEG images", "iax2.cap.jpeg", FT_BOOLEAN, 32,
2514 TFS(&tfs_supported_not_supported), AST_FORMAT_JPEG,
2518 {"PNG images", "iax2.cap.png", FT_BOOLEAN, 32,
2519 TFS(&tfs_supported_not_supported), AST_FORMAT_PNG,
2523 {"H.261 video", "iax2.cap.h261", FT_BOOLEAN, 32,
2524 TFS(&tfs_supported_not_supported), AST_FORMAT_H261,
2528 {"H.263 video", "iax2.cap.h263", FT_BOOLEAN, 32,
2529 TFS(&tfs_supported_not_supported), AST_FORMAT_H263,
2532 /* reassembly stuff */
2533 {&hf_iax2_fragments,
2534 {"IAX2 Fragments", "iax2.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2538 {"IAX2 Fragment data", "iax2.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2541 {&hf_iax2_fragment_overlap,
2542 {"Fragment overlap", "iax2.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2543 NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2545 {&hf_iax2_fragment_overlap_conflict,
2546 {"Conflicting data in fragment overlap", "iax2.fragment.overlap.conflict",
2547 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2548 "Overlapping fragments contained conflicting data", HFILL }},
2550 {&hf_iax2_fragment_multiple_tails,
2551 {"Multiple tail fragments found", "iax2.fragment.multipletails",
2552 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2553 "Several tails were found when defragmenting the packet", HFILL }},
2555 {&hf_iax2_fragment_too_long_fragment,
2556 {"Fragment too long", "iax2.fragment.toolongfragment",
2557 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2558 "Fragment contained data past end of packet", HFILL }},
2560 {&hf_iax2_fragment_error,
2561 {"Defragmentation error", "iax2.fragment.error",
2562 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2563 "Defragmentation error due to illegal fragments", HFILL }},
2565 {&hf_iax2_reassembled_in,
2566 {"IAX2 fragment, reassembled in frame", "iax2.reassembled_in",
2567 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2568 "This IAX2 packet is reassembled in this frame", HFILL }}
2571 static gint *ett[] = {
2573 &ett_iax2_full_mini_subtree,
2577 &ett_iax2_ies_apparent_addr,
2582 /* initialise the hf_iax2_ies[] array to -1 */
2583 memset(hf_iax2_ies,0xff,sizeof(hf_iax2_ies));
2586 proto_register_protocol ("Inter-Asterisk eXchange v2", "IAX2", "iax2");
2587 proto_register_field_array (proto_iax2, hf, array_length (hf));
2588 proto_register_subtree_array (ett, array_length (ett));
2590 register_dissector("iax2", dissect_iax2, proto_iax2);
2592 iax2_codec_dissector_table = register_dissector_table(
2593 "iax2.codec","IAX codec number", FT_UINT32, BASE_HEX);
2594 iax2_dataformat_dissector_table = register_dissector_table(
2595 "iax2.dataformat","IAX dataformat number", FT_UINT32, BASE_HEX);
2597 /* register our init routine to be called at the start of a capture,
2598 to clear out our hash tables etc */
2599 register_init_routine(&iax_init_protocol);
2600 iax2_tap = register_tap("IAX2");
2604 proto_reg_handoff_iax2 (void)
2606 dissector_add("udp.port", IAX2_PORT, find_dissector("iax2"));
2607 dissector_add("iax2.dataformat", AST_DATAFORMAT_V110, find_dissector("v110"));
2608 data_handle = find_dissector("data");
2613 * This sets up the indentation style for this file in emacs.
2620 * vim:set ts=8 sts=2 sw=2 noet: