~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/iax2/iax2-parser.c

  • Committer: Package Import Robot
  • Author(s): Francois Marier
  • Date: 2011-11-25 13:24:12 UTC
  • mfrom: (4.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20111125132412-dc4qvhyosk74cd42
Tags: 1.0.1-4
Don't assume that arch:all packages will get built (closes: #649726)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Asterisk -- A telephony toolkit for Linux.
 
3
 *
 
4
 * Implementation of Inter-Asterisk eXchange
 
5
 * 
 
6
 * Copyright (C) 2003-2004, Digium
 
7
 *
 
8
 * Mark Spencer <markster@digium.com>
 
9
 *
 
10
 * This program is free software, distributed under the terms of
 
11
 * the GNU Lesser (Library) General Public License
 
12
 */
 
13
 
 
14
#if defined(WIN32)  ||  defined(_WIN32_WCE)
 
15
#include <winsock.h>
 
16
#define snprintf _snprintf
 
17
#else
 
18
#include <sys/types.h>
 
19
#include <sys/socket.h>
 
20
#include <netinet/in.h>
 
21
#include <arpa/inet.h>
 
22
#endif
 
23
 
 
24
#ifndef _MSC_VER
 
25
#include <unistd.h>
 
26
#endif
 
27
 
 
28
#include <string.h>
 
29
#include <stdlib.h>
 
30
#include <stdio.h>
 
31
 
 
32
#include "frame.h"
 
33
#include "iax2.h"
 
34
#include "iax2-parser.h"
 
35
 
 
36
static int frames = 0;
 
37
static int iframes = 0;
 
38
static int oframes = 0;
 
39
 
 
40
#ifdef ALIGN32
 
41
static unsigned int get_uint32(unsigned char *p)
 
42
{
 
43
  return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
 
44
}
 
45
 
 
46
static unsigned short get_uint16(unsigned char *p)
 
47
{
 
48
  return (p[0] << 8) | p[1] ;
 
49
}
 
50
 
 
51
#else
 
52
#define get_uint32(p) (*((unsigned int *)(p)))
 
53
#define get_uint16(p) (*((unsigned short *)(p)))
 
54
#endif
 
55
 
 
56
 
 
57
static void internaloutput(const char *str)
 
58
{
 
59
    printf("%s",str);
 
60
}
 
61
 
 
62
static void internalerror(const char *str)
 
63
{
 
64
        fprintf(stderr, "WARNING: %s", str);
 
65
}
 
66
 
 
67
static void (*outputf)(const char *str) = internaloutput;
 
68
static void (*errorf)(const char *str) = internalerror;
 
69
 
 
70
static void dump_addr(char *output, int maxlen, void *value, int len)
 
71
{
 
72
        struct sockaddr_in sin;
 
73
        if (len == sizeof(sin)) {
 
74
                memcpy(&sin, value, len);
 
75
                snprintf(output, maxlen, "IPV4 %s:%d", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
 
76
        } else {
 
77
                snprintf(output, maxlen, "Invalid Address");
 
78
        }
 
79
}
 
80
 
 
81
static void dump_string(char *output, int maxlen, void *value, int len)
 
82
{
 
83
        maxlen--;
 
84
        if (maxlen > len)
 
85
                maxlen = len;
 
86
        strncpy(output,(const char *)value, maxlen);
 
87
        output[maxlen] = '\0';
 
88
}
 
89
 
 
90
static void dump_int(char *output, int maxlen, void *value, int len)
 
91
{
 
92
        if (len == (int)sizeof(unsigned int))
 
93
                snprintf(output, maxlen, "%lu", (unsigned long)ntohl(get_uint32(value)));
 
94
        else
 
95
                snprintf(output, maxlen, "Invalid INT");
 
96
}
 
97
 
 
98
static void dump_short(char *output, int maxlen, void *value, int len)
 
99
{
 
100
        if (len == (int)sizeof(unsigned short))
 
101
                snprintf(output, maxlen, "%d", ntohs(get_uint16(value)));
 
102
        else
 
103
                snprintf(output, maxlen, "Invalid SHORT");
 
104
}
 
105
 
 
106
static void dump_byte(char *output, int maxlen, void *value, int len)
 
107
{
 
108
        if (len == (int)sizeof(unsigned char))
 
109
                snprintf(output, maxlen, "%d", *((unsigned char *)value));
 
110
        else
 
111
                snprintf(output, maxlen, "Invalid BYTE");
 
112
}
 
113
 
 
114
static void dump_samprate(char *output, int maxlen, void *value, int len)
 
115
{
 
116
        char tmp[256]="";
 
117
        int sr;
 
118
        if (len == (int)sizeof(unsigned short)) {
 
119
                sr = ntohs(*((unsigned short *)value));
 
120
                if (sr & IAX_RATE_8KHZ)
 
121
                        strcat(tmp, ",8khz");
 
122
                if (sr & IAX_RATE_11KHZ)
 
123
                        strcat(tmp, ",11.025khz");
 
124
                if (sr & IAX_RATE_16KHZ)
 
125
                        strcat(tmp, ",16khz");
 
126
                if (sr & IAX_RATE_22KHZ)
 
127
                        strcat(tmp, ",22.05khz");
 
128
                if (sr & IAX_RATE_44KHZ)
 
129
                        strcat(tmp, ",44.1khz");
 
130
                if (sr & IAX_RATE_48KHZ)
 
131
                        strcat(tmp, ",48khz");
 
132
                if (strlen(tmp))
 
133
                        strncpy(output, &tmp[1], maxlen - 1);
 
134
                else
 
135
                        strncpy(output, "None specified!\n", maxlen - 1);
 
136
        } else
 
137
                snprintf(output, maxlen, "Invalid SHORT");
 
138
 
 
139
}
 
140
 
 
141
static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len);
 
142
static void dump_prov(char *output, int maxlen, void *value, int len)
 
143
{
 
144
        dump_prov_ies(output, maxlen, (unsigned char *)value, len);
 
145
}
 
146
 
 
147
static struct iax2_ie {
 
148
        int ie;
 
149
        char *name;
 
150
        void (*dump)(char *output, int maxlen, void *value, int len);
 
151
} ies[] = {
 
152
        { IAX_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
 
153
        { IAX_IE_CALLING_NUMBER, "CALLING NUMBER", dump_string },
 
154
        { IAX_IE_CALLING_ANI, "ANI", dump_string },
 
155
        { IAX_IE_CALLING_NAME, "CALLING NAME", dump_string },
 
156
        { IAX_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
 
157
        { IAX_IE_USERNAME, "USERNAME", dump_string },
 
158
        { IAX_IE_PASSWORD, "PASSWORD", dump_string },
 
159
        { IAX_IE_CAPABILITY, "CAPABILITY", dump_int },
 
160
        { IAX_IE_FORMAT, "FORMAT", dump_int },
 
161
        { IAX_IE_LANGUAGE, "LANGUAGE", dump_string },
 
162
        { IAX_IE_CODEC_PREFS, "CODEC_PREFS", dump_string },
 
163
        { IAX_IE_VERSION, "VERSION", dump_short },
 
164
        { IAX_IE_ADSICPE, "ADSICPE", dump_short },
 
165
        { IAX_IE_DNID, "DNID", dump_string },
 
166
        { IAX_IE_AUTHMETHODS, "AUTHMETHODS", dump_short },
 
167
        { IAX_IE_CHALLENGE, "CHALLENGE", dump_string },
 
168
        { IAX_IE_MD5_RESULT, "MD5 RESULT", dump_string },
 
169
        { IAX_IE_RSA_RESULT, "RSA RESULT", dump_string },
 
170
        { IAX_IE_APPARENT_ADDR, "APPARENT ADDRESS", dump_addr },
 
171
        { IAX_IE_REFRESH, "REFRESH", dump_short },
 
172
        { IAX_IE_DPSTATUS, "DIALPLAN STATUS", dump_short },
 
173
        { IAX_IE_CALLNO, "CALL NUMBER", dump_short },
 
174
        { IAX_IE_CAUSE, "CAUSE", dump_string },
 
175
        { IAX_IE_IAX_UNKNOWN, "UNKNOWN IAX CMD", dump_byte },
 
176
        { IAX_IE_MSGCOUNT, "MESSAGE COUNT", dump_short },
 
177
        { IAX_IE_AUTOANSWER, "AUTO ANSWER REQ" },
 
178
        { IAX_IE_TRANSFERID, "TRANSFER ID", dump_int },
 
179
        { IAX_IE_RDNIS, "REFERRING DNIS", dump_string },
 
180
        { IAX_IE_PROVISIONING, "PROVISIONING", dump_prov },
 
181
        { IAX_IE_AESPROVISIONING, "AES PROVISIONG" },
 
182
        { IAX_IE_DATETIME, "DATE TIME", dump_int },
 
183
        { IAX_IE_DEVICETYPE, "DEVICE TYPE", dump_string },
 
184
        { IAX_IE_SERVICEIDENT, "SERVICE IDENT", dump_string },
 
185
        { IAX_IE_FIRMWAREVER, "FIRMWARE VER", dump_short },
 
186
        { IAX_IE_FWBLOCKDESC, "FW BLOCK DESC", dump_int },
 
187
        { IAX_IE_FWBLOCKDATA, "FW BLOCK DATA" },
 
188
        { IAX_IE_PROVVER, "PROVISIONG VER", dump_int },
 
189
        { IAX_IE_CALLINGPRES, "CALLING PRESNTN", dump_byte },
 
190
        { IAX_IE_CALLINGTON, "CALLING TYPEOFNUM", dump_byte },
 
191
        { IAX_IE_CALLINGTNS, "CALLING TRANSITNET", dump_short },
 
192
        { IAX_IE_SAMPLINGRATE, "SAMPLINGRATE", dump_samprate },
 
193
        { IAX_IE_CODEC_PREFS, "CODEC_PREFS", dump_string },
 
194
        { IAX_IE_RR_JITTER, "RR_JITTER", dump_int },
 
195
        { IAX_IE_RR_LOSS, "RR_LOSS", dump_int },
 
196
        { IAX_IE_RR_PKTS, "RR_PKTS", dump_int },
 
197
        { IAX_IE_RR_DELAY, "RR_DELAY", dump_short },
 
198
        { IAX_IE_RR_DROPPED, "RR_DROPPED", dump_int },
 
199
        { IAX_IE_RR_OOO, "RR_OOO", dump_int },
 
200
};
 
201
 
 
202
const char *iax_ie2str(int ie)
 
203
{
 
204
        int x;
 
205
        for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
 
206
                if (ies[x].ie == ie)
 
207
                        return ies[x].name;
 
208
        }
 
209
        return "Unknown IE";
 
210
}
 
211
 
 
212
 
 
213
static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len)
 
214
{
 
215
        int ielen;
 
216
        int ie;
 
217
        int found;
 
218
        char tmp[256];
 
219
        if (len < 2)
 
220
                return;
 
221
        strcpy(output, "\n"); 
 
222
        maxlen -= (int)strlen(output); output += strlen(output);
 
223
        while(len > 2) {
 
224
                ie = iedata[0];
 
225
                ielen = iedata[1];
 
226
                if (ielen + 2> len) {
 
227
                        snprintf(tmp, (int)sizeof(tmp), "Total Prov IE length of %d bytes exceeds remaining prov frame length of %d bytes\n", ielen + 2, len);
 
228
                        strncpy(output, tmp, maxlen - 1);
 
229
                        maxlen -= (int)strlen(output); output += strlen(output);
 
230
                        return;
 
231
                }
 
232
                found = 0;
 
233
                if (!found) {
 
234
                        snprintf(tmp, (int)sizeof(tmp), "       Unknown Prov IE %03d  : Present\n", ie);
 
235
                        strncpy(output, tmp, maxlen - 1);
 
236
                        maxlen -= (int)strlen(output); output += strlen(output);
 
237
                }
 
238
                iedata += (2 + ielen);
 
239
                len -= (2 + ielen);
 
240
        }
 
241
}
 
242
 
 
243
static void dump_ies(unsigned char *iedata, int len)
 
244
{
 
245
        int ielen;
 
246
        int ie;
 
247
        int x;
 
248
        int found;
 
249
        char interp[1024];
 
250
        char tmp[1024];
 
251
        if (len < 2)
 
252
                return;
 
253
        while(len > 2) {
 
254
                ie = iedata[0];
 
255
                ielen = iedata[1];
 
256
                if (ielen + 2> len) {
 
257
                        snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
 
258
                        outputf(tmp);
 
259
                        return;
 
260
                }
 
261
                found = 0;
 
262
                for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
 
263
                        if (ies[x].ie == ie) {
 
264
                                if (ies[x].dump) {
 
265
                                        ies[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
 
266
                                        snprintf(tmp, (int)sizeof(tmp), "   %-15.15s : %s\n", ies[x].name, interp);
 
267
                                        outputf(tmp);
 
268
                                } else {
 
269
                                        if (ielen)
 
270
                                                snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
 
271
                                        else
 
272
                                                strcpy(interp, "Present");
 
273
                                        snprintf(tmp, (int)sizeof(tmp), "   %-15.15s : %s\n", ies[x].name, interp);
 
274
                                        outputf(tmp);
 
275
                                }
 
276
                                found++;
 
277
                        }
 
278
                }
 
279
                if (!found) {
 
280
                        snprintf(tmp, (int)sizeof(tmp), "   Unknown IE %03d  : Present\n", ie);
 
281
                        outputf(tmp);
 
282
                }
 
283
                iedata += (2 + ielen);
 
284
                len -= (2 + ielen);
 
285
        }
 
286
        outputf("\n");
 
287
}
 
288
 
 
289
void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
 
290
{
 
291
        const char *frames[] = {
 
292
                "(0?)",
 
293
                "DTMF   ",
 
294
                "VOICE  ",
 
295
                "VIDEO  ",
 
296
                "CONTROL",
 
297
                "NULL   ",
 
298
                "IAX    ",
 
299
                "TEXT   ",
 
300
                "IMAGE  " };
 
301
        const char *iaxs[] = {
 
302
                "(0?)",
 
303
                "NEW    ",
 
304
                "PING   ",
 
305
                "PONG   ",
 
306
                "ACK    ",
 
307
                "HANGUP ",
 
308
                "REJECT ",
 
309
                "ACCEPT ",
 
310
                "AUTHREQ",
 
311
                "AUTHREP",
 
312
                "INVAL  ",
 
313
                "LAGRQ  ",
 
314
                "LAGRP  ",
 
315
                "REGREQ ",
 
316
                "REGAUTH",
 
317
                "REGACK ",
 
318
                "REGREJ ",
 
319
                "REGREL ",
 
320
                "VNAK   ",
 
321
                "DPREQ  ",
 
322
                "DPREP  ",
 
323
                "DIAL   ",
 
324
                "TXREQ  ",
 
325
                "TXCNT  ",
 
326
                "TXACC  ",
 
327
                "TXREADY",
 
328
                "TXREL  ",
 
329
                "TXREJ  ",
 
330
                "QUELCH ",
 
331
                "UNQULCH",
 
332
                "POKE",
 
333
                "PAGE",
 
334
                "MWI",
 
335
                "UNSUPPORTED",
 
336
                "TRANSFER",
 
337
                "PROVISION",
 
338
                "FWDOWNLD",
 
339
                "FWDATA"
 
340
        };
 
341
        const char *cmds[] = {
 
342
                "(0?)",
 
343
                "HANGUP ",
 
344
                "RING   ",
 
345
                "RINGING",
 
346
                "ANSWER ",
 
347
                "BUSY   ",
 
348
                "TKOFFHK ",
 
349
                "OFFHOOK" };
 
350
        struct ast_iax2_full_hdr *fh;
 
351
        char retries[20];
 
352
        char class2[20];
 
353
        char subclass2[20];
 
354
        const char *clas;
 
355
        const char *subclass;
 
356
        char tmp[256];
 
357
 
 
358
        if (f) {
 
359
                fh = (struct ast_iax2_full_hdr *)f->data;
 
360
                snprintf(retries, (int)sizeof(retries), "%03d", f->retries);
 
361
        } else {
 
362
                fh = fhi;
 
363
                if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS)
 
364
                        strcpy(retries, "Yes");
 
365
                else
 
366
                        strcpy(retries, " No");
 
367
        }
 
368
        if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) {
 
369
                /* Don't mess with mini-frames */
 
370
                return;
 
371
        }
 
