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