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_frame * | iax_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) |
Implementation of the IAX2 protocol.
Definition in file iax2-parser.h.
#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().
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 }
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().
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 | |||
) |
Definition at line 737 of file iax2-parser.c.
References iax_ie_append_raw().
Referenced by __auth_reject(), __auto_hangup(), authenticate(), authenticate_request(), cache_get_callno_locked(), dp_lookup(), handle_call_token(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_transfer(), iax_provision_build(), registry_authrequest(), registry_rerequest(), resend_with_token(), socket_process(), and update_registry().
00738 { 00739 return iax_ie_append_raw(ied, ie, str, strlen(str)); 00740 }
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 }