From Richard van der Hoff:
[obnox/wireshark/wip.git] / epan / dissectors / packet-iax2.c
1 /*
2  * packet-iax2.c
3  *
4  * Routines for IAX2 packet disassembly
5  * By Alastair Maw <asterisk@almaw.com>
6  * Copyright 2003 Alastair Maw
7  *
8  * IAX2 is a VoIP protocol for the open source PBX Asterisk. Please see
9  * http://www.asterisk.org for more information.
10  *
11  * $Id$
12  *
13  * Ethereal - Network traffic analyzer
14  * By Gerald Combs <gerald@ethereal.com>
15  * Copyright 1998 Gerald Combs
16  * 
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.
27  *
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <glib.h>
37
38 #include <epan/circuit.h>
39 #include <epan/packet.h>
40 #include <epan/to_str.h>
41
42 #include "packet-iax2.h"
43 #include "iax2_codec_type.h"
44
45 #define IAX2_PORT               4569
46 #define PROTO_TAG_IAX2          "IAX2"
47
48 /* enough to hold any address in an address_t */
49 #define MAX_ADDRESS 16
50
51 /* the maximum number of transfers (of each end) we can deal with per call,
52  * plus one */
53 #define IAX_MAX_TRANSFERS 2
54
55 /* #define DEBUG_HASHING */
56
57 /* Ethereal ID of the IAX2 protocol */
58 static int proto_iax2 = -1;
59
60 /* The following hf_* variables are used to hold the ethereal IDs of
61  * our header fields; they are filled out when we call
62  * proto_register_field_array() in proto_register_iax2()
63  */
64 static int hf_iax2_packet_type = -1;
65 static int hf_iax2_retransmission = -1;
66 static int hf_iax2_callno = -1;
67 static int hf_iax2_scallno = -1;
68 static int hf_iax2_dcallno = -1;
69 static int hf_iax2_ts = -1;
70 static int hf_iax2_minits = -1;
71 static int hf_iax2_minividts = -1;
72 static int hf_iax2_absts = -1;
73 static int hf_iax2_lateness = -1;
74 static int hf_iax2_minividmarker = -1;
75 static int hf_iax2_oseqno = -1;
76 static int hf_iax2_iseqno = -1;
77 static int hf_iax2_type = -1;
78 static int hf_iax2_csub = -1;
79 static int hf_iax2_dtmf_csub = -1;
80 static int hf_iax2_cmd_csub = -1;
81 static int hf_iax2_iax_csub = -1;
82 static int hf_iax2_voice_csub = -1;
83 static int hf_iax2_voice_codec = -1;
84 static int hf_iax2_video_csub = -1;
85 static int hf_iax2_video_codec = -1;
86 static int hf_iax2_marker = -1;
87
88 static int hf_iax2_cap_g723_1 = -1;
89 static int hf_iax2_cap_gsm = -1;
90 static int hf_iax2_cap_ulaw = -1;
91 static int hf_iax2_cap_alaw = -1;
92 static int hf_iax2_cap_g726 = -1;
93 static int hf_iax2_cap_adpcm = -1;
94 static int hf_iax2_cap_slinear = -1;
95 static int hf_iax2_cap_lpc10 = -1;
96 static int hf_iax2_cap_g729a = -1;
97 static int hf_iax2_cap_speex = -1;
98 static int hf_iax2_cap_ilbc = -1;
99 static int hf_iax2_cap_jpeg = -1;
100 static int hf_iax2_cap_png = -1;
101 static int hf_iax2_cap_h261 = -1;
102 static int hf_iax2_cap_h263 = -1;
103
104 /* hf_iax2_ies is an array of header fields, one per potential Information
105  * Element. It's done this way (rather than having separate variables for each
106  * IE) to make the dissection of information elements clearer and more
107  * orthoganal.
108  *
109  * To add the ability to dissect a new information element, just add an
110  * appropriate entry to hf[] in proto_register_iax2(); dissect_ies() will then
111  * pick it up automatically.
112  */
113 static int hf_iax2_ies[256];
114 static int hf_iax2_ie_datetime = -1;
115 static int hf_IAX_IE_APPARENTADDR_SINFAMILY = -1;
116 static int hf_IAX_IE_APPARENTADDR_SINPORT = -1;
117 static int hf_IAX_IE_APPARENTADDR_SINADDR = -1;
118 static int hf_IAX_IE_UNKNOWN_BYTE = -1;
119 static int hf_IAX_IE_UNKNOWN_I16 = -1;
120 static int hf_IAX_IE_UNKNOWN_I32 = -1;
121 static int hf_IAX_IE_UNKNOWN_BYTES = -1;
122
123 /* These are the ids of the subtrees that we may be creating */
124 static gint ett_iax2 = -1;
125 static gint ett_iax2_full_mini_subtree = -1;
126 static gint ett_iax2_type = -1;         /* Frame-type specific subtree */
127 static gint ett_iax2_ie = -1;           /* single IE */
128 static gint ett_iax2_codecs = -1;       /* capabilities IE */
129 static gint ett_iax2_ies_apparent_addr = -1; /* apparent address IE */
130
131 static dissector_handle_t data_handle;
132
133 /* data-call subdissectors, AST_DATAFORMAT_* */
134 static dissector_table_t iax2_dataformat_dissector_table;
135 /* voice/video call subdissectors, AST_FORMAT_* */
136 static dissector_table_t iax2_codec_dissector_table;
137
138 /* IAX2 Full-frame types */
139 static const value_string iax_frame_types[] = {
140   {0, "(0?)"},
141   {1, "DTMF"},
142   {2, "Voice"},
143   {3, "Video"},
144   {4, "Control"},
145   {5, "NULL"},
146   {6, "IAX"},
147   {7, "Text"},
148   {8, "Image"},
149   {0,NULL}
150 };
151
152 /* Subclasses for IAX packets */
153 static const value_string iax_iax_subclasses[] = {
154   {0, "(0?)"},
155   {1, "NEW"},
156   {2, "PING"},
157   {3, "PONG"},
158   {4, "ACK"},
159   {5, "HANGUP"},
160   {6, "REJECT"},
161   {7, "ACCEPT"},
162   {8, "AUTHREQ"},
163   {9, "AUTHREP"},
164   {10, "INVAL"},
165   {11, "LAGRQ"},
166   {12, "LAGRP"},
167   {13, "REGREQ"},
168   {14, "REGAUTH"},
169   {15, "REGACK"},
170   {16, "REGREJ"},
171   {17, "REGREL"},
172   {18, "VNAK"},
173   {19, "DPREQ"},
174   {20, "DPREP"},
175   {21, "DIAL"},
176   {22, "TXREQ"},
177   {23, "TXCNT"},
178   {24, "TXACC"},
179   {25, "TXREADY"},
180   {26, "TXREL"},
181   {27, "TXREJ"},
182   {28, "QUELCH"},
183   {29, "UNQULCH"},
184   {30, "POKE"},
185   {31, "PAGE"},
186   {32, "MWI"},
187   {33, "UNSUPPORTED"},
188   {34, "TRANSFER"},
189   {35, "PROVISION"},
190   {36, "FWDOWNL"},
191   {37, "FWDATA"},
192   {0,NULL}
193 };
194
195 /* Subclassess for Control packets */
196 static const value_string iax_cmd_subclasses[] = {
197   {0, "(0?)"},
198   {1, "HANGUP"},
199   {2, "RING"},
200   {3, "RINGING"},
201   {4, "ANSWER"},
202   {5, "BUSY"},
203   {6, "TKOFFHK"},
204   {7, "OFFHOOK"},
205   {0xFF, "stop sounds"}, /* sent by app_dial, and not much else */
206   {0,NULL}
207 };
208
209 /* Information elements */
210 static const value_string iax_ies_type[] = {
211   {IAX_IE_CALLED_NUMBER, "Number/extension being called"},
212   {IAX_IE_CALLING_NUMBER, "Calling number"},
213   {IAX_IE_CALLING_ANI, "Calling number ANI for billing"},
214   {IAX_IE_CALLING_NAME, "Name of caller"},
215   {IAX_IE_CALLED_CONTEXT, "Context for number"},
216   {IAX_IE_USERNAME, "Username (peer or user) for authentication"},
217   {IAX_IE_PASSWORD, "Password for authentication"},
218   {IAX_IE_CAPABILITY, "Actual codec capability"},
219   {IAX_IE_FORMAT, "Desired codec format"},
220   {IAX_IE_LANGUAGE, "Desired language"},
221   {IAX_IE_VERSION, "Protocol version"},
222   {IAX_IE_ADSICPE, "CPE ADSI capability"},
223   {IAX_IE_DNID, "Originally dialed DNID"},
224   {IAX_IE_AUTHMETHODS, "Authentication method(s)"},
225   {IAX_IE_CHALLENGE, "Challenge data for MD5/RSA"},
226   {IAX_IE_MD5_RESULT, "MD5 challenge result"},
227   {IAX_IE_RSA_RESULT, "RSA challenge result"},
228   {IAX_IE_APPARENT_ADDR, "Apparent address of peer"},
229   {IAX_IE_REFRESH, "When to refresh registration"},
230   {IAX_IE_DPSTATUS, "Dialplan status"},
231   {IAX_IE_CALLNO, "Call number of peer"},
232   {IAX_IE_CAUSE, "Cause"},
233   {IAX_IE_IAX_UNKNOWN, "Unknown IAX command"},
234   {IAX_IE_MSGCOUNT, "How many messages waiting"},
235   {IAX_IE_AUTOANSWER, "Request auto-answering"},
236   {IAX_IE_MUSICONHOLD, "Request musiconhold with QUELCH"},
237   {IAX_IE_TRANSFERID, "Transfer Request Identifier"},
238   {IAX_IE_RDNIS, "Referring DNIS"},
239   {IAX_IE_PROVISIONING, "Provisioning info"},
240   {IAX_IE_AESPROVISIONING, "AES Provisioning info"},
241   {IAX_IE_DATETIME,"Date/Time"},
242   {IAX_IE_DEVICETYPE, "Device type"},
243   {IAX_IE_SERVICEIDENT, "Service Identifier"},
244   {IAX_IE_FIRMWAREVER, "Firmware revision"},
245   {IAX_IE_FWBLOCKDESC, "Firmware block description"},
246   {IAX_IE_FWBLOCKDATA, "Firmware block of data"},
247   {IAX_IE_PROVVER, "Provisioning version"},
248   {IAX_IE_CALLINGPRES, "Calling presentation"},
249   {IAX_IE_CALLINGTON, "Calling type of number"},
250   {IAX_IE_CALLINGTNS, "Calling transit network select"},
251   {IAX_IE_SAMPLINGRATE, "Supported sampling rates"},
252   {IAX_IE_CAUSECODE, "Hangup cause"},
253   {IAX_IE_ENCRYPTION, "Encryption format"},
254   {IAX_IE_ENCKEY, "Raw encryption key"},
255   {IAX_IE_CODEC_PREFS, "Codec preferences"},
256   {IAX_IE_RR_JITTER, "Received jitter"},
257   {IAX_IE_RR_LOSS, "Received loss"},
258   {IAX_IE_RR_PKTS, "Received frames"},
259   {IAX_IE_RR_DELAY, "Max playout delay in ms for received frames"},
260   {IAX_IE_RR_DROPPED, "Dropped frames"},
261   {IAX_IE_RR_OOO, "Frames received out of order"},
262   {IAX_IE_DATAFORMAT, "Data call format"},
263   {0,NULL}
264 };
265
266 static const value_string codec_types[] = {
267   {AST_FORMAT_G723_1, "G.723.1 compression"},
268   {AST_FORMAT_GSM, "GSM compression"},
269   {AST_FORMAT_ULAW, "Raw mu-law data (G.711)"},
270   {AST_FORMAT_ALAW, "Raw A-law data (G.711)"},
271   {AST_FORMAT_G726, "ADPCM (G.726, 32kbps)"},
272   {AST_FORMAT_ADPCM, "ADPCM (IMA)"},
273   {AST_FORMAT_SLINEAR, "Raw 16-bit Signed Linear (8000 Hz) PCM"},
274   {AST_FORMAT_LPC10, "LPC10, 180 samples/frame"},
275   {AST_FORMAT_G729A, "G.729a Audio"},
276   {AST_FORMAT_SPEEX, "SpeeX Free Compression"},
277   {AST_FORMAT_ILBC, "iLBC Free Compression"},
278   {AST_FORMAT_JPEG, "JPEG Images"},
279   {AST_FORMAT_PNG, "PNG Images"},
280   {AST_FORMAT_H261, "H.261 Video"},
281   {AST_FORMAT_H263, "H.263 Video"},
282   {0,NULL}
283 };
284
285 static const value_string iax_dataformats[] = {
286   {AST_DATAFORMAT_NULL, "N/A (analogue call?)"},
287   {AST_DATAFORMAT_V110, "ITU-T V.110 rate adaption"},
288   {AST_DATAFORMAT_H223_H245,"ITU-T H.223/H.245"},
289   {0,NULL}
290 };
291
292 typedef enum {
293   IAX2_MINI_VOICE_PACKET,
294   IAX2_FULL_PACKET,
295   IAX2_MINI_VIDEO_PACKET,
296   IAX2_META_PACKET
297 } packet_type;
298
299 static const value_string iax_packet_types[] = {
300   {IAX2_FULL_PACKET, "Full packet"},
301   {IAX2_MINI_VOICE_PACKET, "Mini voice packet"},
302   {IAX2_MINI_VIDEO_PACKET, "Mini video packet"},
303   {IAX2_META_PACKET, "Meta packet"},
304   {0,NULL}
305 };
306   
307 static const value_string iax_causecodes[] = {
308   {AST_CAUSE_UNALLOCATED, "Unallocated"},
309   {AST_CAUSE_NO_ROUTE_TRANSIT_NET, "No route transit net"},
310   {AST_CAUSE_NO_ROUTE_DESTINATION, "No route to destination"},
311   {AST_CAUSE_CHANNEL_UNACCEPTABLE, "Channel unacceptable"},
312   {AST_CAUSE_CALL_AWARDED_DELIVERED, "Call awarded delivered"},
313   {AST_CAUSE_NORMAL_CLEARING, "Normal clearing"},
314   {AST_CAUSE_USER_BUSY, "User busy"},
315   {AST_CAUSE_NO_USER_RESPONSE, "No user response"},
316   {AST_CAUSE_NO_ANSWER, "No answer"},
317   {AST_CAUSE_CALL_REJECTED, "Call rejected"},
318   {AST_CAUSE_NUMBER_CHANGED, "Number changed"},
319   {AST_CAUSE_DESTINATION_OUT_OF_ORDER, "Destination out of order"},
320   {AST_CAUSE_INVALID_NUMBER_FORMAT, "Invalid number format"},
321   {AST_CAUSE_FACILITY_REJECTED, "Facility rejected"},
322   {AST_CAUSE_RESPONSE_TO_STATUS_ENQUIRY, "Response to status inquiry"},
323   {AST_CAUSE_NORMAL_UNSPECIFIED, "Normal unspecified"},
324   {AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, "Normal circuit congestion"},
325   {AST_CAUSE_NETWORK_OUT_OF_ORDER, "Network out of order"},
326   {AST_CAUSE_NORMAL_TEMPORARY_FAILURE, "Normal temporary failure"},
327   {AST_CAUSE_SWITCH_CONGESTION, "Switch congestion"},
328   {AST_CAUSE_ACCESS_INFO_DISCARDED, "Access info discarded"},
329   {AST_CAUSE_REQUESTED_CHAN_UNAVAIL, "Requested channel unavailable"},
330   {AST_CAUSE_PRE_EMPTED, "Preempted"},
331   {AST_CAUSE_FACILITY_NOT_SUBSCRIBED, "Facility not subscribed"},
332   {AST_CAUSE_OUTGOING_CALL_BARRED, "Outgoing call barred"},
333   {AST_CAUSE_INCOMING_CALL_BARRED, "Incoming call barred"},
334   {AST_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized"},
335   {AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available"},
336   {AST_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented"},
337   {AST_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented"},
338   {AST_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented"},
339   {AST_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference"},
340   {AST_CAUSE_INCOMPATIBLE_DESTINATION, "Incompatible destination"},
341   {AST_CAUSE_INVALID_MSG_UNSPECIFIED, "Invalid message unspecified"},
342   {AST_CAUSE_MANDATORY_IE_MISSING, "Mandatory IE missing"},
343   {AST_CAUSE_MESSAGE_TYPE_NONEXIST, "Message type nonexistent"},
344   {AST_CAUSE_WRONG_MESSAGE, "Wrong message"},
345   {AST_CAUSE_IE_NONEXIST, "IE nonexistent"},
346   {AST_CAUSE_INVALID_IE_CONTENTS, "Invalid IE contents"},
347   {AST_CAUSE_WRONG_CALL_STATE, "Wrong call state"},
348   {AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, "Recovery on timer expire"},
349   {AST_CAUSE_MANDATORY_IE_LENGTH_ERROR, "Mandatory IE length error"},
350   {AST_CAUSE_PROTOCOL_ERROR, "Protocol error"},
351   {AST_CAUSE_INTERWORKING, "Interworking"},
352   {0, NULL}
353 };
354
355
356 /* ************************************************************************* */
357
358 /* In order to track IAX calls, we have a hash table which maps
359  * {addr,port type,port,call} to a unique circuit id.
360  *
361  * Each call has two such circuits associated with it (a forward and a
362  * reverse circuit, where 'forward' is defined as the direction the NEW
363  * packet went in), and we maintain an iax_call_data structure for each
364  * call, attached to both circuits with circuit_add_proto_data.
365  *
366  * Because {addr,port type,port,call} quadruplets can be reused
367  * (Asterisk reuses call numbers), circuit ids aren't unique to
368  * individual calls and we treat NEW packets somewhat specially. When we
369  * get such a packet, we see if there are any calls with a matching
370  * circuit id, and make sure that its circuits are marked as ended
371  * before that packet.
372  *
373  * A second complication is that we only know one quadruplet at the time
374  * the NEW packet is processed: there is therefore cunningness in
375  * iax_lookup_circuit_details() to look for replies to NEW packets and
376  * create the reverse circuit.
377  */
378
379
380 /* start with a hash of {addr,port type,port,call}->{id} */
381
382 typedef struct {
383   address addr;
384   port_type ptype;
385   guint32 port;
386   guint32 callno;
387
388   /* this is where addr->data points to. it's put in here for easy freeing */
389   guint8 address_data[MAX_ADDRESS];
390 } iax_circuit_key;
391
392 /* tables */
393 static GHashTable *iax_circuit_hashtab = NULL;
394 static GMemChunk *iax_circuit_keys = NULL;
395 static GMemChunk *iax_circuit_vals = NULL;
396 static guint circuitcount = 0;
397
398 /* the number of keys and values to reserve space for in each memory chunk.
399    We assume we won't be tracking many calls at once so this is quite low.
400 */
401 #define IAX_INIT_PACKET_COUNT 10
402
403 #ifdef DEBUG_HASHING
404 static gchar *key_to_str( const iax_circuit_key *key )
405 {
406   static int i=0;
407   static gchar *strp, str[3][80];
408
409   i++;
410   if(i>=3){
411     i=0;
412   }
413   strp=str[i];
414
415   /* why doesn't address_to_str take a const pointer?
416      cast the warnings into oblivion. */
417
418   sprintf(strp,"{%s:%i,%i}",
419           address_to_str((address *)&key->addr),
420           key->port,
421           key->callno);
422   return strp;
423 }
424 #endif
425
426 /* Hash Functions */
427 static gint iax_circuit_equal(gconstpointer v, gconstpointer w)
428 {
429   const iax_circuit_key *v1 = (const iax_circuit_key *)v;
430   const iax_circuit_key *v2 = (const iax_circuit_key *)w;
431   gint result;
432
433   result = ( ADDRESSES_EQUAL(&(v1->addr), &(v2->addr)) &&
434              v1->ptype == v2->ptype &&
435              v1->port  == v2->port &&
436              v1->callno== v2->callno);
437 #ifdef DEBUG_HASHING
438   g_message( "+++ Comparing for equality: %s, %s: %u",key_to_str(v1), key_to_str(v2), result);
439 #endif
440
441   return result;
442 }
443
444 static guint iax_circuit_hash (gconstpointer v)
445 {
446   const iax_circuit_key *key = (const iax_circuit_key *)v;
447   guint hash_val;
448   int i;
449
450   hash_val = 0;
451   for (i = 0; i < key->addr.len; i++)
452     hash_val += (guint)(key->addr.data[i]);
453
454   hash_val += (guint)(key->ptype);
455   hash_val += (guint)(key->port);
456   hash_val += (guint)(key->callno);
457
458 #ifdef DEBUG_HASHING
459   g_message( "+++ Hashing key: %s, result %#x", key_to_str(key), hash_val );
460 #endif
461   
462   return (guint) hash_val;
463 }
464
465 /* Find, or create, a circuit for the given
466    {address,porttype,port,call} quadruplet
467 */
468 static guint iax_circuit_lookup(const address *address,
469                                 port_type ptype,
470                                 guint32 port,
471                                 guint32 callno)
472 {
473   iax_circuit_key key;
474   guint32 *circuit_id_p;
475
476   key.addr = *address;
477   key.ptype = ptype;
478   key.port = port;
479   key.callno = callno;
480
481   circuit_id_p = g_hash_table_lookup( iax_circuit_hashtab, &key);
482   if( ! circuit_id_p ) {
483     iax_circuit_key *new_key;
484
485     new_key = g_mem_chunk_alloc(iax_circuit_keys);
486     new_key->addr.type = address->type;
487     new_key->addr.len = MIN(address->len,MAX_ADDRESS);
488     new_key->addr.data = new_key->address_data;
489     memmove(new_key->address_data,address->data,new_key->addr.len);
490     new_key->ptype = ptype;
491     new_key->port = port;
492     new_key->callno = callno;
493
494     circuit_id_p = g_mem_chunk_alloc(iax_circuit_vals);
495     *circuit_id_p = ++circuitcount;
496
497     g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p);
498
499 #ifdef DEBUG_HASHING
500     g_message("Created new circuit id %u for node %s", *circuit_id_p, key_to_str(new_key));
501 #endif
502   }
503
504   return *circuit_id_p;
505 }
506
507
508 /* ************************************************************************* */
509
510
511 /* This is our per-call data structure, which is attached to both the
512  * forward and reverse circuits.
513  */
514 typedef struct iax_call_data {
515   /* For this data, src and dst are relative to the original direction under
516      which this call is stored. Obviously if the reversed flag is set true by
517      iax_find_call, src and dst are reversed relative to the direction the
518      actual source and destination of the data.
519
520      if the codec changes mid-call, we update it here; because we store a codec
521      number with each packet too, we handle going back to earlier packets
522      without problem.
523   */
524
525   iax_dataformat_t dataformat;
526   guint32 src_codec, dst_codec;
527   guint32 src_vformat, dst_vformat;
528
529   /* when a transfer takes place, we'll get a new circuit id; we assume that we
530      don't try to transfer more than IAX_MAX_TRANSFERS times in a call */
531   guint forward_circuit_ids[IAX_MAX_TRANSFERS];
532   guint reverse_circuit_ids[IAX_MAX_TRANSFERS];
533   guint n_forward_circuit_ids;
534   guint n_reverse_circuit_ids;
535
536   /* this is the subdissector for the call */
537   dissector_handle_t subdissector;
538
539   /* the absolute start time of the call */
540   nstime_t start_time;
541 } iax_call_data;
542
543 static GMemChunk *iax_call_datas = NULL;
544
545 static void iax_init_hash( void )
546 {
547   if (iax_circuit_hashtab)
548     g_hash_table_destroy(iax_circuit_hashtab);
549
550   if (iax_circuit_keys)
551     g_mem_chunk_destroy(iax_circuit_keys);
552   if (iax_circuit_vals)
553     g_mem_chunk_destroy(iax_circuit_vals);
554   if (iax_call_datas)
555     g_mem_chunk_destroy(iax_call_datas);
556
557   iax_circuit_hashtab = g_hash_table_new(iax_circuit_hash, iax_circuit_equal);
558
559   iax_circuit_keys = g_mem_chunk_create(iax_circuit_key,
560                                         2*IAX_INIT_PACKET_COUNT,
561                                         G_ALLOC_ONLY);
562   iax_circuit_vals = g_mem_chunk_create(iax_circuit_key,
563                                         2*IAX_INIT_PACKET_COUNT,
564                                         G_ALLOC_ONLY);
565
566   iax_call_datas = g_mem_chunk_create(iax_call_data,
567                                       IAX_INIT_PACKET_COUNT,
568                                       G_ALLOC_ONLY);
569   circuitcount = 0;
570 }
571
572
573
574 /* creates a new CT_IAX2 circuit with a specified circuit id for a call
575  *
576  * typically a call has up to three associated circuits: an original source, an
577  * original destination, and the result of a transfer.
578  *
579  * For each endpoint, a CT_IAX2 circuit is created and added to the call_data
580  * by this function
581  *
582  * 'reversed' should be true if this end is the one which would have _received_
583  * the NEW packet, or it is an endpoint to which the 'destination' is being
584  * transferred.
585  *
586  */
587 static circuit_t *iax2_new_circuit_for_call(guint circuit_id, guint framenum, iax_call_data *iax_call,
588                                             gboolean reversed)
589 {
590   circuit_t *res;
591   
592   if(( reversed && iax_call->n_reverse_circuit_ids >= IAX_MAX_TRANSFERS) ||
593      ( !reversed && iax_call->n_forward_circuit_ids >= IAX_MAX_TRANSFERS)) {
594     g_warning("Too many transfers for iax_call");
595     return NULL;
596   }
597   
598   res = circuit_new(CT_IAX2,
599                     circuit_id,
600                     framenum );
601
602   circuit_add_proto_data(res, proto_iax2, iax_call);
603         
604   if( reversed )
605     iax_call -> reverse_circuit_ids[iax_call->n_reverse_circuit_ids++] = circuit_id;
606   else
607     iax_call -> forward_circuit_ids[iax_call->n_forward_circuit_ids++] = circuit_id;
608
609   return res;
610 }
611
612
613 /* returns true if this circuit id is a "forward" circuit for this call: ie, it
614  * is the point which _sent_ the original 'NEW' packet, or a point to which that
615  * end was subsequently transferred */
616 static gboolean is_forward_circuit(guint circuit_id,
617                                    const iax_call_data *iax_call)
618 {
619   guint i;
620   for(i=0;i<iax_call->n_forward_circuit_ids;i++){
621     if(circuit_id == iax_call->forward_circuit_ids[i])
622       return TRUE;
623   }
624   return FALSE;
625 }
626
627 /* returns true if this circuit id is a "reverse" circuit for this call: ie, it
628  * is the point which _received_ the original 'NEW' packet, or a point to which that
629  * end was subsequently transferred */
630 static gboolean is_reverse_circuit(guint circuit_id,
631                                    const iax_call_data *iax_call)
632 {
633   guint i;
634   for(i=0;i<iax_call->n_reverse_circuit_ids;i++){
635     if(circuit_id == iax_call->reverse_circuit_ids[i])
636       return TRUE;
637   }
638   return FALSE;
639 }
640
641
642 static iax_call_data *iax_lookup_call_from_dest( guint src_circuit_id,
643                                                  guint dst_circuit_id,
644                                                  guint framenum,
645                                                  gboolean *reversed_p)
646 {
647   circuit_t *dst_circuit;
648   iax_call_data * iax_call;
649   gboolean reversed = FALSE;
650   
651   dst_circuit = find_circuit( CT_IAX2,
652                               dst_circuit_id,
653                               framenum );
654
655   if( !dst_circuit ) {
656 #ifdef DEBUG_HASHING
657     g_message( "++ destination circuit not found, must have missed NEW packet" );
658 #endif
659     if( reversed_p )
660       *reversed_p = FALSE;
661     return NULL;
662   }
663
664 #ifdef DEBUG_HASHING
665   g_message( "++ found destination circuit" );
666 #endif
667       
668   iax_call = (iax_call_data *)circuit_get_proto_data(dst_circuit,proto_iax2);
669
670   /* there's no way we can create a CT_IAX2 circuit without adding
671      iax call data to it; assert this */
672   DISSECTOR_ASSERT(iax_call);
673
674   if( is_forward_circuit(dst_circuit_id, iax_call )) {
675 #ifdef DEBUG_HASHING
676     g_message( "++ destination circuit matches forward_circuit_id of call, "
677                "therefore packet is reversed" );
678 #endif
679
680     reversed = TRUE;
681
682     if( iax_call -> n_reverse_circuit_ids == 0 ) {
683       /* we are going in the reverse direction, and this call
684          doesn't have a reverse circuit associated with it.
685          create one now. */
686 #ifdef DEBUG_HASHING
687       g_message( "++ reverse_circuit_id of call is zero, need to create a "
688                  "new reverse circuit for this call" );
689 #endif
690
691       iax2_new_circuit_for_call( src_circuit_id, framenum, iax_call, TRUE );
692 #ifdef DEBUG_HASHING
693       g_message( "++ done" );
694 #endif
695     } else if( !is_reverse_circuit(src_circuit_id, iax_call )) {
696       g_warning( "IAX Packet %u from circuit ids %u->%u "
697                  "conflicts with earlier call with circuit ids %u->%u",
698                  framenum,
699                  src_circuit_id,dst_circuit_id,
700                  iax_call->forward_circuit_ids[0],
701                  iax_call->reverse_circuit_ids[0]);
702       return NULL;
703     }
704   } else if ( is_reverse_circuit(dst_circuit_id, iax_call)) {
705 #ifdef DEBUG_HASHING
706     g_message( "++ destination circuit matches reverse_circuit_id of call, "
707                "therefore packet is forward" );
708 #endif
709
710     reversed = FALSE;
711     if( !is_forward_circuit(src_circuit_id, iax_call)) {
712       g_warning( "IAX Packet %u from circuit ids %u->%u "
713                  "conflicts with earlier call with circuit ids %u->%u",
714                  framenum,
715                  src_circuit_id,dst_circuit_id,
716                  iax_call->forward_circuit_ids[0],
717                  iax_call->reverse_circuit_ids[0]);
718       if( reversed_p )
719         *reversed_p = FALSE;
720       return NULL;
721     }
722   } else {
723     DISSECTOR_ASSERT_NOT_REACHED();
724   }
725
726   if( reversed_p )
727     *reversed_p = reversed;
728
729   return iax_call;
730 }
731
732   
733 /* looks up an iax_call for this packet */
734 static iax_call_data *iax_lookup_call( packet_info *pinfo, 
735                                        guint32 scallno,
736                                        guint32 dcallno,
737                                        gboolean *reversed_p)
738 {
739   gboolean reversed = FALSE;
740   iax_call_data *iax_call = NULL;
741   guint src_circuit_id;
742
743 #ifdef DEBUG_HASHING
744   g_message( "++ iax_lookup_circuit_details: Looking up circuit for frame %u, "
745              "from {%s:%u:%u} to {%s:%u:%u}", pinfo->fd->num,
746              address_to_str(&pinfo->src),pinfo->srcport,scallno,
747              address_to_str(&pinfo->dst),pinfo->destport,dcallno);
748 #endif
749
750
751   src_circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
752                                       pinfo->srcport,scallno);
753
754
755   /* the most reliable indicator of call is the destination callno, if
756      we have one */
757   if( dcallno != 0 ) {
758     guint dst_circuit_id;
759 #ifdef DEBUG_HASHING
760     g_message( "++ dcallno non-zero, looking up destination circuit" );
761 #endif
762
763     dst_circuit_id = iax_circuit_lookup(&pinfo->dst,pinfo->ptype,
764                                         pinfo->destport,dcallno);
765
766     iax_call = iax_lookup_call_from_dest(src_circuit_id, dst_circuit_id,
767                                          pinfo->fd->num, &reversed);
768   } else {
769     circuit_t *src_circuit;
770
771     /* in all other circumstances, the source circuit should already
772      * exist: its absense indicates that we missed the all-important NEW
773      * packet.
774      */
775
776     src_circuit = find_circuit( CT_IAX2,
777                             src_circuit_id,
778                             pinfo->fd->num );
779
780     if( src_circuit ) {
781       iax_call = (iax_call_data *)circuit_get_proto_data(src_circuit,proto_iax2);
782
783       /* there's no way we can create a CT_IAX2 circuit without adding
784          iax call data to it; assert this */
785       DISSECTOR_ASSERT(iax_call);
786
787       if( is_forward_circuit(src_circuit_id,iax_call))
788         reversed = FALSE;
789       else if(is_reverse_circuit(src_circuit_id,iax_call))
790         reversed = TRUE;
791       else {
792         /* there's also no way we can attach an iax_call_data to a circuit
793            without the circuit being either the forward or reverse circuit
794            for that call; assert this too.
795         */
796         DISSECTOR_ASSERT_NOT_REACHED();
797       }
798     }
799   }
800
801   if(reversed_p)
802     *reversed_p = reversed;
803
804 #ifdef DEBUG_HASHING
805   if( iax_call ) {
806     g_message( "++ Found call for packet: id %u, reversed=%c", iax_call->iax_forward_circuit_ids[0], reversed?'1':'0' );
807   } else {
808     g_message( "++ Call not found. Must have missed the NEW packet?" );
809   }
810 #endif
811   
812   return iax_call;
813 }
814
815
816 /* handles a NEW packet by creating a new iax call and forward circuit.
817    the reverse circuit is not created until the ACK is received and
818    is created by iax_lookup_circuit_details. */
819 static iax_call_data *iax_new_call( packet_info *pinfo, 
820                                     guint32 scallno)
821 {
822   iax_call_data *call;
823   guint circuit_id;
824     
825 #ifdef DEBUG_HASHING
826   g_message( "+ new_circuit: Handling NEW packet, frame %u", pinfo->fd->num );
827 #endif
828   
829   circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
830                                   pinfo->srcport,scallno);
831     
832   call = g_mem_chunk_alloc(iax_call_datas);
833   call -> dataformat = 0;
834   call -> src_codec = 0;
835   call -> dst_codec = 0;
836   call -> n_forward_circuit_ids = 0;
837   call -> n_reverse_circuit_ids = 0;
838   call -> subdissector = NULL;
839   call -> start_time.secs  = pinfo->fd->abs_secs;
840   call -> start_time.nsecs = (pinfo->fd->abs_usecs-1000) * 1000;
841
842   iax2_new_circuit_for_call(circuit_id,pinfo->fd->num,call,FALSE);
843
844   return call;
845 }
846     
847
848 /* ************************************************************************* */
849
850 /* per-packet data */
851 typedef struct iax_packet_data {
852   gboolean first_time; /* we're dissecting this packet for the first time; so
853                           things like codec and transfer requests should be
854                           propogated into the call data */
855   iax_call_data *call_data;
856   guint32 codec;
857   gboolean reversed;
858   nstime_t abstime;    /* the absolute time of this packet, based on its
859                         * timestamp and the NEW packet's time (-1 if unknown) */
860 } iax_packet_data;
861
862 static GMemChunk *iax_packets = NULL;
863
864 static iax_packet_data *iax_new_packet_data(iax_call_data *call, gboolean reversed)
865 {
866   iax_packet_data *p = g_mem_chunk_alloc(iax_packets);
867   p->first_time=TRUE;
868   p->call_data=call;
869   p->codec=0;
870   p->reversed=reversed;
871   p->abstime.secs=-1;
872   p->abstime.nsecs=-1;
873   return p;
874 }
875
876 static void  iax2_populate_pinfo_from_packet_data(packet_info *pinfo, const iax_packet_data * p)
877 {
878   /* info for subdissectors. We always pass on the original forward circuit,
879    * and steal the p2p_dir flag to indicate the direction */
880   if( p->call_data == NULL ) {
881      /* if we missed the NEW packet for this call, call_data will be null. it's
882       * tbd what the best thing to do here is. */
883     pinfo -> ctype = CT_NONE;
884   } else {
885     pinfo -> ctype = CT_IAX2;
886     pinfo -> circuit_id = (guint32)p->call_data->forward_circuit_ids[0];
887     pinfo -> p2p_dir = p->reversed?P2P_DIR_RECV:P2P_DIR_SENT;
888
889     if (check_col (pinfo->cinfo, COL_CIRCUIT_ID)) {
890       col_set_str (pinfo->cinfo, COL_CIRCUIT_ID, "" );
891       col_add_fstr(pinfo->cinfo, COL_CIRCUIT_ID, "%u", pinfo->circuit_id);
892     }
893     if (check_col (pinfo->cinfo, COL_IF_DIR))
894       col_set_str (pinfo->cinfo, COL_IF_DIR, p->reversed ? "rev" : "fwd" );
895   }
896 }
897
898
899 /* ************************************************************************* */
900
901 /* this is passed up from the IE dissector to the main dissector */
902 typedef struct
903 {
904   address peer_address;
905   port_type peer_ptype;
906   guint32 peer_port;
907   guint32 peer_callno;
908   guint32 dataformat;
909 } iax2_ie_data;
910
911
912 static guint32 dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
913                                 guint16 scallno,
914                                 packet_info * pinfo,
915                                 proto_tree * iax2_tree,
916                                 proto_tree * main_tree);
917
918
919 static guint32 dissect_minipacket (tvbuff_t * tvb, guint32 offset, 
920                                 guint16 scallno,
921                                 packet_info * pinfo,
922                                 proto_tree * iax2_tree,
923                                 proto_tree * main_tree);
924
925 static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset, 
926                                         guint16 scallno,
927                                         packet_info * pinfo,
928                                         proto_tree * iax2_tree,
929                                         proto_tree * main_tree);
930
931 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
932                             packet_info *pinfo, proto_tree *tree,
933                             guint32 ts, gboolean video,
934                             iax_packet_data *iax_packet);
935
936
937
938 static void
939 dissect_iax2 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
940 {
941   proto_item *iax2_item = NULL;
942   proto_tree *iax2_tree = NULL;
943   proto_tree *full_mini_subtree = NULL;
944   guint32 offset = 0, len;
945   guint16 scallno = 0;
946   guint16 stmp;
947   packet_type type;
948
949   /* set up the protocol and info fields in the summary pane */
950   if (check_col (pinfo->cinfo, COL_PROTOCOL))
951     {
952       col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2);
953     }
954   if (check_col (pinfo->cinfo, COL_INFO))
955     {
956       col_clear (pinfo->cinfo, COL_INFO);
957     }
958
959   /* add the 'iax2' tree to the main tree */
960   if (tree)
961     {
962       iax2_item = proto_tree_add_item (tree, proto_iax2, tvb, offset, -1, FALSE);
963       iax2_tree = proto_item_add_subtree (iax2_item, ett_iax2);
964     }
965
966   stmp = tvb_get_ntohs(tvb, offset);
967   if( stmp == 0 ) {
968     /* starting with 0x0000 indicates either a mini video packet or a 'meta'
969      * packet, whatever that means */
970     offset+=2;
971     stmp = tvb_get_ntohs(tvb, offset);
972     if( stmp & 0x8000 ) {
973       /* mini video packet */
974       type = IAX2_MINI_VIDEO_PACKET;
975       scallno = stmp & 0x7FFF;
976       offset += 2;
977     }
978     else {
979       type = IAX2_META_PACKET;
980     }
981   } else {
982     /* The source call/fullpacket flag is common to both mini and full packets */
983     scallno = tvb_get_ntohs(tvb, offset);
984     offset += 2;
985     if( scallno & 0x8000 )
986       type = IAX2_FULL_PACKET;
987     else {
988       type = IAX2_MINI_VOICE_PACKET;
989     }
990     scallno &= 0x7FFF;
991   }
992
993   if( tree ) {
994     proto_item *full_mini_base;
995
996     full_mini_base = proto_tree_add_uint(iax2_tree, hf_iax2_packet_type, tvb, 0, offset, type);
997     full_mini_subtree = proto_item_add_subtree(full_mini_base, ett_iax2_full_mini_subtree);
998
999     if( scallno != 0 )
1000       proto_tree_add_item (full_mini_subtree, hf_iax2_scallno, tvb, offset-2, 2, FALSE);
1001   }
1002
1003   switch( type ) {
1004     case IAX2_FULL_PACKET:
1005       len = dissect_fullpacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1006       break;
1007     case IAX2_MINI_VOICE_PACKET:
1008       len = dissect_minipacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1009       break;
1010     case IAX2_MINI_VIDEO_PACKET:
1011       len = dissect_minivideopacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
1012       break;
1013     case IAX2_META_PACKET:
1014       /* not implemented yet */
1015       len = 0;
1016       break;
1017     default:
1018       len = 0;
1019   }
1020
1021   /* update the 'length' of the main IAX2 header field so that it covers just the headers,
1022      not the audio data. */
1023   proto_item_set_len(iax2_item, len);
1024 }
1025
1026 static proto_item *dissect_datetime_ie(tvbuff_t *tvb, guint32 offset, proto_tree *ies_tree)
1027 {
1028   struct tm tm;
1029   guint32 ie_val;
1030   nstime_t datetime;
1031     
1032   proto_tree_add_item (ies_tree, hf_iax2_ies[IAX_IE_DATETIME], tvb, offset + 2, 4, FALSE);
1033   ie_val = tvb_get_ntohl(tvb, offset+2);
1034
1035   /* who's crazy idea for a time encoding was this? */
1036   tm.tm_sec  = (ie_val & 0x1f) << 1;
1037   tm.tm_min  = (ie_val>>5) & 0x3f;
1038   tm.tm_hour = (ie_val>>11) & 0x1f;
1039   tm.tm_mday = (ie_val>>16) & 0x1f;
1040   tm.tm_mon  = ((ie_val>>21) & 0xf) - 1;
1041   tm.tm_year = ((ie_val>>25) & 0x7f) + 100;
1042   tm.tm_isdst= -1; /* there's no info on whether DST was in force; assume it's
1043                     * the same as currently */
1044
1045   datetime.secs = mktime(&tm);
1046   datetime.nsecs = 0;
1047   return proto_tree_add_time (ies_tree, hf_iax2_ie_datetime, tvb, offset+2, 4, &datetime);
1048 }
1049   
1050
1051 /* dissect the information elements in an IAX frame. Returns the updated offset */
1052 static guint32 dissect_ies (tvbuff_t * tvb, guint32 offset,
1053                             proto_tree * iax_tree,
1054                             iax2_ie_data *ie_data)
1055 {
1056   DISSECTOR_ASSERT(ie_data);
1057   
1058   while (offset < tvb_reported_length (tvb)) {
1059
1060     int ies_type = tvb_get_guint8(tvb, offset);
1061     int ies_len = tvb_get_guint8(tvb, offset + 1);
1062
1063     if( iax_tree ) {
1064       proto_item *ti, *ie_item = NULL;
1065       proto_tree *ies_tree;
1066       int ie_hf = hf_iax2_ies[ies_type];
1067
1068       ti = proto_tree_add_text(iax_tree, tvb, offset, ies_len+2, " " );
1069
1070       ies_tree = proto_item_add_subtree(ti, ett_iax2_ie);
1071       
1072       proto_tree_add_text(ies_tree, tvb, offset, 1, "IE id: %s (0x%02X)",
1073                           val_to_str(ies_type, iax_ies_type, "Unknown"),
1074                           ies_type);
1075
1076       proto_tree_add_text(ies_tree, tvb, offset+1, 1, "Length: %u",ies_len);
1077
1078
1079       /* hf_iax2_ies[] is an array, indexed by IE number, of header-fields, one
1080          per IE. Apart from a couple of special cases which require more
1081          complex decoding, we can just look up an entry from the array, and add
1082          the relevant item.
1083       */
1084          
1085       switch (ies_type) {
1086         case IAX_IE_DATETIME:
1087           ie_item = dissect_datetime_ie(tvb,offset,ies_tree);
1088           break;
1089
1090         
1091         case IAX_IE_CAPABILITY:
1092         {
1093           proto_tree *codec_tree;
1094
1095           if (ies_len != 4) THROW(ReportedBoundsError);
1096
1097           ie_item =
1098             proto_tree_add_item (ies_tree, ie_hf,
1099                                  tvb, offset + 2, ies_len, FALSE);
1100           codec_tree =
1101             proto_item_add_subtree (ie_item, ett_iax2_codecs);
1102               
1103           proto_tree_add_item(codec_tree, hf_iax2_cap_g723_1, tvb, offset + 2, ies_len, FALSE );
1104           proto_tree_add_item(codec_tree, hf_iax2_cap_gsm, tvb, offset + 2, ies_len, FALSE );
1105           proto_tree_add_item(codec_tree, hf_iax2_cap_ulaw, tvb, offset + 2, ies_len, FALSE );
1106           proto_tree_add_item(codec_tree, hf_iax2_cap_alaw, tvb, offset + 2, ies_len, FALSE );
1107           proto_tree_add_item(codec_tree, hf_iax2_cap_g726, tvb, offset + 2, ies_len, FALSE );
1108           proto_tree_add_item(codec_tree, hf_iax2_cap_adpcm, tvb, offset + 2, ies_len, FALSE );
1109           proto_tree_add_item(codec_tree, hf_iax2_cap_slinear, tvb, offset + 2, ies_len, FALSE );
1110           proto_tree_add_item(codec_tree, hf_iax2_cap_lpc10, tvb, offset + 2, ies_len, FALSE );
1111           proto_tree_add_item(codec_tree, hf_iax2_cap_g729a, tvb, offset + 2, ies_len, FALSE );
1112           proto_tree_add_item(codec_tree, hf_iax2_cap_speex, tvb, offset + 2, ies_len, FALSE );
1113           proto_tree_add_item(codec_tree, hf_iax2_cap_ilbc, tvb, offset + 2, ies_len, FALSE );
1114           proto_tree_add_item(codec_tree, hf_iax2_cap_jpeg, tvb, offset + 2, ies_len, FALSE );
1115           proto_tree_add_item(codec_tree, hf_iax2_cap_png, tvb, offset + 2, ies_len, FALSE );
1116           proto_tree_add_item(codec_tree, hf_iax2_cap_h261, tvb, offset + 2, ies_len, FALSE );
1117           proto_tree_add_item(codec_tree, hf_iax2_cap_h263, tvb, offset + 2, ies_len, FALSE );
1118           break;
1119         }
1120
1121         case IAX_IE_APPARENT_ADDR:
1122         {
1123           proto_tree *sockaddr_tree = NULL;
1124           guint16 family;
1125
1126           ie_item = proto_tree_add_text(ies_tree, tvb, offset + 2, 16, "Apparent Address");
1127           sockaddr_tree = proto_item_add_subtree(ie_item, ett_iax2_ies_apparent_addr);
1128
1129           /* the family is little-endian. That's probably broken, given
1130              everything else is big-endian, but that's not our fault.
1131           */
1132           family = tvb_get_letohs(tvb, offset+2);
1133           proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINFAMILY, tvb, offset + 2, 2, family);
1134               
1135           switch( family ) {
1136             /* these come from linux/socket.h */
1137             case 2: /* AF_INET */
1138             {
1139               /* the ip address is big-endian, but then so is address.data */
1140               SET_ADDRESS(&ie_data->peer_address,AT_IPv4,4,tvb_get_ptr(tvb,offset+6,4));
1141               
1142               /* IAX is always over UDP */
1143               ie_data->peer_ptype = PT_UDP;
1144               ie_data->peer_port = tvb_get_ntohs(tvb, offset+4);
1145               proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINPORT, tvb, offset + 4, 2, ie_data->peer_port);
1146               proto_tree_add_ipv4(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINADDR, tvb, offset + 6, 4, *(guint32 *)(&ie_data->peer_address.data));
1147               break;
1148             }
1149
1150             default:
1151               g_warning("Not supported in IAX dissector: peer address family of %u", family);
1152               break;
1153           }
1154           break;
1155         }
1156               
1157         case IAX_IE_DATAFORMAT:
1158           if (ies_len != 4) THROW(ReportedBoundsError);
1159           ie_item = proto_tree_add_item (ies_tree, ie_hf, tvb,
1160                                offset + 2, ies_len, FALSE);
1161           ie_data -> dataformat = tvb_get_ntohl(tvb, offset+2);
1162           break;
1163
1164         default:
1165           if( ie_hf != -1 ) {
1166             /* throw an error if the IE isn't the expected length */
1167             gint explen = ftype_length(proto_registrar_get_nth(ie_hf)->type);
1168             if(explen != 0 && ies_len != explen)
1169               THROW(ReportedBoundsError);
1170             ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, FALSE);
1171           } else {
1172             /* we don't understand this ie: add a generic one */
1173             guint32 value;
1174             const guint8 *ptr;
1175             const guint8 *ie_name = val_to_str(ies_type, iax_ies_type, "Unknown");
1176           
1177             switch(ies_len) {
1178               case 1:
1179                 value = tvb_get_guint8(tvb, offset + 2);
1180                 ie_item =
1181                   proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTE,
1182                                              tvb, offset+2, 1, value,
1183                                              "%s: %#02x", ie_name, value );
1184                 break;
1185           
1186               case 2:
1187                 value = tvb_get_ntohs(tvb, offset + 2);
1188                 ie_item =
1189                   proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I16,
1190                                              tvb, offset+2, 2, value,
1191                                              "%s: %#04x", ie_name, value );
1192                 break;
1193         
1194               case 4:
1195                 value = tvb_get_ntohl(tvb, offset + 2);
1196                 ie_item =
1197                   proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I32,
1198                                              tvb, offset+2, 4, value,
1199                                              "%s: %#08x", ie_name, value );
1200                 break;
1201
1202               default:
1203                 ptr = tvb_get_ptr(tvb, offset + 2, ies_len);
1204                 ie_item =
1205                   proto_tree_add_string_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTES,
1206                                                tvb, offset+2, ies_len, ptr,
1207                                                "%s: %s", ie_name, ptr );
1208                 break;
1209             }
1210           }
1211           break;
1212       }
1213
1214       /* by now, we *really* ought to have added an item */
1215       DISSECTOR_ASSERT(ie_item != NULL);
1216
1217       /* Retrieve the text from the item we added, and append it to the main IE
1218        * item */
1219       if(!PROTO_ITEM_IS_HIDDEN(ti)) {
1220         field_info *ie_finfo = PITEM_FINFO(ie_item);
1221         
1222         /* if the representation of the item has already been set, use that;
1223            else we have to allocate a block to put the text into */
1224         if( ie_finfo -> rep != NULL ) 
1225           proto_item_set_text(ti, "Information Element: %s",
1226                               ie_finfo->rep->representation);
1227         else {
1228           guint8 *ie_val = NULL;
1229           ie_val = g_malloc(ITEM_LABEL_LENGTH);
1230           proto_item_fill_label(ie_finfo, ie_val);
1231           proto_item_set_text(ti, "Information Element: %s",
1232                               ie_val);
1233           g_free(ie_val);
1234         }
1235       }
1236     }
1237
1238     offset += ies_len + 2;
1239   }
1240   return offset;
1241 }
1242
1243 static guint32 uncompress_subclass(guint8 csub)
1244 {
1245   /* If the SC_LOG flag is set, return 2^csub otherwise csub */
1246   if (csub & 0x80) {
1247     /* special case for 'compressed' -1 */
1248     if (csub == 0xff)
1249       return (guint32)-1;
1250     else
1251       return 1 << (csub & 0x1F);
1252   }
1253   else
1254     return (guint32)csub;
1255 }
1256
1257 /* returns the new offset */
1258 static guint32 dissect_iax2_command(tvbuff_t * tvb, guint32 offset,
1259                                     packet_info * pinfo, proto_tree *tree,
1260                                     iax_packet_data *iax_packet)
1261 {
1262   guint8 csub = tvb_get_guint8(tvb, offset);
1263   guint8 address_data[MAX_ADDRESS];
1264   iax2_ie_data ie_data = {{AT_NONE,0,address_data},0,0,0,(guint32)-1};
1265   iax_call_data *iax_call = iax_packet -> call_data;
1266   
1267   /* add the subclass */
1268   proto_tree_add_uint (tree, hf_iax2_iax_csub, tvb, offset, 1, csub);
1269   offset++;
1270
1271   if (check_col (pinfo->cinfo, COL_INFO))
1272     col_append_fstr (pinfo->cinfo, COL_INFO, " %s", 
1273                      val_to_str (csub, iax_iax_subclasses, "unknown (0x%02x)"));
1274
1275   if (offset >= tvb_reported_length (tvb))
1276     return offset;
1277   
1278   offset += dissect_ies(tvb, offset, tree, &ie_data);
1279
1280   /* if this is a data call, set up a subdissector for the circuit */
1281   if(iax_call && ie_data.dataformat != (guint32)-1 && iax_call -> subdissector == NULL) {
1282     iax_call -> subdissector = dissector_get_port_handle(iax2_dataformat_dissector_table, ie_data.dataformat );
1283     iax_call -> dataformat = ie_data.dataformat;
1284   }
1285
1286   /* if this is a transfer request, record it in the call data */
1287   if( csub == IAX_COMMAND_TXREQ && iax_packet -> first_time ) {
1288     if( ie_data.peer_address.type != AT_NONE && ie_data.peer_callno != 0 ) {
1289       guint tx_circuit = iax_circuit_lookup(&ie_data.peer_address,
1290                                             ie_data.peer_ptype,
1291                                             ie_data.peer_port,
1292                                             ie_data.peer_callno);
1293
1294 #if 0
1295       g_message("found transfer request for call %u->%u, to new id %u",
1296                 iax_call->forward_circuit_ids[0],
1297                 iax_call->reverse_circuit_ids[0],
1298                 tx_circuit);
1299 #endif
1300       
1301       iax2_new_circuit_for_call(tx_circuit,pinfo->fd->num,iax_call,iax_packet->reversed);
1302     }
1303   }
1304   
1305   return offset;
1306 }
1307
1308 static void iax2_add_ts_fields(packet_info * pinfo, proto_tree * iax2_tree, iax_packet_data *iax_packet, guint16 shortts)
1309 {
1310   guint32 longts = shortts;
1311   nstime_t ts;
1312   proto_item *item;
1313     
1314   if(iax_packet->call_data == NULL) {
1315     /* no call info for this frame; perhaps we missed the NEW packet */
1316     return;
1317   }
1318
1319   if(iax_packet->abstime.secs == -1) {
1320     time_t start_secs = iax_packet->call_data->start_time.secs;
1321     guint32 abs_secs = start_secs + longts/1000;
1322
1323     /* deal with short timestamps by assuming that packets are never more than
1324      * 16 seconds late */
1325     while(abs_secs < pinfo->fd->abs_secs - 16) {
1326       longts += 32768;
1327       abs_secs = start_secs + longts/1000;
1328     }
1329
1330     iax_packet->abstime.secs=abs_secs;
1331     iax_packet->abstime.nsecs=iax_packet->call_data->start_time.nsecs + (longts % 1000) * 1000000;
1332     if(iax_packet->abstime.nsecs >= 1000000000) {
1333       iax_packet->abstime.nsecs -= 1000000000;
1334       iax_packet->abstime.secs ++;
1335     }
1336   }
1337   
1338   item = proto_tree_add_time(iax2_tree, hf_iax2_absts, NULL, 0, 0, &iax_packet->abstime);
1339   PROTO_ITEM_SET_GENERATED(item);
1340
1341   ts.secs  = pinfo->fd->abs_secs;
1342   ts.nsecs = pinfo->fd->abs_usecs * 1000;
1343   get_timedelta(&ts, &ts, &iax_packet->abstime);
1344   
1345   item = proto_tree_add_time(iax2_tree, hf_iax2_lateness, NULL, 0, 0, &ts);
1346   PROTO_ITEM_SET_GENERATED(item);
1347 }
1348
1349 /* returns the new offset */
1350 static guint32
1351 dissect_fullpacket (tvbuff_t * tvb, guint32 offset, 
1352                     guint16 scallno,
1353                     packet_info * pinfo, proto_tree * iax2_tree,
1354                     proto_tree * main_tree)
1355 {
1356   guint32 retransmission = 0;
1357   guint16 dcallno;
1358   guint32 ts;
1359   guint8 type;
1360   guint8 csub;
1361   guint32 codec;
1362
1363   proto_tree *packet_type_tree = NULL;
1364   iax_call_data *iax_call;
1365   iax_packet_data *iax_packet;
1366   gboolean reversed;
1367   gboolean rtp_marker;
1368
1369   /*
1370    * remove the top bit for retransmission detection 
1371    */
1372   dcallno = tvb_get_ntohs(tvb, offset);
1373   retransmission = dcallno & 0x8000;
1374   dcallno = dcallno & 0x7FFF;
1375   ts = tvb_get_ntohl(tvb, offset+2);
1376   type = tvb_get_guint8(tvb, offset + 8);
1377   csub = tvb_get_guint8(tvb, offset + 9);
1378
1379   /* see if we've seen this packet before */
1380   iax_packet = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
1381   if( !iax_packet ) {
1382     /* if not, find or create an iax_call info structure for this IAX session. */
1383
1384     if( type == AST_FRAME_IAX && csub == IAX_COMMAND_NEW ) {
1385       /* NEW packets start a new call */
1386       iax_call = iax_new_call(pinfo,scallno);
1387       reversed = FALSE;
1388     } else {
1389       iax_call = iax_lookup_call(pinfo, scallno, dcallno,
1390                                  &reversed);
1391     }
1392
1393     iax_packet = iax_new_packet_data(iax_call, reversed);
1394     p_add_proto_data(pinfo->fd,proto_iax2,iax_packet);
1395   } else {
1396     iax_call = iax_packet->call_data;
1397     reversed = iax_packet->reversed;
1398   }
1399
1400   iax2_populate_pinfo_from_packet_data(pinfo, iax_packet);
1401   
1402   if( iax2_tree ) {
1403       proto_item *packet_type_base;
1404
1405       proto_tree_add_item (iax2_tree, hf_iax2_dcallno, tvb, offset, 2, FALSE );
1406
1407       proto_tree_add_boolean(iax2_tree, hf_iax2_retransmission, tvb, offset, 2, FALSE );
1408
1409       if( iax_call ) {
1410         proto_item *item = 
1411           proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1412                              iax_call->forward_circuit_ids[0] );
1413         PROTO_ITEM_SET_GENERATED(item);
1414       }
1415
1416       proto_tree_add_uint (iax2_tree, hf_iax2_ts, tvb, offset+2, 4, ts);
1417       iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1418
1419       proto_tree_add_item (iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1,
1420                            FALSE);
1421
1422       proto_tree_add_item (iax2_tree, hf_iax2_iseqno, tvb, offset+7, 1,
1423                            FALSE);
1424       packet_type_base = proto_tree_add_uint (iax2_tree, hf_iax2_type, tvb,
1425                                               offset+8, 1, type);
1426
1427       /* add the type-specific subtree */
1428       packet_type_tree = proto_item_add_subtree (packet_type_base, ett_iax2_type);
1429   }
1430
1431   /* add frame type to info line */
1432   if (check_col (pinfo->cinfo, COL_INFO)) {
1433     col_add_fstr (pinfo->cinfo, COL_INFO, "%s, source call# %d, timestamp %ums",
1434                   val_to_str (type, iax_frame_types, "Unknown (0x%02x)"),
1435                   scallno, ts);
1436   }
1437
1438   switch( type ) {
1439   case AST_FRAME_IAX:
1440     offset=dissect_iax2_command(tvb,offset+9,pinfo,packet_type_tree,iax_packet);
1441     break;
1442     
1443   case AST_FRAME_DTMF:
1444     proto_tree_add_item (packet_type_tree, hf_iax2_dtmf_csub, tvb, offset+9, 1, FALSE);
1445     offset += 10;
1446
1447     if (check_col (pinfo->cinfo, COL_INFO))
1448       col_append_fstr (pinfo->cinfo, COL_INFO, " digit %c", csub );
1449     break;
1450
1451   case AST_FRAME_CONTROL:
1452     /* add the subclass */
1453     proto_tree_add_uint (packet_type_tree, hf_iax2_cmd_csub, tvb,
1454                          offset+9, 1, csub);
1455     offset += 10;
1456
1457     if (check_col (pinfo->cinfo, COL_INFO))
1458       col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
1459                     val_to_str (csub, iax_cmd_subclasses, "unknown (0x%02x)"));
1460     break;
1461
1462   case AST_FRAME_VOICE:
1463     /* add the codec */
1464     iax_packet -> codec = codec = uncompress_subclass(csub);
1465
1466     if( packet_type_tree ) {
1467       proto_tree_add_item (packet_type_tree, hf_iax2_voice_csub, tvb, offset+9, 1, FALSE);
1468       proto_tree_add_uint (packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, codec);
1469     }
1470
1471     offset += 10;
1472
1473     if( iax_call ) {
1474       if( reversed ) {
1475         iax_call->dst_codec = codec;
1476       } else {
1477         iax_call->src_codec = codec;
1478       }
1479     }
1480
1481     dissect_payload(tvb, offset, pinfo, main_tree, ts, FALSE,iax_packet);
1482     break;
1483
1484   case AST_FRAME_VIDEO:
1485     /* bit 6 of the csub is used to represent the rtp 'marker' bit */
1486     rtp_marker = csub & 0x40 ? TRUE:FALSE;
1487     iax_packet -> codec = codec = uncompress_subclass((guint8) (csub & ~40));
1488
1489     if( packet_type_tree ) {
1490       proto_tree_add_item (packet_type_tree, hf_iax2_video_csub, tvb, offset+9, 1, FALSE);
1491       proto_tree_add_item (packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, FALSE);
1492       proto_tree_add_uint (packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, codec);
1493     }
1494
1495     offset += 10;
1496
1497     if( iax_call && iax_packet -> first_time ) {
1498       if( reversed ) {
1499         iax_call->dst_vformat = codec;
1500       } else {
1501         iax_call->src_vformat = codec;
1502       }
1503     }
1504
1505     if( rtp_marker && check_col (pinfo->cinfo, COL_INFO))
1506       col_append_fstr (pinfo->cinfo, COL_INFO, ", Mark" );
1507
1508
1509     dissect_payload(tvb, offset, pinfo, main_tree, ts, TRUE, iax_packet);
1510     break;
1511
1512
1513   default:
1514     proto_tree_add_uint (packet_type_tree, hf_iax2_csub, tvb, offset+9,
1515                          1, csub);
1516     offset += 10;
1517
1518     if (check_col (pinfo->cinfo, COL_INFO))
1519       col_append_fstr (pinfo->cinfo, COL_INFO, " subclass %d", csub );
1520     break;
1521   }
1522
1523   /* next time we come to parse this packet, don't propogate the codec into the
1524    * call_data */
1525   iax_packet->first_time = FALSE;
1526   
1527   return offset;
1528 }
1529
1530 static iax_packet_data *iax2_get_packet_data_for_minipacket(packet_info * pinfo,
1531                                                             guint16 scallno,
1532                                                             gboolean video)
1533 {
1534   /* see if we've seen this packet before */
1535   iax_packet_data *p = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
1536
1537   if( !p ) {
1538     /* if not, find or create an iax_call info structure for this IAX session. */
1539     gboolean reversed;
1540     iax_call_data *iax_call;
1541
1542     iax_call = iax_lookup_call(pinfo, scallno, 0, &reversed);
1543
1544     p = iax_new_packet_data(iax_call,reversed);
1545     p_add_proto_data(pinfo->fd,proto_iax2,p);
1546
1547     /* set the codec for this frame to be whatever the last full frame used */
1548     if( iax_call ) {
1549      if( video ) 
1550         p->codec = reversed ? iax_call -> dst_vformat : iax_call -> src_vformat;
1551       else 
1552         p->codec = reversed ? iax_call -> dst_codec : iax_call -> src_codec;
1553     }
1554   }
1555
1556   iax2_populate_pinfo_from_packet_data(pinfo, p);
1557   return p;
1558 }
1559
1560
1561 static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
1562                                         guint16 scallno, packet_info * pinfo,
1563                                         proto_tree * iax2_tree, proto_tree *main_tree)
1564 {
1565   guint32 ts;
1566   iax_packet_data *iax_packet;
1567   gboolean rtp_marker;
1568   proto_item *item;
1569
1570   ts = tvb_get_ntohs(tvb, offset);
1571
1572   /* bit 15 of the ts is used to represent the rtp 'marker' bit */
1573   rtp_marker = ts & 0x8000 ? TRUE:FALSE;
1574   ts &= ~0x8000;
1575
1576   iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, TRUE);
1577
1578   if( iax2_tree ) {
1579     if( iax_packet->call_data ) {
1580       item = 
1581         proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1582                                     iax_packet->call_data->forward_circuit_ids[0] );
1583       PROTO_ITEM_SET_GENERATED(item);
1584     }
1585
1586     proto_tree_add_item (iax2_tree, hf_iax2_minividts, tvb, offset, 2, FALSE);
1587     iax2_add_ts_fields(pinfo, iax2_tree, iax_packet, (guint16)ts);
1588     proto_tree_add_item (iax2_tree, hf_iax2_minividmarker, tvb, offset, 2, FALSE);
1589   }
1590
1591   offset += 2;
1592   
1593   if (check_col (pinfo->cinfo, COL_INFO))
1594       col_add_fstr (pinfo->cinfo, COL_INFO, 
1595                     "Mini video packet, source call# %d, timestamp %ums%s",
1596                     scallno, ts, rtp_marker?", Mark":"");
1597
1598
1599   dissect_payload(tvb, offset, pinfo, main_tree, ts, TRUE, iax_packet);
1600
1601   /* next time we come to parse this packet, don't propogate the codec into the
1602    * call_data */
1603   iax_packet->first_time = FALSE;
1604   
1605   return offset;
1606 }
1607
1608 static guint32
1609 dissect_minipacket (tvbuff_t * tvb, guint32 offset, guint16 scallno, packet_info * pinfo, proto_tree * iax2_tree,
1610                     proto_tree *main_tree)
1611 {
1612   guint32 ts;
1613   iax_packet_data *iax_packet;
1614   proto_item *item;
1615
1616   ts = tvb_get_ntohs(tvb, offset);
1617
1618   iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, FALSE);
1619
1620   if( iax2_tree ) {
1621     if( iax_packet->call_data ) {
1622       item = proto_tree_add_uint (iax2_tree, hf_iax2_callno, tvb, 0, 4,
1623                                   iax_packet->call_data->forward_circuit_ids[0] );
1624       PROTO_ITEM_SET_GENERATED(item);
1625     }
1626
1627     proto_tree_add_uint (iax2_tree, hf_iax2_minits, tvb, offset, 2, ts);
1628     iax2_add_ts_fields(pinfo, iax2_tree, iax_packet,(guint16)ts);
1629   }
1630   
1631   offset += 2;
1632   
1633   if (check_col (pinfo->cinfo, COL_INFO))
1634       col_add_fstr (pinfo->cinfo, COL_INFO, 
1635                     "Mini packet, source call# %d, timestamp %ums",
1636                     scallno, ts);
1637
1638
1639   /* XXX fix the timestamp logic */
1640   dissect_payload(tvb, offset, pinfo, main_tree, ts, FALSE, iax_packet);
1641
1642
1643   /* next time we come to parse this packet, don't propogate the codec into the
1644    * call_data */
1645   iax_packet->first_time = FALSE;
1646   
1647   return offset;
1648 }
1649
1650 static void dissect_payload(tvbuff_t *tvb, guint32 offset,
1651                             packet_info *pinfo, proto_tree *tree,
1652                             guint32 ts, gboolean video,
1653                             iax_packet_data *iax_packet)
1654 {
1655   gboolean out_of_order = FALSE;
1656   tvbuff_t *sub_tvb;
1657   guint32 codec = iax_packet -> codec;
1658   iax_call_data *iax_call = iax_packet -> call_data;
1659
1660   /* keep compiler quiet */
1661   ts = ts;
1662
1663   if( offset >= tvb_reported_length (tvb)) {
1664     if (check_col (pinfo->cinfo, COL_INFO))
1665       col_append_fstr (pinfo->cinfo, COL_INFO, ", empty frame" );
1666     return;
1667   }
1668
1669   sub_tvb = tvb_new_subset(tvb, offset, -1, -1 );
1670
1671   /* XXX shouldn't pass through out-of-order packets. */
1672
1673   if (check_col (pinfo->cinfo, COL_INFO)) {
1674     if( !video && iax_call && iax_call -> dataformat != 0 ) {
1675       col_append_fstr (pinfo->cinfo, COL_INFO, ", data, format %s",
1676                        val_to_str (iax_call -> dataformat, 
1677                                    iax_dataformats, "unknown (0x%02x)"));
1678
1679       if( out_of_order )
1680         col_append_fstr (pinfo->cinfo, COL_INFO, " (out-of-order packet)");
1681     } else {
1682       col_append_fstr (pinfo->cinfo, COL_INFO, ", %s",
1683                        val_to_str (codec, codec_types, "unknown (0x%02x)"));
1684     }
1685   }
1686
1687   /* pass the rest of the block to a subdissector */
1688   if( !video && iax_call && iax_call->subdissector ) {
1689     call_dissector(iax_call->subdissector,sub_tvb, pinfo, tree);
1690     return;
1691   }
1692
1693   if( codec != 0 && dissector_try_port(iax2_codec_dissector_table, codec, sub_tvb, pinfo, tree ))
1694     return;
1695   
1696   /* we don't know how to dissect our data: dissect it as data */
1697   call_dissector(data_handle,sub_tvb, pinfo, tree);
1698 }
1699
1700 /*
1701  * Init routines
1702  */
1703
1704 /* called at the start of a capture. We should clear out our static, per-capture
1705  * data.
1706  */
1707
1708 static void
1709 iax_init_protocol(void)
1710 {
1711   iax_init_hash();
1712
1713   if (iax_packets)
1714     g_mem_chunk_destroy(iax_packets);
1715   iax_packets = g_mem_chunk_create(iax_packet_data,128,G_ALLOC_ONLY);
1716 }
1717
1718
1719 void
1720 proto_register_iax2 (void)
1721 {
1722   /* we use this for displaying which codecs are supported */
1723   static const true_false_string supported_strings = {
1724     "Supported",
1725     "Not supported"
1726   };
1727
1728   /* A header field is something you can search/filter on.
1729    * 
1730    * We create a structure to register our fields. It consists of an
1731    * array of hf_register_info structures, each of which are of the format
1732    * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1733    */
1734    
1735   static hf_register_info hf[] = {
1736
1737     {&hf_iax2_packet_type,
1738      {"Packet type", "iax2.packet_type", FT_UINT8, BASE_DEC, VALS(iax_packet_types), 0,
1739       "Full/minivoice/minivideo/meta packet",
1740       HFILL}},
1741
1742     {&hf_iax2_callno,
1743      {"Call identifier", "iax2.call", FT_UINT32, BASE_DEC, NULL, 0,
1744       "This is the identifier Ethereal assigns to identify this call. It does "
1745       "not correspond to any real field in the protocol", HFILL }},
1746
1747     {&hf_iax2_scallno,
1748      {"Source call", "iax2.src_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
1749       "src_call holds the number of this call at the packet source pbx",
1750       HFILL}},
1751
1752     /* FIXME could this be turned into a FRAMENUM field? */
1753     {&hf_iax2_dcallno,
1754      {"Destination call", "iax2.dst_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
1755       "dst_call holds the number of this call at the packet destination",
1756       HFILL}},
1757
1758     {&hf_iax2_retransmission,
1759      {"Retransmission", "iax2.retransmission", FT_BOOLEAN, 16,
1760       NULL, 0x8000,
1761       "retransmission is set if this packet is a retransmission of an earlier "
1762       "failed packet", HFILL}},
1763
1764     {&hf_iax2_ts,
1765      {"Timestamp", "iax2.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
1766       "timestamp is the time, in ms after the start of this call, at which "
1767       "this packet was transmitted",
1768       HFILL}},
1769
1770     {&hf_iax2_minits,
1771      {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x0,
1772       "timestamp is the time, in ms after the start of this call, at which "
1773       "this packet was transmitted",
1774       HFILL}},
1775
1776     {&hf_iax2_minividts,
1777      {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
1778       "timestamp is the time, in ms after the start of this call, at which "
1779       "this packet was transmitted",
1780       HFILL}},
1781
1782     {&hf_iax2_absts,
1783      {"Absolute Time", "iax2.abstime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
1784       "The absoulte time of this packet (calculated by adding the IAX timestamp to "
1785       " the start time of this call)",
1786       HFILL}},
1787
1788     {&hf_iax2_lateness,
1789      {"Lateness", "iax2.lateness", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
1790       "The lateness of this packet compared to its timestamp",
1791       HFILL}},
1792
1793     {&hf_iax2_minividmarker,
1794      {"Marker", "iax2.video.marker", FT_UINT16, BASE_DEC, NULL, 0x8000,
1795       "RTP end-of-frame marker",
1796       HFILL}},
1797
1798     {&hf_iax2_oseqno,
1799      {"Outbound seq.no.", "iax2.oseqno", FT_UINT16, BASE_DEC, NULL,
1800       0x0, 
1801       "oseqno is the sequence no of this packet. The first packet has "
1802       "oseqno==0, and subsequent packets increment the oseqno by 1",
1803       HFILL}},
1804
1805     {&hf_iax2_iseqno,
1806      {"Inbound seq.no.", "iax2.iseqno", FT_UINT16, BASE_DEC, NULL, 0x0,
1807       "iseqno is the sequence no of the last successfully recieved packet",
1808       HFILL}},
1809
1810     {&hf_iax2_type,
1811      {"Type", "iax2.type", FT_UINT8, BASE_DEC, VALS (iax_frame_types),
1812       0x0,
1813       "For full IAX2 frames, type is the type of frame",
1814       HFILL}},
1815
1816     {&hf_iax2_csub,
1817      {"Unknown subclass", "iax2.subclass", FT_UINT8, BASE_DEC, NULL, 0x0, 
1818       "Subclass of unknown type of full IAX2 frame",
1819       HFILL}},
1820
1821     {&hf_iax2_dtmf_csub,
1822      {"DTMF subclass (digit)", "iax2.dtmf.subclass", FT_STRINGZ, BASE_NONE, NULL, 0x0,
1823       "DTMF subclass gives the DTMF digit",
1824       HFILL}},
1825
1826     {&hf_iax2_cmd_csub,
1827      {"Control subclass", "iax2.control.subclass", FT_UINT8, BASE_DEC,
1828       VALS (iax_cmd_subclasses), 0x0, 
1829       "This gives the command number for a Control packet.", HFILL}},
1830
1831     {&hf_iax2_iax_csub,
1832      {"IAX subclass", "iax2.iax.subclass", FT_UINT8, BASE_DEC,
1833       VALS (iax_iax_subclasses),
1834       0x0, 
1835       "IAX subclass gives the command number for IAX signalling packets", HFILL}},
1836
1837     {&hf_iax2_voice_csub,
1838      {"Voice Subclass (compressed codec no)", "iax2.voice.subclass", FT_UINT8, BASE_DEC, NULL, 0x0, 
1839       "Voice Subclass (compressed codec no)",
1840       HFILL}},
1841
1842     {&hf_iax2_voice_codec,
1843      {"CODEC", "iax2.voice.codec", FT_UINT32, BASE_HEX, VALS (codec_types),
1844       0x0, 
1845       "CODEC gives the codec used to encode audio data", HFILL}},
1846
1847     {&hf_iax2_video_csub,
1848      {"Video Subclass (compressed codec no)", "iax2.video.subclass", FT_UINT8, BASE_DEC, NULL, 0xBF, 
1849       "Video Subclass (compressed codec no)",
1850       HFILL}},
1851     
1852     {&hf_iax2_marker,
1853      {"Marker", "iax2.video.marker", FT_BOOLEAN, 8, NULL, 0x40,
1854       "RTP end-of-frame marker",
1855       HFILL}},
1856
1857     {&hf_iax2_video_codec,
1858      {"CODEC", "iax2.video.codec", FT_UINT32, BASE_HEX, VALS (codec_types), 0, 
1859       "The codec used to encode video data", HFILL}},
1860     
1861     /*
1862      * Decoding for the ies
1863      */
1864
1865     {&hf_IAX_IE_APPARENTADDR_SINFAMILY,
1866      {"Family", "iax2.iax.app_addr.sinfamily", FT_UINT16, BASE_DEC, NULL, 0, "Family", HFILL }},
1867     {&hf_IAX_IE_APPARENTADDR_SINPORT,
1868      {"Port", "iax2.iax.app_addr.sinport", FT_UINT16, BASE_DEC, NULL, 0, "Port", HFILL }},
1869     {&hf_IAX_IE_APPARENTADDR_SINADDR,
1870      {"Address", "iax2.iax.app_addr.sinaddr", FT_IPv4, BASE_HEX, NULL, 0, "Address", HFILL }},
1871     
1872     {&hf_iax2_ies[IAX_IE_CALLED_NUMBER],
1873      {"Number/extension being called", "iax2.iax.called_number",
1874       FT_STRING,
1875       BASE_NONE, NULL, 0x0, "", HFILL}},
1876
1877     {&hf_iax2_ies[IAX_IE_CALLING_NUMBER],
1878      {"Calling number", "iax2.iax.calling_number", FT_STRING,
1879       BASE_NONE, NULL,
1880       0x0, "", HFILL}},
1881
1882     {&hf_iax2_ies[IAX_IE_CALLING_ANI],
1883      {"Calling number ANI for billing", "iax2.iax.calling_ani",
1884       FT_STRING,
1885       BASE_NONE, NULL, 0x0, "", HFILL}},
1886
1887     {&hf_iax2_ies[IAX_IE_CALLING_NAME],
1888      {"Name of caller", "iax2.iax.calling_name", FT_STRING, BASE_NONE,
1889       NULL,
1890       0x0, "", HFILL}},
1891
1892     {&hf_iax2_ies[IAX_IE_CALLED_CONTEXT],
1893      {"Context for number", "iax2.iax.called_context", FT_STRING,
1894       BASE_NONE,
1895       NULL, 0x0, "", HFILL}},
1896
1897     {&hf_iax2_ies[IAX_IE_USERNAME],
1898      {"Username (peer or user) for authentication",
1899       "iax2.iax.username",
1900       FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
1901
1902     {&hf_iax2_ies[IAX_IE_PASSWORD],
1903      {"Password for authentication", "iax2.iax.password", FT_STRING,
1904       BASE_NONE, NULL, 0x0, "", HFILL}},
1905
1906     {&hf_iax2_ies[IAX_IE_CAPABILITY],
1907      {"Actual codec capability", "iax2.iax.capability", FT_UINT32,
1908       BASE_HEX,
1909       NULL, 0x0, "", HFILL}},
1910
1911     {&hf_iax2_ies[IAX_IE_FORMAT],
1912      {"Desired codec format", "iax2.iax.format", FT_UINT32, BASE_HEX,
1913       VALS (codec_types), 0x0, "", HFILL}},
1914
1915     {&hf_iax2_ies[IAX_IE_LANGUAGE],
1916      {"Desired language", "iax2.iax.language", FT_STRING, BASE_NONE,
1917       NULL,
1918       0x0, "", HFILL}},
1919
1920     {&hf_iax2_ies[IAX_IE_VERSION],
1921      {"Protocol version", "iax2.iax.version", FT_UINT16, BASE_HEX, NULL,
1922       0x0,
1923       "", HFILL}},
1924
1925     {&hf_iax2_ies[IAX_IE_ADSICPE],
1926      {"CPE ADSI capability", "iax2.iax.cpe_adsi", FT_UINT16, BASE_HEX,
1927       NULL,
1928       0x0, "", HFILL}},
1929
1930     {&hf_iax2_ies[IAX_IE_DNID],
1931      {"Originally dialed DNID", "iax2.iax.dnid", FT_STRING, BASE_NONE,
1932       NULL,
1933       0x0, "", HFILL}},
1934
1935     {&hf_iax2_ies[IAX_IE_AUTHMETHODS],
1936      {"Authentication method(s)", "iax2.iax.auth.methods", FT_UINT16,
1937       BASE_HEX,
1938       NULL, 0x0, "", HFILL}},
1939
1940     {&hf_iax2_ies[IAX_IE_CHALLENGE],
1941      {"Challenge data for MD5/RSA", "iax2.iax.auth.challenge",
1942       FT_STRING,
1943       BASE_NONE, NULL, 0x0, "", HFILL}},
1944
1945     {&hf_iax2_ies[IAX_IE_MD5_RESULT],
1946      {"MD5 challenge result", "iax2.iax.auth.md5", FT_STRING,
1947       BASE_NONE, NULL,
1948       0x0, "", HFILL}},
1949
1950     {&hf_iax2_ies[IAX_IE_RSA_RESULT],
1951      {"RSA challenge result", "iax2.iax.auth.rsa", FT_STRING,
1952       BASE_NONE, NULL,
1953       0x0, "", HFILL}},
1954
1955     {&hf_iax2_ies[IAX_IE_REFRESH],
1956      {"When to refresh registration", "iax2.iax.refresh", FT_INT16,
1957       BASE_DEC,
1958       NULL, 0x0, "", HFILL}},
1959
1960     {&hf_iax2_ies[IAX_IE_DPSTATUS],
1961      {"Dialplan status", "iax2.iax.dialplan_status", FT_UINT16,
1962       BASE_HEX, NULL,
1963       0x0, "", HFILL}},
1964
1965     {&hf_iax2_ies[IAX_IE_CALLNO],
1966      {"Call number of peer", "iax2.iax.call_no", FT_UINT16, BASE_DEC,
1967       NULL,
1968       0x0, "", HFILL}},
1969
1970     {&hf_iax2_ies[IAX_IE_CAUSE],
1971      {"Cause", "iax2.iax.cause", FT_STRING, BASE_NONE, NULL, 0x0, "",
1972       HFILL}},
1973
1974     {&hf_iax2_ies[IAX_IE_IAX_UNKNOWN],
1975      {"Unknown IAX command", "iax2.iax.iax_unknown", FT_BYTES,
1976       BASE_HEX, NULL,
1977       0x0, "", HFILL}},
1978
1979     {&hf_iax2_ies[IAX_IE_MSGCOUNT],
1980      {"How many messages waiting", "iax2.iax.msg_count", FT_INT16,
1981       BASE_DEC,
1982       NULL, 0x0, "", HFILL}},
1983
1984     {&hf_iax2_ies[IAX_IE_AUTOANSWER],
1985      {"Request auto-answering", "iax2.iax.autoanswer", FT_NONE,
1986       BASE_NONE,
1987       NULL, 0x0, "", HFILL}},
1988
1989     {&hf_iax2_ies[IAX_IE_MUSICONHOLD],
1990      {"Request musiconhold with QUELCH", "iax2.iax.moh", FT_NONE,
1991       BASE_NONE,
1992       NULL, 0x0, "", HFILL}},
1993
1994     {&hf_iax2_ies[IAX_IE_TRANSFERID],
1995      {"Transfer Request Identifier", "iax2.iax.transferid", FT_UINT32,
1996       BASE_HEX, NULL, 0x0, "", HFILL}},
1997
1998     {&hf_iax2_ies[IAX_IE_RDNIS],
1999      {"Referring DNIS", "iax2.iax.rdnis", FT_STRING, BASE_NONE, NULL,
2000       0x0, "",
2001       HFILL}},
2002
2003     {&hf_iax2_ies[IAX_IE_PROVISIONING],
2004      {"Provisioning info","iax2.iax.provisioning", FT_STRING, BASE_NONE,
2005        NULL, 0x0, "", HFILL}},
2006
2007     {&hf_iax2_ies[IAX_IE_AESPROVISIONING],
2008      {"AES Provisioning info","iax2.iax.aesprovisioning", FT_STRING, BASE_NONE,
2009        NULL, 0x0, "", HFILL}},
2010
2011     {&hf_iax2_ies[IAX_IE_DATETIME],
2012      {"Date/Time", "iax2.iax.datetime.raw", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
2013
2014     {&hf_iax2_ie_datetime,
2015      {"Date/Time", "iax2.iax.datetime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, "", HFILL }},
2016
2017     {&hf_iax2_ies[IAX_IE_DEVICETYPE],
2018      {"Device type", "iax2.iax.devicetype", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2019
2020     {&hf_iax2_ies[IAX_IE_SERVICEIDENT],
2021      {"Service identifier", "iax2.iax.serviceident", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2022
2023     {&hf_iax2_ies[IAX_IE_FIRMWAREVER],
2024      {"Firmware version", "iax2.iax.firmwarever", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
2025
2026     {&hf_iax2_ies[IAX_IE_FWBLOCKDESC],
2027      {"Firmware block description", "iax2.iax.fwblockdesc", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2028
2029     {&hf_iax2_ies[IAX_IE_FWBLOCKDATA],
2030      {"Firmware block of data", "iax2.iax.fwblockdata", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2031
2032     {&hf_iax2_ies[IAX_IE_PROVVER],
2033      {"Provisioning version", "iax2.iax.provver", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2034
2035     {&hf_iax2_ies[IAX_IE_CALLINGPRES],
2036      {"Calling presentation", "iax2.iax.callingpres", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
2037
2038     {&hf_iax2_ies[IAX_IE_CALLINGTON],
2039      {"Calling type of number", "iax2.iax.callington", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
2040
2041     {&hf_iax2_ies[IAX_IE_CALLINGTNS],
2042      {"Calling transit network select", "iax2.iax.callingtns", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
2043
2044     {&hf_iax2_ies[IAX_IE_SAMPLINGRATE],
2045      {"Supported sampling rates", "iax2.iax.samplingrate", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
2046
2047     {&hf_iax2_ies[IAX_IE_CAUSECODE],
2048      {"Hangup cause", "iax2.iax.causecode", FT_UINT8, BASE_HEX, VALS(iax_causecodes),
2049        0x0, "", HFILL}},
2050
2051     {&hf_iax2_ies[IAX_IE_ENCRYPTION],
2052      {"Encryption format", "iax2.iax.encryption", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
2053
2054     {&hf_iax2_ies[IAX_IE_ENCKEY],
2055      {"Encryption key", "iax2.iax.enckey", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2056
2057     {&hf_iax2_ies[IAX_IE_CODEC_PREFS],
2058      {"Codec negotiation", "iax2.iax.codecprefs", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
2059
2060     {&hf_iax2_ies[IAX_IE_RR_JITTER],
2061      {"Received jitter (as in RFC1889)", "iax2.iax.rrjitter", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2062
2063     {&hf_iax2_ies[IAX_IE_RR_LOSS],
2064      {"Received loss (high byte loss pct, low 24 bits loss count, as in rfc1889)", "iax2.iax.rrloss",
2065        FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2066
2067     {&hf_iax2_ies[IAX_IE_RR_PKTS],
2068      {"Total frames received", "iax2.iax.rrpkts", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2069
2070     {&hf_iax2_ies[IAX_IE_RR_DELAY],
2071      {"Max playout delay in ms for received frames", "iax2.iax.rrdelay", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
2072
2073     {&hf_iax2_ies[IAX_IE_RR_DROPPED],
2074      {"Dropped frames (presumably by jitterbuffer)", "iax2.iax.rrdropped", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2075
2076     {&hf_iax2_ies[IAX_IE_RR_OOO],
2077      {"Frame received out of order", "iax2.iax.rrooo", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
2078
2079     {&hf_iax2_ies[IAX_IE_DATAFORMAT],
2080      {"Data call format", "iax2.iax.dataformat", FT_UINT32, BASE_HEX,
2081       VALS(iax_dataformats), 0x0, "", HFILL}},
2082
2083     {&hf_IAX_IE_UNKNOWN_BYTE,
2084      {"Unknown", "iax2.iax.unknownbyte", FT_UINT8, BASE_HEX, NULL,
2085       0x0, "Raw data for unknown IEs",
2086       HFILL}},
2087     {&hf_IAX_IE_UNKNOWN_I16,
2088      {"Unknown", "iax2.iax.unknownshort", FT_UINT16, BASE_HEX, NULL,
2089       0x0, "Raw data for unknown IEs",
2090       HFILL}},
2091     {&hf_IAX_IE_UNKNOWN_I32,
2092      {"Unknown", "iax2.iax.unknownlong", FT_UINT32, BASE_HEX, NULL,
2093       0x0, "Raw data for unknown IEs",
2094       HFILL}},
2095     {&hf_IAX_IE_UNKNOWN_BYTES,
2096      {"Unknown", "iax2.iax.unknownstring", FT_STRING, BASE_NONE, NULL,
2097       0x0, "Raw data for unknown IEs",
2098       HFILL}},
2099
2100     /* capablilites */
2101     {&hf_iax2_cap_g723_1,
2102      {"G.723.1 compression", "iax2.cap.g723_1", FT_BOOLEAN, 32,
2103       TFS(&supported_strings), AST_FORMAT_G723_1,
2104       "G.723.1 compression", HFILL }},
2105
2106     {&hf_iax2_cap_gsm,
2107      {"GSM compression", "iax2.cap.gsm", FT_BOOLEAN, 32,
2108        TFS(&supported_strings), AST_FORMAT_GSM, 
2109       "GSM compression", HFILL }},
2110
2111     {&hf_iax2_cap_ulaw,
2112      {"Raw mu-law data (G.711)", "iax2.cap.ulaw",FT_BOOLEAN, 32,
2113       TFS(&supported_strings), AST_FORMAT_ULAW,
2114       "Raw mu-law data (G.711)", HFILL }},
2115
2116      {&hf_iax2_cap_alaw,
2117       {"Raw A-law data (G.711)", "iax2.cap.alaw",FT_BOOLEAN, 32,
2118        TFS(&supported_strings), AST_FORMAT_ALAW,
2119        "Raw A-law data (G.711)", HFILL }},
2120
2121     {&hf_iax2_cap_g726,
2122      {"G.726 compression", "iax2.cap.g726",FT_BOOLEAN, 32,
2123       TFS(&supported_strings), AST_FORMAT_G726,
2124       "G.726 compression", HFILL }},
2125
2126     {&hf_iax2_cap_adpcm,
2127      {"ADPCM", "iax2.cap.adpcm", FT_BOOLEAN, 32,
2128       TFS(&supported_strings), AST_FORMAT_ADPCM,
2129       "ADPCM", HFILL }},
2130     
2131     {&hf_iax2_cap_slinear,
2132      {"Raw 16-bit Signed Linear (8000 Hz) PCM", "iax2.cap.slinear", 
2133       FT_BOOLEAN, 32, TFS(&supported_strings), AST_FORMAT_SLINEAR, 
2134       "Raw 16-bit Signed Linear (8000 Hz) PCM", HFILL }},
2135
2136     {&hf_iax2_cap_lpc10,
2137      {"LPC10, 180 samples/frame", "iax2.cap.lpc10", FT_BOOLEAN, 32,
2138       TFS(&supported_strings), AST_FORMAT_LPC10,
2139       "LPC10, 180 samples/frame", HFILL }},
2140
2141     {&hf_iax2_cap_g729a,
2142      {"G.729a Audio", "iax2.cap.g729a", FT_BOOLEAN, 32,
2143       TFS(&supported_strings), AST_FORMAT_G729A,
2144       "G.729a Audio", HFILL }},
2145
2146     {&hf_iax2_cap_speex,
2147      {"SPEEX Audio", "iax2.cap.speex", FT_BOOLEAN, 32,
2148       TFS(&supported_strings), AST_FORMAT_SPEEX,
2149       "SPEEX Audio", HFILL }},
2150
2151     {&hf_iax2_cap_ilbc,
2152      {"iLBC Free compressed Audio", "iax2.cap.ilbc", FT_BOOLEAN, 32,
2153       TFS(&supported_strings), AST_FORMAT_ILBC,
2154       "iLBC Free compressed Audio", HFILL }},
2155
2156     {&hf_iax2_cap_jpeg,
2157      {"JPEG images", "iax2.cap.jpeg", FT_BOOLEAN, 32,
2158       TFS(&supported_strings), AST_FORMAT_JPEG,
2159       "JPEG images", HFILL }},
2160
2161     {&hf_iax2_cap_png,
2162      {"PNG images", "iax2.cap.png", FT_BOOLEAN, 32,
2163       TFS(&supported_strings), AST_FORMAT_PNG,
2164       "PNG images", HFILL }},
2165
2166     {&hf_iax2_cap_h261,
2167      {"H.261 video", "iax2.cap.h261", FT_BOOLEAN, 32,
2168       TFS(&supported_strings), AST_FORMAT_H261,
2169       "H.261 video", HFILL }},
2170
2171     {&hf_iax2_cap_h263,
2172      {"H.263 video", "iax2.cap.h263", FT_BOOLEAN, 32,
2173       TFS(&supported_strings), AST_FORMAT_H263,
2174       "H.263 video", HFILL }}
2175   };
2176
2177   static gint *ett[] = {
2178     &ett_iax2,
2179     &ett_iax2_full_mini_subtree,
2180     &ett_iax2_type,
2181     &ett_iax2_ie,
2182     &ett_iax2_codecs,
2183     &ett_iax2_ies_apparent_addr
2184   };
2185
2186   /* initialise the hf_iax2_ies[] array to -1 */
2187   memset(hf_iax2_ies,0xff,sizeof(hf_iax2_ies));
2188
2189   proto_iax2 =
2190     proto_register_protocol ("Inter-Asterisk eXchange v2", "IAX2", "iax2");
2191   proto_register_field_array (proto_iax2, hf, array_length (hf));
2192   proto_register_subtree_array (ett, array_length (ett));
2193
2194   register_dissector("iax2", dissect_iax2, proto_iax2);
2195
2196   iax2_codec_dissector_table = register_dissector_table(
2197     "iax2.codec","IAX codec number", FT_UINT32, BASE_HEX);
2198   iax2_dataformat_dissector_table = register_dissector_table(
2199     "iax2.dataformat","IAX dataformat number", FT_UINT32, BASE_HEX);
2200   
2201   /* register our init routine to be called at the start of a capture,
2202      to clear out our hash tables etc */
2203   register_init_routine(&iax_init_protocol);
2204 }
2205
2206 void
2207 proto_reg_handoff_iax2 (void)
2208 {
2209   dissector_add("udp.port", IAX2_PORT, find_dissector("iax2"));
2210   dissector_add("iax2.dataformat", AST_DATAFORMAT_V110, find_dissector("v110"));
2211   data_handle = find_dissector("data");
2212 }
2213
2214
2215 /* 
2216  * This sets up the indentation style for this file in emacs.
2217  *
2218  * Local Variables:
2219  * c-basic-offset: 2
2220  * End:
2221  */