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