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