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