Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
parser.c
Go to the documentation of this file.
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"
42#include "asterisk/netsock2.h"
45
46#include "include/iax2.h"
47#include "include/parser.h"
48#include "include/provision.h"
49#include "include/codec_pref.h"
50
51static int frames = 0;
52static int iframes = 0;
53static 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)
60static void frame_cache_cleanup(void *data);
61
62/*! \brief A per-thread cache of iax_frame structures */
64
65/*! \brief This is just so iax_frames, a list head struct for holding a list of
66 * iax_frame structures, is defined. */
68
69struct iax_frames {
71 size_t size;
72};
73
74#define FRAME_CACHE_MAX_SIZE 20
75#endif
76
77static void internaloutput(const char *str)
78{
79 fputs(str, stdout);
80}
81
82static void internalerror(const char *str)
83{
84 fprintf(stderr, "WARNING: %s", str);
85}
86
87static void (*outputf)(const char *str) = internaloutput;
88static void (*errorf)(const char *str) = internalerror;
89
90static 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",
109}
110
111static 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
121static 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
130static 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
149static 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
157static 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
165static 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
173static 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
189static 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
211static 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)),
217 else
218 ast_copy_string(output, "Invalid INT", maxlen);
219}
220
221static 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
248static 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))) {
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
263static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len);
264static void dump_prov(char *output, int maxlen, void *value, int len)
265{
266 dump_prov_ies(output, maxlen, value, len);
267}
268
269struct iax2_ie {
270 int ie;
271 char *name;
272 void (*dump)(char *output, int maxlen, void *value, int len);
273};
274static struct iax2_ie infoelts[] = {
275 { IAX_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
276 { IAX_IE_CALLING_NUMBER, "CALLING NUMBER", 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 PROVISIONING" },
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, "PROVISIONING 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_CALLINGANI2, "CALLING ANI2", dump_int },
317 { IAX_IE_SAMPLINGRATE, "SAMPLINGRATE", dump_samprate },
318 { IAX_IE_CAUSECODE, "CAUSE CODE", dump_byte },
319 { IAX_IE_ENCRYPTION, "ENCRYPTION", dump_short },
320 { IAX_IE_ENCKEY, "ENCRYPTION KEY" },
321 { IAX_IE_CODEC_PREFS, "CODEC_PREFS", dump_prefs },
322 { IAX_IE_RR_JITTER, "RR_JITTER", dump_int },
323 { IAX_IE_RR_LOSS, "RR_LOSS", dump_int },
324 { IAX_IE_RR_PKTS, "RR_PKTS", dump_int },
325 { IAX_IE_RR_DELAY, "RR_DELAY", dump_short },
326 { IAX_IE_RR_DROPPED, "RR_DROPPED", dump_int },
327 { IAX_IE_RR_OOO, "RR_OUTOFORDER", dump_int },
328 { IAX_IE_VARIABLE, "VARIABLE", dump_string },
329 { IAX_IE_OSPTOKEN, "OSPTOKEN" },
330 { IAX_IE_CALLTOKEN, "CALLTOKEN" },
331};
332
333static const struct iax2_ie prov_ies[] = {
334 { PROV_IE_USEDHCP, "USEDHCP" },
335 { PROV_IE_IPADDR, "IPADDR", dump_ipaddr },
336 { PROV_IE_SUBNET, "SUBNET", dump_ipaddr },
337 { PROV_IE_GATEWAY, "GATEWAY", dump_ipaddr },
338 { PROV_IE_PORTNO, "BINDPORT", dump_short },
339 { PROV_IE_USER, "USERNAME", dump_string },
340 { PROV_IE_PASS, "PASSWORD", dump_string },
341 { PROV_IE_LANG, "LANGUAGE", dump_string },
342 { PROV_IE_TOS, "TYPEOFSERVICE", dump_byte },
343 { PROV_IE_FLAGS, "FLAGS", dump_prov_flags },
344 { PROV_IE_FORMAT, "FORMAT", dump_int },
345 { PROV_IE_AESKEY, "AESKEY" },
346 { PROV_IE_SERVERIP, "SERVERIP", dump_ipaddr },
347 { PROV_IE_SERVERPORT, "SERVERPORT", dump_short },
348 { PROV_IE_NEWAESKEY, "NEWAESKEY" },
349 { PROV_IE_PROVVER, "PROV VERSION", dump_int },
350 { PROV_IE_ALTSERVER, "ALTSERVERIP", dump_ipaddr },
351};
352
353const char *iax_ie2str(int ie)
354{
355 int x;
356 for (x = 0; x < ARRAY_LEN(infoelts); x++) {
357 if (infoelts[x].ie == ie)
358 return infoelts[x].name;
359 }
360 return "Unknown IE";
361}
362
363
364static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len)
365{
366 int ielen;
367 int ie;
368 int x;
369 int found;
370 char interp[80];
371 char tmp[256];
372 if (len < 2)
373 return;
374 strcpy(output, "\n");
375 maxlen -= strlen(output); output += strlen(output);
376 while(len > 2) {
377 ie = iedata[0];
378 ielen = iedata[1];
379 if (ielen + 2> len) {
380 snprintf(tmp, (int)sizeof(tmp), "Total Prov IE length of %d bytes exceeds remaining prov frame length of %d bytes\n", ielen + 2, len);
381 ast_copy_string(output, tmp, maxlen);
382 maxlen -= strlen(output);
383 output += strlen(output);
384 return;
385 }
386 found = 0;
387 for (x=0;x<(int)sizeof(prov_ies) / (int)sizeof(prov_ies[0]); x++) {
388 if (prov_ies[x].ie == ie) {
389 if (prov_ies[x].dump) {
390 prov_ies[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
391 snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", prov_ies[x].name, interp);
392 ast_copy_string(output, tmp, maxlen);
393 maxlen -= strlen(output); output += strlen(output);
394 } else {
395 if (ielen)
396 snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
397 else
398 strcpy(interp, "Present");
399 snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", prov_ies[x].name, interp);
400 ast_copy_string(output, tmp, maxlen);
401 maxlen -= strlen(output); output += strlen(output);
402 }
403 found++;
404 }
405 }
406 if (!found) {
407 snprintf(tmp, (int)sizeof(tmp), " Unknown Prov IE %03d : Present\n", ie);
408 ast_copy_string(output, tmp, maxlen);
409 maxlen -= strlen(output); output += strlen(output);
410 }
411 iedata += (2 + ielen);
412 len -= (2 + ielen);
413 }
414}
415
416static void dump_ies(unsigned char *iedata, int len)
417{
418 int ielen;
419 int ie;
420 int x;
421 int found;
422 char interp[1024];
423 char tmp[1046];
424
425 if (len < 2)
426 return;
427 while(len >= 2) {
428 ie = iedata[0];
429 ielen = iedata[1];
430 if (ielen + 2> len) {
431 snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
432 outputf(tmp);
433 return;
434 }
435 found = 0;
436 for (x = 0; x < ARRAY_LEN(infoelts); x++) {
437 if (infoelts[x].ie == ie) {
438 if (infoelts[x].dump) {
439 infoelts[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
440 snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", infoelts[x].name, interp);
441 outputf(tmp);
442 } else {
443 if (ielen)
444 snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
445 else
446 strcpy(interp, "Present");
447 snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", infoelts[x].name, interp);
448 outputf(tmp);
449 }
450 found++;
451 }
452 }
453 if (!found) {
454 snprintf(tmp, (int)sizeof(tmp), " Unknown IE %03d : Present\n", ie);
455 outputf(tmp);
456 }
457 iedata += (2 + ielen);
458 len -= (2 + ielen);
459 }
460 outputf("\n");
461}
462
463void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t len)
464{
465 const char *cmd = "Unknown";
466
467 /* if an error occurs here during compile, that means a new iax frame subclass
468 * has been added to the iax_frame_subclass enum. Add the new subclass to the
469 * switch case and make sure to update it with a new string representation. */
470 switch (subclass) {
471 case IAX_COMMAND_NEW:
472 cmd = "NEW ";
473 break;
474 case IAX_COMMAND_PING:
475 cmd = "PING ";
476 break;
477 case IAX_COMMAND_PONG:
478 cmd = "PONG ";
479 break;
480 case IAX_COMMAND_ACK:
481 cmd = "ACK ";
482 break;
484 cmd = "HANGUP ";
485 break;
487 cmd = "REJECT ";
488 break;
490 cmd = "ACCEPT ";
491 break;
493 cmd = "AUTHREQ";
494 break;
496 cmd = "AUTHREP";
497 break;
499 cmd = "INVAL ";
500 break;
502 cmd = "LAGRQ ";
503 break;
505 cmd = "LAGRP ";
506 break;
508 cmd = "REGREQ ";
509 break;
511 cmd = "REGAUTH";
512 break;
514 cmd = "REGACK ";
515 break;
517 cmd = "REGREJ ";
518 break;
520 cmd = "REGREL ";
521 break;
522 case IAX_COMMAND_VNAK:
523 cmd = "VNAK ";
524 break;
526 cmd = "DPREQ ";
527 break;
529 cmd = "DPREP ";
530 break;
531 case IAX_COMMAND_DIAL:
532 cmd = "DIAL ";
533 break;
535 cmd = "TXREQ ";
536 break;
538 cmd = "TXCNT ";
539 break;
541 cmd = "TXACC ";
542 break;
544 cmd = "TXREADY";
545 break;
547 cmd = "TXREL ";
548 break;
550 cmd = "TXREJ ";
551 break;
553 cmd = "QUELCH ";
554 break;
556 cmd = "UNQUELCH";
557 break;
558 case IAX_COMMAND_POKE:
559 cmd = "POKE ";
560 break;
561 case IAX_COMMAND_PAGE:
562 cmd = "PAGE ";
563 break;
564 case IAX_COMMAND_MWI:
565 cmd = "MWI ";
566 break;
568 cmd = "UNSPRTD";
569 break;
571 cmd = "TRANSFR";
572 break;
574 cmd = "PROVISN";
575 break;
577 cmd = "FWDWNLD";
578 break;
580 cmd = "FWDATA ";
581 break;
583 cmd = "TXMEDIA";
584 break;
586 cmd = "RTKEY ";
587 break;
589 cmd = "CTOKEN ";
590 break;
591 }
592 ast_copy_string(str, cmd, len);
593}
594
595void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct ast_sockaddr *addr, int datalen)
596{
597 const char *framelist[] = {
598 "(0?)",
599 "DTMF_E ",
600 "VOICE ",
601 "VIDEO ",
602 "CONTROL",
603 "NULL ",
604 "IAX ",
605 "TEXT ",
606 "IMAGE ",
607 "HTML ",
608 "CNG ",
609 "MODEM ",
610 "DTMF_B ",
611 };
612 const char *cmds[] = {
613 "(0?)",
614 "HANGUP ",
615 "RING ",
616 "RINGING",
617 "ANSWER ",
618 "BUSY ",
619 "TKOFFHK",
620 "OFFHOOK",
621 "CONGSTN",
622 "FLASH ",
623 "WINK ",
624 "OPTION ",
625 "RDKEY ",
626 "RDUNKEY",
627 "PROGRES",
628 "PROCDNG",
629 "HOLD ",
630 "UNHOLD ",
631 "VIDUPDT",
632 "T38 ",
633 "SRCUPDT",
634 "TXFER ",
635 "CNLINE ",
636 "REDIR ",
637 "T38PARM",
638 "CC ERR!",/* This must never go across an IAX link. */
639 "SRCCHG ",
640 "READACT",
641 "AOC ",
642 "ENDOFQ ",
643 "INCOMPL",
644 "MCID ",
645 "UPDRTPP",
646 "PCAUSEC",
647 };
648 struct ast_iax2_full_hdr *fh;
649 char retries[20];
650 char class2[20];
651 char subclass2[20];
652 const char *class;
653 const char *subclass;
654 char *dir;
655 char tmp[512];
656
657 switch(rx) {
658 case 0:
659 dir = "Tx";
660 break;
661 case 2:
662 dir = "TE";
663 break;
664 case 3:
665 dir = "RD";
666 break;
667 default:
668 dir = "Rx";
669 break;
670 }
671 if (f) {
672 fh = f->data;
673 snprintf(retries, sizeof(retries), "%03d", f->retries);
674 } else {
675 fh = fhi;
676 if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS)
677 strcpy(retries, "Yes");
678 else
679 strcpy(retries, " No");
680 }
681 if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) {
682 /* Don't mess with mini-frames */
683 return;
684 }
685 if (fh->type >= ARRAY_LEN(framelist)) {
686 snprintf(class2, sizeof(class2), "(%d?)", fh->type);
687 class = class2;
688 } else {
689 class = framelist[(int)fh->type];
690 }
691 if (fh->type == AST_FRAME_DTMF_BEGIN || fh->type == AST_FRAME_DTMF_END) {
692 sprintf(subclass2, "%c", fh->csub);
693 subclass = subclass2;
694 } else if (fh->type == AST_FRAME_IAX) {
695 iax_frame_subclass2str((int)fh->csub, subclass2, sizeof(subclass2));
696 subclass = subclass2;
697 } else if (fh->type == AST_FRAME_CONTROL) {
698 if (fh->csub >= ARRAY_LEN(cmds)) {
699 snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
700 subclass = subclass2;
701 } else {
702 subclass = cmds[(int)fh->csub];
703 }
704 } else {
705 snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);
706 subclass = subclass2;
707 }
708
709 snprintf(tmp, sizeof(tmp),
710 "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
711 dir,
712 retries, fh->oseqno, fh->iseqno, class, subclass);
713 outputf(tmp);
714 snprintf(tmp, sizeof(tmp), " Timestamp: %05lums SCall: %5.5d DCall: %5.5d %s\n",
715 (unsigned long)ntohl(fh->ts),
716 ntohs(fh->scallno) & ~IAX_FLAG_FULL,
717 ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
719
720 outputf(tmp);
721 if (fh->type == AST_FRAME_IAX)
722 dump_ies(fh->iedata, datalen);
723
724}
725
726int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
727{
728 char tmp[256];
729 if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
730 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);
731 errorf(tmp);
732 return -1;
733 }
734 ied->buf[ied->pos++] = ie;
735 ied->buf[ied->pos++] = datalen;
736 memcpy(ied->buf + ied->pos, data, datalen);
737 ied->pos += datalen;
738 return 0;
739}
740
741int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct ast_sockaddr *addr)
742{
743 return iax_ie_append_raw(ied, ie, addr, addr->len);
744}
745
746int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value)
747{
748 struct _local {
749 unsigned char version;
750 uint64_t value;
751 } __attribute__((packed)) newval = { version, };
752 put_unaligned_uint64(&newval.value, htonll(value));
753 return iax_ie_append_raw(ied, ie, &newval, (int) sizeof(newval));
754}
755
756int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value)
757{
758 unsigned int newval;
759 newval = htonl(value);
760 return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
761}
762
763int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value)
764{
765 unsigned short newval;
766 newval = htons(value);
767 return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
768}
769
770int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const char *str)
771{
772 return iax_ie_append_raw(ied, ie, str, strlen(str));
773}
774
775int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
776{
777 return iax_ie_append_raw(ied, ie, &dat, 1);
778}
779
780int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
781{
782 return iax_ie_append_raw(ied, ie, NULL, 0);
783}
784
785void iax_set_output(void (*func)(const char *))
786{
787 outputf = func;
788}
789
790void iax_set_error(void (*func)(const char *))
791{
792 errorf = func;
793}
794
795int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
796{
797 /* Parse data into information elements */
798 int len;
799 int ie;
800 char tmp[256], *tmp2;
801 struct ast_variable *var, *var2, *prev;
802 unsigned int count;
803 memset(ies, 0, (int)sizeof(struct iax_ies));
804 ies->msgcount = -1;
805 ies->firmwarever = -1;
806 ies->calling_ton = -1;
807 ies->calling_tns = -1;
808 ies->calling_pres = -1;
809 ies->calling_ani2 = -1;
810 ies->samprate = IAX_RATE_8KHZ;
811 while(datalen >= 2) {
812 ie = data[0];
813 len = data[1];
814 if (len > datalen - 2) {
815 snprintf(tmp, sizeof(tmp), "Information element length %d exceeds message size %d\n", len, datalen - 2);
816 errorf(tmp);
817 return -1;
818 }
819 switch(ie) {
821 ies->called_number = (char *)data + 2;
822 break;
824 ies->calling_number = (char *)data + 2;
825 break;
827 ies->calling_ani = (char *)data + 2;
828 break;
830 ies->calling_name = (char *)data + 2;
831 break;
833 ies->called_context = (char *)data + 2;
834 break;
835 case IAX_IE_USERNAME:
836 ies->username = (char *)data + 2;
837 break;
838 case IAX_IE_PASSWORD:
839 ies->password = (char *)data + 2;
840 break;
842 ies->codec_prefs = (char *)data + 2;
843 break;
845 if (len != (int)sizeof(unsigned int)) {
846 snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
847 errorf(tmp);
848 } else if (ies->capability == 0) { /* Don't overwrite capability2, if specified */
849 ies->capability = ntohl(get_unaligned_uint32(data + 2));
850 }
851 break;
853 {
854 int version = data[2];
855 if (version == 0) {
856 if (len != (int)sizeof(char) + sizeof(iax2_format)) {
857 snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int) (sizeof(iax2_format) + sizeof(char)), len);
858 errorf(tmp);
859 } else {
861 }
862 } /* else unknown version */
863 }
864 break;
865 case IAX_IE_FORMAT:
866 if (len != (int)sizeof(unsigned int)) {
867 snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
868 errorf(tmp);
869 } else if (ies->format == 0) { /* Don't overwrite format2, if specified */
870 ies->format = ntohl(get_unaligned_uint32(data + 2));
871 }
872 break;
873 case IAX_IE_FORMAT2:
874 {
875 int version = data[2];
876 if (version == 0) {
877 if (len != (int)sizeof(char) + sizeof(iax2_format)) {
878 snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int) (sizeof(iax2_format) + sizeof(char)), len);
879 errorf(tmp);
880 } else {
881 ies->format = (iax2_format) ntohll(get_unaligned_uint64(data + 3));
882 }
883 } /* else unknown version */
884 }
885 break;
886 case IAX_IE_LANGUAGE:
887 ies->language = (char *)data + 2;
888 break;
889 case IAX_IE_VERSION:
890 if (len != (int)sizeof(unsigned short)) {
891 snprintf(tmp, (int)sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
892 errorf(tmp);
893 } else
894 ies->version = ntohs(get_unaligned_uint16(data + 2));
895 break;
896 case IAX_IE_ADSICPE:
897 if (len != (int)sizeof(unsigned short)) {
898 snprintf(tmp, (int)sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
899 errorf(tmp);
900 } else
901 ies->adsicpe = ntohs(get_unaligned_uint16(data + 2));
902 break;
904 if (len != (int)sizeof(unsigned short)) {
905 snprintf(tmp, (int)sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
906 errorf(tmp);
907 } else
908 ies->samprate = ntohs(get_unaligned_uint16(data + 2));
909 break;
910 case IAX_IE_DNID:
911 ies->dnid = (char *)data + 2;
912 break;
913 case IAX_IE_RDNIS:
914 ies->rdnis = (char *)data + 2;
915 break;
917 if (len != (int)sizeof(unsigned short)) {
918 snprintf(tmp, (int)sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
919 errorf(tmp);
920 } else
921 ies->authmethods = ntohs(get_unaligned_uint16(data + 2));
922 break;
924 if (len != (int)sizeof(unsigned short)) {
925 snprintf(tmp, (int)sizeof(tmp), "Expecting encryption to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
926 errorf(tmp);
927 } else
928 ies->encmethods = ntohs(get_unaligned_uint16(data + 2));
929 break;
930 case IAX_IE_CHALLENGE:
931 ies->challenge = (char *)data + 2;
932 break;
934 ies->md5_result = (char *)data + 2;
935 break;
937 ies->rsa_result = (char *)data + 2;
938 break;
940 memcpy(&ies->apparent_addr , (struct ast_sockaddr *) (data + 2), len);
941 ies->apparent_addr.len = len;
942 break;
943 case IAX_IE_REFRESH:
944 if (len != (int)sizeof(unsigned short)) {
945 snprintf(tmp, (int)sizeof(tmp), "Expecting refresh to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
946 errorf(tmp);
947 } else
948 ies->refresh = ntohs(get_unaligned_uint16(data + 2));
949 break;
950 case IAX_IE_DPSTATUS:
951 if (len != (int)sizeof(unsigned short)) {
952 snprintf(tmp, (int)sizeof(tmp), "Expecting dpstatus to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
953 errorf(tmp);
954 } else
955 ies->dpstatus = ntohs(get_unaligned_uint16(data + 2));
956 break;
957 case IAX_IE_CALLNO:
958 if (len != (int)sizeof(unsigned short)) {
959 snprintf(tmp, (int)sizeof(tmp), "Expecting callno to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
960 errorf(tmp);
961 } else
962 ies->callno = ntohs(get_unaligned_uint16(data + 2));
963 break;
964 case IAX_IE_CAUSE:
965 ies->cause = (char *)data + 2;
966 break;
967 case IAX_IE_CAUSECODE:
968 if (len != 1) {
969 snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
970 errorf(tmp);
971 } else {
972 ies->causecode = data[2];
973 }
974 break;
976 if (len == 1)
977 ies->iax_unknown = data[2];
978 else {
979 snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
980 errorf(tmp);
981 }
982 break;
983 case IAX_IE_MSGCOUNT:
984 if (len != (int)sizeof(unsigned short)) {
985 snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
986 errorf(tmp);
987 } else
988 ies->msgcount = ntohs(get_unaligned_uint16(data + 2));
989 break;
991 ies->autoanswer = 1;
992 break;
994 ies->musiconhold = 1;
995 break;
997 if (len != (int)sizeof(unsigned int)) {
998 snprintf(tmp, (int)sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
999 errorf(tmp);
1000 } else
1001 ies->transferid = ntohl(get_unaligned_uint32(data + 2));
1002 break;
1003 case IAX_IE_DATETIME:
1004 if (len != (int)sizeof(unsigned int)) {
1005 snprintf(tmp, (int)sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1006 errorf(tmp);
1007 } else
1008 ies->datetime = ntohl(get_unaligned_uint32(data + 2));
1009 break;
1010 case IAX_IE_FIRMWAREVER:
1011 if (len != (int)sizeof(unsigned short)) {
1012 snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1013 errorf(tmp);
1014 } else
1015 ies->firmwarever = ntohs(get_unaligned_uint16(data + 2));
1016 break;
1017 case IAX_IE_DEVICETYPE:
1018 ies->devicetype = (char *)data + 2;
1019 break;
1021 ies->serviceident = (char *)data + 2;
1022 break;
1023 case IAX_IE_FWBLOCKDESC:
1024 if (len != (int)sizeof(unsigned int)) {
1025 snprintf(tmp, (int)sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1026 errorf(tmp);
1027 } else
1028 ies->fwdesc = ntohl(get_unaligned_uint32(data + 2));
1029 break;
1030 case IAX_IE_FWBLOCKDATA:
1031 ies->fwdata = data + 2;
1032 ies->fwdatalen = len;
1033 break;
1034 case IAX_IE_ENCKEY:
1035 ies->enckey = data + 2;
1036 ies->enckeylen = len;
1037 break;
1038 case IAX_IE_PROVVER:
1039 if (len != (int)sizeof(unsigned int)) {
1040 snprintf(tmp, (int)sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1041 errorf(tmp);
1042 } else {
1043 ies->provverpres = 1;
1044 ies->provver = ntohl(get_unaligned_uint32(data + 2));
1045 }
1046 break;
1047 case IAX_IE_CALLINGPRES:
1048 if (len == 1)
1049 ies->calling_pres = data[2];
1050 else {
1051 snprintf(tmp, (int)sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len);
1052 errorf(tmp);
1053 }
1054 break;
1055 case IAX_IE_CALLINGTON:
1056 if (len == 1)
1057 ies->calling_ton = data[2];
1058 else {
1059 snprintf(tmp, (int)sizeof(tmp), "Expected single byte callington, but was %d long\n", len);
1060 errorf(tmp);
1061 }
1062 break;
1063 case IAX_IE_CALLINGANI2:
1064 if (len == (int)sizeof(unsigned int)) {
1065 ies->calling_ani2 = ntohl(get_unaligned_uint32(data + 2));
1066 } else {
1067 snprintf(tmp, sizeof(tmp), "Expected callingani2 to be %zu bytes but was %d\n", sizeof(unsigned int), len);
1068 errorf(tmp);
1069 }
1070 break;
1071 case IAX_IE_CALLINGTNS:
1072 if (len != (int)sizeof(unsigned short)) {
1073 snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1074 errorf(tmp);
1075 } else
1076 ies->calling_tns = ntohs(get_unaligned_uint16(data + 2));
1077 break;
1078 case IAX_IE_RR_JITTER:
1079 if (len != (int)sizeof(unsigned int)) {
1080 snprintf(tmp, (int)sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1081 errorf(tmp);
1082 } else {
1083 ies->rr_jitter = ntohl(get_unaligned_uint32(data + 2));
1084 }
1085 break;
1086 case IAX_IE_RR_LOSS:
1087 if (len != (int)sizeof(unsigned int)) {
1088 snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1089 errorf(tmp);
1090 } else {
1091 ies->rr_loss = ntohl(get_unaligned_uint32(data + 2));
1092 }
1093 break;
1094 case IAX_IE_RR_PKTS:
1095 if (len != (int)sizeof(unsigned int)) {
1096 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1097 errorf(tmp);
1098 } else {
1099 ies->rr_pkts = ntohl(get_unaligned_uint32(data + 2));
1100 }
1101 break;
1102 case IAX_IE_RR_DELAY:
1103 if (len != (int)sizeof(unsigned short)) {
1104 snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1105 errorf(tmp);
1106 } else {
1107 ies->rr_delay = ntohs(get_unaligned_uint16(data + 2));
1108 }
1109 break;
1110 case IAX_IE_RR_DROPPED:
1111 if (len != (int)sizeof(unsigned int)) {
1112 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1113 errorf(tmp);
1114 } else {
1115 ies->rr_dropped = ntohl(get_unaligned_uint32(data + 2));
1116 }
1117 break;
1118 case IAX_IE_RR_OOO:
1119 if (len != (int)sizeof(unsigned int)) {
1120 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1121 errorf(tmp);
1122 } else {
1123 ies->rr_ooo = ntohl(get_unaligned_uint32(data + 2));
1124 }
1125 break;
1126 case IAX_IE_VARIABLE:
1127 ast_copy_string(tmp, (char *)data + 2, len + 1);
1128 tmp2 = strchr(tmp, '=');
1129 if (tmp2)
1130 *tmp2++ = '\0';
1131 else
1132 tmp2 = "";
1133 {
1134 struct ast_str *str = ast_str_create(16);
1135 /* Existing variable or new variable? */
1136 for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) {
1137 if (strcmp(tmp, var2->name) == 0) {
1138 ast_str_set(&str, 0, "%s%s", var2->value, tmp2);
1139 var = ast_variable_new(tmp, ast_str_buffer(str), var2->file);
1140 var->next = var2->next;
1141 if (prev) {
1142 prev->next = var;
1143 } else {
1144 ies->vars = var;
1145 }
1146 snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
1147 outputf(tmp);
1148 ast_free(var2);
1149 break;
1150 }
1151 }
1152 ast_free(str);
1153 }
1154
1155 if (!var2) {
1156 var = ast_variable_new(tmp, tmp2, "");
1157 snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
1158 outputf(tmp);
1159 var->next = ies->vars;
1160 ies->vars = var;
1161 }
1162 break;
1163 case IAX_IE_OSPTOKEN:
1164 if ((count = data[2]) < IAX_MAX_OSPBLOCK_NUM) {
1165 ies->osptokenblock[count] = (char *)data + 2 + 1;
1166 ies->ospblocklength[count] = len - 1;
1167 } else {
1168 snprintf(tmp, (int)sizeof(tmp), "Expected OSP token block index to be 0~%d but was %u\n", IAX_MAX_OSPBLOCK_NUM - 1, count);
1169 errorf(tmp);
1170 }
1171 break;
1172 case IAX_IE_CALLTOKEN:
1173 if (len) {
1174 ies->calltokendata = (unsigned char *) data + 2;
1175 }
1176 ies->calltoken = 1;
1177 break;
1178 default:
1179 snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
1180 outputf(tmp);
1181 }
1182 /* Overwrite information element with 0, to null terminate previous portion */
1183 data[0] = 0;
1184 datalen -= (len + 2);
1185 data += (len + 2);
1186 }
1187 /* Null-terminate last field */
1188 *data = '\0';
1189 if (datalen) {
1190 errorf("Invalid information element contents, strange boundary\n");
1191 return -1;
1192 }
1193 return 0;
1194}
1195
1196void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
1197{
1198 fr->af.frametype = f->frametype;
1199 fr->af.subclass.format = f->subclass.format;
1201 fr->af.mallocd = 0; /* Our frame is static relative to the container */
1202 fr->af.datalen = f->datalen;
1203 fr->af.samples = f->samples;
1205 fr->af.src = f->src;
1206 fr->af.delivery.tv_sec = 0;
1207 fr->af.delivery.tv_usec = 0;
1208 fr->af.data.ptr = fr->afdata;
1209 fr->af.len = f->len;
1210 if (fr->af.datalen) {
1211 size_t copy_len = fr->af.datalen;
1212 if (copy_len > fr->afdatalen) {
1213 ast_log(LOG_ERROR, "Losing frame data because destination buffer size '%d' bytes not big enough for '%d' bytes in the frame\n",
1214 (int) fr->afdatalen, (int) fr->af.datalen);
1215 copy_len = fr->afdatalen;
1216 }
1217#if __BYTE_ORDER == __LITTLE_ENDIAN
1218 /* We need to byte-swap slinear samples from network byte order */
1219 if ((fr->af.frametype == AST_FRAME_VOICE) &&
1221 /* 2 bytes / sample for SLINEAR */
1222 ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2);
1223 } else
1224#endif
1225 memcpy(fr->af.data.ptr, f->data.ptr, copy_len);
1226 }
1227}
1228
1229struct iax_frame *iax_frame_new(int direction, int datalen, unsigned int cacheable)
1230{
1231 struct iax_frame *fr;
1232
1233#if !defined(NO_FRAME_CACHE)
1234 if (cacheable) {
1235 struct iax_frames *iax_frames;
1236 struct iax_frame *smallest;
1237
1238 /* Attempt to get a frame from this thread's cache */
1239 if ((iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
1240 smallest = AST_LIST_FIRST(&iax_frames->list);
1242 if (fr->afdatalen >= datalen) {
1243 size_t afdatalen = fr->afdatalen;
1245 iax_frames->size--;
1246 memset(fr, 0, sizeof(*fr));
1247 fr->afdatalen = afdatalen;
1248 break;
1249 } else if (smallest->afdatalen > fr->afdatalen) {
1250 smallest = fr;
1251 }
1252 }
1254 if (!fr) {
1255 if (iax_frames->size >= FRAME_CACHE_MAX_SIZE && smallest) {
1256 /* Make useless cache into something more useful */
1257 AST_LIST_REMOVE(&iax_frames->list, smallest, list);
1258 iax_frames->size--;
1259 ast_free(smallest);
1260 }
1261 if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
1262 return NULL;
1263 }
1264 fr->afdatalen = datalen;
1265 }
1266 } else {
1267 if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
1268 return NULL;
1269 }
1270 fr->afdatalen = datalen;
1271 }
1272 fr->cacheable = 1;
1273 } else
1274#endif
1275 {
1276 if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
1277 return NULL;
1278 }
1279 fr->afdatalen = datalen;
1280 }
1281
1282
1283 fr->direction = direction;
1284 fr->retrans = -1;
1285
1286 if (fr->direction == DIRECTION_INGRESS)
1288 else
1290
1292
1293 return fr;
1294}
1295
1297{
1298#if !defined(NO_FRAME_CACHE)
1299 struct iax_frames *iax_frames = NULL;
1300#endif
1301
1302 /* Note: does not remove from scheduler! */
1303 if (fr->direction == DIRECTION_INGRESS)
1305 else if (fr->direction == DIRECTION_OUTGRESS)
1307 else {
1308 errorf("Attempt to double free frame detected\n");
1309 return;
1310 }
1312
1313#if !defined(NO_FRAME_CACHE)
1314 if (!fr->cacheable
1316 || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
1317 ast_free(fr);
1318 return;
1319 }
1320
1322 fr->direction = 0;
1323 /* Pseudo-sort: keep smaller frames at the top of the list. This should
1324 * increase the chance that we pick the smallest applicable frame for use. */
1325 if (AST_LIST_FIRST(&iax_frames->list) && AST_LIST_FIRST(&iax_frames->list)->afdatalen < fr->afdatalen) {
1327 } else {
1329 }
1330 iax_frames->size++;
1331 return;
1332 }
1333#endif
1334 ast_free(fr);
1335}
1336
1337#if !defined(NO_FRAME_CACHE)
1338static void frame_cache_cleanup(void *data)
1339{
1340 struct iax_frames *framelist = data;
1341 struct iax_frame *current;
1342
1343 while ((current = AST_LIST_REMOVE_HEAD(&framelist->list, list)))
1345
1346 ast_free(framelist);
1347}
1348#endif
1349
1350int iax_get_frames(void) { return frames; }
1351int iax_get_iframes(void) { return iframes; }
1352int iax_get_oframes(void) { return oframes; }
const char * str
Definition app_jack.c:150
#define var
Definition ast_expr2f.c:605
uint64_t ntohll(uint64_t net64)
Definition strcompat.c:364
uint64_t htonll(uint64_t host64)
Definition strcompat.c:390
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ast_log
Definition astobj2.c:42
const char * iax2_getformatname(iax2_format format)
iax2 wrapper function for ast_getformatname
Definition chan_iax2.c:1976
static const char type[]
static char version[AST_MAX_EXTENSION]
size_t current
int iax2_codec_pref_string(struct iax2_codec_pref *pref, char *buf, size_t size)
Dump audio codec preference list into a string.
Definition codec_pref.c:178
void iax2_codec_pref_convert(struct iax2_codec_pref *pref, char *buf, size_t size, int right)
Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string.
Definition codec_pref.c:44
Media Format Bitfield Compatibility API.
char buf[BUFSIZE]
Definition eagi_proxy.c:66
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition format.h:36
Media Format Cache API.
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
static const char name[]
Definition format_mp3.c:68
direction
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Implementation of Inter-Asterisk eXchange, version 2 parser.c parser.h chan_iax2.c.
#define IAX_IE_PASSWORD
Definition iax2.h:137
#define IAX_IE_RR_PKTS
Definition iax2.h:179
iax_frame_subclass
Definition iax2.h:51
@ IAX_COMMAND_MWI
Definition iax2.h:103
@ IAX_COMMAND_FWDOWNL
Definition iax2.h:111
@ IAX_COMMAND_TXREL
Definition iax2.h:91
@ IAX_COMMAND_TXMEDIA
Definition iax2.h:115
@ IAX_COMMAND_AUTHREP
Definition iax2.h:60
@ IAX_COMMAND_PROVISION
Definition iax2.h:109
@ IAX_COMMAND_DPREP
Definition iax2.h:79
@ IAX_COMMAND_REGAUTH
Definition iax2.h:67
@ IAX_COMMAND_INVAL
Definition iax2.h:61
@ IAX_COMMAND_REJECT
Definition iax2.h:57
@ IAX_COMMAND_FWDATA
Definition iax2.h:113
@ IAX_COMMAND_ACK
Definition iax2.h:55
@ IAX_COMMAND_PONG
Definition iax2.h:54
@ IAX_COMMAND_LAGRQ
Definition iax2.h:62
@ IAX_COMMAND_HANGUP
Definition iax2.h:56
@ IAX_COMMAND_TXREADY
Definition iax2.h:89
@ IAX_COMMAND_TXACC
Definition iax2.h:87
@ IAX_COMMAND_QUELCH
Definition iax2.h:95
@ IAX_COMMAND_PING
Definition iax2.h:53
@ IAX_COMMAND_TRANSFER
Definition iax2.h:107
@ IAX_COMMAND_LAGRP
Definition iax2.h:63
@ IAX_COMMAND_TXCNT
Definition iax2.h:85
@ IAX_COMMAND_REGACK
Definition iax2.h:69
@ IAX_COMMAND_AUTHREQ
Definition iax2.h:59
@ IAX_COMMAND_TXREJ
Definition iax2.h:93
@ IAX_COMMAND_REGREJ
Definition iax2.h:71
@ IAX_COMMAND_REGREL
Definition iax2.h:73
@ IAX_COMMAND_CALLTOKEN
Definition iax2.h:119
@ IAX_COMMAND_DIAL
Definition iax2.h:81
@ IAX_COMMAND_ACCEPT
Definition iax2.h:58
@ IAX_COMMAND_UNSUPPORT
Definition iax2.h:105
@ IAX_COMMAND_NEW
Definition iax2.h:52
@ IAX_COMMAND_POKE
Definition iax2.h:99
@ IAX_COMMAND_PAGE
Definition iax2.h:101
@ IAX_COMMAND_REGREQ
Definition iax2.h:65
@ IAX_COMMAND_VNAK
Definition iax2.h:75
@ IAX_COMMAND_UNQUELCH
Definition iax2.h:97
@ IAX_COMMAND_TXREQ
Definition iax2.h:83
@ IAX_COMMAND_RTKEY
Definition iax2.h:117
@ IAX_COMMAND_DPREQ
Definition iax2.h:77
#define IAX_IE_RR_JITTER
Definition iax2.h:177
#define IAX_IE_DNID
Definition iax2.h:143
#define IAX_IE_SERVICEIDENT
Definition iax2.h:163
#define IAX_IE_CALLINGANI2
Definition iax2.h:190
#define IAX_IE_DATETIME
Definition iax2.h:161
#define IAX_IE_CAUSE
Definition iax2.h:152
#define IAX_IE_DPSTATUS
Definition iax2.h:150
#define IAX_IE_CALLING_NUMBER
Definition iax2.h:132
#define IAX_IE_SAMPLINGRATE
Definition iax2.h:171
#define IAX_IE_TRANSFERID
Definition iax2.h:157
#define IAX_RATE_48KHZ
Definition iax2.h:215
#define IAX_IE_CALLTOKEN
Definition iax2.h:185
#define IAX_IE_CALLING_ANI
Definition iax2.h:133
#define IAX_RATE_11KHZ
Definition iax2.h:211
#define IAX_IE_CALLINGTNS
Definition iax2.h:170
#define IAX_IE_RSA_RESULT
Definition iax2.h:147
#define IAX_IE_MSGCOUNT
Definition iax2.h:154
#define IAX_IE_IAX_UNKNOWN
Definition iax2.h:153
int64_t iax2_format
Definition iax2.h:224
#define IAX_IE_ENCKEY
Definition iax2.h:174
#define IAX_IE_FORMAT2
Definition iax2.h:188
#define IAX_RATE_8KHZ
Definition iax2.h:210
#define IAX_IE_CAPABILITY2
Definition iax2.h:187
#define IAX_IE_CALLING_NAME
Definition iax2.h:134
#define IAX_IE_ADSICPE
Definition iax2.h:142
#define IAX_IE_VARIABLE
Definition iax2.h:183
#define IAX_IE_OSPTOKEN
Definition iax2.h:184
#define IAX_IE_LANGUAGE
Definition iax2.h:140
#define IAX_IE_RDNIS
Definition iax2.h:158
#define IAX_FLAG_FULL
Definition iax2.h:40
#define IAX_IE_RR_DROPPED
Definition iax2.h:181
#define IAX_IE_MUSICONHOLD
Definition iax2.h:156
#define IAX_IE_FORMAT
Definition iax2.h:139
#define IAX_IE_ENCRYPTION
Definition iax2.h:173
#define IAX_IE_FIRMWAREVER
Definition iax2.h:164
#define IAX_RATE_16KHZ
Definition iax2.h:212
#define IAX_FLAG_RETRANS
Definition iax2.h:42
#define IAX_IE_CODEC_PREFS
Definition iax2.h:175
#define IAX_IE_CALLED_NUMBER
Definition iax2.h:131
#define IAX_IE_FWBLOCKDATA
Definition iax2.h:166
#define IAX_IE_CAPABILITY
Definition iax2.h:138
#define IAX_IE_PROVISIONING
Definition iax2.h:159
#define IAX_IE_MD5_RESULT
Definition iax2.h:146
#define IAX_IE_AUTOANSWER
Definition iax2.h:155
#define IAX_IE_VERSION
Definition iax2.h:141
#define IAX_IE_RR_OOO
Definition iax2.h:182
#define IAX_IE_CALLNO
Definition iax2.h:151
#define IAX_IE_APPARENT_ADDR
Definition iax2.h:148
#define IAX_IE_AESPROVISIONING
Definition iax2.h:160
#define IAX_IE_REFRESH
Definition iax2.h:149
#define IAX_IE_PROVVER
Definition iax2.h:167
#define IAX_MAX_OSPBLOCK_NUM
Definition iax2.h:193
#define IAX_RATE_44KHZ
Definition iax2.h:214
#define IAX_IE_CALLINGPRES
Definition iax2.h:168
#define IAX_IE_CAUSECODE
Definition iax2.h:172
#define IAX_IE_DEVICETYPE
Definition iax2.h:162
#define IAX_IE_AUTHMETHODS
Definition iax2.h:144
#define IAX_IE_RR_LOSS
Definition iax2.h:178
#define IAX_IE_FWBLOCKDESC
Definition iax2.h:165
#define IAX_IE_CALLED_CONTEXT
Definition iax2.h:135
#define IAX_IE_CALLINGTON
Definition iax2.h:169
#define IAX_RATE_22KHZ
Definition iax2.h:213
#define IAX_IE_USERNAME
Definition iax2.h:136
#define IAX_IE_CHALLENGE
Definition iax2.h:145
#define IAX_IE_RR_DELAY
Definition iax2.h:180
Configuration File Parser.
#define ast_variable_new(name, value, filename)
Media Format Bitfield Compatibility API.
Asterisk internal frame definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
void ast_swapcopy_samples(void *dst, const void *src, int samples)
Definition main/frame.c:396
@ AST_FRAME_DTMF_END
@ AST_FRAME_DTMF_BEGIN
@ AST_FRAME_CONTROL
#define LOG_ERROR
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition localtime.c:2524
Asterisk locking-related definitions:
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition lock.h:764
Network socket handling.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition netsock2.h:256
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition netsock2.c:497
int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr)
Determine if this is an IPv4-mapped IPv6 address.
Definition netsock2.c:507
#define ast_opt_cache_media_frames
Definition options.h:131
int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
Definition parser.c:795
static void dump_int(char *output, int maxlen, void *value, int len)
Definition parser.c:149
int iax_get_iframes(void)
Definition parser.c:1351
static void dump_samprate(char *output, int maxlen, void *value, int len)
Definition parser.c:221
int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct ast_sockaddr *addr)
Definition parser.c:741
void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t len)
Definition parser.c:463
static void dump_prov(char *output, int maxlen, void *value, int len)
Definition parser.c:264
static void dump_short(char *output, int maxlen, void *value, int len)
Definition parser.c:157
int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
Definition parser.c:775
static void(* errorf)(const char *str)
Definition parser.c:88
static int iframes
Definition parser.c:52
#define FRAME_CACHE_MAX_SIZE
Definition parser.c:74
void iax_frame_free(struct iax_frame *fr)
Definition parser.c:1296
static void dump_ies(unsigned char *iedata, int len)
Definition parser.c:416
static int frames
Definition parser.c:51
static void dump_ipaddr(char *output, int maxlen, void *value, int len)
Definition parser.c:189
void iax_set_error(void(*func)(const char *))
Definition parser.c:790
static int oframes
Definition parser.c:53
void iax_set_output(void(*func)(const char *))
Definition parser.c:785
static void dump_datetime(char *output, int maxlen, void *value, int len)
Definition parser.c:173
static void dump_string(char *output, int maxlen, void *value, int len)
Definition parser.c:121
int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
Definition parser.c:780
static const struct iax2_ie prov_ies[]
Definition parser.c:333
int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value)
Definition parser.c:746
struct iax_frame * iax_frame_new(int direction, int datalen, unsigned int cacheable)
Definition parser.c:1229
static void dump_versioned_codec(char *output, int maxlen, void *value, int len)
Definition parser.c:248
static void internalerror(const char *str)
Definition parser.c:82
int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
Definition parser.c:726
int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value)
Definition parser.c:756
static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len)
Definition parser.c:364
static void dump_byte(char *output, int maxlen, void *value, int len)
Definition parser.c:165
int iax_get_oframes(void)
Definition parser.c:1352
static void(* outputf)(const char *str)
Definition parser.c:87
static void dump_prov_flags(char *output, int maxlen, void *value, int len)
Definition parser.c:211
void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
Definition parser.c:1196
static void dump_string_hex(char *output, int maxlen, void *value, int len)
Definition parser.c:111
int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value)
Definition parser.c:763
void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct ast_sockaddr *addr, int datalen)
Definition parser.c:595
int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const char *str)
Definition parser.c:770
static void dump_addr(char *output, int maxlen, void *value, int len)
Definition parser.c:90
static void internaloutput(const char *str)
Definition parser.c:77
static void frame_cache_cleanup(void *data)
Definition parser.c:1338
static struct iax2_ie infoelts[]
Definition parser.c:274
int iax_get_frames(void)
Definition parser.c:1350
static void dump_prefs(char *output, int maxlen, void *value, int len)
Definition parser.c:130
const char * iax_ie2str(int ie)
Definition parser.c:353
Implementation of the IAX2 protocol.
#define DIRECTION_OUTGRESS
Definition parser.h:89
#define DIRECTION_INGRESS
Definition parser.h:88
IAX2 Provisioning protocol.
#define PROV_IE_GATEWAY
Definition provision.h:24
#define PROV_IE_PROVVER
Definition provision.h:38
#define PROV_IE_PORTNO
Definition provision.h:25
#define PROV_IE_SERVERIP
Definition provision.h:35
#define PROV_IE_NEWAESKEY
Definition provision.h:37
#define PROV_IE_USEDHCP
Definition provision.h:21
#define PROV_IE_SUBNET
Definition provision.h:23
#define PROV_IE_FORMAT
Definition provision.h:33
char * iax_provflags2str(char *buf, int buflen, unsigned int flags)
Definition provision.c:90
#define PROV_IE_USER
Definition provision.h:26
#define PROV_IE_IPADDR
Definition provision.h:22
#define PROV_IE_FLAGS
Definition provision.h:32
#define PROV_IE_TOS
Definition provision.h:31
#define PROV_IE_SERVERPORT
Definition provision.h:36
#define PROV_IE_PASS
Definition provision.h:27
#define PROV_IE_LANG
Definition provision.h:30
#define PROV_IE_ALTSERVER
Definition provision.h:39
#define PROV_IE_AESKEY
Definition provision.h:34
#define NULL
Definition resample.c:96
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition strings.h:1113
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
struct timeval delivery
enum ast_frame_type frametype
union ast_frame::@239 data
unsigned char iedata[0]
Definition iax2.h:238
unsigned short dcallno
Definition iax2.h:232
unsigned short scallno
Definition iax2.h:231
unsigned int ts
Definition iax2.h:233
unsigned char iseqno
Definition iax2.h:235
unsigned char csub
Definition iax2.h:237
unsigned char oseqno
Definition iax2.h:234
unsigned char type
Definition iax2.h:236
Socket address structure.
Definition netsock2.h:97
struct sockaddr_storage ss
Definition netsock2.h:98
socklen_t len
Definition netsock2.h:99
Support for dynamic strings.
Definition strings.h:623
int tm_mday
Definition localtime.h:39
int tm_sec
Definition localtime.h:36
int tm_hour
Definition localtime.h:38
int tm_min
Definition localtime.h:37
int tm_year
Definition localtime.h:41
int tm_mon
Definition localtime.h:40
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
char * name
Definition parser.c:271
void(* dump)(char *output, int maxlen, void *value, int len)
Definition parser.c:272
int ie
Definition parser.c:270
This is just so iax_frames, a list head struct for holding a list of iax_frame structures,...
Definition parser.c:67
struct iax_frame::@148 list
int retrans
Definition parser.h:130
unsigned char afdata[0]
Definition parser.h:146
void * data
Definition parser.h:104
int retries
Definition parser.h:108
size_t afdatalen
Definition parser.h:144
unsigned int direction
Definition parser.h:122
int datalen
Definition parser.h:106
struct ast_frame af
Definition parser.h:142
unsigned int cacheable
Definition parser.h:124
struct iax_frame_list list
Definition parser.c:70
size_t size
Definition parser.c:71
unsigned char buf[1024]
Definition parser.h:150
struct ast_sockaddr apparent_addr
Definition parser.h:52
unsigned short adsicpe
Definition parser.h:44
unsigned int rr_jitter
Definition parser.h:75
unsigned int provver
Definition parser.h:72
unsigned char * calltokendata
Definition parser.h:85
unsigned int rr_pkts
Definition parser.h:77
struct ast_variable * vars
Definition parser.h:81
unsigned char calltoken
Definition parser.h:84
unsigned char iax_unknown
Definition parser.h:58
int calling_ani2
Definition parser.h:35
unsigned int rr_loss
Definition parser.h:76
unsigned int authmethods
Definition parser.h:47
char * challenge
Definition parser.h:49
char * dnid
Definition parser.h:45
char * calling_name
Definition parser.h:31
iax2_format capability
Definition parser.h:39
char * called_context
Definition parser.h:36
unsigned char * enckey
Definition parser.h:70
char * calling_number
Definition parser.h:29
unsigned int fwdesc
Definition parser.h:67
char * calling_ani
Definition parser.h:30
int calling_ton
Definition parser.h:32
char * password
Definition parser.h:38
unsigned int transferid
Definition parser.h:62
unsigned int datetime
Definition parser.h:63
unsigned int rr_dropped
Definition parser.h:79
unsigned char causecode
Definition parser.h:57
int firmwarever
Definition parser.h:66
unsigned int ospblocklength[IAX_MAX_OSPBLOCK_NUM]
Definition parser.h:83
int msgcount
Definition parser.h:59
int calling_tns
Definition parser.h:33
char * called_number
Definition parser.h:28
unsigned short callno
Definition parser.h:55
char * md5_result
Definition parser.h:50
int provverpres
Definition parser.h:74
char * language
Definition parser.h:42
char * codec_prefs
Definition parser.h:41
iax2_format format
Definition parser.h:40
unsigned int encmethods
Definition parser.h:48
unsigned char * fwdata
Definition parser.h:68
unsigned short dpstatus
Definition parser.h:54
char * username
Definition parser.h:37
char * rsa_result
Definition parser.h:51
int calling_pres
Definition parser.h:34
int autoanswer
Definition parser.h:60
unsigned short samprate
Definition parser.h:73
int version
Definition parser.h:43
unsigned char fwdatalen
Definition parser.h:69
char * cause
Definition parser.h:56
int musiconhold
Definition parser.h:61
unsigned short refresh
Definition parser.h:53
char * serviceident
Definition parser.h:65
unsigned int rr_ooo
Definition parser.h:80
char * devicetype
Definition parser.h:64
char * rdnis
Definition parser.h:46
unsigned short rr_delay
Definition parser.h:78
unsigned char enckeylen
Definition parser.h:71
char * osptokenblock[IAX_MAX_OSPBLOCK_NUM]
Definition parser.h:82
int value
Definition syslog.c:37
Definitions to aid in the use of thread local storage.
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
Handle unaligned data access.
static unsigned int get_unaligned_uint32(const void *p)
Definition unaligned.h:38
static unsigned short get_unaligned_uint16(const void *p)
Definition unaligned.h:44
static void put_unaligned_uint64(void *p, uint64_t datum)
Definition unaligned.h:51
static uint64_t get_unaligned_uint64(const void *p)
Definition unaligned.h:32
Utility functions.
#define ARRAY_LEN(a)
Definition utils.h:706