added some options and enhancements to the print output:
[obnox/wireshark/wip.git] / 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: packet-iax2.c,v 1.5 2004/02/18 14:30:45 jmayer Exp $
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 #include <epan/packet.h>
38
39 #include "packet-iax2.h"
40
41 #define IAX2_PORT               4569
42 #define PROTO_TAG_IAX2  "IAX2"
43
44 static int proto_iax2 = -1;
45
46 static int hf_iax2_retransmission = -1;
47 static int hf_iax2_scallno = -1;
48 static int hf_iax2_dcallno = -1;
49 static int hf_iax2_ts = -1;
50 static int hf_iax2_minits = -1;
51 static int hf_iax2_voicedata = -1;
52 static int hf_iax2_oseqno = -1;
53 static int hf_iax2_iseqno = -1;
54 static int hf_iax2_type = -1;
55 static int hf_iax2_csub = -1;
56 static int hf_iax2_cmd_csub = -1;
57 static int hf_iax2_iax_csub = -1;
58 static int hf_iax2_voice_csub = -1;
59 static int hf_iax2_ies = -1;
60
61 static int hf_IAX_IE_APPARENTADDR_SINFAMILY = -1;
62 static int hf_IAX_IE_APPARENTADDR_SINPORT = -1;
63 static int hf_IAX_IE_APPARENTADDR_SINADDR = -1;
64 static int hf_IAX_IE_APPARENTADDR_SINZERO = -1;           
65 static int hf_IAX_IE_CALLED_NUMBER = -1;
66 static int hf_IAX_IE_CALLING_NUMBER = -1;
67 static int hf_IAX_IE_CALLING_ANI = -1;
68 static int hf_IAX_IE_CALLING_NAME = -1;
69 static int hf_IAX_IE_CALLED_CONTEXT = -1;
70 static int hf_IAX_IE_USERNAME = -1;
71 static int hf_IAX_IE_PASSWORD = -1;
72 static int hf_IAX_IE_CAPABILITY = -1;
73 static int hf_IAX_IE_FORMAT = -1;
74 static int hf_IAX_IE_LANGUAGE = -1;
75 static int hf_IAX_IE_VERSION = -1;
76 static int hf_IAX_IE_ADSICPE = -1;
77 static int hf_IAX_IE_DNID = -1;
78 static int hf_IAX_IE_AUTHMETHODS = -1;
79 static int hf_IAX_IE_CHALLENGE = -1;
80 static int hf_IAX_IE_MD5_RESULT = -1;
81 static int hf_IAX_IE_RSA_RESULT = -1;
82 static int hf_IAX_IE_REFRESH = -1;
83 static int hf_IAX_IE_DPSTATUS = -1;
84 static int hf_IAX_IE_CALLNO = -1;
85 static int hf_IAX_IE_CAUSE = -1;
86 static int hf_IAX_IE_IAX_UNKNOWN = -1;
87 static int hf_IAX_IE_MSGCOUNT = -1;
88 static int hf_IAX_IE_AUTOANSWER = -1;
89 static int hf_IAX_IE_MUSICONHOLD = -1;
90 static int hf_IAX_IE_TRANSFERID = -1;
91 static int hf_IAX_IE_RDNIS = -1;
92
93
94
95 static gint ett_iax2 = -1;
96 static gint ett_iax2_ies = -1;
97 static gint ett_iax2_codecs = -1;
98 static gint ett_iax2_ies_apparent_addr = -1;
99
100 static const value_string iax_frame_types[] = {
101   {0, "(0?)"},
102   {1, "DTMF"},
103   {2, "Voice"},
104   {3, "Video"},
105   {4, "Control"},
106   {5, "NULL"},
107   {6, "IAX"},
108   {7, "Text"},
109   {8, "Image"}
110 };
111 static const value_string iax_iax_subclasses[] = {
112   {0, "(0?)"},
113   {1, "NEW"},
114   {2, "PING"},
115   {3, "PONG"},
116   {4, "ACK"},
117   {5, "HANGUP"},
118   {6, "REJECT"},
119   {7, "ACCEPT"},
120   {8, "AUTHREQ"},
121   {9, "AUTHREP"},
122   {10, "INVAL"},
123   {11, "LAGRQ"},
124   {12, "LAGRP"},
125   {13, "REGREQ"},
126   {14, "REGAUTH"},
127   {15, "REGACK"},
128   {16, "REGREJ"},
129   {17, "REGREL"},
130   {18, "VNAK"},
131   {19, "DPREQ"},
132   {20, "DPREP"},
133   {21, "DIAL"},
134   {22, "TXREQ"},
135   {23, "TXCNT"},
136   {24, "TXACC"},
137   {25, "TXREADY"},
138   {26, "TXREL"},
139   {27, "TXREJ"},
140   {28, "QUELCH"},
141   {29, "UNQULCH"},
142   {30, "POKE"},
143   {31, "PAGE"},
144   {32, "MWI"},
145   {33, "UNSUPPORTED"},
146   {34, "TRANSFER"}
147 };
148 static const value_string iax_cmd_subclasses[] = {
149   {0, "(0?)"},
150   {1, "HANGUP"},
151   {2, "RING"},
152   {3, "RINGING"},
153   {4, "ANSWER"},
154   {5, "BUSY"},
155   {6, "TKOFFHK"},
156   {7, "OFFHOOK"}
157 };
158
159 static const value_string iax_ies_type[] = {
160   {IAX_IE_CALLED_NUMBER, "Number/extension being called"},
161   {IAX_IE_CALLING_NUMBER, "Calling number"},
162   {IAX_IE_CALLING_ANI, "Calling number ANI for billing"},
163   {IAX_IE_CALLING_NAME, "Name of caller"},
164   {IAX_IE_CALLED_CONTEXT, "Context for number"},
165   {IAX_IE_USERNAME, "Username (peer or user) for authentication"},
166   {IAX_IE_PASSWORD, "Password for authentication"},
167   {IAX_IE_CAPABILITY, "Actual codec capability"},
168   {IAX_IE_FORMAT, "Desired codec format"},
169   {IAX_IE_LANGUAGE, "Desired language"},
170   {IAX_IE_VERSION, "Protocol version"},
171   {IAX_IE_ADSICPE, "CPE ADSI capability"},
172   {IAX_IE_DNID, "Originally dialed DNID"},
173   {IAX_IE_AUTHMETHODS, "Authentication method(s)"},
174   {IAX_IE_CHALLENGE, "Challenge data for MD5/RSA"},
175   {IAX_IE_MD5_RESULT, "MD5 challenge result"},
176   {IAX_IE_RSA_RESULT, "RSA challenge result"},
177   {IAX_IE_APPARENT_ADDR, "Apparent address of peer"},
178   {IAX_IE_REFRESH, "When to refresh registration"},
179   {IAX_IE_DPSTATUS, "Dialplan status"},
180   {IAX_IE_CALLNO, "Call number of peer"},
181   {IAX_IE_CAUSE, "Cause"},
182   {IAX_IE_IAX_UNKNOWN, "Unknown IAX command"},
183   {IAX_IE_MSGCOUNT, "How many messages waiting"},
184   {IAX_IE_AUTOANSWER, "Request auto-answering"},
185   {IAX_IE_MUSICONHOLD, "Request musiconhold with QUELCH"},
186   {IAX_IE_TRANSFERID, "Transfer Request Identifier"},
187   {IAX_IE_RDNIS, "Referring DNIS"}
188 };
189
190 static const value_string codec_types[] = {
191   {AST_FORMAT_G723_1, "G.723.1 compression"},
192   {AST_FORMAT_GSM, "GSM compression"},
193   {AST_FORMAT_ULAW, "Raw mu-law data (G.711)"},
194   {AST_FORMAT_ALAW, "Raw A-law data (G.711)"},
195   {AST_FORMAT_MP3, "MPEG-2 layer 3"},
196   {AST_FORMAT_ADPCM, "ADPCM (whose?)"},
197   {AST_FORMAT_SLINEAR, "Raw 16-bit Signed Linear (8000 Hz) PCM"},
198   {AST_FORMAT_LPC10, "LPC10, 180 samples/frame"},
199   {AST_FORMAT_G729A, "G.729a Audio"}
200 };
201
202 static void
203 dissect_iax2 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
204 {
205   proto_tree *iax2_tree = NULL, *ies_tree = NULL, *codec_tree = NULL, *sockaddr_tree = NULL;
206   proto_item *ti = 0, *ies_base = 0, *codec_base = 0, *sockaddr_item = 0;
207   guint32 offset = 0, codecs = 0, i = 0, mask = 0, retransmission = 0;
208   guint16 scallno;
209   guint16 dcallno;
210   guint32 ts;
211   guint8 type;
212   guint8 csub;
213
214   if (check_col (pinfo->cinfo, COL_PROTOCOL))
215     {
216       col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2);
217     }
218   if (check_col (pinfo->cinfo, COL_INFO))
219     {
220       col_clear (pinfo->cinfo, COL_INFO);
221     }
222
223   if (tree)
224     {
225       ti = proto_tree_add_item (tree, proto_iax2, tvb, offset, -1, FALSE);
226       iax2_tree = proto_item_add_subtree (ti, ett_iax2);
227     }
228
229   scallno = tvb_get_ntohs(tvb, offset);
230   if (scallno & 0x8000)
231     {
232       /*
233        * remove the top bit for header type detection 
234        */
235       scallno = scallno & 0x7FFF;
236       proto_tree_add_uint (iax2_tree, hf_iax2_scallno, tvb, offset, 2,
237                            scallno);
238
239       /*
240        * remove the top bit for retransmission detection 
241        */
242       dcallno = tvb_get_ntohs(tvb, offset + 2);
243       retransmission = dcallno & 0x8000;
244       dcallno = dcallno & 0x7FFF;
245       proto_tree_add_uint (iax2_tree, hf_iax2_dcallno, tvb, offset + 2, 2,
246                            dcallno);
247       proto_tree_add_boolean (iax2_tree, hf_iax2_retransmission, tvb,
248                               offset + 2, 2, retransmission);
249
250       ts = tvb_get_ntohl(tvb, offset + 4);
251       proto_tree_add_uint (iax2_tree, hf_iax2_ts, tvb, offset + 4, 4, ts);
252       proto_tree_add_item (iax2_tree, hf_iax2_oseqno, tvb, offset + 8, 1,
253                            FALSE);
254       proto_tree_add_item (iax2_tree, hf_iax2_iseqno, tvb, offset + 9, 1,
255                            FALSE);
256       type = tvb_get_guint8(tvb, offset + 10);
257       proto_tree_add_uint (iax2_tree, hf_iax2_type, tvb, offset + 10, 1,
258                            type);
259
260       csub = tvb_get_guint8(tvb, offset + 11);
261       if (type == AST_FRAME_IAX)
262         {
263           proto_tree_add_uint (iax2_tree, hf_iax2_iax_csub, tvb,
264                                offset + 11, 1, csub);
265           if (check_col (pinfo->cinfo, COL_INFO))
266             {
267               col_add_fstr (pinfo->cinfo, COL_INFO,
268                             "%s %s, source call# %d, timestamp %ums",
269                             val_to_str (type, iax_frame_types,
270                                         "Unknown (0x%02x)"),
271                             val_to_str (csub, iax_iax_subclasses,
272                                         "unknown (0x%02x)"), scallno,
273                             ts);
274             }
275
276         }
277       else if (type == AST_FRAME_DTMF)
278         {
279           proto_tree_add_text (iax2_tree, tvb, offset + 11, 1, "DTMF digit: %c", csub);
280           if (check_col (pinfo->cinfo, COL_INFO))
281             {
282               col_add_fstr (pinfo->cinfo, COL_INFO,
283                             "%s digit %c, source call# %d, timestamp %ums",
284                             val_to_str (type, iax_frame_types,
285                                         "Unknown (0x%02x)"), csub,
286                             scallno, ts);
287             }
288
289         }
290       else if (type == AST_FRAME_CONTROL)
291         {
292           proto_tree_add_uint (iax2_tree, hf_iax2_cmd_csub, tvb,
293                                offset + 11, 1, csub);
294           if (check_col (pinfo->cinfo, COL_INFO))
295             {
296               col_add_fstr (pinfo->cinfo, COL_INFO,
297                             "%s %s, source call# %d, timestamp %ums",
298                             val_to_str (type, iax_frame_types,
299                                         "Unknown (0x%02x)"),
300                             val_to_str (csub, iax_cmd_subclasses,
301                                         "unknown (0x%02x)"), scallno,
302                             ts);
303             }
304
305         }
306       else if (type == AST_FRAME_VOICE)
307         {
308           proto_tree_add_uint (iax2_tree, hf_iax2_voice_csub, tvb,
309                                offset + 11, 1, csub);
310           if (check_col (pinfo->cinfo, COL_INFO))
311             {
312               col_add_fstr (pinfo->cinfo, COL_INFO,
313                             "%s codec %s, source call# %d, timestamp %ums",
314                             val_to_str (type, iax_frame_types,
315                                         "Unknown (0x%02x)"),
316                             val_to_str (csub, codec_types,
317                                         "unknown (0x%02x)"), scallno,
318                             ts);
319             }
320         }
321       else
322         {
323           proto_tree_add_uint (iax2_tree, hf_iax2_csub, tvb, offset + 11,
324                                1, csub);
325           if (check_col (pinfo->cinfo, COL_INFO))
326             {
327               col_add_fstr (pinfo->cinfo, COL_INFO,
328                             "%s subclass %d, source call# %d, timestamp %ums",
329                             val_to_str (type, iax_frame_types,
330                                         "Unknown (0x%02x)"), csub,
331                             scallno, ts);
332             }
333         }
334       offset += 12;
335
336       if (type == AST_FRAME_IAX && (offset < tvb_reported_length (tvb)))
337         {
338           ies_base =
339             proto_tree_add_item (iax2_tree, hf_iax2_ies, tvb, offset,
340                                  -1, FALSE);
341           ies_tree = proto_item_add_subtree (ies_base, ett_iax2_ies);
342         }
343
344       while (type == AST_FRAME_IAX && offset < tvb_reported_length (tvb))
345         {
346           int ies_type = tvb_get_guint8(tvb, offset);
347           int ies_len = tvb_get_guint8(tvb, offset + 1);
348           switch (ies_type)
349             {
350             case IAX_IE_CALLED_NUMBER:
351               proto_tree_add_item (ies_tree, hf_IAX_IE_CALLED_NUMBER, tvb,
352                                    offset + 2, ies_len, FALSE);
353               break;
354             case IAX_IE_CALLING_NUMBER:
355               proto_tree_add_item (ies_tree, hf_IAX_IE_CALLING_NUMBER,
356                                    tvb, offset + 2, ies_len, FALSE);
357               break;
358             case IAX_IE_CALLING_ANI:
359               proto_tree_add_item (ies_tree, hf_IAX_IE_CALLING_ANI, tvb,
360                                    offset + 2, ies_len, FALSE);
361               break;
362             case IAX_IE_CALLING_NAME:
363               proto_tree_add_item (ies_tree, hf_IAX_IE_CALLING_NAME, tvb,
364                                    offset + 2, ies_len, FALSE);
365               break;
366             case IAX_IE_CALLED_CONTEXT:
367               proto_tree_add_item (ies_tree, hf_IAX_IE_CALLED_CONTEXT,
368                                    tvb, offset + 2, ies_len, FALSE);
369               break;
370             case IAX_IE_USERNAME:
371               proto_tree_add_item (ies_tree, hf_IAX_IE_USERNAME, tvb,
372                                    offset + 2, ies_len, FALSE);
373               break;
374             case IAX_IE_PASSWORD:
375               proto_tree_add_item (ies_tree, hf_IAX_IE_PASSWORD, tvb,
376                                    offset + 2, ies_len, FALSE);
377               break;
378             case IAX_IE_LANGUAGE:
379               proto_tree_add_item (ies_tree, hf_IAX_IE_LANGUAGE, tvb,
380                                    offset + 2, ies_len, FALSE);
381               break;
382             case IAX_IE_DNID:
383               proto_tree_add_item (ies_tree, hf_IAX_IE_DNID, tvb,
384                                    offset + 2, ies_len, FALSE);
385               break;
386             case IAX_IE_CHALLENGE:
387               proto_tree_add_item (ies_tree, hf_IAX_IE_CHALLENGE, tvb,
388                                    offset + 2, ies_len, FALSE);
389               break;
390             case IAX_IE_MD5_RESULT:
391               proto_tree_add_item (ies_tree, hf_IAX_IE_MD5_RESULT, tvb,
392                                    offset + 2, ies_len, FALSE);
393               break;
394             case IAX_IE_RSA_RESULT:
395               proto_tree_add_item (ies_tree, hf_IAX_IE_RSA_RESULT, tvb,
396                                    offset + 2, ies_len, FALSE);
397               break;
398             case IAX_IE_RDNIS:
399               proto_tree_add_item (ies_tree, hf_IAX_IE_RDNIS, tvb,
400                                    offset + 2, ies_len, FALSE);
401               break;
402             case IAX_IE_CAPABILITY:
403               codec_base =
404                 proto_tree_add_item (ies_tree, hf_IAX_IE_CAPABILITY,
405                                      tvb, offset + 2, ies_len, FALSE);
406               codec_tree =
407                 proto_item_add_subtree (codec_base, ett_iax2_codecs);
408
409               codecs = tvb_get_ntohl (tvb, offset + 2);
410               for (i = 0; i < 8; i++)
411                 {
412                   mask = (1 << i);
413                   if (codecs & mask)
414                     proto_tree_add_text (codec_tree, tvb, offset + 2, 4,
415                                          "Supported: %s",
416                                          val_to_str (mask, codec_types,
417                                                      "unknown"));
418                 }
419               for (i = 0; i < 8; i++)
420                 {
421                   mask = (1 << i);
422                   if (!(codecs & mask))
423                     proto_tree_add_text (codec_tree, tvb, offset + 2, 4,
424                                          "Unsupported: %s",
425                                          val_to_str (mask, codec_types,
426                                                      "unknown"));
427                 }
428
429               break;
430             case IAX_IE_FORMAT:
431               proto_tree_add_item (ies_tree, hf_IAX_IE_FORMAT, tvb,
432                                    offset + 2, ies_len, FALSE);
433               break;
434             case IAX_IE_VERSION:
435               proto_tree_add_item (ies_tree, hf_IAX_IE_VERSION, tvb,
436                                    offset + 2, ies_len, FALSE);
437               break;
438             case IAX_IE_ADSICPE:
439               proto_tree_add_item (ies_tree, hf_IAX_IE_ADSICPE, tvb,
440                                    offset + 2, ies_len, FALSE);
441               break;
442             case IAX_IE_AUTHMETHODS:
443               proto_tree_add_item (ies_tree, hf_IAX_IE_AUTHMETHODS, tvb,
444                                    offset + 2, ies_len, FALSE);
445               break;
446             case IAX_IE_APPARENT_ADDR:
447               sockaddr_item = proto_tree_add_text(ies_tree, tvb, offset + 2, 16, "Apparent Address");
448               sockaddr_tree = proto_item_add_subtree(sockaddr_item, ett_iax2_ies_apparent_addr);
449               proto_tree_add_item(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINADDR, tvb, offset + 6, 4, FALSE);
450               proto_tree_add_item(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINPORT, tvb, offset + 4, 2, FALSE);
451               break;
452             case IAX_IE_REFRESH:
453               proto_tree_add_item (ies_tree, hf_IAX_IE_REFRESH, tvb,
454                                    offset + 2, ies_len, FALSE);
455               break;
456             case IAX_IE_DPSTATUS:
457               proto_tree_add_item (ies_tree, hf_IAX_IE_DPSTATUS, tvb,
458                                    offset + 2, ies_len, FALSE);
459               break;
460             case IAX_IE_CALLNO:
461               proto_tree_add_item (ies_tree, hf_IAX_IE_CALLNO, tvb,
462                                    offset + 2, ies_len, FALSE);
463               break;
464             case IAX_IE_CAUSE:
465               proto_tree_add_item (ies_tree, hf_IAX_IE_CAUSE, tvb,
466                                    offset + 2, ies_len, FALSE);
467               break;
468             case IAX_IE_IAX_UNKNOWN:
469               proto_tree_add_item (ies_tree, hf_IAX_IE_IAX_UNKNOWN, tvb,
470                                    offset + 2, ies_len, FALSE);
471               break;
472             case IAX_IE_MSGCOUNT:
473               proto_tree_add_item (ies_tree, hf_IAX_IE_MSGCOUNT, tvb,
474                                    offset + 2, ies_len, FALSE);
475               break;
476             case IAX_IE_AUTOANSWER:
477               proto_tree_add_item (ies_tree, hf_IAX_IE_AUTOANSWER, tvb,
478                                    offset + 2, ies_len, FALSE);
479               break;
480             case IAX_IE_MUSICONHOLD:
481               proto_tree_add_item (ies_tree, hf_IAX_IE_MUSICONHOLD, tvb,
482                                    offset + 2, ies_len, FALSE);
483               break;
484             case IAX_IE_TRANSFERID:
485               proto_tree_add_item (ies_tree, hf_IAX_IE_TRANSFERID, tvb,
486                                    offset + 2, ies_len, FALSE);
487               break;
488             }
489           offset += ies_len + 2;
490         }
491
492     }
493   else
494     {
495       proto_tree_add_uint (iax2_tree, hf_iax2_scallno, tvb, offset, 2,
496                            scallno);
497       ts = tvb_get_ntohs(tvb, offset + 2);
498       proto_tree_add_uint (iax2_tree, hf_iax2_minits, tvb, offset + 2, 2,
499                            ts);
500       if (check_col (pinfo->cinfo, COL_INFO))
501         {
502           col_add_fstr (pinfo->cinfo, COL_INFO,
503                         "Voice frame (mini header), source call# %d, timestamp %ums",
504                         scallno, ts);
505         }
506       proto_tree_add_item (iax2_tree, hf_iax2_voicedata, tvb, offset + 4,
507                            -1, FALSE);
508     }
509
510 }                               /* dissect_iax2 */
511
512 void
513 proto_register_iax2 (void)
514 {
515   static hf_register_info hf[] = {
516     {&hf_iax2_scallno,
517      {"Source call", "iax2.src_call", FT_UINT16, BASE_DEC, NULL, 0x0,
518       "",
519       HFILL}},
520     {&hf_iax2_dcallno,
521      {"Destination call", "iax2.dst_call", FT_UINT16, BASE_DEC, NULL,
522       0x0, "",
523       HFILL}},
524     {&hf_iax2_retransmission,
525      {"Retransmission", "iax2.retransmission", FT_BOOLEAN, BASE_NONE,
526       NULL,
527       0x0, "", HFILL}},
528     {&hf_iax2_ts,
529      {"Timestamp", "iax2.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
530       "",
531       HFILL}},
532     {&hf_iax2_minits,
533      {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x0,
534       "",
535       HFILL}},
536     {&hf_iax2_voicedata,
537      {"Voice data", "iax2.voicedata", FT_BYTES, BASE_NONE, NULL, 0x0,
538       "",
539       HFILL}},
540     {&hf_iax2_oseqno,
541      {"Outbound seq.no.", "iax2.oseqno", FT_UINT16, BASE_DEC, NULL,
542       0x0, "",
543       HFILL}},
544     {&hf_iax2_iseqno,
545      {"Inbound seq.no.", "iax2.iseqno", FT_UINT16, BASE_DEC, NULL, 0x0,
546       "",
547       HFILL}},
548     {&hf_iax2_type,
549      {"Type", "iax2.type", FT_UINT8, BASE_DEC, VALS (iax_frame_types),
550       0x0, "",
551       HFILL}},
552     {&hf_iax2_csub,
553      {"Sub-class", "iax2.subclass", FT_UINT8, BASE_DEC, NULL, 0x0, "",
554       HFILL}},
555     {&hf_iax2_cmd_csub,
556      {"Control type", "iax2.control", FT_UINT8, BASE_DEC,
557       VALS (iax_cmd_subclasses), 0x0, "", HFILL}},
558     {&hf_iax2_voice_csub,
559      {"CODEC", "iax2.voice", FT_UINT8, BASE_DEC, VALS (codec_types),
560       0x0, "", HFILL}},
561     {&hf_iax2_iax_csub,
562      {"IAX type", "iax2.iax", FT_UINT8, BASE_DEC,
563       VALS (iax_iax_subclasses),
564       0x0, "", HFILL}},
565     {&hf_iax2_ies,
566      {"Information elements", "iax2.ies", FT_BYTES, BASE_NONE, NULL,
567       0x0, "", HFILL}},
568         {&hf_IAX_IE_APPARENTADDR_SINFAMILY,
569      {"Family", "iax2.ies.app_addr.sinfamily", FT_UINT16, BASE_DEC, NULL, 0, "Family", HFILL }},
570         {&hf_IAX_IE_APPARENTADDR_SINPORT,
571      {"Port", "iax2.ies.app_addr.sinport", FT_UINT16, BASE_DEC, NULL, 0, "Port", HFILL }},
572         {&hf_IAX_IE_APPARENTADDR_SINADDR,
573      {"Address", "iax2.ies.app_addr.sinaddr", FT_IPv4, BASE_HEX, NULL, 0, "Address", HFILL }},
574         {&hf_IAX_IE_APPARENTADDR_SINZERO,
575      {"Zero", "iax2.ies.app_addr.sinzero", FT_BYTES, BASE_HEX, NULL, 0, "Zero", HFILL }},
576     {&hf_IAX_IE_CALLED_NUMBER,
577      {"Number/extension being called", "iax2.ies.called_number",
578       FT_STRING,
579       BASE_NONE, NULL, 0x0, "", HFILL}},
580     {&hf_IAX_IE_CALLING_NUMBER,
581      {"Calling number", "iax2.ies.calling_number", FT_STRING,
582       BASE_NONE, NULL,
583       0x0, "", HFILL}},
584     {&hf_IAX_IE_CALLING_ANI,
585      {"Calling number ANI for billing", "iax2.ies.calling_ani",
586       FT_STRING,
587       BASE_NONE, NULL, 0x0, "", HFILL}},
588     {&hf_IAX_IE_CALLING_NAME,
589      {"Name of caller", "iax2.ies.calling_name", FT_STRING, BASE_NONE,
590       NULL,
591       0x0, "", HFILL}},
592     {&hf_IAX_IE_CALLED_CONTEXT,
593      {"Context for number", "iax2.ies.called_context", FT_STRING,
594       BASE_NONE,
595       NULL, 0x0, "", HFILL}},
596     {&hf_IAX_IE_USERNAME,
597      {"Username (peer or user) for authentication",
598       "iax2.ies.username",
599       FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
600     {&hf_IAX_IE_PASSWORD,
601      {"Password for authentication", "iax2.ies.password", FT_STRING,
602       BASE_NONE, NULL, 0x0, "", HFILL}},
603     {&hf_IAX_IE_CAPABILITY,
604      {"Actual codec capability", "iax2.ies.capability", FT_UINT32,
605       BASE_HEX,
606       NULL, 0x0, "", HFILL}},
607     {&hf_IAX_IE_FORMAT,
608      {"Desired codec format", "iax2.ies.format", FT_UINT32, BASE_HEX,
609       VALS (codec_types), 0x0, "", HFILL}},
610     {&hf_IAX_IE_LANGUAGE,
611      {"Desired language", "iax2.ies.language", FT_STRING, BASE_NONE,
612       NULL,
613       0x0, "", HFILL}},
614     {&hf_IAX_IE_VERSION,
615      {"Protocol version", "iax2.ies.version", FT_INT16, BASE_HEX, NULL,
616       0x0,
617       "", HFILL}},
618     {&hf_IAX_IE_ADSICPE,
619      {"CPE ADSI capability", "iax2.ies.cpe_adsi", FT_INT16, BASE_HEX,
620       NULL,
621       0x0, "", HFILL}},
622     {&hf_IAX_IE_DNID,
623      {"Originally dialed DNID", "iax2.ies.dnid", FT_STRING, BASE_NONE,
624       NULL,
625       0x0, "", HFILL}},
626     {&hf_IAX_IE_AUTHMETHODS,
627      {"Authentication method(s)", "iax2.ies.auth.methods", FT_INT16,
628       BASE_HEX,
629       NULL, 0x0, "", HFILL}},
630     {&hf_IAX_IE_CHALLENGE,
631      {"Challenge data for MD5/RSA", "iax2.ies.auth.challenge",
632       FT_STRING,
633       BASE_NONE, NULL, 0x0, "", HFILL}},
634     {&hf_IAX_IE_MD5_RESULT,
635      {"MD5 challenge result", "iax2.ies.auth.md5", FT_STRING,
636       BASE_NONE, NULL,
637       0x0, "", HFILL}},
638     {&hf_IAX_IE_RSA_RESULT,
639      {"RSA challenge result", "iax2.ies.auth.rsa", FT_STRING,
640       BASE_NONE, NULL,
641       0x0, "", HFILL}},
642     {&hf_IAX_IE_REFRESH,
643      {"When to refresh registration", "iax2.ies.refresh", FT_INT16,
644       BASE_DEC,
645       NULL, 0x0, "", HFILL}},
646     {&hf_IAX_IE_DPSTATUS,
647      {"Dialplan status", "iax2.ies.dialplan_status", FT_INT16,
648       BASE_HEX, NULL,
649       0x0, "", HFILL}},
650     {&hf_IAX_IE_CALLNO,
651      {"Call number of peer", "iax2.ies.call_no", FT_INT16, BASE_DEC,
652       NULL,
653       0x0, "", HFILL}},
654     {&hf_IAX_IE_CAUSE,
655      {"Cause", "iax2.ies.cause", FT_STRING, BASE_NONE, NULL, 0x0, "",
656       HFILL}},
657     {&hf_IAX_IE_IAX_UNKNOWN,
658      {"Unknown IAX command", "iax2.ies.iax_unknown", FT_BYTES,
659       BASE_HEX, NULL,
660       0x0, "", HFILL}},
661     {&hf_IAX_IE_MSGCOUNT,
662      {"How many messages waiting", "iax2.ies.msg_count", FT_INT16,
663       BASE_DEC,
664       NULL, 0x0, "", HFILL}},
665     {&hf_IAX_IE_AUTOANSWER,
666      {"Request auto-answering", "iax2.ies.autoanswer", FT_NONE,
667       BASE_NONE,
668       NULL, 0x0, "", HFILL}},
669     {&hf_IAX_IE_MUSICONHOLD,
670      {"Request musiconhold with QUELCH", "iax2.ies.moh", FT_NONE,
671       BASE_NONE,
672       NULL, 0x0, "", HFILL}},
673     {&hf_IAX_IE_TRANSFERID,
674      {"Transfer Request Identifier", "iax2.ies.transferid", FT_INT32,
675       BASE_HEX, NULL, 0x0, "", HFILL}},
676     {&hf_IAX_IE_RDNIS,
677      {"Referring DNIS", "iax2.ies.rdnis", FT_STRING, BASE_NONE, NULL,
678       0x0, "",
679       HFILL}}
680   };
681
682   static gint *ett[] = {
683     &ett_iax2,
684     &ett_iax2_ies,
685     &ett_iax2_codecs,
686         &ett_iax2_ies_apparent_addr
687   };
688
689   proto_iax2 =
690     proto_register_protocol ("IAX2", "Inter-Asterisk eXchange v2", "iax2");
691   proto_register_field_array (proto_iax2, hf, array_length (hf));
692   proto_register_subtree_array (ett, array_length (ett));
693
694 }
695
696 void
697 proto_reg_handoff_iax2 (void)
698 {
699
700   dissector_handle_t iax2_handle = NULL;
701
702   iax2_handle = create_dissector_handle (dissect_iax2, proto_iax2);
703
704   dissector_add ("udp.port", IAX2_PORT, iax2_handle);
705 }