Wed Aug 7 17:16:06 2019

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 1241 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().

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

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

Definition at line 1183 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().

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

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

Definition at line 435 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().

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

void iax_frame_wrap ( struct iax_frame fr,
struct ast_frame f 
)

Definition at line 1152 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().

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

int iax_get_frames ( void   ) 

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

Referenced by handle_cli_iax2_show_stats().

01293 { return frames; }

int iax_get_iframes ( void   ) 

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

Referenced by handle_cli_iax2_show_stats().

01294 { return iframes; }

int iax_get_oframes ( void   ) 

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

Referenced by handle_cli_iax2_show_stats().

01295 { return oframes; }

const char* iax_ie2str ( int  ie  ) 

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

References ARRAY_LEN, and iax2_ie::name.

Referenced by iax_ie_append_raw(), and iax_parse_ies().

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

int iax_ie_append ( struct iax_ie_data ied,
unsigned char  ie 
)

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

References iax_ie_append_raw().

Referenced by iax2_call(), and iax_firmware_append().

00748 {
00749    return iax_ie_append_raw(ied, ie, NULL, 0);
00750 }

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

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

References iax_ie_append_raw().

Referenced by iax2_start_transfer(), and update_registry().

00709 {
00710    return iax_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
00711 }

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

Definition at line 742 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().

00743 {
00744    return iax_ie_append_raw(ied, ie, &dat, 1);
00745 }

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

Definition at line 723 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().

00724 {
00725    unsigned int newval;
00726    newval = htonl(value);
00727    return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
00728 }

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

Definition at line 693 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().

00694 {
00695    char tmp[256];
00696    if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
00697       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);
00698       errorf(tmp);
00699       return -1;
00700    }
00701    ied->buf[ied->pos++] = ie;
00702    ied->buf[ied->pos++] = datalen;
00703    memcpy(ied->buf + ied->pos, data, datalen);
00704    ied->pos += datalen;
00705    return 0;
00706 }

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

Definition at line 730 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().

00731 {
00732    unsigned short newval;
00733    newval = htons(value);
00734    return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
00735 }

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 713 of file iax2-parser.c.

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

Referenced by iax2_call(), and socket_process().

00714 {
00715    struct _local {
00716       unsigned char version;
00717       uint64_t value;
00718    } __attribute__((packed)) newval = { version, };
00719    put_unaligned_uint64(&newval.value, htonll(value));
00720    return iax_ie_append_raw(ied, ie, &newval, (int) sizeof(newval));
00721 }

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

Definition at line 762 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().

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

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 567 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().

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


Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1