1 /*
2 * Asterisk -- A telephony toolkit for Linux.
3 *
4 * Implementation of Inter-Asterisk eXchange
5 *
6 * Copyright (C) 2003-2004, Digium
7 *
8 * Mark Spencer <markster@digium.com>
9 *
10 * This program is free software, distributed under the terms of
11 * the GNU Lesser (Library) General Public License
12 */
13
14 #if defined(WIN32) || defined(_WIN32_WCE)
15 #include "winpoop.h"
16 #define snprintf _snprintf
17 #else
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #endif
23
24 #ifndef _MSC_VER
25 #include <unistd.h>
26 #endif
27
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #include "frame.h"
33 #include "iax2.h"
34 #include "iax2-parser.h"
35
36 static int frames = 0;
37 static int iframes = 0;
38 static int oframes = 0;
39
40 #ifdef ALIGN32
get_uint32(unsigned char * p)41 static unsigned int get_uint32(unsigned char *p)
42 {
43 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
44 }
45
get_uint16(unsigned char * p)46 static unsigned short get_uint16(unsigned char *p)
47 {
48 return (p[0] << 8) | p[1] ;
49 }
50
51 #else
52 #define get_uint32(p) (*((unsigned int *)(p)))
53 #define get_uint16(p) (*((unsigned short *)(p)))
54 #endif
55
56
internaloutput(const char * str)57 static void internaloutput(const char *str)
58 {
59 //printf(str);
60 }
61
internalerror(const char * str)62 static void internalerror(const char *str)
63 {
64 fprintf(stderr, "WARNING: %s", str);
65 }
66
67 static void (*outputf)(const char *str) = internaloutput;
68 static void (*errorf)(const char *str) = internalerror;
69
dump_addr(char * output,int maxlen,void * value,int len)70 static void dump_addr(char *output, int maxlen, void *value, int len)
71 {
72 struct sockaddr_in sin;
73 if (len == sizeof(sin)) {
74 memcpy(&sin, value, len);
75 snprintf(output, maxlen, "IPV4 %s:%d", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
76 } else {
77 snprintf(output, maxlen, "Invalid Address");
78 }
79 }
80
dump_string(char * output,int maxlen,void * value,int len)81 static void dump_string(char *output, int maxlen, void *value, int len)
82 {
83 maxlen--;
84 if (maxlen > len)
85 maxlen = len;
86 strncpy(output,(const char *)value, maxlen);
87 output[maxlen] = '\0';
88 }
89
dump_int(char * output,int maxlen,void * value,int len)90 static void dump_int(char *output, int maxlen, void *value, int len)
91 {
92 if (len == (int)sizeof(unsigned int))
93 snprintf(output, maxlen, "%lu", (unsigned long)ntohl(get_uint32(value)));
94 else
95 snprintf(output, maxlen, "Invalid INT");
96 }
97
dump_short(char * output,int maxlen,void * value,int len)98 static void dump_short(char *output, int maxlen, void *value, int len)
99 {
100 if (len == (int)sizeof(unsigned short))
101 snprintf(output, maxlen, "%d", ntohs(get_uint16(value)));
102 else
103 snprintf(output, maxlen, "Invalid SHORT");
104 }
105
dump_byte(char * output,int maxlen,void * value,int len)106 static void dump_byte(char *output, int maxlen, void *value, int len)
107 {
108 if (len == (int)sizeof(unsigned char))
109 snprintf(output, maxlen, "%d", *((unsigned char *)value));
110 else
111 snprintf(output, maxlen, "Invalid BYTE");
112 }
113
dump_samprate(char * output,int maxlen,void * value,int len)114 static void dump_samprate(char *output, int maxlen, void *value, int len)
115 {
116 char tmp[256]="";
117 int sr;
118 if (len == (int)sizeof(unsigned short)) {
119 sr = ntohs(*((unsigned short *)value));
120 if (sr & IAX_RATE_8KHZ)
121 strcat(tmp, ",8khz");
122 if (sr & IAX_RATE_11KHZ)
123 strcat(tmp, ",11.025khz");
124 if (sr & IAX_RATE_16KHZ)
125 strcat(tmp, ",16khz");
126 if (sr & IAX_RATE_22KHZ)
127 strcat(tmp, ",22.05khz");
128 if (sr & IAX_RATE_44KHZ)
129 strcat(tmp, ",44.1khz");
130 if (sr & IAX_RATE_48KHZ)
131 strcat(tmp, ",48khz");
132 if (strlen(tmp))
133 strncpy(output, &tmp[1], maxlen - 1);
134 else
135 strncpy(output, "None specified!\n", maxlen - 1);
136 } else
137 snprintf(output, maxlen, "Invalid SHORT");
138
139 }
140
141 static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len);
dump_prov(char * output,int maxlen,void * value,int len)142 static void dump_prov(char *output, int maxlen, void *value, int len)
143 {
144 dump_prov_ies(output, maxlen, (unsigned char *)value, len);
145 }
146
147 static struct iax2_ie {
148 int ie;
149 char *name;
150 void (*dump)(char *output, int maxlen, void *value, int len);
151 } ies[] = {
152 { IAX_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
153 { IAX_IE_CALLING_NUMBER, "CALLING NUMBER", dump_string },
154 { IAX_IE_CALLING_ANI, "ANI", dump_string },
155 { IAX_IE_CALLING_NAME, "CALLING NAME", dump_string },
156 { IAX_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
157 { IAX_IE_USERNAME, "USERNAME", dump_string },
158 { IAX_IE_PASSWORD, "PASSWORD", dump_string },
159 { IAX_IE_CAPABILITY, "CAPABILITY", dump_int },
160 { IAX_IE_FORMAT, "FORMAT", dump_int },
161 { IAX_IE_LANGUAGE, "LANGUAGE", dump_string },
162 { IAX_IE_VERSION, "VERSION", dump_short },
163 { IAX_IE_ADSICPE, "ADSICPE", dump_short },
164 { IAX_IE_DNID, "DNID", dump_string },
165 { IAX_IE_AUTHMETHODS, "AUTHMETHODS", dump_short },
166 { IAX_IE_CHALLENGE, "CHALLENGE", dump_string },
167 { IAX_IE_MD5_RESULT, "MD5 RESULT", dump_string },
168 { IAX_IE_RSA_RESULT, "RSA RESULT", dump_string },
169 { IAX_IE_APPARENT_ADDR, "APPARENT ADDRESS", dump_addr },
170 { IAX_IE_REFRESH, "REFRESH", dump_short },
171 { IAX_IE_DPSTATUS, "DIALPLAN STATUS", dump_short },
172 { IAX_IE_CALLNO, "CALL NUMBER", dump_short },
173 { IAX_IE_CAUSE, "CAUSE", dump_string },
174 { IAX_IE_IAX_UNKNOWN, "UNKNOWN IAX CMD", dump_byte },
175 { IAX_IE_MSGCOUNT, "MESSAGE COUNT", dump_short },
176 { IAX_IE_AUTOANSWER, "AUTO ANSWER REQ" },
177 { IAX_IE_TRANSFERID, "TRANSFER ID", dump_int },
178 { IAX_IE_RDNIS, "REFERRING DNIS", dump_string },
179 { IAX_IE_PROVISIONING, "PROVISIONING", dump_prov },
180 { IAX_IE_AESPROVISIONING, "AES PROVISIONG" },
181 { IAX_IE_DATETIME, "DATE TIME", dump_int },
182 { IAX_IE_DEVICETYPE, "DEVICE TYPE", dump_string },
183 { IAX_IE_SERVICEIDENT, "SERVICE IDENT", dump_string },
184 { IAX_IE_FIRMWAREVER, "FIRMWARE VER", dump_short },
185 { IAX_IE_FWBLOCKDESC, "FW BLOCK DESC", dump_int },
186 { IAX_IE_FWBLOCKDATA, "FW BLOCK DATA" },
187 { IAX_IE_PROVVER, "PROVISIONG VER", dump_int },
188 { IAX_IE_CALLINGPRES, "CALLING PRESNTN", dump_byte },
189 { IAX_IE_CALLINGTON, "CALLING TYPEOFNUM", dump_byte },
190 { IAX_IE_CALLINGTNS, "CALLING TRANSITNET", dump_short },
191 { IAX_IE_SAMPLINGRATE, "SAMPLINGRATE", dump_samprate },
192 { IAX_IE_CODEC_PREFS, "CODEC_PREFS", dump_string },
193 { IAX_IE_RR_JITTER, "RR_JITTER", dump_int },
194 { IAX_IE_RR_LOSS, "RR_LOSS", dump_int },
195 { IAX_IE_RR_PKTS, "RR_PKTS", dump_int },
196 { IAX_IE_RR_DELAY, "RR_DELAY", dump_short },
197 { IAX_IE_RR_DROPPED, "RR_DROPPED", dump_int },
198 { IAX_IE_RR_OOO, "RR_OOO", dump_int },
199 };
200
iax_ie2str(int ie)201 const char *iax_ie2str(int ie)
202 {
203 int x;
204 for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
205 if (ies[x].ie == ie)
206 return ies[x].name;
207 }
208 return "Unknown IE";
209 }
210
211
dump_prov_ies(char * output,int maxlen,unsigned char * iedata,int len)212 static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len)
213 {
214 int ielen;
215 int ie;
216 int found;
217 char tmp[256];
218 if (len < 2)
219 return;
220 strcpy(output, "\n");
221 maxlen -= (int)strlen(output); output += strlen(output);
222 while(len > 2) {
223 ie = iedata[0];
224 ielen = iedata[1];
225 if (ielen + 2> len) {
226 snprintf(tmp, (int)sizeof(tmp), "Total Prov IE length of %d bytes exceeds remaining prov frame length of %d bytes\n", ielen + 2, len);
227 strncpy(output, tmp, maxlen - 1);
228 maxlen -= (int)strlen(output); output += strlen(output);
229 return;
230 }
231 found = 0;
232 if (!found) {
233 snprintf(tmp, (int)sizeof(tmp), " Unknown Prov IE %03d : Present\n", ie);
234 strncpy(output, tmp, maxlen - 1);
235 maxlen -= (int)strlen(output); output += strlen(output);
236 }
237 iedata += (2 + ielen);
238 len -= (2 + ielen);
239 }
240 }
241
dump_ies(unsigned char * iedata,int len)242 static void dump_ies(unsigned char *iedata, int len)
243 {
244 int ielen;
245 int ie;
246 int x;
247 int found;
248 char interp[1024];
249 char tmp[1024];
250 if (len < 2)
251 return;
252 while(len > 2) {
253 ie = iedata[0];
254 ielen = iedata[1];
255 if (ielen + 2> len) {
256 snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
257 outputf(tmp);
258 return;
259 }
260 found = 0;
261 for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
262 if (ies[x].ie == ie) {
263 if (ies[x].dump) {
264 ies[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
265 snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", ies[x].name, interp);
266 outputf(tmp);
267 } else {
268 if (ielen)
269 snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
270 else
271 strcpy(interp, "Present");
272 snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", ies[x].name, interp);
273 outputf(tmp);
274 }
275 found++;
276 }
277 }
278 if (!found) {
279 snprintf(tmp, (int)sizeof(tmp), " Unknown IE %03d : Present\n", ie);
280 outputf(tmp);
281 }
282 iedata += (2 + ielen);
283 len -= (2 + ielen);
284 }
285 outputf("\n");
286 }
287
iax_showframe(struct iax_frame * f,struct ast_iax2_full_hdr * fhi,int rx,struct sockaddr_in * sin,int datalen)288 void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
289 {
290 const char *frames[] = {
291 "(0?)",
292 "DTMF ",
293 "VOICE ",
294 "VIDEO ",
295 "CONTROL",
296 "NULL ",
297 "IAX ",
298 "TEXT ",
299 "IMAGE " };
300 const char *iaxs[] = {
301 "(0?)",
302 "NEW ",
303 "PING ",
304 "PONG ",
305 "ACK ",
306 "HANGUP ",
307 "REJECT ",
308 "ACCEPT ",
309 "AUTHREQ",
310 "AUTHREP",
311 "INVAL ",
312 "LAGRQ ",
313 "LAGRP ",
314 "REGREQ ",
315 "REGAUTH",
316 "REGACK ",
317 "REGREJ ",
318 "REGREL ",
319 "VNAK ",
320 "DPREQ ",
321 "DPREP ",
322 "DIAL ",
323 "TXREQ ",
324 "TXCNT ",
325 "TXACC ",
326 "TXREADY",
327 "TXREL ",
328 "TXREJ ",
329 "QUELCH ",
330 "UNQULCH",
331 "POKE",
332 "PAGE",
333 "MWI",
334 "UNSUPPORTED",
335 "TRANSFER",
336 "PROVISION",
337 "FWDOWNLD",
338 "FWDATA"
339 };
340 const char *cmds[] = {
341 "(0?)",
342 "HANGUP ",
343 "RING ",
344 "RINGING",
345 "ANSWER ",
346 "BUSY ",
347 "TKOFFHK ",
348 "OFFHOOK ",
349 "CONGESTION ",
350 "FLASH ",
351 "WINK ",
352 "OPTION "
353 };
354 struct ast_iax2_full_hdr *fh;
355 char retries[20];
356 char class2[20];
357 char subclass2[20];
358 const char *clas;
359 const char *subclass;
360 char tmp[256];
361
362 if (f) {
363 fh = (struct ast_iax2_full_hdr *)f->data;
364 snprintf(retries, (int)sizeof(retries), "%03d", f->retries);
365 } else {
366 fh = fhi;
367 if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS)
368 strcpy(retries, "Yes");
369 else
370 strcpy(retries, " No");
371 }
372 if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) {
373 /* Don't mess with mini-frames */
374 return;
375 }
376 if (fh->type >= (int)(sizeof(frames)/sizeof(char *))) {
377 snprintf(class2, (int)sizeof(class2), "(%d?)", fh->type);
378 clas = class2;
379 } else {
380 clas = frames[(int)fh->type];
381 }
382 if (fh->type == AST_FRAME_DTMF) {
383 sprintf(subclass2, "%c", fh->csub);
384 subclass = subclass2;
385 } else if (fh->type == AST_FRAME_IAX) {
386 if (fh->csub >= (int)sizeof(iaxs)/(int)sizeof(iaxs[0])) {
387 snprintf(subclass2, (int)sizeof(subclass2), "(%d?)", fh->csub);
388 subclass = subclass2;
389 } else {
390 subclass = iaxs[(int)fh->csub];
391 }
392 } else if (fh->type == AST_FRAME_CONTROL) {
393 if (fh->csub >= (int)(sizeof(cmds)/sizeof(char *))) {
394 snprintf(subclass2, (int)sizeof(subclass2), "(%d?)", fh->csub);
395 subclass = subclass2;
396 } else {
397 subclass = cmds[(int)fh->csub];
398 }
399 } else {
400 snprintf(subclass2, (int)sizeof(subclass2), "%d", fh->csub);
401 subclass = subclass2;
402 }
403 snprintf(tmp, (int)sizeof(tmp),
404 "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
405 (rx ? "Rx" : "Tx"),
406 retries, fh->oseqno, fh->iseqno, clas, subclass);
407 outputf(tmp);
408 snprintf(tmp, (int)sizeof(tmp),
409 " Timestamp: %05lums SCall: %5.5d DCall: %5.5d [%s:%d]\n",
410 (unsigned long)ntohl(fh->ts),
411 ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
412 inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
413 outputf(tmp);
414 if (fh->type == AST_FRAME_IAX)
415 dump_ies(fh->iedata, datalen);
416 }
417
iax_ie_append_raw(struct iax_ie_data * ied,unsigned char ie,const void * data,int datalen)418 int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
419 {
420 char tmp[256];
421 if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
422 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);
423 errorf(tmp);
424 return -1;
425 }
426 ied->buf[ied->pos++] = ie;
427 ied->buf[ied->pos++] = datalen;
428 memcpy(ied->buf + ied->pos, data, datalen);
429 ied->pos += datalen;
430 return 0;
431 }
432
iax_ie_append_addr(struct iax_ie_data * ied,unsigned char ie,struct sockaddr_in * sin)433 int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
434 {
435 return iax_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
436 }
437
iax_ie_append_int(struct iax_ie_data * ied,unsigned char ie,unsigned int value)438 int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value)
439 {
440 unsigned int newval;
441 newval = htonl(value);
442 return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
443 }
444
iax_ie_append_short(struct iax_ie_data * ied,unsigned char ie,unsigned short value)445 int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value)
446 {
447 unsigned short newval;
448 newval = htons(value);
449 return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
450 }
451
iax_ie_append_str(struct iax_ie_data * ied,unsigned char ie,const char * str)452 int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const char *str)
453 {
454 return iax_ie_append_raw(ied, ie, str, (int)strlen(str));
455 }
456
iax_ie_append_byte(struct iax_ie_data * ied,unsigned char ie,unsigned char dat)457 int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
458 {
459 return iax_ie_append_raw(ied, ie, &dat, 1);
460 }
461
iax_ie_append(struct iax_ie_data * ied,unsigned char ie)462 int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
463 {
464 return iax_ie_append_raw(ied, ie, NULL, 0);
465 }
466
iax_set_output(void (* func)(const char *))467 void iax_set_output(void (*func)(const char *))
468 {
469 outputf = func;
470 }
471
iax_set_error(void (* func)(const char *))472 void iax_set_error(void (*func)(const char *))
473 {
474 errorf = func;
475 }
476
iax_parse_ies(struct iax_ies * ies,unsigned char * data,int datalen)477 int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
478 {
479 /* Parse data into information elements */
480 int len;
481 int ie;
482 char tmp[256];
483 memset(ies, 0, (int)sizeof(struct iax_ies));
484 ies->msgcount = -1;
485 ies->firmwarever = -1;
486 ies->calling_ton = -1;
487 ies->calling_tns = -1;
488 ies->calling_pres = -1;
489 ies->samprate = IAX_RATE_8KHZ;
490 while(datalen >= 2) {
491 ie = data[0];
492 len = data[1];
493 if (len > datalen - 2) {
494 errorf("Information element length exceeds message size\n");
495 return -1;
496 }
497 switch(ie) {
498 case IAX_IE_CALLED_NUMBER:
499 ies->called_number = (char *) data + 2;
500 break;
501 case IAX_IE_CALLING_NUMBER:
502 ies->calling_number = (char *) data + 2;
503 break;
504 case IAX_IE_CALLING_ANI:
505 ies->calling_ani = (char *) data + 2;
506 break;
507 case IAX_IE_CALLING_NAME:
508 ies->calling_name = (char *) data + 2;
509 break;
510 case IAX_IE_CALLED_CONTEXT:
511 ies->called_context = (char *) data + 2;
512 break;
513 case IAX_IE_USERNAME:
514 ies->username = (char *) data + 2;
515 break;
516 case IAX_IE_PASSWORD:
517 ies->password = (char *) data + 2;
518 break;
519 case IAX_IE_CAPABILITY:
520 if (len != (int)sizeof(unsigned int)) {
521 snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
522 errorf(tmp);
523 } else
524 ies->capability = ntohl(get_uint32(data + 2));
525 break;
526 case IAX_IE_FORMAT:
527 if (len != (int)sizeof(unsigned int)) {
528 snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
529 errorf(tmp);
530 } else
531 ies->format = ntohl(get_uint32(data + 2));
532 break;
533 case IAX_IE_LANGUAGE:
534 ies->language = (char *) data + 2;
535 break;
536 case IAX_IE_CODEC_PREFS:
537 ies->codec_prefs = (char *) data + 2;
538 break;
539 case IAX_IE_VERSION:
540 if (len != (int)sizeof(unsigned short)) {
541 snprintf(tmp, (int)sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
542 errorf(tmp);
543 } else
544 ies->version = ntohs(get_uint16(data + 2));
545 break;
546 case IAX_IE_ADSICPE:
547 if (len != (int)sizeof(unsigned short)) {
548 snprintf(tmp, (int)sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
549 errorf(tmp);
550 } else
551 ies->adsicpe = ntohs(get_uint16(data + 2));
552 break;
553 case IAX_IE_SAMPLINGRATE:
554 if (len != (int)sizeof(unsigned short)) {
555 snprintf(tmp, (int)sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
556 errorf(tmp);
557 } else
558 ies->samprate = ntohs(get_uint16(data + 2));
559 break;
560 case IAX_IE_DNID:
561 ies->dnid = (char *) data + 2;
562 break;
563 case IAX_IE_RDNIS:
564 ies->rdnis = (char *) data + 2;
565 break;
566 case IAX_IE_AUTHMETHODS:
567 if (len != (int)sizeof(unsigned short)) {
568 snprintf(tmp, (int)sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
569 errorf(tmp);
570 } else
571 ies->authmethods = ntohs(get_uint16(data + 2));
572 break;
573 case IAX_IE_CHALLENGE:
574 ies->challenge = (char *) data + 2;
575 break;
576 case IAX_IE_MD5_RESULT:
577 ies->md5_result = (char *) data + 2;
578 break;
579 case IAX_IE_RSA_RESULT:
580 ies->rsa_result = (char *) data + 2;
581 break;
582 case IAX_IE_APPARENT_ADDR:
583 ies->apparent_addr = ((struct sockaddr_in *)(data + 2));
584 break;
585 case IAX_IE_REFRESH:
586 if (len != (int)sizeof(unsigned short)) {
587 snprintf(tmp, (int)sizeof(tmp), "Expecting refresh to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
588 errorf(tmp);
589 } else
590 ies->refresh = ntohs(get_uint16(data + 2));
591 break;
592 case IAX_IE_DPSTATUS:
593 if (len != (int)sizeof(unsigned short)) {
594 snprintf(tmp, (int)sizeof(tmp), "Expecting dpstatus to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
595 errorf(tmp);
596 } else
597 ies->dpstatus = ntohs(get_uint16(data + 2));
598 break;
599 case IAX_IE_CALLNO:
600 if (len != (int)sizeof(unsigned short)) {
601 snprintf(tmp, (int)sizeof(tmp), "Expecting callno to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
602 errorf(tmp);
603 } else
604 ies->callno = ntohs(get_uint16(data + 2));
605 break;
606 case IAX_IE_CAUSE:
607 ies->cause = (char *) data + 2;
608 break;
609 case IAX_IE_CAUSECODE:
610 if (len != 1) {
611 snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
612 errorf(tmp);
613 } else {
614 ies->causecode = data[2];
615 }
616 break;
617 case IAX_IE_IAX_UNKNOWN:
618 if (len == 1)
619 ies->iax_unknown = data[2];
620 else {
621 snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
622 errorf(tmp);
623 }
624 break;
625 case IAX_IE_MSGCOUNT:
626 if (len != (int)sizeof(unsigned short)) {
627 snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
628 errorf(tmp);
629 } else
630 ies->msgcount = ntohs(get_uint16(data + 2));
631 break;
632 case IAX_IE_AUTOANSWER:
633 ies->autoanswer = 1;
634 break;
635 case IAX_IE_MUSICONHOLD:
636 ies->musiconhold = 1;
637 break;
638 case IAX_IE_TRANSFERID:
639 if (len != (int)sizeof(unsigned int)) {
640 snprintf(tmp, (int)sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
641 errorf(tmp);
642 } else
643 ies->transferid = ntohl(get_uint32(data + 2));
644 break;
645 case IAX_IE_DATETIME:
646 if (len != (int)sizeof(unsigned int)) {
647 snprintf(tmp, (int)sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
648 errorf(tmp);
649 } else
650 ies->datetime = ntohl(get_uint32(data + 2));
651 break;
652 case IAX_IE_FIRMWAREVER:
653 if (len != (int)sizeof(unsigned short)) {
654 snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
655 errorf(tmp);
656 } else
657 ies->firmwarever = ntohs(get_uint16(data + 2));
658 break;
659 case IAX_IE_DEVICETYPE:
660 ies->devicetype = (char *) data + 2;
661 break;
662 case IAX_IE_SERVICEIDENT:
663 ies->serviceident = (char *) data + 2;
664 break;
665 case IAX_IE_FWBLOCKDESC:
666 if (len != (int)sizeof(unsigned int)) {
667 snprintf(tmp, (int)sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
668 errorf(tmp);
669 } else
670 ies->fwdesc = ntohl(get_uint32(data + 2));
671 break;
672 case IAX_IE_FWBLOCKDATA:
673 ies->fwdata = data + 2;
674 ies->fwdatalen = len;
675 break;
676 case IAX_IE_PROVVER:
677 if (len != (int)sizeof(unsigned int)) {
678 snprintf(tmp, (int)sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
679 errorf(tmp);
680 } else {
681 ies->provverpres = 1;
682 ies->provver = ntohl(get_uint32(data + 2));
683 }
684 break;
685 case IAX_IE_CALLINGPRES:
686 if (len == 1)
687 ies->calling_pres = data[2];
688 else {
689 snprintf(tmp, (int)sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len);
690 errorf(tmp);
691 }
692 break;
693 case IAX_IE_CALLINGTON:
694 if (len == 1)
695 ies->calling_ton = data[2];
696 else {
697 snprintf(tmp, (int)sizeof(tmp), "Expected single byte callington, but was %d long\n", len);
698 errorf(tmp);
699 }
700 break;
701 case IAX_IE_CALLINGTNS:
702 if (len != (int)sizeof(unsigned short)) {
703 snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
704 errorf(tmp);
705 } else
706 ies->calling_tns = ntohs(get_uint16(data + 2));
707 break;
708 case IAX_IE_RR_JITTER:
709 if (len != (int)sizeof(unsigned int)) {
710 snprintf(tmp, (int)sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
711 errorf(tmp);
712 } else {
713 ies->rr_jitter = ntohl(get_uint32(data + 2));
714 }
715 break;
716 case IAX_IE_RR_LOSS:
717 if (len != (int)sizeof(unsigned int)) {
718 snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
719 errorf(tmp);
720 } else {
721 ies->rr_loss = ntohl(get_uint32(data + 2));
722 }
723 break;
724 case IAX_IE_RR_PKTS:
725 if (len != (int)sizeof(unsigned int)) {
726 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
727 errorf(tmp);
728 } else {
729 ies->rr_pkts = ntohl(get_uint32(data + 2));
730 }
731 break;
732 case IAX_IE_RR_DELAY:
733 if (len != (int)sizeof(unsigned short)) {
734 snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
735 errorf(tmp);
736 } else {
737 ies->rr_delay = ntohs(get_uint16(data + 2));
738 }
739 break;
740 case IAX_IE_RR_DROPPED:
741 if (len != (int)sizeof(unsigned int)) {
742 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
743 errorf(tmp);
744 } else {
745 ies->rr_dropped = ntohl(get_uint32(data + 2));
746 }
747 break;
748 case IAX_IE_RR_OOO:
749 if (len != (int)sizeof(unsigned int)) {
750 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
751 errorf(tmp);
752 } else {
753 ies->rr_ooo = ntohl(get_uint32(data + 2));
754 }
755 break;
756 default:
757 snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
758 outputf(tmp);
759 }
760 /* Overwrite information element with 0, to null terminate previous portion */
761 data[0] = 0;
762 datalen -= (len + 2);
763 data += (len + 2);
764 }
765 /* Null-terminate last field */
766 *data = '\0';
767 if (datalen) {
768 errorf("Invalid information element contents, strange boundary\n");
769 return -1;
770 }
771 return 0;
772 }
773
iax_frame_wrap(struct iax_frame * fr,struct ast_frame * f)774 void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
775 {
776 fr->af.frametype = f->frametype;
777 fr->af.subclass = f->subclass;
778 fr->af.mallocd = 0; /* Our frame is static relative to the container */
779 fr->af.datalen = f->datalen;
780 fr->af.samples = f->samples;
781 fr->af.offset = AST_FRIENDLY_OFFSET;
782 fr->af.src = f->src;
783 fr->af.data = fr->afdata;
784 if (fr->af.datalen)
785 memcpy(fr->af.data, f->data, fr->af.datalen);
786 }
787
iax_frame_new(int direction,int datalen)788 struct iax_frame *iax_frame_new(int direction, int datalen)
789 {
790 struct iax_frame *fr;
791 fr = (struct iax_frame *)malloc((int)sizeof(struct iax_frame) + datalen);
792 if (fr) {
793 fr->direction = direction;
794 fr->retrans = -1;
795 frames++;
796 if (fr->direction == DIRECTION_INGRESS)
797 iframes++;
798 else
799 oframes++;
800 }
801 return fr;
802 }
803
iax_frame_free(struct iax_frame * fr)804 void iax_frame_free(struct iax_frame *fr)
805 {
806 /* Note: does not remove from scheduler! */
807 if (fr->direction == DIRECTION_INGRESS)
808 iframes--;
809 else if (fr->direction == DIRECTION_OUTGRESS)
810 oframes--;
811 else {
812 errorf("Attempt to double free frame detected\n");
813 return;
814 }
815 fr->direction = 0;
816 free(fr);
817 frames--;
818 }
819
iax_get_frames(void)820 int iax_get_frames(void) { return frames; }
iax_get_iframes(void)821 int iax_get_iframes(void) { return iframes; }
iax_get_oframes(void)822 int iax_get_oframes(void) { return oframes; }
823