Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-iax2.c
Line
Count
Source
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; see RFC 5456 for the
10
 * protocol.
11
 *
12
 * Wireshark - Network traffic analyzer
13
 * By Gerald Combs <gerald@wireshark.org>
14
 * Copyright 1998 Gerald Combs
15
 *
16
 * SPDX-License-Identifier: GPL-2.0-or-later
17
 */
18
19
#include "config.h"
20
21
22
#include <epan/packet.h>
23
#include <epan/conversation.h>
24
#include <epan/reassemble.h>
25
#include <epan/expert.h>
26
#include <epan/aftypes.h>
27
#include <epan/tap.h>
28
#include <epan/proto_data.h>
29
#include <epan/tfs.h>
30
#include <wsutil/array.h>
31
#include <wsutil/str_util.h>
32
33
#include "packet-iax2.h"
34
35
void proto_register_iax2(void);
36
void proto_reg_handoff_iax2(void);
37
38
16
#define IAX2_PORT               4569
39
148
#define PROTO_TAG_IAX2          "IAX2"
40
41
/* enough to hold any address in an address_t */
42
#define MAX_ADDRESS 16
43
44
/* the maximum number of transfers (of each end) we can deal with per call,
45
 * plus one */
46
1
#define IAX_MAX_TRANSFERS 2
47
48
/* #define DEBUG_HASHING */
49
/* #define DEBUG_DESEGMENT */
50
51
/* Wireshark ID of the IAX2 protocol */
52
static int proto_iax2;
53
54
/* tap register id */
55
static int iax2_tap;
56
57
/* protocol tap info */
58
static iax2_info_t ii_arr[1];
59
static iax2_info_t *iax2_info = ii_arr;
60
61
/* The following hf_* variables are used to hold the wireshark IDs of
62
 * our header fields; they are filled out when we call
63
 * proto_register_field_array() in proto_register_iax2()
64
 */
65
static int hf_iax2_packet_type;
66
static int hf_iax2_retransmission;
67
static int hf_iax2_callno;
68
static int hf_iax2_scallno;
69
static int hf_iax2_dcallno;
70
static int hf_iax2_ts;
71
static int hf_iax2_minits;
72
static int hf_iax2_minividts;
73
static int hf_iax2_absts;
74
static int hf_iax2_lateness;
75
static int hf_iax2_minividmarker;
76
static int hf_iax2_oseqno;
77
static int hf_iax2_iseqno;
78
static int hf_iax2_type;
79
static int hf_iax2_csub;
80
static int hf_iax2_dtmf_csub;
81
static int hf_iax2_cmd_csub;
82
static int hf_iax2_iax_csub;
83
static int hf_iax2_voice_csub;
84
static int hf_iax2_voice_codec;
85
static int hf_iax2_video_csub;
86
static int hf_iax2_video_codec;
87
static int hf_iax2_marker;
88
static int hf_iax2_modem_csub;
89
static int hf_iax2_text_csub;
90
static int hf_iax2_text_text;
91
static int hf_iax2_html_csub;
92
static int hf_iax2_html_url;
93
static int hf_iax2_trunk_metacmd;
94
static int hf_iax2_trunk_cmddata;
95
static int hf_iax2_trunk_cmddata_ts;
96
static int hf_iax2_trunk_ts;
97
static int hf_iax2_trunk_ncalls;
98
static int hf_iax2_trunk_call_len;
99
static int hf_iax2_trunk_call_scallno;
100
static int hf_iax2_trunk_call_ts;
101
static int hf_iax2_trunk_call_data;
102
103
static int hf_iax2_ie_id;
104
static int hf_iax2_length;
105
static int hf_iax2_version;
106
static int hf_iax2_cap_g723_1;
107
static int hf_iax2_cap_gsm;
108
static int hf_iax2_cap_ulaw;
109
static int hf_iax2_cap_alaw;
110
static int hf_iax2_cap_g726_aal2;
111
static int hf_iax2_cap_adpcm;
112
static int hf_iax2_cap_slinear;
113
static int hf_iax2_cap_lpc10;
114
static int hf_iax2_cap_g729a;
115
static int hf_iax2_cap_speex;
116
static int hf_iax2_cap_ilbc;
117
static int hf_iax2_cap_g726;
118
static int hf_iax2_cap_g722;
119
static int hf_iax2_cap_siren7;
120
static int hf_iax2_cap_siren14;
121
static int hf_iax2_cap_slinear16;
122
static int hf_iax2_cap_jpeg;
123
static int hf_iax2_cap_png;
124
static int hf_iax2_cap_h261;
125
static int hf_iax2_cap_h263;
126
static int hf_iax2_cap_h263_plus;
127
static int hf_iax2_cap_h264;
128
static int hf_iax2_cap_mpeg4;
129
static int hf_iax2_cap_vp8;
130
static int hf_iax2_cap_t140_red;
131
static int hf_iax2_cap_t140;
132
static int hf_iax2_cap_g719;
133
static int hf_iax2_cap_speex16;
134
static int hf_iax2_cap_opus;
135
static int hf_iax2_cap_testlaw;
136
137
static int * const hf_iax2_caps[] = {
138
  &hf_iax2_cap_g723_1,
139
  &hf_iax2_cap_gsm,
140
  &hf_iax2_cap_ulaw,
141
  &hf_iax2_cap_alaw,
142
  &hf_iax2_cap_g726_aal2,
143
  &hf_iax2_cap_adpcm,
144
  &hf_iax2_cap_slinear,
145
  &hf_iax2_cap_lpc10,
146
  &hf_iax2_cap_g729a,
147
  &hf_iax2_cap_speex,
148
  &hf_iax2_cap_ilbc,
149
  &hf_iax2_cap_g726,
150
  &hf_iax2_cap_g722,
151
  &hf_iax2_cap_siren7,
152
  &hf_iax2_cap_siren14,
153
  &hf_iax2_cap_slinear16,
154
  &hf_iax2_cap_jpeg,
155
  &hf_iax2_cap_png,
156
  &hf_iax2_cap_h261,
157
  &hf_iax2_cap_h263,
158
  &hf_iax2_cap_h263_plus,
159
  &hf_iax2_cap_h264,
160
  &hf_iax2_cap_mpeg4,
161
  &hf_iax2_cap_vp8,
162
  &hf_iax2_cap_t140_red,
163
  &hf_iax2_cap_t140,
164
  &hf_iax2_cap_g719,
165
  &hf_iax2_cap_speex16,
166
  &hf_iax2_cap_opus,
167
  &hf_iax2_cap_testlaw,
168
  NULL
169
};
170
171
static int hf_iax2_fragment_unfinished;
172
static int hf_iax2_payload_data;
173
static int hf_iax2_fragments;
174
static int hf_iax2_fragment;
175
static int hf_iax2_fragment_overlap;
176
static int hf_iax2_fragment_overlap_conflict;
177
static int hf_iax2_fragment_multiple_tails;
178
static int hf_iax2_fragment_too_long_fragment;
179
static int hf_iax2_fragment_error;
180
static int hf_iax2_fragment_count;
181
static int hf_iax2_reassembled_in;
182
static int hf_iax2_reassembled_length;
183
184
185
/* hf_iax2_ies is an array of header fields, one per potential Information
186
 * Element. It's done this way (rather than having separate variables for each
187
 * IE) to make the dissection of information elements clearer and more
188
 * orthogonal.
189
 *
190
 * To add the ability to dissect a new information element, just add an
191
 * appropriate entry to hf[] in proto_register_iax2(); dissect_ies() will then
192
 * pick it up automatically.
193
 */
194
1.57k
#define NUM_HF_IAX2_IES 256
195
static int hf_iax2_ies[NUM_HF_IAX2_IES];
196
static int hf_iax2_ie_datetime;
197
static int hf_IAX_IE_APPARENTADDR_SINFAMILY;
198
static int hf_IAX_IE_APPARENTADDR_SINPORT;
199
static int hf_IAX_IE_APPARENTADDR_SINADDR;
200
static int hf_IAX_IE_UNKNOWN_BYTE;
201
static int hf_IAX_IE_UNKNOWN_I16;
202
static int hf_IAX_IE_UNKNOWN_I32;
203
static int hf_IAX_IE_UNKNOWN_BYTES;
204
205
/* These are the ids of the subtrees that we may be creating */
206
static int ett_iax2;
207
static int ett_iax2_full_mini_subtree;
208
static int ett_iax2_type;              /* Frame-type specific subtree */
209
static int ett_iax2_ie;                /* single IE */
210
static int ett_iax2_codecs;            /* capabilities IE */
211
static int ett_iax2_ies_apparent_addr; /* apparent address IE */
212
static int ett_iax2_fragment;
213
static int ett_iax2_fragments;
214
static int ett_iax2_trunk_cmddata;
215
static int ett_iax2_trunk_call;
216
217
static expert_field ei_iax_too_many_transfers;
218
static expert_field ei_iax_circuit_id_conflict;
219
static expert_field ei_iax_peer_address_unsupported;
220
static expert_field ei_iax_invalid_len;
221
222
static dissector_handle_t iax2_handle;
223
224
static const fragment_items iax2_fragment_items = {
225
  &ett_iax2_fragment,
226
  &ett_iax2_fragments,
227
  &hf_iax2_fragments,
228
  &hf_iax2_fragment,
229
  &hf_iax2_fragment_overlap,
230
  &hf_iax2_fragment_overlap_conflict,
231
  &hf_iax2_fragment_multiple_tails,
232
  &hf_iax2_fragment_too_long_fragment,
233
  &hf_iax2_fragment_error,
234
  &hf_iax2_fragment_count,
235
  &hf_iax2_reassembled_in,
236
  &hf_iax2_reassembled_length,
237
  /* Reassembled data field */
238
  NULL,
239
  "iax2 fragments"
240
};
241
242
/* data-call subdissectors, AST_DATAFORMAT_* */
243
static dissector_table_t iax2_dataformat_dissector_table;
244
/* voice/video call subdissectors, AST_FORMAT_* */
245
static dissector_table_t iax2_codec_dissector_table;
246
247
248
/* IAX2 Meta trunk packet Command data flags */
249
60
#define IAX2_TRUNK_TS 1
250
251
/* IAX2 Full-frame types */
252
static const value_string iax_frame_types[] = {
253
  {0,                    "(0?)"},
254
  {AST_FRAME_DTMF_END,   "DTMF End"},
255
  {AST_FRAME_VOICE,      "Voice"},
256
  {AST_FRAME_VIDEO,      "Video"},
257
  {AST_FRAME_CONTROL,    "Control"},
258
  {AST_FRAME_NULL,       "NULL"},
259
  {AST_FRAME_IAX,        "IAX"},
260
  {AST_FRAME_TEXT,       "Text"},
261
  {AST_FRAME_IMAGE,      "Image"},
262
  {AST_FRAME_HTML,       "HTML"},
263
  {AST_FRAME_CNG,        "Comfort Noise"},
264
  {AST_FRAME_MODEM,      "Modem"},
265
  {AST_FRAME_DTMF_BEGIN, "DTMF Begin"},
266
  {0, NULL}
267
};
268
static value_string_ext iax_frame_types_ext = VALUE_STRING_EXT_INIT(iax_frame_types);
269
270
/* Subclasses for IAX packets */
271
static const value_string iax_iax_subclasses[] = {
272
  { 0, "(0?)"},
273
  { 1, "NEW"},
274
  { 2, "PING"},
275
  { 3, "PONG"},
276
  { 4, "ACK"},
277
  { 5, "HANGUP"},
278
  { 6, "REJECT"},
279
  { 7, "ACCEPT"},
280
  { 8, "AUTHREQ"},
281
  { 9, "AUTHREP"},
282
  {10, "INVAL"},
283
  {11, "LAGRQ"},
284
  {12, "LAGRP"},
285
  {13, "REGREQ"},
286
  {14, "REGAUTH"},
287
  {15, "REGACK"},
288
  {16, "REGREJ"},
289
  {17, "REGREL"},
290
  {18, "VNAK"},
291
  {19, "DPREQ"},
292
  {20, "DPREP"},
293
  {21, "DIAL"},
294
  {22, "TXREQ"},
295
  {23, "TXCNT"},
296
  {24, "TXACC"},
297
  {25, "TXREADY"},
298
  {26, "TXREL"},
299
  {27, "TXREJ"},
300
  {28, "QUELCH"},
301
  {29, "UNQULCH"},
302
  {30, "POKE"},
303
  {31, "PAGE"},
304
  {32, "MWI"},
305
  {33, "UNSUPPORTED"},
306
  {34, "TRANSFER"},
307
  {35, "PROVISION"},
308
  {36, "FWDOWNL"},
309
  {37, "FWDATA"},
310
  {38, "TXMEDIA"},
311
  {39, "RTKEY"},
312
  {40, "CALLTOKEN"},
313
  {0, NULL}
314
};
315
static value_string_ext iax_iax_subclasses_ext = VALUE_STRING_EXT_INIT(iax_iax_subclasses);
316
317
/* Subclasses for Control packets */
318
static const value_string iax_cmd_subclasses[] = {
319
  {0, "(0?)"},
320
  {1, "HANGUP"},
321
  {2, "RING"},
322
  {3, "RINGING"},
323
  {4, "ANSWER"},
324
  {5, "BUSY"},
325
  {6, "TKOFFHK"},
326
  {7, "OFFHOOK"},
327
  {0xFF, "stop sounds"}, /* sent by app_dial, and not much else */
328
  {0, NULL}
329
};
330
static value_string_ext iax_cmd_subclasses_ext = VALUE_STRING_EXT_INIT(iax_cmd_subclasses);
331
332
/* IAX2 to tap-voip call state mapping for command frames */
333
static const voip_call_state tap_cmd_voip_state[] = {
334
  VOIP_NO_STATE,
335
  VOIP_COMPLETED, /*HANGUP*/
336
  VOIP_RINGING,   /*RING*/
337
  VOIP_RINGING,   /*RINGING*/
338
  VOIP_IN_CALL,   /*ANSWER*/
339
  VOIP_REJECTED,  /*BUSY*/
340
  VOIP_UNKNOWN,   /*TKOFFHK*/
341
  VOIP_UNKNOWN    /*OFFHOOK*/
342
};
343
2
#define NUM_TAP_CMD_VOIP_STATES array_length(tap_cmd_voip_state)
344
345
/* IAX2 to tap-voip call state mapping for IAX frames */
346
static const voip_call_state tap_iax_voip_state[] = {
347
  VOIP_NO_STATE,
348
  VOIP_CALL_SETUP, /*NEW*/
349
  VOIP_NO_STATE,
350
  VOIP_NO_STATE,
351
  VOIP_COMPLETED,  /*HANGUP*/
352
  VOIP_REJECTED,   /*REJECT*/
353
  VOIP_RINGING,    /*ACCEPT*/
354
  VOIP_NO_STATE,
355
  VOIP_NO_STATE,
356
  VOIP_NO_STATE,
357
  VOIP_NO_STATE,
358
  VOIP_NO_STATE,
359
  VOIP_NO_STATE,
360
  VOIP_NO_STATE,
361
  VOIP_NO_STATE,
362
  VOIP_NO_STATE,
363
  VOIP_NO_STATE,
364
  VOIP_NO_STATE,
365
  VOIP_NO_STATE,
366
  VOIP_NO_STATE,
367
  VOIP_NO_STATE,
368
  VOIP_CALL_SETUP, /*DIAL*/
369
  VOIP_NO_STATE,
370
  VOIP_NO_STATE,
371
  VOIP_NO_STATE,
372
  VOIP_NO_STATE,
373
  VOIP_NO_STATE,
374
  VOIP_NO_STATE,
375
  VOIP_NO_STATE,
376
  VOIP_NO_STATE,
377
  VOIP_NO_STATE,
378
  VOIP_NO_STATE,
379
  VOIP_NO_STATE,
380
  VOIP_NO_STATE,
381
  VOIP_NO_STATE,
382
  VOIP_NO_STATE,
383
  VOIP_NO_STATE,
384
  VOIP_NO_STATE
385
};
386
387
79
#define NUM_TAP_IAX_VOIP_STATES array_length(tap_iax_voip_state)
388
389
/* Subclasses for Modem packets */
390
static const value_string iax_modem_subclasses[] = {
391
  {0, "(0?)"},
392
  {1, "T.38"},
393
  {2, "V.150"},
394
  {0, NULL}
395
};
396
397
/* Subclasses for Text packets */
398
static const value_string iax_text_subclasses[] = {
399
  {0, "Text"},
400
  {0, NULL}
401
};
402
403
/* Subclasses for HTML packets */
404
static const value_string iax_html_subclasses[] = {
405
  {0x01, "Sending a URL"},
406
  {0x02, "Data frame"},
407
  {0x04, "Beginning frame"},
408
  {0x08, "End frame"},
409
  {0x10, "Load is complete"},
410
  {0x11, "Peer does not support HTML"},
411
  {0x12, "Link URL"},
412
  {0x13, "Unlink URL"},
413
  {0x14, "Reject Link URL"},
414
  {0, NULL}
415
};
416
417
418
/* Information elements */
419
static const value_string iax_ies_type[] = {
420
  {IAX_IE_CALLED_NUMBER,   "Number/extension being called"},
421
  {IAX_IE_CALLING_NUMBER,  "Calling number"},
422
  {IAX_IE_CALLING_ANI,     "Calling number ANI for billing"},
423
  {IAX_IE_CALLING_NAME,    "Name of caller"},
424
  {IAX_IE_CALLED_CONTEXT,  "Context for number"},
425
  {IAX_IE_USERNAME,        "Username (peer or user) for authentication"},
426
  {IAX_IE_PASSWORD,        "Password for authentication"},
427
  {IAX_IE_CAPABILITY,      "Actual codec capability"},
428
  {IAX_IE_FORMAT,          "Desired codec format"},
429
  {IAX_IE_LANGUAGE,        "Desired language"},
430
  {IAX_IE_VERSION,         "Protocol version"},
431
  {IAX_IE_ADSICPE,         "CPE ADSI capability"},
432
  {IAX_IE_DNID,            "Originally dialed DNID"},
433
  {IAX_IE_AUTHMETHODS,     "Authentication method(s)"},
434
  {IAX_IE_CHALLENGE,       "Challenge data for MD5/RSA"},
435
  {IAX_IE_MD5_RESULT,      "MD5 challenge result"},
436
  {IAX_IE_RSA_RESULT,      "RSA challenge result"},
437
  {IAX_IE_APPARENT_ADDR,   "Apparent address of peer"},
438
  {IAX_IE_REFRESH,         "When to refresh registration"},
439
  {IAX_IE_DPSTATUS,        "Dialplan status"},
440
  {IAX_IE_CALLNO,          "Call number of peer"},
441
  {IAX_IE_CAUSE,           "Cause"},
442
  {IAX_IE_IAX_UNKNOWN,     "Unknown IAX command"},
443
  {IAX_IE_MSGCOUNT,        "How many messages waiting"},
444
  {IAX_IE_AUTOANSWER,      "Request auto-answering"},
445
  {IAX_IE_MUSICONHOLD,     "Request musiconhold with QUELCH"},
446
  {IAX_IE_TRANSFERID,      "Transfer Request Identifier"},
447
  {IAX_IE_RDNIS,           "Referring DNIS"},
448
  {IAX_IE_PROVISIONING,    "Provisioning info"},
449
  {IAX_IE_AESPROVISIONING, "AES Provisioning info"},
450
  {IAX_IE_DATETIME,        "Date/Time"},
451
  {IAX_IE_DEVICETYPE,      "Device type"},
452
  {IAX_IE_SERVICEIDENT,    "Service Identifier"},
453
  {IAX_IE_FIRMWAREVER,     "Firmware revision"},
454
  {IAX_IE_FWBLOCKDESC,     "Firmware block description"},
455
  {IAX_IE_FWBLOCKDATA,     "Firmware block of data"},
456
  {IAX_IE_PROVVER,         "Provisioning version"},
457
  {IAX_IE_CALLINGPRES,     "Calling presentation"},
458
  {IAX_IE_CALLINGTON,      "Calling type of number"},
459
  {IAX_IE_CALLINGTNS,      "Calling transit network select"},
460
  {IAX_IE_SAMPLINGRATE,    "Supported sampling rates"},
461
  {IAX_IE_CAUSECODE,       "Hangup cause"},
462
  {IAX_IE_ENCRYPTION,      "Encryption format"},
463
  {IAX_IE_ENCKEY,          "Raw encryption key"},
464
  {IAX_IE_CODEC_PREFS,     "Codec preferences"},
465
  {IAX_IE_RR_JITTER,       "Received jitter"},
466
  {IAX_IE_RR_LOSS,         "Received loss"},
467
  {IAX_IE_RR_PKTS,         "Received frames"},
468
  {IAX_IE_RR_DELAY,        "Max playout delay in ms for received frames"},
469
  {IAX_IE_RR_DROPPED,      "Dropped frames"},
470
  {IAX_IE_RR_OOO,          "Frames received out of order"},
471
  {IAX_IE_VARIABLE,        "IAX2 variable"},
472
  {IAX_IE_OSPTOKEN,        "OSP Token"},
473
  {IAX_IE_CALLTOKEN,       "Call Token"},
474
  {IAX_IE_CAPABILITY2,     "64-bit codec capability"},
475
  {IAX_IE_FORMAT2,         "64-bit codec format"},
476
  {IAX_IE_DATAFORMAT,      "Data call format"},
477
  {0, NULL}
478
};
479
static value_string_ext iax_ies_type_ext = VALUE_STRING_EXT_INIT(iax_ies_type);
480
481
494
#define CODEC_MASK(codec) ((codec) == (uint32_t)-1 ? 0 : (UINT64_C(1) << (codec)))
482
483
static const val64_string codec_types[] = {
484
  {CODEC_MASK(AST_FORMAT_G723_1),    "G.723.1 compression"},
485
  {CODEC_MASK(AST_FORMAT_GSM),       "GSM compression"},
486
  {CODEC_MASK(AST_FORMAT_ULAW),      "Raw mu-law data (G.711)"},
487
  {CODEC_MASK(AST_FORMAT_ALAW),      "Raw A-law data (G.711)"},
488
  {CODEC_MASK(AST_FORMAT_G726_AAL2), "ADPCM (G.726), 32kbps, AAL2 codeword packing)"},
489
  {CODEC_MASK(AST_FORMAT_ADPCM),     "ADPCM (IMA)"},
490
  {CODEC_MASK(AST_FORMAT_SLINEAR),   "Raw 16-bit Signed Linear (8000 Hz) PCM"},
491
  {CODEC_MASK(AST_FORMAT_LPC10),     "LPC10, 180 samples/frame"},
492
  {CODEC_MASK(AST_FORMAT_G729A),     "G.729a Audio"},
493
  {CODEC_MASK(AST_FORMAT_SPEEX),     "SpeeX Free Compression"},
494
  {CODEC_MASK(AST_FORMAT_ILBC),      "iLBC Free Compression"},
495
  {CODEC_MASK(AST_FORMAT_G726),      "ADPCM (G.726, 32kbps, RFC3551 codeword packing)"},
496
  {CODEC_MASK(AST_FORMAT_G722),      "G.722"},
497
  {CODEC_MASK(AST_FORMAT_SIREN7),    "G.722.1 (also known as Siren7, 32kbps assumed)"},
498
  {CODEC_MASK(AST_FORMAT_SIREN14),   "G.722.1 Annex C (also known as Siren14, 48kbps assumed)"},
499
  {CODEC_MASK(AST_FORMAT_SLINEAR16), "Raw 16-bit Signed Linear (16000 Hz) PCM"},
500
  {CODEC_MASK(AST_FORMAT_JPEG),      "JPEG Images"},
501
  {CODEC_MASK(AST_FORMAT_PNG),       "PNG Images"},
502
  {CODEC_MASK(AST_FORMAT_H261),      "H.261 Video"},
503
  {CODEC_MASK(AST_FORMAT_H263),      "H.263 Video"},
504
  {CODEC_MASK(AST_FORMAT_H263_PLUS), "H.263+ Video"},
505
  {CODEC_MASK(AST_FORMAT_H264),      "H.264 Video"},
506
  {CODEC_MASK(AST_FORMAT_MP4_VIDEO), "MPEG4 Video"},
507
  {CODEC_MASK(AST_FORMAT_VP8),       "VP8 Video"},
508
  {CODEC_MASK(AST_FORMAT_T140_RED),  "T.140 RED Text format RFC 4103"},
509
  {CODEC_MASK(AST_FORMAT_T140),      "T.140 Text format - ITU T.140, RFC 4103"},
510
  {CODEC_MASK(AST_FORMAT_G719),      "G.719 (64 kbps assumed)"},
511
  {CODEC_MASK(AST_FORMAT_SPEEX16),   "SpeeX Wideband (16kHz) Free Compression"},
512
  {CODEC_MASK(AST_FORMAT_OPUS),      "Opus audio (8kHz, 16kHz, 24kHz, 48Khz)"},
513
  {CODEC_MASK(AST_FORMAT_TESTLAW),   "Raw testing-law data (G.711)"},
514
  {0, NULL}
515
};
516
static val64_string_ext codec_types_ext = VAL64_STRING_EXT_INIT(codec_types);
517
518
static const value_string iax_dataformats[] = {
519
  {AST_DATAFORMAT_NULL,      "N/A (analogue call?)"},
520
  {AST_DATAFORMAT_V110,      "ITU-T V.110 rate adaption"},
521
  {AST_DATAFORMAT_H223_H245, "ITU-T H.223/H.245"},
522
  {0, NULL}
523
};
524
525
526
static const value_string iax_packet_types[] = {
527
  {IAX2_FULL_PACKET,       "Full packet"},
528
  {IAX2_MINI_VOICE_PACKET, "Mini voice packet"},
529
  {IAX2_MINI_VIDEO_PACKET, "Mini video packet"},
530
  {IAX2_TRUNK_PACKET,      "Trunk packet"},
531
  {0, NULL}
532
};
533
534
static const value_string iax_causecodes[] = {
535
  {AST_CAUSE_UNALLOCATED,                   "Unallocated"},
536
  {AST_CAUSE_NO_ROUTE_TRANSIT_NET,          "No route transit net"},
537
  {AST_CAUSE_NO_ROUTE_DESTINATION,          "No route to destination"},
538
  {AST_CAUSE_MISDIALLED_TRUNK_PREFIX,       "Misdialled trunk prefix"},
539
  {AST_CAUSE_CHANNEL_UNACCEPTABLE,          "Channel unacceptable"},
540
  {AST_CAUSE_CALL_AWARDED_DELIVERED,        "Call awarded delivered"},
541
  {AST_CAUSE_PRE_EMPTED,                    "Preempted"},
542
  {AST_CAUSE_NUMBER_PORTED_NOT_HERE,        "Number ported not here"},
543
  {AST_CAUSE_NORMAL_CLEARING,               "Normal clearing"},
544
  {AST_CAUSE_USER_BUSY,                     "User busy"},
545
  {AST_CAUSE_NO_USER_RESPONSE,              "No user response"},
546
  {AST_CAUSE_NO_ANSWER,                     "No answer"},
547
  {AST_CAUSE_SUBSCRIBER_ABSENT,             "Subscriber absent"},
548
  {AST_CAUSE_CALL_REJECTED,                 "Call rejected"},
549
  {AST_CAUSE_NUMBER_CHANGED,                "Number changed"},
550
  {AST_CAUSE_REDIRECTED_TO_NEW_DESTINATION, "Redirected to new destination"},
551
  {AST_CAUSE_ANSWERED_ELSEWHERE,            "Answered elsewhere"},
552
  {AST_CAUSE_DESTINATION_OUT_OF_ORDER,      "Destination out of order"},
553
  {AST_CAUSE_INVALID_NUMBER_FORMAT,         "Invalid number format"},
554
  {AST_CAUSE_FACILITY_REJECTED,             "Facility rejected"},
555
  {AST_CAUSE_RESPONSE_TO_STATUS_ENQUIRY,    "Response to status inquiry"},
556
  {AST_CAUSE_NORMAL_UNSPECIFIED,            "Normal unspecified"},
557
  {AST_CAUSE_NORMAL_CIRCUIT_CONGESTION,     "Normal circuit congestion"},
558
  {AST_CAUSE_NETWORK_OUT_OF_ORDER,          "Network out of order"},
559
  {AST_CAUSE_NORMAL_TEMPORARY_FAILURE,      "Normal temporary failure"},
560
  {AST_CAUSE_SWITCH_CONGESTION,             "Switch congestion"},
561
  {AST_CAUSE_ACCESS_INFO_DISCARDED,         "Access info discarded"},
562
  {AST_CAUSE_REQUESTED_CHAN_UNAVAIL,        "Requested channel unavailable"},
563
  {AST_CAUSE_FACILITY_NOT_SUBSCRIBED,       "Facility not subscribed"},
564
  {AST_CAUSE_OUTGOING_CALL_BARRED,          "Outgoing call barred"},
565
  {AST_CAUSE_INCOMING_CALL_BARRED,          "Incoming call barred"},
566
  {AST_CAUSE_BEARERCAPABILITY_NOTAUTH,      "Bearer capability not authorized"},
567
  {AST_CAUSE_BEARERCAPABILITY_NOTAVAIL,     "Bearer capability not available"},
568
  {AST_CAUSE_BEARERCAPABILITY_NOTIMPL,      "Bearer capability not implemented"},
569
  {AST_CAUSE_CHAN_NOT_IMPLEMENTED,          "Channel not implemented"},
570
  {AST_CAUSE_FACILITY_NOT_IMPLEMENTED,      "Facility not implemented"},
571
  {AST_CAUSE_INVALID_CALL_REFERENCE,        "Invalid call reference"},
572
  {AST_CAUSE_INCOMPATIBLE_DESTINATION,      "Incompatible destination"},
573
  {AST_CAUSE_INVALID_MSG_UNSPECIFIED,       "Invalid message unspecified"},
574
  {AST_CAUSE_MANDATORY_IE_MISSING,          "Mandatory IE missing"},
575
  {AST_CAUSE_MESSAGE_TYPE_NONEXIST,         "Message type nonexistent"},
576
  {AST_CAUSE_WRONG_MESSAGE,                 "Wrong message"},
577
  {AST_CAUSE_IE_NONEXIST,                   "IE nonexistent"},
578
  {AST_CAUSE_INVALID_IE_CONTENTS,           "Invalid IE contents"},
579
  {AST_CAUSE_WRONG_CALL_STATE,              "Wrong call state"},
580
  {AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE,      "Recovery on timer expire"},
581
  {AST_CAUSE_MANDATORY_IE_LENGTH_ERROR,     "Mandatory IE length error"},
582
  {AST_CAUSE_PROTOCOL_ERROR,                "Protocol error"},
583
  {AST_CAUSE_INTERWORKING,                  "Interworking"},
584
  {0, NULL}
585
};
586
static value_string_ext iax_causecodes_ext = VALUE_STRING_EXT_INIT(iax_causecodes);
587
588
/* ************************************************************************* */
589
590
/* In order to track IAX calls, we have a hash table which maps
591
 * {addr,port type,port,call} to a unique circuit id.
592
 *
593
 * Each call has two such circuits associated with it (a forward and a
594
 * reverse circuit, where 'forward' is defined as the direction the NEW
595
 * packet went in), and we maintain an iax_call_data structure for each
596
 * call, attached to both circuits with circuit_add_proto_data.
597
 *
598
 * Because {addr,port type,port,call} quadruplets can be reused
599
 * (Asterisk reuses call numbers), circuit ids aren't unique to
600
 * individual calls and we treat NEW packets somewhat specially. When we
601
 * get such a packet, we see if there are any calls with a matching
602
 * circuit id, and make sure that its circuits are marked as ended
603
 * before that packet.
604
 *
605
 * A second complication is that we only know one quadruplet at the time
606
 * the NEW packet is processed: there is therefore cunningness in
607
 * iax_lookup_circuit_details() to look for replies to NEW packets and
608
 * create the reverse circuit.
609
 */
