ee4a6c3bef977002eabe1c3c31b0ac61ed2e8653
[asterisk/asterisk.git] / channels / iax2 / parser.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Implementation of Inter-Asterisk eXchange Protocol, v 2
22  *
23  * \author Mark Spencer <markster@digium.com> 
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37
38 #include "asterisk/frame.h"
39 #include "asterisk/utils.h"
40 #include "asterisk/unaligned.h"
41 #include "asterisk/config.h"
42 #include "asterisk/lock.h"
43 #include "asterisk/threadstorage.h"
44 #include "asterisk/netsock2.h"
45
46 #include "include/iax2.h"
47 #include "include/parser.h"
48 #include "include/provision.h"
49
50 static int frames = 0;
51 static int iframes = 0;
52 static int oframes = 0;
53
54 #if !defined(LOW_MEMORY)
55 static void frame_cache_cleanup(void *data);
56
57 /*! \brief A per-thread cache of iax_frame structures */
58 AST_THREADSTORAGE_CUSTOM(frame_cache, NULL, frame_cache_cleanup);
59
60 /*! \brief This is just so iax_frames, a list head struct for holding a list of
61  *  iax_frame structures, is defined. */
62 AST_LIST_HEAD_NOLOCK(iax_frame_list, iax_frame);
63
64 struct iax_frames {
65         struct iax_frame_list list;
66         size_t size;
67 };
68
69 #define FRAME_CACHE_MAX_SIZE    20
70 #endif
71
72 static void internaloutput(const char *str)
73 {
74         fputs(str, stdout);
75 }
76
77 static void internalerror(const char *str)
78 {
79         fprintf(stderr, "WARNING: %s", str);
80 }
81
82 static void (*outputf)(const char *str) = internaloutput;
83 static void (*errorf)(const char *str) = internalerror;
84
85 static void dump_addr(char *output, int maxlen, void *value, int len)
86 {
87         struct ast_sockaddr addr;
88
89         if (len == (int)sizeof(struct sockaddr_in)) {
90                 addr.ss.ss_family = AF_INET;
91         } else if (len == (int) sizeof(struct sockaddr_in6)) {
92                 addr.ss.ss_family = AF_INET6;
93         } else {
94                 ast_copy_string(output, "Invalid Address", maxlen);
95                 return;
96         }
97
98         memcpy(&addr, value, len);
99         addr.len = len;
100
101         snprintf(output, maxlen, "%s %s",
102                                 ast_sockaddr_is_ipv4(&addr) || ast_sockaddr_is_ipv4_mapped(&addr) ? "IPV4" : "IPV6",
103                                 ast_sockaddr_stringify(&addr));
104 }
105
106 static void dump_string_hex(char *output, int maxlen, void *value, int len)
107 {
108         int i = 0;
109
110         while (len-- && (i + 1) * 4 < maxlen) {
111                 sprintf(output + (4 * i), "\\x%2.2x", *((unsigned char *)value + i));
112                 i++;
113         }
114 }
115
116 static void dump_string(char *output, int maxlen, void *value, int len)
117 {
118         maxlen--;
119         if (maxlen > len)
120                 maxlen = len;
121         strncpy(output, value, maxlen);
122         output[maxlen] = '\0';
123 }
124
125 static void dump_prefs(char *output, int maxlen, void *value, int len)
126 {
127         struct ast_codec_pref pref;
128         int total_len = 0;
129
130         maxlen--;
131         total_len = maxlen;
132
133         if (maxlen > len)
134                 maxlen = len;
135
136         strncpy(output, value, maxlen);
137         output[maxlen] = '\0';
138         
139         ast_codec_pref_convert(&pref, output, total_len, 0);
140         memset(output,0,total_len);
141         ast_codec_pref_string(&pref, output, total_len);
142 }
143
144 static void dump_int(char *output, int maxlen, void *value, int len)
145 {
146         if (len == (int)sizeof(unsigned int))
147                 snprintf(output, maxlen, "%lu", (unsigned long)ntohl(get_unaligned_uint32(value)));
148         else
149                 ast_copy_string(output, "Invalid INT", maxlen); 
150 }
151
152 static void dump_short(char *output, int maxlen, void *value, int len)
153 {
154         if (len == (int)sizeof(unsigned short))
155                 snprintf(output, maxlen, "%d", ntohs(get_unaligned_uint16(value)));
156         else
157                 ast_copy_string(output, "Invalid SHORT", maxlen);
158 }
159
160 static void dump_byte(char *output, int maxlen, void *value, int len)
161 {
162         if (len == (int)sizeof(unsigned char))
163                 snprintf(output, maxlen, "%d", *((unsigned char *)value));
164         else
165                 ast_copy_string(output, "Invalid BYTE", maxlen);
166 }
167
168 static void dump_datetime(char *output, int maxlen, void *value, int len)
169 {
170         struct ast_tm tm;
171         unsigned long val = (unsigned long) ntohl(get_unaligned_uint32(value));
172         if (len == (int)sizeof(unsigned int)) {
173                 tm.tm_sec  = (val & 0x1f) << 1;
174                 tm.tm_min  = (val >> 5) & 0x3f;
175                 tm.tm_hour = (val >> 11) & 0x1f;
176                 tm.tm_mday = (val >> 16) & 0x1f;
177                 tm.tm_mon  = ((val >> 21) & 0x0f) - 1;
178                 tm.tm_year = ((val >> 25) & 0x7f) + 100;
179                 ast_strftime(output, maxlen, "%Y-%m-%d  %T", &tm); 
180         } else
181                 ast_copy_string(output, "Invalid DATETIME format!", maxlen);
182 }
183
184 static void dump_ipaddr(char *output, int maxlen, void *value, int len)
185 {
186         struct ast_sockaddr addr;
187         char *str_addr;
188
189         if (len == (int)sizeof(struct sockaddr_in)) {
190                 addr.ss.ss_family = AF_INET;
191         } else if (len == (int)sizeof(struct sockaddr_in6)) {
192                 addr.ss.ss_family = AF_INET6;
193         } else {
194                 ast_copy_string(output, "Invalid IPADDR", maxlen);
195                 return;
196         }
197
198         memcpy(&addr, value, len);
199         addr.len = len;
200
201         str_addr = ast_sockaddr_stringify(&addr);
202         ast_copy_string(output, str_addr, maxlen);
203 }
204
205
206 static void dump_prov_flags(char *output, int maxlen, void *value, int len)
207 {
208         char buf[256] = "";
209         if (len == (int)sizeof(unsigned int))
210                 snprintf(output, maxlen, "%lu (%s)", (unsigned long)ntohl(get_unaligned_uint32(value)),
211                         iax_provflags2str(buf, sizeof(buf), ntohl(get_unaligned_uint32(value))));
212         else
213                 ast_copy_string(output, "Invalid INT", maxlen);
214 }
215
216 static void dump_samprate(char *output, int maxlen, void *value, int len)
217 {
218         char tmp[256]="";
219         int sr;
220         if (len == (int)sizeof(unsigned short)) {
221                 sr = ntohs(*((unsigned short *)value));
222                 if (sr & IAX_RATE_8KHZ)
223                         strcat(tmp, ",8khz");
224                 if (sr & IAX_RATE_11KHZ)
225                         strcat(tmp, ",11.025khz");
226                 if (sr & IAX_RATE_16KHZ)
227                         strcat(tmp, ",16khz");
228                 if (sr & IAX_RATE_22KHZ)
229                         strcat(tmp, ",22.05khz");
230                 if (sr & IAX_RATE_44KHZ)
231                         strcat(tmp, ",44.1khz");
232                 if (sr & IAX_RATE_48KHZ)
233                         strcat(tmp, ",48khz");
234                 if (strlen(tmp))
235                         ast_copy_string(output, &tmp[1], maxlen);
236                 else
237                         ast_copy_string(output, "None Specified!\n", maxlen);
238         } else
239                 ast_copy_string(output, "Invalid SHORT", maxlen);
240
241 }
242
243 static void dump_versioned_codec(char *output, int maxlen, void *value, int len)
244 {
245         char *version = (char *) value;
246         if (version[0] == 0) {
247                 if (len == (int) (sizeof(iax2_format) + sizeof(char))) {
248                         iax2_format codec = ntohll(get_unaligned_uint64(value + 1));
249                         ast_copy_string(output, iax2_getformatname(codec), maxlen);
250                 } else {
251                         ast_copy_string(output, "Invalid length!", maxlen);
252                 }
253         } else {
254                 ast_copy_string(output, "Unknown version!", maxlen);
255         }
256 }
257
258 static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len);
259 static void dump_prov(char *output, int maxlen, void *value, int len)
260 {
261         dump_prov_ies(output, maxlen, value, len);
262 }
263
264 struct iax2_ie {
265         int ie;
266         char *name;
267         void (*dump)(char *output, int maxlen, void *value, int len);
268 };
269 static struct iax2_ie infoelts[] = {
270         { IAX_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
271         { IAX_IE_CALLING_NUMBER, "CALLING NUMBER", dump_string },
272         { IAX_IE_CALLING_ANI, "ANI", dump_string },
273         { IAX_IE_CALLING_NAME, "CALLING NAME", dump_string },
274         { IAX_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
275         { IAX_IE_USERNAME, "USERNAME", dump_string },
276         { IAX_IE_PASSWORD, "PASSWORD", dump_string },
277         { IAX_IE_CAPABILITY, "CAPABILITY", dump_int },
278         { IAX_IE_CAPABILITY2, "CAPABILITY2", dump_versioned_codec },
279         { IAX_IE_FORMAT, "FORMAT", dump_int },
280         { IAX_IE_FORMAT2, "FORMAT2", dump_versioned_codec },
281         { IAX_IE_LANGUAGE, "LANGUAGE", dump_string },
282         { IAX_IE_VERSION, "VERSION", dump_short },
283         { IAX_IE_ADSICPE, "ADSICPE", dump_short },
284         { IAX_IE_DNID, "DNID", dump_string },
285         { IAX_IE_AUTHMETHODS, "AUTHMETHODS", dump_short },
286         { IAX_IE_CHALLENGE, "CHALLENGE", dump_string_hex },
287         { IAX_IE_MD5_RESULT, "MD5 RESULT", dump_string },
288         { IAX_IE_RSA_RESULT, "RSA RESULT", dump_string },
289         { IAX_IE_APPARENT_ADDR, "APPARENT ADDRESS", dump_addr },
290         { IAX_IE_REFRESH, "REFRESH", dump_short },
291         { IAX_IE_DPSTATUS, "DIALPLAN STATUS", dump_short },
292         { IAX_IE_CALLNO, "CALL NUMBER", dump_short },
293         { IAX_IE_CAUSE, "CAUSE", dump_string },
294         { IAX_IE_IAX_UNKNOWN, "UNKNOWN IAX CMD", dump_byte },
295         { IAX_IE_MSGCOUNT, "MESSAGE COUNT", dump_short },
296         { IAX_IE_AUTOANSWER, "AUTO ANSWER REQ" },
297         { IAX_IE_TRANSFERID, "TRANSFER ID", dump_int },
298         { IAX_IE_RDNIS, "REFERRING DNIS", dump_string },
299         { IAX_IE_PROVISIONING, "PROVISIONING", dump_prov },
300         { IAX_IE_AESPROVISIONING, "AES PROVISIONG" },
301         { IAX_IE_DATETIME, "DATE TIME", dump_datetime },
302         { IAX_IE_DEVICETYPE, "DEVICE TYPE", dump_string },
303         { IAX_IE_SERVICEIDENT, "SERVICE IDENT", dump_string },
304         { IAX_IE_FIRMWAREVER, "FIRMWARE VER", dump_short },
305         { IAX_IE_FWBLOCKDESC, "FW BLOCK DESC", dump_int },
306         { IAX_IE_FWBLOCKDATA, "FW BLOCK DATA" },
307         { IAX_IE_PROVVER, "PROVISIONG VER", dump_int },
308         { IAX_IE_CALLINGPRES, "CALLING PRESNTN", dump_byte },
309         { IAX_IE_CALLINGTON, "CALLING TYPEOFNUM", dump_byte },
310         { IAX_IE_CALLINGTNS, "CALLING TRANSITNET", dump_short },
311         { IAX_IE_SAMPLINGRATE, "SAMPLINGRATE", dump_samprate },
312         { IAX_IE_CAUSECODE, "CAUSE CODE", dump_byte },
313         { IAX_IE_ENCRYPTION, "ENCRYPTION", dump_short },
314         { IAX_IE_ENCKEY, "ENCRYPTION KEY" },
315         { IAX_IE_CODEC_PREFS, "CODEC_PREFS", dump_prefs },
316         { IAX_IE_RR_JITTER, "RR_JITTER", dump_int },
317         { IAX_IE_RR_LOSS, "RR_LOSS", dump_int },
318         { IAX_IE_RR_PKTS, "RR_PKTS", dump_int },
319         { IAX_IE_RR_DELAY, "RR_DELAY", dump_short },
320         { IAX_IE_RR_DROPPED, "RR_DROPPED", dump_int },
321         { IAX_IE_RR_OOO, "RR_OUTOFORDER", dump_int },
322         { IAX_IE_VARIABLE, "VARIABLE", dump_string },
323         { IAX_IE_OSPTOKEN, "OSPTOKEN" },
324         { IAX_IE_CALLTOKEN, "CALLTOKEN" },
325 };
326
327 static const struct iax2_ie prov_ies[] = {
328         { PROV_IE_USEDHCP, "USEDHCP" },
329         { PROV_IE_IPADDR, "IPADDR", dump_ipaddr },
330         { PROV_IE_SUBNET, "SUBNET", dump_ipaddr },
331         { PROV_IE_GATEWAY, "GATEWAY", dump_ipaddr },
332         { PROV_IE_PORTNO, "BINDPORT", dump_short },
333         { PROV_IE_USER, "USERNAME", dump_string },
334         { PROV_IE_PASS, "PASSWORD", dump_string },
335         { PROV_IE_LANG, "LANGUAGE", dump_string },
336         { PROV_IE_TOS, "TYPEOFSERVICE", dump_byte },
337         { PROV_IE_FLAGS, "FLAGS", dump_prov_flags },
338         { PROV_IE_FORMAT, "FORMAT", dump_int },
339         { PROV_IE_AESKEY, "AESKEY" },
340         { PROV_IE_SERVERIP, "SERVERIP", dump_ipaddr },
341         { PROV_IE_SERVERPORT, "SERVERPORT", dump_short },
342         { PROV_IE_NEWAESKEY, "NEWAESKEY" },
343         { PROV_IE_PROVVER, "PROV VERSION", dump_int },
344         { PROV_IE_ALTSERVER, "ALTSERVERIP", dump_ipaddr },
345 };
346
347 const char *iax_ie2str(int ie)
348 {
349         int x;
350         for (x = 0; x < ARRAY_LEN(infoelts); x++) {
351                 if (infoelts[x].ie == ie)
352                         return infoelts[x].name;
353         }
354         return "Unknown IE";
355 }
356
357
358 static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len)
359 {
360         int ielen;
361         int ie;
362         int x;
363         int found;
364         char interp[80];
365         char tmp[256];
366         if (len < 2)
367                 return;
368         strcpy(output, "\n"); 
369         maxlen -= strlen(output); output += strlen(output);
370         while(len > 2) {
371                 ie = iedata[0];
372                 ielen = iedata[1];
373                 if (ielen + 2> len) {
374                         snprintf(tmp, (int)sizeof(tmp), "Total Prov IE length of %d bytes exceeds remaining prov frame length of %d bytes\n", ielen + 2, len);
375                         ast_copy_string(output, tmp, maxlen);
376                         maxlen -= strlen(output);
377                         output += strlen(output);
378                         return;
379                 }
380                 found = 0;
381                 for (x=0;x<(int)sizeof(prov_ies) / (int)sizeof(prov_ies[0]); x++) {
382                         if (prov_ies[x].ie == ie) {
383                                 if (prov_ies[x].dump) {
384                                         prov_ies[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
385                                         snprintf(tmp, (int)sizeof(tmp), "       %-15.15s : %s\n", prov_ies[x].name, interp);
386                                         ast_copy_string(output, tmp, maxlen);
387                                         maxlen -= strlen(output); output += strlen(output);
388                                 } else {
389                                         if (ielen)
390                                                 snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
391                                         else
392                                                 strcpy(interp, "Present");
393                                         snprintf(tmp, (int)sizeof(tmp), "       %-15.15s : %s\n", prov_ies[x].name, interp);
394                                         ast_copy_string(output, tmp, maxlen);
395                                         maxlen -= strlen(output); output += strlen(output);
396                                 }
397                                 found++;
398                         }
399                 }
400                 if (!found) {
401                         snprintf(tmp, (int)sizeof(tmp), "       Unknown Prov IE %03d  : Present\n", ie);
402                         ast_copy_string(output, tmp, maxlen);
403                         maxlen -= strlen(output); output += strlen(output);
404                 }
405                 iedata += (2 + ielen);
406                 len -= (2 + ielen);
407         }
408 }
409
410 static void dump_ies(unsigned char *iedata, int len)
411 {
412         int ielen;
413         int ie;
414         int x;
415         int found;
416         char interp[1024];
417         char tmp[1024];
418
419         if (len < 2)
420                 return;
421         while(len > 2) {
422                 ie = iedata[0];
423                 ielen = iedata[1];
424                 if (ielen + 2> len) {
425                         snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
426                         outputf(tmp);
427                         return;
428                 }
429                 found = 0;
430                 for (x = 0; x < ARRAY_LEN(infoelts); x++) {
431                         if (infoelts[x].ie == ie) {
432                                 if (infoelts[x].dump) {
433                                         infoelts[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
434                                         snprintf(tmp, (int)sizeof(tmp), "   %-15.15s : %s\n", infoelts[x].name, interp);
435                                         outputf(tmp);
436                                 } else {
437                                         if (ielen)
438                                                 snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
439                                         else
440                                                 strcpy(interp, "Present");
441                                         snprintf(tmp, (int)sizeof(tmp), "   %-15.15s : %s\n", infoelts[x].name, interp);
442                                         outputf(tmp);
443                                 }
444                                 found++;
445                         }
446                 }
447                 if (!found) {
448                         snprintf(tmp, (int)sizeof(tmp), "   Unknown IE %03d  : Present\n", ie);
449                         outputf(tmp);
450                 }
451                 iedata += (2 + ielen);
452                 len -= (2 + ielen);
453         }
454         outputf("\n");
455 }
456
457 void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t len)
458 {
459         const char *cmd = "Unknown";
460
461         /* if an error occurs here during compile, that means a new iax frame subclass
462          * has been added to the iax_frame_subclass enum.  Add the new subclass to the
463          * switch case and make sure to update it with a new string representation. */
464         switch (subclass) {
465         case IAX_COMMAND_NEW:
466                 cmd = "NEW    ";
467                 break;
468         case IAX_COMMAND_PING:
469                 cmd = "PING   ";
470                 break;
471         case IAX_COMMAND_PONG:
472                 cmd = "PONG   ";
473                 break;
474         case IAX_COMMAND_ACK:
475                 cmd = "ACK    ";
476                 break;
477         case IAX_COMMAND_HANGUP:
478                 cmd = "HANGUP ";
479                 break;
480         case IAX_COMMAND_REJECT:
481                 cmd = "REJECT ";
482                 break;
483         case IAX_COMMAND_ACCEPT:
484                 cmd = "ACCEPT ";
485                 break;
486         case IAX_COMMAND_AUTHREQ:
487                 cmd = "AUTHREQ";
488                 break;
489         case IAX_COMMAND_AUTHREP:
490                 cmd = "AUTHREP";
491                 break;
492         case IAX_COMMAND_INVAL:
493                 cmd = "INVAL  ";
494                 break;
495         case IAX_COMMAND_LAGRQ:
496                 cmd = "LAGRQ  ";
497                 break;
498         case IAX_COMMAND_LAGRP:
499                 cmd = "LAGRP  ";
500                 break;
501         case IAX_COMMAND_REGREQ:
502                 cmd = "REGREQ ";
503                 break;
504         case IAX_COMMAND_REGAUTH:
505                 cmd = "REGAUTH";
506                 break;
507         case IAX_COMMAND_REGACK:
508                 cmd = "REGACK ";
509                 break;
510         case IAX_COMMAND_REGREJ:
511                 cmd = "REGREJ ";
512                 break;
513         case IAX_COMMAND_REGREL:
514                 cmd = "REGREL ";
515                 break;
516         case IAX_COMMAND_VNAK:
517                 cmd = "VNAK   ";
518                 break;
519         case IAX_COMMAND_DPREQ:
520                 cmd = "DPREQ  ";
521                 break;
522         case IAX_COMMAND_DPREP:
523                 cmd = "DPREP  ";
524                 break;
525         case IAX_COMMAND_DIAL:
526                 cmd = "DIAL   ";
527                 break;
528         case IAX_COMMAND_TXREQ:
529                 cmd = "TXREQ  ";
530                 break;
531         case IAX_COMMAND_TXCNT:
532                 cmd = "TXCNT  ";
533                 break;
534         case IAX_COMMAND_TXACC:
535                 cmd = "TXACC  ";
536                 break;
537         case IAX_COMMAND_TXREADY:
538                 cmd = "TXREADY";
539                 break;
540         case IAX_COMMAND_TXREL:
541                 cmd = "TXREL  ";
542                 break;
543         case IAX_COMMAND_TXREJ:
544                 cmd = "TXREJ  ";
545                 break;
546         case IAX_COMMAND_QUELCH:
547                 cmd = "QUELCH ";
548                 break;
549         case IAX_COMMAND_UNQUELCH:
550                 cmd = "UNQULCH";
551                 break;
552         case IAX_COMMAND_POKE:
553                 cmd = "POKE   ";
554                 break;
555         case IAX_COMMAND_PAGE:
556                 cmd = "PAGE   ";
557                 break;
558         case IAX_COMMAND_MWI:
559                 cmd = "MWI    ";
560                 break;
561         case IAX_COMMAND_UNSUPPORT:
562                 cmd = "UNSPRTD";
563                 break;
564         case IAX_COMMAND_TRANSFER:
565                 cmd = "TRANSFR";
566                 break;
567         case IAX_COMMAND_PROVISION:
568                 cmd = "PROVISN";
569                 break;
570         case IAX_COMMAND_FWDOWNL:
571                 cmd = "FWDWNLD";
572                 break;
573         case IAX_COMMAND_FWDATA:
574                 cmd = "FWDATA ";
575                 break;
576         case IAX_COMMAND_TXMEDIA:
577                 cmd = "TXMEDIA";
578                 break;
579         case IAX_COMMAND_RTKEY:
580                 cmd = "RTKEY  ";
581                 break;
582         case IAX_COMMAND_CALLTOKEN:
583                 cmd = "CTOKEN ";
584                 break;
585         }
586         ast_copy_string(str, cmd, len);
587 }
588
589 void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct ast_sockaddr *addr, int datalen)
590 {
591         const char *framelist[] = {
592                 "(0?)",
593                 "DTMF_E ",
594                 "VOICE  ",
595                 "VIDEO  ",
596                 "CONTROL",
597                 "NULL   ",
598                 "IAX    ",
599                 "TEXT   ",
600                 "IMAGE  ",
601                 "HTML   ",
602                 "CNG    ",
603                 "MODEM  ",
604                 "DTMF_B ",
605         };
606         const char *cmds[] = {
607                 "(0?)",
608                 "HANGUP ",
609                 "RING   ",
610                 "RINGING",
611                 "ANSWER ",
612                 "BUSY   ",
613                 "TKOFFHK",
614                 "OFFHOOK",
615                 "CONGSTN",
616                 "FLASH  ",
617                 "WINK   ",
618                 "OPTION ",
619                 "RDKEY  ",
620                 "RDUNKEY",
621                 "PROGRES",
622                 "PROCDNG",
623                 "HOLD   ",
624                 "UNHOLD ",
625                 "VIDUPDT",
626                 "T38    ",
627                 "SRCUPDT",
628                 "TXFER  ",
629                 "CNLINE ",
630                 "REDIR  ",
631                 "T38PARM",
632                 "CC ERR!",/* This must never go across an IAX link. */
633                 "SRCCHG ",
634                 "READACT",
635                 "AOC    ",
636                 "ENDOFQ ",
637                 "INCOMPL",
638                 "MCID   ",
639                 "UPDRTPP",
640                 "PCAUSEC",
641         };
642         struct ast_iax2_full_hdr *fh;
643         char retries[20];
644         char class2[20];
645         char subclass2[20];
646         const char *class;
647         const char *subclass;
648         char *dir;
649         char tmp[512];
650
651         switch(rx) {
652         case 0:
653                 dir = "Tx";
654                 break;
655         case 2:
656                 dir = "TE";
657                 break;
658         case 3:
659                 dir = "RD";
660                 break;
661         default:
662                 dir = "Rx";
663                 break;
664         }
665         if (f) {
666                 fh = f->data;
667                 snprintf(retries, sizeof(retries), "%03d", f->retries);
668         } else {
669                 fh = fhi;
670                 if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS)
671                         strcpy(retries, "Yes");
672                 else
673                         strcpy(retries, " No");
674         }
675         if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) {
676                 /* Don't mess with mini-frames */
677                 return;
678         }
679         if (fh->type >= ARRAY_LEN(framelist)) {
680                 snprintf(class2, sizeof(class2), "(%d?)", fh->type);
681                 class = class2;
682         } else {
683                 class = framelist[(int)fh->type];
684         }
685         if (fh->type == AST_FRAME_DTMF_BEGIN || fh->type == AST_FRAME_DTMF_END) {
686                 sprintf(subclass2, "%c", fh->csub);
687                 subclass = subclass2;
688         } else if (fh->type == AST_FRAME_IAX) {
689                         iax_frame_subclass2str((int)fh->csub, subclass2, sizeof(subclass2));
690                         subclass = subclass2;
691         } else if (fh->type == AST_FRAME_CONTROL) {
692                 if (fh->csub >= ARRAY_LEN(cmds)) {
693                         snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
694                         subclass = subclass2;
695                 } else {
696                         subclass = cmds[(int)fh->csub];
697                 }
698         } else {
699                 snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);
700                 subclass = subclass2;
701         }
702
703         snprintf(tmp, sizeof(tmp),
704                 "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
705                  dir,
706                  retries, fh->oseqno, fh->iseqno, class, subclass);
707         outputf(tmp);
708         snprintf(tmp, sizeof(tmp), "   Timestamp: %05lums  SCall: %5.5d  DCall: %5.5d %s\n",
709                         (unsigned long)ntohl(fh->ts),
710                         ntohs(fh->scallno) & ~IAX_FLAG_FULL,
711                         ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
712                         ast_sockaddr_stringify(addr));
713
714         outputf(tmp);
715         if (fh->type == AST_FRAME_IAX)
716                 dump_ies(fh->iedata, datalen);
717
718 }
719
720 int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
721 {
722         char tmp[256];
723         if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
724                 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);
725                 errorf(tmp);
726                 return -1;
727         }
728         ied->buf[ied->pos++] = ie;
729         ied->buf[ied->pos++] = datalen;
730         memcpy(ied->buf + ied->pos, data, datalen);
731         ied->pos += datalen;
732         return 0;
733 }
734
735 int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct ast_sockaddr *addr)
736 {
737         return iax_ie_append_raw(ied, ie, addr, addr->len);
738 }
739
740 int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value)
741 {
742         struct _local {
743                 unsigned char version;
744                 uint64_t value;
745         } __attribute__((packed)) newval = { version, };
746         put_unaligned_uint64(&newval.value, htonll(value));
747         return iax_ie_append_raw(ied, ie, &newval, (int) sizeof(newval));
748 }
749
750 int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value) 
751 {
752         unsigned int newval;
753         newval = htonl(value);
754         return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
755 }
756
757 int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value) 
758 {
759         unsigned short newval;
760         newval = htons(value);
761         return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
762 }
763
764 int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const char *str)
765 {
766         return iax_ie_append_raw(ied, ie, str, strlen(str));
767 }
768
769 int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
770 {
771         return iax_ie_append_raw(ied, ie, &dat, 1);
772 }
773
774 int iax_ie_append(struct iax_ie_data *ied, unsigned char ie) 
775 {
776         return iax_ie_append_raw(ied, ie, NULL, 0);
777 }
778
779 void iax_set_output(void (*func)(const char *))
780 {
781         outputf = func;
782 }
783
784 void iax_set_error(void (*func)(const char *))
785 {
786         errorf = func;
787 }
788
789 int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
790 {
791         /* Parse data into information elements */
792         int len;
793         int ie;
794         char tmp[256], *tmp2;
795         struct ast_variable *var, *var2, *prev;
796         unsigned int count;
797         memset(ies, 0, (int)sizeof(struct iax_ies));
798         ies->msgcount = -1;
799         ies->firmwarever = -1;
800         ies->calling_ton = -1;
801         ies->calling_tns = -1;
802         ies->calling_pres = -1;
803         ies->samprate = IAX_RATE_8KHZ;
804         while(datalen >= 2) {
805                 ie = data[0];
806                 len = data[1];
807                 if (len > datalen - 2) {
808                         errorf("Information element length exceeds message size\n");
809                         return -1;
810                 }
811                 switch(ie) {
812                 case IAX_IE_CALLED_NUMBER:
813                         ies->called_number = (char *)data + 2;
814                         break;
815                 case IAX_IE_CALLING_NUMBER:
816                         ies->calling_number = (char *)data + 2;
817                         break;
818                 case IAX_IE_CALLING_ANI:
819                         ies->calling_ani = (char *)data + 2;
820                         break;
821                 case IAX_IE_CALLING_NAME:
822                         ies->calling_name = (char *)data + 2;
823                         break;
824                 case IAX_IE_CALLED_CONTEXT:
825                         ies->called_context = (char *)data + 2;
826                         break;
827                 case IAX_IE_USERNAME:
828                         ies->username = (char *)data + 2;
829                         break;
830                 case IAX_IE_PASSWORD:
831                         ies->password = (char *)data + 2;
832                         break;
833                 case IAX_IE_CODEC_PREFS:
834                         ies->codec_prefs = (char *)data + 2;
835                         break;
836                 case IAX_IE_CAPABILITY:
837                         if (len != (int)sizeof(unsigned int)) {
838                                 snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
839                                 errorf(tmp);
840                         } else if (ies->capability == 0) { /* Don't overwrite capability2, if specified */
841                                 ies->capability = ntohl(get_unaligned_uint32(data + 2));
842                         }
843                         break;
844                 case IAX_IE_CAPABILITY2:
845                         {
846                                 int version = data[2];
847                                 if (version == 0) {
848                                         if (len != (int)sizeof(char) + sizeof(iax2_format)) {
849                                                 snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int) (sizeof(iax2_format) + sizeof(char)), len);
850                                                 errorf(tmp);
851                                         } else {
852                                                 ies->capability = (iax2_format) ntohll(get_unaligned_uint64(data + 3));
853                                         }
854                                 } /* else unknown version */
855                         }
856                         break;
857                 case IAX_IE_FORMAT:
858                         if (len != (int)sizeof(unsigned int)) {
859                                 snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
860                                 errorf(tmp);
861                         } else if (ies->format == 0) { /* Don't overwrite format2, if specified */
862                                 ies->format = ntohl(get_unaligned_uint32(data + 2));
863                         }
864                         break;
865                 case IAX_IE_FORMAT2:
866                         {
867                                 int version = data[2];
868                                 if (version == 0) {
869                                         if (len != (int)sizeof(char) + sizeof(iax2_format)) {
870                                                 snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int) (sizeof(iax2_format) + sizeof(char)), len);
871                                                 errorf(tmp);
872                                         } else {
873                                                 ies->format = (iax2_format) ntohll(get_unaligned_uint64(data + 3));
874                                         }
875                                 } /* else unknown version */
876                         }
877                         break;
878                 case IAX_IE_LANGUAGE:
879                         ies->language = (char *)data + 2;
880                         break;
881                 case IAX_IE_VERSION:
882                         if (len != (int)sizeof(unsigned short)) {
883                                 snprintf(tmp, (int)sizeof(tmp),  "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
884                                 errorf(tmp);
885                         } else
886                                 ies->version = ntohs(get_unaligned_uint16(data + 2));
887                         break;
888                 case IAX_IE_ADSICPE:
889                         if (len != (int)sizeof(unsigned short)) {
890                                 snprintf(tmp, (int)sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
891                                 errorf(tmp);
892                         } else
893                                 ies->adsicpe = ntohs(get_unaligned_uint16(data + 2));
894                         break;
895                 case IAX_IE_SAMPLINGRATE:
896                         if (len != (int)sizeof(unsigned short)) {
897                                 snprintf(tmp, (int)sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
898                                 errorf(tmp);
899                         } else
900                                 ies->samprate = ntohs(get_unaligned_uint16(data + 2));
901                         break;
902                 case IAX_IE_DNID:
903                         ies->dnid = (char *)data + 2;
904                         break;
905                 case IAX_IE_RDNIS:
906                         ies->rdnis = (char *)data + 2;
907                         break;
908                 case IAX_IE_AUTHMETHODS:
909                         if (len != (int)sizeof(unsigned short))  {
910                                 snprintf(tmp, (int)sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
911                                 errorf(tmp);
912                         } else
913                                 ies->authmethods = ntohs(get_unaligned_uint16(data + 2));
914                         break;
915                 case IAX_IE_ENCRYPTION:
916                         if (len != (int)sizeof(unsigned short))  {
917                                 snprintf(tmp, (int)sizeof(tmp), "Expecting encryption to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
918                                 errorf(tmp);
919                         } else
920                                 ies->encmethods = ntohs(get_unaligned_uint16(data + 2));
921                         break;
922                 case IAX_IE_CHALLENGE:
923                         ies->challenge = (char *)data + 2;
924                         break;
925                 case IAX_IE_MD5_RESULT:
926                         ies->md5_result = (char *)data + 2;
927                         break;
928                 case IAX_IE_RSA_RESULT:
929                         ies->rsa_result = (char *)data + 2;
930                         break;
931                 case IAX_IE_APPARENT_ADDR:
932                         memcpy(&ies->apparent_addr , (struct ast_sockaddr *) (data + 2), len);
933                         ies->apparent_addr.len = len;
934                         break;
935                 case IAX_IE_REFRESH:
936                         if (len != (int)sizeof(unsigned short)) {
937                                 snprintf(tmp, (int)sizeof(tmp),  "Expecting refresh to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
938                                 errorf(tmp);
939                         } else
940                                 ies->refresh = ntohs(get_unaligned_uint16(data + 2));
941                         break;
942                 case IAX_IE_DPSTATUS:
943                         if (len != (int)sizeof(unsigned short)) {
944                                 snprintf(tmp, (int)sizeof(tmp),  "Expecting dpstatus to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
945                                 errorf(tmp);
946                         } else
947                                 ies->dpstatus = ntohs(get_unaligned_uint16(data + 2));
948                         break;
949                 case IAX_IE_CALLNO:
950                         if (len != (int)sizeof(unsigned short)) {
951                                 snprintf(tmp, (int)sizeof(tmp),  "Expecting callno to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
952                                 errorf(tmp);
953                         } else
954                                 ies->callno = ntohs(get_unaligned_uint16(data + 2));
955                         break;
956                 case IAX_IE_CAUSE:
957                         ies->cause = (char *)data + 2;
958                         break;
959                 case IAX_IE_CAUSECODE:
960                         if (len != 1) {
961                                 snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
962                                 errorf(tmp);
963                         } else {
964                                 ies->causecode = data[2];
965                         }
966                         break;
967                 case IAX_IE_IAX_UNKNOWN:
968                         if (len == 1)
969                                 ies->iax_unknown = data[2];
970                         else {
971                                 snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
972                                 errorf(tmp);
973                         }
974                         break;
975                 case IAX_IE_MSGCOUNT:
976                         if (len != (int)sizeof(unsigned short)) {
977                                 snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
978                                 errorf(tmp);
979                         } else
980                                 ies->msgcount = ntohs(get_unaligned_uint16(data + 2));  
981                         break;
982                 case IAX_IE_AUTOANSWER:
983                         ies->autoanswer = 1;
984                         break;
985                 case IAX_IE_MUSICONHOLD:
986                         ies->musiconhold = 1;
987                         break;
988                 case IAX_IE_TRANSFERID:
989                         if (len != (int)sizeof(unsigned int)) {
990                                 snprintf(tmp, (int)sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
991                                 errorf(tmp);
992                         } else
993                                 ies->transferid = ntohl(get_unaligned_uint32(data + 2));
994                         break;
995                 case IAX_IE_DATETIME:
996                         if (len != (int)sizeof(unsigned int)) {
997                                 snprintf(tmp, (int)sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
998                                 errorf(tmp);
999                         } else
1000                                 ies->datetime = ntohl(get_unaligned_uint32(data + 2));
1001                         break;
1002                 case IAX_IE_FIRMWAREVER:
1003                         if (len != (int)sizeof(unsigned short)) {
1004                                 snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1005                                 errorf(tmp);
1006                         } else
1007                                 ies->firmwarever = ntohs(get_unaligned_uint16(data + 2));       
1008                         break;
1009                 case IAX_IE_DEVICETYPE:
1010                         ies->devicetype = (char *)data + 2;
1011                         break;
1012                 case IAX_IE_SERVICEIDENT:
1013                         ies->serviceident = (char *)data + 2;
1014                         break;
1015                 case IAX_IE_FWBLOCKDESC:
1016                         if (len != (int)sizeof(unsigned int)) {
1017                                 snprintf(tmp, (int)sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1018                                 errorf(tmp);
1019                         } else
1020                                 ies->fwdesc = ntohl(get_unaligned_uint32(data + 2));
1021                         break;
1022                 case IAX_IE_FWBLOCKDATA:
1023                         ies->fwdata = data + 2;
1024                         ies->fwdatalen = len;
1025                         break;
1026                 case IAX_IE_ENCKEY:
1027                         ies->enckey = data + 2;
1028                         ies->enckeylen = len;
1029                         break;
1030                 case IAX_IE_PROVVER:
1031                         if (len != (int)sizeof(unsigned int)) {
1032                                 snprintf(tmp, (int)sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1033                                 errorf(tmp);
1034                         } else {
1035                                 ies->provverpres = 1;
1036                                 ies->provver = ntohl(get_unaligned_uint32(data + 2));
1037                         }
1038                         break;
1039                 case IAX_IE_CALLINGPRES:
1040                         if (len == 1)
1041                                 ies->calling_pres = data[2];
1042                         else {
1043                                 snprintf(tmp, (int)sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len);
1044                                 errorf(tmp);
1045                         }
1046                         break;
1047                 case IAX_IE_CALLINGTON:
1048                         if (len == 1)
1049                                 ies->calling_ton = data[2];
1050                         else {
1051                                 snprintf(tmp, (int)sizeof(tmp), "Expected single byte callington, but was %d long\n", len);
1052                                 errorf(tmp);
1053                         }
1054                         break;
1055                 case IAX_IE_CALLINGTNS:
1056                         if (len != (int)sizeof(unsigned short)) {
1057                                 snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1058                                 errorf(tmp);
1059                         } else
1060                                 ies->calling_tns = ntohs(get_unaligned_uint16(data + 2));       
1061                         break;
1062                case IAX_IE_RR_JITTER:
1063                        if (len != (int)sizeof(unsigned int)) {
1064                                snprintf(tmp, (int)sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1065                                errorf(tmp);
1066                        } else {
1067                                ies->rr_jitter = ntohl(get_unaligned_uint32(data + 2));
1068                        }
1069                        break;
1070                case IAX_IE_RR_LOSS:
1071                        if (len != (int)sizeof(unsigned int)) {
1072                                snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1073                                errorf(tmp);
1074                        } else {
1075                                ies->rr_loss = ntohl(get_unaligned_uint32(data + 2));
1076                        }
1077                        break;
1078                case IAX_IE_RR_PKTS:
1079                        if (len != (int)sizeof(unsigned int)) {
1080                                snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1081                                errorf(tmp);
1082                        } else {
1083                                ies->rr_pkts = ntohl(get_unaligned_uint32(data + 2));
1084                        }
1085                        break;
1086                case IAX_IE_RR_DELAY:
1087                        if (len != (int)sizeof(unsigned short)) {
1088                                snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1089                         errorf(tmp);
1090                        } else {
1091                                ies->rr_delay = ntohs(get_unaligned_uint16(data + 2));
1092                        }
1093                        break;
1094                 case IAX_IE_RR_DROPPED:
1095                         if (len != (int)sizeof(unsigned int)) {
1096                                 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1097                                 errorf(tmp);
1098                         } else {
1099                                 ies->rr_dropped = ntohl(get_unaligned_uint32(data + 2));
1100                         }
1101                         break;
1102                 case IAX_IE_RR_OOO:
1103                         if (len != (int)sizeof(unsigned int)) {
1104                                 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1105                                 errorf(tmp);
1106                         } else {
1107                                 ies->rr_ooo = ntohl(get_unaligned_uint32(data + 2));
1108                         }
1109                         break;
1110                 case IAX_IE_VARIABLE:
1111                         ast_copy_string(tmp, (char *)data + 2, len + 1);
1112                         tmp2 = strchr(tmp, '=');
1113                         if (tmp2)
1114                                 *tmp2++ = '\0';
1115                         else
1116                                 tmp2 = "";
1117                         {
1118                                 struct ast_str *str = ast_str_create(16);
1119                                 /* Existing variable or new variable? */
1120                                 for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) {
1121                                         if (strcmp(tmp, var2->name) == 0) {
1122                                                 ast_str_set(&str, 0, "%s%s", var2->value, tmp2);
1123                                                 var = ast_variable_new(tmp, ast_str_buffer(str), var2->file);
1124                                                 var->next = var2->next;
1125                                                 if (prev) {
1126                                                         prev->next = var;
1127                                                 } else {
1128                                                         ies->vars = var;
1129                                                 }
1130                                                 snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
1131                                                 outputf(tmp);
1132                                                 ast_free(var2);
1133                                                 break;
1134                                         }
1135                                 }
1136                                 ast_free(str);
1137                         }
1138
1139                         if (!var2) {
1140                                 var = ast_variable_new(tmp, tmp2, "");
1141                                 snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
1142                                 outputf(tmp);
1143                                 var->next = ies->vars;
1144                                 ies->vars = var;
1145                         }
1146                         break;
1147                 case IAX_IE_OSPTOKEN:
1148                         if ((count = data[2]) < IAX_MAX_OSPBLOCK_NUM) {
1149                                 ies->osptokenblock[count] = (char *)data + 2 + 1;
1150                                 ies->ospblocklength[count] = len - 1;
1151                         } else {
1152                                 snprintf(tmp, (int)sizeof(tmp), "Expected OSP token block index to be 0~%d but was %d\n", IAX_MAX_OSPBLOCK_NUM - 1, count);
1153                                 errorf(tmp);
1154                         }
1155                         break;
1156                 case IAX_IE_CALLTOKEN:
1157                         if (len) {
1158                                 ies->calltokendata = (unsigned char *) data + 2;
1159                         }
1160                         ies->calltoken = 1;
1161                         break;
1162                 default:
1163                         snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
1164                         outputf(tmp);
1165                 }
1166                 /* Overwrite information element with 0, to null terminate previous portion */
1167                 data[0] = 0;
1168                 datalen -= (len + 2);
1169                 data += (len + 2);
1170         }
1171         /* Null-terminate last field */
1172         *data = '\0';
1173         if (datalen) {
1174                 errorf("Invalid information element contents, strange boundary\n");
1175                 return -1;
1176         }
1177         return 0;
1178 }
1179
1180 void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
1181 {
1182         fr->af.frametype = f->frametype;
1183         ast_format_copy(&fr->af.subclass.format, &f->subclass.format);
1184         fr->af.mallocd = 0;                             /* Our frame is static relative to the container */
1185         fr->af.datalen = f->datalen;
1186         fr->af.samples = f->samples;
1187         fr->af.offset = AST_FRIENDLY_OFFSET;
1188         fr->af.src = f->src;
1189         fr->af.delivery.tv_sec = 0;
1190         fr->af.delivery.tv_usec = 0;
1191         fr->af.data.ptr = fr->afdata;
1192         fr->af.len = f->len;
1193         if (fr->af.datalen) {
1194                 size_t copy_len = fr->af.datalen;
1195                 if (copy_len > fr->afdatalen) {
1196                         ast_log(LOG_ERROR, "Losing frame data because destination buffer size '%d' bytes not big enough for '%d' bytes in the frame\n",
1197                                 (int) fr->afdatalen, (int) fr->af.datalen);
1198                         copy_len = fr->afdatalen;
1199                 }
1200 #if __BYTE_ORDER == __LITTLE_ENDIAN
1201                 /* We need to byte-swap slinear samples from network byte order */
1202                 if ((fr->af.frametype == AST_FRAME_VOICE) && (fr->af.subclass.format.id == AST_FORMAT_SLINEAR)) {
1203                         /* 2 bytes / sample for SLINEAR */
1204                         ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2);
1205                 } else
1206 #endif
1207                         memcpy(fr->af.data.ptr, f->data.ptr, copy_len);
1208         }
1209 }
1210
1211 struct iax_frame *iax_frame_new(int direction, int datalen, unsigned int cacheable)
1212 {
1213         struct iax_frame *fr;
1214
1215 #if !defined(LOW_MEMORY)
1216         if (cacheable) {
1217                 struct iax_frames *iax_frames;
1218                 struct iax_frame *smallest;
1219
1220                 /* Attempt to get a frame from this thread's cache */
1221                 if ((iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
1222                         smallest = AST_LIST_FIRST(&iax_frames->list);
1223                         AST_LIST_TRAVERSE_SAFE_BEGIN(&iax_frames->list, fr, list) {
1224                                 if (fr->afdatalen >= datalen) {
1225                                         size_t afdatalen = fr->afdatalen;
1226                                         AST_LIST_REMOVE_CURRENT(list);
1227                                         iax_frames->size--;
1228                                         memset(fr, 0, sizeof(*fr));
1229                                         fr->afdatalen = afdatalen;
1230                                         break;
1231                                 } else if (smallest->afdatalen > fr->afdatalen) {
1232                                         smallest = fr;
1233                                 }
1234                         }
1235                         AST_LIST_TRAVERSE_SAFE_END;
1236                         if (!fr) {
1237                                 if (iax_frames->size >= FRAME_CACHE_MAX_SIZE && smallest) {
1238                                         /* Make useless cache into something more useful */
1239                                         AST_LIST_REMOVE(&iax_frames->list, smallest, list);
1240                                         iax_frames->size--;
1241                                         ast_free(smallest);
1242                                 }
1243                                 if (!(fr = ast_calloc_cache(1, sizeof(*fr) + datalen))) {
1244                                         return NULL;
1245                                 }
1246                                 fr->afdatalen = datalen;
1247                         }
1248                 } else {
1249                         if (!(fr = ast_calloc_cache(1, sizeof(*fr) + datalen))) {
1250                                 return NULL;
1251                         }
1252                         fr->afdatalen = datalen;
1253                 }
1254                 fr->cacheable = 1;
1255         } else
1256 #endif
1257         {
1258                 if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
1259                         return NULL;
1260                 }
1261                 fr->afdatalen = datalen;
1262         }
1263
1264
1265         fr->direction = direction;
1266         fr->retrans = -1;
1267         
1268         if (fr->direction == DIRECTION_INGRESS)
1269                 ast_atomic_fetchadd_int(&iframes, 1);
1270         else
1271                 ast_atomic_fetchadd_int(&oframes, 1);
1272         
1273         ast_atomic_fetchadd_int(&frames, 1);
1274
1275         return fr;
1276 }
1277
1278 void iax_frame_free(struct iax_frame *fr)
1279 {
1280 #if !defined(LOW_MEMORY)
1281         struct iax_frames *iax_frames = NULL;
1282 #endif
1283
1284         /* Note: does not remove from scheduler! */
1285         if (fr->direction == DIRECTION_INGRESS)
1286                 ast_atomic_fetchadd_int(&iframes, -1);
1287         else if (fr->direction == DIRECTION_OUTGRESS)
1288                 ast_atomic_fetchadd_int(&oframes, -1);
1289         else {
1290                 errorf("Attempt to double free frame detected\n");
1291                 return;
1292         }
1293         ast_atomic_fetchadd_int(&frames, -1);
1294
1295 #if !defined(LOW_MEMORY)
1296         if (!fr->cacheable || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
1297                 ast_free(fr);
1298                 return;
1299         }
1300
1301         if (iax_frames->size < FRAME_CACHE_MAX_SIZE) {
1302                 fr->direction = 0;
1303                 /* Pseudo-sort: keep smaller frames at the top of the list. This should
1304                  * increase the chance that we pick the smallest applicable frame for use. */
1305                 if (AST_LIST_FIRST(&iax_frames->list) && AST_LIST_FIRST(&iax_frames->list)->afdatalen < fr->afdatalen) {
1306                         AST_LIST_INSERT_TAIL(&iax_frames->list, fr, list);
1307                 } else {
1308                         AST_LIST_INSERT_HEAD(&iax_frames->list, fr, list);
1309                 }
1310                 iax_frames->size++;
1311                 return;
1312         }
1313 #endif
1314         ast_free(fr);
1315 }
1316
1317 #if !defined(LOW_MEMORY)
1318 static void frame_cache_cleanup(void *data)
1319 {
1320         struct iax_frames *framelist = data;
1321         struct iax_frame *current;
1322
1323         while ((current = AST_LIST_REMOVE_HEAD(&framelist->list, list)))
1324                 ast_free(current);
1325
1326         ast_free(framelist);
1327 }
1328 #endif
1329
1330 int iax_get_frames(void) { return frames; }
1331 int iax_get_iframes(void) { return iframes; }
1332 int iax_get_oframes(void) { return oframes; }