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