610
611
612
/* start with a hash of {addr,port type,port,call}->{id} */
613
614
typedef struct {
615
  address   addr;
616
  port_type ptype;
617
  uint32_t  port;
618
  uint32_t  callno;
619
620
  /* this is where addr->data points to. it's put in here for easy freeing */
621
  uint8_t address_data[MAX_ADDRESS];
622
} iax_circuit_key;
623
624
/* tables */
625
static GHashTable *iax_fid_table;
626
static reassembly_table iax_reassembly_table;
627
628
static GHashTable *iax_circuit_hashtab;
629
static unsigned circuitcount;
630
631
/* the number of keys and values to reserve space for in each memory chunk.
632
   We assume we won't be tracking many calls at once so this is quite low.
633
*/
634
#define IAX_INIT_PACKET_COUNT 10
635
636
#ifdef DEBUG_HASHING
637
static char *key_to_str( const iax_circuit_key *key )
638
{
639
  static int    i = 0;
640
  static char   str[3][80];
641
  char         *strp;
642
  char         *addrstr;
643
644
  i++;
645
  if (i >= 3) {
646
    i = 0;
647
  }
648
  strp = str[i];
649
650
  addrstr = address_to_str(NULL, &key->addr);
651
  snprintf(strp, 80, "{%s:%i,%i}",
652
             addrstr,
653
             key->port,
654
             key->callno);
655
  wmem_free(NULL, addrstr);
656
  return strp;
657
}
658
#endif
659
660
/* Hash Functions */
661
static int iax_circuit_equal(const void *v, const void *w)
662
154
{
663
154
  const iax_circuit_key *v1 = (const iax_circuit_key *)v;
664
154
  const iax_circuit_key *v2 = (const iax_circuit_key *)w;
665
154
  int result;
666
667
154
  result = (addresses_equal(&(v1->addr), &(v2->addr)) &&
668
154
            v1->ptype == v2->ptype &&
669
154
            v1->port  == v2->port  &&
670
154
            v1->callno== v2->callno);
671
#ifdef DEBUG_HASHING
672
  ws_debug("+++ Comparing for equality: %s, %s: %u", key_to_str(v1), key_to_str(v2), result);
673
#endif
674
675
154
  return result;
676
154
}
677
678
static unsigned iax_circuit_hash(const void *v)
679
240
{
680
240
  const iax_circuit_key *key = (const iax_circuit_key *)v;
681
240
  unsigned               hash_val;
682
683
240
  hash_val = 0;
684
240
  hash_val = add_address_to_hash(hash_val, &key->addr);
685
240
  hash_val += (unsigned)(key->ptype);
686
240
  hash_val += (unsigned)(key->port);
687
240
  hash_val += (unsigned)(key->callno);
688
689
#ifdef DEBUG_HASHING
690
  ws_debug("+++ Hashing key: %s, result %#x", key_to_str(key), hash_val);
691
#endif
692
693
240
  return (unsigned)hash_val;
694
240
}
695
696
/* Find, or create, a circuit for the given
697
   {address,porttype,port,call} quadruplet
698
*/
699
static unsigned iax_circuit_lookup(const address *address_p,
700
                                port_type ptype,
701
                                uint32_t port,
702
                                uint32_t callno)
703
197
{
704
197
  iax_circuit_key  key;
705
197
  uint32_t        *circuit_id_p;
706
707
197
  key.addr   = *address_p;
708
197
  key.ptype  = ptype;
709
197
  key.port   = port;
710
197
  key.callno = callno;
711
712
197
  circuit_id_p = (uint32_t *)g_hash_table_lookup(iax_circuit_hashtab, &key);
713
197
  if (! circuit_id_p) {
714
43
    iax_circuit_key *new_key;
715
716
43
    new_key = wmem_new(wmem_file_scope(), iax_circuit_key);
717
43
    new_key->addr.type = address_p->type;
718
43
    new_key->addr.len  = MIN(address_p->len, MAX_ADDRESS);
719
43
    new_key->addr.data = new_key->address_data;
720
43
    if (new_key->addr.len > 0)
721
0
      memcpy(new_key->address_data, address_p->data, new_key->addr.len);
722
43
    new_key->ptype     = ptype;
723
43
    new_key->port      = port;
724
43
    new_key->callno    = callno;
725
726
43
    circuit_id_p  = (uint32_t *)wmem_new(wmem_file_scope(), iax_circuit_key);
727
43
    *circuit_id_p = ++circuitcount;
728
729
43
    g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p);
730
731
#ifdef DEBUG_HASHING
732
    ws_debug("Created new circuit id %u for node %s", *circuit_id_p, key_to_str(new_key));
733
#endif
734
43
  }
735
736
197
  return *circuit_id_p;
737
197
}
738
739
740
/* ************************************************************************* */
741
742
typedef struct {
743
  uint32_t    current_frag_id; /* invalid unless current_frag_bytes > 0 */
744
  uint32_t    current_frag_bytes;
745
  uint32_t    current_frag_minlen;
746
} iax_call_dirdata;
747
748
/* This is our per-call data structure, which is attached to both the
749
 * forward and reverse circuits.
750
 */
751
typedef struct iax_call_data {
752
  /* For this data, src and dst are relative to the original direction under
753
     which this call is stored. Obviously if the reversed flag is set true by
754
     iax_find_call, src and dst are reversed relative to the direction the
755
     actual source and destination of the data.
756
757
     if the codec changes mid-call, we update it here; because we store a codec
758
     number with each packet too, we handle going back to earlier packets
759
     without problem.
760
  */
761
762
  iax_dataformat_t dataformat;
763
  uint32_t         src_codec, dst_codec;
764
  uint32_t         src_vformat, dst_vformat;
765
766
  /* when a transfer takes place, we'll get a new circuit id; we assume that we
767
     don't try to transfer more than IAX_MAX_TRANSFERS times in a call */
768
  unsigned forward_circuit_ids[IAX_MAX_TRANSFERS];
769
  unsigned reverse_circuit_ids[IAX_MAX_TRANSFERS];
770
  unsigned n_forward_circuit_ids;
771
  unsigned n_reverse_circuit_ids;
772
773
  /* this is the subdissector for the call */
774
  dissector_handle_t subdissector;
775
776
  /* the absolute start time of the call */
777
  nstime_t start_time;
778
779
  /* time stamp from last full frame, in the first pass */
780
  uint32_t last_full_frame_ts;
781
782
  iax_call_dirdata dirdata[2];
783
} iax_call_data;
784
785
786
787
/* creates a new CONVERSATION_IAX2 circuit with a specified circuit id for a call
788
 *
789
 * typically a call has up to three associated circuits: an original source, an
790
 * original destination, and the result of a transfer.
791
 *
792
 * For each endpoint, a CONVERSATION_IAX2 circuit is created and added to the call_data
793
 * by this function
794
 *
795
 * 'reversed' should be true if this end is the one which would have _received_
796
 * the NEW packet, or it is an endpoint to which the 'destination' is being
797
 * transferred.
798
 *
799
 */
800
static conversation_t *iax2_new_circuit_for_call(packet_info *pinfo, proto_item * item,
801
                                            unsigned circuit_id, unsigned framenum,
802
                                            iax_call_data *iax_call, bool reversed)
803
1
{
804
1
  conversation_t *conv;
805
806
1
  if(!iax_call){
807
0
    return NULL;
808
0
  }
809
1
  if ((reversed && iax_call->n_reverse_circuit_ids >= IAX_MAX_TRANSFERS) ||
810
1
      (! reversed && iax_call->n_forward_circuit_ids >= IAX_MAX_TRANSFERS)) {
811
0
    expert_add_info(pinfo, item, &ei_iax_too_many_transfers);
812
0
    return NULL;
813
0
  }
814
815
1
  conv = conversation_new_by_id(framenum, CONVERSATION_IAX2,
816
1
                    circuit_id);
817
818
1
  conversation_add_proto_data(conv, proto_iax2, iax_call);
819
820
1
  if (reversed)
821
0
    iax_call -> reverse_circuit_ids[iax_call->n_reverse_circuit_ids++] = circuit_id;
822
1
  else
823
1
    iax_call -> forward_circuit_ids[iax_call->n_forward_circuit_ids++] = circuit_id;
824
825
1
  return conv;
826
1
}
827
828
829
/* returns true if this circuit id is a "forward" circuit for this call: ie, it
830
 * is the point which _sent_ the original 'NEW' packet, or a point to which that
831
 * end was subsequently transferred */
