00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <sys/types.h>
00026 #include <sys/socket.h>
00027 #include <string.h>
00028 #include <netinet/in.h>
00029 #include <arpa/inet.h>
00030 #include <unistd.h>
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00037
00038 #include "asterisk/frame.h"
00039 #include "asterisk/utils.h"
00040 #include "asterisk/unaligned.h"
00041 #include "iax2.h"
00042 #include "iax2-parser.h"
00043 #include "iax2-provision.h"
00044
00045 static int frames = 0;
00046 static int iframes = 0;
00047 static int oframes = 0;
00048
00049 static void internaloutput(const char *str)
00050 {
00051 fputs(str, stdout);
00052 }
00053
00054 static void internalerror(const char *str)
00055 {
00056 fprintf(stderr, "WARNING: %s", str);
00057 }
00058
00059 static void (*outputf)(const char *str) = internaloutput;
00060 static void (*errorf)(const char *str) = internalerror;
00061
00062 static void dump_addr(char *output, int maxlen, void *value, int len)
00063 {
00064 struct sockaddr_in sin;
00065 char iabuf[INET_ADDRSTRLEN];
00066 if (len == (int)sizeof(sin)) {
00067 memcpy(&sin, value, len);
00068 snprintf(output, maxlen, "IPV4 %s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
00069 } else {
00070 snprintf(output, maxlen, "Invalid Address");
00071 }
00072 }
00073
00074 static void dump_string(char *output, int maxlen, void *value, int len)
00075 {
00076 maxlen--;
00077 if (maxlen > len)
00078 maxlen = len;
00079 strncpy(output, value, maxlen);
00080 output[maxlen] = '\0';
00081 }
00082
00083 static void dump_prefs(char *output, int maxlen, void *value, int len)
00084 {
00085 struct ast_codec_pref pref;
00086 int total_len = 0;
00087
00088 maxlen--;
00089 total_len = maxlen;
00090
00091 if (maxlen > len)
00092 maxlen = len;
00093
00094 strncpy(output, value, maxlen);
00095 output[maxlen] = '\0';
00096
00097 ast_codec_pref_convert(&pref, output, total_len, 0);
00098 memset(output,0,total_len);
00099 ast_codec_pref_string(&pref, output, total_len);
00100 }
00101
00102 static void dump_int(char *output, int maxlen, void *value, int len)
00103 {
00104 if (len == (int)sizeof(unsigned int))
00105 snprintf(output, maxlen, "%lu", (unsigned long)ntohl(get_unaligned_uint32(value)));
00106 else
00107 ast_copy_string(output, "Invalid INT", maxlen);
00108 }
00109
00110 static void dump_short(char *output, int maxlen, void *value, int len)
00111 {
00112 if (len == (int)sizeof(unsigned short))
00113 snprintf(output, maxlen, "%d", ntohs(get_unaligned_uint16(value)));
00114 else
00115 ast_copy_string(output, "Invalid SHORT", maxlen);
00116 }
00117
00118 static void dump_byte(char *output, int maxlen, void *value, int len)
00119 {
00120 if (len == (int)sizeof(unsigned char))
00121 snprintf(output, maxlen, "%d", *((unsigned char *)value));
00122 else
00123 ast_copy_string(output, "Invalid BYTE", maxlen);
00124 }
00125
00126 static void dump_datetime(char *output, int maxlen, void *value, int len)
00127 {
00128 struct tm tm;
00129 unsigned long val = (unsigned long) ntohl(get_unaligned_uint32(value));
00130 if (len == (int)sizeof(unsigned int)) {
00131 tm.tm_sec = (val & 0x1f) << 1;
00132 tm.tm_min = (val >> 5) & 0x3f;
00133 tm.tm_hour = (val >> 11) & 0x1f;
00134 tm.tm_mday = (val >> 16) & 0x1f;
00135 tm.tm_mon = ((val >> 21) & 0x0f) - 1;
00136 tm.tm_year = ((val >> 25) & 0x7f) + 100;
00137 strftime(output, maxlen, "%Y-%m-%d %T", &tm);
00138 } else
00139 ast_copy_string(output, "Invalid DATETIME format!", maxlen);
00140 }
00141
00142 static void dump_ipaddr(char *output, int maxlen, void *value, int len)
00143 {
00144 struct sockaddr_in sin;
00145 char iabuf[INET_ADDRSTRLEN];
00146 if (len == (int)sizeof(unsigned int)) {
00147 memcpy(&sin.sin_addr, value, len);
00148 ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr);
00149 snprintf(output, maxlen, "%s", iabuf);
00150 } else
00151 ast_copy_string(output, "Invalid IPADDR", maxlen);
00152 }
00153
00154
00155 static void dump_prov_flags(char *output, int maxlen, void *value, int len)
00156 {
00157 char buf[256] = "";
00158 if (len == (int)sizeof(unsigned int))
00159 snprintf(output, maxlen, "%lu (%s)", (unsigned long)ntohl(get_unaligned_uint32(value)),
00160 iax_provflags2str(buf, sizeof(buf), ntohl(get_unaligned_uint32(value))));
00161 else
00162 ast_copy_string(output, "Invalid INT", maxlen);
00163 }
00164
00165 static void dump_samprate(char *output, int maxlen, void *value, int len)
00166 {
00167 char tmp[256]="";
00168 int sr;
00169 if (len == (int)sizeof(unsigned short)) {
00170 sr = ntohs(*((unsigned short *)value));
00171 if (sr & IAX_RATE_8KHZ)
00172 strcat(tmp, ",8khz");
00173 if (sr & IAX_RATE_11KHZ)
00174 strcat(tmp, ",11.025khz");
00175 if (sr & IAX_RATE_16KHZ)
00176 strcat(tmp, ",16khz");
00177 if (sr & IAX_RATE_22KHZ)
00178 strcat(tmp, ",22.05khz");
00179 if (sr & IAX_RATE_44KHZ)
00180 strcat(tmp, ",44.1khz");
00181 if (sr & IAX_RATE_48KHZ)
00182 strcat(tmp, ",48khz");
00183 if (strlen(tmp))
00184 ast_copy_string(output, &tmp[1], maxlen);
00185 else
00186 ast_copy_string(output, "None Specified!\n", maxlen);
00187 } else
00188 ast_copy_string(output, "Invalid SHORT", maxlen);
00189
00190 }
00191
00192 static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len);
00193 static void dump_prov(char *output, int maxlen, void *value, int len)
00194 {
00195 dump_prov_ies(output, maxlen, value, len);
00196 }
00197
00198 static struct iax2_ie {
00199 int ie;
00200 char *name;
00201 void (*dump)(char *output, int maxlen, void *value, int len);
00202 } ies[] = {
00203 { IAX_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
00204 { IAX_IE_CALLING_NUMBER, "CALLING NUMBER", dump_string },
00205 { IAX_IE_CALLING_ANI, "ANI", dump_string },
00206 { IAX_IE_CALLING_NAME, "CALLING NAME", dump_string },
00207 { IAX_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
00208 { IAX_IE_USERNAME, "USERNAME", dump_string },
00209 { IAX_IE_PASSWORD, "PASSWORD", dump_string },
00210 { IAX_IE_CAPABILITY, "CAPABILITY", dump_int },
00211 { IAX_IE_FORMAT, "FORMAT", dump_int },
00212 { IAX_IE_LANGUAGE, "LANGUAGE", dump_string },
00213 { IAX_IE_VERSION, "VERSION", dump_short },
00214 { IAX_IE_ADSICPE, "ADSICPE", dump_short },
00215 { IAX_IE_DNID, "DNID", dump_string },
00216 { IAX_IE_AUTHMETHODS, "AUTHMETHODS", dump_short },
00217 { IAX_IE_CHALLENGE, "CHALLENGE", dump_string },
00218 { IAX_IE_MD5_RESULT, "MD5 RESULT", dump_string },
00219 { IAX_IE_RSA_RESULT, "RSA RESULT", dump_string },
00220 { IAX_IE_APPARENT_ADDR, "APPARENT ADDRESS", dump_addr },
00221 { IAX_IE_REFRESH, "REFRESH", dump_short },
00222 { IAX_IE_DPSTATUS, "DIALPLAN STATUS", dump_short },
00223 { IAX_IE_CALLNO, "CALL NUMBER", dump_short },
00224 { IAX_IE_CAUSE, "CAUSE", dump_string },
00225 { IAX_IE_IAX_UNKNOWN, "UNKNOWN IAX CMD", dump_byte },
00226 { IAX_IE_MSGCOUNT, "MESSAGE COUNT", dump_short },
00227 { IAX_IE_AUTOANSWER, "AUTO ANSWER REQ" },
00228 { IAX_IE_TRANSFERID, "TRANSFER ID", dump_int },
00229 { IAX_IE_RDNIS, "REFERRING DNIS", dump_string },
00230 { IAX_IE_PROVISIONING, "PROVISIONING", dump_prov },
00231 { IAX_IE_AESPROVISIONING, "AES PROVISIONG" },
00232 { IAX_IE_DATETIME, "DATE TIME", dump_datetime },
00233 { IAX_IE_DEVICETYPE, "DEVICE TYPE", dump_string },
00234 { IAX_IE_SERVICEIDENT, "SERVICE IDENT", dump_string },
00235 { IAX_IE_FIRMWAREVER, "FIRMWARE VER", dump_short },
00236 { IAX_IE_FWBLOCKDESC, "FW BLOCK DESC", dump_int },
00237 { IAX_IE_FWBLOCKDATA, "FW BLOCK DATA" },
00238 { IAX_IE_PROVVER, "PROVISIONG VER", dump_int },
00239 { IAX_IE_CALLINGPRES, "CALLING PRESNTN", dump_byte },
00240 { IAX_IE_CALLINGTON, "CALLING TYPEOFNUM", dump_byte },
00241 { IAX_IE_CALLINGTNS, "CALLING TRANSITNET", dump_short },
00242 { IAX_IE_SAMPLINGRATE, "SAMPLINGRATE", dump_samprate },
00243 { IAX_IE_CAUSECODE, "CAUSE CODE", dump_byte },
00244 { IAX_IE_ENCRYPTION, "ENCRYPTION", dump_short },
00245 { IAX_IE_ENCKEY, "ENCRYPTION KEY" },
00246 { IAX_IE_CODEC_PREFS, "CODEC_PREFS", dump_prefs },
00247 { IAX_IE_RR_JITTER, "RR_JITTER", dump_int },
00248 { IAX_IE_RR_LOSS, "RR_LOSS", dump_int },
00249 { IAX_IE_RR_PKTS, "RR_PKTS", dump_int },
00250 { IAX_IE_RR_DELAY, "RR_DELAY", dump_short },
00251 { IAX_IE_RR_DROPPED, "RR_DROPPED", dump_int },
00252 { IAX_IE_RR_OOO, "RR_OUTOFORDER", dump_int },
00253 };
00254
00255 static struct iax2_ie prov_ies[] = {
00256 { PROV_IE_USEDHCP, "USEDHCP" },
00257 { PROV_IE_IPADDR, "IPADDR", dump_ipaddr },
00258 { PROV_IE_SUBNET, "SUBNET", dump_ipaddr },
00259 { PROV_IE_GATEWAY, "GATEWAY", dump_ipaddr },
00260 { PROV_IE_PORTNO, "BINDPORT", dump_short },
00261 { PROV_IE_USER, "USERNAME", dump_string },
00262 { PROV_IE_PASS, "PASSWORD", dump_string },
00263 { PROV_IE_LANG, "LANGUAGE", dump_string },
00264 { PROV_IE_TOS, "TYPEOFSERVICE", dump_byte },
00265 { PROV_IE_FLAGS, "FLAGS", dump_prov_flags },
00266 { PROV_IE_FORMAT, "FORMAT", dump_int },
00267 { PROV_IE_AESKEY, "AESKEY" },
00268 { PROV_IE_SERVERIP, "SERVERIP", dump_ipaddr },
00269 { PROV_IE_SERVERPORT, "SERVERPORT", dump_short },
00270 { PROV_IE_NEWAESKEY, "NEWAESKEY" },
00271 { PROV_IE_PROVVER, "PROV VERSION", dump_int },
00272 { PROV_IE_ALTSERVER, "ALTSERVERIP", dump_ipaddr },
00273 };
00274
00275 const char *iax_ie2str(int ie)
00276 {
00277 int x;
00278 for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
00279 if (ies[x].ie == ie)
00280 return ies[x].name;
00281 }
00282 return "Unknown IE";
00283 }
00284
00285
00286 static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len)
00287 {
00288 int ielen;
00289 int ie;
00290 int x;
00291 int found;
00292 char interp[80];
00293 char tmp[256];
00294 if (len < 2)
00295 return;
00296 strcpy(output, "\n");
00297 maxlen -= strlen(output); output += strlen(output);
00298 while(len > 2) {
00299 ie = iedata[0];
00300 ielen = iedata[1];
00301 if (ielen + 2> len) {
00302 snprintf(tmp, (int)sizeof(tmp), "Total Prov IE length of %d bytes exceeds remaining prov frame length of %d bytes\n", ielen + 2, len);
00303 ast_copy_string(output, tmp, maxlen);
00304 maxlen -= strlen(output);
00305 output += strlen(output);
00306 return;
00307 }
00308 found = 0;
00309 for (x=0;x<(int)sizeof(prov_ies) / (int)sizeof(prov_ies[0]); x++) {
00310 if (prov_ies[x].ie == ie) {
00311 if (prov_ies[x].dump) {
00312 prov_ies[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
00313 snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", prov_ies[x].name, interp);
00314 ast_copy_string(output, tmp, maxlen);
00315 maxlen -= strlen(output); output += strlen(output);
00316 } else {
00317 if (ielen)
00318 snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
00319 else
00320 strcpy(interp, "Present");
00321 snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", prov_ies[x].name, interp);
00322 ast_copy_string(output, tmp, maxlen);
00323 maxlen -= strlen(output); output += strlen(output);
00324 }
00325 found++;
00326 }
00327 }
00328 if (!found) {
00329 snprintf(tmp, (int)sizeof(tmp), " Unknown Prov IE %03d : Present\n", ie);
00330 ast_copy_string(output, tmp, maxlen);
00331 maxlen -= strlen(output); output += strlen(output);
00332 }
00333 iedata += (2 + ielen);
00334 len -= (2 + ielen);
00335 }
00336 }
00337
00338 static void dump_ies(unsigned char *iedata, int len)
00339 {
00340 int ielen;
00341 int ie;
00342 int x;
00343 int found;
00344 char interp[1024];
00345 char tmp[1024];
00346 if (len < 2)
00347 return;
00348 while(len > 2) {
00349 ie = iedata[0];
00350 ielen = iedata[1];
00351 if (ielen + 2> len) {
00352 snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
00353 outputf(tmp);
00354 return;
00355 }
00356 found = 0;
00357 for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
00358 if (ies[x].ie == ie) {
00359 if (ies[x].dump) {
00360 ies[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
00361 snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", ies[x].name, interp);
00362 outputf(tmp);
00363 } else {
00364 if (ielen)
00365 snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
00366 else
00367 strcpy(interp, "Present");
00368 snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", ies[x].name, interp);
00369 outputf(tmp);
00370 }
00371 found++;
00372 }
00373 }
00374 if (!found) {
00375 snprintf(tmp, (int)sizeof(tmp), " Unknown IE %03d : Present\n", ie);
00376 outputf(tmp);
00377 }
00378 iedata += (2 + ielen);
00379 len -= (2 + ielen);
00380 }
00381 outputf("\n");
00382 }
00383
00384 void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
00385 {
00386 const char *frames[] = {
00387 "(0?)",
00388 "DTMF ",
00389 "VOICE ",
00390 "VIDEO ",
00391 "CONTROL",
00392 "NULL ",
00393 "IAX ",
00394 "TEXT ",
00395 "IMAGE ",
00396 "HTML ",
00397 "CNG " };
00398 const char *iaxs[] = {
00399 "(0?)",
00400 "NEW ",
00401 "PING ",
00402 "PONG ",
00403 "ACK ",
00404 "HANGUP ",
00405 "REJECT ",
00406 "ACCEPT ",
00407 "AUTHREQ",
00408 "AUTHREP",
00409 "INVAL ",
00410 "LAGRQ ",
00411 "LAGRP ",
00412 "REGREQ ",
00413 "REGAUTH",
00414 "REGACK ",
00415 "REGREJ ",
00416 "REGREL ",
00417 "VNAK ",
00418 "DPREQ ",
00419 "DPREP ",
00420 "DIAL ",
00421 "TXREQ ",
00422 "TXCNT ",
00423 "TXACC ",
00424 "TXREADY",
00425 "TXREL ",
00426 "TXREJ ",
00427 "QUELCH ",
00428 "UNQULCH",
00429 "POKE ",
00430 "PAGE ",
00431 "MWI ",
00432 "UNSPRTD",
00433 "TRANSFR",
00434 "PROVISN",
00435 "FWDWNLD",
00436 "FWDATA "
00437 };
00438 const char *cmds[] = {
00439 "(0?)",
00440 "HANGUP ",
00441 "RING ",
00442 "RINGING",
00443 "ANSWER ",
00444 "BUSY ",
00445 "TKOFFHK",
00446 "OFFHOOK" };
00447 struct ast_iax2_full_hdr *fh;
00448 char retries[20];
00449 char class2[20];
00450 char subclass2[20];
00451 const char *class;
00452 const char *subclass;
00453 char *dir;
00454 char tmp[512];
00455 char iabuf[INET_ADDRSTRLEN];
00456
00457 switch(rx) {
00458 case 0:
00459 dir = "Tx";
00460 break;
00461 case 2:
00462 dir = "TE";
00463 break;
00464 case 3:
00465 dir = "RD";
00466 break;
00467 default:
00468 dir = "Rx";
00469 break;
00470 }
00471 if (f) {
00472 fh = f->data;
00473 snprintf(retries, sizeof(retries), "%03d", f->retries);
00474 } else {
00475 fh = fhi;
00476 if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS)
00477 strcpy(retries, "Yes");
00478 else
00479 strcpy(retries, " No");
00480 }
00481 if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) {
00482
00483 return;
00484 }
00485 if (fh->type >= (int)sizeof(frames)/(int)sizeof(frames[0])) {
00486 snprintf(class2, sizeof(class2), "(%d?)", fh->type);
00487 class = class2;
00488 } else {
00489 class = frames[(int)fh->type];
00490 }
00491 if (fh->type == AST_FRAME_DTMF) {
00492 sprintf(subclass2, "%c", fh->csub);
00493 subclass = subclass2;
00494 } else if (fh->type == AST_FRAME_IAX) {
00495 if (fh->csub >= (int)sizeof(iaxs)/(int)sizeof(iaxs[0])) {
00496 snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
00497 subclass = subclass2;
00498 } else {
00499 subclass = iaxs[(int)fh->csub];
00500 }
00501 } else if (fh->type == AST_FRAME_CONTROL) {
00502 if (fh->csub >= (int)sizeof(cmds)/(int)sizeof(cmds[0])) {
00503 snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
00504 subclass = subclass2;
00505 } else {
00506 subclass = cmds[(int)fh->csub];
00507 }
00508 } else {
00509 snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);
00510 subclass = subclass2;
00511 }
00512 snprintf(tmp, sizeof(tmp),
00513 "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
00514 dir,
00515 retries, fh->oseqno, fh->iseqno, class, subclass);
00516 outputf(tmp);
00517 snprintf(tmp, sizeof(tmp),
00518 " Timestamp: %05lums SCall: %5.5d DCall: %5.5d [%s:%d]\n",
00519 (unsigned long)ntohl(fh->ts),
00520 ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
00521 ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port));
00522 outputf(tmp);
00523 if (fh->type == AST_FRAME_IAX)
00524 dump_ies(fh->iedata, datalen);
00525 }
00526
00527 int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, void *data, int datalen)
00528 {
00529 char tmp[256];
00530 if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
00531 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);
00532 errorf(tmp);
00533 return -1;
00534 }
00535 ied->buf[ied->pos++] = ie;
00536 ied->buf[ied->pos++] = datalen;
00537 memcpy(ied->buf + ied->pos, data, datalen);
00538 ied->pos += datalen;
00539 return 0;
00540 }
00541
00542 int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
00543 {
00544 return iax_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
00545 }
00546
00547 int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value)
00548 {
00549 unsigned int newval;
00550 newval = htonl(value);
00551 return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
00552 }
00553
00554 int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value)
00555 {
00556 unsigned short newval;
00557 newval = htons(value);
00558 return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
00559 }
00560
00561 int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, char *str)
00562 {
00563 return iax_ie_append_raw(ied, ie, str, strlen(str));
00564 }
00565
00566 int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
00567 {
00568 return iax_ie_append_raw(ied, ie, &dat, 1);
00569 }
00570
00571 int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
00572 {
00573 return iax_ie_append_raw(ied, ie, NULL, 0);
00574 }
00575
00576 void iax_set_output(void (*func)(const char *))
00577 {
00578 outputf = func;
00579 }
00580
00581 void iax_set_error(void (*func)(const char *))
00582 {
00583 errorf = func;
00584 }
00585
00586 int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
00587 {
00588
00589 int len;
00590 int ie;
00591 char tmp[256];
00592 memset(ies, 0, (int)sizeof(struct iax_ies));
00593 ies->msgcount = -1;
00594 ies->firmwarever = -1;
00595 ies->calling_ton = -1;
00596 ies->calling_tns = -1;
00597 ies->calling_pres = -1;
00598 ies->samprate = IAX_RATE_8KHZ;
00599 while(datalen >= 2) {
00600 ie = data[0];
00601 len = data[1];
00602 if (len > datalen - 2) {
00603 errorf("Information element length exceeds message size\n");
00604 return -1;
00605 }
00606 switch(ie) {
00607 case IAX_IE_CALLED_NUMBER:
00608 ies->called_number = (char *)data + 2;
00609 break;
00610 case IAX_IE_CALLING_NUMBER:
00611 ies->calling_number = (char *)data + 2;
00612 break;
00613 case IAX_IE_CALLING_ANI:
00614 ies->calling_ani = (char *)data + 2;
00615 break;
00616 case IAX_IE_CALLING_NAME:
00617 ies->calling_name = (char *)data + 2;
00618 break;
00619 case IAX_IE_CALLED_CONTEXT:
00620 ies->called_context = (char *)data + 2;
00621 break;
00622 case IAX_IE_USERNAME:
00623 ies->username = (char *)data + 2;
00624 break;
00625 case IAX_IE_PASSWORD:
00626 ies->password = (char *)data + 2;
00627 break;
00628 case IAX_IE_CODEC_PREFS:
00629 ies->codec_prefs = (char *)data + 2;
00630 break;
00631 case IAX_IE_CAPABILITY:
00632 if (len != (int)sizeof(unsigned int)) {
00633 snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00634 errorf(tmp);
00635 } else
00636 ies->capability = ntohl(get_unaligned_uint32(data + 2));
00637 break;
00638 case IAX_IE_FORMAT:
00639 if (len != (int)sizeof(unsigned int)) {
00640 snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00641 errorf(tmp);
00642 } else
00643 ies->format = ntohl(get_unaligned_uint32(data + 2));
00644 break;
00645 case IAX_IE_LANGUAGE:
00646 ies->language = (char *)data + 2;
00647 break;
00648 case IAX_IE_VERSION:
00649 if (len != (int)sizeof(unsigned short)) {
00650 snprintf(tmp, (int)sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00651 errorf(tmp);
00652 } else
00653 ies->version = ntohs(get_unaligned_uint16(data + 2));
00654 break;
00655 case IAX_IE_ADSICPE:
00656 if (len != (int)sizeof(unsigned short)) {
00657 snprintf(tmp, (int)sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00658 errorf(tmp);
00659 } else
00660 ies->adsicpe = ntohs(get_unaligned_uint16(data + 2));
00661 break;
00662 case IAX_IE_SAMPLINGRATE:
00663 if (len != (int)sizeof(unsigned short)) {
00664 snprintf(tmp, (int)sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00665 errorf(tmp);
00666 } else
00667 ies->samprate = ntohs(get_unaligned_uint16(data + 2));
00668 break;
00669 case IAX_IE_DNID:
00670 ies->dnid = (char *)data + 2;
00671 break;
00672 case IAX_IE_RDNIS:
00673 ies->rdnis = (char *)data + 2;
00674 break;
00675 case IAX_IE_AUTHMETHODS:
00676 if (len != (int)sizeof(unsigned short)) {
00677 snprintf(tmp, (int)sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00678 errorf(tmp);
00679 } else
00680 ies->authmethods = ntohs(get_unaligned_uint16(data + 2));
00681 break;
00682 case IAX_IE_ENCRYPTION:
00683 if (len != (int)sizeof(unsigned short)) {
00684 snprintf(tmp, (int)sizeof(tmp), "Expecting encryption to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00685 errorf(tmp);
00686 } else
00687 ies->encmethods = ntohs(get_unaligned_uint16(data + 2));
00688 break;
00689 case IAX_IE_CHALLENGE:
00690 ies->challenge = (char *)data + 2;
00691 break;
00692 case IAX_IE_MD5_RESULT:
00693 ies->md5_result = (char *)data + 2;
00694 break;
00695 case IAX_IE_RSA_RESULT:
00696 ies->rsa_result = (char *)data + 2;
00697 break;
00698 case IAX_IE_APPARENT_ADDR:
00699 ies->apparent_addr = ((struct sockaddr_in *)(data + 2));
00700 break;
00701 case IAX_IE_REFRESH:
00702 if (len != (int)sizeof(unsigned short)) {
00703 snprintf(tmp, (int)sizeof(tmp), "Expecting refresh to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00704 errorf(tmp);
00705 } else
00706 ies->refresh = ntohs(get_unaligned_uint16(data + 2));
00707 break;
00708 case IAX_IE_DPSTATUS:
00709 if (len != (int)sizeof(unsigned short)) {
00710 snprintf(tmp, (int)sizeof(tmp), "Expecting dpstatus to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00711 errorf(tmp);
00712 } else
00713 ies->dpstatus = ntohs(get_unaligned_uint16(data + 2));
00714 break;
00715 case IAX_IE_CALLNO:
00716 if (len != (int)sizeof(unsigned short)) {
00717 snprintf(tmp, (int)sizeof(tmp), "Expecting callno to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00718 errorf(tmp);
00719 } else
00720 ies->callno = ntohs(get_unaligned_uint16(data + 2));
00721 break;
00722 case IAX_IE_CAUSE:
00723 ies->cause = (char *)data + 2;
00724 break;
00725 case IAX_IE_CAUSECODE:
00726 if (len != 1) {
00727 snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
00728 errorf(tmp);
00729 } else {
00730 ies->causecode = data[2];
00731 }
00732 break;
00733 case IAX_IE_IAX_UNKNOWN:
00734 if (len == 1)
00735 ies->iax_unknown = data[2];
00736 else {
00737 snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
00738 errorf(tmp);
00739 }
00740 break;
00741 case IAX_IE_MSGCOUNT:
00742 if (len != (int)sizeof(unsigned short)) {
00743 snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00744 errorf(tmp);
00745 } else
00746 ies->msgcount = ntohs(get_unaligned_uint16(data + 2));
00747 break;
00748 case IAX_IE_AUTOANSWER:
00749 ies->autoanswer = 1;
00750 break;
00751 case IAX_IE_MUSICONHOLD:
00752 ies->musiconhold = 1;
00753 break;
00754 case IAX_IE_TRANSFERID:
00755 if (len != (int)sizeof(unsigned int)) {
00756 snprintf(tmp, (int)sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00757 errorf(tmp);
00758 } else
00759 ies->transferid = ntohl(get_unaligned_uint32(data + 2));
00760 break;
00761 case IAX_IE_DATETIME:
00762 if (len != (int)sizeof(unsigned int)) {
00763 snprintf(tmp, (int)sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00764 errorf(tmp);
00765 } else
00766 ies->datetime = ntohl(get_unaligned_uint32(data + 2));
00767 break;
00768 case IAX_IE_FIRMWAREVER:
00769 if (len != (int)sizeof(unsigned short)) {
00770 snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00771 errorf(tmp);
00772 } else
00773 ies->firmwarever = ntohs(get_unaligned_uint16(data + 2));
00774 break;
00775 case IAX_IE_DEVICETYPE:
00776 ies->devicetype = (char *)data + 2;
00777 break;
00778 case IAX_IE_SERVICEIDENT:
00779 ies->serviceident = (char *)data + 2;
00780 break;
00781 case IAX_IE_FWBLOCKDESC:
00782 if (len != (int)sizeof(unsigned int)) {
00783 snprintf(tmp, (int)sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00784 errorf(tmp);
00785 } else
00786 ies->fwdesc = ntohl(get_unaligned_uint32(data + 2));
00787 break;
00788 case IAX_IE_FWBLOCKDATA:
00789 ies->fwdata = data + 2;
00790 ies->fwdatalen = len;
00791 break;
00792 case IAX_IE_ENCKEY:
00793 ies->enckey = data + 2;
00794 ies->enckeylen = len;
00795 break;
00796 case IAX_IE_PROVVER:
00797 if (len != (int)sizeof(unsigned int)) {
00798 snprintf(tmp, (int)sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00799 errorf(tmp);
00800 } else {
00801 ies->provverpres = 1;
00802 ies->provver = ntohl(get_unaligned_uint32(data + 2));
00803 }
00804 break;
00805 case IAX_IE_CALLINGPRES:
00806 if (len == 1)
00807 ies->calling_pres = data[2];
00808 else {
00809 snprintf(tmp, (int)sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len);
00810 errorf(tmp);
00811 }
00812 break;
00813 case IAX_IE_CALLINGTON:
00814 if (len == 1)
00815 ies->calling_ton = data[2];
00816 else {
00817 snprintf(tmp, (int)sizeof(tmp), "Expected single byte callington, but was %d long\n", len);
00818 errorf(tmp);
00819 }
00820 break;
00821 case IAX_IE_CALLINGTNS:
00822 if (len != (int)sizeof(unsigned short)) {
00823 snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00824 errorf(tmp);
00825 } else
00826 ies->calling_tns = ntohs(get_unaligned_uint16(data + 2));
00827 break;
00828 case IAX_IE_RR_JITTER:
00829 if (len != (int)sizeof(unsigned int)) {
00830 snprintf(tmp, (int)sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00831 errorf(tmp);
00832 } else {
00833 ies->rr_jitter = ntohl(get_unaligned_uint32(data + 2));
00834 }
00835 break;
00836 case IAX_IE_RR_LOSS:
00837 if (len != (int)sizeof(unsigned int)) {
00838 snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00839 errorf(tmp);
00840 } else {
00841 ies->rr_loss = ntohl(get_unaligned_uint32(data + 2));
00842 }
00843 break;
00844 case IAX_IE_RR_PKTS:
00845 if (len != (int)sizeof(unsigned int)) {
00846 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00847 errorf(tmp);
00848 } else {
00849 ies->rr_pkts = ntohl(get_unaligned_uint32(data + 2));
00850 }
00851 break;
00852 case IAX_IE_RR_DELAY:
00853 if (len != (int)sizeof(unsigned short)) {
00854 snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00855 errorf(tmp);
00856 } else {
00857 ies->rr_delay = ntohs(get_unaligned_uint16(data + 2));
00858 }
00859 break;
00860 case IAX_IE_RR_DROPPED:
00861 if (len != (int)sizeof(unsigned int)) {
00862 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00863 errorf(tmp);
00864 } else {
00865 ies->rr_dropped = ntohl(get_unaligned_uint32(data + 2));
00866 }
00867 break;
00868 case IAX_IE_RR_OOO:
00869 if (len != (int)sizeof(unsigned int)) {
00870 snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00871 errorf(tmp);
00872 } else {
00873 ies->rr_ooo = ntohl(get_unaligned_uint32(data + 2));
00874 }
00875 break;
00876 default:
00877 snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
00878 outputf(tmp);
00879 }
00880
00881 data[0] = 0;
00882 datalen -= (len + 2);
00883 data += (len + 2);
00884 }
00885
00886 *data = '\0';
00887 if (datalen) {
00888 errorf("Invalid information element contents, strange boundary\n");
00889 return -1;
00890 }
00891 return 0;
00892 }
00893
00894 void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
00895 {
00896 fr->af.frametype = f->frametype;
00897 fr->af.subclass = f->subclass;
00898 fr->af.mallocd = 0;
00899 fr->af.datalen = f->datalen;
00900 fr->af.samples = f->samples;
00901 fr->af.offset = AST_FRIENDLY_OFFSET;
00902 fr->af.src = f->src;
00903 fr->af.delivery.tv_sec = 0;
00904 fr->af.delivery.tv_usec = 0;
00905 fr->af.data = fr->afdata;
00906 if (fr->af.datalen) {
00907 #if __BYTE_ORDER == __LITTLE_ENDIAN
00908
00909 if ((fr->af.frametype == AST_FRAME_VOICE) && (fr->af.subclass == AST_FORMAT_SLINEAR)) {
00910 ast_swapcopy_samples(fr->af.data, f->data, fr->af.samples);
00911 } else
00912 #endif
00913 memcpy(fr->af.data, f->data, fr->af.datalen);
00914 }
00915 }
00916
00917 struct iax_frame *iax_frame_new(int direction, int datalen)
00918 {
00919 struct iax_frame *fr;
00920 fr = malloc((int)sizeof(struct iax_frame) + datalen);
00921 if (fr) {
00922 fr->direction = direction;
00923 fr->retrans = -1;
00924 frames++;
00925 if (fr->direction == DIRECTION_INGRESS)
00926 iframes++;
00927 else
00928 oframes++;
00929 }
00930 return fr;
00931 }
00932
00933 void iax_frame_free(struct iax_frame *fr)
00934 {
00935
00936 if (fr->direction == DIRECTION_INGRESS)
00937 iframes--;
00938 else if (fr->direction == DIRECTION_OUTGRESS)
00939 oframes--;
00940 else {
00941 errorf("Attempt to double free frame detected\n");
00942 return;
00943 }
00944 fr->direction = 0;
00945 free(fr);
00946 frames--;
00947 }
00948
00949 int iax_get_frames(void) { return frames; }
00950 int iax_get_iframes(void) { return iframes; }
00951 int iax_get_oframes(void) { return oframes; }