Tue Aug 20 16:35:05 2013

Asterisk developer's documentation


iax2-parser.h File Reference

Implementation of the IAX2 protocol. More...

#include "asterisk/linkedlists.h"
#include "asterisk/crypto.h"
#include "asterisk/frame_defs.h"

Go to the source code of this file.

Data Structures

struct  iax_frame
struct  iax_ie_data
struct  iax_ies

Defines

#define DIRECTION_INGRESS   1
#define DIRECTION_OUTGRESS   2

Functions

void iax_frame_free (struct iax_frame *fr)
struct iax_frameiax_frame_new (int direction, int datalen, unsigned int cacheable)
void iax_frame_subclass2str (enum iax_frame_subclass subclass, char *str, size_t len)
void iax_frame_wrap (struct iax_frame *fr, struct ast_frame *f)
int iax_get_frames (void)
int iax_get_iframes (void)
int iax_get_oframes (void)
const char * iax_ie2str (int ie)
int iax_ie_append (struct iax_ie_data *ied, unsigned char ie)
int iax_ie_append_addr (struct iax_ie_data *ied, unsigned char ie, const struct sockaddr_in *sin)
int iax_ie_append_byte (struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
int iax_ie_append_int (struct iax_ie_data *ied, unsigned char ie, unsigned int value)
int iax_ie_append_raw (struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
int iax_ie_append_short (struct iax_ie_data *ied, unsigned char ie, unsigned short value)
int iax_ie_append_str (struct iax_ie_data *ied, unsigned char ie, const char *str)
int iax_ie_append_versioned_uint64 (struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value)
int iax_parse_ies (struct iax_ies *ies, unsigned char *data, int datalen)
void iax_set_error (void(*output)(const char *data))
void iax_set_output (void(*output)(const char *data))
void iax_showframe (struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)

Detailed Description

Implementation of the IAX2 protocol.

Definition in file iax2-parser.h.


Define Documentation

#define DIRECTION_INGRESS   1

Definition at line 85 of file iax2-parser.h.

Referenced by iax_frame_free(), iax_frame_new(), and iaxfrdup2().

#define DIRECTION_OUTGRESS   2

Definition at line 86 of file iax2-parser.h.

Referenced by iax2_send(), iax_frame_free(), and send_trunk().


Function Documentation

void iax_frame_free ( struct iax_frame fr  ) 

Definition at line 1231 of file iax2-parser.c.

References iax_frame::afdatalen, ast_atomic_fetchadd_int(), ast_free, AST_LIST_FIRST, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, ast_threadstorage_get(), iax_frame::cacheable, iax_frame::direction, DIRECTION_INGRESS, DIRECTION_OUTGRESS, errorf, frame_cache, FRAME_CACHE_MAX_SIZE, iax_frames::list, and iax_frames::size.

Referenced by iax2_frame_free(), and transmit_frame().

01232 {
01233 #if !defined(LOW_MEMORY)
01234    struct iax_frames *iax_frames = NULL;
01235 #endif
01236 
01237    /* Note: does not remove from scheduler! */
01238    if (fr->direction == DIRECTION_INGRESS)
01239       ast_atomic_fetchadd_int(&iframes, -1);
01240    else if (fr->direction == DIRECTION_OUTGRESS)
01241       ast_atomic_fetchadd_int(&oframes, -1);
01242    else {
01243       errorf("Attempt to double free frame detected\n");
01244       return;
01245    }
01246    ast_atomic_fetchadd_int(&frames, -1);
01247 
01248 #if !defined(LOW_MEMORY)
01249    if (!fr->cacheable || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
01250       ast_free(fr);
01251       return;
01252    }
01253 
01254    if (iax_frames->size < FRAME_CACHE_MAX_SIZE) {
01255       fr->direction = 0;
01256       /* Pseudo-sort: keep smaller frames at the top of the list. This should
01257        * increase the chance that we pick the smallest applicable frame for use. */
01258       if (AST_LIST_FIRST(&iax_frames->list) && AST_LIST_FIRST(&iax_frames->list)->afdatalen < fr->afdatalen) {
01259          AST_LIST_INSERT_TAIL(&iax_frames->list, fr, list);
01260       } else {
01261          AST_LIST_INSERT_HEAD(&iax_frames->list, fr, list);
01262       }
01263       iax_frames->size++;
01264       return;
01265    }
01266 #endif
01267    ast_free(fr);
01268 }

struct iax_frame* iax_frame_new ( int  direction,
int  datalen,
unsigned int  cacheable 
) [read]

Definition at line 1173 of file iax2-parser.c.

References iax_frame::afdatalen, ast_atomic_fetchadd_int(), ast_calloc, ast_calloc_cache, AST_LIST_FIRST, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_realloc, ast_threadstorage_get(), iax_frame::cacheable, iax_frame::direction, DIRECTION_INGRESS, frame_cache, FRAME_CACHE_MAX_SIZE, iax_frames::list, iax_frame::retrans, and iax_frames::size.

Referenced by iax2_send(), and iaxfrdup2().

01174 {
01175    struct iax_frame *fr = NULL;
01176 
01177 #if !defined(LOW_MEMORY)
01178    struct iax_frames *iax_frames = NULL;
01179    struct iax_frame *smallest = NULL;
01180 
01181    /* Attempt to get a frame from this thread's cache */
01182    if ((iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
01183       smallest = AST_LIST_FIRST(&iax_frames->list);
01184       AST_LIST_TRAVERSE_SAFE_BEGIN(&iax_frames->list, fr, list) {
01185          if (fr->afdatalen >= datalen) {
01186             size_t afdatalen = fr->afdatalen;
01187             AST_LIST_REMOVE_CURRENT(list);
01188             iax_frames->size--;
01189             memset(fr, 0, sizeof(*fr));
01190             fr->afdatalen = afdatalen;
01191             break;
01192          } else if (smallest->afdatalen > fr->afdatalen) {
01193             smallest = fr;
01194          }
01195       }
01196       AST_LIST_TRAVERSE_SAFE_END;
01197    }
01198    if (!fr) {
01199       if (iax_frames && iax_frames->size >= FRAME_CACHE_MAX_SIZE && smallest) {
01200          /* Make useless cache into something more useful */
01201          AST_LIST_REMOVE(&iax_frames->list, smallest, list);
01202          if (!(fr = ast_realloc(smallest, sizeof(*fr) + datalen))) {
01203             AST_LIST_INSERT_TAIL(&iax_frames->list, smallest, list);
01204             return NULL;
01205          }
01206       } else if (!(fr = ast_calloc_cache(1, sizeof(*fr) + datalen)))
01207          return NULL;
01208       fr->afdatalen = datalen;
01209    }
01210 #else
01211    if (!(fr = ast_calloc(1, sizeof(*fr) + datalen)))
01212       return NULL;
01213    fr->afdatalen = datalen;
01214 #endif
01215 
01216 
01217    fr->direction = direction;
01218    fr->retrans = -1;
01219    fr->cacheable = cacheable;
01220    
01221    if (fr->direction == DIRECTION_INGRESS)
01222       ast_atomic_fetchadd_int(&iframes, 1);
01223    else
01224       ast_atomic_fetchadd_int(&oframes, 1);
01225    
01226    ast_atomic_fetchadd_int(&frames, 1);
01227 
01228    return fr;
01229 }

void iax_frame_subclass2str ( enum iax_frame_subclass  subclass,
char *  str,
size_t  len 
)

Definition at line 433 of file iax2-parser.c.

References ast_copy_string(), IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, IAX_COMMAND_CALLTOKEN, IAX_COMMAND_DIAL, IAX_COMMAND_DPREP, IAX_COMMAND_DPREQ, IAX_COMMAND_FWDATA, IAX_COMMAND_FWDOWNL, IAX_COMMAND_HANGUP, IAX_COMMAND_INVAL, IAX_COMMAND_LAGRP, IAX_COMMAND_LAGRQ, IAX_COMMAND_MWI, IAX_COMMAND_NEW, IAX_COMMAND_PAGE, IAX_COMMAND_PING, IAX_COMMAND_POKE, IAX_COMMAND_PONG, IAX_COMMAND_PROVISION, IAX_COMMAND_QUELCH, IAX_COMMAND_REGACK, IAX_COMMAND_REGAUTH, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, IAX_COMMAND_RTKEY, IAX_COMMAND_TRANSFER, IAX_COMMAND_TXACC, IAX_COMMAND_TXCNT, IAX_COMMAND_TXMEDIA, IAX_COMMAND_TXREADY, IAX_COMMAND_TXREJ, IAX_COMMAND_TXREL, IAX_COMMAND_TXREQ, IAX_COMMAND_UNQUELCH, IAX_COMMAND_UNSUPPORT, and IAX_COMMAND_VNAK.

Referenced by ast_cli_netstats(), handle_cli_iax2_show_channels(), and iax_showframe().

00434 {
00435    const char *cmd = "Unknown";
00436 
00437    /* if an error occurs here during compile, that means a new iax frame subclass
00438     * has been added to the iax_frame_subclass enum.  Add the new subclass to the
00439     * switch case and make sure to update it with a new string representation. */
00440    switch (subclass) {
00441    case IAX_COMMAND_NEW:
00442       cmd = "NEW    ";
00443       break;
00444    case IAX_COMMAND_PING:
00445       cmd = "PING   ";
00446       break;
00447    case IAX_COMMAND_PONG:
00448       cmd = "PONG   ";
00449       break;
00450    case IAX_COMMAND_ACK:
00451       cmd = "ACK    ";
00452       break;
00453    case IAX_COMMAND_HANGUP:
00454       cmd = "HANGUP ";
00455       break;
00456    case IAX_COMMAND_REJECT:
00457       cmd = "REJECT ";
00458       break;
00459    case IAX_COMMAND_ACCEPT:
00460       cmd = "ACCEPT ";
00461       break;
00462    case IAX_COMMAND_AUTHREQ:
00463       cmd = "AUTHREQ";
00464       break;
00465    case IAX_COMMAND_AUTHREP:
00466       cmd = "AUTHREP";
00467       break;
00468    case IAX_COMMAND_INVAL:
00469       cmd = "INVAL  ";
00470       break;
00471    case IAX_COMMAND_LAGRQ:
00472       cmd = "LAGRQ  ";
00473       break;
00474    case IAX_COMMAND_LAGRP:
00475       cmd = "LAGRP  ";
00476       break;
00477    case IAX_COMMAND_REGREQ:
00478       cmd = "REGREQ ";
00479       break;
00480    case IAX_COMMAND_REGAUTH:
00481       cmd = "REGAUTH";
00482       break;
00483    case IAX_COMMAND_REGACK:
00484       cmd = "REGACK ";
00485       break;
00486    case IAX_COMMAND_REGREJ:
00487       cmd = "REGREJ ";
00488       break;
00489    case IAX_COMMAND_REGREL:
00490       cmd = "REGREL ";
00491       break;
00492    case IAX_COMMAND_VNAK:
00493       cmd = "VNAK   ";
00494       break;
00495    case IAX_COMMAND_DPREQ:
00496       cmd = "DPREQ  ";
00497       break;
00498    case IAX_COMMAND_DPREP:
00499       cmd = "DPREP  ";
00500       break;
00501    case IAX_COMMAND_DIAL:
00502       cmd = "DIAL   ";
00503       break;
00504    case IAX_COMMAND_TXREQ:
00505       cmd = "TXREQ  ";
00506       break;
00507    case IAX_COMMAND_TXCNT:
00508       cmd = "TXCNT  ";
00509       break;
00510    case IAX_COMMAND_TXACC:
00511       cmd = "TXACC  ";
00512       break;
00513    case IAX_COMMAND_TXREADY:
00514       cmd = "TXREADY";
00515       break;
00516    case IAX_COMMAND_TXREL:
00517       cmd = "TXREL  ";
00518       break;
00519    case IAX_COMMAND_TXREJ:
00520       cmd = "TXREJ  ";
00521       break;
00522    case IAX_COMMAND_QUELCH:
00523       cmd = "QUELCH ";
00524       break;
00525    case IAX_COMMAND_UNQUELCH:
00526       cmd = "UNQULCH";
00527       break;
00528    case IAX_COMMAND_POKE:
00529       cmd = "POKE   ";
00530       break;
00531    case IAX_COMMAND_PAGE:
00532       cmd = "PAGE   ";
00533       break;
00534    case IAX_COMMAND_MWI:
00535       cmd = "MWI    ";
00536       break;
00537    case IAX_COMMAND_UNSUPPORT:
00538       cmd = "UNSPRTD";
00539       break;
00540    case IAX_COMMAND_TRANSFER:
00541       cmd = "TRANSFR";
00542       break;
00543    case IAX_COMMAND_PROVISION:
00544       cmd = "PROVISN";
00545       break;
00546    case IAX_COMMAND_FWDOWNL:
00547       cmd = "FWDWNLD";
00548       break;
00549    case IAX_COMMAND_FWDATA:
00550       cmd = "FWDATA ";
00551       break;
00552    case IAX_COMMAND_TXMEDIA:
00553       cmd = "TXMEDIA";
00554       break;
00555    case IAX_COMMAND_RTKEY:
00556       cmd = "RTKEY  ";
00557       break;
00558    case IAX_COMMAND_CALLTOKEN:
00559       cmd = "CTOKEN ";
00560       break;
00561    }
00562    ast_copy_string(str, cmd, len);
00563 }

void iax_frame_wrap ( struct iax_frame fr,
struct ast_frame f 
)

Definition at line 1142 of file iax2-parser.c.

References iax_frame::af, iax_frame::afdata, iax_frame::afdatalen, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_swapcopy_samples(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_frame::frametype, ast_frame::len, LOG_ERROR, ast_frame::mallocd, ast_frame::offset, ast_frame::ptr, ast_frame::samples, ast_frame::src, and ast_frame::subclass.

Referenced by iax2_send(), iaxfrdup2(), socket_process(), and socket_process_meta().

01143 {
01144    fr->af.frametype = f->frametype;
01145    fr->af.subclass.codec = f->subclass.codec;
01146    fr->af.mallocd = 0;           /* Our frame is static relative to the container */
01147    fr->af.datalen = f->datalen;
01148    fr->af.samples = f->samples;
01149    fr->af.offset = AST_FRIENDLY_OFFSET;
01150    fr->af.src = f->src;
01151    fr->af.delivery.tv_sec = 0;
01152    fr->af.delivery.tv_usec = 0;
01153    fr->af.data.ptr = fr->afdata;
01154    fr->af.len = f->len;
01155    if (fr->af.datalen) {
01156       size_t copy_len = fr->af.datalen;
01157       if (copy_len > fr->afdatalen) {
01158          ast_log(LOG_ERROR, "Losing frame data because destination buffer size '%d' bytes not big enough for '%d' bytes in the frame\n",
01159             (int) fr->afdatalen, (int) fr->af.datalen);
01160          copy_len = fr->afdatalen;
01161       }
01162 #if __BYTE_ORDER == __LITTLE_ENDIAN
01163       /* We need to byte-swap slinear samples from network byte order */
01164       if ((fr->af.frametype == AST_FRAME_VOICE) && (fr->af.subclass.codec == AST_FORMAT_SLINEAR)) {
01165          /* 2 bytes / sample for SLINEAR */
01166          ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2);
01167       } else
01168 #endif
01169          memcpy(fr->af.data.ptr, f->data.ptr, copy_len);
01170    }
01171 }

int iax_get_frames ( void   ) 

Definition at line 1283 of file iax2-parser.c.

Referenced by handle_cli_iax2_show_stats().

01283 { return frames; }

int iax_get_iframes ( void   ) 

Definition at line 1284 of file iax2-parser.c.

Referenced by handle_cli_iax2_show_stats().

01284 { return iframes; }

int iax_get_oframes ( void   ) 

Definition at line 1285 of file iax2-parser.c.

Referenced by handle_cli_iax2_show_stats().

01285 { return oframes; }

const char* iax_ie2str ( int  ie  ) 

Definition at line 324 of file iax2-parser.c.

References ARRAY_LEN, infoelts, and iax2_ie::name.

Referenced by iax_ie_append_raw(), and iax_parse_ies().

00325 {
00326    int x;
00327    for (x = 0; x < ARRAY_LEN(infoelts); x++) {
00328       if (infoelts[x].ie == ie)
00329          return infoelts[x].name;
00330    }
00331    return "Unknown IE";
00332 }

int iax_ie_append ( struct iax_ie_data ied,
unsigned char  ie 
)

Definition at line 737 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by iax2_call(), and iax_firmware_append().

00738 {
00739    return iax_ie_append_raw(ied, ie, NULL, 0);
00740 }

int iax_ie_append_addr ( struct iax_ie_data ied,
unsigned char  ie,
const struct sockaddr_in *  sin 
)

Definition at line 698 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by iax2_start_transfer(), and update_registry().

00699 {
00700    return iax_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
00701 }

int iax_ie_append_byte ( struct iax_ie_data ied,
unsigned char  ie,
unsigned char  dat 
)

Definition at line 732 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by __auth_reject(), __auto_hangup(), authenticate_request(), iax2_call(), iax2_hangup(), iax_provision_build(), and socket_process().

00733 {
00734    return iax_ie_append_raw(ied, ie, &dat, 1);
00735 }

int iax_ie_append_int ( struct iax_ie_data ied,
unsigned char  ie,
unsigned int  value 
)

Definition at line 713 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by cache_get_callno_locked(), construct_rr(), iax2_call(), iax2_start_transfer(), iax_firmware_append(), iax_provision_build(), socket_process(), try_transfer(), and update_registry().

00714 {
00715    unsigned int newval;
00716    newval = htonl(value);
00717    return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
00718 }

int iax_ie_append_raw ( struct iax_ie_data ied,
unsigned char  ie,
const void *  data,
int  datalen 
)

Definition at line 683 of file iax2-parser.c.

References iax_ie_data::buf, errorf, iax_ie2str(), and iax_ie_data::pos.

Referenced by iax2_call(), iax2_key_rotate(), iax2_provision(), iax_firmware_append(), iax_ie_append(), iax_ie_append_addr(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), and iax_ie_append_versioned_uint64().

00684 {
00685    char tmp[256];
00686    if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
00687       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);
00688       errorf(tmp);
00689       return -1;
00690    }
00691    ied->buf[ied->pos++] = ie;
00692    ied->buf[ied->pos++] = datalen;
00693    memcpy(ied->buf + ied->pos, data, datalen);
00694    ied->pos += datalen;
00695    return 0;
00696 }

int iax_ie_append_short ( struct iax_ie_data ied,
unsigned char  ie,
unsigned short  value 
)

Definition at line 720 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by authenticate_request(), cache_get_callno_locked(), construct_rr(), dp_lookup(), iax2_call(), iax2_do_register(), iax2_start_transfer(), iax_provision_build(), registry_authrequest(), registry_rerequest(), socket_process(), and update_registry().

00721 {
00722    unsigned short newval;
00723    newval = htons(value);
00724    return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
00725 }

int iax_ie_append_str ( struct iax_ie_data ied,
unsigned char  ie,
const char *  str 
)
int iax_ie_append_versioned_uint64 ( struct iax_ie_data ied,
unsigned char  ie,
unsigned char  version,
uint64_t  value 
)

Definition at line 703 of file iax2-parser.c.

References htonll(), iax_ie_append_raw(), and put_unaligned_uint64().

Referenced by iax2_call(), and socket_process().

00704 {
00705    struct _local {
00706       unsigned char version;
00707       uint64_t value;
00708    } __attribute__((packed)) newval = { version, };
00709    put_unaligned_uint64(&newval.value, htonll(value));
00710    return iax_ie_append_raw(ied, ie, &newval, (int) sizeof(newval));
00711 }

int iax_parse_ies ( struct iax_ies ies,
unsigned char *  data,
int  datalen 
)

Definition at line 752 of file iax2-parser.c.

References iax_ies::adsicpe, iax_ies::apparent_addr, ast_copy_string(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_variable_new(), iax_ies::authmethods, iax_ies::autoanswer, iax_ies::called_context, iax_ies::called_number, iax_ies::calling_ani, iax_ies::calling_name, iax_ies::calling_number, iax_ies::calling_pres, iax_ies::calling_tns, iax_ies::calling_ton, iax_ies::callno, iax_ies::calltoken, iax_ies::calltokendata, iax_ies::capability, iax_ies::cause, iax_ies::causecode, iax_ies::challenge, iax_ies::codec_prefs, iax_ies::datetime, iax_ies::devicetype, iax_ies::dnid, iax_ies::dpstatus, iax_ies::enckey, iax_ies::enckeylen, iax_ies::encmethods, errorf, ast_variable::file, iax_ies::firmwarever, iax_ies::format, iax_ies::fwdata, iax_ies::fwdatalen, iax_ies::fwdesc, get_unaligned_uint16(), get_unaligned_uint32(), get_unaligned_uint64(), iax_ie2str(), IAX_IE_ADSICPE, IAX_IE_APPARENT_ADDR, IAX_IE_AUTHMETHODS, IAX_IE_AUTOANSWER, IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CALLING_ANI, IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_CALLINGPRES, IAX_IE_CALLINGTNS, IAX_IE_CALLINGTON, IAX_IE_CALLNO, IAX_IE_CALLTOKEN, IAX_IE_CAPABILITY, IAX_IE_CAPABILITY2, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_CODEC_PREFS, IAX_IE_DATETIME, IAX_IE_DEVICETYPE, IAX_IE_DNID, IAX_IE_DPSTATUS, IAX_IE_ENCKEY, IAX_IE_ENCRYPTION, IAX_IE_FIRMWAREVER, IAX_IE_FORMAT, IAX_IE_FORMAT2, IAX_IE_FWBLOCKDATA, IAX_IE_FWBLOCKDESC, IAX_IE_IAX_UNKNOWN, IAX_IE_LANGUAGE, IAX_IE_MD5_RESULT, IAX_IE_MSGCOUNT, IAX_IE_MUSICONHOLD, IAX_IE_OSPTOKEN, IAX_IE_PASSWORD, IAX_IE_PROVVER, IAX_IE_RDNIS, IAX_IE_REFRESH, IAX_IE_RR_DELAY, IAX_IE_RR_DROPPED, IAX_IE_RR_JITTER, IAX_IE_RR_LOSS, IAX_IE_RR_OOO, IAX_IE_RR_PKTS, IAX_IE_RSA_RESULT, IAX_IE_SAMPLINGRATE, IAX_IE_SERVICEIDENT, IAX_IE_TRANSFERID, IAX_IE_USERNAME, IAX_IE_VARIABLE, IAX_IE_VERSION, IAX_MAX_OSPBLOCK_NUM, IAX_RATE_8KHZ, iax_ies::iax_unknown, iax_ies::language, len(), iax_ies::md5_result, iax_ies::msgcount, iax_ies::musiconhold, ast_variable::name, ast_variable::next, ntohll(), iax_ies::ospblocklength, iax_ies::osptokenblock, outputf, iax_ies::password, iax_ies::provver, iax_ies::provverpres, iax_ies::rdnis, iax_ies::refresh, iax_ies::rr_delay, iax_ies::rr_dropped, iax_ies::rr_jitter, iax_ies::rr_loss, iax_ies::rr_ooo, iax_ies::rr_pkts, iax_ies::rsa_result, iax_ies::samprate, iax_ies::serviceident, str, iax_ies::transferid, iax_ies::username, ast_variable::value, var, iax_ies::vars, iax_ies::version, and version.

Referenced by socket_process().

00753 {
00754    /* Parse data into information elements */
00755    int len;
00756    int ie;
00757    char tmp[256], *tmp2;
00758    struct ast_variable *var, *var2, *prev;
00759    unsigned int count;
00760    memset(ies, 0, (int)sizeof(struct iax_ies));
00761    ies->msgcount = -1;
00762    ies->firmwarever = -1;
00763    ies->calling_ton = -1;
00764    ies->calling_tns = -1;
00765    ies->calling_pres = -1;
00766    ies->samprate = IAX_RATE_8KHZ;
00767    while(datalen >= 2) {
00768       ie = data[0];
00769       len = data[1];
00770       if (len > datalen - 2) {
00771          errorf("Information element length exceeds message size\n");
00772          return -1;
00773       }
00774       switch(ie) {
00775       case IAX_IE_CALLED_NUMBER:
00776          ies->called_number = (char *)data + 2;
00777          break;
00778       case IAX_IE_CALLING_NUMBER:
00779          ies->calling_number = (char *)data + 2;
00780          break;
00781       case IAX_IE_CALLING_ANI:
00782          ies->calling_ani = (char *)data + 2;
00783          break;
00784       case IAX_IE_CALLING_NAME:
00785          ies->calling_name = (char *)data + 2;
00786          break;
00787       case IAX_IE_CALLED_CONTEXT:
00788          ies->called_context = (char *)data + 2;
00789          break;
00790       case IAX_IE_USERNAME:
00791          ies->username = (char *)data + 2;
00792          break;
00793       case IAX_IE_PASSWORD:
00794          ies->password = (char *)data + 2;
00795          break;
00796       case IAX_IE_CODEC_PREFS:
00797          ies->codec_prefs = (char *)data + 2;
00798          break;
00799       case IAX_IE_CAPABILITY:
00800          if (len != (int)sizeof(unsigned int)) {
00801             snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00802             errorf(tmp);
00803          } else if (ies->capability == 0) { /* Don't overwrite capability2, if specified */
00804             ies->capability = ntohl(get_unaligned_uint32(data + 2));
00805          }
00806          break;
00807       case IAX_IE_CAPABILITY2:
00808          {
00809             int version = data[2];
00810             if (version == 0) {
00811                if (len != (int)sizeof(char) + sizeof(format_t)) {
00812                   snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int) (sizeof(format_t) + sizeof(char)), len);
00813                   errorf(tmp);
00814                } else {
00815                   ies->capability = (format_t) ntohll(get_unaligned_uint64(data + 3));
00816                }
00817             } /* else unknown version */
00818          }
00819          break;
00820       case IAX_IE_FORMAT:
00821          if (len != (int)sizeof(unsigned int)) {
00822             snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00823             errorf(tmp);
00824          } else if (ies->format == 0) { /* Don't overwrite format2, if specified */
00825             ies->format = ntohl(get_unaligned_uint32(data + 2));
00826          }
00827          break;
00828       case IAX_IE_FORMAT2:
00829          {
00830             int version = data[2];
00831             if (version == 0) {
00832                if (len != (int)sizeof(char) + sizeof(format_t)) {
00833                   snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int) (sizeof(format_t) + sizeof(char)), len);
00834                   errorf(tmp);
00835                } else {
00836                   ies->format = (format_t) ntohll(get_unaligned_uint64(data + 3));
00837                }
00838             } /* else unknown version */
00839          }
00840          break;
00841       case IAX_IE_LANGUAGE:
00842          ies->language = (char *)data + 2;
00843          break;
00844       case IAX_IE_VERSION:
00845          if (len != (int)sizeof(unsigned short)) {
00846             snprintf(tmp, (int)sizeof(tmp),  "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00847             errorf(tmp);
00848          } else
00849             ies->version = ntohs(get_unaligned_uint16(data + 2));
00850          break;
00851       case IAX_IE_ADSICPE:
00852          if (len != (int)sizeof(unsigned short)) {
00853             snprintf(tmp, (int)sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00854             errorf(tmp);
00855          } else
00856             ies->adsicpe = ntohs(get_unaligned_uint16(data + 2));
00857          break;
00858       case IAX_IE_SAMPLINGRATE:
00859          if (len != (int)sizeof(unsigned short)) {
00860             snprintf(tmp, (int)sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00861             errorf(tmp);
00862          } else
00863             ies->samprate = ntohs(get_unaligned_uint16(data + 2));
00864          break;
00865       case IAX_IE_DNID:
00866          ies->dnid = (char *)data + 2;
00867          break;
00868       case IAX_IE_RDNIS:
00869          ies->rdnis = (char *)data + 2;
00870          break;
00871       case IAX_IE_AUTHMETHODS:
00872          if (len != (int)sizeof(unsigned short))  {
00873             snprintf(tmp, (int)sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00874             errorf(tmp);
00875          } else
00876             ies->authmethods = ntohs(get_unaligned_uint16(data + 2));
00877          break;
00878       case IAX_IE_ENCRYPTION:
00879          if (len != (int)sizeof(unsigned short))  {
00880             snprintf(tmp, (int)sizeof(tmp), "Expecting encryption to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00881             errorf(tmp);
00882          } else
00883             ies->encmethods = ntohs(get_unaligned_uint16(data + 2));
00884          break;
00885       case IAX_IE_CHALLENGE:
00886          ies->challenge = (char *)data + 2;
00887          break;
00888       case IAX_IE_MD5_RESULT:
00889          ies->md5_result = (char *)data + 2;
00890          break;
00891       case IAX_IE_RSA_RESULT:
00892          ies->rsa_result = (char *)data + 2;
00893          break;
00894       case IAX_IE_APPARENT_ADDR:
00895          ies->apparent_addr = ((struct sockaddr_in *)(data + 2));
00896          break;
00897       case IAX_IE_REFRESH:
00898          if (len != (int)sizeof(unsigned short)) {
00899             snprintf(tmp, (int)sizeof(tmp),  "Expecting refresh to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00900             errorf(tmp);
00901          } else
00902             ies->refresh = ntohs(get_unaligned_uint16(data + 2));
00903          break;
00904       case IAX_IE_DPSTATUS:
00905          if (len != (int)sizeof(unsigned short)) {
00906             snprintf(tmp, (int)sizeof(tmp),  "Expecting dpstatus to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00907             errorf(tmp);
00908          } else
00909             ies->dpstatus = ntohs(get_unaligned_uint16(data + 2));
00910          break;
00911       case IAX_IE_CALLNO:
00912          if (len != (int)sizeof(unsigned short)) {
00913             snprintf(tmp, (int)sizeof(tmp),  "Expecting callno to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00914             errorf(tmp);
00915          } else
00916             ies->callno = ntohs(get_unaligned_uint16(data + 2));
00917          break;
00918       case IAX_IE_CAUSE:
00919          ies->cause = (char *)data + 2;
00920          break;
00921       case IAX_IE_CAUSECODE:
00922          if (len != 1) {
00923             snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
00924             errorf(tmp);
00925          } else {
00926             ies->causecode = data[2];
00927          }
00928          break;
00929       case IAX_IE_IAX_UNKNOWN:
00930          if (len == 1)
00931             ies->iax_unknown = data[2];
00932          else {
00933             snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
00934             errorf(tmp);
00935          }
00936          break;
00937       case IAX_IE_MSGCOUNT:
00938          if (len != (int)sizeof(unsigned short)) {
00939             snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00940             errorf(tmp);
00941          } else
00942             ies->msgcount = ntohs(get_unaligned_uint16(data + 2));   
00943          break;
00944       case IAX_IE_AUTOANSWER:
00945          ies->autoanswer = 1;
00946          break;
00947       case IAX_IE_MUSICONHOLD:
00948          ies->musiconhold = 1;
00949          break;
00950       case IAX_IE_TRANSFERID:
00951          if (len != (int)sizeof(unsigned int)) {
00952             snprintf(tmp, (int)sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00953             errorf(tmp);
00954          } else
00955             ies->transferid = ntohl(get_unaligned_uint32(data + 2));
00956          break;
00957       case IAX_IE_DATETIME:
00958          if (len != (int)sizeof(unsigned int)) {
00959             snprintf(tmp, (int)sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00960             errorf(tmp);
00961          } else
00962             ies->datetime = ntohl(get_unaligned_uint32(data + 2));
00963          break;
00964       case IAX_IE_FIRMWAREVER:
00965          if (len != (int)sizeof(unsigned short)) {
00966             snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00967             errorf(tmp);
00968          } else
00969             ies->firmwarever = ntohs(get_unaligned_uint16(data + 2));   
00970          break;
00971       case IAX_IE_DEVICETYPE:
00972          ies->devicetype = (char *)data + 2;
00973          break;
00974       case IAX_IE_SERVICEIDENT:
00975          ies->serviceident = (char *)data + 2;
00976          break;
00977       case IAX_IE_FWBLOCKDESC:
00978          if (len != (int)sizeof(unsigned int)) {
00979             snprintf(tmp, (int)sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00980             errorf(tmp);
00981          } else
00982             ies->fwdesc = ntohl(get_unaligned_uint32(data + 2));
00983          break;
00984       case IAX_IE_FWBLOCKDATA:
00985          ies->fwdata = data + 2;
00986          ies->fwdatalen = len;
00987          break;
00988       case IAX_IE_ENCKEY:
00989          ies->enckey = data + 2;
00990          ies->enckeylen = len;
00991          break;
00992       case IAX_IE_PROVVER:
00993          if (len != (int)sizeof(unsigned int)) {
00994             snprintf(tmp, (int)sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00995             errorf(tmp);
00996          } else {
00997             ies->provverpres = 1;
00998             ies->provver = ntohl(get_unaligned_uint32(data + 2));
00999          }
01000          break;
01001       case IAX_IE_CALLINGPRES:
01002          if (len == 1)
01003             ies->calling_pres = data[2];
01004          else {
01005             snprintf(tmp, (int)sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len);
01006             errorf(tmp);
01007          }
01008          break;
01009       case IAX_IE_CALLINGTON:
01010          if (len == 1)
01011             ies->calling_ton = data[2];
01012          else {
01013             snprintf(tmp, (int)sizeof(tmp), "Expected single byte callington, but was %d long\n", len);
01014             errorf(tmp);
01015          }
01016          break;
01017       case IAX_IE_CALLINGTNS:
01018          if (len != (int)sizeof(unsigned short)) {
01019             snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
01020             errorf(tmp);
01021          } else
01022             ies->calling_tns = ntohs(get_unaligned_uint16(data + 2));   
01023          break;
01024                case IAX_IE_RR_JITTER:
01025                        if (len != (int)sizeof(unsigned int)) {
01026                                snprintf(tmp, (int)sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
01027                                errorf(tmp);
01028                        } else {
01029                                ies->rr_jitter = ntohl(get_unaligned_uint32(data + 2));
01030                        }
01031                        break;
01032                case IAX_IE_RR_LOSS:
01033                        if (len != (int)sizeof(unsigned int)) {
01034                                snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
01035                                errorf(tmp);
01036                        } else {
01037                                ies->rr_loss = ntohl(get_unaligned_uint32(data + 2));
01038                        }
01039                        break;
01040                case IAX_IE_RR_PKTS:
01041                        if (len != (int)sizeof(unsigned int)) {
01042                                snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
01043                                errorf(tmp);
01044                        } else {
01045                                ies->rr_pkts = ntohl(get_unaligned_uint32(data + 2));
01046                        }
01047                        break;
01048                case IAX_IE_RR_DELAY:
01049                        if (len != (int)sizeof(unsigned short)) {
01050                                snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
01051                         errorf(tmp);
01052                        } else {
01053                                ies->rr_delay = ntohs(get_unaligned_uint16(data + 2));
01054                        }
01055                        break;
01056       case IAX_IE_RR_DROPPED:
01057          if (len != (int)sizeof(unsigned int)) {
01058             snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
01059             errorf(tmp);
01060          } else {
01061             ies->rr_dropped = ntohl(get_unaligned_uint32(data + 2));
01062          }
01063          break;
01064       case IAX_IE_RR_OOO:
01065          if (len != (int)sizeof(unsigned int)) {
01066             snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
01067             errorf(tmp);
01068          } else {
01069             ies->rr_ooo = ntohl(get_unaligned_uint32(data + 2));
01070          }
01071          break;
01072       case IAX_IE_VARIABLE:
01073          ast_copy_string(tmp, (char *)data + 2, len + 1);
01074          tmp2 = strchr(tmp, '=');
01075          if (tmp2)
01076             *tmp2++ = '\0';
01077          else
01078             tmp2 = "";
01079          {
01080             struct ast_str *str = ast_str_create(16);
01081             /* Existing variable or new variable? */
01082             for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) {
01083                if (strcmp(tmp, var2->name) == 0) {
01084                   ast_str_set(&str, 0, "%s%s", var2->value, tmp2);
01085                   var = ast_variable_new(tmp, ast_str_buffer(str), var2->file);
01086                   var->next = var2->next;
01087                   if (prev) {
01088                      prev->next = var;
01089                   } else {
01090                      ies->vars = var;
01091                   }
01092                   snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
01093                   outputf(tmp);
01094                   ast_free(var2);
01095                   break;
01096                }
01097             }
01098             ast_free(str);
01099          }
01100 
01101          if (!var2) {
01102             var = ast_variable_new(tmp, tmp2, "");
01103             snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
01104             outputf(tmp);
01105             var->next = ies->vars;
01106             ies->vars = var;
01107          }
01108          break;
01109       case IAX_IE_OSPTOKEN:
01110          if ((count = data[2]) < IAX_MAX_OSPBLOCK_NUM) {
01111             ies->osptokenblock[count] = (char *)data + 2 + 1;
01112             ies->ospblocklength[count] = len - 1;
01113          } else {
01114             snprintf(tmp, (int)sizeof(tmp), "Expected OSP token block index to be 0~%d but was %d\n", IAX_MAX_OSPBLOCK_NUM - 1, count);
01115             errorf(tmp);
01116          }
01117          break;
01118       case IAX_IE_CALLTOKEN:
01119          if (len) {
01120             ies->calltokendata = (unsigned char *) data + 2;
01121          }
01122          ies->calltoken = 1;
01123          break;
01124       default:
01125          snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
01126          outputf(tmp);
01127       }
01128       /* Overwrite information element with 0, to null terminate previous portion */
01129       data[0] = 0;
01130       datalen -= (len + 2);
01131       data += (len + 2);
01132    }
01133    /* Null-terminate last field */
01134    *data = '\0';
01135    if (datalen) {
01136       errorf("Invalid information element contents, strange boundary\n");
01137       return -1;
01138    }
01139    return 0;
01140 }

void iax_set_error ( void(*)(const char *data)  output  ) 
void iax_set_output ( void(*)(const char *data)  output  ) 
void iax_showframe ( struct iax_frame f,
struct ast_iax2_full_hdr fhi,
int  rx,
struct sockaddr_in *  sin,
int  datalen 
)

Definition at line 565 of file iax2-parser.c.

References ARRAY_LEN, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_IAX, ast_inet_ntoa(), ast_iax2_full_hdr::csub, iax_frame::data, ast_iax2_full_hdr::dcallno, dump_ies(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_subclass2str(), ast_iax2_full_hdr::iedata, ast_iax2_full_hdr::iseqno, ast_iax2_full_hdr::oseqno, outputf, iax_frame::retries, ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::ts, and ast_iax2_full_hdr::type.

Referenced by iax_outputframe().

00566 {
00567    const char *framelist[] = {
00568       "(0?)",
00569       "DTMF_E ",
00570       "VOICE  ",
00571       "VIDEO  ",
00572       "CONTROL",
00573       "NULL   ",
00574       "IAX    ",
00575       "TEXT   ",
00576       "IMAGE  ",
00577       "HTML   ",
00578       "CNG    ",
00579       "MODEM  ",
00580       "DTMF_B ",
00581    };
00582    const char *cmds[] = {
00583       "(0?)",
00584       "HANGUP ",
00585       "RING   ",
00586       "RINGING",
00587       "ANSWER ",
00588       "BUSY   ",
00589       "TKOFFHK",
00590       "OFFHOOK",
00591       "CONGSTN",
00592       "FLASH  ",
00593       "WINK   ",
00594       "OPTION ",
00595       "RDKEY  ",
00596       "RDUNKEY",
00597       "PROGRES",
00598       "PROCDNG",
00599       "HOLD   ",
00600       "UNHOLD ",
00601       "VIDUPDT",
00602       "T38    ",
00603       "SRCUPDT",
00604       "TXFER  ",
00605       "CNLINE ",
00606       "REDIR  ",
00607    };
00608    struct ast_iax2_full_hdr *fh;
00609    char retries[20];
00610    char class2[20];
00611    char subclass2[20];
00612    const char *class;
00613    const char *subclass;
00614    char *dir;
00615    char tmp[512];
00616 
00617    switch(rx) {
00618    case 0:
00619       dir = "Tx";
00620       break;
00621    case 2:
00622       dir = "TE";
00623       break;
00624    case 3:
00625       dir = "RD";
00626       break;
00627    default:
00628       dir = "Rx";
00629       break;
00630    }
00631    if (f) {
00632       fh = f->data;
00633       snprintf(retries, sizeof(retries), "%03d", f->retries);
00634    } else {
00635       fh = fhi;
00636       if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS)
00637          strcpy(retries, "Yes");
00638       else
00639          strcpy(retries, " No");
00640    }
00641    if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) {
00642       /* Don't mess with mini-frames */
00643       return;
00644    }
00645    if (fh->type >= ARRAY_LEN(framelist)) {
00646       snprintf(class2, sizeof(class2), "(%d?)", fh->type);
00647       class = class2;
00648    } else {
00649       class = framelist[(int)fh->type];
00650    }
00651    if (fh->type == AST_FRAME_DTMF_BEGIN || fh->type == AST_FRAME_DTMF_END) {
00652       sprintf(subclass2, "%c", fh->csub);
00653       subclass = subclass2;
00654    } else if (fh->type == AST_FRAME_IAX) {
00655          iax_frame_subclass2str((int)fh->csub, subclass2, sizeof(subclass2));
00656          subclass = subclass2;
00657    } else if (fh->type == AST_FRAME_CONTROL) {
00658       if (fh->csub >= ARRAY_LEN(cmds)) {
00659          snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
00660          subclass = subclass2;
00661       } else {
00662          subclass = cmds[(int)fh->csub];
00663       }
00664    } else {
00665       snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);
00666       subclass = subclass2;
00667    }
00668    snprintf(tmp, sizeof(tmp), 
00669        "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
00670        dir,
00671        retries, fh->oseqno, fh->iseqno, class, subclass);
00672    outputf(tmp);
00673    snprintf(tmp, sizeof(tmp), 
00674        "   Timestamp: %05lums  SCall: %5.5d  DCall: %5.5d [%s:%d]\n",
00675        (unsigned long)ntohl(fh->ts),
00676        ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
00677        ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
00678    outputf(tmp);
00679    if (fh->type == AST_FRAME_IAX)
00680       dump_ies(fh->iedata, datalen);
00681 }


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1