832
static bool is_forward_circuit(unsigned circuit_id,
833
                                   const iax_call_data *iax_call)
834
0
{
835
0
  unsigned i;
836
0
  for(i=0; i<iax_call->n_forward_circuit_ids; i++) {
837
0
    if (circuit_id == iax_call->forward_circuit_ids[i])
838
0
      return true;
839
0
  }
840
0
  return false;
841
0
}
842
843
/* returns true if this circuit id is a "reverse" circuit for this call: ie, it
844
 * is the point which _received_ the original 'NEW' packet, or a point to which that
845
 * end was subsequently transferred */
846
static bool is_reverse_circuit(unsigned circuit_id,
847
                                   const iax_call_data *iax_call)
848
0
{
849
0
  unsigned i;
850
0
  for(i=0; i<iax_call->n_reverse_circuit_ids; i++){
851
0
    if (circuit_id == iax_call->reverse_circuit_ids[i])
852
0
      return true;
853
0
  }
854
0
  return false;
855
0
}
856
857
858
static iax_call_data *iax_lookup_call_from_dest(packet_info *pinfo, proto_item * item,
859
                                                 unsigned src_circuit_id,
860
                                                 unsigned dst_circuit_id,
861
                                                 unsigned framenum,
862
                                                 bool *reversed_p)
863
95
{
864
95
  conversation_t  *dst_conv;
865
95
  iax_call_data *iax_call;
866
95
  bool           reversed = false;
867
868
95
  dst_conv = find_conversation_by_id(framenum, CONVERSATION_IAX2, dst_circuit_id);
869
870
95
  if (!dst_conv) {
871
#ifdef DEBUG_HASHING
872
    ws_debug("++ destination circuit not found, must have missed NEW packet");
873
#endif
874
95
    if (reversed_p)
875
95
      *reversed_p = false;
876
95
    return NULL;
877
95
  }
878
879
#ifdef DEBUG_HASHING
880
  ws_debug("++ found destination circuit");
881
#endif
882
883
0
  iax_call = (iax_call_data *)conversation_get_proto_data(dst_conv, proto_iax2);
884
885
  /* there's no way we can create a CONVERSATION_IAX2 circuit without adding
886
     iax call data to it; assert this */
887
0
  DISSECTOR_ASSERT(iax_call);
888
889
0
  if (is_forward_circuit(dst_circuit_id, iax_call)) {
890
#ifdef DEBUG_HASHING
891
    ws_debug("++ destination circuit matches forward_circuit_id of call, "
892
             "therefore packet is reversed");
893
#endif
894
895
0
    reversed = true;
896
897
0
    if (iax_call -> n_reverse_circuit_ids == 0) {
898
      /* we are going in the reverse direction, and this call
899
         doesn't have a reverse circuit associated with it.
900
         create one now. */
901
#ifdef DEBUG_HASHING
902
      ws_debug("++ reverse_circuit_id of call is zero, need to create a "
903
              "new reverse circuit for this call");
904
#endif
905
906
0
      iax2_new_circuit_for_call(pinfo, item, src_circuit_id, framenum, iax_call, true);
907
#ifdef DEBUG_HASHING
908
      ws_debug("++ done");
909
#endif
910
0
    } else if (!is_reverse_circuit(src_circuit_id, iax_call)) {
911
0
      expert_add_info_format(pinfo, item, &ei_iax_circuit_id_conflict,
912
0
                "IAX Packet %u from circuit ids %u->%u conflicts with earlier call with circuit ids %u->%u",
913
0
                framenum,
914
0
                src_circuit_id, dst_circuit_id,
915
0
                iax_call->forward_circuit_ids[0],
916
0
                iax_call->reverse_circuit_ids[0]);
917
0
      return NULL;
918
0
    }
919
0
  } else if (is_reverse_circuit(dst_circuit_id, iax_call)) {
920
#ifdef DEBUG_HASHING
921
    ws_debug("++ destination circuit matches reverse_circuit_id of call, "
922
            "therefore packet is forward");
923
#endif
924
925
0
    reversed = false;
926
0
    if (!is_forward_circuit(src_circuit_id, iax_call)) {
927
0
      expert_add_info_format(pinfo, item, &ei_iax_circuit_id_conflict,
928
0
                "IAX Packet %u from circuit ids %u->%u conflicts with earlier call with circuit ids %u->%u",
929
0
                framenum,
930
0
                src_circuit_id, dst_circuit_id,
931
0
                iax_call->forward_circuit_ids[0],
932
0
                iax_call->reverse_circuit_ids[0]);
933
0
      if (reversed_p)
934
0
        *reversed_p = false;
935
0
      return NULL;
936
0
    }
937
0
  } else {
938
0
    DISSECTOR_ASSERT_NOT_REACHED();
939
0
  }
940
941
0
  if (reversed_p)
942
0
    *reversed_p = reversed;
943
944
0
  return iax_call;
945
0
}
946
947
948
/* looks up an iax_call for this packet */
949
static iax_call_data *iax_lookup_call( packet_info *pinfo,
950
                                       uint32_t scallno,
951
                                       uint32_t dcallno,
952
                                       bool *reversed_p)
953
101
{
954
101
  bool           reversed = false;
955
101
  iax_call_data *iax_call = NULL;
956
101
  unsigned       src_circuit_id;
957
#ifdef DEBUG_HASHING
958
  char          *srcstr, *dststr;
959
#endif
960
961
#ifdef DEBUG_HASHING
962
  srcstr = address_to_str(NULL, &pinfo->src);
963
  dststr = address_to_str(NULL, &pinfo->dst);
964
  ws_debug("++ iax_lookup_circuit_details: Looking up circuit for frame %u, "
965
          "from {%s:%u:%u} to {%s:%u:%u}", pinfo->num,
966
          srcstr, pinfo->srcport, scallno,
967
          dststr, pinfo->destport, dcallno);
968
  wmem_free(NULL, srcstr);
969
  wmem_free(NULL, dststr);
970
#endif
971
972
973
101
  src_circuit_id = iax_circuit_lookup(&pinfo->src, pinfo->ptype,
974
101
                                      pinfo->srcport, scallno);
975
976
977
  /* the most reliable indicator of call is the destination callno, if
978
     we have one */
979
101
  if (dcallno != 0) {
980
95
    unsigned dst_circuit_id;
981
#ifdef DEBUG_HASHING
982
    ws_debug("++ dcallno non-zero, looking up destination circuit");
983
#endif
984
985
95
    dst_circuit_id = iax_circuit_lookup(&pinfo->dst, pinfo->ptype,
986
95
                                        pinfo->destport, dcallno);
987
988
95
    iax_call = iax_lookup_call_from_dest(pinfo, NULL, src_circuit_id, dst_circuit_id,
989
95
                                         pinfo->num, &reversed);
990
95
  } else {
991
6
    conversation_t *src_conv;
992
993
    /* in all other circumstances, the source circuit should already
994
     * exist: its absence indicates that we missed the all-important NEW
995
     * packet.
996
     */
997
998
6
    src_conv = find_conversation_by_id(pinfo->num, CONVERSATION_IAX2, src_circuit_id);
999
1000
6
    if (src_conv) {
1001
0
      iax_call = (iax_call_data *)conversation_get_proto_data(src_conv, proto_iax2);
1002
1003
      /* there's no way we can create a CONVERSATION_IAX2 circuit without adding
1004
         iax call data to it; assert this */
1005
0
      DISSECTOR_ASSERT(iax_call);
1006
1007
0
      if (is_forward_circuit(src_circuit_id, iax_call))
1008
0
        reversed = false;
1009
0
      else if (is_reverse_circuit(src_circuit_id, iax_call))
1010
0
        reversed = true;
1011
0
      else {
1012
        /* there's also no way we can attach an iax_call_data to a circuit
1013
           without the circuit being either the forward or reverse circuit
1014
           for that call; assert this too.
1015
        */
1016
0
        DISSECTOR_ASSERT_NOT_REACHED();
1017
0
      }
1018
0
    }
1019
6
  }
1020
1021
101
  if (reversed_p)
1022
101
    *reversed_p = reversed;
1023
1024
#ifdef DEBUG_HASHING
1025
  if (iax_call) {
1026
    ws_debug("++ Found call for packet: id %u, reversed=%c", iax_call->forward_circuit_ids[0], reversed?'1':'0');
1027
  } else {
1028
    ws_debug("++ Call not found. Must have missed the NEW packet?");
1029
  }
1030
#endif
1031
1032
101
  return iax_call;
1033
101
}
1034
1035
/* initialize the per-direction parts of an iax_call_data structure */
1036
static void init_dir_data(iax_call_dirdata *dirdata)
1037
2
{
1038
2
  dirdata -> current_frag_bytes=0;
1039
2
  dirdata -> current_frag_minlen=0;
1040
2
}
1041
1042
1043
/* handles a NEW packet by creating a new iax call and forward circuit.
1044
   the reverse circuit is not created until the ACK is received and
1045
   is created by iax_lookup_circuit_details. */
1046
static iax_call_data *iax_new_call( packet_info *pinfo,
1047
                                    uint32_t scallno)
1048
1
{
1049
1
  iax_call_data         *call;
1050
1
  unsigned               circuit_id;
1051
1
  static const nstime_t  millisecond = NSTIME_INIT_SECS_MSECS(0, 1);
1052
1053
#ifdef DEBUG_HASHING
1054
  ws_debug("+ new_circuit: Handling NEW packet, frame %u", pinfo->num);
1055
#endif
1056
1057
1
  circuit_id = iax_circuit_lookup(&pinfo->src, pinfo->ptype,
1058
1
                                  pinfo->srcport, scallno);
1059
1060
1
  call = wmem_new(wmem_file_scope(), iax_call_data);
1061
1
  call -> dataformat = AST_DATAFORMAT_NULL;
1062
1
  call -> src_codec = 0;
1063
1
  call -> dst_codec = 0;
1064
1
  call -> src_vformat = 0;
1065
1
  call -> dst_vformat = 0;
1066
1
  call -> n_forward_circuit_ids = 0;
1067
1
  call -> n_reverse_circuit_ids = 0;
1068
1
  call -> subdissector = NULL;
1069
1
  call -> start_time = pinfo->abs_ts;
1070
1
  call -> last_full_frame_ts = 0;
1071
1
  nstime_delta(&call -> start_time, &call -> start_time, &millisecond);
1072
1
  init_dir_data(&call->dirdata[0]);
1073
1
  init_dir_data(&call->dirdata[1]);
1074
1075
1
  iax2_new_circuit_for_call(pinfo, NULL, circuit_id, pinfo->num, call, false);
1076
1077
1
  return call;
1078
1
}
1079
1080
1081
/* ************************************************************************* */
1082
1083
/* per-packet data */
1084
typedef struct iax_packet_data {
1085
  bool           first_time; /* we're dissecting this packet for the first time; so
1086
                              * things like codec and transfer requests should be
1087
                              * propagated into the call data */
1088
  iax_call_data *call_data;
1089
  uint32_t       codec;
1090
  bool           reversed;
1091
  nstime_t       abstime;    /* the absolute time of this packet, based on its
1092
                              * timestamp and the NEW packet's time (-1 if unknown) */
1093
} iax_packet_data;
1094
1095
static iax_packet_data *iax_new_packet_data(iax_call_data *call, bool reversed)
1096
102
{
1097
102
  iax_packet_data *p = wmem_new(wmem_file_scope(), iax_packet_data);
1098
102
  p->first_time    = true;
1099
102
  p->call_data     = call;
1100
102
  p->codec         = 0;
1101
102
  p->reversed      = reversed;
1102
102
  p->abstime.secs  = -1;
1103
102
  p->abstime.nsecs = -1;
1104
102
  return p;
1105
102
}
1106
1107
static void  iax2_populate_pinfo_from_packet_data(packet_info *pinfo, const iax_packet_data *p)
1108
102
{
1109
102
  if (p->call_data != NULL) {
1110
     /* if we missed the NEW packet for this call, call_data will be null. it's
1111
      * tbd what the best thing to do here is. */
1112
1
    pinfo->p2p_dir = p->reversed?P2P_DIR_RECV:P2P_DIR_SENT;
1113
1114
1
    col_set_str(pinfo->cinfo, COL_IF_DIR, p->reversed ? "rev" : "fwd");
1115
1
  }
1116
102
}
1117
1118
1119
/* ************************************************************************* */
1120
1121
/* this is passed up from the IE dissector to the main dissector */
1122
typedef struct
1123
{
1124
  address   peer_address;
1125
  port_type peer_ptype;
1126
  uint32_t  peer_port;
1127
  uint32_t  peer_callno;
1128
  uint32_t  dataformat;
1129
} iax2_ie_data;
1130
1131
1132
static uint32_t dissect_fullpacket(tvbuff_t *tvb, uint32_t offset,
1133
                                  uint16_t scallno,
1134
                                  packet_info *pinfo,
1135
                                  proto_tree *iax2_tree,
1136
                                  proto_tree *main_tree);
1137
1138
1139
static uint32_t dissect_minipacket(tvbuff_t *tvb, uint32_t offset,
1140
                                  uint16_t scallno,
1141
                                  packet_info *pinfo,
1142
                                  proto_tree *iax2_tree,
1143
                                  proto_tree *main_tree);
1144
1145
static uint32_t dissect_minivideopacket(tvbuff_t *tvb, uint32_t offset,
1146
                                       uint16_t scallno,
1147
                                       packet_info *pinfo,
1148
                                       proto_tree *iax2_tree,
1149
                                       proto_tree *main_tree);
1150
1151
static uint32_t dissect_trunkpacket(tvbuff_t *tvb, uint32_t offset,
1152
                                   uint16_t scallno,
1153
                                   packet_info *pinfo,
1154
                                   proto_tree *iax2_tree,
1155
                                   proto_tree *main_tree);
1156
1157
static void dissect_payload(tvbuff_t *tvb, uint32_t offset,
1158
                            packet_info *pinfo, proto_tree *iax2_tree,
1159
                            proto_tree *tree, uint32_t ts, bool video,
1160
                            iax_packet_data *iax_packet);
1161
1162
1163
1164
static int
1165
dissect_iax2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1166
148
{
1167
148
  proto_item  *iax2_item;
1168
148
  proto_tree  *iax2_tree;
1169
148
  proto_tree  *full_mini_subtree = NULL;
1170
148
  uint32_t     offset            = 0, len;
1171
148
  uint16_t     scallno           = 0;
1172
148
  uint16_t     stmp;
1173
148
  packet_type  type;
1174
148
  proto_item *full_mini_base;
1175
1176
  /* set up the protocol and info fields in the summary pane */
1177
148
  col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2);
1178
148
  col_clear(pinfo->cinfo, COL_INFO);
1179
1180
  /* add the 'iax2' tree to the main tree */
1181
148
  iax2_item = proto_tree_add_item(tree, proto_iax2, tvb, offset, -1, ENC_NA);
1182
148
  iax2_tree = proto_item_add_subtree(iax2_item, ett_iax2);
1183
1184
148
  stmp = tvb_get_ntohs(tvb, offset);
1185
148
  if (stmp == 0) {
1186
    /* starting with 0x0000 indicates meta packet which can be either a mini
1187
     * video packet or a trunk packet */
1188
45
    offset+=2;
1189
45
    stmp = tvb_get_ntohs(tvb, offset);
1190
45
    if (stmp & 0x8000) {
1191
      /* mini video packet */
1192
1
      type = IAX2_MINI_VIDEO_PACKET;
1193
1
      scallno = stmp & 0x7FFF;
1194
1
      offset += 2;
1195
1
    }
1196
44
    else {
1197
44
      type = IAX2_TRUNK_PACKET;
1198
44
    }
1199
103
  } else {
1200
    /* The source call/fullpacket flag is common to both mini and full packets */
1201
103
    scallno = tvb_get_ntohs(tvb, offset);
1202
103
    offset += 2;
1203
103
    if (scallno & 0x8000)
1204
100
      type = IAX2_FULL_PACKET;
1205
3
    else {
1206
3
      type = IAX2_MINI_VOICE_PACKET;
1207
3
    }
1208
103
    scallno &= 0x7FFF;
1209
103
  }
1210
1211
148
  full_mini_base = proto_tree_add_uint(iax2_tree, hf_iax2_packet_type, tvb, 0, offset, type);
1212
148
  full_mini_subtree = proto_item_add_subtree(full_mini_base, ett_iax2_full_mini_subtree);
1213
1214
148
  if (scallno != 0)
1215
104
    proto_tree_add_item(full_mini_subtree, hf_iax2_scallno, tvb, offset-2, 2, ENC_BIG_ENDIAN);
1216
1217
148
  iax2_info->ptype = type;
1218
148
  iax2_info->scallno = 0;
1219
148
  iax2_info->dcallno = 0;
1220
148
  iax2_info->ftype = 0;
1221
148
  iax2_info->csub = 0;
1222
148
  iax2_info->payload_len = 0;
1223
148
  iax2_info->timestamp = 0;
1224
148
  iax2_info->callState = VOIP_NO_STATE;
1225
148
  iax2_info->messageName = NULL;
1226
148
  iax2_info->callingParty = NULL;
1227
148
  iax2_info->calledParty = NULL;
1228
148
  iax2_info->payload_data = NULL;
1229
1230
148
  switch (type) {
1231
100
    case IAX2_FULL_PACKET:
1232
100
      len = dissect_fullpacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree);
1233
100
      break;
1234
3
    case IAX2_MINI_VOICE_PACKET:
1235
3
      iax2_info->messageName = "MINI_VOICE_PACKET";
1236
3
      len = dissect_minipacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree);
1237
3
      break;
1238
1
    case IAX2_MINI_VIDEO_PACKET:
1239
1
      iax2_info->messageName = "MINI_VIDEO_PACKET";
1240
1
      len = dissect_minivideopacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree);
1241
1
      break;
1242
44
    case IAX2_TRUNK_PACKET:
1243
44
      iax2_info->messageName = "TRUNK_PACKET";
1244
44
      len = dissect_trunkpacket(tvb, offset, scallno, pinfo, full_mini_subtree, tree);
1245
44
      break;
1246
0
    default:
1247
0
      len = 0;
1248
148
  }
1249
1250
  /* update the 'length' of the main IAX2 header field so that it covers just the headers,
1251
     not the audio data. */
1252
95
  proto_item_set_len(iax2_item, len);
1253
95
  tap_queue_packet(iax2_tap, pinfo, iax2_info);
1254
95
  return tvb_captured_length(tvb);
1255
148
}
1256
1257
static proto_item *dissect_datetime_ie(tvbuff_t *tvb, uint32_t offset, proto_tree *ies_tree)
1258
13
{
1259
13
  struct tm tm;
1260
13
  uint32_t  ie_val;
1261
13
  nstime_t  datetime;
1262
1263
13
  proto_tree_add_item(ies_tree, hf_iax2_ies[IAX_IE_DATETIME], tvb, offset + 2, 4, ENC_BIG_ENDIAN);
1264
13
  ie_val = tvb_get_ntohl(tvb, offset+2);
1265
1266
  /* who's crazy idea for a time encoding was this? */
1267
13
  tm.tm_sec  = (ie_val       & 0x1f) << 1;
1268
13
  tm.tm_min  = (ie_val>>5)   & 0x3f;
1269
13
  tm.tm_hour = (ie_val>>11)  & 0x1f;
1270
13
  tm.tm_mday = (ie_val>>16)  & 0x1f;
1271
13
  tm.tm_mon  = ((ie_val>>21) & 0x0f) - 1;
1272
13
  tm.tm_year = ((ie_val>>25) & 0x7f) + 100;
1273
13
  tm.tm_isdst= -1; /* there's no info on whether DST was in force; assume it's
1274
                    * the same as currently */
1275
1276
13
  datetime.secs = mktime(&tm);
1277
13
  datetime.nsecs = 0;
1278
13
  return proto_tree_add_time(ies_tree, hf_iax2_ie_datetime, tvb, offset+2, 4, &datetime);
1279
13
}
1280
1281
1282
/* dissect the information elements in an IAX frame. Returns the updated offset */
1283
static uint32_t dissect_ies(tvbuff_t *tvb, packet_info *pinfo, uint32_t offset,
1284
                           proto_tree *iax_tree, proto_item * iax_item,
1285
                           iax2_ie_data *ie_data)