372
        if (fh->type > (int)sizeof(frames)/(int)sizeof(char *)) {
 
373
                snprintf(class2, (int)sizeof(class2), "(%d?)", fh->type);
 
374
                clas = class2;
 
375
        } else {
 
376
                clas = frames[(int)fh->type];
 
377
        }
 
378
        if (fh->type == AST_FRAME_DTMF) {
 
379
                sprintf(subclass2, "%c", fh->csub);
 
380
                subclass = subclass2;
 
381
        } else if (fh->type == AST_FRAME_IAX) {
 
382
                if (fh->csub >= (int)sizeof(iaxs)/(int)sizeof(iaxs[0])) {
 
383
                        snprintf(subclass2, (int)sizeof(subclass2), "(%d?)", fh->csub);
 
384
                        subclass = subclass2;
 
385
                } else {
 
386
                        subclass = iaxs[(int)fh->csub];
 
387
                }
 
388
        } else if (fh->type == AST_FRAME_CONTROL) {
 
389
                if (fh->csub > (int)sizeof(cmds)/(int)sizeof(char *)) {
 
390
                        snprintf(subclass2, (int)sizeof(subclass2), "(%d?)", fh->csub);
 
391
                        subclass = subclass2;
 
392
                } else {
 
393
                        subclass = cmds[(int)fh->csub];
 
394
                }
 
395
        } else {
 
396
                snprintf(subclass2, (int)sizeof(subclass2), "%d", fh->csub);
 
397
                subclass = subclass2;
 
398
        }
 
