Asterisk - The Open Source Telephony Project  GIT-master-8beac82
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"
41 #include "asterisk/threadstorage.h"
42 #include "asterisk/netsock2.h"
43 #include "asterisk/format_cache.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 */
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 
69 struct iax_frames {
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_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 
333 static 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 
353 const 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 
364 static 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 
416 static 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 
463 void 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;
483  case IAX_COMMAND_HANGUP:
484  cmd = "HANGUP ";
485  break;
486  case IAX_COMMAND_REJECT:
487  cmd = "REJECT ";
488  break;
489  case IAX_COMMAND_ACCEPT:
490  cmd = "ACCEPT ";
491  break;
492  case IAX_COMMAND_AUTHREQ:
493  cmd = "AUTHREQ";
494  break;
495  case IAX_COMMAND_AUTHREP:
496  cmd = "AUTHREP";
497  break;
498  case IAX_COMMAND_INVAL:
499  cmd = "INVAL ";
500  break;
501  case IAX_COMMAND_LAGRQ:
502  cmd = "LAGRQ ";
503  break;
504  case IAX_COMMAND_LAGRP:
505  cmd = "LAGRP ";
506  break;
507  case IAX_COMMAND_REGREQ:
508  cmd = "REGREQ ";
509  break;
510  case IAX_COMMAND_REGAUTH:
511  cmd = "REGAUTH";
512  break;
513  case IAX_COMMAND_REGACK:
514  cmd = "REGACK ";
515  break;
516  case IAX_COMMAND_REGREJ:
517  cmd = "REGREJ ";
518  break;
519  case IAX_COMMAND_REGREL:
520  cmd = "REGREL ";
521  break;
522  case IAX_COMMAND_VNAK:
523  cmd = "VNAK ";
524  break;
525  case IAX_COMMAND_DPREQ:
526  cmd = "DPREQ ";
527  break;
528  case IAX_COMMAND_DPREP:
529  cmd = "DPREP ";
530  break;
531  case IAX_COMMAND_DIAL:
532  cmd = "DIAL ";
533  break;
534  case IAX_COMMAND_TXREQ:
535  cmd = "TXREQ ";
536  break;
537  case IAX_COMMAND_TXCNT:
538  cmd = "TXCNT ";
539  break;
540  case IAX_COMMAND_TXACC:
541  cmd = "TXACC ";
542  break;
543  case IAX_COMMAND_TXREADY:
544  cmd = "TXREADY";
545  break;
546  case IAX_COMMAND_TXREL:
547  cmd = "TXREL ";
548  break;
549  case IAX_COMMAND_TXREJ:
550  cmd = "TXREJ ";
551  break;
552  case IAX_COMMAND_QUELCH:
553  cmd = "QUELCH ";
554  break;
556  cmd = "UNQULCH";
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;
576  case IAX_COMMAND_FWDOWNL:
577  cmd = "FWDWNLD";
578  break;
579  case IAX_COMMAND_FWDATA:
580  cmd = "FWDATA ";
581  break;
582  case IAX_COMMAND_TXMEDIA:
583  cmd = "TXMEDIA";
584  break;
585  case IAX_COMMAND_RTKEY:
586  cmd = "RTKEY ";
587  break;
589  cmd = "CTOKEN ";
590  break;
591  }
592  ast_copy_string(str, cmd, len);
593 }
594 
595 void 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,
718  ast_sockaddr_stringify(addr));
719 
720  outputf(tmp);
721  if (fh->type == AST_FRAME_IAX)
722  dump_ies(fh->iedata, datalen);
723 
724 }
725 
726 int 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 
741 int 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 
746 int 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 
756 int 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 
763 int 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 
770 int 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 
775 int 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 
780 int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
781 {
782  return iax_ie_append_raw(ied, ie, NULL, 0);
783 }
784 
785 void iax_set_output(void (*func)(const char *))
786 {
787  outputf = func;
788 }
789 
790 void iax_set_error(void (*func)(const char *))
791 {
792  errorf = func;
793 }
794 
795 int 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  errorf("Information element length exceeds message size\n");
816  return -1;
817  }
818  switch(ie) {
820  ies->called_number = (char *)data + 2;
821  break;
823  ies->calling_number = (char *)data + 2;
824  break;
825  case IAX_IE_CALLING_ANI:
826  ies->calling_ani = (char *)data + 2;
827  break;
828  case IAX_IE_CALLING_NAME:
829  ies->calling_name = (char *)data + 2;
830  break;
832  ies->called_context = (char *)data + 2;
833  break;
834  case IAX_IE_USERNAME:
835  ies->username = (char *)data + 2;
836  break;
837  case IAX_IE_PASSWORD:
838  ies->password = (char *)data + 2;
839  break;
840  case IAX_IE_CODEC_PREFS:
841  ies->codec_prefs = (char *)data + 2;
842  break;
843  case IAX_IE_CAPABILITY:
844  if (len != (int)sizeof(unsigned int)) {
845  snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
846  errorf(tmp);
847  } else if (ies->capability == 0) { /* Don't overwrite capability2, if specified */
848  ies->capability = ntohl(get_unaligned_uint32(data + 2));
849  }
850  break;
851  case IAX_IE_CAPABILITY2:
852  {
853  int version = data[2];
854  if (version == 0) {
855  if (len != (int)sizeof(char) + sizeof(iax2_format)) {
856  snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int) (sizeof(iax2_format) + sizeof(char)), len);
857  errorf(tmp);
858  } else {
860  }
861  } /* else unknown version */
862  }
863  break;
864  case IAX_IE_FORMAT:
865  if (len != (int)sizeof(unsigned int)) {
866  snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
867  errorf(tmp);
868  } else if (ies->format == 0) { /* Don't overwrite format2, if specified */
869  ies->format = ntohl(get_unaligned_uint32(data + 2));
870  }
871  break;
872  case IAX_IE_FORMAT2:
873  {
874  int version = data[2];
875  if (version == 0) {
876  if (len != (int)sizeof(char) + sizeof(iax2_format)) {
877  snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int) (sizeof(iax2_format) + sizeof(char)), len);
878  errorf(tmp);
879  } else {
880  ies->format = (iax2_format) ntohll(get_unaligned_uint64(data + 3));
881  }
882  } /* else unknown version */
883  }
884  break;
885  case IAX_IE_LANGUAGE:
886  ies->language = (char *)data + 2;
887  break;
888  case IAX_IE_VERSION:
889  if (len != (int)sizeof(unsigned short)) {
890  snprintf(tmp, (int)sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
891  errorf(tmp);
892  } else
893  ies->version = ntohs(get_unaligned_uint16(data + 2));
894  break;
895  case IAX_IE_ADSICPE:
896  if (len != (int)sizeof(unsigned short)) {
897  snprintf(tmp, (int)sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
898  errorf(tmp);
899  } else
900  ies->adsicpe = ntohs(get_unaligned_uint16(data + 2));
901  break;
902  case IAX_IE_SAMPLINGRATE:
903  if (len != (int)sizeof(unsigned short)) {
904  snprintf(tmp, (int)sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
905  errorf(tmp);
906  } else
907  ies->samprate = ntohs(get_unaligned_uint16(data + 2));
908  break;
909  case IAX_IE_DNID:
910  ies->dnid = (char *)data + 2;
911  break;
912  case IAX_IE_RDNIS:
913  ies->rdnis = (char *)data + 2;
914  break;
915  case IAX_IE_AUTHMETHODS:
916  if (len != (int)sizeof(unsigned short)) {
917  snprintf(tmp, (int)sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
918  errorf(tmp);
919  } else
920  ies->authmethods = ntohs(get_unaligned_uint16(data + 2));
921  break;
922  case IAX_IE_ENCRYPTION:
923  if (len != (int)sizeof(unsigned short)) {
924  snprintf(tmp, (int)sizeof(tmp), "Expecting encryption to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
925  errorf(tmp);
926  } else
927  ies->encmethods = ntohs(get_unaligned_uint16(data + 2));
928  break;
929  case IAX_IE_CHALLENGE:
930  ies->challenge = (char *)data + 2;
931  break;
932  case IAX_IE_MD5_RESULT:
933  ies->md5_result = (char *)data + 2;
934  break;
935  case IAX_IE_RSA_RESULT:
936  ies->rsa_result = (char *)data + 2;
937  break;
939  memcpy(&ies->apparent_addr , (struct ast_sockaddr *) (data + 2), len);
940  ies->apparent_addr.len = len;
941  break;
942  case IAX_IE_REFRESH:
943  if (len != (int)sizeof(unsigned short)) {
944  snprintf(tmp, (int)sizeof(tmp), "Expecting refresh to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
945  errorf(tmp);
946  } else
947  ies->refresh = ntohs(get_unaligned_uint16(data + 2));
948  break;
949  case IAX_IE_DPSTATUS:
950  if (len != (int)sizeof(unsigned short)) {
951  snprintf(tmp, (int)sizeof(tmp), "Expecting dpstatus to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
952  errorf(tmp);
953  } else
954  ies->dpstatus = ntohs(get_unaligned_uint16(data + 2));
955  break;
956  case IAX_IE_CALLNO:
957  if (len != (int)sizeof(unsigned short)) {
958  snprintf(tmp, (int)sizeof(tmp), "Expecting callno to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
959  errorf(tmp);
960  } else
961  ies->callno = ntohs(get_unaligned_uint16(data + 2));
962  break;
963  case IAX_IE_CAUSE:
964  ies->cause = (char *)data + 2;
965  break;
966  case IAX_IE_CAUSECODE:
967  if (len != 1) {
968  snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
969  errorf(tmp);
970  } else {
971  ies->causecode = data[2];
972  }
973  break;
974  case IAX_IE_IAX_UNKNOWN:
975  if (len == 1)
976  ies->iax_unknown = data[2];
977  else {
978  snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
979  errorf(tmp);
980  }
981  break;
982  case IAX_IE_MSGCOUNT:
983  if (len != (int)sizeof(unsigned short)) {
984  snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
985  errorf(tmp);
986  } else
987  ies->msgcount = ntohs(get_unaligned_uint16(data + 2));
988  break;
989  case IAX_IE_AUTOANSWER:
990  ies->autoanswer = 1;
991  break;
992  case IAX_IE_MUSICONHOLD:
993  ies->musiconhold = 1;
994  break;
995  case IAX_IE_TRANSFERID:
996  if (len != (int)sizeof(unsigned int)) {
997  snprintf(tmp, (int)sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
998  errorf(tmp);
999  } else
1000  ies->transferid = ntohl(get_unaligned_uint32(data + 2));
1001  break;
1002  case IAX_IE_DATETIME:
1003  if (len != (int)sizeof(unsigned int)) {
1004  snprintf(tmp, (int)sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1005  errorf(tmp);
1006  } else
1007  ies->datetime = ntohl(get_unaligned_uint32(data + 2));
1008  break;
1009  case IAX_IE_FIRMWAREVER:
1010  if (len != (int)sizeof(unsigned short)) {
1011  snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1012  errorf(tmp);
1013  } else
1014  ies->firmwarever = ntohs(get_unaligned_uint16(data + 2));
1015  break;
1016  case IAX_IE_DEVICETYPE:
1017  ies->devicetype = (char *)data + 2;
1018  break;
1019  case IAX_IE_SERVICEIDENT:
1020  ies->serviceident = (char *)data + 2;
1021  break;
1022  case IAX_IE_FWBLOCKDESC:
1023  if (len != (int)sizeof(unsigned int)) {
1024  snprintf(tmp, (int)sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1025  errorf(tmp);
1026  } else
1027  ies->fwdesc = ntohl(get_unaligned_uint32(data + 2));
1028  break;
1029  case IAX_IE_FWBLOCKDATA:
1030  ies->fwdata = data + 2;
1031  ies->fwdatalen = len;
1032  break;
1033  case IAX_IE_ENCKEY:
1034  ies->enckey = data + 2;
1035  ies->enckeylen = len;
1036  break;
1037  case IAX_IE_PROVVER:
1038  if (len != (int)sizeof(unsigned int)) {
1039  snprintf(tmp, (int)sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1040  errorf(tmp);
1041  } else {
1042  ies->provverpres = 1;
1043  ies->provver = ntohl(get_unaligned_uint32(data + 2));
1044  }
1045  break;
1046  case IAX_IE_CALLINGPRES:
1047  if (len == 1)
1048  ies->calling_pres = data[2];
1049  else {
1050  snprintf(tmp, (int)sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len);
1051  errorf(tmp);
1052  }
1053  break;
1054  case IAX_IE_CALLINGTON:
1055  if (len == 1)
1056  ies->calling_ton = data[2];
1057  else {
1058  snprintf(tmp, (int)sizeof(tmp), "Expected single byte callington, but was %d long\n", len);
1059  errorf(tmp);
1060  }
1061  break;
1062  case IAX_IE_CALLINGANI2:
1063  if (len == (int)sizeof(unsigned int)) {
1064  ies->calling_ani2 = ntohl(get_unaligned_uint32(data + 2));
1065  } else {
1066  snprintf(tmp, (int)sizeof(tmp), "callingani2 was %d long: %s\n", len, data + 2);
1067  errorf(tmp);
1068  }
1069  break;
1070  case IAX_IE_CALLINGTNS:
1071  if (len != (int)sizeof(unsigned short)) {
1072  snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1073  errorf(tmp);
1074  } else
1075  ies->calling_tns = ntohs(get_unaligned_uint16(data + 2));
1076  break;
1077  case IAX_IE_RR_JITTER:
1078  if (len != (int)sizeof(unsigned int)) {
1079  snprintf(tmp, (int)sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1080  errorf(tmp);
1081  } else {
1082  ies->rr_jitter = ntohl(get_unaligned_uint32(data + 2));
1083  }
1084  break;
1085  case IAX_IE_RR_LOSS:
1086  if (len != (int)sizeof(unsigned int)) {
1087  snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1088  errorf(tmp);
1089  } else {
1090  ies->rr_loss = ntohl(get_unaligned_uint32(data + 2));
1091  }
1092  break;
1093  case IAX_IE_RR_PKTS:
1094  if (len != (int)sizeof(unsigned int)) {
1095  snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1096  errorf(tmp);
1097  } else {
1098  ies->rr_pkts = ntohl(get_unaligned_uint32(data + 2));
1099  }
1100  break;
1101  case IAX_IE_RR_DELAY:
1102  if (len != (int)sizeof(unsigned short)) {
1103  snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1104  errorf(tmp);
1105  } else {
1106  ies->rr_delay = ntohs(get_unaligned_uint16(data + 2));
1107  }
1108  break;
1109  case IAX_IE_RR_DROPPED:
1110  if (len != (int)sizeof(unsigned int)) {
1111  snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1112  errorf(tmp);
1113  } else {
1114  ies->rr_dropped = ntohl(get_unaligned_uint32(data + 2));
1115  }
1116  break;
1117  case IAX_IE_RR_OOO:
1118  if (len != (int)sizeof(unsigned int)) {
1119  snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1120  errorf(tmp);
1121  } else {
1122  ies->rr_ooo = ntohl(get_unaligned_uint32(data + 2));
1123  }
1124  break;
1125  case IAX_IE_VARIABLE:
1126  ast_copy_string(tmp, (char *)data + 2, len + 1);
1127  tmp2 = strchr(tmp, '=');
1128  if (tmp2)
1129  *tmp2++ = '\0';
1130  else
1131  tmp2 = "";
1132  {
1133  struct ast_str *str = ast_str_create(16);
1134  /* Existing variable or new variable? */
1135  for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) {
1136  if (strcmp(tmp, var2->name) == 0) {
1137  ast_str_set(&str, 0, "%s%s", var2->value, tmp2);
1138  var = ast_variable_new(tmp, ast_str_buffer(str), var2->file);
1139  var->next = var2->next;
1140  if (prev) {
1141  prev->next = var;
1142  } else {
1143  ies->vars = var;
1144  }
1145  snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
1146  outputf(tmp);
1147  ast_free(var2);
1148  break;
1149  }
1150  }
1151  ast_free(str);
1152  }
1153 
1154  if (!var2) {
1155  var = ast_variable_new(tmp, tmp2, "");
1156  snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
1157  outputf(tmp);
1158  var->next = ies->vars;
1159  ies->vars = var;
1160  }
1161  break;
1162  case IAX_IE_OSPTOKEN:
1163  if ((count = data[2]) < IAX_MAX_OSPBLOCK_NUM) {
1164  ies->osptokenblock[count] = (char *)data + 2 + 1;
1165  ies->ospblocklength[count] = len - 1;
1166  } else {
1167  snprintf(tmp, (int)sizeof(tmp), "Expected OSP token block index to be 0~%d but was %u\n", IAX_MAX_OSPBLOCK_NUM - 1, count);
1168  errorf(tmp);
1169  }
1170  break;
1171  case IAX_IE_CALLTOKEN:
1172  if (len) {
1173  ies->calltokendata = (unsigned char *) data + 2;
1174  }
1175  ies->calltoken = 1;
1176  break;
1177  default:
1178  snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
1179  outputf(tmp);
1180  }
1181  /* Overwrite information element with 0, to null terminate previous portion */
1182  data[0] = 0;
1183  datalen -= (len + 2);
1184  data += (len + 2);
1185  }
1186  /* Null-terminate last field */
1187  *data = '\0';
1188  if (datalen) {
1189  errorf("Invalid information element contents, strange boundary\n");
1190  return -1;
1191  }
1192  return 0;
1193 }
1194 
1195 void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
1196 {
1197  fr->af.frametype = f->frametype;
1198  fr->af.subclass.format = f->subclass.format;
1199  fr->af.subclass.integer = f->subclass.integer;
1200  fr->af.mallocd = 0; /* Our frame is static relative to the container */
1201  fr->af.datalen = f->datalen;
1202  fr->af.samples = f->samples;
1204  fr->af.src = f->src;
1205  fr->af.delivery.tv_sec = 0;
1206  fr->af.delivery.tv_usec = 0;
1207  fr->af.data.ptr = fr->afdata;
1208  fr->af.len = f->len;
1209  if (fr->af.datalen) {
1210  size_t copy_len = fr->af.datalen;
1211  if (copy_len > fr->afdatalen) {
1212  ast_log(LOG_ERROR, "Losing frame data because destination buffer size '%d' bytes not big enough for '%d' bytes in the frame\n",
1213  (int) fr->afdatalen, (int) fr->af.datalen);
1214  copy_len = fr->afdatalen;
1215  }
1216 #if __BYTE_ORDER == __LITTLE_ENDIAN
1217  /* We need to byte-swap slinear samples from network byte order */
1218  if ((fr->af.frametype == AST_FRAME_VOICE) &&
1220  /* 2 bytes / sample for SLINEAR */
1221  ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2);
1222  } else
1223 #endif
1224  memcpy(fr->af.data.ptr, f->data.ptr, copy_len);
1225  }
1226 }
1227 
1228 struct iax_frame *iax_frame_new(int direction, int datalen, unsigned int cacheable)
1229 {
1230  struct iax_frame *fr;
1231 
1232 #if !defined(NO_FRAME_CACHE)
1233  if (cacheable) {
1234  struct iax_frames *iax_frames;
1235  struct iax_frame *smallest;
1236 
1237  /* Attempt to get a frame from this thread's cache */
1238  if ((iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
1239  smallest = AST_LIST_FIRST(&iax_frames->list);
1240  AST_LIST_TRAVERSE_SAFE_BEGIN(&iax_frames->list, fr, list) {
1241  if (fr->afdatalen >= datalen) {
1242  size_t afdatalen = fr->afdatalen;
1244  iax_frames->size--;
1245  memset(fr, 0, sizeof(*fr));
1246  fr->afdatalen = afdatalen;
1247  break;
1248  } else if (smallest->afdatalen > fr->afdatalen) {
1249  smallest = fr;
1250  }
1251  }
1253  if (!fr) {
1254  if (iax_frames->size >= FRAME_CACHE_MAX_SIZE && smallest) {
1255  /* Make useless cache into something more useful */
1256  AST_LIST_REMOVE(&iax_frames->list, smallest, list);
1257  iax_frames->size--;
1258  ast_free(smallest);
1259  }
1260  if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
1261  return NULL;
1262  }
1263  fr->afdatalen = datalen;
1264  }
1265  } else {
1266  if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
1267  return NULL;
1268  }
1269  fr->afdatalen = datalen;
1270  }
1271  fr->cacheable = 1;
1272  } else
1273 #endif
1274  {
1275  if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
1276  return NULL;
1277  }
1278  fr->afdatalen = datalen;
1279  }
1280 
1281 
1282  fr->direction = direction;
1283  fr->retrans = -1;
1284 
1285  if (fr->direction == DIRECTION_INGRESS)
1287  else
1289 
1291 
1292  return fr;
1293 }
1294 
1295 void iax_frame_free(struct iax_frame *fr)
1296 {
1297 #if !defined(NO_FRAME_CACHE)
1298  struct iax_frames *iax_frames = NULL;
1299 #endif
1300 
1301  /* Note: does not remove from scheduler! */
1302  if (fr->direction == DIRECTION_INGRESS)
1304  else if (fr->direction == DIRECTION_OUTGRESS)
1306  else {
1307  errorf("Attempt to double free frame detected\n");
1308  return;
1309  }
1311 
1312 #if !defined(NO_FRAME_CACHE)
1313  if (!fr->cacheable
1315  || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
1316  ast_free(fr);
1317  return;
1318  }
1319 
1320  if (iax_frames->size < FRAME_CACHE_MAX_SIZE) {
1321  fr->direction = 0;
1322  /* Pseudo-sort: keep smaller frames at the top of the list. This should
1323  * increase the chance that we pick the smallest applicable frame for use. */
1324  if (AST_LIST_FIRST(&iax_frames->list) && AST_LIST_FIRST(&iax_frames->list)->afdatalen < fr->afdatalen) {
1325  AST_LIST_INSERT_TAIL(&iax_frames->list, fr, list);
1326  } else {
1327  AST_LIST_INSERT_HEAD(&iax_frames->list, fr, list);
1328  }
1329  iax_frames->size++;
1330  return;
1331  }
1332 #endif
1333  ast_free(fr);
1334 }
1335 
1336 #if !defined(NO_FRAME_CACHE)
1337 static void frame_cache_cleanup(void *data)
1338 {
1339  struct iax_frames *framelist = data;
1340  struct iax_frame *current;
1341 
1342  while ((current = AST_LIST_REMOVE_HEAD(&framelist->list, list)))
1343  ast_free(current);
1344 
1345  ast_free(framelist);
1346 }
1347 #endif
1348 
1349 int iax_get_frames(void) { return frames; }
1350 int iax_get_iframes(void) { return iframes; }
1351 int iax_get_oframes(void) { return oframes; }
struct ast_variable * next
struct ast_frame af
Definition: parser.h:142
struct sockaddr_storage ss
Definition: netsock2.h:98
#define PROV_IE_FLAGS
Definition: provision.h:32
static void(* outputf)(const char *str)
Definition: parser.c:87
unsigned int fwdesc
Definition: parser.h:67
#define IAX_IE_IAX_UNKNOWN
Definition: iax2.h:153
static void dump_int(char *output, int maxlen, void *value, int len)
Definition: parser.c:149
static void dump_byte(char *output, int maxlen, void *value, int len)
Definition: parser.c:165
#define IAX_RATE_22KHZ
Definition: iax2.h:213
static void frame_cache_cleanup(void *data)
Definition: parser.c:1337
#define IAX_IE_CAPABILITY2
Definition: iax2.h:187
static struct ast_threadstorage frame_cache
Definition: parser.c:63
unsigned char csub
Definition: iax2.h:237
static const char name[]
Definition: format_mp3.c:68
int calling_tns
Definition: parser.h:33
Asterisk locking-related definitions:
#define IAX_IE_CALLINGTNS
Definition: iax2.h:170
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
Definition: parser.c:780
char * serviceident
Definition: parser.h:65
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define IAX_IE_PROVVER
Definition: iax2.h:167
char * rsa_result
Definition: parser.h:51
This is just so iax_frames, a list head struct for holding a list of iax_frame structures, is defined.
Definition: parser.c:67
int iax_get_oframes(void)
Definition: parser.c:1351
char * md5_result
Definition: parser.h:50
#define IAX_RATE_44KHZ
Definition: iax2.h:214
Definition: ast_expr2.c:325
static int iframes
Definition: parser.c:52
static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len)
Definition: parser.c:364
unsigned short scallno
Definition: iax2.h:231
size_t afdatalen
Definition: parser.h:144
#define PROV_IE_USEDHCP
Definition: provision.h:21
static const struct iax2_ie prov_ies[]
Definition: parser.c:333
iax_frame_subclass
Definition: iax2.h:51
const char * iax_ie2str(int ie)
Definition: parser.c:353
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
unsigned int transferid
Definition: parser.h:62
#define PROV_IE_NEWAESKEY
Definition: provision.h:37
static void dump_samprate(char *output, int maxlen, void *value, int len)
Definition: parser.c:221
static void dump_prefs(char *output, int maxlen, void *value, int len)
Definition: parser.c:130
#define IAX_IE_VARIABLE
Definition: iax2.h:183
#define IAX_IE_RR_LOSS
Definition: iax2.h:178
struct iax_frame * iax_frame_new(int direction, int datalen, unsigned int cacheable)
Definition: parser.c:1228
const char * iax2_getformatname(iax2_format format)
iax2 wrapper function for ast_getformatname
Definition: chan_iax2.c:1904
unsigned char * fwdata
Definition: parser.h:68
#define IAX_IE_DATETIME
Definition: iax2.h:161
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
char * username
Definition: parser.h:37
unsigned char oseqno
Definition: iax2.h:234
unsigned int rr_dropped
Definition: parser.h:79
int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value)
Definition: parser.c:756
int calling_ton
Definition: parser.h:32
void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
Definition: parser.c:1195
static int tmp()
Definition: bt_open.c:389
socklen_t len
Definition: netsock2.h:99
static void dump_ies(unsigned char *iedata, int len)
Definition: parser.c:416
#define IAX_IE_CALLNO
Definition: iax2.h:151
#define IAX_RATE_48KHZ
Definition: iax2.h:215
Structure for variables, used for configurations and for channel variables.
iax2_format format
Definition: parser.h:40
void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t len)
Definition: parser.c:463
#define IAX_IE_MD5_RESULT
Definition: iax2.h:146
static int oframes
Definition: parser.c:53
unsigned char * enckey
Definition: parser.h:70
#define var
Definition: ast_expr2f.c:614
#define IAX_IE_FIRMWAREVER
Definition: iax2.h:164
int firmwarever
Definition: parser.h:66
void ast_swapcopy_samples(void *dst, const void *src, int samples)
Definition: main/frame.c:396
unsigned char afdata[0]
Definition: parser.h:146
#define IAX_IE_RR_DELAY
Definition: iax2.h:180
#define IAX_IE_AUTOANSWER
Definition: iax2.h:155
static struct iax2_ie infoelts[]
Definition: parser.c:274
int iax_get_frames(void)
Definition: parser.c:1349
#define IAX_IE_SAMPLINGRATE
Definition: iax2.h:171
#define PROV_IE_USER
Definition: provision.h:26
unsigned int rr_loss
Definition: parser.h:76
unsigned int datetime
Definition: parser.h:63
Definition: parser.h:27
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
#define IAX_IE_CHALLENGE
Definition: iax2.h:145
unsigned int provver
Definition: parser.h:72
unsigned short dpstatus
Definition: parser.h:54
Definitions to aid in the use of thread local storage.
#define FRAME_CACHE_MAX_SIZE
Definition: parser.c:74
unsigned char fwdatalen
Definition: parser.h:69
int value
Definition: syslog.c:37
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:855
#define IAX_IE_DPSTATUS
Definition: iax2.h:150
char * devicetype
Definition: parser.h:64
static void(* errorf)(const char *str)
Definition: parser.c:88
#define PROV_IE_SUBNET
Definition: provision.h:23
#define IAX_IE_LANGUAGE
Definition: iax2.h:140
char * calling_number
Definition: parser.h:29
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
Socket address structure.
Definition: netsock2.h:97
int tm_year
Definition: localtime.h:41
#define IAX_IE_RR_JITTER
Definition: iax2.h:177
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:755
#define IAX_IE_CALLING_NUMBER
Definition: iax2.h:132
int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
Definition: parser.c:775
Implementation of the IAX2 protocol.
struct ast_frame_subclass subclass
#define IAX_IE_CALLING_ANI
Definition: iax2.h:133
static void dump_string_hex(char *output, int maxlen, void *value, int len)
Definition: parser.c:111
Utility functions.
static void dump_ipaddr(char *output, int maxlen, void *value, int len)
Definition: parser.c:189
static void dump_addr(char *output, int maxlen, void *value, int len)
Definition: parser.c:90
unsigned char type
Definition: iax2.h:236
#define IAX_IE_DEVICETYPE
Definition: iax2.h:162
#define IAX_IE_ENCRYPTION
Definition: iax2.h:173
#define IAX_IE_ENCKEY
Definition: iax2.h:174
int msgcount
Definition: parser.h:59
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:1065
unsigned short dcallno
Definition: iax2.h:232
Configuration File Parser.
char * called_context
Definition: parser.h:36
char * codec_prefs
Definition: parser.h:41
int iax_get_iframes(void)
Definition: parser.c:1350
char * challenge
Definition: parser.h:49
#define ast_log
Definition: astobj2.c:42
Handle unaligned data access.
int ie
Definition: parser.c:270
#define IAX_MAX_OSPBLOCK_NUM
Definition: iax2.h:193
unsigned int encmethods
Definition: parser.h:48
int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct ast_sockaddr *addr)
Definition: parser.c:741
unsigned short callno
Definition: parser.h:55
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
int provverpres
Definition: parser.h:74
unsigned char * calltokendata
Definition: parser.h:85
#define IAX_IE_FORMAT2
Definition: iax2.h:188
unsigned char causecode
Definition: parser.h:57
#define IAX_IE_CALLINGANI2
Definition: iax2.h:190
static void dump_short(char *output, int maxlen, void *value, int len)
Definition: parser.c:157
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
const char * src
#define DIRECTION_OUTGRESS
Definition: parser.h:89
#define ast_opt_cache_media_frames
Definition: options.h:121
unsigned int cacheable
Definition: parser.h:124
#define DIRECTION_INGRESS
Definition: parser.h:88
#define IAX_IE_CAUSECODE
Definition: iax2.h:172
int calling_ani2
Definition: parser.h:35
unsigned int rr_jitter
Definition: parser.h:75
#define IAX_IE_VERSION
Definition: iax2.h:141
#define PROV_IE_IPADDR
Definition: provision.h:22
static int frames
Definition: parser.c:51
unsigned char iax_unknown
Definition: parser.h:58
uint64_t htonll(uint64_t host64)
Definition: strcompat.c:390
#define PROV_IE_FORMAT
Definition: provision.h:33
char * osptokenblock[IAX_MAX_OSPBLOCK_NUM]
Definition: parser.h:82
#define IAX_IE_SERVICEIDENT
Definition: iax2.h:163
int tm_mon
Definition: localtime.h:40
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
Asterisk internal frame definitions.
void(* dump)(char *output, int maxlen, void *value, int len)
Definition: parser.c:272
#define IAX_IE_CALLING_NAME
Definition: iax2.h:134
union ast_frame::@250 data
int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
Definition: parser.c:726
size_t size
Definition: parser.c:71
#define IAX_IE_PROVISIONING
Definition: iax2.h:159
#define IAX_IE_AESPROVISIONING
Definition: iax2.h:160
int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value)
Definition: parser.c:746
#define PROV_IE_SERVERPORT
Definition: provision.h:36
unsigned short adsicpe
Definition: parser.h:44
#define ast_variable_new(name, value, filename)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
int tm_mday
Definition: localtime.h:39
AST_LIST_HEAD_NOLOCK(contactliststruct, contact)
#define IAX_IE_DNID
Definition: iax2.h:143
static unsigned int get_unaligned_uint32(const void *p)
Definition: unaligned.h:38
#define ARRAY_LEN(a)
Definition: utils.h:639
Network socket handling.
int version
Definition: parser.h:43
static unsigned short get_unaligned_uint16(const void *p)
Definition: unaligned.h:44
unsigned int direction
Definition: parser.h:122
char * iax_provflags2str(char *buf, int buflen, unsigned int flags)
Definition: provision.c:90
#define IAX_IE_CALLTOKEN
Definition: iax2.h:185
unsigned int rr_ooo
Definition: parser.h:80
static void internalerror(const char *str)
Definition: parser.c:82
#define IAX_IE_CALLED_NUMBER
Definition: iax2.h:131
int pos
Definition: parser.h:151
IAX2 Provisioning protocol.
#define PROV_IE_AESKEY
Definition: provision.h:34
#define IAX_IE_ADSICPE
Definition: iax2.h:142
static void dump_versioned_codec(char *output, int maxlen, void *value, int len)
Definition: parser.c:248
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static void dump_prov_flags(char *output, int maxlen, void *value, int len)
Definition: parser.c:211
Implementation of Inter-Asterisk eXchange, version 2 iax2-parser::c iax2-parser.h chan_iax2...
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static void dump_prov(char *output, int maxlen, void *value, int len)
Definition: parser.c:264
Media Format Bitfield Compatibility API.
void * data
Definition: parser.h:104
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
int calling_pres
Definition: parser.h:34
#define IAX_IE_AUTHMETHODS
Definition: iax2.h:144
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * language
Definition: parser.h:42
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define IAX_IE_PASSWORD
Definition: iax2.h:137
char * rdnis
Definition: parser.h:46
void iax_frame_free(struct iax_frame *fr)
Definition: parser.c:1295
#define IAX_IE_MSGCOUNT
Definition: iax2.h:154
void iax_set_error(void(*func)(const char *))
Definition: parser.c:790
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define IAX_IE_FWBLOCKDESC
Definition: iax2.h:165
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
char * calling_name
Definition: parser.h:31
uint64_t ntohll(uint64_t net64)
Definition: strcompat.c:364
int retries
Definition: parser.h:108
unsigned int authmethods
Definition: parser.h:47
#define IAX_IE_RR_OOO
Definition: iax2.h:182
#define ast_free(a)
Definition: astmm.h:182
int datalen
Definition: parser.h:106
unsigned char calltoken
Definition: parser.h:84
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static void put_unaligned_uint64(void *p, uint64_t datum)
Definition: unaligned.h:51
unsigned char iedata[0]
Definition: iax2.h:238
int autoanswer
Definition: parser.h:60
#define PROV_IE_PORTNO
Definition: provision.h:25
unsigned char iseqno
Definition: iax2.h:235
#define IAX_IE_CODEC_PREFS
Definition: iax2.h:175
char * called_number
Definition: parser.h:28
static void dump_datetime(char *output, int maxlen, void *value, int len)
Definition: parser.c:173
int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr)
Determine if this is an IPv4-mapped IPv6 address.
Definition: netsock2.c:507
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
int tm_hour
Definition: localtime.h:38
int retrans
Definition: parser.h:130
unsigned char buf[1024]
Definition: parser.h:150
#define IAX_IE_OSPTOKEN
Definition: iax2.h:184
unsigned char enckeylen
Definition: parser.h:71
struct timeval delivery
unsigned short rr_delay
Definition: parser.h:78
int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
Definition: parser.c:795
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
#define IAX_IE_CALLINGTON
Definition: iax2.h:169
int tm_sec
Definition: localtime.h:36
#define IAX_IE_REFRESH
Definition: iax2.h:149
struct ast_variable * vars
Definition: parser.h:81
#define IAX_IE_CALLINGPRES
Definition: iax2.h:168
#define PROV_IE_SERVERIP
Definition: provision.h:35
#define IAX_IE_RDNIS
Definition: iax2.h:158
int musiconhold
Definition: parser.h:61
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define IAX_IE_USERNAME
Definition: iax2.h:136
int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const char *str)
Definition: parser.c:770
#define IAX_IE_RR_DROPPED
Definition: iax2.h:181
#define PROV_IE_GATEWAY
Definition: provision.h:24
struct ast_sockaddr apparent_addr
Definition: parser.h:52
unsigned int rr_pkts
Definition: parser.h:77
#define IAX_IE_MUSICONHOLD
Definition: iax2.h:156
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
#define IAX_IE_RR_PKTS
Definition: iax2.h:179
Data structure associated with a single frame of data.
#define IAX_FLAG_FULL
Definition: iax2.h:40
#define IAX_IE_CAUSE
Definition: iax2.h:152
#define IAX_IE_RSA_RESULT
Definition: iax2.h:147
unsigned int ospblocklength[IAX_MAX_OSPBLOCK_NUM]
Definition: parser.h:83
#define PROV_IE_ALTSERVER
Definition: provision.h:39
char * password
Definition: parser.h:38
char * name
Definition: parser.c:271
#define IAX_IE_FWBLOCKDATA
Definition: iax2.h:166
char * calling_ani
Definition: parser.h:30
#define IAX_IE_CALLED_CONTEXT
Definition: iax2.h:135
int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value)
Definition: parser.c:763
#define IAX_RATE_16KHZ
Definition: iax2.h:212
void iax_set_output(void(*func)(const char *))
Definition: parser.c:785
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
enum ast_frame_type frametype
#define IAX_IE_APPARENT_ADDR
Definition: iax2.h:148
struct iax_frame_list list
Definition: parser.c:70
iax2_format capability
Definition: parser.h:39
Media Format Bitfield Compatibility API.
#define PROV_IE_TOS
Definition: provision.h:31
struct ast_format * format
unsigned short refresh
Definition: parser.h:53
#define IAX_IE_TRANSFERID
Definition: iax2.h:157
char * cause
Definition: parser.h:56
#define IAX_IE_FORMAT
Definition: iax2.h:139
direction
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
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
#define IAX_FLAG_RETRANS
Definition: iax2.h:42
#define IAX_RATE_11KHZ
Definition: iax2.h:211
#define PROV_IE_PASS
Definition: provision.h:27
static void internaloutput(const char *str)
Definition: parser.c:77
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
static void dump_string(char *output, int maxlen, void *value, int len)
Definition: parser.c:121
#define IAX_IE_CAPABILITY
Definition: iax2.h:138
#define IAX_RATE_8KHZ
Definition: iax2.h:210
static uint64_t get_unaligned_uint64(const void *p)
Definition: unaligned.h:32
int tm_min
Definition: localtime.h:37
#define PROV_IE_LANG
Definition: provision.h:30
char * dnid
Definition: parser.h:45
int64_t iax2_format
Definition: iax2.h:224
unsigned short samprate
Definition: parser.h:73
Media Format Cache API.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
unsigned int ts
Definition: iax2.h:233
#define PROV_IE_PROVVER
Definition: provision.h:38