1286
78
{
1287
78
  DISSECTOR_ASSERT(ie_data);
1288
1289
1.60k
  while (offset < tvb_reported_length(tvb)) {
1290
1291
1.58k
    int     ies_type = tvb_get_uint8(tvb, offset);
1292
1.58k
    int     ies_len  = tvb_get_uint8(tvb, offset + 1);
1293
1.58k
    uint16_t apparent_addr_family;
1294
1295
    /* do non-tree-dependent stuff first */
1296
1.58k
    switch (ies_type) {
1297
25
      case IAX_IE_DATAFORMAT:
1298
25
        if (ies_len != 4) {
1299
24
          proto_tree_add_expert(iax_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1);
1300
24
          break;
1301
24
        }
1302
1
        ie_data -> dataformat = tvb_get_ntohl(tvb, offset+2);
1303
1
        break;
1304
1305
87
      case IAX_IE_CALLED_NUMBER:
1306
87
        iax2_info->calledParty = tvb_format_text(pinfo->pool, tvb, offset+2, ies_len);
1307
87
        break;
1308
71
      case IAX_IE_CALLING_NUMBER:
1309
71
        iax2_info->callingParty = tvb_format_text(pinfo->pool, tvb, offset+2, ies_len);
1310
71
        break;
1311
1312
13
      case IAX_IE_APPARENT_ADDR:
1313
        /* The IAX2 I-D says that the "apparent address" structure
1314
           "is the same as the linux struct sockaddr_in", without
1315
           bothering to note that the address family field is in
1316
           *host* byte order in that structure (the I-D seems to be
1317
           assuming that "everything is a Vax^Wx86 or x86-64" with
1318
           the address family field being little-endian).
1319
1320
           This means the address family values are the Linux
1321
           address family values. */
1322
13
        apparent_addr_family = tvb_get_letohs(tvb, offset+2);
1323
13
        switch (apparent_addr_family) {
1324
1
          case LINUX_AF_INET:
1325
            /* IAX is always over UDP */
1326
1
            ie_data->peer_ptype = PT_UDP;
1327
1
            ie_data->peer_port = tvb_get_ntohs(tvb, offset+4);
1328
1329
            /* the ip address is big-endian, but then so is peer_address.data */
1330
1
            set_address_tvb(&ie_data->peer_address, AT_IPv4, 4, tvb, offset+6);
1331
1
            break;
1332
1333
11
          default:
1334
11
            expert_add_info_format(pinfo, iax_item, &ei_iax_peer_address_unsupported,
1335
11
                "Not supported in IAX dissector: peer address family of %u", apparent_addr_family);
1336
11
            break;
1337
13
        }
1338
12
        break;
1339
1.58k
    }
1340
1341
1342
    /* the rest of this stuff only needs doing if we have an iax_tree */
1343
1344
1.57k
    if (iax_tree && ies_type < NUM_HF_IAX2_IES) {
1345
1.57k
      proto_item *ti, *ie_item = NULL;
1346
1.57k
      proto_tree *ies_tree;
1347
1.57k
      int ie_hf = hf_iax2_ies[ies_type];
1348
1349
1.57k
      ies_tree = proto_tree_add_subtree(iax_tree, tvb, offset, ies_len+2, ett_iax2_ie, &ti, " ");
1350
1351
1.57k
      proto_tree_add_uint(ies_tree, hf_iax2_ie_id, tvb, offset, 1, ies_type);
1352
1.57k
      proto_tree_add_uint(ies_tree, hf_iax2_length, tvb, offset + 1, 1, ies_len);
1353
1354
1355
      /* hf_iax2_ies[] is an array, indexed by IE number, of header-fields, one
1356
         per IE. Apart from a couple of special cases which require more
1357
         complex decoding, we can just look up an entry from the array, and add
1358
         the relevant item, although the encoding value used depends on the
1359
         type of the item.
1360
      */
1361
1362
1.57k
      switch (ies_type) {
1363
13
        case IAX_IE_DATETIME:
1364
13
          ie_item = dissect_datetime_ie(tvb, offset, ies_tree);
1365
13
          break;
1366
1367
1368
16
        case IAX_IE_CAPABILITY:
1369
16
        {
1370
16
          if (ies_len != 4) {
1371
14
            proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1);
1372
14
            break;
1373
14
          }
1374
1375
2
          ie_item =
1376
2
            proto_tree_add_bitmask(ies_tree, tvb, offset + 2, ie_hf,
1377
2
              ett_iax2_codecs, hf_iax2_caps, ENC_BIG_ENDIAN);
1378
2
          break;
1379
16
        }
1380
1381
1382
50
        case IAX_IE_CAPABILITY2:
1383
50
        {
1384
50
          int version = tvb_get_uint8(tvb, offset + 2);
1385
1386
50
          proto_tree_add_uint(ies_tree, hf_iax2_version, tvb, offset + 2, 1, version);
1387
1388
50
          if (version == 0) {
1389
2
            if (ies_len != 9) {
1390
1
              proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1);
1391
1
              break;
1392
1
            }
1393
1394
1
            ie_item =
1395
1
              proto_tree_add_bitmask(ies_tree, tvb, offset + 3, ie_hf,
1396
1
                ett_iax2_codecs, hf_iax2_caps, ENC_BIG_ENDIAN);
1397
1
          }
1398
49
          break;
1399
50
        }
1400
1401
1402
78
        case IAX_IE_FORMAT:
1403
78
        {
1404
78
          if (ies_len != 4) {
1405
77
            proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1);
1406
77
            break;
1407
77
          }
1408
1409
1
          ie_item =
1410
1
            proto_tree_add_item(ies_tree, ie_hf,
1411
1
                                tvb, offset + 2, 4, ENC_BIG_ENDIAN);
1412
1
          break;
1413
78
        }
1414
1415
1416
25
        case IAX_IE_FORMAT2:
1417
25
        {
1418
25
          int version = tvb_get_uint8(tvb, offset + 2);
1419
1420
25
          proto_tree_add_uint(ies_tree, hf_iax2_version, tvb, offset + 2, 1, version);
1421
1422
25
          if (version == 0) {
1423
5
            if (ies_len != 9) {
1424
5
              proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1);
1425
5
              break;
1426
5
            }
1427
1428
0
            ie_item =
1429
0
              proto_tree_add_item(ies_tree, ie_hf,
1430
0
                                  tvb, offset + 3, 8, ENC_BIG_ENDIAN);
1431
0
          }
1432
20
          break;
1433
25
        }
1434
1435
1436
20
        case IAX_IE_APPARENT_ADDR:
1437
12
        {
1438
12
          proto_tree *sockaddr_tree;
1439
1440
12
          sockaddr_tree = proto_tree_add_subtree(ies_tree, tvb, offset + 2, 16,
1441
12
                            ett_iax2_ies_apparent_addr, &ie_item, "Apparent Address");
1442
1443
          /* The IAX2 I-D says that the "apparent address" structure
1444
             "is the same as the linux struct sockaddr_in", without
1445
             bothering to note that the address family field is in
1446
             *host* byte order in that structure (the I-D seems to be
1447
             assuming that "everything is a Vax^Wx86 or x86-64" with
1448
             the address family field being little-endian).
1449
1450
             This means the address family values are the Linux
1451
             address family values. */
1452
12
          apparent_addr_family = tvb_get_letohs(tvb, offset+2);
1453
12
          proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINFAMILY, tvb, offset + 2, 2, apparent_addr_family);
1454
1455
12
          if (apparent_addr_family == LINUX_AF_INET && ie_data->peer_address.type == AT_IPv4) {
1456
1
            uint32_t addr;
1457
1
            proto_tree_add_uint(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINPORT, tvb, offset + 4, 2, ie_data->peer_port);
1458
1
            memcpy(&addr, ie_data->peer_address.data, 4);
1459
1
            proto_tree_add_ipv4(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINADDR, tvb, offset + 6, 4, addr);
1460
1
          }
1461
12
          break;
1462
25
        }
1463
1464
1.38k
        default:
1465
1.38k
          if (ie_hf != 0) {
1466
351
            int explen = proto_registrar_get_length(ie_hf);
1467
351
            if (explen != 0 && ies_len != explen) {
1468
73
              proto_tree_add_expert(ies_tree, pinfo, &ei_iax_invalid_len, tvb, offset+1, 1);
1469
73
              break;
1470
73
            }
1471
1472
278
            switch (proto_registrar_get_ftype(ie_hf)) {
1473
0
            case FT_UINT8:
1474
6
            case FT_UINT16:
1475
6
            case FT_UINT24:
1476
8
            case FT_UINT32:
1477
8
            case FT_UINT64:
1478
8
            case FT_INT8:
1479
12
            case FT_INT16:
1480
12
            case FT_INT24:
1481
12
            case FT_INT32:
1482
12
            case FT_INT64:
1483
12
            case FT_BOOLEAN:
1484
12
            case FT_IPv4:
1485
12
                ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_BIG_ENDIAN);
1486
12
                break;
1487
1488
15
            case FT_BYTES:
1489
40
            case FT_NONE:
1490
40
                ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_NA);
1491
40
                break;
1492
1493
226
            case FT_STRING:
1494
226
            case FT_STRINGZ:
1495
226
                ie_item = proto_tree_add_item(ies_tree, ie_hf, tvb, offset + 2, ies_len, ENC_UTF_8|ENC_NA);
1496
226
                break;
1497
1498
0
            default:
1499
0
                DISSECTOR_ASSERT_NOT_REACHED();
1500
0
                break;
1501
278
            }
1502
1.03k
          } else {
1503
            /* we don't understand this ie: add a generic one */
1504
1.03k
            uint32_t      value;
1505
1.03k
            const char *ptr;
1506
1.03k
            const char   *ie_name = val_to_str_ext_const(ies_type, &iax_ies_type_ext, "Unknown");
1507
1508
1.03k
            switch (ies_len) {
1509
24
              case 1:
1510
24
                value = tvb_get_uint8(tvb, offset + 2);
1511
24
                ie_item =
1512
24
                  proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTE,
1513
24
                                             tvb, offset+2, 1, value,
1514
24
                                             "%s: %#02x", ie_name, value);
1515
24
                break;
1516
1517
16
              case 2:
1518
16
                value = tvb_get_ntohs(tvb, offset + 2);
1519
16
                ie_item =
1520
16
                  proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I16,
1521
16
                                             tvb, offset+2, 2, value,
1522
16
                                             "%s: %#04x", ie_name, value);
1523
16
                break;
1524
1525
14
              case 4:
1526
14
                value = tvb_get_ntohl(tvb, offset + 2);
1527
14
                ie_item =
1528
14
                  proto_tree_add_uint_format(ies_tree, hf_IAX_IE_UNKNOWN_I32,
1529
14
                                             tvb, offset+2, 4, value,
1530
14
                                             "%s: %#08x", ie_name, value);
1531
14
                break;
1532
1533
977
              default:
1534
977
                ptr = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset + 2, ies_len, ENC_ASCII);
1535
977
                ie_item =
1536
977
                  proto_tree_add_string_format(ies_tree, hf_IAX_IE_UNKNOWN_BYTES,
1537
977
                                               tvb, offset+2, ies_len, ptr,
1538
977
                                               "%s: %s", ie_name, ptr);
1539
977
                break;
1540
1.03k
            }
1541
1.03k
          }
1542
1.26k
          break;
1543
1.57k
      }
1544
1545
      /* Retrieve the text from the item we added, and append it to the main IE
1546
       * item */
1547
1.53k
      if (ie_item && !proto_item_is_hidden(ti)) {
1548
1.29k
        field_info *ie_finfo = PITEM_FINFO(ie_item);
1549
1550
        /* if the representation of the item has already been set, use that;
1551
           else we have to allocate a block to put the text into */
1552
1.29k
        if (ie_finfo && ie_finfo->rep != NULL)
1553
1.00k
          proto_item_set_text(ti, "Information Element: %s",
1554
1.00k
                              ie_finfo->rep->representation);
1555
283
        else {
1556
283
          char *ie_val = (char *)wmem_alloc(pinfo->pool, ITEM_LABEL_LENGTH);
1557
283
          proto_item_fill_label(ie_finfo, ie_val, NULL);
1558
283
          proto_item_set_text(ti, "Information Element: %s",
1559
283
                              ie_val);
1560
283
        }
1561
1.29k
      }
1562
1.53k
    }
1563
1564
1.53k
    offset += ies_len + 2;
1565
1.53k
  }
1566
27
  return offset;
1567
78
}
1568
1569
static uint32_t uncompress_subclass(uint8_t csub)
1570
6
{
1571
  /* If the SC_LOG flag is set, return 2^csub otherwise csub */
1572
6
  if (csub & 0x80) {
1573
    /* special case for 'compressed' -1 */
1574
1
    if (csub == 0xff)
1575
0
      return (uint32_t)-1;
1576
1
    else
1577
1
      return csub & 0x3F;
1578
1
  }
1579
5
  else {
1580
5
    switch (csub) {
1581
2
      case 0x01: return 0;
1582
1
      case 0x02: return 1;
1583
0
      case 0x04: return 2;
1584
0
      case 0x08: return 3;
1585
0
      case 0x10: return 4;
1586
0
      case 0x20: return 5;
1587
0
      case 0x40: return 6;
1588
2
      default: return (uint32_t)-1;
1589
5
    }
1590
5
  }
1591
6
}
1592
1593
/* returns the new offset */
1594
static uint32_t dissect_iax2_command(tvbuff_t *tvb, uint32_t offset,
1595
                                    packet_info *pinfo, proto_tree *tree,
1596
                                    iax_packet_data *iax_packet)
1597
79
{
1598
79
  uint8_t        csub = tvb_get_uint8(tvb, offset);
1599
79
  proto_item*    ti;
1600
79
  iax2_ie_data   ie_data;
1601
79
  iax_call_data *iax_call;
1602
1603
79
  ie_data.peer_address.type = AT_NONE;
1604
79
  ie_data.peer_address.len  = 0;
1605
79
  ie_data.peer_address.data = NULL;
1606
79
  ie_data.peer_ptype        = PT_NONE;
1607
79
  ie_data.peer_port         = 0;
1608
79
  ie_data.peer_callno       = 0;
1609
79
  ie_data.dataformat        = (uint32_t)-1;
1610
79
  iax_call                  = iax_packet -> call_data;
1611
1612
  /* add the subclass */
1613
79
  ti = proto_tree_add_uint(tree, hf_iax2_iax_csub, tvb, offset, 1, csub);
1614
79
  offset++;
1615
1616
79
  col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1617
79
                     val_to_str_ext(pinfo->pool, csub, &iax_iax_subclasses_ext, "unknown (0x%02x)"));
1618
1619
79
  if (offset >= tvb_reported_length(tvb))
1620
1
    return offset;
1621
1622
78
  offset = dissect_ies(tvb, pinfo, offset, tree, ti, &ie_data);
1623
1624
  /* if this is a data call, set up a subdissector for the circuit */
1625
78
  if (iax_call && ie_data.dataformat != (uint32_t)-1 && iax_call -> subdissector == NULL) {
1626
0
    iax_call -> subdissector = dissector_get_uint_handle(iax2_dataformat_dissector_table, ie_data.dataformat);
1627
0
    iax_call -> dataformat = (iax_dataformat_t)ie_data.dataformat;
1628
0
  }
1629
1630
  /* if this is a transfer request, record it in the call data */
1631
78
  if (csub == IAX_COMMAND_TXREQ && iax_packet -> first_time) {
1632
0
    if (ie_data.peer_address.type != AT_NONE && ie_data.peer_callno != 0) {
1633
0
      unsigned tx_circuit = iax_circuit_lookup(&ie_data.peer_address,
1634
0
                                            ie_data.peer_ptype,
1635
0
                                            ie_data.peer_port,
1636
0
                                            ie_data.peer_callno);
1637
1638
0
      iax2_new_circuit_for_call(pinfo, NULL, tx_circuit, pinfo->num, iax_call, iax_packet->reversed);
1639
0
    }
1640
0
  }
1641
1642
78
  return offset;
1643
79
}
1644
1645
static void iax2_add_ts_fields(packet_info *pinfo, proto_tree *iax2_tree, tvbuff_t *tvb, iax_packet_data *iax_packet, packet_type type, uint32_t relts)
1646
102
{
1647
102
  uint32_t    full_relts = relts;
1648
102
  nstime_t    lateness;
1649
102
  proto_item *item;
1650
1651
102
  if (iax_packet->call_data == NULL) {
1652
    /* no call info for this frame; perhaps we missed the NEW packet */
1653
101
    return;
1654
101
  }
1655
1656
1
  if (iax_packet->abstime.secs == -1) {
1657
1
    nstime_t rel;
1658
1659
1
    switch (type) {
1660
0
    case IAX2_MINI_VOICE_PACKET:
1661
      /* RFC 5456 says
1662
       *
1663
       *   Abbreviated 'Mini Frames' are normally used for audio and
1664
       *   video; however, each time the time-stamp is a multiple of
1665
       *   32,768 (0x8000 hex), a standard or 'Full Frame' MUST be sent.
1666
       *
1667
       * and, for what it later calls "Mini Frames", by which it means
1668
       * what we're calling "mini voice packets", it says:
1669
       *
1670
       *   Mini frames carry a 16-bit time-stamp, which is the lower 16 bits
1671
       *   of the transmitting peer's full 32-bit time-stamp for the call.
1672
       *   The time-stamp allows synchronization of incoming frames so that
1673
       *   they MAY be processed in chronological order instead of the
1674
       *   (possibly different) order in which they are received.  The 16-bit
1675
       *   time-stamp wraps after 65.536 seconds, at which point a full frame
1676
       *   SHOULD be sent to notify the remote peer that its time-stamp has
1677
       *   been reset.  A call MUST continue to send mini frames starting
1678
       *   with time-stamp 0 even if acknowledgment of the resynchronization
1679
       *   is not received.
1680
       *
1681
       * *If* we see all the full frames, that means we *should* be able
1682
       * to convert the 16-bit time stamp to a full 32-bit time stamp by
1683
       * ORing the upper 16 bits of the last full frame time stamp we saw
1684
       * in above the 16-bit time stamp.
1685
       *
1686
       * XXX - what, if anything, should we do about full frames we've
1687
       * missed? */
1688
0
      full_relts = (iax_packet->call_data->last_full_frame_ts & 0xFFFF0000) | relts;
1689
0
      break;
1690
1691
1
    case IAX2_FULL_PACKET:
1692
1
    case IAX2_TRUNK_PACKET:
1693
      /* Timestamps have the full 32 bits of the timestamp.
1694
       * Save it, to add to the mini-packet time stamps.
1695
       *
1696
       * XXX - that's a maximum of 4294967296 milliseconds
1697
       * or about 4294967 seconds or about 49 days.
1698
       * Do we need to worry about that overflowing? */
1699
1
      full_relts = relts;
1700
1
      iax_packet->call_data->last_full_frame_ts = full_relts;
1701
1
      break;
1702
1703
0
    case IAX2_MINI_VIDEO_PACKET:
1704
      /* See the comment above in the IAX2_MINI_VOICE_PACKET case.
1705
       * Note also that RFC 5456 says, in section 8.1.3.1 "Meta Video
1706
       * Frames", which covers what we're calling "mini video packets":
1707
       *
1708
       *   Meta video frames carry a 16-bit time-stamp, which is the lower 16
1709
       *   bits of the transmitting peer's full 32-bit time-stamp for the
1710
       *   call.  When this time-stamp wraps, a Full Frame SHOULD be sent to
1711
       *   notify the remote peer that the time-stamp has been reset to 0.
1712
       *
1713
       * *but* it also shows the uppermost bit of that time stamp as "?",
1714
       * with a 15-bit time stamp, in the ASCII-art packet diagram after
1715
       * it.  dissect_minivideopacket() says "bit 15 of the ts is used to
1716
       * represent the rtp 'marker' bit"; presumably that's what's going
1717
       * on, but the RFC doesn't say that.
1718
       *
1719
       * So we assume that the time stamp is only 15 bits, and that the
1720
       * upper *17* bits of the last full frame's time stamp need to be
1721
       * ORed in above the 15 bits of time stamp.
1722
       *
1723
       * XXX - do we need to worry about overflows or missed packets
1724
       * with full timestamps? */
1725
0
      full_relts = (iax_packet->call_data->last_full_frame_ts & 0xFFFF8000) | relts;
1726
0
      break;
1727
1
    }
1728
1729
    /* Convert the full relative time stamp to an nstime_t */
1730
1
    rel.secs = full_relts / 1000;
1731
1
    rel.nsecs = (full_relts % 1000) * 1000000;
1732
1733
    /* Add it to the start time to get the absolute time. */
1734
1
    nstime_sum(&iax_packet->abstime, &iax_packet->call_data->start_time, &rel);
1735
1
  }
1736
1
  iax2_info->timestamp = relts; /* raw time stamp; nobody uses it */
1737
1738
1
  if (iax2_tree) {
1739
1
    item = proto_tree_add_time(iax2_tree, hf_iax2_absts, tvb, 0, 0, &iax_packet->abstime);
1740
1
    proto_item_set_generated(item);
1741
1742
1
    nstime_delta(&lateness, &pinfo->abs_ts, &iax_packet->abstime);
1743
1744
1
    item = proto_tree_add_time(iax2_tree, hf_iax2_lateness, tvb, 0, 0, &lateness);
1745
1
    proto_item_set_generated(item);
1746
1
  }
1747
1
}
1748
1749
/* returns the new offset */
1750
static uint32_t
1751
dissect_fullpacket(tvbuff_t *tvb, uint32_t offset,
1752
                   uint16_t scallno,
1753
                   packet_info *pinfo, proto_tree *iax2_tree,
1754
                   proto_tree *main_tree)
