Asterisk - The Open Source Telephony Project GIT-master-a358458
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 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;
826 ies->calling_ani = (char *)data + 2;
827 break;
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;
841 ies->codec_prefs = (char *)data + 2;
842 break;
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;
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;
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;
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;
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;
933 ies->md5_result = (char *)data + 2;
934 break;
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;
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;
990 ies->autoanswer = 1;
991 break;
993 ies->musiconhold = 1;
994 break;
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;
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, sizeof(tmp), "Expected callingani2 to be %zu bytes but was %d\n", sizeof(unsigned int), len);
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);
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
1195void 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;
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
1228struct 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 */
1239 smallest = AST_LIST_FIRST(&iax_frames->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
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
1316 ast_free(fr);
1317 return;
1318 }
1319
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) {
1326 } else {
1328 }
1329 iax_frames->size++;
1330 return;
1331 }
1332#endif
1333 ast_free(fr);
1334}
1335
1336#if !defined(NO_FRAME_CACHE)
1337static 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)))
1344
1345 ast_free(framelist);
1346}
1347#endif
1348
1349int iax_get_frames(void) { return frames; }
1350int iax_get_iframes(void) { return iframes; }
1351int iax_get_oframes(void) { return oframes; }
const char * str
Definition: app_jack.c:147
#define var
Definition: ast_expr2f.c:605
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
static int tmp()
Definition: bt_open.c:389
const char * iax2_getformatname(iax2_format format)
iax2 wrapper function for ast_getformatname
Definition: chan_iax2.c:1950
static const char type[]
Definition: chan_ooh323.c:109
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
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.
Definition: format_cache.c:41
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
uint64_t ntohll(uint64_t net64)
Definition: strcompat.c:364
uint64_t htonll(uint64_t host64)
Definition: strcompat.c:390
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_VOICE
@ 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).
Definition: linkedlists.h:225
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
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:757
size_t current
Definition: main/cli.c:113
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:121
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:1350
static struct ast_threadstorage frame_cache
Definition: parser.c:63
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:1295
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:1228
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:1351
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:1195
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:1337
static struct iax2_ie infoelts[]
Definition: parser.c:274
int iax_get_frames(void)
Definition: parser.c:1349
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
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#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
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
union ast_frame::@226 data
struct timeval delivery
enum ast_frame_type frametype
const char * src
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::@139 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
int pos
Definition: parser.h:151
unsigned char buf[1024]
Definition: parser.h:150
Definition: parser.h:27
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
Definition: ast_expr2.c:325
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:666