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