1755
100
{
1756
100
  uint16_t dcallno;
1757
100
  uint32_t ts;
1758
100
  uint8_t type;
1759
100
  uint8_t csub;
1760
100
  uint32_t codec;
1761
1762
100
  proto_tree      *packet_type_tree = NULL;
1763
100
  iax_call_data   *iax_call;
1764
100
  iax_packet_data *iax_packet;
1765
100
  bool             reversed;
1766
100
  bool             rtp_marker;
1767
1768
  /*
1769
   * remove the top bit for retransmission detection
1770
   */
1771
100
  dcallno = tvb_get_ntohs(tvb, offset) & 0x7FFF;
1772
100
  ts = tvb_get_ntohl(tvb, offset + 2);
1773
100
  type = tvb_get_uint8(tvb, offset + 8);
1774
100
  csub = tvb_get_uint8(tvb, offset + 9);
1775
100
  iax2_info->ftype   = type;
1776
100
  iax2_info->csub    = csub;
1777
100
  iax2_info->scallno = scallno;
1778
100
  iax2_info->dcallno = dcallno;
1779
1780
  /* see if we've seen this packet before */
1781
100
  iax_packet = (iax_packet_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0);
1782
100
  if (!iax_packet) {
1783
    /* if not, find or create an iax_call info structure for this IAX session. */
1784
1785
98
    if (type == AST_FRAME_IAX && csub == IAX_COMMAND_NEW) {
1786
      /* NEW packets start a new call */
1787
1
      iax_call = iax_new_call(pinfo, scallno);
1788
1
      reversed = false;
1789
97
    } else {
1790
97
      iax_call = iax_lookup_call(pinfo, scallno, dcallno,
1791
97
                                 &reversed);
1792
97
    }
1793
1794
98
    iax_packet = iax_new_packet_data(iax_call, reversed);
1795
98
    p_add_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0, iax_packet);
1796
98
  } else {
1797
2
    iax_call = iax_packet->call_data;
1798
2
    reversed = iax_packet->reversed;
1799
2
  }
1800
1801
100
  iax2_populate_pinfo_from_packet_data(pinfo, iax_packet);
1802
1803
100
  if (iax2_tree) {
1804
98
    proto_item *packet_type_base;
1805
1806
98
    proto_tree_add_item(iax2_tree, hf_iax2_dcallno, tvb, offset, 2, ENC_BIG_ENDIAN);
1807
1808
98
    proto_tree_add_item(iax2_tree, hf_iax2_retransmission, tvb, offset, 2, ENC_BIG_ENDIAN);
1809
1810
98
    if (iax_call) {
1811
1
      proto_item *item =
1812
1
        proto_tree_add_uint(iax2_tree, hf_iax2_callno, tvb, 0, 4,
1813
1
                            iax_call->forward_circuit_ids[0]);
1814
1
      proto_item_set_generated(item);
1815
1
    }
1816
1817
98
    proto_tree_add_uint(iax2_tree, hf_iax2_ts, tvb, offset+2, 4, ts);
1818
98
    iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_FULL_PACKET, ts);
1819
1820
98
    proto_tree_add_item(iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1,
1821
98
                        ENC_BIG_ENDIAN);
1822
1823
98
    proto_tree_add_item(iax2_tree, hf_iax2_iseqno, tvb, offset+7, 1,
1824
98
                        ENC_BIG_ENDIAN);
1825
98
    packet_type_base = proto_tree_add_uint(iax2_tree, hf_iax2_type, tvb,
1826
98
                                           offset+8, 1, type);
1827
1828
    /* add the type-specific subtree */
1829
98
    packet_type_tree = proto_item_add_subtree(packet_type_base, ett_iax2_type);
1830
98
  } else {
1831
2
    iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_FULL_PACKET, ts);
1832
2
  }
1833
1834
1835
  /* add frame type to info line */
1836
100
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s, source call# %d, timestamp %ums",
1837
100
                 val_to_str_ext(pinfo->pool, type, &iax_frame_types_ext, "Unknown (0x%02x)"),
1838
100
                 scallno, ts);
1839
1840
100
  iax2_info->messageName = val_to_str_ext(pinfo->pool, type, &iax_frame_types_ext, "Unknown (0x%02x)");
1841
1842
100
  switch (type) {
1843
79
  case AST_FRAME_IAX:
1844
79
    offset=dissect_iax2_command(tvb, offset+9, pinfo, packet_type_tree, iax_packet);
1845
79
    iax2_info->messageName = val_to_str_ext(pinfo->pool, csub, &iax_iax_subclasses_ext, "unknown (0x%02x)");
1846
79
    if (csub < NUM_TAP_IAX_VOIP_STATES) iax2_info->callState = tap_iax_voip_state[csub];
1847
79
    break;
1848
1849
1
  case AST_FRAME_DTMF_BEGIN:
1850
7
  case AST_FRAME_DTMF_END:
1851
7
    proto_tree_add_item(packet_type_tree, hf_iax2_dtmf_csub, tvb, offset+9, 1, ENC_ASCII);
1852
7
    offset += 10;
1853
1854
7
    col_append_fstr(pinfo->cinfo, COL_INFO, " digit %s", format_char(pinfo->pool, csub));
1855
7
    break;
1856
1857
2
  case AST_FRAME_CONTROL:
1858
    /* add the subclass */
1859
2
    proto_tree_add_uint(packet_type_tree, hf_iax2_cmd_csub, tvb,
1860
2
                         offset+9, 1, csub);
1861
2
    offset += 10;
1862
1863
2
    col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1864
2
                      val_to_str_ext(pinfo->pool, csub, &iax_cmd_subclasses_ext, "unknown (0x%02x)"));
1865
2
    iax2_info->messageName = val_to_str_ext(pinfo->pool, csub, &iax_cmd_subclasses_ext, "unknown (0x%02x)");
1866
2
    if (csub < NUM_TAP_CMD_VOIP_STATES) iax2_info->callState = tap_cmd_voip_state[csub];
1867
2
    break;
1868
1869
3
  case AST_FRAME_VOICE:
1870
    /* add the codec */
1871
3
    iax_packet -> codec = codec = uncompress_subclass(csub);
1872
1873
3
    if (packet_type_tree) {
1874
3
      proto_item *item;
1875
3
      proto_tree_add_item(packet_type_tree, hf_iax2_voice_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1876
3
      item = proto_tree_add_uint64(packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, CODEC_MASK(codec));
1877
3
      proto_item_set_generated(item);
1878
3
    }
1879
1880
3
    offset += 10;
1881
1882
3
    if (iax_call) {
1883
0
      if (reversed) {
1884
0
        iax_call->dst_codec = codec;
1885
0
      } else {
1886
0
        iax_call->src_codec = codec;
1887
0
      }
1888
0
    }
1889
1890
3
    dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, false, iax_packet);
1891
3
    break;
1892
1893
3
  case AST_FRAME_VIDEO:
1894
    /* bit 6 of the csub is used to represent the rtp 'marker' bit */
1895
3
    rtp_marker = csub & 0x40 ? true:false;
1896
3
    iax_packet -> codec = codec = uncompress_subclass((uint8_t)(csub & ~0x40));
1897
1898
3
    if (packet_type_tree) {
1899
3
      proto_item *item;
1900
3
      proto_tree_add_item(packet_type_tree, hf_iax2_video_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1901
3
      proto_tree_add_item(packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1902
3
      item = proto_tree_add_uint64(packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, CODEC_MASK(codec));
1903
3
      proto_item_set_generated(item);
1904
3
    }
1905
1906
3
    offset += 10;
1907
1908
3
    if (iax_call && iax_packet -> first_time) {
1909
0
      if (reversed) {
1910
0
        iax_call->dst_vformat = codec;
1911
0
      } else {
1912
0
        iax_call->src_vformat = codec;
1913
0
      }
1914
0
    }
1915
1916
3
    if (rtp_marker)
1917
0
      col_append_str(pinfo->cinfo, COL_INFO, ", Mark");
1918
1919
1920
3
    dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, true, iax_packet);
1921
3
    break;
1922
1923
1
  case AST_FRAME_MODEM:
1924
1
    proto_tree_add_item(packet_type_tree, hf_iax2_modem_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1925
1
    offset += 10;
1926
1927
1
    col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1928
1
                      val_to_str(pinfo->pool, csub, iax_modem_subclasses, "unknown (0x%02x)"));
1929
1
    break;
1930
1931
1
  case AST_FRAME_TEXT:
1932
1
    proto_tree_add_item(packet_type_tree, hf_iax2_text_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1933
1
    offset += 10;
1934
1935
1
    {
1936
1
      int textlen = tvb_captured_length_remaining(tvb, offset);
1937
1
      if (textlen > 0)
1938
1
      {
1939
1
        proto_tree_add_item(packet_type_tree, hf_iax2_text_text, tvb, offset, textlen, ENC_UTF_8);
1940
1
        offset += textlen;
1941
1
      }
1942
1
    }
1943
1
    break;
1944
1945
1
  case AST_FRAME_HTML:
1946
1
    proto_tree_add_item(packet_type_tree, hf_iax2_html_csub, tvb, offset+9, 1, ENC_BIG_ENDIAN);
1947
1
    offset += 10;
1948
1949
1
    if (csub == 0x01)
1950
0
    {
1951
0
      int urllen = tvb_captured_length_remaining(tvb, offset);
1952
0
      if (urllen > 0)
1953
0
      {
1954
0
        proto_item *pi = proto_tree_add_item(packet_type_tree, hf_iax2_html_url, tvb, offset, urllen, ENC_UTF_8);
1955
0
        proto_item_set_url(pi);
1956
0
        offset += urllen;
1957
0
      }
1958
0
    }
1959
1
    break;
1960
1961
0
  case AST_FRAME_CNG:
1962
1
  default:
1963
1
    proto_tree_add_uint(packet_type_tree, hf_iax2_csub, tvb, offset+9,
1964
1
                        1, csub);
1965
1
    offset += 10;
1966
1967
1
    col_append_fstr(pinfo->cinfo, COL_INFO, " subclass %d", csub);
1968
1
    break;
1969
100
  }
1970
1971
  /* next time we come to parse this packet, don't propagate the codec into the
1972
   * call_data */
1973
47
  iax_packet->first_time = false;
1974
1975
47
  return offset;
1976
100
}
1977
1978
static iax_packet_data *iax2_get_packet_data_for_minipacket(packet_info *pinfo,
1979
                                                            uint16_t scallno,
1980
                                                            bool video)
1981
4
{
1982
  /* see if we've seen this packet before */
1983
4
  iax_packet_data *p = (iax_packet_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0);
1984
1985
4
  if (!p) {
1986
    /* if not, find or create an iax_call info structure for this IAX session. */
1987
4
    bool reversed;
1988
4
    iax_call_data *iax_call;
1989
1990
4
    iax_call = iax_lookup_call(pinfo, scallno, 0, &reversed);
1991
1992
4
    p = iax_new_packet_data(iax_call, reversed);
1993
4
    p_add_proto_data(wmem_file_scope(), pinfo, proto_iax2, 0, p);
1994
1995
    /* set the codec for this frame to be whatever the last full frame used */
1996
4
    if (iax_call) {
1997
0
     if (video)
1998
0
        p->codec = reversed ? iax_call -> dst_vformat : iax_call -> src_vformat;
1999
0
      else
2000
0
        p->codec = reversed ? iax_call -> dst_codec : iax_call -> src_codec;
2001
0
    }
2002
4
  }
2003
2004
4
  iax2_populate_pinfo_from_packet_data(pinfo, p);
2005
4
  return p;
2006
4
}
2007
2008
2009
static uint32_t dissect_minivideopacket(tvbuff_t *tvb, uint32_t offset,
2010
                                       uint16_t scallno, packet_info *pinfo,
2011
                                       proto_tree *iax2_tree, proto_tree *main_tree)
2012
1
{
2013
1
  uint32_t         ts;
2014
1
  iax_packet_data *iax_packet;
2015
1
  bool             rtp_marker;
2016
1
  proto_item      *item;
2017
2018
1
  ts = tvb_get_ntohs(tvb, offset);
2019
2020
  /* bit 15 of the ts is used to represent the rtp 'marker' bit */
2021
1
  rtp_marker = ts & 0x8000 ? true:false;
2022
1
  ts &= ~0x8000;
2023
2024
1
  iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, true);
2025
2026
1
  if (iax2_tree) {
2027
1
    if (iax_packet->call_data) {
2028
0
      item =
2029
0
        proto_tree_add_uint(iax2_tree, hf_iax2_callno, tvb, 0, 4,
2030
0
                            iax_packet->call_data->forward_circuit_ids[0]);
2031
0
      proto_item_set_generated(item);
2032
0
    }
2033
2034
1
    proto_tree_add_item(iax2_tree, hf_iax2_minividts, tvb, offset, 2, ENC_BIG_ENDIAN);
2035
1
    iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VIDEO_PACKET, ts);
2036
1
    proto_tree_add_item(iax2_tree, hf_iax2_minividmarker, tvb, offset, 2, ENC_BIG_ENDIAN);
2037
1
  } else {
2038
0
    iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VIDEO_PACKET, ts);
2039
0
  }
2040
2041
1
  offset += 2;
2042
2043
1
  col_add_fstr(pinfo->cinfo, COL_INFO,
2044
1
                   "Mini video packet, source call# %d, timestamp %ums%s",
2045
1
                   scallno, ts, rtp_marker?", Mark":"");
2046
2047
2048
1
  dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, true, iax_packet);
2049
2050
  /* next time we come to parse this packet, don't propagate the codec into the
2051
   * call_data */
2052
1
  iax_packet->first_time = false;
2053
2054
1
  return offset;
2055
1
}
2056
2057
static uint32_t dissect_minipacket(tvbuff_t *tvb, uint32_t offset, uint16_t scallno,
2058
                                  packet_info *pinfo, proto_tree *iax2_tree,
2059
                                  proto_tree *main_tree)
2060
3
{
2061
3
  uint32_t         ts;
2062
3
  iax_packet_data *iax_packet;
2063
3
  proto_item      *item;
2064
2065
3
  ts = tvb_get_ntohs(tvb, offset);
2066
2067
3
  iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, false);
2068
2069
3
  if (iax2_tree) {
2070
3
    if (iax_packet->call_data) {
2071
0
      item = proto_tree_add_uint(iax2_tree, hf_iax2_callno, tvb, 0, 4,
2072
0
                                 iax_packet->call_data->forward_circuit_ids[0]);
2073
0
      proto_item_set_generated(item);
2074
0
    }
2075
2076
3
    proto_tree_add_uint(iax2_tree, hf_iax2_minits, tvb, offset, 2, ts);
2077
3
    iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VOICE_PACKET, ts);
2078
3
  } else {
2079
0
    iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VOICE_PACKET, ts);
2080
0
  }
2081
2082
2083
3
  offset += 2;
2084
2085
3
  col_add_fstr(pinfo->cinfo, COL_INFO,
2086
3
                    "Mini packet, source call# %d, timestamp %ums",
2087
3
                    scallno, ts);
2088
2089
2090
  /* XXX fix the timestamp logic */
2091
3
  dissect_payload(tvb, offset, pinfo, iax2_tree, main_tree, ts, false, iax_packet);
2092
2093
2094
  /* next time we come to parse this packet, don't propagate the codec into the
2095
   * call_data */
2096
3
  iax_packet->first_time = false;
2097
2098
3
  return offset;
