mirror of https://github.com/asterisk/asterisk
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@647 65c4cc65-6c06-0410-ace0-fbb531ad65f31.0
parent
7640e83360
commit
61e446f04b
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,344 @@
|
|||||||
|
/*
|
||||||
|
* Asterisk -- A telephony toolkit for Linux.
|
||||||
|
*
|
||||||
|
* Implementation of Inter-Asterisk eXchange
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003, Digium
|
||||||
|
*
|
||||||
|
* Mark Spencer <markster@linux-support.net>
|
||||||
|
*
|
||||||
|
* This program is free software, distributed under the terms of
|
||||||
|
* the GNU General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <asterisk/frame.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "iax2.h"
|
||||||
|
#include "iax2-parser.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void internaloutput(const char *str)
|
||||||
|
{
|
||||||
|
printf(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void internalerror(const char *str)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "WARNING: %s", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void (*outputf)(const char *str) = internaloutput;
|
||||||
|
static void (*errorf)(const char *str) = internalerror;
|
||||||
|
|
||||||
|
static void dump_addr(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
if (len == sizeof(sin)) {
|
||||||
|
memcpy(&sin, value, len);
|
||||||
|
snprintf(output, maxlen, "IPV4 %s:%d", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
|
||||||
|
} else {
|
||||||
|
snprintf(output, maxlen, "Invalid Address");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_string(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
maxlen--;
|
||||||
|
if (maxlen > len)
|
||||||
|
maxlen = len;
|
||||||
|
strncpy(output,value, maxlen);
|
||||||
|
output[maxlen] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_int(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
if (len == sizeof(unsigned int))
|
||||||
|
snprintf(output, maxlen, "%d", ntohl(*((unsigned int *)value)));
|
||||||
|
else
|
||||||
|
snprintf(output, maxlen, "Invalid INT");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_short(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
if (len == sizeof(unsigned short))
|
||||||
|
snprintf(output, maxlen, "%d", ntohs(*((unsigned short *)value)));
|
||||||
|
else
|
||||||
|
snprintf(output, maxlen, "Invalid SHORT");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_byte(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
if (len == sizeof(unsigned char))
|
||||||
|
snprintf(output, maxlen, "%d", ntohs(*((unsigned char *)value)));
|
||||||
|
else
|
||||||
|
snprintf(output, maxlen, "Invalid BYTE");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct iax2_ie {
|
||||||
|
int ie;
|
||||||
|
char *name;
|
||||||
|
void (*dump)(char *output, int maxlen, void *value, int len);
|
||||||
|
} ies[] = {
|
||||||
|
{ IAX_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
|
||||||
|
{ IAX_IE_CALLING_NUMBER, "CALLING NUMBER", dump_string },
|
||||||
|
{ IAX_IE_CALLING_NUMBER, "ANI", dump_string },
|
||||||
|
{ IAX_IE_CALLING_NAME, "CALLING NAME", dump_string },
|
||||||
|
{ IAX_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
|
||||||
|
{ IAX_IE_USERNAME, "USERNAME", dump_string },
|
||||||
|
{ IAX_IE_PASSWORD, "PASSWORD", dump_string },
|
||||||
|
{ IAX_IE_CAPABILITY, "CAPABILITY", dump_int },
|
||||||
|
{ IAX_IE_FORMAT, "FORMAT", dump_int },
|
||||||
|
{ IAX_IE_LANGUAGE, "LANGUAGE", dump_string },
|
||||||
|
{ IAX_IE_VERSION, "VERSION", dump_short },
|
||||||
|
{ IAX_IE_ADSICPE, "ADSICPE", dump_short },
|
||||||
|
{ IAX_IE_DNID, "DNID", dump_string },
|
||||||
|
{ IAX_IE_AUTHMETHODS, "AUTHMETHODS", dump_short },
|
||||||
|
{ IAX_IE_CHALLENGE, "CHALLENGE", dump_string },
|
||||||
|
{ IAX_IE_MD5_RESULT, "MD5 RESULT", dump_string },
|
||||||
|
{ IAX_IE_RSA_RESULT, "RSA RESULT", dump_string },
|
||||||
|
{ IAX_IE_APPARENT_ADDR, "APPARENT ADDRESS", dump_addr },
|
||||||
|
{ IAX_IE_REFRESH, "REFRESH", dump_short },
|
||||||
|
{ IAX_IE_DPSTATUS, "DIALPLAN STATUS", dump_short },
|
||||||
|
{ IAX_IE_CALLNO, "CALL NUMBER", dump_short },
|
||||||
|
{ IAX_IE_CAUSE, "CAUSE", dump_string },
|
||||||
|
{ IAX_IE_IAX_UNKNOWN, "UNKNOWN IAX CMD", dump_byte },
|
||||||
|
{ IAX_IE_MSGCOUNT, "MESSAGE COUNT", dump_short },
|
||||||
|
{ IAX_IE_AUTOANSWER, "AUTO ANSWER REQ" },
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *iax_ie2str(int ie)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x=0;x<sizeof(ies) / sizeof(ies[0]); x++) {
|
||||||
|
if (ies[x].ie == ie)
|
||||||
|
return ies[x].name;
|
||||||
|
}
|
||||||
|
return "Unknown IE";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_ies(unsigned char *iedata, int len)
|
||||||
|
{
|
||||||
|
int ielen;
|
||||||
|
int ie;
|
||||||
|
int x;
|
||||||
|
int found;
|
||||||
|
char interp[80];
|
||||||
|
char tmp[256];
|
||||||
|
if (len < 2)
|
||||||
|
return;
|
||||||
|
while(len > 2) {
|
||||||
|
ie = iedata[0];
|
||||||
|
ielen = iedata[1];
|
||||||
|
if (ielen + 2> len) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
|
||||||
|
outputf(tmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
found = 0;
|
||||||
|
for (x=0;x<sizeof(ies) / sizeof(ies[0]); x++) {
|
||||||
|
if (ies[x].ie == ie) {
|
||||||
|
if (ies[x].dump) {
|
||||||
|
ies[x].dump(interp, sizeof(interp), iedata + 2, ielen);
|
||||||
|
snprintf(tmp, sizeof(tmp), " %-15.15s : %s\n", ies[x].name, interp);
|
||||||
|
outputf(tmp);
|
||||||
|
} else {
|
||||||
|
snprintf(tmp, sizeof(tmp), " %-15.15s : Present\n", ies[x].name);
|
||||||
|
outputf(tmp);
|
||||||
|
}
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
snprintf(tmp, sizeof(tmp), " Unknown IE %03d : Present\n", ie);
|
||||||
|
outputf(tmp);
|
||||||
|
}
|
||||||
|
iedata += (2 + ielen);
|
||||||
|
len -= (2 + ielen);
|
||||||
|
}
|
||||||
|
outputf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void iax_showframe(struct ast_iax2_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
|
||||||
|
{
|
||||||
|
char *frames[] = {
|
||||||
|
"(0?)",
|
||||||
|
"DTMF ",
|
||||||
|
"VOICE ",
|
||||||
|
"VIDEO ",
|
||||||
|
"CONTROL",
|
||||||
|
"NULL ",
|
||||||
|
"IAX ",
|
||||||
|
"TEXT ",
|
||||||
|
"IMAGE " };
|
||||||
|
char *iaxs[] = {
|
||||||
|
"(0?)",
|
||||||
|
"NEW ",
|
||||||
|
"PING ",
|
||||||
|
"PONG ",
|
||||||
|
"ACK ",
|
||||||
|
"HANGUP ",
|
||||||
|
"REJECT ",
|
||||||
|
"ACCEPT ",
|
||||||
|
"AUTHREQ",
|
||||||
|
"AUTHREP",
|
||||||
|
"INVAL ",
|
||||||
|
"LAGRQ ",
|
||||||
|
"LAGRP ",
|
||||||
|
"REGREQ ",
|
||||||
|
"REGAUTH",
|
||||||
|
"REGACK ",
|
||||||
|
"REGREJ ",
|
||||||
|
"REGREL ",
|
||||||
|
"VNAK ",
|
||||||
|
"DPREQ ",
|
||||||
|
"DPREP ",
|
||||||
|
"DIAL ",
|
||||||
|
"TXREQ ",
|
||||||
|
"TXCNT ",
|
||||||
|
"TXACC ",
|
||||||
|
"TXREADY",
|
||||||
|
"TXREL ",
|
||||||
|
"TXREJ ",
|
||||||
|
"QUELCH ",
|
||||||
|
"UNQULCH",
|
||||||
|
"POKE",
|
||||||
|
"PAGE",
|
||||||
|
"MWI",
|
||||||
|
"UNSUPPORTED",
|
||||||
|
};
|
||||||
|
char *cmds[] = {
|
||||||
|
"(0?)",
|
||||||
|
"HANGUP ",
|
||||||
|
"RING ",
|
||||||
|
"RINGING",
|
||||||
|
"ANSWER ",
|
||||||
|
"BUSY ",
|
||||||
|
"TKOFFHK ",
|
||||||
|
"OFFHOOK" };
|
||||||
|
struct ast_iax2_full_hdr *fh;
|
||||||
|
char retries[20];
|
||||||
|
char class2[20];
|
||||||
|
char subclass2[20];
|
||||||
|
char *class;
|
||||||
|
char *subclass;
|
||||||
|
char tmp[256];
|
||||||
|
if (f) {
|
||||||
|
fh = f->data;
|
||||||
|
snprintf(retries, sizeof(retries), "%03d", f->retries);
|
||||||
|
} else {
|
||||||
|
fh = fhi;
|
||||||
|
if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS)
|
||||||
|
strcpy(retries, "Yes");
|
||||||
|
else
|
||||||
|
strcpy(retries, "No");
|
||||||
|
}
|
||||||
|
if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) {
|
||||||
|
/* Don't mess with mini-frames */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fh->type > sizeof(frames)/sizeof(char *)) {
|
||||||
|
snprintf(class2, sizeof(class2), "(%d?)", fh->type);
|
||||||
|
class = class2;
|
||||||
|
} else {
|
||||||
|
class = frames[(int)fh->type];
|
||||||
|
}
|
||||||
|
if (fh->type == AST_FRAME_DTMF) {
|
||||||
|
sprintf(subclass2, "%c", fh->csub);
|
||||||
|
subclass = subclass2;
|
||||||
|
} else if (fh->type == AST_FRAME_IAX) {
|
||||||
|
if (fh->csub >= sizeof(iaxs)/sizeof(iaxs[0])) {
|
||||||
|
snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
|
||||||
|
subclass = subclass2;
|
||||||
|
} else {
|
||||||
|
subclass = iaxs[(int)fh->csub];
|
||||||
|
}
|
||||||
|
} else if (fh->type == AST_FRAME_CONTROL) {
|
||||||
|
if (fh->csub > sizeof(cmds)/sizeof(char *)) {
|
||||||
|
snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
|
||||||
|
subclass = subclass2;
|
||||||
|
} else {
|
||||||
|
subclass = cmds[(int)fh->csub];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);
|
||||||
|
subclass = subclass2;
|
||||||
|
}
|
||||||
|
snprintf(tmp, sizeof(tmp),
|
||||||
|
"%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
|
||||||
|
(rx ? "Rx" : "Tx"),
|
||||||
|
retries, fh->oseqno, fh->iseqno, class, subclass);
|
||||||
|
outputf(tmp);
|
||||||
|
snprintf(tmp, sizeof(tmp),
|
||||||
|
" Timestamp: %05dms SCall: %5.5d DCall: %5.5d [%s:%d]\n",
|
||||||
|
ntohl(fh->ts),
|
||||||
|
ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
|
||||||
|
inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
|
||||||
|
outputf(tmp);
|
||||||
|
if (fh->type == AST_FRAME_IAX)
|
||||||
|
dump_ies(fh->iedata, datalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, void *data, int datalen)
|
||||||
|
{
|
||||||
|
char tmp[256];
|
||||||
|
if (datalen > (sizeof(ied->buf) - ied->pos)) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", iax_ie2str(ie), ie, datalen, sizeof(ied->buf) - ied->pos);
|
||||||
|
errorf(tmp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ied->buf[ied->pos++] = ie;
|
||||||
|
ied->buf[ied->pos++] = datalen;
|
||||||
|
memcpy(ied->buf + ied->pos, data, datalen);
|
||||||
|
ied->pos += datalen;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
|
||||||
|
{
|
||||||
|
return iax_ie_append_raw(ied, ie, sin, sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value)
|
||||||
|
{
|
||||||
|
unsigned int newval;
|
||||||
|
newval = htonl(value);
|
||||||
|
return iax_ie_append_raw(ied, ie, &newval, sizeof(newval));
|
||||||
|
}
|
||||||
|
|
||||||
|
int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value)
|
||||||
|
{
|
||||||
|
unsigned short newval;
|
||||||
|
newval = htons(value);
|
||||||
|
return iax_ie_append_raw(ied, ie, &newval, sizeof(newval));
|
||||||
|
}
|
||||||
|
|
||||||
|
int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, unsigned char *str)
|
||||||
|
{
|
||||||
|
return iax_ie_append_raw(ied, ie, str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
|
||||||
|
{
|
||||||
|
return iax_ie_append_raw(ied, ie, &dat, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
|
||||||
|
{
|
||||||
|
return iax_ie_append_raw(ied, ie, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void iax_set_output(void (*func)(const char *))
|
||||||
|
{
|
||||||
|
outputf = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iax_set_error(void (*func)(const char *))
|
||||||
|
{
|
||||||
|
errorf = func;
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Asterisk -- A telephony toolkit for Linux.
|
||||||
|
*
|
||||||
|
* Implementation of Inter-Asterisk eXchange
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003, Digium
|
||||||
|
*
|
||||||
|
* Mark Spencer <markster@linux-support.net>
|
||||||
|
*
|
||||||
|
* This program is free software, distributed under the terms of
|
||||||
|
* the GNU General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _IAX2_PARSER_H
|
||||||
|
#define _IAX2_PARSER_H
|
||||||
|
|
||||||
|
struct iax_ies {
|
||||||
|
char *called_number;
|
||||||
|
char *calling_number;
|
||||||
|
char *calling_ani;
|
||||||
|
char *calling_name;
|
||||||
|
char *called_context;
|
||||||
|
char *username;
|
||||||
|
char *password;
|
||||||
|
unsigned int capability;
|
||||||
|
unsigned int format;
|
||||||
|
char *language;
|
||||||
|
int version;
|
||||||
|
unsigned short adsicpe;
|
||||||
|
char *dnid;
|
||||||
|
unsigned int authmethods;
|
||||||
|
char *challenge;
|
||||||
|
char *md5_result;
|
||||||
|
char *rsa_result;
|
||||||
|
struct sockaddr_in *apparent_addr;
|
||||||
|
unsigned short refresh;
|
||||||
|
unsigned short dpstatus;
|
||||||
|
unsigned short callno;
|
||||||
|
char *cause;
|
||||||
|
unsigned char iax_unknown;
|
||||||
|
int msgcount;
|
||||||
|
int autoanswer;
|
||||||
|
int musiconhold;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DIRECTION_INGRESS 1
|
||||||
|
#define DIRECTION_OUTGRESS 2
|
||||||
|
|
||||||
|
struct ast_iax2_frame {
|
||||||
|
/* /Our/ call number */
|
||||||
|
unsigned short callno;
|
||||||
|
/* /Their/ call number */
|
||||||
|
unsigned short dcallno;
|
||||||
|
/* Start of raw frame (outgoing only) */
|
||||||
|
void *data;
|
||||||
|
/* Length of frame (outgoing only) */
|
||||||
|
int datalen;
|
||||||
|
/* How many retries so far? */
|
||||||
|
int retries;
|
||||||
|
/* Outgoing relative timestamp (ms) */
|
||||||
|
unsigned int ts;
|
||||||
|
/* How long to wait before retrying */
|
||||||
|
int retrytime;
|
||||||
|
/* Are we received out of order? */
|
||||||
|
int outoforder;
|
||||||
|
/* Have we been sent at all yet? */
|
||||||
|
int sentyet;
|
||||||
|
/* Outgoing Packet sequence number */
|
||||||
|
int oseqno;
|
||||||
|
/* Next expected incoming packet sequence number */
|
||||||
|
int iseqno;
|
||||||
|
/* Non-zero if should be sent to transfer peer */
|
||||||
|
int transfer;
|
||||||
|
/* Non-zero if this is the final message */
|
||||||
|
int final;
|
||||||
|
/* Ingress or outgres */
|
||||||
|
int direction;
|
||||||
|
/* Retransmission ID */
|
||||||
|
int retrans;
|
||||||
|
/* Easy linking */
|
||||||
|
struct ast_iax2_frame *next;
|
||||||
|
struct ast_iax2_frame *prev;
|
||||||
|
/* Actual, isolated frame header */
|
||||||
|
struct ast_frame af;
|
||||||
|
unsigned char unused[AST_FRIENDLY_OFFSET];
|
||||||
|
unsigned char afdata[0]; /* Data for frame */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct iax_ie_data {
|
||||||
|
unsigned char buf[1024];
|
||||||
|
int pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Choose a different function for output */
|
||||||
|
extern void iax_set_output(void (*output)(const char *data));
|
||||||
|
/* Choose a different function for errors */
|
||||||
|
extern void iax_set_error(void (*output)(const char *data));
|
||||||
|
extern void iax_showframe(struct ast_iax2_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen);
|
||||||
|
|
||||||
|
extern const char *iax_ie2str(int ie);
|
||||||
|
|
||||||
|
extern int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, void *data, int datalen);
|
||||||
|
extern int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, struct sockaddr_in *sin);
|
||||||
|
extern int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value);
|
||||||
|
extern int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value);
|
||||||
|
extern int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, unsigned char *str);
|
||||||
|
extern int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat);
|
||||||
|
extern int iax_ie_append(struct iax_ie_data *ied, unsigned char ie);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in new issue