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