2099
3
}
2100
2101
2102
static uint32_t dissect_trunkcall_ts(tvbuff_t *tvb, uint32_t offset, proto_tree *iax2_tree, uint16_t *scallno)
2103
349
{
2104
349
  proto_tree *call_tree;
2105
349
  uint16_t    datalen, rlen, ts;
2106
  /*
2107
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2108
   |     Data Length (in octets)   |R|     Source Call Number      |
2109
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2110
   |           time-stamp          |                               |
2111
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
2112
   |                                       Data                    |
2113
   :                                                               :
2114
   |                                                               |
2115
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2116
   */
2117
349
  datalen = tvb_get_ntohs(tvb, offset);
2118
349
  *scallno = tvb_get_ntohs(tvb, offset + 2);
2119
349
  ts = tvb_get_ntohs(tvb, offset + 4);
2120
2121
349
  rlen = MIN(tvb_captured_length(tvb) - offset - 6, datalen);
2122
2123
349
  if (iax2_tree) {
2124
349
    call_tree = proto_tree_add_subtree_format(iax2_tree, tvb, offset, rlen + 6,
2125
349
                        ett_iax2_trunk_call, NULL, "Trunk call from %u, ts: %u", *scallno, ts);
2126
2127
349
    proto_tree_add_item(call_tree, hf_iax2_trunk_call_len, tvb, offset, 2, ENC_BIG_ENDIAN);
2128
349
    proto_tree_add_item(call_tree, hf_iax2_trunk_call_scallno, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2129
349
    proto_tree_add_item(call_tree, hf_iax2_trunk_call_ts, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
2130
349
    proto_tree_add_item(call_tree, hf_iax2_trunk_call_data, tvb, offset + 6, rlen, ENC_NA);
2131
349
  }
2132
349
  offset += 6 + rlen;
2133
2134
349
  return offset;
2135
349
}
2136
2137
static uint32_t dissect_trunkcall_nots(tvbuff_t *tvb, uint32_t offset, proto_tree *iax2_tree, uint16_t *scallno)
2138
476
{
2139
476
  proto_tree *call_tree;
2140
476
  uint16_t    datalen, rlen;
2141
  /*
2142
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2143
   |R|      Source Call Number     |     Data Length (in octets)   |
2144
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2145
   |                                                               |
2146
   :                             Data                              :
2147
   |                                                               |
2148
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2149
   */
2150
476
  *scallno = tvb_get_ntohs(tvb, offset);
2151
476
  datalen = tvb_get_ntohs(tvb, offset + 2);
2152
2153
476
  rlen = MIN(tvb_captured_length(tvb) - offset - 4, datalen);
2154
2155
476
  if (iax2_tree) {
2156
476
    call_tree = proto_tree_add_subtree_format(iax2_tree, tvb, offset, rlen + 6,
2157
476
                        ett_iax2_trunk_call, NULL, "Trunk call from %u", *scallno);
2158
2159
476
    proto_tree_add_item(call_tree, hf_iax2_trunk_call_scallno, tvb, offset, 2, ENC_BIG_ENDIAN);
2160
476
    proto_tree_add_item(call_tree, hf_iax2_trunk_call_len, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2161
476
    proto_tree_add_item(call_tree, hf_iax2_trunk_call_data, tvb, offset + 4, rlen, ENC_NA);
2162
476
  }
2163
476
  offset += 4 + rlen;
2164
2165
476
  return offset;
2166
476
}
2167
2168
typedef struct _call_list {
2169
  uint16_t           scallno;
2170
  struct _call_list *next;
2171
} call_list;
2172
2173
static call_list *call_list_append(wmem_allocator_t *pool, call_list *list, uint16_t scallno)
2174
144
{
2175
144
  call_list *node = wmem_new0(pool, call_list);
2176
2177
144
  node->scallno = scallno;
2178
2179
144
  if (list) {
2180
102
    call_list *cur = list;
2181
321
    while (cur->next) {
2182
219
      cur = cur->next;
2183
219
    }
2184
102
    cur->next = node;
2185
102
    return list;
2186
102
  } else {
2187
42
    return node;
2188
42
  }
2189
144
}
2190
2191
static bool call_list_find(call_list *list, uint16_t scallno)
2192
825
{
2193
1.82k
  for (; list; list = list->next) {
2194
1.67k
    if (list->scallno == scallno) {
2195
681
      return true;
2196
681
    }
2197
1.67k
  }
2198
144
  return false;
2199
825
}
2200
2201
static unsigned call_list_length(call_list *list)
2202
44
{
2203
44
  unsigned count = 0;
2204
188
  for (; list; list = list->next) {
2205
144
    count++;
2206
144
  }
2207
44
  return count;
2208
44
}
2209
2210
static uint32_t dissect_trunkpacket(tvbuff_t *tvb, uint32_t offset,
2211
                                   uint16_t scallno_param _U_, packet_info *pinfo,
2212
                                   proto_tree *iax2_tree, proto_tree *main_tree _U_)
2213
44
{
2214
44
  uint8_t     cmddata, trunkts;
2215
44
  unsigned    nframes    = 0, ncalls = 0;
2216
44
  proto_item *cd, *nc    = NULL;
2217
44
  proto_tree *field_tree = NULL;
2218
44
  call_list  *calls      = NULL;
2219
  /*iax_packet_data *iax_packet;*/
2220
2221
44
  cmddata = tvb_get_uint8(tvb, offset + 1);
2222
44
  trunkts = cmddata & IAX2_TRUNK_TS;
2223
2224
  /* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1   */
2225
  /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
2226
  /* |F|         Meta Indicator      |V|Meta Command | Cmd Data (0)  | */
2227
  /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
2228
  /* |                            time-stamp                         | */
2229
  /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
2230
2231
44
  if (iax2_tree) {
2232
    /* Meta Command */
2233
44
    proto_tree_add_item(iax2_tree, hf_iax2_trunk_metacmd, tvb, offset, 1, ENC_BIG_ENDIAN);
2234
2235
    /* Command data */
2236
44
    cd = proto_tree_add_uint(iax2_tree, hf_iax2_trunk_cmddata, tvb, offset + 1, 1, cmddata);
2237
44
    field_tree = proto_item_add_subtree(cd, ett_iax2_trunk_cmddata);
2238
44
    if (trunkts)
2239
22
      proto_item_append_text(cd, " (trunk timestamps)");
2240
2241
    /* CD -> Trunk timestamp */
2242
44
    proto_tree_add_boolean(field_tree, hf_iax2_trunk_cmddata_ts, tvb, offset + 1, 1, cmddata);
2243
2244
    /* Timestamp */
2245
44
    proto_tree_add_item(iax2_tree, hf_iax2_trunk_ts, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
2246
44
  }
2247
2248
44
  offset += 6;
2249
2250
44
  if (trunkts) {
2251
    /* Trunk calls with timestamp */
2252
371
    while(tvb_captured_length_remaining(tvb, offset) >= 6) {
2253
349
      uint16_t scallno;
2254
349
      offset = dissect_trunkcall_ts(tvb, offset, iax2_tree, &scallno);
2255
349
      if (!call_list_find(calls, scallno)) {
2256
63
        calls = call_list_append(pinfo->pool, calls, scallno);
2257
63
      }
2258
349
      nframes++;
2259
349
    }
2260
22
  }
2261
22
  else {
2262
    /* Trunk calls without timestamp */
2263
498
    while(tvb_captured_length_remaining(tvb, offset) >= 4) {
2264
476
      uint16_t scallno;
2265
476
      offset = dissect_trunkcall_nots(tvb, offset, iax2_tree, &scallno);
2266
476
      if (!call_list_find(calls, scallno)) {
2267
81
        calls = call_list_append(pinfo->pool, calls, scallno);
2268
81
      }
2269
476
      nframes++;
2270
476
    }
2271
22
  }
2272
2273
44
  ncalls = call_list_length(calls);
2274
2275
44
  if (iax2_tree) {
2276
    /* number of items */
2277
44
    nc = proto_tree_add_uint(iax2_tree, hf_iax2_trunk_ncalls, NULL, 0, 0, ncalls);
2278
44
    proto_item_set_generated(nc);
2279
44
  }
2280
2281
44
  col_add_fstr(pinfo->cinfo, COL_INFO, "Trunk packet with %d media frame%s for %d call%s",
2282
44
               nframes, plurality(nframes, "", "s"),
2283
44
               ncalls, plurality(ncalls, "", "s"));
2284
2285
44
  return offset;
2286
44
}
2287
2288
2289
static void process_iax_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2290
                              bool video, iax_packet_data *iax_packet)
2291
8
{
2292
8
  uint32_t       codec    = iax_packet -> codec;
2293
8
  iax_call_data *iax_call = iax_packet -> call_data;
2294
2295
#ifdef DEBUG_DESEGMENT
2296
  ws_debug("calling process_iax_pdu; len = %u", tvb_reported_length(tvb));
2297
#endif
2298
2299
8
  if (!video && iax_call && iax_call->subdissector) {
2300
0
    iax2_dissector_info_t dissector_info;
2301
2302
    /* info for subdissectors. We always pass on the original forward circuit,
2303
     * and steal the p2p_dir flag to indicate the direction */
2304
0
    if (iax_packet->call_data == NULL) {
2305
     /* if we missed the NEW packet for this call, call_data will be null. it's
2306
      * tbd what the best thing to do here is. */
2307
0
      memset(&dissector_info, 0, sizeof(dissector_info));
2308
0
    } else {
2309
0
      dissector_info.ctype = CONVERSATION_IAX2;
2310
0
      dissector_info.circuit_id = (uint32_t)iax_packet->call_data->forward_circuit_ids[0];
2311
0
    }
2312
2313
0
    call_dissector_with_data(iax_call->subdissector, tvb, pinfo, tree, &dissector_info);
2314
8
  } else if (codec != 0 && dissector_try_uint(iax2_codec_dissector_table, codec, tvb, pinfo, tree)) {
2315
    /* codec dissector handled our data */
2316
8
  } else {
2317
    /* we don't know how to dissect our data: dissect it as data */
2318
8
    call_data_dissector(tvb, pinfo, tree);
2319
8
  }
2320
2321
#ifdef DEBUG_DESEGMENT
2322
  ws_debug("called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u",
2323
            pinfo->desegment_len, pinfo->desegment_offset);
2324
#endif
2325
8
}
2326
2327
static void desegment_iax(tvbuff_t *tvb, packet_info *pinfo, proto_tree *iax2_tree,
2328
                          proto_tree *tree, bool video, iax_packet_data *iax_packet)
2329
0
{
2330
2331
0
  iax_call_data    *iax_call       = iax_packet -> call_data;
2332
0
  iax_call_dirdata *dirdata;
2333
0
  void *            value          = NULL;
2334
0
  uint32_t          frag_offset    = 0;
2335
0
  fragment_head    *fd_head;
2336
0
  bool              must_desegment = false;
2337
2338
0
  DISSECTOR_ASSERT(iax_call);
2339
2340
0
  pinfo->can_desegment    = 2;
2341
0
  pinfo->desegment_offset = 0;
2342
0
  pinfo->desegment_len    = 0;
2343
2344
#ifdef DEBUG_DESEGMENT
2345
  ws_debug("dissecting packet %u", pinfo->num);
2346
#endif
2347
2348
0
  dirdata = &(iax_call->dirdata[!!(iax_packet->reversed)]);
2349
2350
0
  if ((!pinfo->fd->visited && (dirdata->current_frag_bytes > 0)) ||
2351
0
     ((value = g_hash_table_lookup(iax_fid_table, GUINT_TO_POINTER(pinfo->num))) != NULL)) {
2352
2353
    /* then we are continuing an already-started pdu */
2354
0
    uint32_t fid;
2355
0
    uint32_t frag_len = tvb_reported_length(tvb);
2356
0
    bool complete;
2357
2358
#ifdef DEBUG_DESEGMENT
2359
    ws_debug("visited: %i; c_f_b: %u; hash: %u->%u", pinfo->fd->visited?1:0,
2360
            dirdata->current_frag_bytes, pinfo->num, dirdata->current_frag_id);
2361
#endif
2362
2363
0
    if (!pinfo->fd->visited) {
2364
0
      uint32_t tot_len;
2365
0
      fid = dirdata->current_frag_id;
2366
0
      tot_len                      = dirdata->current_frag_minlen;
2367
0
      DISSECTOR_ASSERT(g_hash_table_lookup(iax_fid_table, GUINT_TO_POINTER(pinfo->num)) == NULL);
2368
0
      g_hash_table_insert(iax_fid_table, GUINT_TO_POINTER(pinfo->num), GUINT_TO_POINTER(fid));
2369
0
      frag_offset                  = dirdata->current_frag_bytes;
2370
0
      dirdata->current_frag_bytes += frag_len;
2371
0
      complete                     = dirdata->current_frag_bytes > tot_len;
2372
#ifdef DEBUG_DESEGMENT
2373
      ws_debug("hash: %u->%u; frag_offset: %u; c_f_b: %u; totlen: %u",
2374
              pinfo->num, fid, frag_offset, dirdata->current_frag_bytes, tot_len);
2375
#endif
2376
0
    } else {
2377
0
      fid = GPOINTER_TO_UINT(value);
2378
      /* these values are unused by fragment_add if pinfo->fd->visited */
2379
0
      dirdata->current_frag_bytes = 0;
2380
0
      complete = false;
2381
0
    }
2382
2383
    /* fragment_add checks for already-added */
2384
0
    fd_head = fragment_add(&iax_reassembly_table, tvb, 0, pinfo, fid, NULL,
2385
0
                           frag_offset,
2386
0
                           frag_len, !complete);
2387
2388
0
    if (fd_head && (pinfo->num == fd_head->reassembled_in)) {
2389
0
      int32_t old_len;
2390
0
      tvbuff_t *next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
2391
0
      add_new_data_source(pinfo, next_tvb, "Reassembled IAX2");
2392
2393
0
      process_iax_pdu(next_tvb, pinfo, tree, video, iax_packet);
2394
2395
      /* calculate the amount of data which was available to the higher-level
2396
         dissector before we added this segment; if the returned offset is
2397
         within that section, the higher-level dissector was unable to find any
2398
         pdus; if it's after that, it found one or more complete PDUs.
2399
      */
2400
0
      old_len = (int32_t)(tvb_reported_length(next_tvb) - frag_len);
2401
0
      if (pinfo->desegment_len &&
2402
0
          (pinfo->desegment_offset < old_len)) {
2403
        /* oops, it wasn't actually complete */
2404
0
        fragment_set_partial_reassembly(&iax_reassembly_table, pinfo, fid, NULL);
2405
0
        if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
2406
          /* only one more byte should be enough for a retry */
2407
0
          dirdata->current_frag_minlen = fd_head->datalen + 1;
2408
0
        } else {
2409
0
          dirdata->current_frag_minlen = fd_head->datalen + pinfo->desegment_len;
2410
0
        }
2411
0
      } else {
2412
        /* we successfully dissected some data; create the proto tree items for
2413
         * the fragments, and flag any remaining data for desegmentation */
2414
2415
0
        proto_item *iax_tree_item, *frag_tree_item;
2416
        /* this nargery is to insert the fragment tree into the main tree
2417
         * between the IAX protocol entry and the subdissector entry */
2418
0
        show_fragment_tree(fd_head, &iax2_fragment_items, tree, pinfo, next_tvb, &frag_tree_item);
2419
0
        iax_tree_item = proto_item_get_parent(proto_tree_get_parent(iax2_tree));
2420
0
        if (frag_tree_item && iax_tree_item)
2421
0
          proto_tree_move_item(tree, iax_tree_item, frag_tree_item);
2422
2423
0
        dirdata->current_frag_minlen = dirdata->current_frag_id = dirdata->current_frag_bytes = 0;
2424
2425
0
        if (pinfo->desegment_len) {
2426
          /* there's a bit of data left to desegment */
2427
0
          must_desegment = true;
2428
          /* make desegment_offset relative to our tvb */
2429
0
          pinfo->desegment_offset -= old_len;
2430
0
        }
2431
2432
        /* don't add a 'reassembled in' item for this pdu */
2433
0
        fd_head = NULL;
2434
0
      }
2435
0
    }
2436
0
  } else {
2437
    /* This segment was not found in our table, so it doesn't
2438
       contain a continuation of a higher-level PDU.
2439
       Call the normal subdissector.
2440
    */
2441
2442
0
    process_iax_pdu(tvb, pinfo, tree, video, iax_packet);
2443
2444
0
    if (pinfo->desegment_len) {
2445
      /* the higher-level dissector has asked for some more data - ie,
2446
         the end of this segment does not coincide with the end of a
2447
         higher-level PDU. */
2448
0
      must_desegment = true;
2449
0
    }
2450
2451
0
    fd_head = NULL;
2452
0
  }
2453
2454
  /* must_desegment is set if the end of this segment (or the whole of it)
2455
   * contained the start of a higher-level PDU; we must add whatever is left of
2456
   * this segment (after pinfo->desegment_offset) to a fragment table for disassembly. */
2457
0
  if (must_desegment) {
2458
0
    uint32_t fid = pinfo->num; /* a new fragment id */
2459
0
    uint32_t deseg_offset = pinfo->desegment_offset;
2460
0
    uint32_t frag_len = tvb_reported_length_remaining(tvb, deseg_offset);
2461
0
    dirdata->current_frag_id = fid;
2462
0
    dirdata->current_frag_bytes = frag_len;
2463
2464
0
    if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
2465
      /* only one more byte should be enough for a retry */
2466
0
      dirdata->current_frag_minlen = frag_len + 1;
2467
0
    } else {
2468
0
      dirdata->current_frag_minlen = frag_len + pinfo->desegment_len;
2469
0
    }
2470
2471
0
    fd_head = fragment_add(&iax_reassembly_table,
2472
0
                           tvb, deseg_offset, pinfo, fid, NULL,
2473
0
                           0, frag_len, true);
2474
#ifdef DEBUG_DESEGMENT
2475
    ws_debug("Start offset of undissected bytes: %u; "
2476
            "Bytes remaining in this segment: %u; min required bytes: %u\n",
2477
            deseg_offset, frag_len, frag_len + pinfo->desegment_len);
2478
#endif
2479
0
  }
2480
2481
  /* add a 'reassembled in' item if necessary */
2482
0
  if (fd_head != NULL) {
2483
0
    uint32_t deseg_offset = pinfo->desegment_offset;
2484
0
    if (fd_head->reassembled_in != 0 &&
2485
0
        !(fd_head->flags & FD_PARTIAL_REASSEMBLY)) {
2486
0
      proto_item *iax_tree_item;
2487
0
      iax_tree_item = proto_tree_add_uint(tree, hf_iax2_reassembled_in,
2488
0
                                          tvb, deseg_offset, tvb_reported_length_remaining(tvb, deseg_offset),
2489
0
                                          fd_head->reassembled_in);
2490
0
      proto_item_set_generated(iax_tree_item);
2491
0
    } else {
2492
      /* this fragment is never reassembled */
2493
0
      proto_tree_add_item(tree, hf_iax2_fragment_unfinished, tvb, deseg_offset, -1, ENC_NA);
2494
0
    }
2495
2496
0
    if (pinfo->desegment_offset == 0) {
2497
0
      col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAX2");
2498
0
      col_set_str(pinfo->cinfo, COL_INFO, "[IAX2 segment of a reassembled PDU]");
2499
0
    }
2500
0
  }
2501
2502
0
  pinfo->can_desegment = 0;
2503
0
  pinfo->desegment_offset = 0;
2504
0
  pinfo->desegment_len = 0;
2505
0
}
2506
2507
static void dissect_payload(tvbuff_t *tvb, uint32_t offset,
2508
                            packet_info *pinfo, proto_tree *iax2_tree,
2509
                            proto_tree *tree, uint32_t ts _U_, bool video,
2510
                            iax_packet_data *iax_packet)
2511
10
{
2512
#if 0
2513
  bool           out_of_order = false;
2514
#endif
2515
10
  tvbuff_t      *sub_tvb;
2516
10
  uint32_t       codec        = iax_packet -> codec;
2517
10
  uint32_t       nbytes;
2518
10
  iax_call_data *iax_call     = iax_packet -> call_data;
2519
2520
10
  if (offset >= tvb_reported_length(tvb)) {
2521
2
    col_append_str(pinfo->cinfo, COL_INFO, ", empty frame");
2522
2
    return;
2523
2
  }
2524
2525
8
  sub_tvb = tvb_new_subset_remaining(tvb, offset);
2526
2527
  /* XXX shouldn't pass through out-of-order packets. */
2528
2529
8
  if (!video && iax_call && iax_call -> dataformat != 0) {
2530
0
      col_append_fstr(pinfo->cinfo, COL_INFO, ", data, format %s",
2531
0
                      val_to_str(pinfo->pool, iax_call -> dataformat,
2532
0
                                 iax_dataformats, "unknown (0x%02x)"));
2533
#if 0
2534
      if (out_of_order)
2535
        col_append_str(pinfo->cinfo, COL_INFO, " (out-of-order packet)");
2536
#endif
2537
8
  } else {
2538
8
      col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
2539
8
                      val64_to_str_ext_wmem(pinfo->pool, CODEC_MASK(codec), &codec_types_ext, "unknown (0x%04x)"));
2540
8
  }
2541
2542
8
  nbytes = tvb_reported_length(sub_tvb);
2543
8
  proto_tree_add_item(iax2_tree, hf_iax2_payload_data, sub_tvb, 0, -1, ENC_NA);
2544
2545
8
  iax2_info->payload_len = nbytes;
2546
  /* XXX - The IAX2 Analysis Dialog does check if pinfo->fd->pkt_len and
2547
   * pinfo->fd->cap_len are equal before using this, but it might be safer
2548
   * to do like the RTP dissector and have the payload_data pointer be NULL
2549
   * if the lengths aren't equal, and perhaps a boolean indicating that the
2550
   * the payload data is absent.
2551
   */
2552
8
  iax2_info->payload_data = tvb_get_ptr(sub_tvb, 0, tvb_captured_length(sub_tvb));
2553
2554
  /* pass the rest of the block to a subdissector */
2555
8
  if (iax_packet->call_data)
2556
0
    desegment_iax(sub_tvb, pinfo, iax2_tree, tree, video, iax_packet);
2557
8
  else
2558
8
    process_iax_pdu(sub_tvb, pinfo, tree, video, iax_packet);
2559
8
}
2560
2561
/*
2562
 * Init routines
2563
 */
2564
2565
/* called at the start of a capture. We should clear out our static, per-capture
2566
 * data.
2567
 */
