#include "asterisk.h"
#include "asterisk/network.h"
#include <sys/ioctl.h>
#include <zlib.h>
#include <sys/signal.h>
#include <pthread.h>
#include <net/if.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/md5.h"
#include "asterisk/dundi.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/crypto.h"
#include "asterisk/astdb.h"
#include "asterisk/acl.h"
#include "asterisk/app.h"
#include "dundi-parser.h"

Go to the source code of this file.
Data Structures | |
| struct | alltrans |
| struct | dundi_hint_metadata |
| struct | dundi_mapping |
| struct | dundi_packet |
| struct | dundi_peer |
| struct | dundi_peer::permissionlist |
| struct | dundi_precache_queue |
| struct | dundi_query_state |
| struct | dundi_request |
| struct | dundi_result_datastore |
| struct | dundi_transaction |
| struct | dundi_transaction::packetlist |
| struct | mappings |
| struct | pcq |
| struct | peers |
| struct | permission |
| struct | requests |
Defines | |
| #define | DUNDI_FLAG_INTERNAL_NOPARTIAL (1 << 17) |
| #define | DUNDI_MODEL_INBOUND (1 << 0) |
| #define | DUNDI_MODEL_OUTBOUND (1 << 1) |
| #define | DUNDI_MODEL_SYMMETRIC (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND) |
| #define | DUNDI_SECRET_TIME DUNDI_DEFAULT_CACHE_TIME |
| #define | DUNDI_TIMING_HISTORY 10 |
| #define | FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n" |
| #define | FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n" |
| #define | FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n" |
| #define | FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n" |
| #define | FORMAT "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n" |
| #define | FORMAT2 "%-12.12s %-12.12s %-10.10s\n" |
| #define | FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n" |
| #define | FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n" |
| #define | FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n" |
| #define | FORMAT2 "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n" |
| #define | MAX_OPTS 128 |
| #define | MAX_PACKET_SIZE 8192 |
| #define | MAX_RESULTS 64 |
| #define | MAX_WEIGHT 59999 |
Enumerations | |
| enum | { FLAG_ISREG = (1 << 0), FLAG_DEAD = (1 << 1), FLAG_FINAL = (1 << 2), FLAG_ISQUAL = (1 << 3), FLAG_ENCRYPT = (1 << 4), FLAG_SENDFULLKEY = (1 << 5), FLAG_STOREHIST = (1 << 6) } |
| enum | { OPT_BYPASS_CACHE = (1 << 0) } |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static void | abort_request (struct dundi_request *dr) |
| static int | ack_trans (struct dundi_transaction *trans, int iseqno) |
| static void | append_permission (struct permissionlist *permlist, const char *s, int allow) |
| static int | append_transaction (struct dundi_request *dr, struct dundi_peer *p, int ttl, dundi_eid *avoid[]) |
| static void | apply_peer (struct dundi_transaction *trans, struct dundi_peer *p) |
| static unsigned long | avoid_crc32 (dundi_eid *avoid[]) |
| static void | build_iv (unsigned char *iv) |
| static void | build_mapping (const char *name, const char *value) |
| static void | build_peer (dundi_eid *eid, struct ast_variable *v, int *globalpcmode) |
| static void | build_secret (char *secret, int seclen) |
| static void | build_transactions (struct dundi_request *dr, int ttl, int order, int *foundcache, int *skipped, int blockempty, int nocache, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int directs[]) |
| static int | cache_lookup (struct dundi_request *req, dundi_eid *peer_eid, uint32_t crc32, int *lowexpiration) |
| static int | cache_lookup_internal (time_t now, struct dundi_request *req, char *key, char *eid_str_full, int *lowexpiration) |
| static int | cache_save (dundi_eid *eidpeer, struct dundi_request *req, int start, int unaffected, int expiration, int push) |
| static int | cache_save_hint (dundi_eid *eidpeer, struct dundi_request *req, struct dundi_hint *hint, int expiration) |
| static void | cancel_request (struct dundi_request *dr) |
| static int | check_key (struct dundi_peer *peer, unsigned char *newkey, unsigned char *newsig, uint32_t keycrc32) |
| static void | check_password (void) |
| static int | check_request (struct dundi_request *dr) |
| static char * | complete_peer_helper (const char *line, const char *word, int pos, int state, int rpos) |
| static struct dundi_transaction * | create_transaction (struct dundi_peer *p) |
| static int | decrypt_memcpy (unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_decrypt_key *dcx) |
| static void | deep_copy_peer (struct dundi_peer *peer_dst, const struct dundi_peer *peer_src) |
| static void | destroy_map (struct dundi_mapping *map) |
| static void | destroy_packet (struct dundi_packet *pack, int needfree) |
| static void | destroy_packets (struct packetlist *p) |
| static void | destroy_peer (struct dundi_peer *peer) |
| static void | destroy_permissions (struct permissionlist *permlist) |
| static void | destroy_trans (struct dundi_transaction *trans, int fromtimeout) |
| static int | discover_transactions (struct dundi_request *dr) |
| static int | do_autokill (const void *data) |
| static int | do_qualify (const void *data) |
| static int | do_register (const void *data) |
| static int | do_register_expire (const void *data) |
| static void | drds_destroy (struct dundi_result_datastore *drds) |
| static void | drds_destroy_cb (void *data) |
| static int | dundi_ack (struct dundi_transaction *trans, int final) |
| static int | dundi_answer_entity (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext) |
| static int | dundi_answer_query (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext) |
| static int | dundi_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| static void | dundi_debug_output (const char *data) |
| static struct dundi_hdr * | dundi_decrypt (struct dundi_transaction *trans, unsigned char *dst, int *dstlen, struct dundi_hdr *ohdr, struct dundi_encblock *src, int srclen) |
| static int | dundi_discover (struct dundi_transaction *trans) |
| static char * | dundi_do_lookup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dundi_do_precache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dundi_do_query (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dundi_encrypt (struct dundi_transaction *trans, struct dundi_packet *pack) |
| static void | dundi_error_output (const char *data) |
| static int | dundi_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| static int | dundi_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| static char * | dundi_flush (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dundi_helper (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *data, int flag) |
| static void | dundi_ie_append_eid_appropriately (struct dundi_ie_data *ied, char *context, dundi_eid *eid, dundi_eid *us) |
| int | dundi_lookup (struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int cbypass) |
| Lookup the given number in the given dundi context. Lookup number in a given dundi context (if unspecified use e164), the given callerid (if specified) and return up to maxret results in the array specified. | |
| static int | dundi_lookup_internal (struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *md, int *expiration, int cybpass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[]) |
| static int | dundi_lookup_local (struct dundi_result *dr, struct dundi_mapping *map, char *called_number, dundi_eid *us_eid, int anscnt, struct dundi_hint_metadata *hmd) |
| static void * | dundi_lookup_thread (void *data) |
| static int | dundi_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| int | dundi_precache (const char *context, const char *number) |
| Pre-cache to push upstream peers. | |
| static void | dundi_precache_full (void) |
| static int | dundi_precache_internal (const char *context, const char *number, int ttl, dundi_eid *avoids[]) |
| static void * | dundi_precache_thread (void *data) |
| static int | dundi_prop_precache (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext) |
| static int | dundi_query (struct dundi_transaction *trans) |
| int | dundi_query_eid (struct dundi_entity_info *dei, const char *dcontext, dundi_eid eid) |
| Retrieve information on a specific EID. | |
| static int | dundi_query_eid_internal (struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[]) |
| static int | dundi_query_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| static void * | dundi_query_thread (void *data) |
| static void | dundi_reject (struct dundi_hdr *h, struct sockaddr_in *sin) |
| static int | dundi_result_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| static int | dundi_rexmit (const void *data) |
| static int | dundi_send (struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied) |
| static char * | dundi_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dundi_show_entityid (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dundi_show_mappings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dundi_show_peer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dundi_show_peers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dundi_show_precache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dundi_show_requests (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dundi_show_trans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dundi_store_history (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dundi_xmit (struct dundi_packet *pack) |
| static int | dundifunc_read (struct ast_channel *chan, const char *cmd, char *num, char *buf, size_t len) |
| static int | encrypt_memcpy (unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_encrypt_key *ecx) |
| static struct dundi_peer * | find_peer (dundi_eid *eid) |
| static struct dundi_transaction * | find_transaction (struct dundi_hdr *hdr, struct sockaddr_in *sin) |
| static int | get_mapping_weight (struct dundi_mapping *map, struct varshead *headp) |
| static int | get_trans_id (void) |
| static int | handle_command_response (struct dundi_transaction *trans, struct dundi_hdr *hdr, int datalen, int encrypted) |
| static int | handle_frame (struct dundi_hdr *h, struct sockaddr_in *sin, int datalen) |
| static int | has_permission (struct permissionlist *permlist, char *cont) |
| static int | load_module (void) |
| static void | load_password (void) |
| static void | mark_mappings (void) |
| static void | mark_peers (void) |
| static char * | model2str (int model) |
| static void * | network_thread (void *ignore) |
| static int | optimize_transactions (struct dundi_request *dr, int order) |
| static void | populate_addr (struct dundi_peer *peer, dundi_eid *eid) |
| static int | precache_trans (struct dundi_transaction *trans, struct dundi_mapping *maps, int mapcount, int *minexp, int *foundanswers) |
| static int | precache_transactions (struct dundi_request *dr, struct dundi_mapping *maps, int mapcount, int *expiration, int *foundanswers) |
| static void * | process_clearcache (void *ignore) |
| static void * | process_precache (void *ign) |
| static void | prune_mappings (void) |
| static void | prune_peers (void) |
| static void | qualify_peer (struct dundi_peer *peer, int schedonly) |
| static int | query_transactions (struct dundi_request *dr) |
| static int | register_request (struct dundi_request *dr, struct dundi_request **pending) |
| static int | reload (void) |
| static void | reschedule_precache (const char *number, const char *context, int expiration) |
| static int | rescomp (const void *a, const void *b) |
| static int | reset_transaction (struct dundi_transaction *trans) |
| static void | save_secret (const char *newkey, const char *oldkey) |
| static int | set_config (char *config_file, struct sockaddr_in *sin, int reload) |
| static int | socket_read (int *id, int fd, short events, void *cbdata) |
| static void | sort_results (struct dundi_result *results, int count) |
| static int | start_network_thread (void) |
| static int | str2tech (char *str) |
| static char * | tech2str (int tech) |
| static int | unload_module (void) |
| static void | unregister_request (struct dundi_request *dr) |
| static int | update_key (struct dundi_peer *peer) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Distributed Universal Number Discovery (DUNDi)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_crypto", } |
| static struct dundi_peer * | any_peer |
| Wildcard peer. | |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static int | authdebug = 0 |
| static pthread_t | clearcachethreadid = AST_PTHREADT_NULL |
| static struct ast_cli_entry | cli_dundi [] |
| static char | country [80] |
| static char | cursecret [80] |
| static int | default_expiration = 60 |
| static char | dept [80] |
| static int | dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME |
| static struct ast_custom_function | dundi_function |
| static int | dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE |
| static struct ast_custom_function | dundi_query_function |
| static struct ast_app_option | dundi_query_opts [128] = { [ 'b' ] = { .flag = OPT_BYPASS_CACHE }, } |
| static struct ast_datastore_info | dundi_result_datastore_info |
| static struct ast_custom_function | dundi_result_function |
| static unsigned int | dundi_result_id |
| static int | dundi_shutdown = 0 |
| static struct ast_switch | dundi_switch |
| static int | dundi_ttl = DUNDI_DEFAULT_TTL |
| static int | dundidebug = 0 |
| static char | email [80] |
| static dundi_eid | empty_eid = { { 0, 0, 0, 0, 0, 0 } } |
| static int | global_autokilltimeout = 0 |
| static dundi_eid | global_eid |
| static int | global_storehistory = 0 |
| static struct io_context * | io |
| static char | ipaddr [80] |
| static char | locality [80] |
| static int | netsocket = -1 |
| static pthread_t | netthreadid = AST_PTHREADT_NULL |
| static char | org [80] |
| static char | phone [80] |
| static pthread_t | precachethreadid = AST_PTHREADT_NULL |
| static time_t | rotatetime |
| static struct ast_sched_context * | sched |
| static char | secretpath [80] |
| static char | stateprov [80] |
| static unsigned int | tos = 0 |
Definition in file pbx_dundi.c.
| #define DUNDI_FLAG_INTERNAL_NOPARTIAL (1 << 17) |
Definition at line 168 of file pbx_dundi.c.
Referenced by build_mapping(), and dundi_lookup_local().
| #define DUNDI_MODEL_INBOUND (1 << 0) |
Definition at line 151 of file pbx_dundi.c.
Referenced by build_peer(), dundi_show_peer(), handle_command_response(), and model2str().
| #define DUNDI_MODEL_OUTBOUND (1 << 1) |
Definition at line 152 of file pbx_dundi.c.
Referenced by build_peer(), build_transactions(), dundi_show_peer(), model2str(), and set_config().
| #define DUNDI_MODEL_SYMMETRIC (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND) |
| #define DUNDI_SECRET_TIME DUNDI_DEFAULT_CACHE_TIME |
| #define DUNDI_TIMING_HISTORY 10 |
Keep times of last 10 lookups
Definition at line 156 of file pbx_dundi.c.
Referenced by destroy_trans(), dundi_flush(), and dundi_show_peer().
| #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n" |
| #define FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n" |
| #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n" |
| #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n" |
| #define FORMAT "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n" |
| #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n" |
| #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n" |
| #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n" |
| #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n" |
| #define FORMAT2 "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n" |
| #define MAX_OPTS 128 |
| #define MAX_PACKET_SIZE 8192 |
Definition at line 147 of file pbx_dundi.c.
Referenced by handle_command_response(), and socket_read().
| #define MAX_RESULTS 64 |
Definition at line 145 of file pbx_dundi.c.
| #define MAX_WEIGHT 59999 |
Definition at line 149 of file pbx_dundi.c.
Referenced by build_mapping(), and get_mapping_weight().
| anonymous enum |
| FLAG_ISREG | Transaction is register request |
| FLAG_DEAD | Transaction is dead |
| FLAG_FINAL | Transaction has final message sent |
| FLAG_ISQUAL | Transaction is a qualification |
| FLAG_ENCRYPT | Transaction is encrypted wiht ECX/DCX |
| FLAG_SENDFULLKEY | Send full key on transaction |
| FLAG_STOREHIST | Record historic performance |
Definition at line 158 of file pbx_dundi.c.
00158 { 00159 FLAG_ISREG = (1 << 0), /*!< Transaction is register request */ 00160 FLAG_DEAD = (1 << 1), /*!< Transaction is dead */ 00161 FLAG_FINAL = (1 << 2), /*!< Transaction has final message sent */ 00162 FLAG_ISQUAL = (1 << 3), /*!< Transaction is a qualification */ 00163 FLAG_ENCRYPT = (1 << 4), /*!< Transaction is encrypted wiht ECX/DCX */ 00164 FLAG_SENDFULLKEY = (1 << 5), /*!< Send full key on transaction */ 00165 FLAG_STOREHIST = (1 << 6), /*!< Record historic performance */ 00166 };
| anonymous enum |
| static void __reg_module | ( | void | ) | [static] |
Definition at line 4893 of file pbx_dundi.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 4893 of file pbx_dundi.c.
| static void abort_request | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3448 of file pbx_dundi.c.
References AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, destroy_trans(), and dundi_request::trans.
Referenced by dundi_lookup_internal().
03449 { 03450 struct dundi_transaction *trans; 03451 03452 AST_LIST_LOCK(&peers); 03453 while ((trans = AST_LIST_FIRST(&dr->trans))) { 03454 /* This will remove the transaction from the list */ 03455 destroy_trans(trans, 0); 03456 } 03457 AST_LIST_UNLOCK(&peers); 03458 }
| static int ack_trans | ( | struct dundi_transaction * | trans, | |
| int | iseqno | |||
| ) | [static] |
Definition at line 2000 of file pbx_dundi.c.
References AST_LIST_EMPTY, AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_log(), AST_SCHED_DEL, dundi_transaction::autokillid, destroy_packet(), destroy_packets(), dundi_packet::h, dundi_transaction::lasttrans, LOG_WARNING, dundi_hdr::oseqno, and dundi_transaction::packets.
Referenced by handle_frame().
02001 { 02002 struct dundi_packet *pack; 02003 02004 /* Ack transmitted packet corresponding to iseqno */ 02005 AST_LIST_TRAVERSE(&trans->packets, pack, list) { 02006 if ((pack->h->oseqno + 1) % 255 == iseqno) { 02007 destroy_packet(pack, 0); 02008 if (!AST_LIST_EMPTY(&trans->lasttrans)) { 02009 ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n"); 02010 destroy_packets(&trans->lasttrans); 02011 } 02012 AST_LIST_INSERT_HEAD(&trans->lasttrans, pack, list); 02013 AST_SCHED_DEL(sched, trans->autokillid); 02014 return 1; 02015 } 02016 } 02017 02018 return 0; 02019 }
| static void append_permission | ( | struct permissionlist * | permlist, | |
| const char * | s, | |||
| int | allow | |||
| ) | [static] |
Definition at line 4211 of file pbx_dundi.c.
References permission::allow, ast_calloc, AST_LIST_INSERT_TAIL, and permission::name.
Referenced by build_peer().
04212 { 04213 struct permission *perm; 04214 04215 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(s) + 1))) 04216 return; 04217 04218 strcpy(perm->name, s); 04219 perm->allow = allow; 04220 04221 AST_LIST_INSERT_TAIL(permlist, perm, list); 04222 }
| static int append_transaction | ( | struct dundi_request * | dr, | |
| struct dundi_peer * | p, | |||
| int | ttl, | |||
| dundi_eid * | avoid[] | |||
| ) | [static] |
Definition at line 3403 of file pbx_dundi.c.
References dundi_peer::addr, ast_debug, ast_eid_to_str(), AST_LIST_INSERT_HEAD, ast_strlen_zero(), create_transaction(), dundi_request::dcontext, DUNDI_MAX_STACK, dundi_peer::eid, dundi_transaction::eidcount, dundi_transaction::eids, dundi_peer::lastms, dundi_peer::maxms, dundi_request::number, dundi_transaction::parent, dundi_request::query_eid, dundi_request::trans, and dundi_transaction::ttl.
Referenced by build_transactions().
03404 { 03405 struct dundi_transaction *trans; 03406 int x; 03407 char eid_str[20]; 03408 char eid_str2[20]; 03409 03410 /* Ignore if not registered */ 03411 if (!p->addr.sin_addr.s_addr) 03412 return 0; 03413 if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms))) 03414 return 0; 03415 03416 if (ast_strlen_zero(dr->number)) 03417 ast_debug(1, "Will query peer '%s' for '%s' (context '%s')\n", ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid), ast_eid_to_str(eid_str2, sizeof(eid_str2), &dr->query_eid), dr->dcontext); 03418 else 03419 ast_debug(1, "Will query peer '%s' for '%s@%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid), dr->number, dr->dcontext); 03420 03421 trans = create_transaction(p); 03422 if (!trans) 03423 return -1; 03424 trans->parent = dr; 03425 trans->ttl = ttl; 03426 for (x = 0; avoid[x] && (x < DUNDI_MAX_STACK); x++) 03427 trans->eids[x] = *avoid[x]; 03428 trans->eidcount = x; 03429 AST_LIST_INSERT_HEAD(&dr->trans, trans, parentlist); 03430 03431 return 0; 03432 }
| static void apply_peer | ( | struct dundi_transaction * | trans, | |
| struct dundi_peer * | p | |||
| ) | [static] |
Definition at line 1279 of file pbx_dundi.c.
References dundi_peer::addr, dundi_transaction::addr, ast_set_flag, ast_strlen_zero(), dundi_transaction::autokilltimeout, DUNDI_DEFAULT_RETRANS_TIMER, dundi_peer::eid, FLAG_ENCRYPT, dundi_peer::inkey, dundi_peer::lastms, dundi_peer::maxms, dundi_transaction::retranstimer, dundi_transaction::them_eid, dundi_peer::us_eid, and dundi_transaction::us_eid.
Referenced by create_transaction(), and handle_command_response().
01280 { 01281 if (!trans->addr.sin_addr.s_addr) 01282 memcpy(&trans->addr, &p->addr, sizeof(trans->addr)); 01283 trans->us_eid = p->us_eid; 01284 trans->them_eid = p->eid; 01285 /* Enable encryption if appropriate */ 01286 if (!ast_strlen_zero(p->inkey)) 01287 ast_set_flag(trans, FLAG_ENCRYPT); 01288 if (p->maxms) { 01289 trans->autokilltimeout = p->maxms; 01290 trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; 01291 if (p->lastms > 1) { 01292 trans->retranstimer = p->lastms * 2; 01293 /* Keep it from being silly */ 01294 if (trans->retranstimer < 150) 01295 trans->retranstimer = 150; 01296 } 01297 if (trans->retranstimer > DUNDI_DEFAULT_RETRANS_TIMER) 01298 trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; 01299 } else 01300 trans->autokilltimeout = global_autokilltimeout; 01301 }
| static unsigned long avoid_crc32 | ( | dundi_eid * | avoid[] | ) | [static] |
Definition at line 3569 of file pbx_dundi.c.
References dundi_request::crc32.
Referenced by dundi_lookup_internal().
03570 { 03571 /* Idea is that we're calculating a checksum which is independent of 03572 the order that the EID's are listed in */ 03573 uint32_t acrc32 = 0; 03574 int x; 03575 for (x=0;avoid[x];x++) { 03576 /* Order doesn't matter */ 03577 if (avoid[x+1]) { 03578 acrc32 ^= crc32(0L, (unsigned char *)avoid[x], sizeof(dundi_eid)); 03579 } 03580 } 03581 return acrc32; 03582 }
| static void build_iv | ( | unsigned char * | iv | ) | [static] |
Definition at line 522 of file pbx_dundi.c.
References ast_random().
Referenced by build_secret(), dundi_encrypt(), and update_key().
00523 { 00524 /* XXX Would be nice to be more random XXX */ 00525 unsigned int *fluffy; 00526 int x; 00527 fluffy = (unsigned int *)(iv); 00528 for (x=0;x<4;x++) 00529 fluffy[x] = ast_random(); 00530 }
| static void build_mapping | ( | const char * | name, | |
| const char * | value | |||
| ) | [static] |
Definition at line 4226 of file pbx_dundi.c.
References dundi_mapping::_weight, ast_calloc, ast_copy_string(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_log(), ast_strdup, ast_strdupa, ast_strlen_zero(), dundi_mapping::dcontext, dundi_mapping::dead, dundi_mapping::dest, DUNDI_FLAG_COMMERCIAL, DUNDI_FLAG_INTERNAL_NOPARTIAL, DUNDI_FLAG_MOBILE, DUNDI_FLAG_NOCOMUNSOLICIT, DUNDI_FLAG_NOUNSOLICITED, DUNDI_FLAG_RESIDENTIAL, dundi_mapping::lcontext, LOG_WARNING, map, MAX_OPTS, MAX_WEIGHT, dundi_mapping::options, str2tech(), dundi_mapping::tech, and dundi_mapping::weightstr.
Referenced by set_config().
04227 { 04228 char *t, *fields[MAX_OPTS]; 04229 struct dundi_mapping *map; 04230 int x; 04231 int y; 04232 04233 t = ast_strdupa(value); 04234 04235 AST_LIST_TRAVERSE(&mappings, map, list) { 04236 /* Find a double match */ 04237 if (!strcasecmp(map->dcontext, name) && 04238 (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) && 04239 (!value[strlen(map->lcontext)] || 04240 (value[strlen(map->lcontext)] == ',')))) 04241 break; 04242 } 04243 if (!map) { 04244 if (!(map = ast_calloc(1, sizeof(*map)))) 04245 return; 04246 AST_LIST_INSERT_HEAD(&mappings, map, list); 04247 map->dead = 1; 04248 } 04249 map->options = 0; 04250 memset(fields, 0, sizeof(fields)); 04251 x = 0; 04252 while (t && x < MAX_OPTS) { 04253 fields[x++] = t; 04254 t = strchr(t, ','); 04255 if (t) { 04256 *t = '\0'; 04257 t++; 04258 } 04259 } /* Russell was here, arrrr! */ 04260 if ((x == 1) && ast_strlen_zero(fields[0])) { 04261 /* Placeholder mapping */ 04262 ast_copy_string(map->dcontext, name, sizeof(map->dcontext)); 04263 map->dead = 0; 04264 } else if (x >= 4) { 04265 ast_copy_string(map->dcontext, name, sizeof(map->dcontext)); 04266 ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext)); 04267 if ((sscanf(fields[1], "%30d", &map->_weight) == 1) && (map->_weight >= 0) && (map->_weight <= MAX_WEIGHT)) { 04268 ast_copy_string(map->dest, fields[3], sizeof(map->dest)); 04269 if ((map->tech = str2tech(fields[2]))) 04270 map->dead = 0; 04271 } else if (!strncmp(fields[1], "${", 2) && fields[1][strlen(fields[1]) - 1] == '}') { 04272 map->weightstr = ast_strdup(fields[1]); 04273 ast_copy_string(map->dest, fields[3], sizeof(map->dest)); 04274 if ((map->tech = str2tech(fields[2]))) 04275 map->dead = 0; 04276 } else { 04277 ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext); 04278 } 04279 for (y = 4;y < x; y++) { 04280 if (!strcasecmp(fields[y], "nounsolicited")) 04281 map->options |= DUNDI_FLAG_NOUNSOLICITED; 04282 else if (!strcasecmp(fields[y], "nocomunsolicit")) 04283 map->options |= DUNDI_FLAG_NOCOMUNSOLICIT; 04284 else if (!strcasecmp(fields[y], "residential")) 04285 map->options |= DUNDI_FLAG_RESIDENTIAL; 04286 else if (!strcasecmp(fields[y], "commercial")) 04287 map->options |= DUNDI_FLAG_COMMERCIAL; 04288 else if (!strcasecmp(fields[y], "mobile")) 04289 map->options |= DUNDI_FLAG_MOBILE; 04290 else if (!strcasecmp(fields[y], "nopartial")) 04291 map->options |= DUNDI_FLAG_INTERNAL_NOPARTIAL; 04292 else 04293 ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]); 04294 } 04295 } else 04296 ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x); 04297 }
| static void build_peer | ( | dundi_eid * | eid, | |
| struct ast_variable * | v, | |||
| int * | globalpcmode | |||
| ) | [static] |
Definition at line 4381 of file pbx_dundi.c.
References dundi_peer::addr, append_permission(), ast_calloc, ast_copy_string(), ast_eid_cmp(), ast_eid_to_str(), ast_gethostbyname(), AST_LIST_EMPTY, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_sched_add(), AST_SCHED_DEL, ast_str_to_eid(), ast_true(), dundi_peer::dead, DEFAULT_MAXMS, destroy_permissions(), do_register(), DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, DUNDI_MODEL_SYMMETRIC, DUNDI_PORT, dundi_peer::dynamic, dundi_peer::eid, hp, dundi_peer::include, dundi_peer::inkey, ast_variable::lineno, LOG_WARNING, dundi_peer::maxms, dundi_peer::model, ast_variable::name, ast_variable::next, dundi_peer::order, dundi_peer::outkey, dundi_peer::pcmodel, dundi_peer::permit, populate_addr(), qualify_peer(), dundi_peer::qualifyid, dundi_peer::registerexpire, dundi_peer::registerid, dundi_peer::us_eid, and ast_variable::value.
04382 { 04383 struct dundi_peer *peer; 04384 struct ast_hostent he; 04385 struct hostent *hp; 04386 dundi_eid testeid; 04387 int needregister=0; 04388 char eid_str[20]; 04389 04390 AST_LIST_LOCK(&peers); 04391 AST_LIST_TRAVERSE(&peers, peer, list) { 04392 if (!ast_eid_cmp(&peer->eid, eid)) { 04393 break; 04394 } 04395 } 04396 if (!peer) { 04397 /* Add us into the list */ 04398 if (!(peer = ast_calloc(1, sizeof(*peer)))) { 04399 AST_LIST_UNLOCK(&peers); 04400 return; 04401 } 04402 peer->registerid = -1; 04403 peer->registerexpire = -1; 04404 peer->qualifyid = -1; 04405 peer->addr.sin_family = AF_INET; 04406 peer->addr.sin_port = htons(DUNDI_PORT); 04407 populate_addr(peer, eid); 04408 AST_LIST_INSERT_HEAD(&peers, peer, list); 04409 } 04410 peer->dead = 0; 04411 peer->eid = *eid; 04412 peer->us_eid = global_eid; 04413 destroy_permissions(&peer->permit); 04414 destroy_permissions(&peer->include); 04415 AST_SCHED_DEL(sched, peer->registerid); 04416 for (; v; v = v->next) { 04417 if (!strcasecmp(v->name, "inkey")) { 04418 ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey)); 04419 } else if (!strcasecmp(v->name, "outkey")) { 04420 ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey)); 04421 } else if (!strcasecmp(v->name, "port")) { 04422 peer->addr.sin_port = htons(atoi(v->value)); 04423 } else if (!strcasecmp(v->name, "host")) { 04424 if (!strcasecmp(v->value, "dynamic")) { 04425 peer->dynamic = 1; 04426 } else { 04427 hp = ast_gethostbyname(v->value, &he); 04428 if (hp) { 04429 memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr)); 04430 peer->dynamic = 0; 04431 } else { 04432 ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno); 04433 peer->dead = 1; 04434 } 04435 } 04436 } else if (!strcasecmp(v->name, "ustothem")) { 04437 if (!ast_str_to_eid(&testeid, v->value)) 04438 peer->us_eid = testeid; 04439 else 04440 ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno); 04441 } else if (!strcasecmp(v->name, "include")) { 04442 append_permission(&peer->include, v->value, 1); 04443 } else if (!strcasecmp(v->name, "permit")) { 04444 append_permission(&peer->permit, v->value, 1); 04445 } else if (!strcasecmp(v->name, "noinclude")) { 04446 append_permission(&peer->include, v->value, 0); 04447 } else if (!strcasecmp(v->name, "deny")) { 04448 append_permission(&peer->permit, v->value, 0); 04449 } else if (!strcasecmp(v->name, "register")) { 04450 needregister = ast_true(v->value); 04451 } else if (!strcasecmp(v->name, "order")) { 04452 if (!strcasecmp(v->value, "primary")) 04453 peer->order = 0; 04454 else if (!strcasecmp(v->value, "secondary")) 04455 peer->order = 1; 04456 else if (!strcasecmp(v->value, "tertiary")) 04457 peer->order = 2; 04458 else if (!strcasecmp(v->value, "quartiary")) 04459 peer->order = 3; 04460 else { 04461 ast_log(LOG_WARNING, "'%s' is not a valid order, should be primary, secondary, tertiary or quartiary at line %d\n", v->value, v->lineno); 04462 } 04463 } else if (!strcasecmp(v->name, "qualify")) { 04464 if (!strcasecmp(v->value, "no")) { 04465 peer->maxms = 0; 04466 } else if (!strcasecmp(v->value, "yes")) { 04467 peer->maxms = DEFAULT_MAXMS; 04468 } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) { 04469 ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n", 04470 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno); 04471 peer->maxms = 0; 04472 } 04473 } else if (!strcasecmp(v->name, "model")) { 04474 if (!strcasecmp(v->value, "inbound")) 04475 peer->model = DUNDI_MODEL_INBOUND; 04476 else if (!strcasecmp(v->value, "outbound")) 04477 peer->model = DUNDI_MODEL_OUTBOUND; 04478 else if (!strcasecmp(v->value, "symmetric")) 04479 peer->model = DUNDI_MODEL_SYMMETRIC; 04480 else if (!strcasecmp(v->value, "none")) 04481 peer->model = 0; 04482 else { 04483 ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 04484 v->value, v->lineno); 04485 } 04486 } else if (!strcasecmp(v->name, "precache")) { 04487 if (!strcasecmp(v->value, "inbound")) 04488 peer->pcmodel = DUNDI_MODEL_INBOUND; 04489 else if (!strcasecmp(v->value, "outbound")) 04490 peer->pcmodel = DUNDI_MODEL_OUTBOUND; 04491 else if (!strcasecmp(v->value, "symmetric")) 04492 peer->pcmodel = DUNDI_MODEL_SYMMETRIC; 04493 else if (!strcasecmp(v->value, "none")) 04494 peer->pcmodel = 0; 04495 else { 04496 ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 04497 v->value, v->lineno); 04498 } 04499 } 04500 } 04501 (*globalpcmode) |= peer->pcmodel; 04502 if (!peer->model && !peer->pcmodel) { 04503 ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n", 04504 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04505 peer->dead = 1; 04506 } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) { 04507 ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n", 04508 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04509 peer->dead = 1; 04510 } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) { 04511 ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n", 04512 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04513 peer->dead = 1; 04514 } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) { 04515 ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n", 04516 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04517 } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) { 04518 ast_log(LOG_WARNING, "Peer '%s' is supposed to have permission for some inbound searches but isn't an inbound peer or outbound precache!\n", 04519 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04520 } else { 04521 if (needregister) { 04522 peer->registerid = ast_sched_add(sched, 2000, do_register, peer); 04523 } 04524 qualify_peer(peer, 1); 04525 } 04526 AST_LIST_UNLOCK(&peers); 04527 }
| static void build_secret | ( | char * | secret, | |
| int | seclen | |||
| ) | [static] |
Definition at line 2090 of file pbx_dundi.c.
References ast_base64encode(), and build_iv().
Referenced by check_password(), and load_password().
02091 { 02092 unsigned char tmp[16]; 02093 char *s; 02094 build_iv(tmp); 02095 secret[0] = '\0'; 02096 ast_base64encode(secret, tmp, sizeof(tmp), seclen); 02097 /* Eliminate potential bad characters */ 02098 while((s = strchr(secret, ';'))) *s = '+'; 02099 while((s = strchr(secret, '/'))) *s = '+'; 02100 while((s = strchr(secret, ':'))) *s = '+'; 02101 while((s = strchr(secret, '@'))) *s = '+'; 02102 }
| static void build_transactions | ( | struct dundi_request * | dr, | |
| int | ttl, | |||
| int | order, | |||
| int * | foundcache, | |||
| int * | skipped, | |||
| int | blockempty, | |||
| int | nocache, | |||
| int | modeselect, | |||
| dundi_eid * | skip, | |||
| dundi_eid * | avoid[], | |||
| int | directs[] | |||
| ) | [static] |
Definition at line 3460 of file pbx_dundi.c.
References append_transaction(), ast_clear_flag_nonstd, ast_debug, ast_eid_cmp(), ast_eid_to_str(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, cache_lookup(), dundi_request::crc32, dundi_request::dcontext, dundi_eid_zero(), DUNDI_HINT_UNAFFECTED, DUNDI_MODEL_OUTBOUND, dundi_peer::eid, dundi_request::expiration, has_permission(), dundi_request::hmd, dundi_peer::include, dundi_peer::model, dundi_peer::order, pass, dundi_peer::pcmodel, dundi_peer::permit, and dundi_peer::us_eid.
Referenced by dundi_lookup_internal(), dundi_precache_internal(), and dundi_query_eid_internal().
03461 { 03462 struct dundi_peer *p; 03463 int x; 03464 int res; 03465 int pass; 03466 int allowconnect; 03467 char eid_str[20]; 03468 AST_LIST_LOCK(&peers); 03469 AST_LIST_TRAVERSE(&peers, p, list) { 03470 if (modeselect == 1) { 03471 /* Send the precache to push upstreams only! */ 03472 pass = has_permission(&p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND); 03473 allowconnect = 1; 03474 } else { 03475 /* Normal lookup / EID query */ 03476 pass = has_permission(&p->include, dr->dcontext); 03477 allowconnect = p->model & DUNDI_MODEL_OUTBOUND; 03478 } 03479 if (skip) { 03480 if (!ast_eid_cmp(skip, &p->eid)) 03481 pass = 0; 03482 } 03483 if (pass) { 03484 if (p->order <= order) { 03485 /* Check order first, then check cache, regardless of 03486 omissions, this gets us more likely to not have an 03487 affected answer. */ 03488 if((nocache || !(res = cache_lookup(dr, &p->eid, dr->crc32, &dr->expiration)))) { 03489 res = 0; 03490 /* Make sure we haven't already seen it and that it won't 03491 affect our answer */ 03492 for (x=0;avoid[x];x++) { 03493 if (!ast_eid_cmp(avoid[x], &p->eid) || !ast_eid_cmp(avoid[x], &p->us_eid)) { 03494 /* If not a direct connection, it affects our answer */ 03495 if (directs && !directs[x]) 03496 ast_clear_flag_nonstd(dr->hmd, DUNDI_HINT_UNAFFECTED); 03497 break; 03498 } 03499 } 03500 /* Make sure we can ask */ 03501 if (allowconnect) { 03502 if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) { 03503 /* Check for a matching or 0 cache entry */ 03504 append_transaction(dr, p, ttl, avoid); 03505 } else { 03506 ast_debug(1, "Avoiding '%s' in transaction\n", ast_eid_to_str(eid_str, sizeof(eid_str), avoid[x])); 03507 } 03508 } 03509 } 03510 *foundcache |= res; 03511 } else if (!*skipped || (p->order < *skipped)) 03512 *skipped = p->order; 03513 } 03514 } 03515 AST_LIST_UNLOCK(&peers); 03516 }
| static int cache_lookup | ( | struct dundi_request * | req, | |
| dundi_eid * | peer_eid, | |||
| uint32_t | crc32, | |||
| int * | lowexpiration | |||
| ) | [static] |
Definition at line 1227 of file pbx_dundi.c.
References ast_copy_string(), ast_eid_to_str(), cache_lookup_internal(), dundi_request::dcontext, dundi_eid_to_str_short(), dundi_hint_metadata::exten, dundi_request::hmd, dundi_request::number, dundi_request::respcount, and dundi_request::root_eid.
Referenced by build_transactions().
01228 { 01229 char key[256]; 01230 char eid_str[20]; 01231 char eidroot_str[20]; 01232 time_t now; 01233 int res=0; 01234 int res2=0; 01235 char eid_str_full[20]; 01236 char tmp[256]=""; 01237 int x; 01238 01239 time(&now); 01240 dundi_eid_to_str_short(eid_str, sizeof(eid_str), peer_eid); 01241 dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); 01242 ast_eid_to_str(eid_str_full, sizeof(eid_str_full), peer_eid); 01243 snprintf(key, sizeof(key), "%s/%s/%s/e%08x", eid_str, req->number, req->dcontext, crc32); 01244 res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01245 snprintf(key, sizeof(key), "%s/%s/%s/e%08x", eid_str, req->number, req->dcontext, 0); 01246 res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01247 snprintf(key, sizeof(key), "%s/%s/%s/r%s", eid_str, req->number, req->dcontext, eidroot_str); 01248 res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01249 x = 0; 01250 if (!req->respcount) { 01251 while(!res2) { 01252 /* Look and see if we have a hint that would preclude us from looking at this 01253 peer for this number. */ 01254 if (!(tmp[x] = req->number[x])) 01255 break; 01256 x++; 01257 /* Check for hints */ 01258 snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08x", eid_str, tmp, req->dcontext, crc32); 01259 res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01260 snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08x", eid_str, tmp, req->dcontext, 0); 01261 res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01262 snprintf(key, sizeof(key), "hint/%s/%s/%s/r%s", eid_str, tmp, req->dcontext, eidroot_str); 01263 res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01264 if (res2) { 01265 if (strlen(tmp) > strlen(req->hmd->exten)) { 01266 /* Update meta data if appropriate */ 01267 ast_copy_string(req->hmd->exten, tmp, sizeof(req->hmd->exten)); 01268 } 01269 } 01270 } 01271 res |= res2; 01272 } 01273 01274 return res; 01275 }
| static int cache_lookup_internal | ( | time_t | now, | |
| struct dundi_request * | req, | |||
| char * | key, | |||
| char * | eid_str_full, | |||
| int * | lowexpiration | |||
| ) | [static] |
Definition at line 1155 of file pbx_dundi.c.
References ast_clear_flag_nonstd, ast_copy_flags, ast_copy_string(), ast_db_del(), ast_db_get(), ast_debug, ast_eid_to_str(), AST_FLAGS_ALL, ast_get_time_t(), dundi_result::dest, dundi_request::dr, dundi_flags2str(), DUNDI_HINT_DONT_ASK, dundi_str_short_to_eid(), dundi_result::eid, dundi_result::eid_str, dundi_result::expiration, ast_flags::flags, dundi_request::hmd, dundi_request::respcount, dundi_result::tech, tech2str(), dundi_result::techint, and dundi_result::weight.
Referenced by cache_lookup().
01156 { 01157 char data[1024]; 01158 char *ptr, *term, *src; 01159 int tech; 01160 struct ast_flags flags; 01161 int weight; 01162 int length; 01163 int z; 01164 char fs[256]; 01165 01166 /* Build request string */ 01167 if (!ast_db_get("dundi/cache", key, data, sizeof(data))) { 01168 time_t timeout; 01169 ptr = data; 01170 if (!ast_get_time_t(ptr, &timeout, 0, &length)) { 01171 int expiration = timeout - now; 01172 if (expiration > 0) { 01173 ast_debug(1, "Found cache expiring in %d seconds!\n", expiration); 01174 ptr += length + 1; 01175 while((sscanf(ptr, "%30d/%30d/%30d/%n", &(flags.flags), &weight, &tech, &length) == 3)) { 01176 ptr += length; 01177 term = strchr(ptr, '|'); 01178 if (term) { 01179 *term = '\0'; 01180 src = strrchr(ptr, '/'); 01181 if (src) { 01182 *src = '\0'; 01183 src++; 01184 } else 01185 src = ""; 01186 ast_debug(1, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n", 01187 tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags.flags), eid_str_full); 01188 /* Make sure it's not already there */ 01189 for (z=0;z<req->respcount;z++) { 01190 if ((req->dr[z].techint == tech) && 01191 !strcmp(req->dr[z].dest, ptr)) 01192 break; 01193 } 01194 if (z == req->respcount) { 01195 /* Copy into parent responses */ 01196 ast_copy_flags(&(req->dr[req->respcount]), &flags, AST_FLAGS_ALL); 01197 req->dr[req->respcount].weight = weight; 01198 req->dr[req->respcount].techint = tech; 01199 req->dr[req->respcount].expiration = expiration; 01200 dundi_str_short_to_eid(&req->dr[req->respcount].eid, src); 01201 ast_eid_to_str(req->dr[req->respcount].eid_str, 01202 sizeof(req->dr[req->respcount].eid_str), &req->dr[req->respcount].eid); 01203 ast_copy_string(req->dr[req->respcount].dest, ptr, 01204 sizeof(req->dr[req->respcount].dest)); 01205 ast_copy_string(req->dr[req->respcount].tech, tech2str(tech), 01206 sizeof(req->dr[req->respcount].tech)); 01207 req->respcount++; 01208 ast_clear_flag_nonstd(req->hmd, DUNDI_HINT_DONT_ASK); 01209 } else if (req->dr[z].weight > weight) 01210 req->dr[z].weight = weight; 01211 ptr = term + 1; 01212 } 01213 } 01214 /* We found *something* cached */ 01215 if (expiration < *lowexpiration) 01216 *lowexpiration = expiration; 01217 return 1; 01218 } else 01219 ast_db_del("dundi/cache", key); 01220 } else 01221 ast_db_del("dundi/cache", key); 01222 } 01223 01224 return 0; 01225 }
| static int cache_save | ( | dundi_eid * | eidpeer, | |
| struct dundi_request * | req, | |||
| int | start, | |||
| int | unaffected, | |||
| int | expiration, | |||
| int | push | |||
| ) | [static] |
Definition at line 884 of file pbx_dundi.c.
References ast_db_put(), dundi_request::crc32, dundi_request::dcontext, dundi_result::dest, dundi_request::dr, dundi_eid_to_str_short(), dundi_result::eid, dundi_result::flags, dundi_request::number, dundi_request::respcount, dundi_request::root_eid, dundi_result::techint, and dundi_result::weight.
Referenced by dundi_prop_precache(), and handle_command_response().
00885 { 00886 int x; 00887 char key1[256]; 00888 char key2[256]; 00889 char data[1024]; 00890 char eidpeer_str[20]; 00891 char eidroot_str[20]; 00892 time_t timeout; 00893 00894 if (expiration < 1) 00895 expiration = dundi_cache_time; 00896 00897 /* Keep pushes a little longer, cut pulls a little short */ 00898 if (push) 00899 expiration += 10; 00900 else 00901 expiration -= 10; 00902 if (expiration < 1) 00903 expiration = 1; 00904 dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer); 00905 dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); 00906 snprintf(key1, sizeof(key1), "%s/%s/%s/e%08x", eidpeer_str, req->number, req->dcontext, unaffected ? 0 : req->crc32); 00907 snprintf(key2, sizeof(key2), "%s/%s/%s/r%s", eidpeer_str, req->number, req->dcontext, eidroot_str); 00908 /* Build request string */ 00909 time(&timeout); 00910 timeout += expiration; 00911 snprintf(data, sizeof(data), "%ld|", (long)(timeout)); 00912 for (x=start;x<req->respcount;x++) { 00913 /* Skip anything with an illegal pipe in it */ 00914 if (strchr(req->dr[x].dest, '|')) 00915 continue; 00916 snprintf(data + strlen(data), sizeof(data) - strlen(data), "%d/%d/%d/%s/%s|", 00917 req->dr[x].flags, req->dr[x].weight, req->dr[x].techint, req->dr[x].dest, 00918 dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), &req->dr[x].eid)); 00919 } 00920 ast_db_put("dundi/cache", key1, data); 00921 ast_db_put("dundi/cache", key2, data); 00922 return 0; 00923 }
| static int cache_save_hint | ( | dundi_eid * | eidpeer, | |
| struct dundi_request * | req, | |||
| struct dundi_hint * | hint, | |||
| int | expiration | |||
| ) | [static] |
Definition at line 849 of file pbx_dundi.c.
References ast_db_put(), ast_debug, ast_test_flag_nonstd, dundi_request::crc32, dundi_hint::data, dundi_request::dcontext, dundi_eid_to_str_short(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, and dundi_request::root_eid.
Referenced by dundi_prop_precache(), and handle_command_response().
00850 { 00851 int unaffected; 00852 char key1[256]; 00853 char key2[256]; 00854 char eidpeer_str[20]; 00855 char eidroot_str[20]; 00856 char data[80]; 00857 time_t timeout; 00858 00859 if (expiration < 0) 00860 expiration = dundi_cache_time; 00861 00862 /* Only cache hint if "don't ask" is there... */ 00863 if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK))) 00864 return 0; 00865 00866 unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED)); 00867 00868 dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer); 00869 dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); 00870 snprintf(key1, sizeof(key1), "hint/%s/%s/%s/e%08x", eidpeer_str, hint->data, req->dcontext, unaffected ? 0 : req->crc32); 00871 snprintf(key2, sizeof(key2), "hint/%s/%s/%s/r%s", eidpeer_str, hint->data, req->dcontext, eidroot_str); 00872 00873 time(&timeout); 00874 timeout += expiration; 00875 snprintf(data, sizeof(data), "%ld|", (long)(timeout)); 00876 00877 ast_db_put("dundi/cache", key1, data); 00878 ast_debug(1, "Caching hint at '%s'\n", key1); 00879 ast_db_put("dundi/cache", key2, data); 00880 ast_debug(1, "Caching hint at '%s'\n", key2); 00881 return 0; 00882 }
| static void cancel_request | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3434 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, DUNDI_COMMAND_CANCEL, dundi_send(), dundi_transaction::parent, and dundi_request::trans.
Referenced by dundi_lookup_internal(), and dundi_precache_internal().
03435 { 03436 struct dundi_transaction *trans; 03437 03438 AST_LIST_LOCK(&peers); 03439 while ((trans = AST_LIST_REMOVE_HEAD(&dr->trans, parentlist))) { 03440 /* Orphan transaction from request */ 03441 trans->parent = NULL; 03442 /* Send final cancel */ 03443 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 03444 } 03445 AST_LIST_UNLOCK(&peers); 03446 }
| static int check_key | ( | struct dundi_peer * | peer, | |
| unsigned char * | newkey, | |||
| unsigned char * | newsig, | |||
| uint32_t | keycrc32 | |||
| ) | [static] |
Definition at line 1478 of file pbx_dundi.c.
References ast_aes_set_decrypt_key(), ast_aes_set_encrypt_key(), ast_check_signature_bin(), ast_debug, ast_decrypt_bin(), ast_eid_to_str(), ast_key_get(), AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log(), dundi_peer::eid, dundi_peer::inkey, LOG_NOTICE, dundi_peer::outkey, dundi_peer::rxenckey, dundi_peer::them_dcx, dundi_peer::them_ecx, and dundi_peer::them_keycrc32.
Referenced by handle_command_response().
01479 { 01480 unsigned char dst[128]; 01481 int res; 01482 struct ast_key *key, *skey; 01483 char eid_str[20]; 01484 ast_debug(1, "Expected '%08x' got '%08x'\n", peer->them_keycrc32, keycrc32); 01485 if (peer->them_keycrc32 && (peer->them_keycrc32 == keycrc32)) { 01486 /* A match */ 01487 return 1; 01488 } else if (!newkey || !newsig) 01489 return 0; 01490 if (!memcmp(peer->rxenckey, newkey, 128) && 01491 !memcmp(peer->rxenckey + 128, newsig, 128)) { 01492 /* By definition, a match */ 01493 return 1; 01494 } 01495 /* Decrypt key */ 01496 key = ast_key_get(peer->outkey, AST_KEY_PRIVATE); 01497 if (!key) { 01498 ast_log(LOG_NOTICE, "Unable to find key '%s' to decode shared key from '%s'\n", 01499 peer->outkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01500 return -1; 01501 } 01502 01503 skey = ast_key_get(peer->inkey, AST_KEY_PUBLIC); 01504 if (!skey) { 01505 ast_log(LOG_NOTICE, "Unable to find key '%s' to verify shared key from '%s'\n", 01506 peer->inkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01507 return -1; 01508 } 01509 01510 /* First check signature */ 01511 res = ast_check_signature_bin(skey, (char *)newkey, 128, newsig); 01512 if (res) 01513 return 0; 01514 01515 res = ast_decrypt_bin(dst, newkey, sizeof(dst), key); 01516 if (res != 16) { 01517 if (res >= 0) 01518 ast_log(LOG_NOTICE, "Weird, key decoded to the wrong size (%d)\n", res); 01519 return 0; 01520 } 01521 /* Decrypted, passes signature */ 01522 ast_debug(1, "Wow, new key combo passed signature and decrypt!\n"); 01523 memcpy(peer->rxenckey, newkey, 128); 01524 memcpy(peer->rxenckey + 128, newsig, 128); 01525 peer->them_keycrc32 = crc32(0L, peer->rxenckey, 128); 01526 ast_aes_set_decrypt_key(dst, &peer->them_dcx); 01527 ast_aes_set_encrypt_key(dst, &peer->them_ecx); 01528 return 1; 01529 }
| static void check_password | ( | void | ) | [static] |
Definition at line 2157 of file pbx_dundi.c.
References ast_copy_string(), build_secret(), and save_secret().
02158 { 02159 char oldsecret[80]; 02160 time_t now; 02161 02162 time(&now); 02163 #if 0 02164 printf("%ld/%ld\n", now, rotatetime); 02165 #endif 02166 if ((now - rotatetime) >= 0) { 02167 /* Time to rotate keys */ 02168 ast_copy_string(oldsecret, cursecret, sizeof(oldsecret)); 02169 build_secret(cursecret, sizeof(cursecret)); 02170 save_secret(cursecret, oldsecret); 02171 } 02172 }
| static int check_request | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3555 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.
Referenced by dundi_lookup_internal().
03556 { 03557 struct dundi_request *cur; 03558 03559 AST_LIST_LOCK(&peers); 03560 AST_LIST_TRAVERSE(&requests, cur, list) { 03561 if (cur == dr) 03562 break; 03563 } 03564 AST_LIST_UNLOCK(&peers); 03565 03566 return cur ? 1 : 0; 03567 }
| static char* complete_peer_helper | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state, | |||
| int | rpos | |||
| ) | [static] |
Definition at line 2391 of file pbx_dundi.c.
References ast_eid_to_str(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, dundi_peer::eid, and len().
Referenced by dundi_show_peer().
02392 { 02393 int which=0, len; 02394 char *ret = NULL; 02395 struct dundi_peer *p; 02396 char eid_str[20]; 02397 02398 if (pos != rpos) 02399 return NULL; 02400 AST_LIST_LOCK(&peers); 02401 len = strlen(word); 02402 AST_LIST_TRAVERSE(&peers, p, list) { 02403 const char *s = ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid); 02404 if (!strncasecmp(word, s, len) && ++which > state) { 02405 ret = ast_strdup(s); 02406 break; 02407 } 02408 } 02409 AST_LIST_UNLOCK(&peers); 02410 return ret; 02411 }
| static struct dundi_transaction * create_transaction | ( | struct dundi_peer * | p | ) | [static, read] |
Definition at line 2910 of file pbx_dundi.c.
References dundi_peer::addr, apply_peer(), ast_calloc, AST_LIST_INSERT_HEAD, ast_set_flag, ast_tvnow(), dundi_transaction::autokillid, DUNDI_DEFAULT_RETRANS_TIMER, FLAG_SENDFULLKEY, FLAG_STOREHIST, get_trans_id(), dundi_transaction::retranstimer, dundi_peer::sentfullkey, dundi_transaction::start, and dundi_transaction::strans.
Referenced by append_transaction(), do_register(), find_transaction(), and qualify_peer().
02911 { 02912 struct dundi_transaction *trans; 02913 int tid; 02914 02915 /* Don't allow creation of transactions to non-registered peers */ 02916 if (p && !p->addr.sin_addr.s_addr) 02917 return NULL; 02918 tid = get_trans_id(); 02919 if (tid < 1) 02920 return NULL; 02921 if (!(trans = ast_calloc(1, sizeof(*trans)))) 02922 return NULL; 02923 02924 if (global_storehistory) { 02925 trans->start = ast_tvnow(); 02926 ast_set_flag(trans, FLAG_STOREHIST); 02927 } 02928 trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; 02929 trans->autokillid = -1; 02930 if (p) { 02931 apply_peer(trans, p); 02932 if (!p->sentfullkey) 02933 ast_set_flag(trans, FLAG_SENDFULLKEY); 02934 } 02935 trans->strans = tid; 02936 AST_LIST_INSERT_HEAD(&alltrans, trans, all); 02937 02938 return trans; 02939 }
| static int decrypt_memcpy | ( | unsigned char * | dst, | |
| unsigned char * | src, | |||
| int | len, | |||
| unsigned char * | iv, | |||
| ast_aes_decrypt_key * | dcx | |||
| ) | [static] |
Definition at line 1370 of file pbx_dundi.c.
References ast_aes_decrypt().
Referenced by dundi_decrypt().
01371 { 01372 unsigned char lastblock[16]; 01373 int x; 01374 memcpy(lastblock, iv, sizeof(lastblock)); 01375 while(len > 0) { 01376 ast_aes_decrypt(src, dst, dcx); 01377 for (x=0;x<16;x++) 01378 dst[x] ^= lastblock[x]; 01379 memcpy(lastblock, src, sizeof(lastblock)); 01380 dst += 16; 01381 src += 16; 01382 len -= 16; 01383 } 01384 return 0; 01385 }
| static void deep_copy_peer | ( | struct dundi_peer * | peer_dst, | |
| const struct dundi_peer * | peer_src | |||
| ) | [static] |
Definition at line 1531 of file pbx_dundi.c.
References permission::allow, ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, dundi_peer::include, permission::name, and dundi_peer::permit.
Referenced by handle_command_response().
01532 { 01533 struct permission *cur, *perm; 01534 01535 memcpy(peer_dst, peer_src, sizeof(*peer_dst)); 01536 01537 memset(&peer_dst->permit, 0, sizeof(peer_dst->permit)); 01538 memset(&peer_dst->include, 0, sizeof(peer_dst->permit)); 01539 01540 AST_LIST_TRAVERSE(&peer_src->permit, cur, list) { 01541 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1))) 01542 continue; 01543 01544 perm->allow = cur->allow; 01545 strcpy(perm->name, cur->name); 01546 01547 AST_LIST_INSERT_HEAD(&peer_dst->permit, perm, list); 01548 } 01549 01550 AST_LIST_TRAVERSE(&peer_src->include, cur, list) { 01551 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1))) 01552 continue; 01553 01554 perm->allow = cur->allow; 01555 strcpy(perm->name, cur->name); 01556 01557 AST_LIST_INSERT_HEAD(&peer_dst->include, perm, list); 01558 } 01559 }
| static void destroy_map | ( | struct dundi_mapping * | map | ) | [static] |
Definition at line 4174 of file pbx_dundi.c.
References ast_free, and dundi_mapping::weightstr.
Referenced by prune_mappings().
| static void destroy_packet | ( | struct dundi_packet * | pack, | |
| int | needfree | |||
| ) | [static] |
Definition at line 2957 of file pbx_dundi.c.
References ast_free, AST_LIST_REMOVE, AST_SCHED_DEL, dundi_transaction::packets, dundi_packet::parent, and dundi_packet::retransid.
Referenced by ack_trans().
02958 { 02959 if (pack->parent) 02960 AST_LIST_REMOVE(&pack->parent->packets, pack, list); 02961 AST_SCHED_DEL(sched, pack->retransid); 02962 if (needfree) 02963 ast_free(pack); 02964 }
| static void destroy_packets | ( | struct packetlist * | p | ) | [static] |
Definition at line 1989 of file pbx_dundi.c.
References ast_free, AST_LIST_REMOVE_HEAD, AST_SCHED_DEL, and dundi_packet::retransid.
Referenced by ack_trans(), destroy_trans(), and handle_frame().
01990 { 01991 struct dundi_packet *pack; 01992 01993 while ((pack = AST_LIST_REMOVE_HEAD(p, list))) { 01994 AST_SCHED_DEL(sched, pack->retransid); 01995 ast_free(pack); 01996 } 01997 }
| static void destroy_peer | ( | struct dundi_peer * | peer | ) | [static] |
Definition at line 4163 of file pbx_dundi.c.
References ast_free, AST_SCHED_DEL, destroy_permissions(), destroy_trans(), dundi_peer::include, dundi_peer::permit, dundi_peer::qualifyid, dundi_peer::registerid, and dundi_peer::regtrans.
Referenced by prune_peers().
04164 { 04165 AST_SCHED_DEL(sched, peer->registerid); 04166 if (peer->regtrans) 04167 destroy_trans(peer->regtrans, 0); 04168 AST_SCHED_DEL(sched, peer->qualifyid); 04169 destroy_permissions(&peer->permit); 04170 destroy_permissions(&peer->include); 04171 ast_free(peer); 04172 }
| static void destroy_permissions | ( | struct permissionlist * | permlist | ) | [static] |
Definition at line 4155 of file pbx_dundi.c.
References ast_free, and AST_LIST_REMOVE_HEAD.
Referenced by build_peer(), and destroy_peer().
04156 { 04157 struct permission *perm; 04158 04159 while ((perm = AST_LIST_REMOVE_HEAD(permlist, list))) 04160 ast_free(perm); 04161 }
| static void destroy_trans | ( | struct dundi_transaction * | trans, | |
| int | fromtimeout | |||
| ) | [static] |
Definition at line 2966 of file pbx_dundi.c.
References ast_eid_cmp(), ast_eid_to_str(), ast_free, AST_LIST_EMPTY, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_log(), ast_malloc, AST_SCHED_DEL, ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), dundi_transaction::autokillid, dundi_peer::avgms, dundi_request::dcontext, destroy_packets(), DUNDI_TIMING_HISTORY, dundi_peer::eid, errno, FLAG_DEAD, FLAG_ISQUAL, FLAG_ISREG, FLAG_STOREHIST, dundi_peer::lastms, dundi_transaction::lasttrans, LOG_NOTICE, LOG_WARNING, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::maxms, dundi_request::number, dundi_transaction::packets, dundi_transaction::parent, dundi_request::pfds, dundi_peer::qualtrans, dundi_peer::qualtx, dundi_peer::regtrans, dundi_transaction::start, dundi_transaction::them_eid, dundi_transaction::thread, and dundi_request::trans.
Referenced by abort_request(), destroy_peer(), do_autokill(), do_register(), dundi_lookup_thread(), dundi_precache_thread(), dundi_query_thread(), dundi_rexmit(), handle_frame(), precache_trans(), precache_transactions(), and qualify_peer().
02967 { 02968 struct dundi_peer *peer; 02969 int ms; 02970 int x; 02971 int cnt; 02972 char eid_str[20]; 02973 if (ast_test_flag(trans, FLAG_ISREG | FLAG_ISQUAL | FLAG_STOREHIST)) { 02974 AST_LIST_TRAVERSE(&peers, peer, list) { 02975 if (peer->regtrans == trans) 02976 peer->regtrans = NULL; 02977 if (peer->qualtrans == trans) { 02978 if (fromtimeout) { 02979 if (peer->lastms > -1) 02980 ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02981 peer->lastms = -1; 02982 } else { 02983 ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx); 02984 if (ms < 1) 02985 ms = 1; 02986 if (ms < peer->maxms) { 02987 if ((peer->lastms >= peer->maxms) || (peer->lastms < 0)) 02988 ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02989 } else if (peer->lastms < peer->maxms) { 02990 ast_log(LOG_NOTICE, "Peer '%s' has become TOO LAGGED (%d ms)\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), ms); 02991 } 02992 peer->lastms = ms; 02993 } 02994 peer->qualtrans = NULL; 02995 } 02996 if (ast_test_flag(trans, FLAG_STOREHIST)) { 02997 if (trans->parent && !ast_strlen_zero(trans->parent->number)) { 02998 if (!ast_eid_cmp(&trans->them_eid, &peer->eid)) { 02999 peer->avgms = 0; 03000 cnt = 0; 03001 if (peer->lookups[DUNDI_TIMING_HISTORY-1]) 03002 ast_free(peer->lookups[DUNDI_TIMING_HISTORY-1]); 03003 for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) { 03004 peer->lookuptimes[x] = peer->lookuptimes[x-1]; 03005 peer->lookups[x] = peer->lookups[x-1]; 03006 if (peer->lookups[x]) { 03007 peer->avgms += peer->lookuptimes[x]; 03008 cnt++; 03009 } 03010 } 03011 peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start); 03012 peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2); 03013 if (peer->lookups[0]) { 03014 sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext); 03015 peer->avgms += peer->lookuptimes[0]; 03016 cnt++; 03017 } 03018 if (cnt) 03019 peer->avgms /= cnt; 03020 } 03021 } 03022 } 03023 } 03024 } 03025 if (trans->parent) { 03026 /* Unlink from parent if appropriate */ 03027 AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist); 03028 if (AST_LIST_EMPTY(&trans->parent->trans)) { 03029 /* Wake up sleeper */ 03030 if (trans->parent->pfds[1] > -1) { 03031 if (write(trans->parent->pfds[1], "killa!", 6) < 0) { 03032 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 03033 } 03034 } 03035 } 03036 } 03037 /* Unlink from all trans */ 03038 AST_LIST_REMOVE(&alltrans, trans, all); 03039 destroy_packets(&trans->packets); 03040 destroy_packets(&trans->lasttrans); 03041 AST_SCHED_DEL(sched, trans->autokillid); 03042 if (trans->thread) { 03043 /* If used by a thread, mark as dead and be done */ 03044 ast_set_flag(trans, FLAG_DEAD); 03045 } else 03046 ast_free(trans); 03047 }
| static int discover_transactions | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3288 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_discover(), and dundi_request::trans.
Referenced by dundi_lookup_internal().
03289 { 03290 struct dundi_transaction *trans; 03291 AST_LIST_LOCK(&peers); 03292 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03293 dundi_discover(trans); 03294 } 03295 AST_LIST_UNLOCK(&peers); 03296 return 0; 03297 }
| static int do_autokill | ( | const void * | data | ) | [static] |
Definition at line 3143 of file pbx_dundi.c.
References ast_eid_to_str(), ast_log(), dundi_transaction::autokillid, destroy_trans(), LOG_NOTICE, and dundi_transaction::them_eid.
Referenced by dundi_discover(), dundi_query(), and precache_trans().
03144 { 03145 struct dundi_transaction *trans = (struct dundi_transaction *)data; 03146 char eid_str[20]; 03147 ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n", 03148 ast_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid)); 03149 trans->autokillid = -1; 03150 destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */ 03151 return 0; 03152 }
| static int do_qualify | ( | const void * | data | ) | [static] |
Definition at line 4326 of file pbx_dundi.c.
References qualify_peer(), and dundi_peer::qualifyid.
Referenced by qualify_peer().
04327 { 04328 struct dundi_peer *peer = (struct dundi_peer *)data; 04329 peer->qualifyid = -1; 04330 qualify_peer(peer, 0); 04331 return 0; 04332 }
| static int do_register | ( | const void * | data | ) | [static] |
Definition at line 4300 of file pbx_dundi.c.
References ast_debug, ast_eid_to_str(), ast_log(), ast_sched_add(), ast_set_flag, create_transaction(), destroy_trans(), DUNDI_COMMAND_REGREQ, DUNDI_DEFAULT_VERSION, dundi_ie_append_eid(), dundi_ie_append_short(), DUNDI_IE_EID, DUNDI_IE_EXPIRATION, DUNDI_IE_VERSION, dundi_send(), dundi_peer::eid, FLAG_ISREG, LOG_NOTICE, dundi_peer::registerid, dundi_peer::regtrans, dundi_transaction::us_eid, and dundi_peer::us_eid.
Referenced by build_peer().
04301 { 04302 struct dundi_ie_data ied; 04303 struct dundi_peer *peer = (struct dundi_peer *)data; 04304 char eid_str[20]; 04305 char eid_str2[20]; 04306 ast_debug(1, "Register us as '%s' to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->us_eid), ast_eid_to_str(eid_str2, sizeof(eid_str2), &peer->eid)); 04307 peer->registerid = ast_sched_add(sched, default_expiration * 1000, do_register, data); 04308 /* Destroy old transaction if there is one */ 04309 if (peer->regtrans) 04310 destroy_trans(peer->regtrans, 0); 04311 peer->regtrans = create_transaction(peer); 04312 if (peer->regtrans) { 04313 ast_set_flag(peer->regtrans, FLAG_ISREG); 04314 memset(&ied, 0, sizeof(ied)); 04315 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 04316 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &peer->regtrans->us_eid); 04317 dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, default_expiration); 04318 dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied); 04319 04320 } else 04321 ast_log(LOG_NOTICE, "Unable to create new transaction for registering to '%s'!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04322 04323 return 0; 04324 }
| static int do_register_expire | ( | const void * | data | ) | [static] |
Definition at line 1304 of file pbx_dundi.c.
References dundi_peer::addr, ast_debug, ast_eid_to_str(), dundi_peer::eid, dundi_peer::lastms, and dundi_peer::registerexpire.
Referenced by handle_command_response(), and populate_addr().
01305 { 01306 struct dundi_peer *peer = (struct dundi_peer *)data; 01307 char eid_str[20]; 01308 ast_debug(1, "Register expired for '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01309 peer->registerexpire = -1; 01310 peer->lastms = 0; 01311 memset(&peer->addr, 0, sizeof(peer->addr)); 01312 return 0; 01313 }
| static void drds_destroy | ( | struct dundi_result_datastore * | drds | ) | [static] |
Definition at line 3966 of file pbx_dundi.c.
References ast_free.
Referenced by drds_destroy_cb(), and dundi_query_read().
03967 { 03968 ast_free(drds); 03969 }
| static void drds_destroy_cb | ( | void * | data | ) | [static] |
Definition at line 3971 of file pbx_dundi.c.
References drds_destroy().
03972 { 03973 struct dundi_result_datastore *drds = data; 03974 drds_destroy(drds); 03975 }
| static int dundi_ack | ( | struct dundi_transaction * | trans, | |
| int | final | |||
| ) | [static] |
Definition at line 440 of file pbx_dundi.c.
References DUNDI_COMMAND_ACK, and dundi_send().
Referenced by handle_command_response(), and handle_frame().
00441 { 00442 return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL); 00443 }
| static int dundi_answer_entity | ( | struct dundi_transaction * | trans, | |
| struct dundi_ies * | ies, | |||
| char * | ccontext | |||
| ) | [static] |
Definition at line 794 of file pbx_dundi.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), ast_free, ast_log(), ast_pthread_create_detached, dundi_ies::called_context, dundi_query_state::called_context, DUNDI_CAUSE_GENERAL, DUNDI_COMMAND_EIDRESPONSE, dundi_ie_append_cause(), DUNDI_IE_CAUSE, dundi_query_thread(), dundi_send(), dundi_ies::eidcount, dundi_query_state::eids, dundi_ies::eids, dundi_query_state::fluffy, LOG_WARNING, dundi_ies::reqeid, dundi_query_state::reqeid, dundi_transaction::thread, dundi_query_state::trans, dundi_ies::ttl, and dundi_query_state::ttl.
Referenced by handle_command_response().
00795 { 00796 struct dundi_query_state *st; 00797 int totallen; 00798 int x; 00799 int skipfirst=0; 00800 char eid_str[20]; 00801 char *s; 00802 pthread_t lookupthread; 00803 00804 if (ies->eidcount > 1) { 00805 /* Since it is a requirement that the first EID is the authenticating host 00806 and the last EID is the root, it is permissible that the first and last EID 00807 could be the same. In that case, we should go ahead copy only the "root" section 00808 since we will not need it for authentication. */ 00809 if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1])) 00810 skipfirst = 1; 00811 } 00812 totallen = sizeof(struct dundi_query_state); 00813 totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid); 00814 st = ast_calloc(1, totallen); 00815 if (st) { 00816 ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context)); 00817 memcpy(&st->reqeid, ies->reqeid, sizeof(st->reqeid)); 00818 st->trans = trans; 00819 st->ttl = ies->ttl - 1; 00820 if (st->ttl < 0) 00821 st->ttl = 0; 00822 s = st->fluffy; 00823 for (x=skipfirst;ies->eids[x];x++) { 00824 st->eids[x-skipfirst] = (dundi_eid *)s; 00825 *st->eids[x-skipfirst] = *ies->eids[x]; 00826 s += sizeof(dundi_eid); 00827 } 00828 ast_debug(1, "Answering EID query for '%s@%s'!\n", ast_eid_to_str(eid_str, sizeof(eid_str), ies->reqeid), ies->called_context); 00829 00830 trans->thread = 1; 00831 if (ast_pthread_create_detached(&lookupthread, NULL, dundi_query_thread, st)) { 00832 struct dundi_ie_data ied = { 0, }; 00833 trans->thread = 0; 00834 ast_log(LOG_WARNING, "Unable to create thread!\n"); 00835 ast_free(st); 00836 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); 00837 dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); 00838 return -1; 00839 } 00840 } else { 00841 struct dundi_ie_data ied = { 0, }; 00842 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); 00843 dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); 00844 return -1; 00845 } 00846 return 0; 00847 }
| static int dundi_answer_query | ( | struct dundi_transaction * | trans, | |
| struct dundi_ies * | ies, | |||
| char * | ccontext | |||
| ) | [static] |
Definition at line 1072 of file pbx_dundi.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_eid_cmp(), ast_free, AST_LIST_TRAVERSE, ast_log(), ast_pthread_create_detached, dundi_ies::called_context, dundi_query_state::called_context, dundi_ies::called_number, dundi_query_state::called_number, dundi_ies::cbypass, dundi_mapping::dcontext, dundi_query_state::directs, DUNDI_CAUSE_GENERAL, DUNDI_COMMAND_DPRESPONSE, dundi_ie_append_cause(), DUNDI_IE_CAUSE, dundi_lookup_thread(), dundi_send(), dundi_ies::eid_direct, dundi_ies::eidcount, dundi_query_state::eids, dundi_ies::eids, dundi_query_state::fluffy, dundi_mapping::list, LOG_WARNING, dundi_query_state::maps, dundi_mapping::next, dundi_query_state::nocache, dundi_query_state::nummaps, dundi_transaction::thread, dundi_query_state::trans, dundi_ies::ttl, and dundi_query_state::ttl.
Referenced by handle_command_response().
01073 { 01074 struct dundi_query_state *st; 01075 int totallen; 01076 int x; 01077 struct dundi_ie_data ied; 01078 char *s; 01079 struct dundi_mapping *cur; 01080 int mapcount = 0; 01081 int skipfirst = 0; 01082 01083 pthread_t lookupthread; 01084 totallen = sizeof(struct dundi_query_state); 01085 /* Count matching map entries */ 01086 AST_LIST_TRAVERSE(&mappings, cur, list) { 01087 if (!strcasecmp(cur->dcontext, ccontext)) 01088 mapcount++; 01089 } 01090 /* If no maps, return -1 immediately */ 01091 if (!mapcount) 01092 return -1; 01093 01094 if (ies->eidcount > 1) { 01095 /* Since it is a requirement that the first EID is the authenticating host 01096 and the last EID is the root, it is permissible that the first and last EID 01097 could be the same. In that case, we should go ahead copy only the "root" section 01098 since we will not need it for authentication. */ 01099 if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1])) 01100 skipfirst = 1; 01101 } 01102 01103 totallen += mapcount * sizeof(struct dundi_mapping); 01104 totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid); 01105 st = ast_calloc(1, totallen); 01106 if (st) { 01107 ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context)); 01108 ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number)); 01109 st->trans = trans; 01110 st->ttl = ies->ttl - 1; 01111 st->nocache = ies->cbypass; 01112 if (st->ttl < 0) 01113 st->ttl = 0; 01114 s = st->fluffy; 01115 for (x=skipfirst;ies->eids[x];x++) { 01116 st->eids[x-skipfirst] = (dundi_eid *)s; 01117 *st->eids[x-skipfirst] = *ies->eids[x]; 01118 st->directs[x-skipfirst] = ies->eid_direct[x]; 01119 s += sizeof(dundi_eid); 01120 } 01121 /* Append mappings */ 01122 x = 0; 01123 st->maps = (struct dundi_mapping *)s; 01124 AST_LIST_TRAVERSE(&mappings, cur, list) { 01125 if (!strcasecmp(cur->dcontext, ccontext)) { 01126 if (x < mapcount) { 01127 st->maps[x] = *cur; 01128 st->maps[x].list.next = NULL; 01129 x++; 01130 } 01131 } 01132 } 01133 st->nummaps = mapcount; 01134 ast_debug(1, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context); 01135 trans->thread = 1; 01136 if (ast_pthread_create_detached(&lookupthread, NULL, dundi_lookup_thread, st)) { 01137 trans->thread = 0; 01138 ast_log(LOG_WARNING, "Unable to create thread!\n"); 01139 ast_free(st); 01140 memset(&ied, 0, sizeof(ied)); 01141 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); 01142 dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); 01143 return -1; 01144 } 01145 } else { 01146 ast_log(LOG_WARNING, "Out of memory!\n"); 01147 memset(&ied, 0, sizeof(ied)); 01148 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); 01149 dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); 01150 return -1; 01151 } 01152 return 0; 01153 }
| static int dundi_canmatch | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Definition at line 4573 of file pbx_dundi.c.
References DUNDI_FLAG_CANMATCH, and dundi_helper().
04574 { 04575 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH); 04576 }
| static void dundi_debug_output | ( | const char * | data | ) | [static] |
Definition at line 347 of file pbx_dundi.c.
References ast_verbose.
Referenced by load_module().
00348 { 00349 if (dundidebug) 00350 ast_verbose("%s", data); 00351 }
| static struct dundi_hdr* dundi_decrypt | ( | struct dundi_transaction * | trans, | |
| unsigned char * | dst, | |||
| int * | dstlen, | |||
| struct dundi_hdr * | ohdr, | |||
| struct dundi_encblock * | src, | |||
| int | srclen | |||
| ) | [static, read] |
Definition at line 1387 of file pbx_dundi.c.
References ast_debug, dundi_transaction::dcx, decrypt_memcpy(), dundi_encblock::encdata, and dundi_encblock::iv.
Referenced by handle_command_response().
01388 { 01389 int space = *dstlen; 01390 unsigned long bytes; 01391 struct dundi_hdr *h; 01392 unsigned char *decrypt_space; 01393 decrypt_space = alloca(srclen); 01394 if (!decrypt_space) 01395 return NULL; 01396 decrypt_memcpy(decrypt_space, src->encdata, srclen, src->iv, &trans->dcx); 01397 /* Setup header */ 01398 h = (struct dundi_hdr *)dst; 01399 *h = *ohdr; 01400 bytes = space - 6; 01401 if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) { 01402 ast_debug(1, "Ouch, uncompress failed :(\n"); 01403 return NULL; 01404 } 01405 /* Update length */ 01406 *dstlen = bytes + 6; 01407 /* Return new header */ 01408 return h; 01409 }
| static int dundi_discover | ( | struct dundi_transaction * | trans | ) | [static] |
Definition at line 3176 of file pbx_dundi.c.
References ast_log(), ast_sched_add(), dundi_transaction::autokillid, dundi_transaction::autokilltimeout, dundi_request::cbypass, dundi_request::dcontext, do_autokill(), DUNDI_COMMAND_DPDISCOVER, DUNDI_DEFAULT_VERSION, dundi_eid_zero(), dundi_ie_append(), dundi_ie_append_eid(), dundi_ie_append_eid_appropriately(), dundi_ie_append_short(), dundi_ie_append_str(), DUNDI_IE_CACHEBYPASS, DUNDI_IE_CALLED_CONTEXT, DUNDI_IE_CALLED_NUMBER, DUNDI_IE_EID_DIRECT, DUNDI_IE_TTL, DUNDI_IE_VERSION, dundi_send(), dundi_transaction::eidcount, dundi_transaction::eids, LOG_WARNING, dundi_request::number, dundi_transaction::parent, dundi_transaction::ttl, and dundi_transaction::us_eid.
Referenced by discover_transactions().
03177 { 03178 struct dundi_ie_data ied; 03179 int x; 03180 if (!trans->parent) { 03181 ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n"); 03182 return -1; 03183 } 03184 memset(&ied, 0, sizeof(ied)); 03185 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 03186 if (!dundi_eid_zero(&trans->us_eid)) 03187 dundi_ie_append_eid(&ied, DUNDI_IE_EID_DIRECT, &trans->us_eid); 03188 for (x=0;x<trans->eidcount;x++) 03189 dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid); 03190 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number); 03191 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); 03192 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); 03193 if (trans->parent->cbypass) 03194 dundi_ie_append(&ied, DUNDI_IE_CACHEBYPASS); 03195 if (trans->autokilltimeout) 03196 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); 03197 return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied); 03198 }
| static char* dundi_do_lookup | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2430 of file pbx_dundi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_result::dest, dundi_flags2str(), dundi_lookup(), dundi_result::eid_str, dundi_result::expiration, ast_cli_args::fd, sort_results(), dundi_result::tech, ast_cli_entry::usage, and dundi_result::weight.
02431 { 02432 int res; 02433 char tmp[256]; 02434 char fs[80] = ""; 02435 char *context; 02436 int x; 02437 int bypass = 0; 02438 struct dundi_result dr[MAX_RESULTS]; 02439 struct timeval start; 02440 switch (cmd) { 02441 case CLI_INIT: 02442 e->command = "dundi lookup"; 02443 e->usage = 02444 "Usage: dundi lookup <number>[@context] [bypass]\n" 02445 " Lookup the given number within the given DUNDi context\n" 02446 "(or e164 if none is specified). Bypasses cache if 'bypass'\n" 02447 "keyword is specified.\n"; 02448 return NULL; 02449 case CLI_GENERATE: 02450 return NULL; 02451 } 02452 02453 if ((a->argc < 3) || (a->argc > 4)) 02454 return CLI_SHOWUSAGE; 02455 if (a->argc > 3) { 02456 if (!strcasecmp(a->argv[3], "bypass")) 02457 bypass=1; 02458 else 02459 return CLI_SHOWUSAGE; 02460 } 02461 ast_copy_string(tmp, a->argv[2], sizeof(tmp)); 02462 context = strchr(tmp, '@'); 02463 if (context) { 02464 *context = '\0'; 02465 context++; 02466 } 02467 start = ast_tvnow(); 02468 res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass); 02469 02470 if (res < 0) 02471 ast_cli(a->fd, "DUNDi lookup returned error.\n"); 02472 else if (!res) 02473 ast_cli(a->fd, "DUNDi lookup returned no results.\n"); 02474 else 02475 sort_results(dr, res); 02476 for (x=0;x<res;x++) { 02477 ast_cli(a->fd, "%3d. %5d %s/%s (%s)\n", x + 1, dr[x].weight, dr[x].tech, dr[x].dest, dundi_flags2str(fs, sizeof(fs), dr[x].flags)); 02478 ast_cli(a->fd, " from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration); 02479 } 02480 ast_cli(a->fd, "DUNDi lookup completed in %" PRIi64 " ms\n", ast_tvdiff_ms(ast_tvnow(), start)); 02481 return CLI_SUCCESS; 02482 }
| static char* dundi_do_precache | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2484 of file pbx_dundi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_precache(), ast_cli_args::fd, and ast_cli_entry::usage.
02485 { 02486 int res; 02487 char tmp[256]; 02488 char *context; 02489 struct timeval start; 02490 switch (cmd) { 02491 case CLI_INIT: 02492 e->command = "dundi precache"; 02493 e->usage = 02494 "Usage: dundi precache <number>[@context]\n" 02495 " Lookup the given number within the given DUNDi context\n" 02496 "(or e164 if none is specified) and precaches the results to any\n" 02497 "upstream DUNDi push servers.\n"; 02498 return NULL; 02499 case CLI_GENERATE: 02500 return NULL; 02501 } 02502 if ((a->argc < 3) || (a->argc > 3)) 02503 return CLI_SHOWUSAGE; 02504 ast_copy_string(tmp, a->argv[2], sizeof(tmp)); 02505 context = strchr(tmp, '@'); 02506 if (context) { 02507 *context = '\0'; 02508 context++; 02509 } 02510 start = ast_tvnow(); 02511 res = dundi_precache(context, tmp); 02512 02513 if (res < 0) 02514 ast_cli(a->fd, "DUNDi precache returned error.\n"); 02515 else if (!res) 02516 ast_cli(a->fd, "DUNDi precache returned no error.\n"); 02517 ast_cli(a->fd, "DUNDi lookup completed in %" PRIi64 " ms\n", ast_tvdiff_ms(ast_tvnow(), start)); 02518 return CLI_SUCCESS; 02519 }
| static char* dundi_do_query | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2521 of file pbx_dundi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_str_to_eid(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_entity_info::country, dundi_query_eid(), dundi_entity_info::email, ast_cli_args::fd, dundi_entity_info::ipaddr, dundi_entity_info::locality, dundi_entity_info::org, dundi_entity_info::orgunit, dundi_entity_info::phone, dundi_entity_info::stateprov, and ast_cli_entry::usage.
02522 { 02523 int res; 02524 char tmp[256]; 02525 char *context; 02526 dundi_eid eid; 02527 struct dundi_entity_info dei; 02528 switch (cmd) { 02529 case CLI_INIT: 02530 e->command = "dundi query"; 02531 e->usage = 02532 "Usage: dundi query <entity>[@context]\n" 02533 " Attempts to retrieve contact information for a specific\n" 02534 "DUNDi entity identifier (EID) within a given DUNDi context (or\n" 02535 "e164 if none is specified).\n"; 02536 return NULL; 02537 case CLI_GENERATE: 02538 return NULL; 02539 } 02540 if ((a->argc < 3) || (a->argc > 3)) 02541 return CLI_SHOWUSAGE; 02542 if (ast_str_to_eid(&eid, a->argv[2])) { 02543 ast_cli(a->fd, "'%s' is not a valid EID!\n", a->argv[2]); 02544 return CLI_SHOWUSAGE; 02545 } 02546 ast_copy_string(tmp, a->argv[2], sizeof(tmp)); 02547 context = strchr(tmp, '@'); 02548 if (context) { 02549 *context = '\0'; 02550 context++; 02551 } 02552 res = dundi_query_eid(&dei, context, eid); 02553 if (res < 0) 02554 ast_cli(a->fd, "DUNDi Query EID returned error.\n"); 02555 else if (!res) 02556 ast_cli(a->fd, "DUNDi Query EID returned no results.\n"); 02557 else { 02558 ast_cli(a->fd, "DUNDi Query EID succeeded:\n"); 02559 ast_cli(a->fd, "Department: %s\n", dei.orgunit); 02560 ast_cli(a->fd, "Organization: %s\n", dei.org); 02561 ast_cli(a->fd, "City/Locality: %s\n", dei.locality); 02562 ast_cli(a->fd, "State/Province: %s\n", dei.stateprov); 02563 ast_cli(a->fd, "Country: %s\n", dei.country); 02564 ast_cli(a->fd, "E-mail: %s\n", dei.email); 02565 ast_cli(a->fd, "Phone: %s\n", dei.phone); 02566 ast_cli(a->fd, "IP Address: %s\n", dei.ipaddr); 02567 } 02568 return CLI_SUCCESS; 02569 }
| static int dundi_encrypt | ( | struct dundi_transaction * | trans, | |
| struct dundi_packet * | pack | |||
| ) | [static] |
Definition at line 1411 of file pbx_dundi.c.
References ast_debug, ast_log(), ast_set_flag, ast_test_flag, dundi_ie_data::buf, build_iv(), dundi_hdr::cmdflags, dundi_hdr::cmdresp, dundi_packet::data, dundi_packet::datalen, dundi_transaction::dcx, DUNDI_COMMAND_ENCRYPT, dundi_ie_append_eid(), dundi_ie_append_encdata(), dundi_ie_append_int(), dundi_ie_append_raw(), DUNDI_IE_EID, DUNDI_IE_ENCDATA, DUNDI_IE_KEYCRC32, DUNDI_IE_SHAREDKEY, DUNDI_IE_SIGNATURE, dundi_transaction::ecx, encrypt_memcpy(), find_peer(), FLAG_SENDFULLKEY, dundi_packet::h, dundi_hdr::ies, dundi_hdr::iseqno, len(), LOG_NOTICE, dundi_hdr::oseqno, dundi_ie_data::pos, dundi_peer::sentfullkey, dundi_transaction::them_eid, dundi_peer::txenckey, update_key(), dundi_peer::us_dcx, dundi_peer::us_ecx, dundi_transaction::us_eid, and dundi_peer::us_keycrc32.
Referenced by dundi_send().
01412 { 01413 unsigned char *compress_space; 01414 int len; 01415 int res; 01416 unsigned long bytes; 01417 struct dundi_ie_data ied; 01418 struct dundi_peer *peer; 01419 unsigned char iv[16]; 01420 len = pack->datalen + pack->datalen / 100 + 42; 01421 compress_space = alloca(len); 01422 if (compress_space) { 01423 memset(compress_space, 0, len); 01424 /* We care about everthing save the first 6 bytes of header */ 01425 bytes = len; 01426 res = compress(compress_space, &bytes, pack->data + 6, pack->datalen - 6); 01427 if (res != Z_OK) { 01428 ast_debug(1, "Ouch, compression failed!\n"); 01429 return -1; 01430 } 01431 memset(&ied, 0, sizeof(ied)); 01432 /* Say who we are */ 01433 if (!pack->h->iseqno && !pack->h->oseqno) { 01434 /* Need the key in the first copy */ 01435 if (!(peer = find_peer(&trans->them_eid))) 01436 return -1; 01437 if (update_key(peer)) 01438 return -1; 01439 if (!peer->sentfullkey) 01440 ast_set_flag(trans, FLAG_SENDFULLKEY); 01441 /* Append key data */ 01442 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); 01443 if (ast_test_flag(trans, FLAG_SENDFULLKEY)) { 01444 dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128); 01445 dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128); 01446 } else { 01447 dundi_ie_append_int(&ied, DUNDI_IE_KEYCRC32, peer->us_keycrc32); 01448 } 01449 /* Setup contexts */ 01450 trans->ecx = peer->us_ecx; 01451 trans->dcx = peer->us_dcx; 01452 01453 /* We've sent the full key */ 01454 peer->sentfullkey = 1; 01455 } 01456 /* Build initialization vector */ 01457 build_iv(iv); 01458 /* Add the field, rounded up to 16 bytes */ 01459 dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, iv, NULL, ((bytes + 15) / 16) * 16); 01460 /* Copy the data */ 01461 if ((ied.pos + bytes) >= sizeof(ied.buf)) { 01462 ast_log(LOG_NOTICE, "Final packet too large!\n"); 01463 return -1; 01464 } 01465 encrypt_memcpy(ied.buf + ied.pos, compress_space, bytes, iv, &trans->ecx); 01466 ied.pos += ((bytes + 15) / 16) * 16; 01467 /* Reconstruct header */ 01468 pack->datalen = sizeof(struct dundi_hdr); 01469 pack->h->cmdresp = DUNDI_COMMAND_ENCRYPT; 01470 pack->h->cmdflags = 0; 01471 memcpy(pack->h->ies, ied.buf, ied.pos); 01472 pack->datalen += ied.pos; 01473 return 0; 01474 } 01475 return -1; 01476 }
| static void dundi_error_output | ( | const char * | data | ) | [static] |
Definition at line 353 of file pbx_dundi.c.
References ast_log(), and LOG_WARNING.
Referenced by load_module().
00354 { 00355 ast_log(LOG_WARNING, "%s", data); 00356 }
| static int dundi_exec | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Definition at line 4578 of file pbx_dundi.c.
References ast_log(), ast_strlen_zero(), ast_test_flag, DUNDI_FLAG_EXISTS, dundi_lookup(), ast_channel::exten, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), S_OR, and sort_results().
04579 { 04580 struct dundi_result results[MAX_RESULTS]; 04581 int res; 04582 int x=0; 04583 char req[1024]; 04584 const char *dundiargs; 04585 struct ast_app *dial; 04586 04587 if (!strncasecmp(context, "macro-", 6)) { 04588 if (!chan) { 04589 ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n"); 04590 return -1; 04591 } 04592 /* If done as a macro, use macro extension */ 04593 if (!strcasecmp(exten, "s")) { 04594 exten = pbx_builtin_getvar_helper(chan, "ARG1"); 04595 if (ast_strlen_zero(exten)) 04596 exten = chan->macroexten; 04597 if (ast_strlen_zero(exten)) 04598 exten = chan->exten; 04599 if (ast_strlen_zero(exten)) { 04600 ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n"); 04601 return -1; 04602 } 04603 } 04604 if (ast_strlen_zero(data)) 04605 data = "e164"; 04606 } else { 04607 if (ast_strlen_zero(data)) 04608 data = context; 04609 } 04610 res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0); 04611 if (res > 0) { 04612 sort_results(results, res); 04613 for (x=0;x<res;x++) { 04614 if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) { 04615 if (!--priority) 04616 break; 04617 } 04618 } 04619 } 04620 if (x < res) { 04621 /* Got a hit! */ 04622 dundiargs = pbx_builtin_getvar_helper(chan, "DUNDIDIALARGS"); 04623 snprintf(req, sizeof(req), "%s/%s,,%s", results[x].tech, results[x].dest, 04624 S_OR(dundiargs, "")); 04625 dial = pbx_findapp("Dial"); 04626 if (dial) 04627 res = pbx_exec(chan, dial, req); 04628 } else 04629 res = -1; 04630 return res; 04631 }
| static int dundi_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Definition at line 4568 of file pbx_dundi.c.
References DUNDI_FLAG_EXISTS, and dundi_helper().
04569 { 04570 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS); 04571 }
| static char* dundi_flush | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2332 of file pbx_dundi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_db_deltree(), ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_peer::avgms, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, DUNDI_TIMING_HISTORY, ast_cli_args::fd, dundi_peer::lookups, dundi_peer::lookuptimes, and ast_cli_entry::usage.
02333 { 02334 int stats = 0; 02335 switch (cmd) { 02336 case CLI_INIT: 02337 e->command = "dundi flush [stats]"; 02338 e->usage = 02339 "Usage: dundi flush [stats]\n" 02340 " Flushes DUNDi answer cache, used primarily for debug. If\n" 02341 "'stats' is present, clears timer statistics instead of normal\n" 02342 "operation.\n"; 02343 return NULL; 02344 case CLI_GENERATE: 02345 return NULL; 02346 } 02347 if ((a->argc < 2) || (a->argc > 3)) 02348 return CLI_SHOWUSAGE; 02349 if (a->argc > 2) { 02350 if (!strcasecmp(a->argv[2], "stats")) 02351 stats = 1; 02352 else 02353 return CLI_SHOWUSAGE; 02354 } 02355 if (stats) { 02356 /* Flush statistics */ 02357 struct dundi_peer *p; 02358 int x; 02359 AST_LIST_LOCK(&peers); 02360 AST_LIST_TRAVERSE(&peers, p, list) { 02361 for (x = 0;x < DUNDI_TIMING_HISTORY; x++) { 02362 if (p->lookups[x]) 02363 ast_free(p->lookups[x]); 02364 p->lookups[x] = NULL; 02365 p->lookuptimes[x] = 0; 02366 } 02367 p->avgms = 0; 02368 } 02369 AST_LIST_UNLOCK(&peers); 02370 } else { 02371 ast_db_deltree("dundi/cache", NULL); 02372 ast_cli(a->fd, "DUNDi Cache Flushed\n"); 02373 } 02374 return CLI_SUCCESS; 02375 }
| static int dundi_helper | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | data, | |||
| int | flag | |||
| ) | [static] |
Definition at line 4529 of file pbx_dundi.c.
References ast_log(), ast_strlen_zero(), ast_test_flag, dundi_lookup(), ast_channel::exten, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, and pbx_builtin_getvar_helper().
Referenced by dundi_canmatch(), dundi_exists(), and dundi_matchmore().
04530 { 04531 struct dundi_result results[MAX_RESULTS]; 04532 int res; 04533 int x; 04534 int found = 0; 04535 if (!strncasecmp(context, "macro-", 6)) { 04536 if (!chan) { 04537 ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n"); 04538 return -1; 04539 } 04540 /* If done as a macro, use macro extension */ 04541 if (!strcasecmp(exten, "s")) { 04542 exten = pbx_builtin_getvar_helper(chan, "ARG1"); 04543 if (ast_strlen_zero(exten)) 04544 exten = chan->macroexten; 04545 if (ast_strlen_zero(exten)) 04546 exten = chan->exten; 04547 if (ast_strlen_zero(exten)) { 04548 ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n"); 04549 return -1; 04550 } 04551 } 04552 if (ast_strlen_zero(data)) 04553 data = "e164"; 04554 } else { 04555 if (ast_strlen_zero(data)) 04556 data = context; 04557 } 04558 res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0); 04559 for (x=0;x<res;x++) { 04560 if (ast_test_flag(results + x, flag)) 04561 found++; 04562 } 04563 if (found >= priority) 04564 return 1; 04565 return 0; 04566 }
| static void dundi_ie_append_eid_appropriately | ( | struct dundi_ie_data * | ied, | |
| char * | context, | |||
| dundi_eid * | eid, | |||
| dundi_eid * | us | |||
| ) | [static] |
Definition at line 3154 of file pbx_dundi.c.
References ast_eid_cmp(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_ie_append_eid(), DUNDI_IE_EID, DUNDI_IE_EID_DIRECT, dundi_peer::eid, has_permission(), and dundi_peer::include.
Referenced by dundi_discover().
03155 { 03156 struct dundi_peer *p; 03157 if (!ast_eid_cmp(eid, us)) { 03158 dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid); 03159 return; 03160 } 03161 AST_LIST_LOCK(&peers); 03162 AST_LIST_TRAVERSE(&peers, p, list) { 03163 if (!ast_eid_cmp(&p->eid, eid)) { 03164 if (has_permission(&p->include, context)) 03165 dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid); 03166 else 03167 dundi_ie_append_eid(ied, DUNDI_IE_EID, eid); 03168 break; 03169 } 03170 } 03171 if (!p) 03172 dundi_ie_append_eid(ied, DUNDI_IE_EID, eid); 03173 AST_LIST_UNLOCK(&peers); 03174 }
| int dundi_lookup | ( | struct dundi_result * | result, | |
| int | maxret, | |||
| struct ast_channel * | chan, | |||
| const char * | dcontext, | |||
| const char * | number, | |||
| int | nocache | |||
| ) |
Lookup the given number in the given dundi context. Lookup number in a given dundi context (if unspecified use e164), the given callerid (if specified) and return up to maxret results in the array specified.
| the | number of results found. | |
| -1 | on a hangup of the channel. |
Definition at line 3686 of file pbx_dundi.c.
References DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, dundi_lookup_internal(), and dundi_hint_metadata::flags.
Referenced by dundi_do_lookup(), dundi_exec(), dundi_helper(), dundi_query_read(), and dundifunc_read().
03687 { 03688 struct dundi_hint_metadata hmd; 03689 dundi_eid *avoid[1] = { NULL, }; 03690 int direct[1] = { 0, }; 03691 int expiration = dundi_cache_time; 03692 memset(&hmd, 0, sizeof(hmd)); 03693 hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; 03694 return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct); 03695 }
| static int dundi_lookup_internal | ( | struct dundi_result * | result, | |
| int | maxret, | |||
| struct ast_channel * | chan, | |||
| const char * | dcontext, | |||
| const char * | number, | |||
| int | ttl, | |||
| int | blockempty, | |||
| struct dundi_hint_metadata * | md, | |||
| int * | expiration, | |||
| int | cybpass, | |||
| int | modeselect, | |||
| dundi_eid * | skip, | |||
| dundi_eid * | avoid[], | |||
| int | direct[] | |||
| ) | [static] |
Definition at line 3584 of file pbx_dundi.c.
References abort_request(), ast_channel_name(), ast_check_hangup(), ast_copy_string(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), AST_LIST_EMPTY, ast_log(), ast_set_flag_nonstd, ast_tvdiff_ms(), ast_tvnow(), ast_waitfor_n_fd(), avoid_crc32(), build_transactions(), cancel_request(), dundi_request::cbypass, check_request(), dundi_request::crc32, dundi_request::dcontext, discover_transactions(), dundi_request::dr, DUNDI_FLUFF_TIME, DUNDI_HINT_TTL_EXPIRED, DUNDI_TTL_TIME, errno, dundi_request::expiration, dundi_request::hmd, LOG_WARNING, dundi_request::maxcount, dundi_request::number, optimize_transactions(), dundi_request::pfds, register_request(), dundi_request::respcount, dundi_request::root_eid, dundi_request::trans, and unregister_request().
Referenced by dundi_lookup(), dundi_lookup_thread(), and precache_trans().
03585 { 03586 int res; 03587 struct dundi_request dr, *pending; 03588 dundi_eid *rooteid=NULL; 03589 int x; 03590 int ttlms; 03591 int ms; 03592 int foundcache; 03593 int skipped=0; 03594 int order=0; 03595 char eid_str[20]; 03596 struct timeval start; 03597 03598 /* Don't do anthing for a hungup channel */ 03599 if (chan && ast_check_hangup(chan)) 03600 return 0; 03601 03602 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03603 03604 for (x=0;avoid[x];x++) 03605 rooteid = avoid[x]; 03606 /* Now perform real check */ 03607 memset(&dr, 0, sizeof(dr)); 03608 if (pipe(dr.pfds)) { 03609 ast_log(LOG_WARNING, "pipe failed: %s\n" , strerror(errno)); 03610 return -1; 03611 } 03612 dr.dr = result; 03613 dr.hmd = hmd; 03614 dr.maxcount = maxret; 03615 dr.expiration = *expiration; 03616 dr.cbypass = cbypass; 03617 dr.crc32 = avoid_crc32(avoid); 03618 ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext)); 03619 ast_copy_string(dr.number, number, sizeof(dr.number)); 03620 if (rooteid) 03621 dr.root_eid = *rooteid; 03622 res = register_request(&dr, &pending); 03623 if (res) { 03624 /* Already a request */ 03625 if (rooteid && !ast_eid_cmp(&dr.root_eid, &pending->root_eid)) { 03626 /* This is on behalf of someone else. Go ahead and close this out since 03627 they'll get their answer anyway. */ 03628 ast_debug(1, "Oooh, duplicate request for '%s@%s' for '%s'\n", 03629 dr.number,dr.dcontext,ast_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid)); 03630 close(dr.pfds[0]); 03631 close(dr.pfds[1]); 03632 return -2; 03633 } else { 03634 /* Wait for the cache to populate */ 03635 ast_debug(1, "Waiting for similar request for '%s@%s' for '%s'\n", 03636 dr.number,dr.dcontext,ast_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid)); 03637 start = ast_tvnow(); 03638 while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !ast_check_hangup(chan))) { 03639 /* XXX Would be nice to have a way to poll/select here XXX */ 03640 /* XXX this is a busy wait loop!!! */ 03641 usleep(1); 03642 } 03643 /* Continue on as normal, our cache should kick in */ 03644 } 03645 } 03646 /* Create transactions */ 03647 do { 03648 order = skipped; 03649 skipped = 0; 03650 foundcache = 0; 03651 build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct); 03652 } while (skipped && !foundcache && AST_LIST_EMPTY(&dr.trans)); 03653 /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't 03654 do this earlier because we didn't know if we were going to have transactions 03655 or not. */ 03656 if (!ttl) { 03657 ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED); 03658 abort_request(&dr); 03659 unregister_request(&dr); 03660 close(dr.pfds[0]); 03661 close(dr.pfds[1]); 03662 return 0; 03663 } 03664 03665 /* Optimize transactions */ 03666 optimize_transactions(&dr, order); 03667 /* Actually perform transactions */ 03668 discover_transactions(&dr); 03669 /* Wait for transaction to come back */ 03670 start = ast_tvnow(); 03671 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !ast_check_hangup(chan))) { 03672 ms = 100; 03673 ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL); 03674 } 03675 if (chan && ast_check_hangup(chan)) 03676 ast_debug(1, "Hrm, '%s' hungup before their query for %s@%s finished\n", ast_channel_name(chan), dr.number, dr.dcontext); 03677 cancel_request(&dr); 03678 unregister_request(&dr); 03679 res = dr.respcount; 03680 *expiration = dr.expiration; 03681 close(dr.pfds[0]); 03682 close(dr.pfds[1]); 03683 return res; 03684 }
| static int dundi_lookup_local | ( | struct dundi_result * | dr, | |
| struct dundi_mapping * | map, | |||
| char * | called_number, | |||
| dundi_eid * | us_eid, | |||
| int | anscnt, | |||
| struct dundi_hint_metadata * | hmd | |||
| ) | [static] |
Definition at line 567 of file pbx_dundi.c.
References ast_canmatch_extension(), ast_clear_flag, ast_clear_flag_nonstd, ast_copy_flags, ast_copy_string(), ast_eid_to_str(), ast_exists_extension(), AST_FLAGS_ALL, ast_ignore_pattern(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_matchmore_extension(), AST_MAX_EXTENSION, ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_var_assign(), ast_var_delete(), dundi_result::dest, dundi_mapping::dest, DUNDI_FLAG_CANMATCH, DUNDI_FLAG_EXISTS, DUNDI_FLAG_IGNOREPAT, DUNDI_FLAG_INTERNAL_NOPARTIAL, DUNDI_FLAG_MATCHMORE, DUNDI_HINT_DONT_ASK, dundi_result::eid, ast_var_t::entries, dundi_result::expiration, dundi_hint_metadata::exten, get_mapping_weight(), dundi_mapping::lcontext, dundi_mapping::options, pbx_substitute_variables_varshead(), dundi_result::tech, dundi_mapping::tech, tech2str(), dundi_result::techint, and dundi_result::weight.
Referenced by dundi_lookup_thread(), and precache_trans().
00568 { 00569 struct ast_flags flags = {0}; 00570 int x; 00571 if (!ast_strlen_zero(map->lcontext)) { 00572 if (ast_exists_extension(NULL, map->lcontext, called_number, 1, NULL)) 00573 ast_set_flag(&flags, DUNDI_FLAG_EXISTS); 00574 if (ast_canmatch_extension(NULL, map->lcontext, called_number, 1, NULL)) 00575 ast_set_flag(&flags, DUNDI_FLAG_CANMATCH); 00576 if (ast_matchmore_extension(NULL, map->lcontext, called_number, 1, NULL)) 00577 ast_set_flag(&flags, DUNDI_FLAG_MATCHMORE); 00578 if (ast_ignore_pattern(map->lcontext, called_number)) 00579 ast_set_flag(&flags, DUNDI_FLAG_IGNOREPAT); 00580 00581 /* Clearly we can't say 'don't ask' anymore if we found anything... */ 00582 if (ast_test_flag(&flags, AST_FLAGS_ALL)) 00583 ast_clear_flag_nonstd(hmd, DUNDI_HINT_DONT_ASK); 00584 00585 if (map->options & DUNDI_FLAG_INTERNAL_NOPARTIAL) { 00586 /* Skip partial answers */ 00587 ast_clear_flag(&flags, DUNDI_FLAG_MATCHMORE|DUNDI_FLAG_CANMATCH); 00588 } 00589 if (ast_test_flag(&flags, AST_FLAGS_ALL)) { 00590 struct varshead headp; 00591 struct ast_var_t *newvariable; 00592 ast_set_flag(&flags, map->options & 0xffff); 00593 ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL); 00594 dr[anscnt].techint = map->tech; 00595 dr[anscnt].expiration = dundi_cache_time; 00596 ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech)); 00597 dr[anscnt].eid = *us_eid; 00598 ast_eid_to_str(dr[anscnt].eid_str, sizeof(dr[anscnt].eid_str), &dr[anscnt].eid); 00599 if (ast_test_flag(&flags, DUNDI_FLAG_EXISTS)) { 00600 AST_LIST_HEAD_INIT_NOLOCK(&headp); 00601 newvariable = ast_var_assign("NUMBER", called_number); 00602 AST_LIST_INSERT_HEAD(&headp, newvariable, entries); 00603 newvariable = ast_var_assign("EID", dr[anscnt].eid_str); 00604 AST_LIST_INSERT_HEAD(&headp, newvariable, entries); 00605 newvariable = ast_var_assign("SECRET", cursecret); 00606 AST_LIST_INSERT_HEAD(&headp, newvariable, entries); 00607 newvariable = ast_var_assign("IPADDR", ipaddr); 00608 AST_LIST_INSERT_HEAD(&headp, newvariable, entries); 00609 pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest)); 00610 dr[anscnt].weight = get_mapping_weight(map, &headp); 00611 while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries))) 00612 ast_var_delete(newvariable); 00613 } else { 00614 dr[anscnt].dest[0] = '\0'; 00615 dr[anscnt].weight = get_mapping_weight(map, NULL); 00616 } 00617 anscnt++; 00618 } else { 00619 /* No answers... Find the fewest number of digits from the 00620 number for which we have no answer. */ 00621 char tmp[AST_MAX_EXTENSION + 1] = ""; 00622 for (x = 0; x < (sizeof(tmp) - 1); x++) { 00623 tmp[x] = called_number[x]; 00624 if (!tmp[x]) 00625 break; 00626 if (!ast_canmatch_extension(NULL, map->lcontext, tmp, 1, NULL)) { 00627 /* Oops found something we can't match. If this is longer 00628 than the running hint, we have to consider it */ 00629 if (strlen(tmp) > strlen(hmd->exten)) { 00630 ast_copy_string(hmd->exten, tmp, sizeof(hmd->exten)); 00631 } 00632 break; 00633 } 00634 } 00635 } 00636 } 00637 return anscnt; 00638 }
| static void* dundi_lookup_thread | ( | void * | data | ) | [static] |
Definition at line 642 of file pbx_dundi.c.
References ast_debug, ast_eid_to_str(), ast_free, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_test_flag, ast_test_flag_nonstd, dundi_query_state::called_context, dundi_query_state::called_number, destroy_trans(), dundi_query_state::directs, DUNDI_CAUSE_DUPLICATE, DUNDI_COMMAND_DPRESPONSE, DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, DUNDI_IE_ANSWER, dundi_ie_append_answer(), dundi_ie_append_cause(), dundi_ie_append_hint(), dundi_ie_append_short(), DUNDI_IE_CAUSE, DUNDI_IE_EXPIRATION, DUNDI_IE_HINT, dundi_lookup_internal(), dundi_lookup_local(), dundi_send(), dundi_query_state::eids, dundi_result::expiration, dundi_hint_metadata::exten, FLAG_DEAD, dundi_hint_metadata::flags, dundi_query_state::maps, dundi_query_state::nocache, dundi_query_state::nummaps, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, dundi_transaction::us_eid, and dundi_result::weight.
Referenced by dundi_answer_query().
00643 { 00644 struct dundi_query_state *st = data; 00645 struct dundi_result dr[MAX_RESULTS]; 00646 struct dundi_ie_data ied; 00647 struct dundi_hint_metadata hmd; 00648 char eid_str[20]; 00649 int res, x; 00650 int ouranswers=0; 00651 int max = 999999; 00652 int expiration = dundi_cache_time; 00653 00654 ast_debug(1, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, 00655 st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves"); 00656 memset(&ied, 0, sizeof(ied)); 00657 memset(&dr, 0, sizeof(dr)); 00658 memset(&hmd, 0, sizeof(hmd)); 00659 /* Assume 'don't ask for anything' and 'unaffected', no TTL expired */ 00660 hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; 00661 for (x=0;x<st->nummaps;x++) 00662 ouranswers = dundi_lookup_local(dr, st->maps + x, st->called_number, &st->trans->us_eid, ouranswers, &hmd); 00663 if (ouranswers < 0) 00664 ouranswers = 0; 00665 for (x=0;x<ouranswers;x++) { 00666 if (dr[x].weight < max) 00667 max = dr[x].weight; 00668 } 00669 00670 if (max) { 00671 /* If we do not have a canonical result, keep looking */ 00672 res = dundi_lookup_internal(dr + ouranswers, MAX_RESULTS - ouranswers, NULL, st->called_context, st->called_number, st->ttl, 1, &hmd, &expiration, st->nocache, 0, NULL, st->eids, st->directs); 00673 if (res > 0) { 00674 /* Append answer in result */ 00675 ouranswers += res; 00676 } else { 00677 if ((res < -1) && (!ouranswers)) 00678 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_DUPLICATE, "Duplicate Request Pending"); 00679 } 00680 } 00681 AST_LIST_LOCK(&peers); 00682 /* Truncate if "don't ask" isn't present */ 00683 if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK)) 00684 hmd.exten[0] = '\0'; 00685 if (ast_test_flag(st->trans, FLAG_DEAD)) { 00686 ast_debug(1, "Our transaction went away!\n"); 00687 st->trans->thread = 0; 00688 destroy_trans(st->trans, 0); 00689 } else { 00690 for (x=0;x<ouranswers;x++) { 00691 /* Add answers */ 00692 if (dr[x].expiration && (expiration > dr[x].expiration)) 00693 expiration = dr[x].expiration; 00694 dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest); 00695 } 00696 dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten); 00697 dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration); 00698 dundi_send(st->trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); 00699 st->trans->thread = 0; 00700 } 00701 AST_LIST_UNLOCK(&peers); 00702 ast_free(st); 00703 return NULL; 00704 }
| static int dundi_matchmore | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Definition at line 4633 of file pbx_dundi.c.
References DUNDI_FLAG_MATCHMORE, and dundi_helper().
04634 { 04635 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE); 04636 }
| int dundi_precache | ( | const char * | context, | |
| const char * | number | |||
| ) |
Pre-cache to push upstream peers.
Definition at line 3830 of file pbx_dundi.c.
References dundi_precache_internal().
Referenced by dundi_do_precache(), and process_precache().
03831 { 03832 dundi_eid *avoid[1] = { NULL, }; 03833 return dundi_precache_internal(context, number, dundi_ttl, avoid); 03834 }
| static void dundi_precache_full | ( | void | ) | [static] |
Definition at line 3733 of file pbx_dundi.c.
References ast_get_context_name(), ast_get_extension_name(), AST_LIST_TRAVERSE, ast_log(), ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), dundi_mapping::dcontext, dundi_mapping::lcontext, LOG_NOTICE, and reschedule_precache().
Referenced by set_config().
03734 { 03735 struct dundi_mapping *cur; 03736 struct ast_context *con; 03737 struct ast_exten *e; 03738 03739 AST_LIST_TRAVERSE(&mappings, cur, list) { 03740 ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext); 03741 ast_rdlock_contexts(); 03742 con = NULL; 03743 while ((con = ast_walk_contexts(con))) { 03744 if (strcasecmp(cur->lcontext, ast_get_context_name(con))) 03745 continue; 03746 /* Found the match, now queue them all up */ 03747 ast_rdlock_context(con); 03748 e = NULL; 03749 while ((e = ast_walk_context_extensions(con, e))) 03750 reschedule_precache(ast_get_extension_name(e), cur->dcontext, 0); 03751 ast_unlock_context(con); 03752 } 03753 ast_unlock_contexts(); 03754 } 03755 }
| static int dundi_precache_internal | ( | const char * | context, | |
| const char * | number, | |||
| int | ttl, | |||
| dundi_eid * | avoids[] | |||
| ) | [static] |
Definition at line 3757 of file pbx_dundi.c.
References ast_copy_string(), ast_debug, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor_n_fd(), build_transactions(), cancel_request(), dundi_request::dcontext, dundi_request::dr, DUNDI_FLUFF_TIME, DUNDI_TTL_TIME, errno, dundi_request::expiration, dundi_request::hmd, LOG_NOTICE, LOG_WARNING, dundi_request::maxcount, dundi_request::number, optimize_transactions(), dundi_request::pfds, precache_transactions(), reschedule_precache(), and dundi_request::trans.
Referenced by dundi_precache(), and dundi_precache_thread().
03758 { 03759 struct dundi_request dr; 03760 struct dundi_hint_metadata hmd; 03761 struct dundi_result dr2[MAX_RESULTS]; 03762 struct timeval start; 03763 struct dundi_mapping *maps = NULL, *cur; 03764 int nummaps = 0; 03765 int foundanswers; 03766 int foundcache, skipped, ttlms, ms; 03767 if (!context) 03768 context = "e164"; 03769 ast_debug(1, "Precache internal (%s@%s)!\n", number, context); 03770 03771 AST_LIST_LOCK(&peers); 03772 AST_LIST_TRAVERSE(&mappings, cur, list) { 03773 if (!strcasecmp(cur->dcontext, context)) 03774 nummaps++; 03775 } 03776 if (nummaps) { 03777 maps = alloca(nummaps * sizeof(*maps)); 03778 nummaps = 0; 03779 if (maps) { 03780 AST_LIST_TRAVERSE(&mappings, cur, list) { 03781 if (!strcasecmp(cur->dcontext, context)) 03782 maps[nummaps++] = *cur; 03783 } 03784 } 03785 } 03786 AST_LIST_UNLOCK(&peers); 03787 if (!nummaps || !maps) 03788 return -1; 03789 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03790 memset(&dr2, 0, sizeof(dr2)); 03791 memset(&dr, 0, sizeof(dr)); 03792 memset(&hmd, 0, sizeof(hmd)); 03793 dr.dr = dr2; 03794 ast_copy_string(dr.number, number, sizeof(dr.number)); 03795 ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext)); 03796 dr.maxcount = MAX_RESULTS; 03797 dr.expiration = dundi_cache_time; 03798 dr.hmd = &hmd; 03799 dr.pfds[0] = dr.pfds[1] = -1; 03800 if (pipe(dr.pfds) < 0) { 03801 ast_log(LOG_WARNING, "pipe() failed: %s\n", strerror(errno)); 03802 return -1; 03803 } 03804 build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL); 03805 optimize_transactions(&dr, 0); 03806 foundanswers = 0; 03807 precache_transactions(&dr, maps, nummaps, &dr.expiration, &foundanswers); 03808 if (foundanswers) { 03809 if (dr.expiration > 0) 03810 reschedule_precache(dr.number, dr.dcontext, dr.expiration); 03811 else 03812 ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext); 03813 } 03814 start = ast_tvnow(); 03815 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) { 03816 if (dr.pfds[0] > -1) { 03817 ms = 100; 03818 ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL); 03819 } else 03820 usleep(1); 03821 } 03822 cancel_request(&dr); 03823 if (dr.pfds[0] > -1) { 03824 close(dr.pfds[0]); 03825 close(dr.pfds[1]); 03826 } 03827 return 0; 03828 }
| static void* dundi_precache_thread | ( | void * | data | ) | [static] |
Definition at line 706 of file pbx_dundi.c.
References ast_debug, ast_eid_to_str(), ast_free, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_test_flag, ast_test_flag_nonstd, dundi_query_state::called_context, dundi_query_state::called_number, destroy_trans(), DUNDI_COMMAND_PRECACHERP, DUNDI_HINT_DONT_ASK, dundi_precache_internal(), dundi_send(), dundi_query_state::eids, dundi_hint_metadata::exten, FLAG_DEAD, dundi_transaction::thread, dundi_query_state::trans, and dundi_query_state::ttl.
Referenced by dundi_prop_precache().
00707 { 00708 struct dundi_query_state *st = data; 00709 struct dundi_ie_data ied; 00710 struct dundi_hint_metadata hmd; 00711 char eid_str[20]; 00712 00713 ast_debug(1, "Whee, precaching '%s@%s' for '%s'\n", st->called_number, st->called_context, 00714 st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves"); 00715 memset(&ied, 0, sizeof(ied)); 00716 00717 /* Now produce precache */ 00718 dundi_precache_internal(st->called_context, st->called_number, st->ttl, st->eids); 00719 00720 AST_LIST_LOCK(&peers); 00721 /* Truncate if "don't ask" isn't present */ 00722 if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK)) 00723 hmd.exten[0] = '\0'; 00724 if (ast_test_flag(st->trans, FLAG_DEAD)) { 00725 ast_debug(1, "Our transaction went away!\n"); 00726 st->trans->thread = 0; 00727 destroy_trans(st->trans, 0); 00728 } else { 00729 dundi_send(st->trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied); 00730 st->trans->thread = 0; 00731 } 00732 AST_LIST_UNLOCK(&peers); 00733 ast_free(st); 00734 return NULL; 00735 }
| static int dundi_prop_precache | ( | struct dundi_transaction * | trans, | |
| struct dundi_ies * | ies, | |||
| char * | ccontext | |||
| ) | [static] |
Definition at line 925 of file pbx_dundi.c.
References dundi_ies::anscount, dundi_ies::answers, ast_calloc, ast_clear_flag_nonstd, ast_copy_string(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), ast_free, AST_LIST_TRAVERSE, ast_log(), ast_pthread_create_detached, cache_save(), cache_save_hint(), dundi_query_state::called_context, dundi_ies::called_context, dundi_query_state::called_number, dundi_ies::called_number, dundi_ies::cbypass, dundi_answer::data, dundi_mapping::dcontext, dundi_request::dcontext, dundi_result::dest, dundi_query_state::directs, dundi_request::dr, DUNDI_CAUSE_GENERAL, DUNDI_COMMAND_PRECACHERP, DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, dundi_ie_append_cause(), DUNDI_IE_CAUSE, dundi_precache_thread(), dundi_send(), dundi_answer::eid, dundi_result::eid, dundi_ies::eid_direct, dundi_result::eid_str, dundi_ies::eidcount, dundi_query_state::eids, dundi_ies::eids, dundi_result::expiration, dundi_ies::expiration, dundi_request::expiration, dundi_answer::flags, dundi_result::flags, dundi_hint_metadata::flags, dundi_query_state::fluffy, dundi_ies::hint, dundi_request::hmd, dundi_mapping::list, LOG_NOTICE, LOG_WARNING, dundi_query_state::maps, dundi_request::maxcount, dundi_mapping::next, dundi_query_state::nocache, dundi_request::number, dundi_query_state::nummaps, dundi_transaction::parent, dundi_request::pfds, dundi_answer::protocol, dundi_request::respcount, dundi_result::tech, tech2str(), dundi_result::techint, dundi_transaction::them_eid, dundi_transaction::thread, dundi_query_state::trans, dundi_ies::ttl, dundi_query_state::ttl, dundi_answer::weight, and dundi_result::weight.
Referenced by handle_command_response().
00926 { 00927 struct dundi_query_state *st; 00928 int totallen; 00929 int x,z; 00930 struct dundi_ie_data ied; 00931 char *s; 00932 struct dundi_result dr2[MAX_RESULTS]; 00933 struct dundi_request dr; 00934 struct dundi_hint_metadata hmd; 00935 00936 struct dundi_mapping *cur; 00937 int mapcount; 00938 int skipfirst = 0; 00939 00940 pthread_t lookupthread; 00941 00942 memset(&dr2, 0, sizeof(dr2)); 00943 memset(&dr, 0, sizeof(dr)); 00944 memset(&hmd, 0, sizeof(hmd)); 00945 00946 /* Forge request structure to hold answers for cache */ 00947 hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; 00948 dr.dr = dr2; 00949 dr.maxcount = MAX_RESULTS; 00950 dr.expiration = dundi_cache_time; 00951 dr.hmd = &hmd; 00952 dr.pfds[0] = dr.pfds[1] = -1; 00953 trans->parent = &dr; 00954 ast_copy_string(dr.dcontext, ies->called_context ? ies->called_context : "e164", sizeof(dr.dcontext)); 00955 ast_copy_string(dr.number, ies->called_number, sizeof(dr.number)); 00956 00957 for (x=0;x<ies->anscount;x++) { 00958 if (trans->parent->respcount < trans->parent->maxcount) { 00959 /* Make sure it's not already there */ 00960 for (z=0;z<trans->parent->respcount;z++) { 00961 if ((trans->parent->dr[z].techint == ies->answers[x]->protocol) && 00962 !strcmp(trans->parent->dr[z].dest, (char *)ies->answers[x]->data)) 00963 break; 00964 } 00965 if (z == trans->parent->respcount) { 00966 /* Copy into parent responses */ 00967 trans->parent->dr[trans->parent->respcount].flags = ntohs(ies->answers[x]->flags); 00968 trans->parent->dr[trans->parent->respcount].techint = ies->answers[x]->protocol; 00969 trans->parent->dr[trans->parent->respcount].weight = ntohs(ies->answers[x]->weight); 00970 trans->parent->dr[trans->parent->respcount].eid = ies->answers[x]->eid; 00971 if (ies->expiration > 0) 00972 trans->parent->dr[trans->parent->respcount].expiration = ies->expiration; 00973 else 00974 trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time; 00975 ast_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, 00976 sizeof(trans->parent->dr[trans->parent->respcount].eid_str), 00977 &ies->answers[x]->eid); 00978 ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies->answers[x]->data, 00979 sizeof(trans->parent->dr[trans->parent->respcount].dest)); 00980 ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies->answers[x]->protocol), 00981 sizeof(trans->parent->dr[trans->parent->respcount].tech)); 00982 trans->parent->respcount++; 00983 ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); 00984 } else if (trans->parent->dr[z].weight > ies->answers[x]->weight) { 00985 /* Update weight if appropriate */ 00986 trans->parent->dr[z].weight = ies->answers[x]->weight; 00987 } 00988 } else 00989 ast_log(LOG_NOTICE, "Dropping excessive answers in precache for %s@%s\n", 00990 trans->parent->number, trans->parent->dcontext); 00991 00992 } 00993 /* Save all the results (if any) we had. Even if no results, still cache lookup. */ 00994 cache_save(&trans->them_eid, trans->parent, 0, 0, ies->expiration, 1); 00995 if (ies->hint) 00996 cache_save_hint(&trans->them_eid, trans->parent, ies->hint, ies->expiration); 00997 00998 totallen = sizeof(struct dundi_query_state); 00999 /* Count matching map entries */ 01000 mapcount = 0; 01001 AST_LIST_TRAVERSE(&mappings, cur, list) { 01002 if (!strcasecmp(cur->dcontext, ccontext)) 01003 mapcount++; 01004 } 01005 01006 /* If no maps, return -1 immediately */ 01007 if (!mapcount) 01008 return -1; 01009 01010 if (ies->eidcount > 1) { 01011 /* Since it is a requirement that the first EID is the authenticating host 01012 and the last EID is the root, it is permissible that the first and last EID 01013 could be the same. In that case, we should go ahead copy only the "root" section 01014 since we will not need it for authentication. */ 01015 if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1])) 01016 skipfirst = 1; 01017 } 01018 01019 /* Prepare to run a query and then propagate that as necessary */ 01020 totallen += mapcount * sizeof(struct dundi_mapping); 01021 totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid); 01022 st = ast_calloc(1, totallen); 01023 if (st) { 01024 ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context)); 01025 ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number)); 01026 st->trans = trans; 01027 st->ttl = ies->ttl - 1; 01028 st->nocache = ies->cbypass; 01029 if (st->ttl < 0) 01030 st->ttl = 0; 01031 s = st->fluffy; 01032 for (x=skipfirst;ies->eids[x];x++) { 01033 st->eids[x-skipfirst] = (dundi_eid *)s; 01034 *st->eids[x-skipfirst] = *ies->eids[x]; 01035 st->directs[x-skipfirst] = ies->eid_direct[x]; 01036 s += sizeof(dundi_eid); 01037 } 01038 /* Append mappings */ 01039 x = 0; 01040 st->maps = (struct dundi_mapping *)s; 01041 AST_LIST_TRAVERSE(&mappings, cur, list) { 01042 if (!strcasecmp(cur->dcontext, ccontext)) { 01043 if (x < mapcount) { 01044 st->maps[x] = *cur; 01045 st->maps[x].list.next = NULL; 01046 x++; 01047 } 01048 } 01049 } 01050 st->nummaps = mapcount; 01051 ast_debug(1, "Forwarding precache for '%s@%s'!\n", ies->called_number, ies->called_context); 01052 trans->thread = 1; 01053 if (ast_pthread_create_detached(&lookupthread, NULL, dundi_precache_thread, st)) { 01054 trans->thread = 0; 01055 ast_log(LOG_WARNING, "Unable to create thread!\n"); 01056 ast_free(st); 01057 memset(&ied, 0, sizeof(ied)); 01058 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); 01059 dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied); 01060 return -1; 01061 } 01062 } else { 01063 ast_log(LOG_WARNING, "Out of memory!\n"); 01064 memset(&ied, 0, sizeof(ied)); 01065 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); 01066 dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied); 01067 return -1; 01068 } 01069 return 0; 01070 }
| static int dundi_query | ( | struct dundi_transaction * | trans | ) | [static] |
Definition at line 3266 of file pbx_dundi.c.
References ast_log(), ast_sched_add(), dundi_transaction::autokillid, dundi_transaction::autokilltimeout, dundi_request::dcontext, do_autokill(), DUNDI_COMMAND_EIDQUERY, DUNDI_DEFAULT_VERSION, dundi_eid_zero(), dundi_ie_append_eid(), dundi_ie_append_short(), dundi_ie_append_str(), DUNDI_IE_CALLED_CONTEXT, DUNDI_IE_EID, DUNDI_IE_REQEID, DUNDI_IE_TTL, DUNDI_IE_VERSION, dundi_send(), dundi_transaction::eidcount, dundi_transaction::eids, LOG_WARNING, dundi_transaction::parent, dundi_request::query_eid, dundi_transaction::ttl, and dundi_transaction::us_eid.
Referenced by query_transactions().
03267 { 03268 struct dundi_ie_data ied; 03269 int x; 03270 if (!trans->parent) { 03271 ast_log(LOG_WARNING, "Tried to query a transaction with no parent?!?\n"); 03272 return -1; 03273 } 03274 memset(&ied, 0, sizeof(ied)); 03275 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 03276 if (!dundi_eid_zero(&trans->us_eid)) 03277 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); 03278 for (x=0;x<trans->eidcount;x++) 03279 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]); 03280 dundi_ie_append_eid(&ied, DUNDI_IE_REQEID, &trans->parent->query_eid); 03281 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); 03282 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); 03283 if (trans->autokilltimeout) 03284 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); 03285 return dundi_send(trans, DUNDI_COMMAND_EIDQUERY, 0, 0, &ied); 03286 }
| int dundi_query_eid | ( | struct dundi_entity_info * | dei, | |
| const char * | dcontext, | |||
| dundi_eid | eid | |||
| ) |
Retrieve information on a specific EID.
Definition at line 3883 of file pbx_dundi.c.
References dundi_query_eid_internal().
Referenced by dundi_do_query().
03884 { 03885 dundi_eid *avoid[1] = { NULL, }; 03886 struct dundi_hint_metadata hmd; 03887 memset(&hmd, 0, sizeof(hmd)); 03888 return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid); 03889 }
| static int dundi_query_eid_internal | ( | struct dundi_entity_info * | dei, | |
| const char * | dcontext, | |||
| dundi_eid * | eid, | |||
| struct dundi_hint_metadata * | hmd, | |||
| int | ttl, | |||
| int | blockempty, | |||
| dundi_eid * | avoid[] | |||
| ) | [static] |
Definition at line 3836 of file pbx_dundi.c.
References ast_copy_string(), AST_LIST_EMPTY, ast_set_flag_nonstd, ast_tvdiff_ms(), ast_tvnow(), build_transactions(), dundi_request::dcontext, dundi_request::dei, DUNDI_FLUFF_TIME, DUNDI_HINT_TTL_EXPIRED, DUNDI_TTL_TIME, dundi_request::hmd, optimize_transactions(), dundi_request::pfds, dundi_request::query_eid, query_transactions(), dundi_request::respcount, dundi_request::root_eid, and dundi_request::trans.
Referenced by dundi_query_eid(), and dundi_query_thread().
03837 { 03838 int res; 03839 struct dundi_request dr; 03840 dundi_eid *rooteid=NULL; 03841 int x; 03842 int ttlms; 03843 int skipped=0; 03844 int foundcache=0; 03845 struct timeval start; 03846 03847 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03848 03849 for (x=0;avoid[x];x++) 03850 rooteid = avoid[x]; 03851 /* Now perform real check */ 03852 memset(&dr, 0, sizeof(dr)); 03853 dr.hmd = hmd; 03854 dr.dei = dei; 03855 dr.pfds[0] = dr.pfds[1] = -1; 03856 ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext)); 03857 memcpy(&dr.query_eid, eid, sizeof(dr.query_eid)); 03858 if (rooteid) 03859 dr.root_eid = *rooteid; 03860 /* Create transactions */ 03861 build_transactions(&dr, ttl, 9999, &foundcache, &skipped, blockempty, 0, 0, NULL, avoid, NULL); 03862 03863 /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't 03864 do this earlier because we didn't know if we were going to have transactions 03865 or not. */ 03866 if (!ttl) { 03867 ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED); 03868 return 0; 03869 } 03870 03871 /* Optimize transactions */ 03872 optimize_transactions(&dr, 9999); 03873 /* Actually perform transactions */ 03874 query_transactions(&dr); 03875 /* Wait for transaction to come back */ 03876 start = ast_tvnow(); 03877 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) 03878 usleep(1); 03879 res = dr.respcount; 03880 return res; 03881 }
| static int dundi_query_read | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 3982 of file pbx_dundi.c.
References args, ARRAY_LEN, AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, AST_DECLARE_APP_ARGS, ast_log(), ast_module_user_add, ast_module_user_remove, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_datastore::data, drds_destroy(), dundi_lookup(), dundi_query_opts, dundi_result_datastore::id, LOG_ERROR, LOG_WARNING, dundi_result_datastore::num_results, OPT_BYPASS_CACHE, parse(), dundi_result_datastore::results, and sort_results().
03983 { 03984 struct ast_module_user *u; 03985 AST_DECLARE_APP_ARGS(args, 03986 AST_APP_ARG(number); 03987 AST_APP_ARG(context); 03988 AST_APP_ARG(options); 03989 ); 03990 struct ast_flags opts = { 0, }; 03991 char *parse; 03992 struct dundi_result_datastore *drds; 03993 struct ast_datastore *datastore; 03994 03995 u = ast_module_user_add(chan); 03996 03997 if (ast_strlen_zero(data)) { 03998 ast_log(LOG_WARNING, "DUNDIQUERY requires an argument (number)\n"); 03999 ast_module_user_remove(u); 04000 return -1; 04001 } 04002 04003 if (!chan) { 04004 ast_log(LOG_ERROR, "DUNDIQUERY can not be used without a channel!\n"); 04005 ast_module_user_remove(u); 04006 return -1; 04007 } 04008 04009 parse = ast_strdupa(data); 04010 04011 AST_STANDARD_APP_ARGS(args, parse); 04012 04013 if (!ast_strlen_zero(args.options)) 04014 ast_app_parse_options(dundi_query_opts, &opts, NULL, args.options); 04015 04016 if (ast_strlen_zero(args.context)) 04017 args.context = "e164"; 04018 04019 if (!(drds = ast_calloc(1, sizeof(*drds)))) { 04020 ast_module_user_remove(u); 04021 return -1; 04022 } 04023 04024 drds->id = ast_atomic_fetchadd_int((int *) &dundi_result_id, 1); 04025 snprintf(buf, len, "%u", drds->id); 04026 04027 if (!(datastore = ast_datastore_alloc(&dundi_result_datastore_info, buf))) { 04028 drds_destroy(drds); 04029 ast_module_user_remove(u); 04030 return -1; 04031 } 04032 04033 datastore->data = drds; 04034 04035 drds->num_results = dundi_lookup(drds->results, ARRAY_LEN(drds->results), NULL, args.context, 04036 args.number, ast_test_flag(&opts, OPT_BYPASS_CACHE)); 04037 04038 if (drds->num_results > 0) 04039 sort_results(drds->results, drds->num_results); 04040 04041 ast_channel_lock(chan); 04042 ast_channel_datastore_add(chan, datastore); 04043 ast_channel_unlock(chan); 04044 04045 ast_module_user_remove(u); 04046 04047 return 0; 04048 }
| static void* dundi_query_thread | ( | void * | data | ) | [static] |
Definition at line 739 of file pbx_dundi.c.
References ast_copy_string(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), ast_free, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_strlen_zero(), ast_test_flag, dundi_query_state::called_context, dundi_query_state::called_number, dundi_entity_info::country, destroy_trans(), DUNDI_COMMAND_EIDRESPONSE, dundi_ie_append_hint(), dundi_ie_append_str(), DUNDI_IE_COUNTRY, DUNDI_IE_DEPARTMENT, DUNDI_IE_EMAIL, DUNDI_IE_HINT, DUNDI_IE_IPADDR, DUNDI_IE_LOCALITY, DUNDI_IE_ORGANIZATION, DUNDI_IE_PHONE, DUNDI_IE_STATE_PROV, dundi_query_eid_internal(), dundi_send(), dundi_query_state::eids, dundi_entity_info::email, dundi_hint_metadata::exten, FLAG_DEAD, dundi_hint_metadata::flags, dundi_entity_info::ipaddr, dundi_entity_info::locality, dundi_entity_info::org, dundi_entity_info::orgunit, dundi_entity_info::phone, dundi_query_state::reqeid, dundi_entity_info::stateprov, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, and dundi_transaction::us_eid.
Referenced by dundi_answer_entity().
00740 { 00741 struct dundi_query_state *st = data; 00742 struct dundi_entity_info dei; 00743 struct dundi_ie_data ied; 00744 struct dundi_hint_metadata hmd; 00745 char eid_str[20]; 00746 int res; 00747 00748 ast_debug(1, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, 00749 st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves"); 00750 memset(&ied, 0, sizeof(ied)); 00751 memset(&dei, 0, sizeof(dei)); 00752 memset(&hmd, 0, sizeof(hmd)); 00753 if (!ast_eid_cmp(&st->trans->us_eid, &st->reqeid)) { 00754 /* Ooh, it's us! */ 00755 ast_debug(1, "Neat, someone look for us!\n"); 00756 ast_copy_string(dei.orgunit, dept, sizeof(dei.orgunit)); 00757 ast_copy_string(dei.org, org, sizeof(dei.org)); 00758 ast_copy_string(dei.locality, locality, sizeof(dei.locality)); 00759 ast_copy_string(dei.stateprov, stateprov, sizeof(dei.stateprov)); 00760 ast_copy_string(dei.country, country, sizeof(dei.country)); 00761 ast_copy_string(dei.email, email, sizeof(dei.email)); 00762 ast_copy_string(dei.phone, phone, sizeof(dei.phone)); 00763 res = 1; 00764 } else { 00765 /* If we do not have a canonical result, keep looking */ 00766 res = dundi_query_eid_internal(&dei, st->called_context, &st->reqeid, &hmd, st->ttl, 1, st->eids); 00767 } 00768 AST_LIST_LOCK(&peers); 00769 if (ast_test_flag(st->trans, FLAG_DEAD)) { 00770 ast_debug(1, "Our transaction went away!\n"); 00771 st->trans->thread = 0; 00772 destroy_trans(st->trans, 0); 00773 } else { 00774 if (res) { 00775 dundi_ie_append_str(&ied, DUNDI_IE_DEPARTMENT, dei.orgunit); 00776 dundi_ie_append_str(&ied, DUNDI_IE_ORGANIZATION, dei.org); 00777 dundi_ie_append_str(&ied, DUNDI_IE_LOCALITY, dei.locality); 00778 dundi_ie_append_str(&ied, DUNDI_IE_STATE_PROV, dei.stateprov); 00779 dundi_ie_append_str(&ied, DUNDI_IE_COUNTRY, dei.country); 00780 dundi_ie_append_str(&ied, DUNDI_IE_EMAIL, dei.email); 00781 dundi_ie_append_str(&ied, DUNDI_IE_PHONE, dei.phone); 00782 if (!ast_strlen_zero(dei.ipaddr)) 00783 dundi_ie_append_str(&ied, DUNDI_IE_IPADDR, dei.ipaddr); 00784 } 00785 dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten); 00786 dundi_send(st->trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); 00787 st->trans->thread = 0; 00788 } 00789 AST_LIST_UNLOCK(&peers); 00790 ast_free(st); 00791 return NULL; 00792 }
| static void dundi_reject | ( | struct dundi_hdr * | h, | |
| struct sockaddr_in * | sin | |||
| ) | [static] |
Definition at line 444 of file pbx_dundi.c.
References dundi_transaction::addr, dundi_hdr::cmdresp, dundi_hdr::dtrans, DUNDI_COMMAND_INVALID, dundi_xmit(), dundi_hdr::iseqno, dundi_hdr::oseqno, and dundi_hdr::strans.
Referenced by handle_frame().
00445 { 00446 struct { 00447 struct dundi_packet pack; 00448 struct dundi_hdr hdr; 00449 } tmp; 00450 struct dundi_transaction trans; 00451 /* Never respond to an INVALID with another INVALID */ 00452 if (h->cmdresp == DUNDI_COMMAND_INVALID) 00453 return; 00454 memset(&tmp, 0, sizeof(tmp)); 00455 memset(&trans, 0, sizeof(trans)); 00456 memcpy(&trans.addr, sin, sizeof(trans.addr)); 00457 tmp.hdr.strans = h->dtrans; 00458 tmp.hdr.dtrans = h->strans; 00459 tmp.hdr.iseqno = h->oseqno; 00460 tmp.hdr.oseqno = h->iseqno; 00461 tmp.hdr.cmdresp = DUNDI_COMMAND_INVALID; 00462 tmp.hdr.cmdflags = 0; 00463 tmp.pack.h = (struct dundi_hdr *)tmp.pack.data; 00464 tmp.pack.datalen = sizeof(struct dundi_hdr); 00465 tmp.pack.parent = &trans; 00466 dundi_xmit(&tmp.pack); 00467 }
| static int dundi_result_read | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 4055 of file pbx_dundi.c.
References args, AST_APP_ARG, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_DECLARE_APP_ARGS, ast_log(), ast_module_user_add, ast_module_user_remove, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_datastore::data, dundi_result::dest, LOG_ERROR, LOG_WARNING, dundi_result_datastore::num_results, parse(), dundi_result_datastore::results, and dundi_result::tech.
04056 { 04057 struct ast_module_user *u; 04058 AST_DECLARE_APP_ARGS(args, 04059 AST_APP_ARG(id); 04060 AST_APP_ARG(resultnum); 04061 ); 04062 char *parse; 04063 unsigned int num; 04064 struct dundi_result_datastore *drds; 04065 struct ast_datastore *datastore; 04066 int res = -1; 04067 04068 u = ast_module_user_add(chan); 04069 04070 if (ast_strlen_zero(data)) { 04071 ast_log(LOG_WARNING, "DUNDIRESULT requires an argument (id and resultnum)\n"); 04072 goto finish; 04073 } 04074 04075 if (!chan) { 04076 ast_log(LOG_ERROR, "DUNDRESULT can not be used without a channel!\n"); 04077 goto finish; 04078 } 04079 04080 parse = ast_strdupa(data); 04081 04082 AST_STANDARD_APP_ARGS(args, parse); 04083 04084 if (ast_strlen_zero(args.id)) { 04085 ast_log(LOG_ERROR, "A result ID must be provided to DUNDIRESULT\n"); 04086 goto finish; 04087 } 04088 04089 if (ast_strlen_zero(args.resultnum)) { 04090 ast_log(LOG_ERROR, "A result number must be given to DUNDIRESULT!\n"); 04091 goto finish; 04092 } 04093 04094 ast_channel_lock(chan); 04095 datastore = ast_channel_datastore_find(chan, &dundi_result_datastore_info, args.id); 04096 ast_channel_unlock(chan); 04097 04098 if (!datastore) { 04099 ast_log(LOG_WARNING, "No DUNDi results found for query ID '%s'\n", args.id); 04100 goto finish; 04101 } 04102 04103 drds = datastore->data; 04104 04105 if (!strcasecmp(args.resultnum, "getnum")) { 04106 snprintf(buf, len, "%u", drds->num_results); 04107 res = 0; 04108 goto finish; 04109 } 04110 04111 if (sscanf(args.resultnum, "%30u", &num) != 1) { 04112 ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to DUNDIRESULT!\n", 04113 args.resultnum); 04114 goto finish; 04115 } 04116 04117 if (num && num <= drds->num_results) { 04118 snprintf(buf, len, "%s/%s", drds->results[num - 1].tech, drds->results[num - 1].dest); 04119 res = 0; 04120 } else 04121 ast_log(LOG_WARNING, "Result number %u is not valid for DUNDi query results for ID %s!\n", num, args.id); 04122 04123 finish: 04124 ast_module_user_remove(u); 04125 04126 return res; 04127 }
| static int dundi_rexmit | ( | const void * | data | ) | [static] |
Definition at line 3049 of file pbx_dundi.c.
References dundi_transaction::addr, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_test_flag, destroy_trans(), dundi_xmit(), FLAG_ISQUAL, dundi_packet::h, LOG_NOTICE, dundi_hdr::oseqno, dundi_packet::parent, dundi_packet::retrans, dundi_packet::retransid, and dundi_hdr::strans.
Referenced by dundi_send().
03050 { 03051 struct dundi_packet *pack = (struct dundi_packet *)data; 03052 int res; 03053 AST_LIST_LOCK(&peers); 03054 if (pack->retrans < 1) { 03055 pack->retransid = -1; 03056 if (!ast_test_flag(pack->parent, FLAG_ISQUAL)) 03057 ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n", 03058 ast_inet_ntoa(pack->parent->addr.sin_addr), 03059 ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans)); 03060 destroy_trans(pack->parent, 1); 03061 res = 0; 03062 } else { 03063 /* Decrement retransmission, try again */ 03064 pack->retrans--; 03065 dundi_xmit(pack); 03066 res = 1; 03067 } 03068 AST_LIST_UNLOCK(&peers); 03069 return res; 03070 }
| static int dundi_send | ( | struct dundi_transaction * | trans, | |
| int | cmdresp, | |||
| int | flags, | |||
| int | final, | |||
| struct dundi_ie_data * | ied | |||
| ) | [static] |
Definition at line 3072 of file pbx_dundi.c.
References dundi_transaction::addr, dundi_transaction::aseqno, ast_calloc, ast_eid_to_str(), ast_free, AST_LIST_INSERT_HEAD, ast_log(), ast_sched_add(), ast_set_flag, ast_test_flag, dundi_hdr::cmdflags, dundi_hdr::cmdresp, dundi_packet::data, dundi_packet::datalen, dundi_transaction::dtrans, dundi_hdr::dtrans, DUNDI_COMMAND_ACK, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_DPRESPONSE, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_EIDRESPONSE, DUNDI_COMMAND_FINAL, DUNDI_COMMAND_PRECACHERP, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, DUNDI_COMMAND_REGRESPONSE, DUNDI_DEFAULT_RETRANS, dundi_encrypt(), dundi_rexmit(), dundi_showframe(), dundi_xmit(), FLAG_ENCRYPT, FLAG_FINAL, dundi_packet::h, dundi_hdr::ies, dundi_transaction::iseqno, dundi_hdr::iseqno, len(), LOG_NOTICE, dundi_transaction::oseqno, dundi_hdr::oseqno, dundi_transaction::packets, dundi_packet::parent, dundi_packet::retrans, dundi_packet::retransid, dundi_transaction::retranstimer, dundi_transaction::strans, dundi_hdr::strans, and dundi_transaction::them_eid.
Referenced by cancel_request(), do_register(), dundi_ack(), dundi_answer_entity(), dundi_answer_query(), dundi_discover(), dundi_lookup_thread(), dundi_precache_thread(), dundi_prop_precache(), dundi_query(), dundi_query_thread(), handle_command_response(), precache_trans(), and qualify_peer().
03073 { 03074 struct dundi_packet *pack; 03075 int res; 03076 int len; 03077 char eid_str[20]; 03078 len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0); 03079 /* Reserve enough space for encryption */ 03080 if (ast_test_flag(trans, FLAG_ENCRYPT)) 03081 len += 384; 03082 pack = ast_calloc(1, len); 03083 if (pack) { 03084 pack->h = (struct dundi_hdr *)(pack->data); 03085 if (cmdresp != DUNDI_COMMAND_ACK) { 03086 pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack); 03087 pack->retrans = DUNDI_DEFAULT_RETRANS - 1; 03088 AST_LIST_INSERT_HEAD(&trans->packets, pack, list); 03089 } 03090 pack->parent = trans; 03091 pack->h->strans = htons(trans->strans); 03092 pack->h->dtrans = htons(trans->dtrans); 03093 pack->h->iseqno = trans->iseqno; 03094 pack->h->oseqno = trans->oseqno; 03095 pack->h->cmdresp = cmdresp; 03096 pack->datalen = sizeof(struct dundi_hdr); 03097 if (ied) { 03098 memcpy(pack->h->ies, ied->buf, ied->pos); 03099 pack->datalen += ied->pos; 03100 } 03101 if (final) { 03102 pack->h->cmdresp |= DUNDI_COMMAND_FINAL; 03103 ast_set_flag(trans, FLAG_FINAL); 03104 } 03105 pack->h->cmdflags = flags; 03106 if (cmdresp != DUNDI_COMMAND_ACK) { 03107 trans->oseqno++; 03108 trans->oseqno = trans->oseqno % 256; 03109 } 03110 trans->aseqno = trans->iseqno; 03111 /* If we have their public key, encrypt */ 03112 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 03113 switch(cmdresp) { 03114 case DUNDI_COMMAND_REGREQ: 03115 case DUNDI_COMMAND_REGRESPONSE: 03116 case DUNDI_COMMAND_DPDISCOVER: 03117 case DUNDI_COMMAND_DPRESPONSE: 03118 case DUNDI_COMMAND_EIDQUERY: 03119 case DUNDI_COMMAND_EIDRESPONSE: 03120 case DUNDI_COMMAND_PRECACHERQ: 03121 case DUNDI_COMMAND_PRECACHERP: 03122 if (dundidebug) 03123 dundi_showframe(pack->h, 2, &trans->addr, pack->datalen - sizeof(struct dundi_hdr)); 03124 res = dundi_encrypt(trans, pack); 03125 break; 03126 default: 03127 res = 0; 03128 } 03129 } else 03130 res = 0; 03131 if (!res) 03132 res = dundi_xmit(pack); 03133 if (res) 03134 ast_log(LOG_NOTICE, "Failed to send packet to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid)); 03135 03136 if (cmdresp == DUNDI_COMMAND_ACK) 03137 ast_free(pack); 03138 return res; 03139 } 03140 return -1; 03141 }
| static char* dundi_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2279 of file pbx_dundi.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
02280 { 02281 switch (cmd) { 02282 case CLI_INIT: 02283 e->command = "dundi set debug {on|off}"; 02284 e->usage = 02285 "Usage: dundi set debug {on|off}\n" 02286 " Enables/Disables dumping of DUNDi packets for debugging purposes\n"; 02287 return NULL; 02288 case CLI_GENERATE: 02289 return NULL; 02290 } 02291 02292 if (a->argc != e->args) 02293 return CLI_SHOWUSAGE; 02294 02295 if (!strncasecmp(a->argv[e->args -1], "on", 2)) { 02296 dundidebug = 1; 02297 ast_cli(a->fd, "DUNDi Debugging Enabled\n"); 02298 } else { 02299 dundidebug = 0; 02300 ast_cli(a->fd, "DUNDi Debugging Disabled\n"); 02301 } 02302 return CLI_SUCCESS; 02303 }
| static char* dundi_show_entityid | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2770 of file pbx_dundi.c.
References ast_cli_args::argc, ast_cli(), ast_eid_to_str(), AST_LIST_LOCK, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
02771 { 02772 char eid_str[20]; 02773 switch (cmd) { 02774 case CLI_INIT: 02775 e->command = "dundi show entityid"; 02776 e->usage = 02777 "Usage: dundi show entityid\n" 02778 " Displays the global entityid for this host.\n"; 02779 return NULL; 02780 case CLI_GENERATE: 02781 return NULL; 02782 } 02783 if (a->argc != 3) 02784 return CLI_SHOWUSAGE; 02785 AST_LIST_LOCK(&peers); 02786 ast_eid_to_str(eid_str, sizeof(eid_str), &global_eid); 02787 AST_LIST_UNLOCK(&peers); 02788 ast_cli(a->fd, "Global EID for this system is '%s'\n", eid_str); 02789 return CLI_SUCCESS; 02790 }
| static char* dundi_show_mappings | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2824 of file pbx_dundi.c.
References ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_mapping::dcontext, dundi_mapping::dest, dundi_flags2str(), ast_cli_args::fd, FORMAT, FORMAT2, get_mapping_weight(), dundi_mapping::lcontext, map, dundi_mapping::options, dundi_mapping::tech, tech2str(), and ast_cli_entry::usage.
02825 { 02826 #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n" 02827 #define FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n" 02828 struct dundi_mapping *map; 02829 char fs[256]; 02830 char weight[8]; 02831 switch (cmd) { 02832 case CLI_INIT: 02833 e->command = "dundi show mappings"; 02834 e->usage = 02835 "Usage: dundi show mappings\n" 02836 " Lists all known DUNDi mappings.\n"; 02837 return NULL; 02838 case CLI_GENERATE: 02839 return NULL; 02840 } 02841 if (a->argc != 3) 02842 return CLI_SHOWUSAGE; 02843 AST_LIST_LOCK(&peers); 02844 ast_cli(a->fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination"); 02845 AST_LIST_TRAVERSE(&mappings, map, list) { 02846 snprintf(weight, sizeof(weight), "%d", get_mapping_weight(map, NULL)); 02847 ast_cli(a->fd, FORMAT, map->dcontext, weight, 02848 ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext, 02849 dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest); 02850 } 02851 AST_LIST_UNLOCK(&peers); 02852 return CLI_SUCCESS; 02853 #undef FORMAT 02854 #undef FORMAT2 02855 }
| static char* dundi_show_peer | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2571 of file pbx_dundi.c.
References dundi_peer::addr, permission::allow, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_eid_to_str(), ast_inet_ntoa(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), dundi_peer::avgms, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_peer_helper(), DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, DUNDI_TIMING_HISTORY, dundi_peer::dynamic, dundi_peer::eid, ast_cli_args::fd, dundi_peer::include, dundi_peer::inkey, ast_cli_args::line, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::model, model2str(), ast_cli_args::n, permission::name, dundi_peer::order, dundi_peer::outkey, dundi_peer::permit, ast_cli_args::pos, dundi_peer::registerid, ast_cli_entry::usage, and ast_cli_args::word.
02572 { 02573 struct dundi_peer *peer; 02574 struct permission *p; 02575 char *order; 02576 char eid_str[20]; 02577 int x, cnt; 02578 switch (cmd) { 02579 case CLI_INIT: 02580 e->command = "dundi show peer"; 02581 e->usage = 02582 "Usage: dundi show peer [peer]\n" 02583 " Provide a detailed description of a specifid DUNDi peer.\n"; 02584 return NULL; 02585 case CLI_GENERATE: 02586 return complete_peer_helper(a->line, a->word, a->pos, a->n, 3); 02587 } 02588 if (a->argc != 4) 02589 return CLI_SHOWUSAGE; 02590 AST_LIST_LOCK(&peers); 02591 AST_LIST_TRAVERSE(&peers, peer, list) { 02592 if (!strcasecmp(ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), a->argv[3])) 02593 break; 02594 } 02595 if (peer) { 02596 switch(peer->order) { 02597 case 0: 02598 order = "Primary"; 02599 break; 02600 case 1: 02601 order = "Secondary"; 02602 break; 02603 case 2: 02604 order = "Tertiary"; 02605 break; 02606 case 3: 02607 order = "Quartiary"; 02608 break; 02609 default: 02610 order = "Unknown"; 02611 } 02612 ast_cli(a->fd, "Peer: %s\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02613 ast_cli(a->fd, "Model: %s\n", model2str(peer->model)); 02614 ast_cli(a->fd, "Order: %s\n", order); 02615 ast_cli(a->fd, "Host: %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>"); 02616 ast_cli(a->fd, "Port: %d\n", ntohs(peer->addr.sin_port)); 02617 ast_cli(a->fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no"); 02618 ast_cli(a->fd, "Reg: %s\n", peer->registerid < 0 ? "No" : "Yes"); 02619 ast_cli(a->fd, "In Key: %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey); 02620 ast_cli(a->fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey); 02621 if (!AST_LIST_EMPTY(&peer->include)) 02622 ast_cli(a->fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)"); 02623 AST_LIST_TRAVERSE(&peer->include, p, list) 02624 ast_cli(a->fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name); 02625 if (!AST_LIST_EMPTY(&peer->permit)) 02626 ast_cli(a->fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)"); 02627 AST_LIST_TRAVERSE(&peer->permit, p, list) 02628 ast_cli(a->fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name); 02629 cnt = 0; 02630 for (x = 0;x < DUNDI_TIMING_HISTORY; x++) { 02631 if (peer->lookups[x]) { 02632 if (!cnt) 02633 ast_cli(a->fd, "Last few query times:\n"); 02634 ast_cli(a->fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]); 02635 cnt++; 02636 } 02637 } 02638 if (cnt) 02639 ast_cli(a->fd, "Average query time: %d ms\n", peer->avgms); 02640 } else 02641 ast_cli(a->fd, "No such peer '%s'\n", a->argv[3]); 02642 AST_LIST_UNLOCK(&peers); 02643 return CLI_SUCCESS; 02644 }
| static char* dundi_show_peers | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2646 of file pbx_dundi.c.
References dundi_peer::addr, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_eid_to_str(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_peer::avgms, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_peer::dynamic, dundi_peer::eid, ast_cli_args::fd, FORMAT, FORMAT2, dundi_peer::lastms, dundi_peer::maxms, dundi_peer::model, model2str(), status, and ast_cli_entry::usage.
02647 { 02648 #define FORMAT2 "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n" 02649 #define FORMAT "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n" 02650 struct dundi_peer *peer; 02651 int registeredonly=0; 02652 char avgms[20]; 02653 char eid_str[20]; 02654 int online_peers = 0; 02655 int offline_peers = 0; 02656 int unmonitored_peers = 0; 02657 int total_peers = 0; 02658 switch (cmd) { 02659 case CLI_INIT: 02660 e->command = "dundi show peers [registered|include|exclude|begin]"; 02661 e->usage = 02662 "Usage: dundi show peers [registered|include|exclude|begin]\n" 02663 " Lists all known DUNDi peers.\n" 02664 " If 'registered' is present, only registered peers are shown.\n"; 02665 return NULL; 02666 case CLI_GENERATE: 02667 return NULL; 02668 } 02669 02670 if ((a->argc != 3) && (a->argc != 4) && (a->argc != 5)) 02671 return CLI_SHOWUSAGE; 02672 if ((a->argc == 4)) { 02673 if (!strcasecmp(a->argv[3], "registered")) { 02674 registeredonly = 1; 02675 } else 02676 return CLI_SHOWUSAGE; 02677 } 02678 AST_LIST_LOCK(&peers); 02679 ast_cli(a->fd, FORMAT2, "EID", "Host", "Port", "Model", "AvgTime", "Status"); 02680 AST_LIST_TRAVERSE(&peers, peer, list) { 02681 char status[20]; 02682 int print_line = -1; 02683 char srch[2000]; 02684 total_peers++; 02685 if (registeredonly && !peer->addr.sin_addr.s_addr) 02686 continue; 02687 if (peer->maxms) { 02688 if (peer->lastms < 0) { 02689 strcpy(status, "UNREACHABLE"); 02690 offline_peers++; 02691 } 02692 else if (peer->lastms > peer->maxms) { 02693 snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms); 02694 offline_peers++; 02695 } 02696 else if (peer->lastms) { 02697 snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms); 02698 online_peers++; 02699 } 02700 else { 02701 strcpy(status, "UNKNOWN"); 02702 offline_peers++; 02703 } 02704 } else { 02705 strcpy(status, "Unmonitored"); 02706 unmonitored_peers++; 02707 } 02708 if (peer->avgms) 02709 snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms); 02710 else 02711 strcpy(avgms, "Unavail"); 02712 snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 02713 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 02714 peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status); 02715 02716 if (a->argc == 5) { 02717 if (!strcasecmp(a->argv[3],"include") && strstr(srch,a->argv[4])) { 02718 print_line = -1; 02719 } else if (!strcasecmp(a->argv[3],"exclude") && !strstr(srch,a->argv[4])) { 02720 print_line = 1; 02721 } else if (!strcasecmp(a->argv[3],"begin") && !strncasecmp(srch,a->argv[4],strlen(a->argv[4]))) { 02722 print_line = -1; 02723 } else { 02724 print_line = 0; 02725 } 02726 } 02727 02728 if (print_line) { 02729 ast_cli(a->fd, FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 02730 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 02731 peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status); 02732 } 02733 } 02734 ast_cli(a->fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers); 02735 AST_LIST_UNLOCK(&peers); 02736 return CLI_SUCCESS; 02737 #undef FORMAT 02738 #undef FORMAT2 02739 }
| static char* dundi_show_precache | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2857 of file pbx_dundi.c.
References ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_precache_queue::context, dundi_precache_queue::expiration, ast_cli_args::fd, FORMAT, FORMAT2, dundi_precache_queue::number, and ast_cli_entry::usage.
02858 { 02859 #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n" 02860 #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n" 02861 struct dundi_precache_queue *qe; 02862 int h,m,s; 02863 time_t now; 02864 switch (cmd) { 02865 case CLI_INIT: 02866 e->command = "dundi show precache"; 02867 e->usage = 02868 "Usage: dundi show precache\n" 02869 " Lists all known DUNDi scheduled precache updates.\n"; 02870 return NULL; 02871 case CLI_GENERATE: 02872 return NULL; 02873 } 02874 if (a->argc != 3) 02875 return CLI_SHOWUSAGE; 02876 time(&now); 02877 ast_cli(a->fd, FORMAT2, "Number", "Context", "Expiration"); 02878 AST_LIST_LOCK(&pcq); 02879 AST_LIST_TRAVERSE(&pcq, qe, list) { 02880 s = qe->expiration - now; 02881 h = s / 3600; 02882 s = s % 3600; 02883 m = s / 60; 02884 s = s % 60; 02885 ast_cli(a->fd, FORMAT, qe->number, qe->context, h,m,s); 02886 } 02887 AST_LIST_UNLOCK(&pcq); 02888 02889 return CLI_SUCCESS; 02890 #undef FORMAT 02891 #undef FORMAT2 02892 }
| static char* dundi_show_requests | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2792 of file pbx_dundi.c.
References ast_cli_args::argc, ast_cli(), ast_eid_to_str(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_request::dcontext, dundi_eid_zero(), ast_cli_args::fd, FORMAT, FORMAT2, dundi_request::maxcount, dundi_request::number, dundi_request::respcount, dundi_request::root_eid, and ast_cli_entry::usage.
02793 { 02794 #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n" 02795 #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n" 02796 struct dundi_request *req; 02797 char eidstr[20]; 02798 switch (cmd) { 02799 case CLI_INIT: 02800 e->command = "dundi show requests"; 02801 e->usage = 02802 "Usage: dundi show requests\n" 02803 " Lists all known pending DUNDi requests.\n"; 02804 return NULL; 02805 case CLI_GENERATE: 02806 return NULL; 02807 } 02808 if (a->argc != 3) 02809 return CLI_SHOWUSAGE; 02810 AST_LIST_LOCK(&peers); 02811 ast_cli(a->fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp"); 02812 AST_LIST_TRAVERSE(&requests, req, list) { 02813 ast_cli(a->fd, FORMAT, req->number, req->dcontext, 02814 dundi_eid_zero(&req->root_eid) ? "<unspecified>" : ast_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount); 02815 } 02816 AST_LIST_UNLOCK(&peers); 02817 return CLI_SUCCESS; 02818 #undef FORMAT 02819 #undef FORMAT2 02820 }
| static char* dundi_show_trans | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2741 of file pbx_dundi.c.
References dundi_transaction::addr, ast_cli_args::argc, dundi_transaction::aseqno, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_transaction::dtrans, ast_cli_args::fd, FORMAT, FORMAT2, dundi_transaction::iseqno, dundi_transaction::oseqno, dundi_transaction::strans, and ast_cli_entry::usage.
02742 { 02743 #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n" 02744 #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n" 02745 struct dundi_transaction *trans; 02746 switch (cmd) { 02747 case CLI_INIT: 02748 e->command = "dundi show trans"; 02749 e->usage = 02750 "Usage: dundi show trans\n" 02751 " Lists all known DUNDi transactions.\n"; 02752 return NULL; 02753 case CLI_GENERATE: 02754 return NULL; 02755 } 02756 if (a->argc != 3) 02757 return CLI_SHOWUSAGE; 02758 AST_LIST_LOCK(&peers); 02759 ast_cli(a->fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack"); 02760 AST_LIST_TRAVERSE(&alltrans, trans, all) { 02761 ast_cli(a->fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr), 02762 ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno); 02763 } 02764 AST_LIST_UNLOCK(&peers); 02765 return CLI_SUCCESS; 02766 #undef FORMAT 02767 #undef FORMAT2 02768 }
| static char* dundi_store_history | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2305 of file pbx_dundi.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
02306 { 02307 switch (cmd) { 02308 case CLI_INIT: 02309 e->command = "dundi store history {on|off}"; 02310 e->usage = 02311 "Usage: dundi store history {on|off}\n" 02312 " Enables/Disables storing of DUNDi requests and times for debugging\n" 02313 "purposes\n"; 02314 return NULL; 02315 case CLI_GENERATE: 02316 return NULL; 02317 } 02318 02319 if (a->argc != e->args) 02320 return CLI_SHOWUSAGE; 02321 02322 if (!strncasecmp(a->argv[e->args -1], "on", 2)) { 02323 global_storehistory = 1; 02324 ast_cli(a->fd, "DUNDi History Storage Enabled\n"); 02325 } else { 02326 global_storehistory = 0; 02327 ast_cli(a->fd, "DUNDi History Storage Disabled\n"); 02328 } 02329 return CLI_SUCCESS; 02330 }
| static int dundi_xmit | ( | struct dundi_packet * | pack | ) | [static] |
Definition at line 2941 of file pbx_dundi.c.
References dundi_transaction::addr, ast_inet_ntoa(), ast_log(), dundi_packet::data, dundi_packet::datalen, dundi_showframe(), errno, dundi_packet::h, LOG_WARNING, and dundi_packet::parent.
Referenced by dundi_reject(), dundi_rexmit(), and dundi_send().
02942 { 02943 int res; 02944 if (dundidebug) 02945 dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr)); 02946 res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr)); 02947 if (res < 0) { 02948 ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n", 02949 ast_inet_ntoa(pack->parent->addr.sin_addr), 02950 ntohs(pack->parent->addr.sin_port), strerror(errno)); 02951 } 02952 if (res > 0) 02953 res = 0; 02954 return res; 02955 }
| static int dundifunc_read | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | num, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 3899 of file pbx_dundi.c.
References args, AST_APP_ARG, ast_app_parse_options(), AST_DECLARE_APP_ARGS, ast_log(), ast_module_user_add, ast_module_user_remove, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, DUNDI_FLAG_EXISTS, dundi_lookup(), dundi_query_opts, LOG_WARNING, OPT_BYPASS_CACHE, parse(), and sort_results().
03900 { 03901 int results; 03902 int x; 03903 struct ast_module_user *u; 03904 struct dundi_result dr[MAX_RESULTS]; 03905 AST_DECLARE_APP_ARGS(args, 03906 AST_APP_ARG(number); 03907 AST_APP_ARG(context); 03908 AST_APP_ARG(options); 03909 ); 03910 char *parse; 03911 struct ast_flags opts = { 0, }; 03912 03913 buf[0] = '\0'; 03914 03915 if (ast_strlen_zero(num)) { 03916 ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n"); 03917 return -1; 03918 } 03919 03920 u = ast_module_user_add(chan); 03921 03922 parse = ast_strdupa(num); 03923 03924 AST_STANDARD_APP_ARGS(args, parse); 03925 03926 if (!ast_strlen_zero(args.options)) { 03927 ast_app_parse_options(dundi_query_opts, &opts, NULL, args.options); 03928 } 03929 if (ast_strlen_zero(args.context)) { 03930 args.context = "e164"; 03931 } 03932 03933 results = dundi_lookup(dr, MAX_RESULTS, NULL, args.context, args.number, ast_test_flag(&opts, OPT_BYPASS_CACHE)); 03934 if (results > 0) { 03935 sort_results(dr, results); 03936 for (x = 0; x < results; x++) { 03937 if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) { 03938 snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest); 03939 break; 03940 } 03941 } 03942 } 03943 03944 ast_module_user_remove(u); 03945 03946 return 0; 03947 }
| static int encrypt_memcpy | ( | unsigned char * | dst, | |
| unsigned char * | src, | |||
| int | len, | |||
| unsigned char * | iv, | |||
| ast_aes_encrypt_key * | ecx | |||
| ) | [static] |
Definition at line 1354 of file pbx_dundi.c.
References ast_aes_encrypt().
Referenced by dundi_encrypt().
01355 { 01356 unsigned char curblock[16]; 01357 int x; 01358 memcpy(curblock, iv, sizeof(curblock)); 01359 while(len > 0) { 01360 for (x=0;x<16;x++) 01361 curblock[x] ^= src[x]; 01362 ast_aes_encrypt(curblock, dst, ecx); 01363 memcpy(curblock, dst, sizeof(curblock)); 01364 dst += 16; 01365 src += 16; 01366 len -= 16; 01367 } 01368 return 0; 01369 }
| static struct dundi_peer* find_peer | ( | dundi_eid * | eid | ) | [static, read] |
Definition at line 504 of file pbx_dundi.c.
References any_peer, ast_eid_cmp(), AST_LIST_TRAVERSE, and dundi_peer::eid.
00505 { 00506 struct dundi_peer *cur = NULL; 00507 00508 if (!eid) 00509 eid = &empty_eid; 00510 00511 AST_LIST_TRAVERSE(&peers, cur, list) { 00512 if (!ast_eid_cmp(&cur->eid,eid)) 00513 break; 00514 } 00515 00516 if (!cur && any_peer) 00517 cur = any_peer; 00518 00519 return cur; 00520 }
| static struct dundi_transaction* find_transaction | ( | struct dundi_hdr * | hdr, | |
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 402 of file pbx_dundi.c.
References dundi_transaction::addr, AST_LIST_TRAVERSE, dundi_hdr::cmdresp, create_transaction(), dundi_transaction::dtrans, dundi_hdr::dtrans, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_ENCRYPT, DUNDI_COMMAND_NULL, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, inaddrcmp(), dundi_hdr::strans, and dundi_transaction::strans.
Referenced by acf_transaction_read(), acf_transaction_write(), ast_odbc_release_obj(), commit_exec(), handle_frame(), and rollback_exec().
00403 { 00404 struct dundi_transaction *trans; 00405 00406 /* Look for an exact match first */ 00407 AST_LIST_TRAVERSE(&alltrans, trans, all) { 00408 if (!inaddrcmp(&trans->addr, sin) && 00409 ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ || 00410 ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) { 00411 if (hdr->strans) 00412 trans->dtrans = ntohs(hdr->strans) & 32767; 00413 return trans; 00414 } 00415 } 00416 00417 switch(hdr->cmdresp & 0x7f) { 00418 case DUNDI_COMMAND_DPDISCOVER: 00419 case DUNDI_COMMAND_EIDQUERY: 00420 case DUNDI_COMMAND_PRECACHERQ: 00421 case DUNDI_COMMAND_REGREQ: 00422 case DUNDI_COMMAND_NULL: 00423 case DUNDI_COMMAND_ENCRYPT: 00424 if (!hdr->strans) 00425 break; 00426 /* Create new transaction */ 00427 if (!(trans = create_transaction(NULL))) 00428 break; 00429 memcpy(&trans->addr, sin, sizeof(trans->addr)); 00430 trans->dtrans = ntohs(hdr->strans) & 32767; 00431 default: 00432 break; 00433 } 00434 00435 return trans; 00436 }
| static int get_mapping_weight | ( | struct dundi_mapping * | map, | |
| struct varshead * | headp | |||
| ) | [static] |
Definition at line 548 of file pbx_dundi.c.
References dundi_mapping::_weight, MAX_WEIGHT, pbx_substitute_variables_helper(), pbx_substitute_variables_varshead(), and dundi_mapping::weightstr.
Referenced by dundi_lookup_local(), and dundi_show_mappings().
00549 { 00550 char buf[32]; 00551 00552 buf[0] = 0; 00553 if (map->weightstr) { 00554 if (headp) { 00555 pbx_substitute_variables_varshead(headp, map->weightstr, buf, sizeof(buf) - 1); 00556 } else { 00557 pbx_substitute_variables_helper(NULL, map->weightstr, buf, sizeof(buf) - 1); 00558 } 00559 00560 if (sscanf(buf, "%30d", &map->_weight) != 1) 00561 map->_weight = MAX_WEIGHT; 00562 } 00563 00564 return map->_weight; 00565 }
| static int get_trans_id | ( | void | ) | [static] |
Definition at line 469 of file pbx_dundi.c.
References AST_LIST_TRAVERSE, ast_random(), and dundi_transaction::strans.
Referenced by create_transaction(), and reset_transaction().
00470 { 00471 struct dundi_transaction *t; 00472 int stid = (ast_random() % 32766) + 1; 00473 int tid = stid; 00474 00475 do { 00476 AST_LIST_TRAVERSE(&alltrans, t, all) { 00477 if (t->strans == tid) 00478 break; 00479 } 00480 if (!t) 00481 return tid; 00482 tid = (tid % 32766) + 1; 00483 } while (tid != stid); 00484 00485 return 0; 00486 }
| static int handle_command_response | ( | struct dundi_transaction * | trans, | |
| struct dundi_hdr * | hdr, | |||
| int | datalen, | |||
| int | encrypted | |||
| ) | [static] |
Definition at line 1561 of file pbx_dundi.c.
References dundi_peer::addr, dundi_transaction::addr, dundi_ies::anscount, dundi_ies::answers, any_peer, apply_peer(), dundi_transaction::aseqno, ast_calloc, ast_clear_flag, ast_clear_flag_nonstd, ast_copy_string(), ast_db_put(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), ast_free, ast_inet_ntoa(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_sched_add(), AST_SCHED_DEL, ast_set_flag, ast_set_flag_nonstd, ast_strlen_zero(), ast_test_flag, ast_test_flag_nonstd, ast_verb, cache_save(), cache_save_hint(), dundi_ies::called_context, dundi_ies::called_number, dundi_ies::cause, check_key(), dundi_hdr::cmdresp, dundi_entity_info::country, dundi_hint::data, dundi_answer::data, dundi_request::dcontext, dundi_transaction::dcx, deep_copy_peer(), dundi_request::dei, dundi_result::dest, do_register_expire(), dundi_request::dr, dundi_ack(), dundi_answer_entity(), dundi_answer_query(), DUNDI_CAUSE_GENERAL, DUNDI_CAUSE_NOAUTH, DUNDI_COMMAND_CANCEL, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_DPRESPONSE, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_EIDRESPONSE, DUNDI_COMMAND_ENCREJ, DUNDI_COMMAND_ENCRYPT, DUNDI_COMMAND_INVALID, DUNDI_COMMAND_NULL, DUNDI_COMMAND_PRECACHERP, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, DUNDI_COMMAND_REGRESPONSE, DUNDI_COMMAND_UNKNOWN, dundi_decrypt(), dundi_eid_to_str_short(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_TTL_EXPIRED, DUNDI_HINT_UNAFFECTED, dundi_ie_append_byte(), dundi_ie_append_cause(), dundi_ie_append_eid(), dundi_ie_append_encdata(), dundi_ie_append_raw(), dundi_ie_append_short(), DUNDI_IE_CAUSE, DUNDI_IE_EID, DUNDI_IE_ENCDATA, DUNDI_IE_EXPIRATION, DUNDI_IE_SHAREDKEY, DUNDI_IE_SIGNATURE, DUNDI_IE_UNKNOWN, DUNDI_MODEL_INBOUND, dundi_parse_ies(), dundi_prop_precache(), dundi_send(), dundi_showframe(), dundi_peer::dynamic, dundi_transaction::ecx, dundi_answer::eid, dundi_result::eid, dundi_peer::eid, dundi_result::eid_str, dundi_ies::eidcount, dundi_ies::eids, dundi_entity_info::email, dundi_ies::encblock, dundi_encblock::encdata, dundi_ies::enclen, dundi_ies::encsharedkey, dundi_ies::encsig, dundi_request::expiration, dundi_result::expiration, dundi_ies::expiration, dundi_hint_metadata::exten, find_peer(), FLAG_ENCRYPT, FLAG_SENDFULLKEY, dundi_answer::flags, dundi_result::flags, has_permission(), dundi_ies::hint, dundi_request::hmd, dundi_hdr::ies, inaddrcmp(), dundi_peer::include, dundi_peer::inkey, dundi_entity_info::ipaddr, dundi_transaction::iseqno, dundi_encblock::iv, dundi_ies::keycrc32, dundi_transaction::lasttrans, dundi_entity_info::locality, LOG_NOTICE, LOG_WARNING, MAX_PACKET_SIZE, dundi_request::maxcount, dundi_peer::model, dundi_request::number, dundi_entity_info::org, dundi_entity_info::orgunit, dundi_transaction::oseqno, dundi_hdr::oseqno, dundi_transaction::parent, dundi_peer::pcmodel, dundi_peer::permit, dundi_entity_info::phone, dundi_ie_data::pos, dundi_answer::protocol, dundi_ies::q_country, dundi_ies::q_dept, dundi_ies::q_email, dundi_ies::q_ipaddr, dundi_ies::q_locality, dundi_ies::q_org, dundi_ies::q_phone, dundi_ies::q_stateprov, qualify_peer(), dundi_request::query_eid, dundi_peer::registerexpire, reset_transaction(), dundi_request::respcount, dundi_peer::sentfullkey, dundi_entity_info::stateprov, dundi_result::tech, tech2str(), dundi_result::techint, dundi_peer::them_dcx, dundi_peer::them_ecx, dundi_transaction::them_eid, dundi_peer::txenckey, dundi_peer::us_eid, dundi_transaction::us_eid, dundi_answer::weight, and dundi_result::weight.
Referenced by handle_frame().
01562 { 01563 /* Handle canonical command / response */ 01564 int final = hdr->cmdresp & 0x80; 01565 int cmd = hdr->cmdresp & 0x7f; 01566 int x,y,z; 01567 int resp; 01568 int res; 01569 int authpass=0; 01570 unsigned char *bufcpy; 01571 #ifdef LOW_MEMORY 01572 struct dundi_ie_data *ied = ast_calloc(1, sizeof(*ied)); 01573 #else 01574 struct dundi_ie_data _ied = { 01575 .pos = 0, 01576 }; 01577 struct dundi_ie_data *ied = &_ied; 01578 #endif 01579 struct dundi_ies ies = { 01580 .eidcount = 0, 01581 }; 01582 struct dundi_peer *peer = NULL; 01583 char eid_str[20]; 01584 char eid_str2[20]; 01585 int retval = -1; 01586 01587 if (!ied) { 01588 return -1; 01589 } 01590 01591 if (datalen) { 01592 bufcpy = alloca(datalen); 01593 if (!bufcpy) { 01594 goto return_cleanup; 01595 } 01596 /* Make a copy for parsing */ 01597 memcpy(bufcpy, hdr->ies, datalen); 01598 ast_debug(1, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : ""); 01599 if (dundi_parse_ies(&ies, bufcpy, datalen) < 0) { 01600 ast_log(LOG_WARNING, "Failed to parse DUNDI information elements!\n"); 01601 goto return_cleanup; 01602 } 01603 } 01604 switch(cmd) { 01605 case DUNDI_COMMAND_DPDISCOVER: 01606 case DUNDI_COMMAND_EIDQUERY: 01607 case DUNDI_COMMAND_PRECACHERQ: 01608 if (cmd == DUNDI_COMMAND_EIDQUERY) 01609 resp = DUNDI_COMMAND_EIDRESPONSE; 01610 else if (cmd == DUNDI_COMMAND_PRECACHERQ) 01611 resp = DUNDI_COMMAND_PRECACHERP; 01612 else 01613 resp = DUNDI_COMMAND_DPRESPONSE; 01614 /* A dialplan or entity discover -- qualify by highest level entity */ 01615 peer = find_peer(ies.eids[0]); 01616 if (!peer) { 01617 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL); 01618 dundi_send(trans, resp, 0, 1, ied); 01619 } else { 01620 int hasauth = 0; 01621 trans->us_eid = peer->us_eid; 01622 if (strlen(peer->inkey)) { 01623 hasauth = encrypted; 01624 } else 01625 hasauth = 1; 01626 if (hasauth) { 01627 /* Okay we're authentiated and all, now we check if they're authorized */ 01628 if (!ies.called_context) 01629 ies.called_context = "e164"; 01630 if (cmd == DUNDI_COMMAND_EIDQUERY) { 01631 res = dundi_answer_entity(trans, &ies, ies.called_context); 01632 } else { 01633 if (ast_strlen_zero(ies.called_number)) { 01634 /* They're not permitted to access that context */ 01635 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Invalid or missing number/entity"); 01636 dundi_send(trans, resp, 0, 1, ied); 01637 } else if ((cmd == DUNDI_COMMAND_DPDISCOVER) && 01638 (peer->model & DUNDI_MODEL_INBOUND) && 01639 has_permission(&peer->permit, ies.called_context)) { 01640 res = dundi_answer_query(trans, &ies, ies.called_context); 01641 if (res < 0) { 01642 /* There is no such dundi context */ 01643 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context"); 01644 dundi_send(trans, resp, 0, 1, ied); 01645 } 01646 } else if ((cmd = DUNDI_COMMAND_PRECACHERQ) && 01647 (peer->pcmodel & DUNDI_MODEL_INBOUND) && 01648 has_permission(&peer->include, ies.called_context)) { 01649 res = dundi_prop_precache(trans, &ies, ies.called_context); 01650 if (res < 0) { 01651 /* There is no such dundi context */ 01652 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context"); 01653 dundi_send(trans, resp, 0, 1, ied); 01654 } 01655 } else { 01656 /* They're not permitted to access that context */ 01657 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Permission to context denied"); 01658 dundi_send(trans, resp, 0, 1, ied); 01659 } 01660 } 01661 } else { 01662 /* They're not permitted to access that context */ 01663 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unencrypted responses not permitted"); 01664 dundi_send(trans, resp, 0, 1, ied); 01665 } 01666 } 01667 break; 01668 case DUNDI_COMMAND_REGREQ: 01669 /* A register request -- should only have one entity */ 01670 peer = find_peer(ies.eids[0]); 01671 01672 /* if the peer is not found and we have a valid 'any_peer' setting */ 01673 if (any_peer && peer == any_peer) { 01674 /* copy any_peer into a new peer object */ 01675 peer = ast_calloc(1, sizeof(*peer)); 01676 if (peer) { 01677 deep_copy_peer(peer, any_peer); 01678 01679 /* set EID to remote EID */ 01680 peer->eid = *ies.eids[0]; 01681 01682 AST_LIST_LOCK(&peers); 01683 AST_LIST_INSERT_HEAD(&peers, peer, list); 01684 AST_LIST_UNLOCK(&peers); 01685 } 01686 } 01687 01688 if (!peer || !peer->dynamic) { 01689 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL); 01690 dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied); 01691 } else { 01692 int hasauth = 0; 01693 trans->us_eid = peer->us_eid; 01694 if (!ast_strlen_zero(peer->inkey)) { 01695 hasauth = encrypted; 01696 } else 01697 hasauth = 1; 01698 if (hasauth) { 01699 int expire = default_expiration; 01700 char data[256]; 01701 int needqual = 0; 01702 AST_SCHED_DEL(sched, peer->registerexpire); 01703 peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer); 01704 snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(trans->addr.sin_addr), 01705 ntohs(trans->addr.sin_port), expire); 01706 ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data); 01707 if (inaddrcmp(&peer->addr, &trans->addr)) { 01708 ast_verb(3, "Registered DUNDi peer '%s' at '%s:%d'\n", 01709 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 01710 ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port)); 01711 needqual = 1; 01712 } 01713 01714 memcpy(&peer->addr, &trans->addr, sizeof(peer->addr)); 01715 dundi_ie_append_short(ied, DUNDI_IE_EXPIRATION, default_expiration); 01716 dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied); 01717 if (needqual) 01718 qualify_peer(peer, 1); 01719 } 01720 } 01721 break; 01722 case DUNDI_COMMAND_DPRESPONSE: 01723 /* A dialplan response, lets see what we got... */ 01724 if (ies.cause < 1) { 01725 /* Success of some sort */ 01726 ast_debug(1, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount); 01727 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 01728 authpass = encrypted; 01729 } else 01730 authpass = 1; 01731 if (authpass) { 01732 /* Pass back up answers */ 01733 if (trans->parent && trans->parent->dr) { 01734 y = trans->parent->respcount; 01735 for (x=0;x<ies.anscount;x++) { 01736 if (trans->parent->respcount < trans->parent->maxcount) { 01737 /* Make sure it's not already there */ 01738 for (z=0;z<trans->parent->respcount;z++) { 01739 if ((trans->parent->dr[z].techint == ies.answers[x]->protocol) && 01740 !strcmp(trans->parent->dr[z].dest, (char *)ies.answers[x]->data)) 01741 break; 01742 } 01743 if (z == trans->parent->respcount) { 01744 /* Copy into parent responses */ 01745 trans->parent->dr[trans->parent->respcount].flags = ntohs(ies.answers[x]->flags); 01746 trans->parent->dr[trans->parent->respcount].techint = ies.answers[x]->protocol; 01747 trans->parent->dr[trans->parent->respcount].weight = ntohs(ies.answers[x]->weight); 01748 trans->parent->dr[trans->parent->respcount].eid = ies.answers[x]->eid; 01749 if (ies.expiration > 0) 01750 trans->parent->dr[trans->parent->respcount].expiration = ies.expiration; 01751 else 01752 trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time; 01753 ast_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, 01754 sizeof(trans->parent->dr[trans->parent->respcount].eid_str), 01755 &ies.answers[x]->eid); 01756 ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies.answers[x]->data, 01757 sizeof(trans->parent->dr[trans->parent->respcount].dest)); 01758 ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies.answers[x]->protocol), 01759 sizeof(trans->parent->dr[trans->parent->respcount].tech)); 01760 trans->parent->respcount++; 01761 ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); 01762 } else if (trans->parent->dr[z].weight > ies.answers[x]->weight) { 01763 /* Update weight if appropriate */ 01764 trans->parent->dr[z].weight = ies.answers[x]->weight; 01765 } 01766 } else 01767 ast_log(LOG_NOTICE, "Dropping excessive answers to request for %s@%s\n", 01768 trans->parent->number, trans->parent->dcontext); 01769 } 01770 /* Save all the results (if any) we had. Even if no results, still cache lookup. Let 01771 the cache know if this request was unaffected by our entity list. */ 01772 cache_save(&trans->them_eid, trans->parent, y, 01773 ies.hint ? ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_UNAFFECTED)) : 0, ies.expiration, 0); 01774 if (ies.hint) { 01775 cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration); 01776 if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED))) 01777 ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED); 01778 if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_DONT_ASK))) { 01779 if (strlen((char *)ies.hint->data) > strlen(trans->parent->hmd->exten)) { 01780 ast_copy_string(trans->parent->hmd->exten, (char *)ies.hint->data, 01781 sizeof(trans->parent->hmd->exten)); 01782 } 01783 } else { 01784 ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); 01785 } 01786 } 01787 if (ies.expiration > 0) { 01788 if (trans->parent->expiration > ies.expiration) { 01789 trans->parent->expiration = ies.expiration; 01790 } 01791 } 01792 } 01793 /* Close connection if not final */ 01794 if (!final) 01795 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01796 } 01797 01798 } else { 01799 /* Auth failure, check for data */ 01800 if (!final) { 01801 /* Cancel if they didn't already */ 01802 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01803 } 01804 } 01805 break; 01806 case DUNDI_COMMAND_EIDRESPONSE: 01807 /* A dialplan response, lets see what we got... */ 01808 if (ies.cause < 1) { 01809 /* Success of some sort */ 01810 ast_debug(1, "Looks like success of some sort (%d)\n", ies.cause); 01811 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 01812 authpass = encrypted; 01813 } else 01814 authpass = 1; 01815 if (authpass) { 01816 /* Pass back up answers */ 01817 if (trans->parent && trans->parent->dei && ies.q_org) { 01818 if (!trans->parent->respcount) { 01819 trans->parent->respcount++; 01820 if (ies.q_dept) 01821 ast_copy_string(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit)); 01822 if (ies.q_org) 01823 ast_copy_string(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org)); 01824 if (ies.q_locality) 01825 ast_copy_string(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality)); 01826 if (ies.q_stateprov) 01827 ast_copy_string(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov)); 01828 if (ies.q_country) 01829 ast_copy_string(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country)); 01830 if (ies.q_email) 01831 ast_copy_string(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email)); 01832 if (ies.q_phone) 01833 ast_copy_string(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone)); 01834 if (ies.q_ipaddr) 01835 ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr)); 01836 if (!ast_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) { 01837 /* If it's them, update our address */ 01838 ast_copy_string(trans->parent->dei->ipaddr, ast_inet_ntoa(trans->addr.sin_addr), sizeof(trans->parent->dei->ipaddr)); 01839 } 01840 } 01841 if (ies.hint) { 01842 if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED))) 01843 ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED); 01844 } 01845 } 01846 /* Close connection if not final */ 01847 if (!final) 01848 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01849 } 01850 01851 } else { 01852 /* Auth failure, check for data */ 01853 if (!final) { 01854 /* Cancel if they didn't already */ 01855 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01856 } 01857 } 01858 break; 01859 case DUNDI_COMMAND_REGRESPONSE: 01860 /* A dialplan response, lets see what we got... */ 01861 if (ies.cause < 1) { 01862 int hasauth; 01863 /* Success of some sort */ 01864 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 01865 hasauth = encrypted; 01866 } else 01867 hasauth = 1; 01868 01869 if (!hasauth) { 01870 ast_log(LOG_NOTICE, "Reponse to register not authorized!\n"); 01871 if (!final) { 01872 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Improper signature in answer"); 01873 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, ied); 01874 } 01875 } else { 01876 ast_debug(1, "Yay, we've registered as '%s' to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->us_eid), 01877 ast_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid)); 01878 /* Close connection if not final */ 01879 if (!final) 01880 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01881 } 01882 } else { 01883 /* Auth failure, cancel if they didn't for some reason */ 01884 if (!final) { 01885 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01886 } 01887 } 01888 break; 01889 case DUNDI_COMMAND_INVALID: 01890 case DUNDI_COMMAND_NULL: 01891 case DUNDI_COMMAND_PRECACHERP: 01892 /* Do nothing special */ 01893 if (!final) 01894 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01895 break; 01896 case DUNDI_COMMAND_ENCREJ: 01897 if ((ast_test_flag(trans, FLAG_SENDFULLKEY)) || AST_LIST_EMPTY(&trans->lasttrans) || !(peer = find_peer(&trans->them_eid))) { 01898 /* No really, it's over at this point */ 01899 if (!final) 01900 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01901 } else { 01902 /* Send with full key */ 01903 ast_set_flag(trans, FLAG_SENDFULLKEY); 01904 if (final) { 01905 /* Ooops, we got a final message, start by sending ACK... */ 01906 dundi_ack(trans, hdr->cmdresp & 0x80); 01907 trans->aseqno = trans->iseqno; 01908 /* Now, we gotta create a new transaction */ 01909 if (!reset_transaction(trans)) { 01910 /* Make sure handle_frame doesn't destroy us */ 01911 hdr->cmdresp &= 0x7f; 01912 /* Parse the message we transmitted */ 01913 memset(&ies, 0, sizeof(ies)); 01914 dundi_parse_ies(&ies, (AST_LIST_FIRST(&trans->lasttrans))->h->ies, (AST_LIST_FIRST(&trans->lasttrans))->datalen - sizeof(struct dundi_hdr)); 01915 /* Reconstruct outgoing encrypted packet */ 01916 memset(ied, 0, sizeof(*ied)); 01917 dundi_ie_append_eid(ied, DUNDI_IE_EID, &trans->us_eid); 01918 dundi_ie_append_raw(ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128); 01919 dundi_ie_append_raw(ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128); 01920 if (ies.encblock) 01921 dundi_ie_append_encdata(ied, DUNDI_IE_ENCDATA, ies.encblock->iv, ies.encblock->encdata, ies.enclen); 01922 dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, (AST_LIST_FIRST(&trans->lasttrans))->h->cmdresp & 0x80, ied); 01923 peer->sentfullkey = 1; 01924 } 01925 } 01926 } 01927 break; 01928 case DUNDI_COMMAND_ENCRYPT: 01929 if (!encrypted) { 01930 /* No nested encryption! */ 01931 if ((trans->iseqno == 1) && !trans->oseqno) { 01932 if (!ies.eids[0] || !(peer = find_peer(ies.eids[0])) || 01933 ((!ies.encsharedkey || !ies.encsig) && !ies.keycrc32) || 01934 (check_key(peer, ies.encsharedkey, ies.encsig, ies.keycrc32) < 1)) { 01935 if (!final) { 01936 dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL); 01937 } 01938 break; 01939 } 01940 apply_peer(trans, peer); 01941 /* Key passed, use new contexts for this session */ 01942 trans->ecx = peer->them_ecx; 01943 trans->dcx = peer->them_dcx; 01944 } 01945 if (ast_test_flag(trans, FLAG_ENCRYPT) && ies.encblock && ies.enclen) { 01946 struct dundi_hdr *dhdr; 01947 unsigned char decoded[MAX_PACKET_SIZE]; 01948 int ddatalen; 01949 ddatalen = sizeof(decoded); 01950 dhdr = dundi_decrypt(trans, decoded, &ddatalen, hdr, ies.encblock, ies.enclen); 01951 if (dhdr) { 01952 /* Handle decrypted response */ 01953 if (dundidebug) 01954 dundi_showframe(dhdr, 3, &trans->addr, ddatalen - sizeof(struct dundi_hdr)); 01955 handle_command_response(trans, dhdr, ddatalen - sizeof(struct dundi_hdr), 1); 01956 /* Carry back final flag */ 01957 hdr->cmdresp |= dhdr->cmdresp & 0x80; 01958 break; 01959 } else { 01960 ast_debug(1, "Ouch, decrypt failed :(\n"); 01961 } 01962 } 01963 } 01964 if (!final) { 01965 /* Turn off encryption */ 01966 ast_clear_flag(trans, FLAG_ENCRYPT); 01967 dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL); 01968 } 01969 break; 01970 default: 01971 /* Send unknown command if we don't know it, with final flag IFF it's the 01972 first command in the dialog and only if we haven't received final notification */ 01973 if (!final) { 01974 dundi_ie_append_byte(ied, DUNDI_IE_UNKNOWN, cmd); 01975 dundi_send(trans, DUNDI_COMMAND_UNKNOWN, 0, !hdr->oseqno, ied); 01976 } 01977 } 01978 01979 retval = 0; 01980 01981 return_cleanup: 01982 #ifdef LOW_MEMORY 01983 ast_free(ied); 01984 #endif 01985 return retval; 01986 }
| static int handle_frame | ( | struct dundi_hdr * | h, | |
| struct sockaddr_in * | sin, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 2021 of file pbx_dundi.c.
References ack_trans(), dundi_transaction::aseqno, ast_debug, ast_test_flag, dundi_hdr::cmdresp, destroy_packets(), destroy_trans(), dundi_ack(), DUNDI_COMMAND_ACK, dundi_reject(), find_transaction(), FLAG_FINAL, handle_command_response(), dundi_hdr::iseqno, dundi_transaction::iseqno, dundi_transaction::lasttrans, dundi_transaction::oiseqno, and dundi_hdr::oseqno.
02022 { 02023 struct dundi_transaction *trans; 02024 trans = find_transaction(h, sin); 02025 if (!trans) { 02026 dundi_reject(h, sin); 02027 return 0; 02028 } 02029 /* Got a transaction, see where this header fits in */ 02030 if (h->oseqno == trans->iseqno) { 02031 /* Just what we were looking for... Anything but ack increments iseqno */ 02032 if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) { 02033 /* If final, we're done */ 02034 destroy_trans(trans, 0); 02035 return 0; 02036 } 02037 if (h->cmdresp != DUNDI_COMMAND_ACK) { 02038 trans->oiseqno = trans->iseqno; 02039 trans->iseqno++; 02040 handle_command_response(trans, h, datalen, 0); 02041 } 02042 if (trans->aseqno != trans->iseqno) { 02043 dundi_ack(trans, h->cmdresp & 0x80); 02044 trans->aseqno = trans->iseqno; 02045 } 02046 /* Delete any saved last transmissions */ 02047 destroy_packets(&trans->lasttrans); 02048 if (h->cmdresp & 0x80) { 02049 /* Final -- destroy now */ 02050 destroy_trans(trans, 0); 02051 } 02052 } else if (h->oseqno == trans->oiseqno) { 02053 /* Last incoming sequence number -- send ACK without processing */ 02054 dundi_ack(trans, 0); 02055 } else { 02056 /* Out of window -- simply drop */ 02057 ast_debug(1, "Dropping packet out of window!\n"); 02058 } 02059 return 0; 02060 }
| static int has_permission | ( | struct permissionlist * | permlist, | |
| char * | cont | |||
| ) | [static] |
Definition at line 358 of file pbx_dundi.c.
References permission::allow, AST_LIST_TRAVERSE, and permission::name.
Referenced by build_transactions(), dundi_ie_append_eid_appropriately(), handle_command_response(), and optimize_transactions().
00359 { 00360 struct permission *perm; 00361 int res = 0; 00362 00363 AST_LIST_TRAVERSE(permlist, perm, list) { 00364 if (!strcasecmp(perm->name, "all") || !strcasecmp(perm->name, cont)) 00365 res = perm->allow; 00366 } 00367 00368 return res; 00369 }
| static int load_module | ( | void | ) | [static] |
Definition at line 4835 of file pbx_dundi.c.
References ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_inet_ntoa(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_netsock_set_qos(), ast_register_switch(), ast_sched_context_create(), ast_verb, dundi_debug_output(), dundi_error_output(), DUNDI_PORT, dundi_set_error(), dundi_set_output(), errno, io_context_create(), LOG_ERROR, set_config(), and start_network_thread().
04836 { 04837 struct sockaddr_in sin; 04838 04839 dundi_set_output(dundi_debug_output); 04840 dundi_set_error(dundi_error_output); 04841 04842 sin.sin_family = AF_INET; 04843 sin.sin_port = htons(DUNDI_PORT); 04844 sin.sin_addr.s_addr = INADDR_ANY; 04845 04846 /* Make a UDP socket */ 04847 io = io_context_create(); 04848 sched = ast_sched_context_create(); 04849 04850 if (!io || !sched) 04851 return AST_MODULE_LOAD_DECLINE; 04852 04853 if (set_config("dundi.conf", &sin, 0)) 04854 return AST_MODULE_LOAD_DECLINE; 04855 04856 netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 04857 04858 if (netsocket < 0) { 04859 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 04860 return AST_MODULE_LOAD_DECLINE; 04861 } 04862 if (bind(netsocket, (struct sockaddr *) &sin, sizeof(sin))) { 04863 ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", 04864 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), strerror(errno)); 04865 return AST_MODULE_LOAD_DECLINE; 04866 } 04867 04868 ast_netsock_set_qos(netsocket, tos, 0, "DUNDi"); 04869 04870 if (start_network_thread()) { 04871 ast_log(LOG_ERROR, "Unable to start network thread\n"); 04872 close(netsocket); 04873 return AST_MODULE_LOAD_DECLINE; 04874 } 04875 04876 ast_cli_register_multiple(cli_dundi, ARRAY_LEN(cli_dundi)); 04877 if (ast_register_switch(&dundi_switch)) 04878 ast_log(LOG_ERROR, "Unable to register DUNDi switch\n"); 04879 ast_custom_function_register(&dundi_function); 04880 ast_custom_function_register(&dundi_query_function); 04881 ast_custom_function_register(&dundi_result_function); 04882 04883 ast_verb(2, "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 04884 04885 return AST_MODULE_LOAD_SUCCESS; 04886 }
| static void load_password | ( | void | ) | [static] |
Definition at line 2118 of file pbx_dundi.c.
References ast_copy_string(), ast_db_get(), ast_get_time_t(), build_secret(), DUNDI_SECRET_TIME, last, and save_secret().
Referenced by set_config().
02119 { 02120 char *current=NULL; 02121 char *last=NULL; 02122 char tmp[256]; 02123 time_t expired; 02124 02125 ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp)); 02126 if (!ast_get_time_t(tmp, &expired, 0, NULL)) { 02127 ast_db_get(secretpath, "secret", tmp, sizeof(tmp)); 02128 current = strchr(tmp, ';'); 02129 if (!current) 02130 current = tmp; 02131 else { 02132 *current = '\0'; 02133 current++; 02134 }; 02135 if ((time(NULL) - expired) < 0) { 02136 if ((expired - time(NULL)) > DUNDI_SECRET_TIME) 02137 expired = time(NULL) + DUNDI_SECRET_TIME; 02138 } else if ((time(NULL) - (expired + DUNDI_SECRET_TIME)) < 0) { 02139 last = current; 02140 current = NULL; 02141 } else { 02142 last = NULL; 02143 current = NULL; 02144 } 02145 } 02146 if (current) { 02147 /* Current key is still valid, just setup rotatation properly */ 02148 ast_copy_string(cursecret, current, sizeof(cursecret)); 02149 rotatetime = expired; 02150 } else { 02151 /* Current key is out of date, rotate or eliminate all together */ 02152 build_secret(cursecret, sizeof(cursecret)); 02153 save_secret(cursecret, last); 02154 } 02155 }
| static void mark_mappings | ( | void | ) | [static] |
Definition at line 4144 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_mapping::dead, and map.
Referenced by set_config(), and unload_module().
04145 { 04146 struct dundi_mapping *map; 04147 04148 AST_LIST_LOCK(&peers); 04149 AST_LIST_TRAVERSE(&mappings, map, list) { 04150 map->dead = 1; 04151 } 04152 AST_LIST_UNLOCK(&peers); 04153 }
| static void mark_peers | ( | void | ) | [static] |
Definition at line 4134 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and dundi_peer::dead.
Referenced by set_config(), and unload_module().
04135 { 04136 struct dundi_peer *peer; 04137 AST_LIST_LOCK(&peers); 04138 AST_LIST_TRAVERSE(&peers, peer, list) { 04139 peer->dead = 1; 04140 } 04141 AST_LIST_UNLOCK(&peers); 04142 }
| static char* model2str | ( | int | model | ) | [static] |
Definition at line 2377 of file pbx_dundi.c.
References DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, and DUNDI_MODEL_SYMMETRIC.
Referenced by dundi_show_peer(), and dundi_show_peers().
02378 { 02379 switch(model) { 02380 case DUNDI_MODEL_INBOUND: 02381 return "Inbound"; 02382 case DUNDI_MODEL_OUTBOUND: 02383 return "Outbound"; 02384 case DUNDI_MODEL_SYMMETRIC: 02385 return "Symmetric"; 02386 default: 02387 return "Unknown"; 02388 } 02389 }
| static void* network_thread | ( | void * | ignore | ) | [static] |
Definition at line 2174 of file pbx_dundi.c.
References ast_io_add(), AST_IO_IN, ast_io_wait(), AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, ast_sched_runq(), ast_sched_wait(), check_password(), and socket_read().
02175 { 02176 /* Our job is simple: Send queued messages, retrying if necessary. Read frames 02177 from the network, and queue them for delivery to the channels */ 02178 int res; 02179 /* Establish I/O callback for socket read */ 02180 ast_io_add(io, netsocket, socket_read, AST_IO_IN, NULL); 02181 02182 while (!dundi_shutdown) { 02183 res = ast_sched_wait(sched); 02184 if ((res > 1000) || (res < 0)) 02185 res = 1000; 02186 res = ast_io_wait(io, res); 02187 if (res >= 0) { 02188 AST_LIST_LOCK(&peers); 02189 ast_sched_runq(sched); 02190 AST_LIST_UNLOCK(&peers); 02191 } 02192 check_password(); 02193 } 02194 02195 netthreadid = AST_PTHREADT_NULL; 02196 02197 return NULL; 02198 }
| static int optimize_transactions | ( | struct dundi_request * | dr, | |
| int | order | |||
| ) | [static] |
Definition at line 3347 of file pbx_dundi.c.
References ast_eid_cmp(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_request::dcontext, DUNDI_MAX_STACK, dundi_peer::eid, dundi_transaction::eidcount, dundi_transaction::eids, has_permission(), dundi_peer::include, dundi_peer::order, dundi_transaction::them_eid, dundi_request::trans, and dundi_transaction::us_eid.
Referenced by dundi_lookup_internal(), dundi_precache_internal(), and dundi_query_eid_internal().
03348 { 03349 /* Minimize the message propagation through DUNDi by 03350 alerting the network to hops which should be not be considered */ 03351 struct dundi_transaction *trans; 03352 struct dundi_peer *peer; 03353 dundi_eid tmp; 03354 int x; 03355 int needpush; 03356 03357 AST_LIST_LOCK(&peers); 03358 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03359 /* Pop off the true root */ 03360 if (trans->eidcount) { 03361 tmp = trans->eids[--trans->eidcount]; 03362 needpush = 1; 03363 } else { 03364 tmp = trans->us_eid; 03365 needpush = 0; 03366 } 03367 03368 AST_LIST_TRAVERSE(&peers, peer, list) { 03369 if (has_permission(&peer->include, dr->dcontext) && 03370 ast_eid_cmp(&peer->eid, &trans->them_eid) && 03371 (peer->order <= order)) { 03372 /* For each other transaction, make sure we don't 03373 ask this EID about the others if they're not 03374 already in the list */ 03375 if (!ast_eid_cmp(&tmp, &peer->eid)) 03376 x = -1; 03377 else { 03378 for (x=0;x<trans->eidcount;x++) { 03379 if (!ast_eid_cmp(&trans->eids[x], &peer->eid)) 03380 break; 03381 } 03382 } 03383 if (x == trans->eidcount) { 03384 /* Nope not in the list, if needed, add us at the end since we're the source */ 03385 if (trans->eidcount < DUNDI_MAX_STACK - needpush) { 03386 trans->eids[trans->eidcount++] = peer->eid; 03387 /* Need to insert the real root (or us) at the bottom now as 03388 a requirement now. */ 03389 needpush = 1; 03390 } 03391 } 03392 } 03393 } 03394 /* If necessary, push the true root back on the end */ 03395 if (needpush) 03396 trans->eids[trans->eidcount++] = tmp; 03397 } 03398 AST_LIST_UNLOCK(&peers); 03399 03400 return 0; 03401 }
| static void populate_addr | ( | struct dundi_peer * | peer, | |
| dundi_eid * | eid | |||
| ) | [static] |
Definition at line 4357 of file pbx_dundi.c.
References dundi_peer::addr, ast_db_get(), ast_eid_to_str(), ast_sched_add(), do_register_expire(), inet_aton(), and dundi_peer::registerexpire.
Referenced by build_peer().
04358 { 04359 char data[256]; 04360 char *c; 04361 int port, expire; 04362 char eid_str[20]; 04363 ast_eid_to_str(eid_str, sizeof(eid_str), eid); 04364 if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) { 04365 c = strchr(data, ':'); 04366 if (c) { 04367 *c = '\0'; 04368 c++; 04369 if (sscanf(c, "%5d:%30d", &port, &expire) == 2) { 04370 /* Got it! */ 04371 inet_aton(data, &peer->addr.sin_addr); 04372 peer->addr.sin_family = AF_INET; 04373 peer->addr.sin_port = htons(port); 04374 peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer); 04375 } 04376 } 04377 } 04378 }
| static int precache_trans | ( | struct dundi_transaction * | trans, | |
| struct dundi_mapping * | maps, | |||
| int | mapcount, | |||
| int * | minexp, | |||
| int * | foundanswers | |||
| ) | [static] |
Definition at line 3200 of file pbx_dundi.c.
References ast_log(), ast_sched_add(), dundi_transaction::autokillid, dundi_transaction::autokilltimeout, dundi_request::dcontext, destroy_trans(), do_autokill(), DUNDI_COMMAND_PRECACHERQ, DUNDI_DEFAULT_VERSION, dundi_eid_zero(), DUNDI_IE_ANSWER, dundi_ie_append_answer(), dundi_ie_append_eid(), dundi_ie_append_hint(), dundi_ie_append_short(), dundi_ie_append_str(), DUNDI_IE_CALLED_CONTEXT, DUNDI_IE_CALLED_NUMBER, DUNDI_IE_EID, DUNDI_IE_EXPIRATION, DUNDI_IE_HINT, DUNDI_IE_TTL, DUNDI_IE_VERSION, dundi_lookup_internal(), dundi_lookup_local(), dundi_send(), dundi_transaction::eidcount, dundi_transaction::eids, dundi_result::expiration, dundi_hint_metadata::exten, dundi_hint_metadata::flags, LOG_WARNING, dundi_request::number, dundi_transaction::parent, dundi_transaction::them_eid, dundi_transaction::ttl, dundi_transaction::us_eid, and dundi_result::weight.
Referenced by precache_transactions().
03201 { 03202 struct dundi_ie_data ied; 03203 int x, res; 03204 int max = 999999; 03205 int expiration = dundi_cache_time; 03206 int ouranswers=0; 03207 dundi_eid *avoid[1] = { NULL, }; 03208 int direct[1] = { 0, }; 03209 struct dundi_result dr[MAX_RESULTS]; 03210 struct dundi_hint_metadata hmd; 03211 if (!trans->parent) { 03212 ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n"); 03213 return -1; 03214 } 03215 memset(&hmd, 0, sizeof(hmd)); 03216 memset(&dr, 0, sizeof(dr)); 03217 /* Look up the answers we're going to include */ 03218 for (x=0;x<mapcount;x++) 03219 ouranswers = dundi_lookup_local(dr, maps + x, trans->parent->number, &trans->us_eid, ouranswers, &hmd); 03220 if (ouranswers < 0) 03221 ouranswers = 0; 03222 for (x=0;x<ouranswers;x++) { 03223 if (dr[x].weight < max) 03224 max = dr[x].weight; 03225 } 03226 if (max) { 03227 /* If we do not have a canonical result, keep looking */ 03228 res = dundi_lookup_internal(dr + ouranswers, MAX_RESULTS - ouranswers, NULL, trans->parent->dcontext, trans->parent->number, trans->ttl, 1, &hmd, &expiration, 0, 1, &trans->them_eid, avoid, direct); 03229 if (res > 0) { 03230 /* Append answer in result */ 03231 ouranswers += res; 03232 } 03233 } 03234 03235 if (ouranswers > 0) { 03236 *foundanswers += ouranswers; 03237 memset(&ied, 0, sizeof(ied)); 03238 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 03239 if (!dundi_eid_zero(&trans->us_eid)) 03240 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); 03241 for (x=0;x<trans->eidcount;x++) 03242 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]); 03243 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number); 03244 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); 03245 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); 03246 for (x=0;x<ouranswers;x++) { 03247 /* Add answers */ 03248 if (dr[x].expiration && (expiration > dr[x].expiration)) 03249 expiration = dr[x].expiration; 03250 dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest); 03251 } 03252 dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten); 03253 dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration); 03254 if (trans->autokilltimeout) 03255 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); 03256 if (expiration < *minexp) 03257 *minexp = expiration; 03258 return dundi_send(trans, DUNDI_COMMAND_PRECACHERQ, 0, 0, &ied); 03259 } else { 03260 /* Oops, nothing to send... */ 03261 destroy_trans(trans, 0); 03262 return 0; 03263 } 03264 }
| static int precache_transactions | ( | struct dundi_request * | dr, | |
| struct dundi_mapping * | maps, | |||
| int | mapcount, | |||
| int * | expiration, | |||
| int * | foundanswers | |||
| ) | [static] |
Definition at line 3299 of file pbx_dundi.c.
References ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_test_flag, destroy_trans(), FLAG_DEAD, LOG_WARNING, precache_trans(), dundi_transaction::thread, and dundi_request::trans.
Referenced by dundi_precache_internal().
03300 { 03301 struct dundi_transaction *trans; 03302 03303 /* Mark all as "in thread" so they don't disappear */ 03304 AST_LIST_LOCK(&peers); 03305 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03306 if (trans->thread) 03307 ast_log(LOG_WARNING, "This shouldn't happen, really...\n"); 03308 trans->thread = 1; 03309 } 03310 AST_LIST_UNLOCK(&peers); 03311 03312 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03313 if (!ast_test_flag(trans, FLAG_DEAD)) 03314 precache_trans(trans, maps, mapcount, expiration, foundanswers); 03315 } 03316 03317 /* Cleanup any that got destroyed in the mean time */ 03318 AST_LIST_LOCK(&peers); 03319 AST_LIST_TRAVERSE_SAFE_BEGIN(&dr->trans, trans, parentlist) { 03320 trans->thread = 0; 03321 if (ast_test_flag(trans, FLAG_DEAD)) { 03322 ast_debug(1, "Our transaction went away!\n"); 03323 /* This is going to remove the transaction from the dundi_request's list, as well 03324 * as the global transactions list */ 03325 destroy_trans(trans, 0); 03326 } 03327 } 03328 AST_LIST_TRAVERSE_SAFE_END 03329 AST_LIST_UNLOCK(&peers); 03330 03331 return 0; 03332 }
| static void* process_clearcache | ( | void * | ignore | ) | [static] |
Definition at line 2200 of file pbx_dundi.c.
References ast_db_del(), ast_db_freetree(), ast_db_gettree(), ast_debug, ast_get_time_t(), AST_PTHREADT_NULL, ast_db_entry::data, ast_db_entry::key, and ast_db_entry::next.
Referenced by start_network_thread().
02201 { 02202 struct ast_db_entry *db_entry, *db_tree; 02203 int striplen = sizeof("/dundi/cache"); 02204 time_t now; 02205 02206 while (!dundi_shutdown) { 02207 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); 02208 02209 time(&now); 02210 02211 db_entry = db_tree = ast_db_gettree("dundi/cache", NULL); 02212 for (; db_entry; db_entry = db_entry->next) { 02213 time_t expiry; 02214 02215 if (!ast_get_time_t(db_entry->data, &expiry, 0, NULL)) { 02216 if (expiry < now) { 02217 ast_debug(1, "clearing expired DUNDI cache entry: %s\n", db_entry->key); 02218 ast_db_del("dundi/cache", db_entry->key + striplen); 02219 } 02220 } 02221 } 02222 ast_db_freetree(db_tree); 02223 02224 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 02225 pthread_testcancel(); 02226 sleep(60); 02227 pthread_testcancel(); 02228 } 02229 02230 clearcachethreadid = AST_PTHREADT_NULL; 02231 return NULL; 02232 }
| static void* process_precache | ( | void * | ign | ) | [static] |
Definition at line 2234 of file pbx_dundi.c.
References ast_copy_string(), ast_free, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, AST_PTHREADT_NULL, dundi_precache_queue::context, dundi_precache(), dundi_precache_queue::expiration, and dundi_precache_queue::number.
Referenced by start_network_thread().
02235 { 02236 struct dundi_precache_queue *qe; 02237 time_t now; 02238 char context[256]; 02239 char number[256]; 02240 int run; 02241 02242 while (!dundi_shutdown) { 02243 time(&now); 02244 run = 0; 02245 AST_LIST_LOCK(&pcq); 02246 if ((qe = AST_LIST_FIRST(&pcq))) { 02247 if (!qe->expiration) { 02248 /* Gone... Remove... */ 02249 AST_LIST_REMOVE_HEAD(&pcq, list); 02250 ast_free(qe); 02251 } else if (qe->expiration < now) { 02252 /* Process this entry */ 02253 qe->expiration = 0; 02254 ast_copy_string(context, qe->context, sizeof(context)); 02255 ast_copy_string(number, qe->number, sizeof(number)); 02256 run = 1; 02257 } 02258 } 02259 AST_LIST_UNLOCK(&pcq); 02260 if (run) { 02261 dundi_precache(context, number); 02262 } else 02263 sleep(1); 02264 } 02265 02266 precachethreadid = AST_PTHREADT_NULL; 02267 02268 return NULL; 02269 }
| static void prune_mappings | ( | void | ) | [static] |
Definition at line 4196 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, dundi_mapping::dead, destroy_map(), and map.
Referenced by set_config(), and unload_module().
04197 { 04198 struct dundi_mapping *map; 04199 04200 AST_LIST_LOCK(&peers); 04201 AST_LIST_TRAVERSE_SAFE_BEGIN(&mappings, map, list) { 04202 if (map->dead) { 04203 AST_LIST_REMOVE_CURRENT(list); 04204 destroy_map(map); 04205 } 04206 } 04207 AST_LIST_TRAVERSE_SAFE_END; 04208 AST_LIST_UNLOCK(&peers); 04209 }
| static void prune_peers | ( | void | ) | [static] |
Definition at line 4181 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, dundi_peer::dead, and destroy_peer().
04182 { 04183 struct dundi_peer *peer; 04184 04185 AST_LIST_LOCK(&peers); 04186 AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, list) { 04187 if (peer->dead) { 04188 AST_LIST_REMOVE_CURRENT(list); 04189 destroy_peer(peer); 04190 } 04191 } 04192 AST_LIST_TRAVERSE_SAFE_END; 04193 AST_LIST_UNLOCK(&peers); 04194 }
| static void qualify_peer | ( | struct dundi_peer * | peer, | |
| int | schedonly | |||
| ) | [static] |
Definition at line 4334 of file pbx_dundi.c.
References ast_sched_add(), AST_SCHED_DEL, ast_set_flag, ast_tvnow(), create_transaction(), destroy_trans(), do_qualify(), DUNDI_COMMAND_NULL, dundi_send(), FLAG_ISQUAL, dundi_peer::lastms, dundi_peer::maxms, dundi_peer::qualifyid, dundi_peer::qualtrans, and dundi_peer::qualtx.
Referenced by build_peer(), do_qualify(), and handle_command_response().
04335 { 04336 int when; 04337 AST_SCHED_DEL(sched, peer->qualifyid); 04338 if (peer->qualtrans) 04339 destroy_trans(peer->qualtrans, 0); 04340 peer->qualtrans = NULL; 04341 if (peer->maxms > 0) { 04342 when = 60000; 04343 if (peer->lastms < 0) 04344 when = 10000; 04345 if (schedonly) 04346 when = 5000; 04347 peer->qualifyid = ast_sched_add(sched, when, do_qualify, peer); 04348 if (!schedonly) 04349 peer->qualtrans = create_transaction(peer); 04350 if (peer->qualtrans) { 04351 peer->qualtx = ast_tvnow(); 04352 ast_set_flag(peer->qualtrans, FLAG_ISQUAL); 04353 dundi_send(peer->qualtrans, DUNDI_COMMAND_NULL, 0, 1, NULL); 04354 } 04355 } 04356 }
| static int query_transactions | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3334 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_query(), and dundi_request::trans.
Referenced by dundi_query_eid_internal().
03335 { 03336 struct dundi_transaction *trans; 03337 03338 AST_LIST_LOCK(&peers); 03339 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03340 dundi_query(trans); 03341 } 03342 AST_LIST_UNLOCK(&peers); 03343 03344 return 0; 03345 }
| static int register_request | ( | struct dundi_request * | dr, | |
| struct dundi_request ** | pending | |||
| ) | [static] |
Definition at line 3518 of file pbx_dundi.c.
References ast_debug, ast_eid_cmp(), ast_eid_to_str(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_request::crc32, dundi_request::dcontext, dundi_request::number, and dundi_request::root_eid.
Referenced by dundi_lookup_internal().
03519 { 03520 struct dundi_request *cur; 03521 int res=0; 03522 char eid_str[20]; 03523 AST_LIST_LOCK(&peers); 03524 AST_LIST_TRAVERSE(&requests, cur, list) { 03525 ast_debug(1, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number, 03526 dr->dcontext, dr->number); 03527 if (!strcasecmp(cur->dcontext, dr->dcontext) && 03528 !strcasecmp(cur->number, dr->number) && 03529 (!ast_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) { 03530 ast_debug(1, "Found existing query for '%s@%s' for '%s' crc '%08x'\n", 03531 cur->dcontext, cur->number, ast_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32); 03532 *pending = cur; 03533 res = 1; 03534 break; 03535 } 03536 } 03537 if (!res) { 03538 ast_debug(1, "Registering request for '%s@%s' on behalf of '%s' crc '%08x'\n", 03539 dr->number, dr->dcontext, ast_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32); 03540 /* Go ahead and link us in since nobody else is searching for this */ 03541 AST_LIST_INSERT_HEAD(&requests, dr, list); 03542 *pending = NULL; 03543 } 03544 AST_LIST_UNLOCK(&peers); 03545 return res; 03546 }
| static int reload | ( | void | ) | [static] |
Definition at line 4825 of file pbx_dundi.c.
References AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, and set_config().
04826 { 04827 struct sockaddr_in sin; 04828 04829 if (set_config("dundi.conf", &sin, 1)) 04830 return AST_MODULE_LOAD_FAILURE; 04831 04832 return AST_MODULE_LOAD_SUCCESS; 04833 }
| static void reschedule_precache | ( | const char * | number, | |
| const char * | context, | |||
| int | expiration | |||
| ) | [static] |
Definition at line 3697 of file pbx_dundi.c.
References ast_calloc, AST_LIST_FIRST, AST_LIST_INSERT_AFTER, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, dundi_precache_queue::context, dundi_precache_queue::expiration, len(), and dundi_precache_queue::number.
Referenced by dundi_precache_full(), and dundi_precache_internal().
03698 { 03699 int len; 03700 struct dundi_precache_queue *qe, *prev; 03701 03702 AST_LIST_LOCK(&pcq); 03703 AST_LIST_TRAVERSE_SAFE_BEGIN(&pcq, qe, list) { 03704 if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) { 03705 AST_LIST_REMOVE_CURRENT(list); 03706 break; 03707 } 03708 } 03709 AST_LIST_TRAVERSE_SAFE_END; 03710 if (!qe) { 03711 len = sizeof(*qe); 03712 len += strlen(number) + 1; 03713 len += strlen(context) + 1; 03714 if (!(qe = ast_calloc(1, len))) { 03715 AST_LIST_UNLOCK(&pcq); 03716 return; 03717 } 03718 strcpy(qe->number, number); 03719 qe->context = qe->number + strlen(number) + 1; 03720 strcpy(qe->context, context); 03721 } 03722 time(&qe->expiration); 03723 qe->expiration += expiration; 03724 if ((prev = AST_LIST_FIRST(&pcq))) { 03725 while (AST_LIST_NEXT(prev, list) && ((AST_LIST_NEXT(prev, list))->expiration <= qe->expiration)) 03726 prev = AST_LIST_NEXT(prev, list); 03727 AST_LIST_INSERT_AFTER(&pcq, prev, qe, list); 03728 } else 03729 AST_LIST_INSERT_HEAD(&pcq, qe, list); 03730 AST_LIST_UNLOCK(&pcq); 03731 }
| static int rescomp | ( | const void * | a, | |
| const void * | b | |||
| ) | [static] |
Definition at line 2413 of file pbx_dundi.c.
References dundi_result::weight.
Referenced by sort_results().
02414 { 02415 const struct dundi_result *resa, *resb; 02416 resa = a; 02417 resb = b; 02418 if (resa->weight < resb->weight) 02419 return -1; 02420 if (resa->weight > resb->weight) 02421 return 1; 02422 return 0; 02423 }
| static int reset_transaction | ( | struct dundi_transaction * | trans | ) | [static] |
Definition at line 488 of file pbx_dundi.c.
References dundi_transaction::aseqno, ast_clear_flag, dundi_transaction::dtrans, FLAG_FINAL, get_trans_id(), dundi_transaction::iseqno, dundi_transaction::oiseqno, dundi_transaction::oseqno, and dundi_transaction::strans.
Referenced by handle_command_response().
00489 { 00490 int tid; 00491 tid = get_trans_id(); 00492 if (tid < 1) 00493 return -1; 00494 trans->strans = tid; 00495 trans->dtrans = 0; 00496 trans->iseqno = 0; 00497 trans->oiseqno = 0; 00498 trans->oseqno = 0; 00499 trans->aseqno = 0; 00500 ast_clear_flag(trans, FLAG_FINAL); 00501 return 0; 00502 }
| static void save_secret | ( | const char * | newkey, | |
| const char * | oldkey | |||
| ) | [static] |
Definition at line 2105 of file pbx_dundi.c.
References ast_db_put(), and DUNDI_SECRET_TIME.
Referenced by check_password(), and load_password().
02106 { 02107 char tmp[256]; 02108 if (oldkey) 02109 snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey); 02110 else 02111 snprintf(tmp, sizeof(tmp), "%s", newkey); 02112 rotatetime = time(NULL) + DUNDI_SECRET_TIME; 02113 ast_db_put(secretpath, "secret", tmp); 02114 snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime); 02115 ast_db_put(secretpath, "secretexpiry", tmp); 02116 }
| static int set_config | ( | char * | config_file, | |
| struct sockaddr_in * | sin, | |||
| int | reload | |||
| ) | [static] |
Definition at line 4647 of file pbx_dundi.c.
References any_peer, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_eid_default, ast_gethostbyname(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_str2tos(), ast_str_to_eid(), ast_true(), ast_variable_browse(), build_mapping(), build_peer(), CONFIG_STATUS_FILEINVALID, DEFAULT_MAXMS, DUNDI_DEFAULT_CACHE_TIME, DUNDI_DEFAULT_TTL, DUNDI_MODEL_OUTBOUND, dundi_precache_full(), find_peer(), hp, ast_variable::lineno, load_password(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, mark_mappings(), mark_peers(), MAXHOSTNAMELEN, ast_variable::name, ast_variable::next, prune_mappings(), prune_peers(), and ast_variable::value.
04648 { 04649 struct ast_config *cfg; 04650 struct ast_variable *v; 04651 char *cat; 04652 int x; 04653 struct ast_flags config_flags = { 0 }; 04654 char hn[MAXHOSTNAMELEN] = ""; 04655 struct ast_hostent he; 04656 struct hostent *hp; 04657 struct sockaddr_in sin2; 04658 static int last_port = 0; 04659 int globalpcmodel = 0; 04660 dundi_eid testeid; 04661 04662 if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) { 04663 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); 04664 return -1; 04665 } 04666 04667 dundi_ttl = DUNDI_DEFAULT_TTL; 04668 dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME; 04669 any_peer = NULL; 04670 04671 ipaddr[0] = '\0'; 04672 if (!gethostname(hn, sizeof(hn)-1)) { 04673 hp = ast_gethostbyname(hn, &he); 04674 if (hp) { 04675 memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr)); 04676 ast_copy_string(ipaddr, ast_inet_ntoa(sin2.sin_addr), sizeof(ipaddr)); 04677 } else 04678 ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn); 04679 } else 04680 ast_log(LOG_WARNING, "Unable to get host name!\n"); 04681 AST_LIST_LOCK(&peers); 04682 04683 memcpy(&global_eid, &ast_eid_default, sizeof(global_eid)); 04684 04685 global_storehistory = 0; 04686 ast_copy_string(secretpath, "dundi", sizeof(secretpath)); 04687 v = ast_variable_browse(cfg, "general"); 04688 while(v) { 04689 if (!strcasecmp(v->name, "port")){ 04690 sin->sin_port = htons(atoi(v->value)); 04691 if(last_port==0){ 04692 last_port=sin->sin_port; 04693 } else if(sin->sin_port != last_port) 04694 ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n"); 04695 } else if (!strcasecmp(v->name, "bindaddr")) { 04696 struct hostent *hep; 04697 struct ast_hostent hent; 04698 hep = ast_gethostbyname(v->value, &hent); 04699 if (hep) { 04700 memcpy(&sin->sin_addr, hep->h_addr, sizeof(sin->sin_addr)); 04701 } else 04702 ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value); 04703 } else if (!strcasecmp(v->name, "authdebug")) { 04704 authdebug = ast_true(v->value); 04705 } else if (!strcasecmp(v->name, "ttl")) { 04706 if ((sscanf(v->value, "%30d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) { 04707 dundi_ttl = x; 04708 } else { 04709 ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n", 04710 v->value, v->lineno, DUNDI_DEFAULT_TTL); 04711 } 04712 } else if (!strcasecmp(v->name, "autokill")) { 04713 if (sscanf(v->value, "%30d", &x) == 1) { 04714 if (x >= 0) 04715 global_autokilltimeout = x; 04716 else 04717 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); 04718 } else if (ast_true(v->value)) { 04719 global_autokilltimeout = DEFAULT_MAXMS; 04720 } else { 04721 global_autokilltimeout = 0; 04722 } 04723 } else if (!strcasecmp(v->name, "entityid")) { 04724 if (!ast_str_to_eid(&testeid, v->value)) 04725 global_eid = testeid; 04726 else 04727 ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno); 04728 } else if (!strcasecmp(v->name, "tos")) { 04729 if (ast_str2tos(v->value, &tos)) 04730 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); 04731 } else if (!strcasecmp(v->name, "department")) { 04732 ast_copy_string(dept, v->value, sizeof(dept)); 04733 } else if (!strcasecmp(v->name, "organization")) { 04734 ast_copy_string(org, v->value, sizeof(org)); 04735 } else if (!strcasecmp(v->name, "locality")) { 04736 ast_copy_string(locality, v->value, sizeof(locality)); 04737 } else if (!strcasecmp(v->name, "stateprov")) { 04738 ast_copy_string(stateprov, v->value, sizeof(stateprov)); 04739 } else if (!strcasecmp(v->name, "country")) { 04740 ast_copy_string(country, v->value, sizeof(country)); 04741 } else if (!strcasecmp(v->name, "email")) { 04742 ast_copy_string(email, v->value, sizeof(email)); 04743 } else if (!strcasecmp(v->name, "phone")) { 04744 ast_copy_string(phone, v->value, sizeof(phone)); 04745 } else if (!strcasecmp(v->name, "storehistory")) { 04746 global_storehistory = ast_true(v->value); 04747 } else if (!strcasecmp(v->name, "cachetime")) { 04748 if ((sscanf(v->value, "%30d", &x) == 1)) { 04749 dundi_cache_time = x; 04750 } else { 04751 ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n", 04752 v->value, v->lineno, DUNDI_DEFAULT_CACHE_TIME); 04753 } 04754 } 04755 v = v->next; 04756 } 04757 AST_LIST_UNLOCK(&peers); 04758 mark_mappings(); 04759 v = ast_variable_browse(cfg, "mappings"); 04760 while(v) { 04761 build_mapping(v->name, v->value); 04762 v = v->next; 04763 } 04764 prune_mappings(); 04765 mark_peers(); 04766 cat = ast_category_browse(cfg, NULL); 04767 while(cat) { 04768 if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) { 04769 /* Entries */ 04770 if (!ast_str_to_eid(&testeid, cat)) 04771 build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel); 04772 else if (!strcasecmp(cat, "*")) { 04773 build_peer(&empty_eid, ast_variable_browse(cfg, cat), &globalpcmodel); 04774 any_peer = find_peer(NULL); 04775 } else 04776 ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat); 04777 } 04778 cat = ast_category_browse(cfg, cat); 04779 } 04780 prune_peers(); 04781 ast_config_destroy(cfg); 04782 load_password(); 04783 if (globalpcmodel & DUNDI_MODEL_OUTBOUND) 04784 dundi_precache_full(); 04785 return 0; 04786 }
| static int socket_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | cbdata | |||
| ) | [static] |
Definition at line 2062 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), dundi_showframe(), errno, handle_frame(), len(), LOG_WARNING, and MAX_PACKET_SIZE.
02063 { 02064 struct sockaddr_in sin; 02065 int res; 02066 struct dundi_hdr *h; 02067 char buf[MAX_PACKET_SIZE]; 02068 socklen_t len = sizeof(sin); 02069 02070 res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len); 02071 if (res < 0) { 02072 if (errno != ECONNREFUSED) 02073 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); 02074 return 1; 02075 } 02076 if (res < sizeof(struct dundi_hdr)) { 02077 ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct dundi_hdr)); 02078 return 1; 02079 } 02080 buf[res] = '\0'; 02081 h = (struct dundi_hdr *) buf; 02082 if (dundidebug) 02083 dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr)); 02084 AST_LIST_LOCK(&peers); 02085 handle_frame(h, &sin, res - sizeof(struct dundi_hdr)); 02086 AST_LIST_UNLOCK(&peers); 02087 return 1; 02088 }
| static void sort_results | ( | struct dundi_result * | results, | |
| int | count | |||
| ) | [static] |
Definition at line 2425 of file pbx_dundi.c.
References rescomp().
Referenced by dundi_do_lookup(), dundi_exec(), dundi_query_read(), and dundifunc_read().
02426 { 02427 qsort(results, count, sizeof(results[0]), rescomp); 02428 }
| static int start_network_thread | ( | void | ) | [static] |
Definition at line 2271 of file pbx_dundi.c.
References ast_pthread_create_background, network_thread(), process_clearcache(), and process_precache().
02272 { 02273 ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); 02274 ast_pthread_create_background(&precachethreadid, NULL, process_precache, NULL); 02275 ast_pthread_create_background(&clearcachethreadid, NULL, process_clearcache, NULL); 02276 return 0; 02277 }
| static int str2tech | ( | char * | str | ) | [static] |
Definition at line 387 of file pbx_dundi.c.
References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, and DUNDI_PROTO_SIP.
Referenced by build_mapping().
00388 { 00389 if (!strcasecmp(str, "IAX") || !strcasecmp(str, "IAX2")) 00390 return DUNDI_PROTO_IAX; 00391 else if (!strcasecmp(str, "SIP")) 00392 return DUNDI_PROTO_SIP; 00393 else if (!strcasecmp(str, "H323")) 00394 return DUNDI_PROTO_H323; 00395 else 00396 return -1; 00397 }
| static char* tech2str | ( | int | tech | ) | [static] |
Definition at line 371 of file pbx_dundi.c.
References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, DUNDI_PROTO_NONE, and DUNDI_PROTO_SIP.
Referenced by cache_lookup_internal(), dundi_lookup_local(), dundi_prop_precache(), dundi_show_mappings(), and handle_command_response().
00372 { 00373 switch(tech) { 00374 case DUNDI_PROTO_NONE: 00375 return "None"; 00376 case DUNDI_PROTO_IAX: 00377 return "IAX2"; 00378 case DUNDI_PROTO_SIP: 00379 return "SIP"; 00380 case DUNDI_PROTO_H323: 00381 return "H323"; 00382 default: 00383 return "Unknown"; 00384 } 00385 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 4788 of file pbx_dundi.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_module_user_hangup_all, AST_PTHREADT_NULL, ast_sched_context_destroy(), ast_unregister_switch(), io_context_destroy(), mark_mappings(), mark_peers(), prune_mappings(), and prune_peers().
04789 { 04790 pthread_t previous_netthreadid = netthreadid, previous_precachethreadid = precachethreadid, previous_clearcachethreadid = clearcachethreadid; 04791 ast_module_user_hangup_all(); 04792 04793 /* Stop all currently running threads */ 04794 dundi_shutdown = 1; 04795 if (previous_netthreadid != AST_PTHREADT_NULL) { 04796 pthread_kill(previous_netthreadid, SIGURG); 04797 pthread_join(previous_netthreadid, NULL); 04798 } 04799 if (previous_precachethreadid != AST_PTHREADT_NULL) { 04800 pthread_kill(previous_precachethreadid, SIGURG); 04801 pthread_join(previous_precachethreadid, NULL); 04802 } 04803 if (previous_clearcachethreadid != AST_PTHREADT_NULL) { 04804 pthread_cancel(previous_clearcachethreadid); 04805 pthread_join(previous_clearcachethreadid, NULL); 04806 } 04807 04808 ast_cli_unregister_multiple(cli_dundi, ARRAY_LEN(cli_dundi)); 04809 ast_unregister_switch(&dundi_switch); 04810 ast_custom_function_unregister(&dundi_function); 04811 ast_custom_function_unregister(&dundi_query_function); 04812 ast_custom_function_unregister(&dundi_result_function); 04813 close(netsocket); 04814 io_context_destroy(io); 04815 ast_sched_context_destroy(sched); 04816 04817 mark_mappings(); 04818 prune_mappings(); 04819 mark_peers(); 04820 prune_peers(); 04821 04822 return 0; 04823 }
| static void unregister_request | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3548 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
Referenced by dundi_lookup_internal().
03549 { 03550 AST_LIST_LOCK(&peers); 03551 AST_LIST_REMOVE(&requests, dr, list); 03552 AST_LIST_UNLOCK(&peers); 03553 }
| static int update_key | ( | struct dundi_peer * | peer | ) | [static] |
Definition at line 1315 of file pbx_dundi.c.
References ast_aes_set_decrypt_key(), ast_aes_set_encrypt_key(), ast_eid_to_str(), ast_encrypt_bin(), ast_key_get(), AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log(), ast_sign_bin(), build_iv(), dundi_peer::eid, dundi_peer::inkey, dundi_peer::keyexpire, LOG_NOTICE, dundi_peer::outkey, dundi_peer::sentfullkey, dundi_peer::txenckey, dundi_peer::us_dcx, dundi_peer::us_ecx, and dundi_peer::us_keycrc32.
Referenced by dundi_encrypt().
01316 { 01317 unsigned char key[16]; 01318 struct ast_key *ekey, *skey; 01319 char eid_str[20]; 01320 int res; 01321 if (!peer->keyexpire || (peer->keyexpire < time(NULL))) { 01322 build_iv(key); 01323 ast_aes_set_encrypt_key(key, &peer->us_ecx); 01324 ast_aes_set_decrypt_key(key, &peer->us_dcx); 01325 ekey = ast_key_get(peer->inkey, AST_KEY_PUBLIC); 01326 if (!ekey) { 01327 ast_log(LOG_NOTICE, "No such key '%s' for creating RSA encrypted shared key for '%s'!\n", 01328 peer->inkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01329 return -1; 01330 } 01331 skey = ast_key_get(peer->outkey, AST_KEY_PRIVATE); 01332 if (!skey) { 01333 ast_log(LOG_NOTICE, "No such key '%s' for signing RSA encrypted shared key for '%s'!\n", 01334 peer->outkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01335 return -1; 01336 } 01337 if ((res = ast_encrypt_bin(peer->txenckey, key, sizeof(key), ekey)) != 128) { 01338 ast_log(LOG_NOTICE, "Whoa, got a weird encrypt size (%d != %d)!\n", res, 128); 01339 return -1; 01340 } 01341 if ((res = ast_sign_bin(skey, (char *)peer->txenckey, 128, peer->txenckey + 128))) { 01342 ast_log(LOG_NOTICE, "Failed to sign key (%d)!\n", res); 01343 return -1; 01344 } 01345 peer->us_keycrc32 = crc32(0L, peer->txenckey, 128); 01346 peer->sentfullkey = 0; 01347 /* Looks good */ 01348 time(&peer->keyexpire); 01349 peer->keyexpire += dundi_key_ttl; 01350 } 01351 return 0; 01352 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Distributed Universal Number Discovery (DUNDi)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_crypto", } [static] |
Definition at line 4893 of file pbx_dundi.c.
struct dundi_peer* any_peer [static] |
Wildcard peer.
This peer is created if the [*] entry is specified in dundi.conf
Definition at line 343 of file pbx_dundi.c.
Referenced by find_peer(), handle_command_response(), and set_config().
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 4893 of file pbx_dundi.c.
int authdebug = 0 [static] |
Definition at line 184 of file pbx_dundi.c.
pthread_t clearcachethreadid = AST_PTHREADT_NULL [static] |
Definition at line 181 of file pbx_dundi.c.
struct ast_cli_entry cli_dundi[] [static] |
Definition at line 2894 of file pbx_dundi.c.
char country[80] [static] |
char cursecret[80] [static] |
Definition at line 200 of file pbx_dundi.c.
int default_expiration = 60 [static] |
Definition at line 190 of file pbx_dundi.c.
char dept[80] [static] |
Definition at line 192 of file pbx_dundi.c.
int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME [static] |
Definition at line 187 of file pbx_dundi.c.
int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE [static] |
Definition at line 186 of file pbx_dundi.c.
struct ast_custom_function dundi_query_function [static] |
Initial value:
{
.name = "DUNDIQUERY",
.read = dundi_query_read,
}
Definition at line 4050 of file pbx_dundi.c.
struct ast_app_option dundi_query_opts[128] = { [ 'b' ] = { .flag = OPT_BYPASS_CACHE }, } [static] |
Definition at line 3897 of file pbx_dundi.c.
Referenced by dundi_query_read(), and dundifunc_read().
struct ast_datastore_info dundi_result_datastore_info [static] |
Initial value:
{
.type = "DUNDIQUERY",
.destroy = drds_destroy_cb,
}
Definition at line 3977 of file pbx_dundi.c.
struct ast_custom_function dundi_result_function [static] |
Initial value:
{
.name = "DUNDIRESULT",
.read = dundi_result_read,
}
Definition at line 4129 of file pbx_dundi.c.
unsigned int dundi_result_id [static] |
Definition at line 3958 of file pbx_dundi.c.
int dundi_shutdown = 0 [static] |
Definition at line 204 of file pbx_dundi.c.
struct ast_switch dundi_switch [static] |
Definition at line 4638 of file pbx_dundi.c.
int dundi_ttl = DUNDI_DEFAULT_TTL [static] |
Definition at line 185 of file pbx_dundi.c.
int dundidebug = 0 [static] |
Definition at line 183 of file pbx_dundi.c.
char email[80] [static] |
Definition at line 197 of file pbx_dundi.c.
Definition at line 203 of file pbx_dundi.c.
int global_autokilltimeout = 0 [static] |
Definition at line 188 of file pbx_dundi.c.
dundi_eid global_eid [static] |
Definition at line 189 of file pbx_dundi.c.
int global_storehistory = 0 [static] |
Definition at line 191 of file pbx_dundi.c.
struct io_context* io [static] |
Definition at line 176 of file pbx_dundi.c.
char ipaddr[80] [static] |
Definition at line 201 of file pbx_dundi.c.
Referenced by realtime_peer(), and realtime_update_peer().
char locality[80] [static] |
Definition at line 194 of file pbx_dundi.c.
int netsocket = -1 [static] |
Definition at line 178 of file pbx_dundi.c.
Referenced by ast_netsock_bindaddr(), and handle_error().
pthread_t netthreadid = AST_PTHREADT_NULL [static] |
Definition at line 179 of file pbx_dundi.c.
char org[80] [static] |
char phone[80] [static] |
pthread_t precachethreadid = AST_PTHREADT_NULL [static] |
Definition at line 180 of file pbx_dundi.c.
time_t rotatetime [static] |
Definition at line 202 of file pbx_dundi.c.
struct ast_sched_context* sched [static] |
Definition at line 177 of file pbx_dundi.c.
char secretpath[80] [static] |
Definition at line 199 of file pbx_dundi.c.
char stateprov[80] [static] |
Definition at line 195 of file pbx_dundi.c.
unsigned int tos = 0 [static] |
Definition at line 182 of file pbx_dundi.c.
1.5.6