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