2568
2569
static void
2570
iax_init_protocol(void)
2571
16
{
2572
16
  iax_circuit_hashtab = g_hash_table_new(iax_circuit_hash, iax_circuit_equal);
2573
16
  circuitcount = 0;
2574
2575
16
  iax_fid_table = g_hash_table_new(g_direct_hash, g_direct_equal);
2576
16
}
2577
2578
static void
2579
iax_cleanup_protocol(void)
2580
0
{
2581
0
  g_hash_table_destroy(iax_circuit_hashtab);
2582
0
  g_hash_table_destroy(iax_fid_table);
2583
0
}
2584
2585
2586
void
2587
proto_register_iax2(void)
2588
16
{
2589
  /* A header field is something you can search/filter on.
2590
   *
2591
   * We create a structure to register our fields. It consists of an
2592
   * array of hf_register_info structures, each of which are of the format
2593
   * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
2594
   */
2595
2596
16
  static hf_register_info hf[] = {
2597
2598
16
    {&hf_iax2_packet_type,
2599
16
     {"Packet type", "iax2.packet_type",
2600
16
      FT_UINT8, BASE_DEC, VALS(iax_packet_types), 0,
2601
16
      "Full/minivoice/minivideo/trunk packet",
2602
16
      HFILL}},
2603
2604
16
    {&hf_iax2_callno,
2605
16
     {"Call identifier", "iax2.call",
2606
16
      FT_UINT32, BASE_DEC, NULL, 0,
2607
16
      "This is the identifier Wireshark assigns to identify this call."
2608
16
      " It does not correspond to any real field in the protocol",
2609
16
      HFILL }},
2610
2611
16
    {&hf_iax2_scallno,
2612
16
     {"Source call", "iax2.src_call",
2613
16
      FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2614
16
      "src_call holds the number of this call at the packet source pbx",
2615
16
      HFILL}},
2616
2617
    /* FIXME could this be turned into a FRAMENUM field? */
2618
16
    {&hf_iax2_dcallno,
2619
16
     {"Destination call", "iax2.dst_call",
2620
16
      FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2621
16
      "dst_call holds the number of this call at the packet destination",
2622
16
      HFILL}},
2623
2624
16
    {&hf_iax2_retransmission,
2625
16
     {"Retransmission", "iax2.retransmission",
2626
16
      FT_BOOLEAN, 16, NULL, 0x8000,
2627
16
      "retransmission is set if this packet is a retransmission of an earlier failed packet",
2628
16
      HFILL}},
2629
2630
16
    {&hf_iax2_ts,
2631
16
     {"Timestamp", "iax2.timestamp",
2632
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
2633
16
      "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2634
16
      HFILL}},
2635
2636
16
    {&hf_iax2_minits,
2637
16
     {"Timestamp", "iax2.timestamp",
2638
16
      FT_UINT16, BASE_DEC, NULL, 0x0,
2639
16
      "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2640
16
      HFILL}},
2641
2642
16
    {&hf_iax2_minividts,
2643
16
     {"Timestamp", "iax2.timestamp",
2644
16
      FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2645
16
      "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2646
16
      HFILL}},
2647
2648
16
    {&hf_iax2_absts,
2649
16
     {"Absolute Time", "iax2.abstime",
2650
16
      FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2651
16
      "The absolute time of this packet (calculated by adding the IAX timestamp to  the start time of this call)",
2652
16
      HFILL}},
2653
2654
16
    {&hf_iax2_lateness,
2655
16
     {"Lateness", "iax2.lateness",
2656
16
      FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2657
16
      "The lateness of this packet compared to its timestamp",
2658
16
      HFILL}},
2659
2660
16
    {&hf_iax2_minividmarker,
2661
16
     {"Marker", "iax2.video.mini_marker",
2662
16
      FT_UINT16, BASE_DEC, NULL, 0x8000,
2663
16
      "RTP end-of-frame marker",
2664
16
      HFILL}},
2665
2666
16
    {&hf_iax2_oseqno,
2667
16
     {"Outbound seq.no.", "iax2.oseqno",
2668
16
      FT_UINT16, BASE_DEC, NULL, 0x0,
2669
16
      "oseqno is the sequence no of this packet. The first packet has oseqno==0,"
2670
16
      " and subsequent packets increment the oseqno by 1",
2671
16
      HFILL}},
2672
2673
16
    {&hf_iax2_iseqno,
2674
16
     {"Inbound seq.no.", "iax2.iseqno",
2675
16
      FT_UINT16, BASE_DEC, NULL, 0x0,
2676
16
      "iseqno is the sequence no of the last successfully received packet",
2677
16
      HFILL}},
2678
2679
16
    {&hf_iax2_type,
2680
16
     {"Type", "iax2.type",
2681
16
      FT_UINT8, BASE_DEC | BASE_EXT_STRING, &iax_frame_types_ext, 0x0,
2682
16
      "For full IAX2 frames, type is the type of frame",
2683
16
      HFILL}},
2684
2685
16
    {&hf_iax2_csub,
2686
16
     {"Unknown subclass", "iax2.subclass",
2687
16
      FT_UINT8, BASE_DEC, NULL, 0x0,
2688
16
      "Subclass of unknown type of full IAX2 frame",
2689
16
      HFILL}},
2690
2691
16
    {&hf_iax2_dtmf_csub,
2692
16
     {"DTMF subclass (digit)", "iax2.dtmf.subclass",
2693
16
      FT_STRINGZ, BASE_NONE, NULL, 0x0,
2694
16
      "DTMF subclass gives the DTMF digit",
2695
16
      HFILL}},
2696
2697
16
    {&hf_iax2_cmd_csub,
2698
16
     {"Control subclass", "iax2.control.subclass",
2699
16
      FT_UINT8, BASE_DEC | BASE_EXT_STRING, &iax_cmd_subclasses_ext, 0x0,
2700
16
      "This gives the command number for a Control packet.",
2701
16
      HFILL}},
2702
2703
16
    {&hf_iax2_iax_csub,
2704
16
     {"IAX subclass", "iax2.iax.subclass",
2705
16
      FT_UINT8, BASE_DEC | BASE_EXT_STRING, &iax_iax_subclasses_ext, 0x0,
2706
16
      "IAX subclass gives the command number for IAX signaling packets",
2707
16
      HFILL}},
2708
2709
16
    {&hf_iax2_voice_csub,
2710
16
     {"Voice Subclass (compressed codec no)", "iax2.voice.subclass",
2711
16
      FT_UINT8, BASE_DEC, NULL, 0x0,
2712
16
      NULL, HFILL}},
2713
2714
16
    {&hf_iax2_voice_codec,
2715
16
     {"CODEC", "iax2.voice.codec",
2716
16
      FT_UINT64, BASE_HEX | BASE_EXT_STRING | BASE_VAL64_STRING, &codec_types_ext, 0x0,
2717
16
      "CODEC gives the codec used to encode audio data",
2718
16
      HFILL}},
2719
2720
16
    {&hf_iax2_video_csub,
2721
16
     {"Video Subclass (compressed codec no)", "iax2.video.subclass",
2722
16
      FT_UINT8, BASE_DEC, NULL, 0xBF,
2723
16
      NULL, HFILL}},
2724
2725
16
    {&hf_iax2_marker,
2726
16
     {"Marker", "iax2.video.marker",
2727
16
      FT_BOOLEAN, 8, NULL, 0x40,
2728
16
      "RTP end-of-frame marker",
2729
16
      HFILL}},
2730
2731
16
    {&hf_iax2_video_codec,
2732
16
     {"CODEC", "iax2.video.codec",
2733
16
      FT_UINT64, BASE_HEX | BASE_EXT_STRING | BASE_VAL64_STRING, &codec_types_ext, 0,
2734
16
      "The codec used to encode video data",
2735
16
      HFILL}},
2736
2737
16
    {&hf_iax2_modem_csub,
2738
16
     {"Modem subclass", "iax2.modem.subclass",
2739
16
      FT_UINT8, BASE_DEC, VALS(iax_modem_subclasses), 0x0,
2740
16
      "Modem subclass gives the type of modem",
2741
16
      HFILL}},
2742
2743
16
    {&hf_iax2_text_csub,
2744
16
     {"Text subclass", "iax2.text.subclass",
2745
16
      FT_UINT8, BASE_DEC, VALS(iax_text_subclasses), 0x0,
2746
16
      NULL,
2747
16
      HFILL}},
2748
2749
16
    {&hf_iax2_text_text,
2750
16
     {"Text", "iax2.text.text",
2751
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2752
16
      NULL,
2753
16
      HFILL}},
2754
2755
16
    {&hf_iax2_html_csub,
2756
16
     {"HTML subclass", "iax2.html.subclass",
2757
16
      FT_UINT8, BASE_DEC, VALS(iax_html_subclasses), 0x0,
2758
16
      NULL,
2759
16
      HFILL}},
2760
2761
16
    {&hf_iax2_html_url,
2762
16
     {"HTML URL", "iax2.html.url",
2763
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2764
16
      NULL,
2765
16
      HFILL}},
2766
2767
16
    {&hf_iax2_trunk_ts,
2768
16
     {"Timestamp", "iax2.timestamp",
2769
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
2770
16
      "timestamp is the time, in ms after the start of Command data this call,"
2771
16
      " at which this trunk packet was transmitted",
2772
16
      HFILL}},
2773
2774
16
    {&hf_iax2_trunk_metacmd,
2775
16
     {"Meta command", "iax2.trunk.metacmd",
2776
16
      FT_UINT8, BASE_DEC, NULL, 0x7F,
2777
16
      "Meta command indicates whether or not the Meta Frame is a trunk.",
2778
16
      HFILL}},
2779
2780
16
    {&hf_iax2_trunk_cmddata,
2781
16
     {"Command data", "iax2.trunk.cmddata",
2782
16
      FT_UINT8, BASE_HEX, NULL, 0x0,
2783
16
      "Flags for options that apply to a trunked call",
2784
16
      HFILL}},
2785
2786
16
    {&hf_iax2_trunk_cmddata_ts,
2787
16
     {"Trunk timestamps", "iax2.trunk.cmddata.ts",
2788
16
      FT_BOOLEAN, 8, NULL, IAX2_TRUNK_TS,
2789
16
      "True: calls do each include their own timestamp",
2790
16
      HFILL}},
2791
2792
16
    {&hf_iax2_trunk_call_len,
2793
16
     {"Data length", "iax2.trunk.call.len",
2794
16
      FT_UINT16, BASE_DEC, NULL, 0x0,
2795
16
      "Trunk call data length in octets",
2796
16
      HFILL}},
2797
2798
16
    {&hf_iax2_trunk_call_scallno,
2799
16
     {"Source call number", "iax2.trunk.call.scallno",
2800
16
      FT_UINT16, BASE_DEC, NULL, 0x7FFF,
2801
16
      "Trunk call source call number",
2802
16
      HFILL}},
2803
2804
16
    {&hf_iax2_trunk_call_ts,
2805
16
     {"Timestamp", "iax2.trunk.call.ts",
2806
16
      FT_UINT16, BASE_DEC, NULL, 0x0,
2807
16
      "timestamp is the time, in ms after the start of this call, at which this packet was transmitted",
2808
16
      HFILL}},
2809
2810
16
    {&hf_iax2_trunk_call_data,
2811
16
     {"Data", "iax2.trunk.call.payload",
2812
16
      FT_BYTES, BASE_NONE, NULL, 0x0,
2813
16
      "Payload carried by this trunked packet.",
2814
16
      HFILL}},
2815
2816
16
    {&hf_iax2_trunk_ncalls,
2817
16
     {"Number of calls", "iax2.trunk.ncalls",
2818
16
      FT_UINT16, BASE_DEC, NULL, 0x0,
2819
16
      "Number of calls in this trunk packet",
2820
16
      HFILL}},
2821
2822
    /*
2823
     * Decoding for the ies
2824
     */
2825
2826
16
    {&hf_IAX_IE_APPARENTADDR_SINFAMILY,
2827
16
     {"Family", "iax2.iax.app_addr.sinfamily",
2828
16
      FT_UINT16, BASE_DEC, NULL, 0,
2829
16
      NULL, HFILL }},
2830
2831
16
    {&hf_IAX_IE_APPARENTADDR_SINPORT,
2832
16
     {"Port", "iax2.iax.app_addr.sinport",
2833
16
      FT_UINT16, BASE_DEC, NULL, 0,
2834
16
      NULL, HFILL }},
2835
2836
16
    {&hf_IAX_IE_APPARENTADDR_SINADDR,
2837
16
     {"Address", "iax2.iax.app_addr.sinaddr",
2838
16
      FT_IPv4, BASE_NONE, NULL, 0,
2839
16
      NULL, HFILL }},
2840
2841
16
    {&hf_iax2_ies[IAX_IE_CALLED_NUMBER],
2842
16
     {"Number/extension being called", "iax2.iax.called_number",
2843
16
      FT_STRING,
2844
16
      BASE_NONE, NULL, 0x0, NULL, HFILL}},
2845
2846
16
    {&hf_iax2_ies[IAX_IE_CALLING_NUMBER],
2847
16
     {"Calling number", "iax2.iax.calling_number",
2848
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2849
16
      NULL, HFILL}},
2850
2851
2852
16
    {&hf_iax2_ies[IAX_IE_CALLING_ANI],
2853
16
     {"Calling number ANI for billing", "iax2.iax.calling_ani",
2854
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2855
16
      NULL, HFILL}},
2856
2857
16
    {&hf_iax2_ies[IAX_IE_CALLING_NAME],
2858
16
     {"Name of caller", "iax2.iax.calling_name",
2859
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2860
16
      NULL, HFILL}},
2861
2862
16
    {&hf_iax2_ies[IAX_IE_CALLED_CONTEXT],
2863
16
     {"Context for number", "iax2.iax.called_context",
2864
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2865
16
      NULL, HFILL}},
2866
2867
16
    {&hf_iax2_ies[IAX_IE_USERNAME],
2868
16
     {"Username (peer or user) for authentication", "iax2.iax.username",
2869
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2870
16
      NULL, HFILL}},
2871
2872
16
    {&hf_iax2_ies[IAX_IE_PASSWORD],
2873
16
     {"Password for authentication", "iax2.iax.password",
2874
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2875
16
      NULL, HFILL}},
2876
2877
16
    {&hf_iax2_ies[IAX_IE_CAPABILITY],
2878
16
     {"Actual codec capability", "iax2.iax.capability",
2879
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
2880
16
      NULL, HFILL}},
2881
2882
16
    {&hf_iax2_ies[IAX_IE_FORMAT],
2883
16
     {"Desired codec format", "iax2.iax.format",
2884
16
      FT_UINT64, BASE_HEX | BASE_EXT_STRING | BASE_VAL64_STRING, &codec_types_ext, 0x0,
2885
16
      NULL, HFILL}},
2886
2887
16
    {&hf_iax2_ies[IAX_IE_LANGUAGE],
2888
16
     {"Desired language", "iax2.iax.language",
2889
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2890
16
      NULL, HFILL}},
2891
2892
16
    {&hf_iax2_ies[IAX_IE_VERSION],
2893
16
     {"Protocol version", "iax2.iax.version",
2894
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
2895
16
      NULL, HFILL}},
2896
2897
16
    {&hf_iax2_ies[IAX_IE_ADSICPE],
2898
16
     {"CPE ADSI capability", "iax2.iax.cpe_adsi",
2899
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
2900
16
      NULL, HFILL}},
2901
2902
16
    {&hf_iax2_ies[IAX_IE_DNID],
2903
16
     {"Originally dialed DNID", "iax2.iax.dnid",
2904
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2905
16
      NULL, HFILL}},
2906
2907
16
    {&hf_iax2_ies[IAX_IE_AUTHMETHODS],
2908
16
     {"Authentication method(s)", "iax2.iax.auth.methods",
2909
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
2910
16
      NULL, HFILL}},
2911
2912
16
    {&hf_iax2_ies[IAX_IE_CHALLENGE],
2913
16
     {"Challenge data for MD5/RSA", "iax2.iax.auth.challenge",
2914
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2915
16
      NULL, HFILL}},
2916
2917
16
    {&hf_iax2_ies[IAX_IE_MD5_RESULT],
2918
16
     {"MD5 challenge result", "iax2.iax.auth.md5",
2919
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2920
16
      NULL, HFILL}},
2921
2922
16
    {&hf_iax2_ies[IAX_IE_RSA_RESULT],
2923
16
     {"RSA challenge result", "iax2.iax.auth.rsa",
2924
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2925
16
      NULL, HFILL}},
2926
2927
16
    {&hf_iax2_ies[IAX_IE_REFRESH],
2928
16
     {"When to refresh registration", "iax2.iax.refresh",
2929
16
      FT_INT16, BASE_DEC, NULL, 0x0,
2930
16
      NULL, HFILL}},
2931
2932
16
    {&hf_iax2_ies[IAX_IE_DPSTATUS],
2933
16
     {"Dialplan status", "iax2.iax.dialplan_status",
2934
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
2935
16
      NULL, HFILL}},
2936
2937
16
    {&hf_iax2_ies[IAX_IE_CALLNO],
2938
16
     {"Call number of peer", "iax2.iax.call_no",
2939
16
      FT_UINT16, BASE_DEC, NULL, 0x0,
2940
16
      NULL, HFILL}},
2941
2942
16
    {&hf_iax2_ies[IAX_IE_CAUSE],
2943
16
     {"Cause", "iax2.iax.cause",
2944
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2945
16
      NULL, HFILL}},
2946
2947
16
    {&hf_iax2_ies[IAX_IE_IAX_UNKNOWN],
2948
16
     {"Unknown IAX command", "iax2.iax.iax_unknown",
2949
16
      FT_BYTES, BASE_NONE, NULL, 0x0,
2950
16
      NULL, HFILL}},
2951
2952
16
    {&hf_iax2_ies[IAX_IE_MSGCOUNT],
2953
16
     {"How many messages waiting", "iax2.iax.msg_count",
2954
16
      FT_INT16, BASE_DEC, NULL, 0x0,
2955
16
      NULL, HFILL}},
2956
2957
16
    {&hf_iax2_ies[IAX_IE_AUTOANSWER],
2958
16
     {"Request auto-answering", "iax2.iax.autoanswer",
2959
16
      FT_NONE, BASE_NONE, NULL, 0x0,
2960
16
      NULL, HFILL}},
2961
2962
16
    {&hf_iax2_ies[IAX_IE_MUSICONHOLD],
2963
16
     {"Request musiconhold with QUELCH", "iax2.iax.moh",
2964
16
      FT_NONE, BASE_NONE, NULL, 0x0,
2965
16
      NULL, HFILL}},
2966
2967
16
    {&hf_iax2_ies[IAX_IE_TRANSFERID],
2968
16
     {"Transfer Request Identifier", "iax2.iax.transferid",
2969
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
2970
16
      NULL, HFILL}},
2971
2972
16
    {&hf_iax2_ies[IAX_IE_RDNIS],
2973
16
     {"Referring DNIS", "iax2.iax.rdnis",
2974
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2975
16
      NULL, HFILL}},
2976
2977
16
    {&hf_iax2_ies[IAX_IE_PROVISIONING],
2978
16
     {"Provisioning info", "iax2.iax.provisioning",
2979
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2980
16
      NULL, HFILL}},
2981
2982
16
    {&hf_iax2_ies[IAX_IE_AESPROVISIONING],
2983
16
     {"AES Provisioning info", "iax2.iax.aesprovisioning",
2984
16
      FT_STRING, BASE_NONE, NULL, 0x0,
2985
16
      NULL, HFILL}},
2986
2987
16
    {&hf_iax2_ies[IAX_IE_DATETIME],
2988
16
     {"Date/Time", "iax2.iax.datetime.raw",
2989
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
2990
16
      NULL, HFILL}},
2991
2992
16
    {&hf_iax2_ie_datetime,
2993
16
     {"Date/Time", "iax2.iax.datetime",
2994
16
      FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2995
16
      NULL, HFILL }},
2996
2997
16
    {&hf_iax2_ies[IAX_IE_DEVICETYPE],
2998
16
     {"Device type", "iax2.iax.devicetype",
2999
16
      FT_STRING, BASE_NONE, NULL, 0x0,
3000
16
      NULL, HFILL}},
3001
3002
16
    {&hf_iax2_ies[IAX_IE_SERVICEIDENT],
3003
16
     {"Service identifier", "iax2.iax.serviceident",
3004
16
      FT_STRING, BASE_NONE, NULL, 0x0,
3005
16
      NULL, HFILL}},
3006
3007
16
    {&hf_iax2_ies[IAX_IE_FIRMWAREVER],
3008
16
     {"Firmware version", "iax2.iax.firmwarever",
3009
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
3010
16
      NULL, HFILL}},
3011
3012
16
    {&hf_iax2_ies[IAX_IE_FWBLOCKDESC],
3013
16
     {"Firmware block description", "iax2.iax.fwblockdesc",
3014
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
3015
16
      NULL, HFILL}},
3016
3017
16
    {&hf_iax2_ies[IAX_IE_FWBLOCKDATA],
3018
16
     {"Firmware block of data", "iax2.iax.fwblockdata",
3019
16
      FT_STRING, BASE_NONE, NULL, 0x0,
3020
16
      NULL, HFILL}},
3021
3022
16
    {&hf_iax2_ies[IAX_IE_PROVVER],
3023
16
     {"Provisioning version", "iax2.iax.provver",
3024
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
3025
16
      NULL, HFILL}},
3026
3027
16
    {&hf_iax2_ies[IAX_IE_CALLINGPRES],
3028
16
     {"Calling presentation", "iax2.iax.callingpres",
3029
16
      FT_UINT8, BASE_HEX, NULL, 0x0,
3030
16
      NULL, HFILL}},
3031
3032
16
    {&hf_iax2_ies[IAX_IE_CALLINGTON],
3033
16
     {"Calling type of number", "iax2.iax.callington",
3034
16
      FT_UINT8, BASE_HEX, NULL, 0x0,
3035
16
      NULL, HFILL}},
3036
3037
16
    {&hf_iax2_ies[IAX_IE_CALLINGTNS],
3038
16
     {"Calling transit network select", "iax2.iax.callingtns",
3039
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
3040
16
      NULL, HFILL}},
3041
3042
16
    {&hf_iax2_ies[IAX_IE_SAMPLINGRATE],
3043
16
     {"Supported sampling rates", "iax2.iax.samplingrate",
3044
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
3045
16
      NULL, HFILL}},
3046
3047
16
    {&hf_iax2_ies[IAX_IE_CAUSECODE],
3048
16
     {"Hangup cause", "iax2.iax.causecode",
3049
16
      FT_UINT8, BASE_HEX | BASE_EXT_STRING, &iax_causecodes_ext, 0x0,
3050
16
      NULL, HFILL}},
3051
3052
16
    {&hf_iax2_ies[IAX_IE_ENCRYPTION],
3053
16
     {"Encryption format", "iax2.iax.encryption",
3054
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
3055
16
      NULL, HFILL}},
3056
3057
16
    {&hf_iax2_ies[IAX_IE_ENCKEY],
3058
16
     {"Encryption key", "iax2.iax.enckey",
3059
16
      FT_STRING, BASE_NONE, NULL, 0x0,
3060
16
      NULL, HFILL}},
3061
3062
16
    {&hf_iax2_ies[IAX_IE_CODEC_PREFS],
3063
16
     {"Codec negotiation", "iax2.iax.codecprefs",
3064
16
      FT_STRING, BASE_NONE, NULL, 0x0,
3065
16
      NULL, HFILL}},
3066
3067
16
    {&hf_iax2_ies[IAX_IE_RR_JITTER],
3068
16
     {"Received jitter (as in RFC1889)", "iax2.iax.rrjitter",
3069
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
3070
16
      NULL, HFILL}},
3071
3072
16
    {&hf_iax2_ies[IAX_IE_RR_LOSS],
3073
16
     {"Received loss (high byte loss pct, low 24 bits loss count, as in rfc1889)", "iax2.iax.rrloss",
3074
16
       FT_UINT32, BASE_HEX, NULL, 0x0,
3075
16
      NULL, HFILL}},
3076
3077
16
    {&hf_iax2_ies[IAX_IE_RR_PKTS],
3078
16
     {"Total frames received", "iax2.iax.rrpkts",
3079
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
3080
16
      NULL, HFILL}},
3081
3082
16
    {&hf_iax2_ies[IAX_IE_RR_DELAY],
3083
16
     {"Max playout delay in ms for received frames", "iax2.iax.rrdelay",
3084
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
3085
16
      NULL, HFILL}},
3086
3087
16
    {&hf_iax2_ies[IAX_IE_RR_DROPPED],
3088
16
     {"Dropped frames (presumably by jitterbuffer)", "iax2.iax.rrdropped",
3089
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
3090
16
      NULL, HFILL}},
3091
3092
16
    {&hf_iax2_ies[IAX_IE_RR_OOO],
3093
16
     {"Frame received out of order", "iax2.iax.rrooo",
3094
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
3095
16
      NULL, HFILL}},
3096
3097
16
    {&hf_iax2_ies[IAX_IE_CAPABILITY2],
3098
16
     {"64-bit codec capability", "iax2.iax.capability2",
3099
16
      FT_UINT64, BASE_HEX, NULL, 0x0,
3100
16
      NULL, HFILL}},
3101
3102
16
    {&hf_iax2_ies[IAX_IE_FORMAT2],
3103
16
     {"64-bit codec format", "iax2.iax.format2",
3104
16
      FT_UINT64, BASE_HEX | BASE_EXT_STRING | BASE_VAL64_STRING, &codec_types_ext, 0x0,
3105
16
      NULL, HFILL}},
3106
3107
16
    {&hf_iax2_ies[IAX_IE_DATAFORMAT],
3108
16
     {"Data call format", "iax2.iax.dataformat",
3109
16
      FT_UINT32, BASE_HEX, VALS(iax_dataformats), 0x0,
3110
16
      NULL, HFILL}},
3111
3112
16
    {&hf_IAX_IE_UNKNOWN_BYTE,
3113
16
     {"Unknown", "iax2.iax.unknownbyte",
3114
16
      FT_UINT8, BASE_HEX, NULL, 0x0,
3115
16
      "Raw data for unknown IEs", HFILL}},
3116
3117
16
    {&hf_IAX_IE_UNKNOWN_I16,
3118
16
     {"Unknown", "iax2.iax.unknownshort",
3119
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
3120
16
      "Raw data for unknown IEs", HFILL}},
3121
3122
16
    {&hf_IAX_IE_UNKNOWN_I32,
3123
16
     {"Unknown", "iax2.iax.unknownlong",
3124
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
3125
16
      "Raw data for unknown IEs", HFILL}},
3126
3127
16
    {&hf_IAX_IE_UNKNOWN_BYTES,
3128
16
     {"Unknown", "iax2.iax.unknownstring",
3129
16
      FT_STRING, BASE_NONE, NULL, 0x0,
3130
16
      "Raw data for unknown IEs", HFILL}},
3131
3132
16
    {&hf_iax2_ie_id,
3133
16
     {"IE id", "iax2.ie_id",
3134
16
      FT_UINT8, BASE_DEC|BASE_EXT_STRING, &iax_ies_type_ext, 0x0,
3135
16
      NULL, HFILL}},
3136
3137
16
    {&hf_iax2_length,
3138
16
     {"Length", "iax2.length",
3139
16
      FT_UINT8, BASE_DEC, NULL, 0x0,
3140
16
      NULL, HFILL}},
3141
3142
16
    {&hf_iax2_version,
3143
16
     {"Version", "iax2.version",
3144
16
      FT_UINT8, BASE_DEC, NULL, 0x0,
3145
16
      NULL, HFILL}},
3146
3147
    /* capabilities */
3148
16
    {&hf_iax2_cap_g723_1,
3149
16
     {"G.723.1 compression", "iax2.cap.g723_1",
3150
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_G723_1),
3151
16
      NULL, HFILL }},
3152
3153
16
    {&hf_iax2_cap_gsm,
3154
16
     {"GSM compression", "iax2.cap.gsm",
3155
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_GSM),
3156
16
      NULL, HFILL }},
