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