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