3157
3158
16
    {&hf_iax2_cap_ulaw,
3159
16
     {"Raw mu-law data (G.711)", "iax2.cap.ulaw",
3160
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_ULAW),
3161
16
      NULL, HFILL }},
3162
3163
16
     {&hf_iax2_cap_alaw,
3164
16
      {"Raw A-law data (G.711)", "iax2.cap.alaw",
3165
16
       FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_ALAW),
3166
16
       NULL, HFILL } },
3167
3168
16
    {&hf_iax2_cap_g726_aal2,
3169
16
     {"ADPCM (G.726, 32kbps, AAL2 codeword packing)", "iax2.cap.g726_aal2",
3170
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_G726_AAL2),
3171
16
      NULL, HFILL }},
3172
3173
16
    {&hf_iax2_cap_adpcm,
3174
16
     {"ADPCM", "iax2.cap.adpcm",
3175
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_ADPCM),
3176
16
      NULL, HFILL }},
3177
3178
16
    {&hf_iax2_cap_slinear,
3179
16
     {"Raw 16-bit Signed Linear (8000 Hz) PCM", "iax2.cap.slinear",
3180
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_SLINEAR),
3181
16
      NULL, HFILL }},
3182
3183
16
    {&hf_iax2_cap_lpc10,
3184
16
     {"LPC10, 180 samples/frame", "iax2.cap.lpc10",
3185
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_LPC10),
3186
16
      NULL, HFILL }},
3187
3188
16
    {&hf_iax2_cap_g729a,
3189
16
     {"G.729a Audio", "iax2.cap.g729a",
3190
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_G729A),
3191
16
      NULL, HFILL }},
3192
3193
16
    {&hf_iax2_cap_speex,
3194
16
     {"SpeeX Free Compression", "iax2.cap.speex",
3195
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_SPEEX),
3196
16
      NULL, HFILL }},
3197
3198
16
    {&hf_iax2_cap_ilbc,
3199
16
     {"iLBC Free Compression", "iax2.cap.ilbc",
3200
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_ILBC),
3201
16
      NULL, HFILL }},
3202
3203
16
    {&hf_iax2_cap_g726,
3204
16
     {"ADPCM (G.726, 32kbps, RFC3551 codeword packing)", "iax2.cap.g726",
3205
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_G726),
3206
16
      NULL, HFILL }},
3207
3208
16
    {&hf_iax2_cap_g722,
3209
16
     {"G.722", "iax2.cap.g722",
3210
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_G722),
3211
16
      NULL, HFILL }},
3212
3213
16
    {&hf_iax2_cap_siren7,
3214
16
     {"G.722.1 (also known as Siren7, 32kbps assumed)", "iax2.cap.siren7",
3215
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_SIREN7),
3216
16
      NULL, HFILL }},
3217
3218
16
    {&hf_iax2_cap_siren14,
3219
16
     {"G.722.1 Annex C (also known as Siren14, 48kbps assumed)", "iax2.cap.siren14",
3220
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_SIREN14),
3221
16
      NULL, HFILL }},
3222
3223
16
    {&hf_iax2_cap_slinear16,
3224
16
     {"Raw 16-bit Signed Linear (16000 Hz) PCM", "iax2.cap.slinear16",
3225
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_SLINEAR16),
3226
16
      NULL, HFILL }},
3227
3228
16
    {&hf_iax2_cap_jpeg,
3229
16
     {"JPEG images", "iax2.cap.jpeg",
3230
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_JPEG),
3231
16
      NULL, HFILL }},
3232
3233
16
    {&hf_iax2_cap_png,
3234
16
     {"PNG images", "iax2.cap.png",
3235
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_PNG),
3236
16
      NULL, HFILL }},
3237
3238
16
    {&hf_iax2_cap_h261,
3239
16
     {"H.261 video", "iax2.cap.h261",
3240
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_H261),
3241
16
      NULL, HFILL }},
3242
3243
16
    {&hf_iax2_cap_h263,
3244
16
     {"H.263 video", "iax2.cap.h263",
3245
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_H263),
3246
16
      NULL, HFILL }},
3247
3248
16
    {&hf_iax2_cap_h263_plus,
3249
16
     {"H.263+ video", "iax2.cap.h263_plus",
3250
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_H263_PLUS),
3251
16
      NULL, HFILL }},
3252
3253
16
    {&hf_iax2_cap_h264,
3254
16
     {"H.264 video", "iax2.cap.h264",
3255
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_H264),
3256
16
      NULL, HFILL }},
3257
3258
16
    {&hf_iax2_cap_mpeg4,
3259
16
     {"MPEG4 video", "iax2.cap.mpeg4",
3260
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_MP4_VIDEO),
3261
16
      NULL, HFILL }},
3262
3263
16
    {&hf_iax2_cap_vp8,
3264
16
     {"VP8 video", "iax2.cap.vp8",
3265
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_VP8),
3266
16
      NULL, HFILL }},
3267
3268
16
    {&hf_iax2_cap_t140_red,
3269
16
     {"T.140 RED Text format RFC 4103", "iax2.cap.t140_red",
3270
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_T140_RED),
3271
16
      NULL, HFILL }},
3272
3273
16
    {&hf_iax2_cap_t140,
3274
16
     {"T.140 Text format - ITU T.140, RFC 4103", "iax2.cap.t140",
3275
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_T140),
3276
16
      NULL, HFILL }},
3277
3278
16
    {&hf_iax2_cap_g719,
3279
16
     {"G.719 (64 kbps assumed)", "iax2.cap.g719",
3280
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_G719),
3281
16
      NULL, HFILL }},
3282
3283
16
    {&hf_iax2_cap_speex16,
3284
16
     {"SpeeX Wideband (16kHz) Free Compression", "iax2.cap.speex16",
3285
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_SPEEX16),
3286
16
      NULL, HFILL }},
3287
3288
16
    {&hf_iax2_cap_opus,
3289
16
     {"Opus audio (8kHz, 16kHz, 24kHz, 48Khz)", "iax2.cap.opus",
3290
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_OPUS),
3291
16
      NULL, HFILL }},
3292
3293
16
    {&hf_iax2_cap_testlaw,
3294
16
     {"Raw testing-law data (G.711)", "iax2.cap.testlaw",
3295
16
      FT_BOOLEAN, 64, TFS(&tfs_supported_not_supported), CODEC_MASK(AST_FORMAT_TESTLAW),
3296
16
      NULL, HFILL }},
3297
3298
16
    {&hf_iax2_fragment_unfinished,
3299
16
     {"IAX2 fragment, unfinished", "iax2.fragment_unfinished",
3300
16
      FT_BYTES, BASE_NONE, NULL, 0x0,
3301
16
      NULL, HFILL }},
3302
3303
16
    {&hf_iax2_payload_data,
3304
16
     {"IAX2 payload", "iax2.payload_data",
3305
16
      FT_BYTES, BASE_NONE, NULL, 0x0,
3306
16
      NULL, HFILL }},
3307
3308
    /* reassembly stuff */
3309
16
    {&hf_iax2_fragments,
3310
16
     {"IAX2 Fragments", "iax2.fragments",
3311
16
      FT_NONE, BASE_NONE, NULL, 0x0,
3312
16
      NULL, HFILL }},
3313
3314
16
    {&hf_iax2_fragment,
3315
16
     {"IAX2 Fragment data", "iax2.fragment",
3316
16
      FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3317
16
      NULL, HFILL }},
3318
3319
16
    {&hf_iax2_fragment_overlap,
3320
16
     {"Fragment overlap", "iax2.fragment.overlap",
3321
16
      FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3322
16
      "Fragment overlaps with other fragments", HFILL }},
3323
3324
16
    {&hf_iax2_fragment_overlap_conflict,
3325
16
     {"Conflicting data in fragment overlap", "iax2.fragment.overlap.conflict",
3326
16
      FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3327
16
      "Overlapping fragments contained conflicting data", HFILL }},
3328
3329
16
    {&hf_iax2_fragment_multiple_tails,
3330
16
     {"Multiple tail fragments found", "iax2.fragment.multipletails",
3331
16
      FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3332
16
      "Several tails were found when defragmenting the packet", HFILL }},
3333
3334
16
    {&hf_iax2_fragment_too_long_fragment,
3335
16
     {"Fragment too long", "iax2.fragment.toolongfragment",
3336
16
      FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3337
16
      "Fragment contained data past end of packet", HFILL }},
3338
3339
16
    {&hf_iax2_fragment_error,
3340
16
     {"Defragmentation error", "iax2.fragment.error",
3341
16
      FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3342
16
      "Defragmentation error due to illegal fragments", HFILL }},
3343
3344
16
    {&hf_iax2_fragment_count,
3345
16
     {"Fragment count", "iax2.fragment.count",
3346
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
3347
16
      NULL, HFILL }},
3348
3349
16
    {&hf_iax2_reassembled_in,
3350
16
     {"IAX2 fragment, reassembled in frame", "iax2.reassembled_in",
3351
16
      FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3352
16
      "This IAX2 packet is reassembled in this frame", HFILL }},
3353
3354
16
    {&hf_iax2_reassembled_length,
3355
16
     {"Reassembled IAX2 length", "iax2.reassembled.length",
3356
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
3357
16
      "The total length of the reassembled payload", HFILL }}
3358
16
  };
3359
3360
16
  static int *ett[] = {
3361
16
    &ett_iax2,
3362
16
    &ett_iax2_full_mini_subtree,
3363
16
    &ett_iax2_type,
3364
16
    &ett_iax2_ie,
3365
16
    &ett_iax2_codecs,
3366
16
    &ett_iax2_ies_apparent_addr,
3367
16
    &ett_iax2_fragment,
3368
16
    &ett_iax2_fragments,
3369
16
    &ett_iax2_trunk_cmddata,
3370
16
    &ett_iax2_trunk_call
3371
16
  };
3372
3373
16
  static ei_register_info ei[] = {
3374
16
    { &ei_iax_too_many_transfers, { "iax2.too_many_transfers", PI_PROTOCOL, PI_WARN, "Too many transfers for iax_call", EXPFILL }},
3375
16
    { &ei_iax_circuit_id_conflict, { "iax2.circuit_id_conflict", PI_PROTOCOL, PI_WARN, "Circuit ID conflict", EXPFILL }},
3376
16
    { &ei_iax_peer_address_unsupported, { "iax2.peer_address_unsupported", PI_PROTOCOL, PI_WARN, "Peer address unsupported", EXPFILL }},
3377
16
    { &ei_iax_invalid_len, { "iax2.invalid_len", PI_PROTOCOL, PI_WARN, "Invalid length", EXPFILL }},
3378
16
  };
3379
3380
16
  expert_module_t* expert_iax;
3381
3382
16
  proto_iax2 = proto_register_protocol("Inter-Asterisk eXchange v2", "IAX2", "iax2");
3383
16
  proto_register_field_array(proto_iax2, hf, array_length(hf));
3384
16
  proto_register_subtree_array(ett, array_length(ett));
3385
16
  expert_iax = expert_register_protocol(proto_iax2);
3386
16
  expert_register_field_array(expert_iax, ei, array_length(ei));
3387
3388
16
  iax2_handle = register_dissector("iax2", dissect_iax2, proto_iax2);
3389
3390
16
  iax2_codec_dissector_table = register_dissector_table(
3391
16
    "iax2.codec", "IAX codec number", proto_iax2, FT_UINT32, BASE_HEX);
3392
16
  iax2_dataformat_dissector_table = register_dissector_table(
3393
16
    "iax2.dataformat", "IAX dataformat number", proto_iax2, FT_UINT32, BASE_HEX);
3394
3395
  /* register our init routine to be called at the start of a capture,
3396
     to clear out our hash tables etc */
3397
16
  register_init_routine(&iax_init_protocol);
3398
16
  register_cleanup_routine(&iax_cleanup_protocol);
3399
16
  reassembly_table_register(&iax_reassembly_table,
3400
16
                        &addresses_reassembly_table_functions);
3401
3402
16
  iax2_tap = register_tap("IAX2");
3403
16
}
3404
3405
void
3406
proto_reg_handoff_iax2(void)
3407
16
{
3408
16
  dissector_handle_t v110_handle;
3409
3410
16
  dissector_add_uint_with_preference("udp.port", IAX2_PORT, iax2_handle);
3411
16
  v110_handle =  find_dissector("v110");
3412
16
  if (v110_handle)
3413
0
    dissector_add_uint("iax2.dataformat", AST_DATAFORMAT_V110, v110_handle);
3414
16
}
3415
3416
/*
3417
 * Editor modelines
3418
 *
3419
 * Local Variables:
3420
 * c-basic-offset: 2
3421
 * tab-width: 8
3422
 * indent-tabs-mode: nil
3423
 * End:
3424
 *
3425
 * ex: set shiftwidth=2 tabstop=8 expandtab:
3426
 * :indentSize=2:tabSize=8:noTabs=true:
3427
 */