399
snprintf(tmp, (int)sizeof(tmp), 
 
400
"%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
 
401
        (rx ? "Rx" : "Tx"),
 
402
        retries, fh->oseqno, fh->iseqno, clas, subclass);
 
403
        outputf(tmp);
 
404
snprintf(tmp, (int)sizeof(tmp), 
 
405
"   Timestamp: %05lums  SCall: %5.5d  DCall: %5.5d [%s:%d]\n",
 
406
        (unsigned long)ntohl(fh->ts),
 
407
        ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
 
408
                inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
 
409
        outputf(tmp);
 
410
        if (fh->type == AST_FRAME_IAX)
 
411
                dump_ies(fh->iedata, datalen);
 
412
}
 
413
 
 
414
int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
 
415
{
 
416
        char tmp[256];
 
417
        if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
 
418
                snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", iax_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
 
419
                errorf(tmp);
 
420
                return -1;
 
421
        }
 
422
        ied->buf[ied->pos++] = ie;
 
423
        ied->buf[ied->pos++] = datalen;
 
424
        memcpy(ied->buf + ied->pos, data, datalen);
 
425
        ied->pos += datalen;
 
426
        return 0;
 
427
}
 
428
 
 
429
int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
 
430
{
 
431
        return iax_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
 
432
}
 
