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