433
 
 
434
int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value) 
 
435
{
 
436
        unsigned int newval;
 
437
        newval = htonl(value);
 
438
        return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
 
439
}
 
440
 
 
441
int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value) 
 
442
{
 
443
        unsigned short newval;
 
444
        newval = htons(value);
 
445
        return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
 
446
}
 
447
 
 
448
int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const char *str)
 
449
{
 
450
        return iax_ie_append_raw(ied, ie, str, (int)strlen(str));
 
451
}
 
452
 
 
453
int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
 
454
{
 
455
        return iax_ie_append_raw(ied, ie, &dat, 1);
 
456
}
 
457
 
 
458
int iax_ie_append(struct iax_ie_data *ied, unsigned char ie) 
 
459
{
 
460
        return iax_ie_append_raw(ied, ie, NULL, 0);
 
461
}
 
462
 
 
463
void iax_set_output(void (*func)(const char *))
 
464
{
 
465
        outputf = func;
 
466
}
 
467
 
 
468
void iax_set_error(void (*func)(const char *))
 
469
{
 
470
        errorf = func;
 
471
}
 
472
 
 
473
int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
 
474
{
 
475
        /* Parse data into information elements */
 
476
        int len;
 
477
        int ie;
 
478
        char tmp[256];
 
479
        memset(ies, 0, (int)sizeof(struct iax_ies));
 
480
        ies->msgcount = -1;
 
481
        ies->firmwarever = -1;
 
482
        ies->calling_ton = -1;
 
483
        ies->calling_tns = -1;
 
484
        ies->calling_pres = -1;
 
485
        ies->samprate = IAX_RATE_8KHZ;
 
486
        while(datalen >= 2) {
 
487
                ie = data[0];
 
488
                len = data[1];
 
489
                if (len > datalen - 2) {
 
490
                        errorf("Information element length exceeds message size\n");
 
491
                        return -1;
 
492
                }
 
493
                switch(ie) {
 
494
                case IAX_IE_CALLED_NUMBER:
 
495
                        ies->called_number = (char *) data + 2;
 
496
                        break;
 
497
                case IAX_IE_CALLING_NUMBER:
 
498
                        ies->calling_number = (char *) data + 2;
 
499
                        break;
 
500
                case IAX_IE_CALLING_ANI:
 
501
                        ies->calling_ani = (char *) data + 2;
 
502
                        break;
 
503
                case IAX_IE_CALLING_NAME:
 
504
                        ies->calling_name = (char *) data + 2;
 
505
                        break;
 
506
                case IAX_IE_CALLED_CONTEXT:
 
507
                        ies->called_context = (char *) data + 2;
 
508
                        break;
 
509
                case IAX_IE_USERNAME:
 
510
                        ies->username = (char *) data + 2;
 
511
                        break;
 
512
                case IAX_IE_PASSWORD:
 
513
                        ies->password = (char *) data + 2;
 
514
                        break;
 
515
                case IAX_IE_CAPABILITY:
 
516
                        if (len != (int)sizeof(unsigned int)) {
 
517
                                snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
518
                                errorf(tmp);
 
519
                        } else
 
520
                                ies->capability = ntohl(get_uint32(data + 2));
 
521
                        break;
 
522
                case IAX_IE_FORMAT:
 
523
                        if (len != (int)sizeof(unsigned int)) {
 
524
                                snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
525
                                errorf(tmp);
 
526
                        } else
 
527
                                ies->format = ntohl(get_uint32(data + 2));
 
528
                        break;
 
529
                case IAX_IE_LANGUAGE:
 
530
                        ies->language = (char *) data + 2;
 
531
                        break;
 
532
                case IAX_IE_CODEC_PREFS:
 
533
                        ies->codec_prefs = (char *) data + 2;
 
534
                        break;
 
535
                case IAX_IE_VERSION:
 
536
                        if (len != (int)sizeof(unsigned short)) {
 
537
                                snprintf(tmp, (int)sizeof(tmp),  "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
538
                                errorf(tmp);
 
539
                        } else
 
540
                                ies->version = ntohs(get_uint16(data + 2));
 
541
                        break;
 
542
                case IAX_IE_ADSICPE:
 
543
                        if (len != (int)sizeof(unsigned short)) {
 
544
                                snprintf(tmp, (int)sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
545
                                errorf(tmp);
 
546
                        } else
 
547
                                ies->adsicpe = ntohs(get_uint16(data + 2));
 
548
                        break;
 
549
                case IAX_IE_SAMPLINGRATE:
 
550
                        if (len != (int)sizeof(unsigned short)) {
 
551
                                snprintf(tmp, (int)sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
552
                                errorf(tmp);
 
553
                        } else
 
554
                                ies->samprate = ntohs(get_uint16(data + 2));
 
555
                        break;
 
556
                case IAX_IE_DNID:
 
557
                        ies->dnid = (char *) data + 2;
 
558
                        break;
 
559
                case IAX_IE_RDNIS:
 
560
                        ies->rdnis = (char *) data + 2;
 
561
                        break;
 
562
                case IAX_IE_AUTHMETHODS:
 
563
                        if (len != (int)sizeof(unsigned short))  {
 
564
                                snprintf(tmp, (int)sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
565
                                errorf(tmp);
 
566
                        } else
 
567
                                ies->authmethods = ntohs(get_uint16(data + 2));
 
568
                        break;
 
569
                case IAX_IE_CHALLENGE:
 
570
                        ies->challenge = (char *) data + 2;
 
571
                        break;
 
572
                case IAX_IE_MD5_RESULT:
 
573
                        ies->md5_result = (char *) data + 2;
 
574
                        break;
 
575
                case IAX_IE_RSA_RESULT:
 
576
                        ies->rsa_result = (char *) data + 2;
 
577
                        break;
 
578
                case IAX_IE_APPARENT_ADDR:
 
579
                        ies->apparent_addr = ((struct sockaddr_in *)(data + 2));
 
580
                        break;
 
581
                case IAX_IE_REFRESH:
 
582
                        if (len != (int)sizeof(unsigned short)) {
 
583
                                snprintf(tmp, (int)sizeof(tmp),  "Expecting refresh to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
584
                                errorf(tmp);
 
585
                        } else
 
586
                                ies->refresh = ntohs(get_uint16(data + 2));
 
587
                        break;
 
588
                case IAX_IE_DPSTATUS:
 
589
                        if (len != (int)sizeof(unsigned short)) {
 
590
                                snprintf(tmp, (int)sizeof(tmp),  "Expecting dpstatus to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
591
                                errorf(tmp);
 
592
                        } else
 
593
                                ies->dpstatus = ntohs(get_uint16(data + 2));
 
594
                        break;
 
595
                case IAX_IE_CALLNO:
 
596
                        if (len != (int)sizeof(unsigned short)) {
 
597
                                snprintf(tmp, (int)sizeof(tmp),  "Expecting callno to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
598
                                errorf(tmp);
 
599
                        } else
 
600
                                ies->callno = ntohs(get_uint16(data + 2));
 
601
                        break;
 
602
                case IAX_IE_CAUSE:
 
603
                        ies->cause = (char *) data + 2;
 
604
                        break;
 
605
                case IAX_IE_CAUSECODE:
 
606
                        if (len != 1) {
 
607
                                snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
 
608
                                errorf(tmp);
 
609
                        } else {
 
610
                                ies->causecode = data[2];
 
611
                        }
 
612
                        break;
 
613
                case IAX_IE_IAX_UNKNOWN:
 
614
                        if (len == 1)
 
615
                                ies->iax_unknown = data[2];
 
616
                        else {
 
617
                                snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
 
618
                                errorf(tmp);
 
619
                        }
 
620
                        break;
 
621
                case IAX_IE_MSGCOUNT:
 
622
                        if (len != (int)sizeof(unsigned short)) {
 
623
                                snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
624
                                errorf(tmp);
 
625
                        } else
 
626
                                ies->msgcount = ntohs(get_uint16(data + 2));    
 
627
                        break;
 
628
                case IAX_IE_AUTOANSWER:
 
629
                        ies->autoanswer = 1;
 
630
                        break;
 
631
                case IAX_IE_MUSICONHOLD:
 
632
                        ies->musiconhold = 1;
 
633
                        break;
 
634
                case IAX_IE_TRANSFERID:
 
635
                        if (len != (int)sizeof(unsigned int)) {
 
636
                                snprintf(tmp, (int)sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
637
                                errorf(tmp);
 
638
                        } else
 
639
                                ies->transferid = ntohl(get_uint32(data + 2));
 
640
                        break;
 
641
                case IAX_IE_DATETIME:
 
642
                        if (len != (int)sizeof(unsigned int)) {
 
643
                                snprintf(tmp, (int)sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
644
                                errorf(tmp);
 
645
                        } else
 
646
                                ies->datetime = ntohl(get_uint32(data + 2));
 
647
                        break;
 
648
                case IAX_IE_FIRMWAREVER:
 
649
                        if (len != (int)sizeof(unsigned short)) {
 
650
                                snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
651
                                errorf(tmp);
 
652
                        } else
 
653
                                ies->firmwarever = ntohs(get_uint16(data + 2)); 
 
654
                        break;
 
655
                case IAX_IE_DEVICETYPE:
 
656
                        ies->devicetype = (char *) data + 2;
 
657
                        break;
 
658
                case IAX_IE_SERVICEIDENT:
 
659
                        ies->serviceident = (char *) data + 2;
 
660
                        break;
 
661
                case IAX_IE_FWBLOCKDESC:
 
662
                        if (len != (int)sizeof(unsigned int)) {
 
663
                                snprintf(tmp, (int)sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
664
                                errorf(tmp);
 
665
                        } else
 
666
                                ies->fwdesc = ntohl(get_uint32(data + 2));
 
667
                        break;
 
668
                case IAX_IE_FWBLOCKDATA:
 
669
                        ies->fwdata = data + 2;
 
670
                        ies->fwdatalen = len;
 
671
                        break;
 
672
                case IAX_IE_PROVVER:
 
673
                        if (len != (int)sizeof(unsigned int)) {
 
674
                                snprintf(tmp, (int)sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
675
                                errorf(tmp);
 
676
                        } else {
 
677
                                ies->provverpres = 1;
 
678
                                ies->provver = ntohl(get_uint32(data + 2));
 
679
                        }
 
680
                        break;
 
681
                case IAX_IE_CALLINGPRES:
 
682
                        if (len == 1)
 
683
                                ies->calling_pres = data[2];
 
684
                        else {
 
685
                                snprintf(tmp, (int)sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len);
 
686
                                errorf(tmp);
 
687
                        }
 
688
                        break;
 
689
                case IAX_IE_CALLINGTON:
 
690
                        if (len == 1)
 
691
                                ies->calling_ton = data[2];
 
692
                        else {
 
693
                                snprintf(tmp, (int)sizeof(tmp), "Expected single byte callington, but was %d long\n", len);
 
694
                                errorf(tmp);
 
695
                        }
 
696
                        break;
 
697
                case IAX_IE_CALLINGTNS:
 
698
                        if (len != (int)sizeof(unsigned short)) {
 
699
                                snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
700
                                errorf(tmp);
 
701
                        } else
 
702
                                ies->calling_tns = ntohs(get_uint16(data + 2)); 
 
703
                        break;
 
704
                case IAX_IE_RR_JITTER:
 
705
                        if (len != (int)sizeof(unsigned int)) {
 
706
                                snprintf(tmp, (int)sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
707
                                errorf(tmp);
 
708
                        } else {
 
709
                                ies->rr_jitter = ntohl(get_uint32(data + 2));
 
710
                        }
 
711
                        break;
 
712
                case IAX_IE_RR_LOSS:
 
713
                        if (len != (int)sizeof(unsigned int)) {
 
714
                                snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
715
                                errorf(tmp);
 
716
                        } else {
 
717
                                ies->rr_loss = ntohl(get_uint32(data + 2));
 
718
                        }
 
719
                        break;
 
720
                case IAX_IE_RR_PKTS:
 
721
                        if (len != (int)sizeof(unsigned int)) {
 
722
                                snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
723
                                errorf(tmp);
 
724
                        } else {
 
725
                                ies->rr_pkts = ntohl(get_uint32(data + 2));
 
726
                        }
 
727
                        break;
 
728
                case IAX_IE_RR_DELAY:
 
729
                        if (len != (int)sizeof(unsigned short)) {
 
730
                                snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
 
731
                                errorf(tmp);
 
732
                        } else {
 
733
                                ies->rr_delay = ntohs(get_uint16(data + 2));
 
734
                        }
 
735
                        break;
 
736
                case IAX_IE_RR_DROPPED:
 
737
                        if (len != (int)sizeof(unsigned int)) {
 
738
                                snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
739
                                errorf(tmp);
 
740
                        } else {
 
741
                                ies->rr_dropped = ntohl(get_uint32(data + 2));
 
742
                        }
 
743
                        break;
 
744
                case IAX_IE_RR_OOO:
 
745
                        if (len != (int)sizeof(unsigned int)) {
 
746
                                snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
 
747
                                errorf(tmp);
 
748
                        } else {
 
749
                                ies->rr_ooo = ntohl(get_uint32(data + 2));
 
750
                        }
 
751
                        break;
 
752
                default:
 
753
                        snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
 
754
                        outputf(tmp);
 
755
                }
 
756
                /* Overwrite information element with 0, to null terminate previous portion */
 
757
                data[0] = 0;
 
758
                datalen -= (len + 2);
 
759
                data += (len + 2);
 
760
        }
 
761
        /* Null-terminate last field */
 
762
        *data = '\0';
 
763
        if (datalen) {
 
764
                errorf("Invalid information element contents, strange boundary\n");
 
765
                return -1;
 
766
        }
 
767
        return 0;
 
768
}
 
769
 
 
770
void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
 
771
{
 
772
        fr->af.frametype = f->frametype;
 
773
        fr->af.subclass = f->subclass;
 
774
        fr->af.mallocd = 0;                             /* Our frame is static relative to the container */
 
775
        fr->af.datalen = f->datalen;
 
776
        fr->af.samples = f->samples;
 
777
        fr->af.offset = AST_FRIENDLY_OFFSET;
 
778
        fr->af.src = f->src;
 
779
        fr->af.data = fr->afdata;
 
780
        if (fr->af.datalen) 
 
781
                memcpy(fr->af.data, f->data, fr->af.datalen);
 
782
}
 
783
 
 
784
struct iax_frame *iax_frame_new(int direction, int datalen)
 
785
{
 
786
        struct iax_frame *fr;
 
787
        fr = (struct iax_frame *)malloc((int)sizeof(struct iax_frame) + datalen);
 
788
        if (fr) {
 
789
                fr->direction = direction;
 
790
                fr->retrans = -1;
 
791
                frames++;
 
792
                if (fr->direction == DIRECTION_INGRESS)
 
793
                        iframes++;
 
794
                else
 
795
                        oframes++;
 
796
        }
 
797
        return fr;
 
798
}
 
799
 
 
800
void iax_frame_free(struct iax_frame *fr)
 
801
{
 
802
        /* Note: does not remove from scheduler! */
 
803
        if (fr->direction == DIRECTION_INGRESS)
 
804
                iframes--;
 
805
        else if (fr->direction == DIRECTION_OUTGRESS)
 
806
                oframes--;
 
807
        else {
 
808
                errorf("Attempt to double free frame detected\n");
 
809
                return;
 
810
        }
 
811
        fr->direction = 0;
 
812
        free(fr);
 
813
        frames--;
 
814
}
 
815
 
 
816
int iax_get_frames(void) { return frames; }
 
817
int iax_get_iframes(void) { return iframes; }
 
818
int iax_get_oframes(void) { return oframes; }