#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <netinet/ip.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <zlib.h>
#include <sys/signal.h>
#include <pthread.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/options.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/crypto.h"
#include "asterisk/astdb.h"
#include "asterisk/acl.h"
#include "asterisk/aes.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_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 | FLAG_DEAD (1 << 1) |
#define | FLAG_ENCRYPT (1 << 4) |
#define | FLAG_FINAL (1 << 2) |
#define | FLAG_ISQUAL (1 << 3) |
#define | FLAG_ISREG (1 << 0) |
#define | FLAG_SENDFULLKEY (1 << 5) |
#define | FLAG_STOREHIST (1 << 6) |
#define | FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n" |
#define | FORMAT "%-12.12s %-7d %-12.12s %-10.10s %-5.5s %-25.25s\n" |
#define | FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n" |
#define | FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n" |
#define | FORMAT "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n" |
#define | FORMAT2 "%-12.12s %-12.12s %-10.10s\n" |
#define | FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n" |
#define | FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n" |
#define | FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n" |
#define | FORMAT2 "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n" |
#define | KEY_IN 1 |
#define | KEY_OUT 0 |
#define | MAX_OPTS 128 |
#define | MAX_PACKET_SIZE 8192 |
#define | MAX_RESULTS 64 |
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, 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 (char *name, 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_4 (const char *line, const char *word, int pos, int state) |
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, aes_decrypt_ctx *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 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 int | dundi_do_debug (int fd, int argc, char *argv[]) |
static int | dundi_do_lookup (int fd, int argc, char *argv[]) |
static int | dundi_do_precache (int fd, int argc, char *argv[]) |
static int | dundi_do_query (int fd, int argc, char *argv[]) |
static int | dundi_do_store_history (int fd, int argc, char *argv[]) |
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 int | dundi_flush (int fd, int argc, char *argv[]) |
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 (or e164 if unspecified) using the given callerid (if specified) and return up to maxret results in the array specified. returns the number of results found or -1 on a hangup of teh channel. | |
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) |
static int | dundi_no_debug (int fd, int argc, char *argv[]) |
static int | dundi_no_store_history (int fd, int argc, char *argv[]) |
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 void * | dundi_query_thread (void *data) |
static void | dundi_reject (struct dundi_hdr *h, struct sockaddr_in *sin) |
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 int | dundi_show_entityid (int fd, int argc, char *argv[]) |
static int | dundi_show_mappings (int fd, int argc, char *argv[]) |
static int | dundi_show_peer (int fd, int argc, char *argv[]) |
static int | dundi_show_peers (int fd, int argc, char *argv[]) |
static int | dundi_show_precache (int fd, int argc, char *argv[]) |
static int | dundi_show_requests (int fd, int argc, char *argv[]) |
static int | dundi_show_trans (int fd, int argc, char *argv[]) |
static int | dundi_xmit (struct dundi_packet *pack) |
static int | dundifunc_read (struct ast_channel *chan, char *cmd, char *num, char *buf, size_t len) |
static int | encrypt_memcpy (unsigned char *dst, unsigned char *src, int len, unsigned char *iv, aes_encrypt_ctx *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_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) |
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 | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 char | country [80] |
static char | cursecret [80] |
static char | debug_usage [] |
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 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 char | flush_usage [] |
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 char | lookup_usage [] |
static int | netsocket = -1 |
static pthread_t | netthreadid = AST_PTHREADT_NULL |
static char | no_debug_usage [] |
static char | no_store_history_usage [] |
static char | org [80] |
static char | phone [80] |
static char | precache_usage [] |
static pthread_t | precachethreadid = AST_PTHREADT_NULL |
static char | query_usage [] |
static time_t | rotatetime |
static struct sched_context * | sched |
static char | secretpath [80] |
static char | show_entityid_usage [] |
static char | show_mappings_usage [] |
static char | show_peer_usage [] |
static char | show_peers_usage [] |
static char | show_precache_usage [] |
static char | show_requests_usage [] |
static char | show_trans_usage [] |
static char | stateprov [80] |
static char | store_history_usage [] |
static 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 84 of file pbx_dundi.c.
Referenced by dundi_show_peer(), handle_command_response(), and model2str().
#define DUNDI_MODEL_OUTBOUND (1 << 1) |
Definition at line 85 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 89 of file pbx_dundi.c.
Referenced by destroy_trans(), dundi_flush(), and dundi_show_peer().
#define FLAG_DEAD (1 << 1) |
Transaction is dead
Definition at line 92 of file pbx_dundi.c.
Referenced by dundi_lookup_thread(), dundi_precache_thread(), dundi_query_thread(), and precache_transactions().
#define FLAG_ENCRYPT (1 << 4) |
Transaction is encrypted wiht ECX/DCX
Definition at line 95 of file pbx_dundi.c.
Referenced by apply_peer(), dundi_send(), and handle_command_response().
#define FLAG_FINAL (1 << 2) |
Transaction has final message sent
Definition at line 93 of file pbx_dundi.c.
Referenced by dundi_send(), handle_frame(), and reset_transaction().
#define FLAG_ISQUAL (1 << 3) |
Transaction is a qualification
Definition at line 94 of file pbx_dundi.c.
Referenced by destroy_trans(), dundi_rexmit(), and qualify_peer().
#define FLAG_ISREG (1 << 0) |
Transaction is register request
Definition at line 91 of file pbx_dundi.c.
Referenced by destroy_trans(), and do_register().
#define FLAG_SENDFULLKEY (1 << 5) |
Send full key on transaction
Definition at line 96 of file pbx_dundi.c.
Referenced by create_transaction(), and dundi_encrypt().
#define FLAG_STOREHIST (1 << 6) |
Record historic performance
Definition at line 97 of file pbx_dundi.c.
Referenced by create_transaction(), and destroy_trans().
#define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n" |
#define FORMAT "%-12.12s %-7d %-12.12s %-10.10s %-5.5s %-25.25s\n" |
#define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n" |
#define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n" |
#define FORMAT "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n" |
#define FORMAT2 "%-12.12s %-12.12s %-10.10s\n" |
#define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n" |
#define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n" |
#define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n" |
#define FORMAT2 "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n" |
#define KEY_IN 1 |
Definition at line 108 of file pbx_dundi.c.
#define KEY_OUT 0 |
Definition at line 107 of file pbx_dundi.c.
#define MAX_OPTS 128 |
#define MAX_PACKET_SIZE 8192 |
#define MAX_RESULTS 64 |
Definition at line 80 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().
static void __reg_module | ( | void | ) | [static] |
Definition at line 4685 of file pbx_dundi.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 4685 of file pbx_dundi.c.
static void abort_request | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3405 of file pbx_dundi.c.
References AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, destroy_trans(), and dr.
Referenced by dundi_lookup_internal().
03406 { 03407 struct dundi_transaction *trans; 03408 03409 AST_LIST_LOCK(&peers); 03410 while ((trans = AST_LIST_FIRST(&dr->trans))) { 03411 /* This will remove the transaction from the list */ 03412 destroy_trans(trans, 0); 03413 } 03414 AST_LIST_UNLOCK(&peers); 03415 }
static int ack_trans | ( | struct dundi_transaction * | trans, | |
int | iseqno | |||
) | [static] |
Definition at line 1976 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().
01977 { 01978 struct dundi_packet *pack; 01979 01980 /* Ack transmitted packet corresponding to iseqno */ 01981 AST_LIST_TRAVERSE(&trans->packets, pack, list) { 01982 if ((pack->h->oseqno + 1) % 255 == iseqno) { 01983 destroy_packet(pack, 0); 01984 if (!AST_LIST_EMPTY(&trans->lasttrans)) { 01985 ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n"); 01986 destroy_packets(&trans->lasttrans); 01987 } 01988 AST_LIST_INSERT_HEAD(&trans->lasttrans, pack, list); 01989 AST_SCHED_DEL(sched, trans->autokillid); 01990 return 1; 01991 } 01992 } 01993 01994 return 0; 01995 }
static void append_permission | ( | struct permissionlist * | permlist, | |
char * | s, | |||
int | allow | |||
) | [static] |
Definition at line 3992 of file pbx_dundi.c.
References ast_calloc, AST_LIST_INSERT_TAIL, and permission::list.
03993 { 03994 struct permission *perm; 03995 03996 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(s) + 1))) 03997 return; 03998 03999 strcpy(perm->name, s); 04000 perm->allow = allow; 04001 04002 AST_LIST_INSERT_TAIL(permlist, perm, list); 04003 }
static int append_transaction | ( | struct dundi_request * | dr, | |
struct dundi_peer * | p, | |||
int | ttl, | |||
dundi_eid * | avoid[] | |||
) | [static] |
Definition at line 3362 of file pbx_dundi.c.
References dundi_peer::addr, AST_LIST_INSERT_HEAD, ast_log(), 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, LOG_DEBUG, dundi_peer::maxms, dundi_transaction::parent, dundi_transaction::parentlist, and dundi_transaction::ttl.
Referenced by build_transactions().
03363 { 03364 struct dundi_transaction *trans; 03365 int x; 03366 char eid_str[20]; 03367 char eid_str2[20]; 03368 03369 /* Ignore if not registered */ 03370 if (!p->addr.sin_addr.s_addr) 03371 return 0; 03372 if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms))) 03373 return 0; 03374 if (ast_strlen_zero(dr->number)) 03375 ast_log(LOG_DEBUG, "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); 03376 else 03377 ast_log(LOG_DEBUG, "Will query peer '%s' for '%s@%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid), dr->number, dr->dcontext); 03378 trans = create_transaction(p); 03379 if (!trans) 03380 return -1; 03381 trans->parent = dr; 03382 trans->ttl = ttl; 03383 for (x = 0; avoid[x] && (x < DUNDI_MAX_STACK); x++) 03384 trans->eids[x] = *avoid[x]; 03385 trans->eidcount = x; 03386 AST_LIST_INSERT_HEAD(&dr->trans, trans, parentlist); 03387 03388 return 0; 03389 }
static void apply_peer | ( | struct dundi_transaction * | trans, | |
struct dundi_peer * | p | |||
) | [static] |
Definition at line 1253 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().
01254 { 01255 if (!trans->addr.sin_addr.s_addr) 01256 memcpy(&trans->addr, &p->addr, sizeof(trans->addr)); 01257 trans->us_eid = p->us_eid; 01258 trans->them_eid = p->eid; 01259 /* Enable encryption if appropriate */ 01260 if (!ast_strlen_zero(p->inkey)) 01261 ast_set_flag(trans, FLAG_ENCRYPT); 01262 if (p->maxms) { 01263 trans->autokilltimeout = p->maxms; 01264 trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; 01265 if (p->lastms > 1) { 01266 trans->retranstimer = p->lastms * 2; 01267 /* Keep it from being silly */ 01268 if (trans->retranstimer < 150) 01269 trans->retranstimer = 150; 01270 } 01271 if (trans->retranstimer > DUNDI_DEFAULT_RETRANS_TIMER) 01272 trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; 01273 } else 01274 trans->autokilltimeout = global_autokilltimeout; 01275 }
static unsigned long avoid_crc32 | ( | dundi_eid * | avoid[] | ) | [static] |
Definition at line 3526 of file pbx_dundi.c.
References dundi_request::crc32.
Referenced by dundi_lookup_internal().
03527 { 03528 /* Idea is that we're calculating a checksum which is independent of 03529 the order that the EID's are listed in */ 03530 uint32_t acrc32 = 0; 03531 int x; 03532 for (x=0;avoid[x];x++) { 03533 /* Order doesn't matter */ 03534 if (avoid[x+1]) { 03535 acrc32 ^= crc32(0L, (unsigned char *)avoid[x], sizeof(dundi_eid)); 03536 } 03537 } 03538 return acrc32; 03539 }
static void build_iv | ( | unsigned char * | iv | ) | [static] |
Definition at line 503 of file pbx_dundi.c.
References ast_random().
Referenced by build_secret(), dundi_encrypt(), and update_key().
00504 { 00505 /* XXX Would be nice to be more random XXX */ 00506 unsigned int *fluffy; 00507 int x; 00508 fluffy = (unsigned int *)(iv); 00509 for (x=0;x<4;x++) 00510 fluffy[x] = ast_random(); 00511 }
static void build_mapping | ( | char * | name, | |
char * | value | |||
) | [static] |
Definition at line 4007 of file pbx_dundi.c.
References ast_calloc, ast_copy_string(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_log(), 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, str2tech(), and t.
Referenced by set_config().
04008 { 04009 char *t, *fields[MAX_OPTS]; 04010 struct dundi_mapping *map; 04011 int x; 04012 int y; 04013 04014 t = ast_strdupa(value); 04015 04016 AST_LIST_TRAVERSE(&mappings, map, list) { 04017 /* Find a double match */ 04018 if (!strcasecmp(map->dcontext, name) && 04019 (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) && 04020 (!value[strlen(map->lcontext)] || 04021 (value[strlen(map->lcontext)] == ',')))) 04022 break; 04023 } 04024 if (!map) { 04025 if (!(map = ast_calloc(1, sizeof(*map)))) 04026 return; 04027 AST_LIST_INSERT_HEAD(&mappings, map, list); 04028 map->dead = 1; 04029 } 04030 map->options = 0; 04031 memset(fields, 0, sizeof(fields)); 04032 x = 0; 04033 while (t && x < MAX_OPTS) { 04034 fields[x++] = t; 04035 t = strchr(t, ','); 04036 if (t) { 04037 *t = '\0'; 04038 t++; 04039 } 04040 } /* Russell was here, arrrr! */ 04041 if ((x == 1) && ast_strlen_zero(fields[0])) { 04042 /* Placeholder mapping */ 04043 ast_copy_string(map->dcontext, name, sizeof(map->dcontext)); 04044 map->dead = 0; 04045 } else if (x >= 4) { 04046 ast_copy_string(map->dcontext, name, sizeof(map->dcontext)); 04047 ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext)); 04048 if ((sscanf(fields[1], "%30d", &map->weight) == 1) && (map->weight >= 0) && (map->weight < 60000)) { 04049 ast_copy_string(map->dest, fields[3], sizeof(map->dest)); 04050 if ((map->tech = str2tech(fields[2]))) { 04051 map->dead = 0; 04052 } 04053 } else { 04054 ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext); 04055 } 04056 for (y = 4;y < x; y++) { 04057 if (!strcasecmp(fields[y], "nounsolicited")) 04058 map->options |= DUNDI_FLAG_NOUNSOLICITED; 04059 else if (!strcasecmp(fields[y], "nocomunsolicit")) 04060 map->options |= DUNDI_FLAG_NOCOMUNSOLICIT; 04061 else if (!strcasecmp(fields[y], "residential")) 04062 map->options |= DUNDI_FLAG_RESIDENTIAL; 04063 else if (!strcasecmp(fields[y], "commercial")) 04064 map->options |= DUNDI_FLAG_COMMERCIAL; 04065 else if (!strcasecmp(fields[y], "mobile")) 04066 map->options |= DUNDI_FLAG_MOBILE; 04067 else if (!strcasecmp(fields[y], "nopartial")) 04068 map->options |= DUNDI_FLAG_INTERNAL_NOPARTIAL; 04069 else 04070 ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]); 04071 } 04072 } else 04073 ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x); 04074 }
static void build_peer | ( | dundi_eid * | eid, | |
struct ast_variable * | v, | |||
int * | globalpcmode | |||
) | [static] |
Definition at line 4158 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.
04159 { 04160 struct dundi_peer *peer; 04161 struct ast_hostent he; 04162 struct hostent *hp; 04163 dundi_eid testeid; 04164 int needregister=0; 04165 char eid_str[20]; 04166 04167 AST_LIST_LOCK(&peers); 04168 AST_LIST_TRAVERSE(&peers, peer, list) { 04169 if (!dundi_eid_cmp(&peer->eid, eid)) { 04170 break; 04171 } 04172 } 04173 if (!peer) { 04174 /* Add us into the list */ 04175 if (!(peer = ast_calloc(1, sizeof(*peer)))) { 04176 AST_LIST_UNLOCK(&peers); 04177 return; 04178 } 04179 peer->registerid = -1; 04180 peer->registerexpire = -1; 04181 peer->qualifyid = -1; 04182 peer->addr.sin_family = AF_INET; 04183 peer->addr.sin_port = htons(DUNDI_PORT); 04184 populate_addr(peer, eid); 04185 AST_LIST_INSERT_HEAD(&peers, peer, list); 04186 } 04187 peer->dead = 0; 04188 peer->eid = *eid; 04189 peer->us_eid = global_eid; 04190 destroy_permissions(&peer->permit); 04191 destroy_permissions(&peer->include); 04192 AST_SCHED_DEL(sched, peer->registerid); 04193 for (; v; v = v->next) { 04194 if (!strcasecmp(v->name, "inkey")) { 04195 ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey)); 04196 } else if (!strcasecmp(v->name, "outkey")) { 04197 ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey)); 04198 } else if (!strcasecmp(v->name, "port")) { 04199 peer->addr.sin_port = htons(atoi(v->value)); 04200 } else if (!strcasecmp(v->name, "host")) { 04201 if (!strcasecmp(v->value, "dynamic")) { 04202 peer->dynamic = 1; 04203 } else { 04204 hp = ast_gethostbyname(v->value, &he); 04205 if (hp) { 04206 memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr)); 04207 peer->dynamic = 0; 04208 } else { 04209 ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno); 04210 peer->dead = 1; 04211 } 04212 } 04213 } else if (!strcasecmp(v->name, "ustothem")) { 04214 if (!dundi_str_to_eid(&testeid, v->value)) 04215 peer->us_eid = testeid; 04216 else 04217 ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno); 04218 } else if (!strcasecmp(v->name, "include")) { 04219 append_permission(&peer->include, v->value, 1); 04220 } else if (!strcasecmp(v->name, "permit")) { 04221 append_permission(&peer->permit, v->value, 1); 04222 } else if (!strcasecmp(v->name, "noinclude")) { 04223 append_permission(&peer->include, v->value, 0); 04224 } else if (!strcasecmp(v->name, "deny")) { 04225 append_permission(&peer->permit, v->value, 0); 04226 } else if (!strcasecmp(v->name, "register")) { 04227 needregister = ast_true(v->value); 04228 } else if (!strcasecmp(v->name, "order")) { 04229 if (!strcasecmp(v->value, "primary")) 04230 peer->order = 0; 04231 else if (!strcasecmp(v->value, "secondary")) 04232 peer->order = 1; 04233 else if (!strcasecmp(v->value, "tertiary")) 04234 peer->order = 2; 04235 else if (!strcasecmp(v->value, "quartiary")) 04236 peer->order = 3; 04237 else { 04238 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); 04239 } 04240 } else if (!strcasecmp(v->name, "qualify")) { 04241 if (!strcasecmp(v->value, "no")) { 04242 peer->maxms = 0; 04243 } else if (!strcasecmp(v->value, "yes")) { 04244 peer->maxms = DEFAULT_MAXMS; 04245 } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) { 04246 ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n", 04247 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno); 04248 peer->maxms = 0; 04249 } 04250 } else if (!strcasecmp(v->name, "model")) { 04251 if (!strcasecmp(v->value, "inbound")) 04252 peer->model = DUNDI_MODEL_INBOUND; 04253 else if (!strcasecmp(v->value, "outbound")) 04254 peer->model = DUNDI_MODEL_OUTBOUND; 04255 else if (!strcasecmp(v->value, "symmetric")) 04256 peer->model = DUNDI_MODEL_SYMMETRIC; 04257 else if (!strcasecmp(v->value, "none")) 04258 peer->model = 0; 04259 else { 04260 ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 04261 v->value, v->lineno); 04262 } 04263 } else if (!strcasecmp(v->name, "precache")) { 04264 if (!strcasecmp(v->value, "inbound")) 04265 peer->pcmodel = DUNDI_MODEL_INBOUND; 04266 else if (!strcasecmp(v->value, "outbound")) 04267 peer->pcmodel = DUNDI_MODEL_OUTBOUND; 04268 else if (!strcasecmp(v->value, "symmetric")) 04269 peer->pcmodel = DUNDI_MODEL_SYMMETRIC; 04270 else if (!strcasecmp(v->value, "none")) 04271 peer->pcmodel = 0; 04272 else { 04273 ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 04274 v->value, v->lineno); 04275 } 04276 } 04277 } 04278 (*globalpcmode) |= peer->pcmodel; 04279 if (!peer->model && !peer->pcmodel) { 04280 ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n", 04281 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04282 peer->dead = 1; 04283 } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) { 04284 ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n", 04285 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04286 peer->dead = 1; 04287 } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) { 04288 ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n", 04289 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04290 peer->dead = 1; 04291 } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) { 04292 ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n", 04293 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04294 } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) { 04295 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", 04296 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04297 } else { 04298 if (needregister) { 04299 peer->registerid = ast_sched_add(sched, 2000, do_register, peer); 04300 } 04301 qualify_peer(peer, 1); 04302 } 04303 AST_LIST_UNLOCK(&peers); 04304 }
static void build_secret | ( | char * | secret, | |
int | seclen | |||
) | [static] |
Definition at line 2066 of file pbx_dundi.c.
References ast_base64encode(), build_iv(), and s.
Referenced by check_password(), and load_password().
02067 { 02068 unsigned char tmp[16]; 02069 char *s; 02070 build_iv(tmp); 02071 secret[0] = '\0'; 02072 ast_base64encode(secret, tmp, sizeof(tmp), seclen); 02073 /* Eliminate potential bad characters */ 02074 while((s = strchr(secret, ';'))) *s = '+'; 02075 while((s = strchr(secret, '/'))) *s = '+'; 02076 while((s = strchr(secret, ':'))) *s = '+'; 02077 while((s = strchr(secret, '@'))) *s = '+'; 02078 }
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 3417 of file pbx_dundi.c.
References append_transaction(), ast_clear_flag_nonstd, AST_LIST_LOCK, AST_LIST_TRAVERSE, ast_log(), 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, LOG_DEBUG, dundi_peer::model, dundi_peer::order, dundi_peer::pcmodel, dundi_peer::permit, and dundi_peer::us_eid.
Referenced by dundi_lookup_internal(), dundi_precache_internal(), and dundi_query_eid_internal().
03418 { 03419 struct dundi_peer *p; 03420 int x; 03421 int res; 03422 int pass; 03423 int allowconnect; 03424 char eid_str[20]; 03425 AST_LIST_LOCK(&peers); 03426 AST_LIST_TRAVERSE(&peers, p, list) { 03427 if (modeselect == 1) { 03428 /* Send the precache to push upstreams only! */ 03429 pass = has_permission(&p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND); 03430 allowconnect = 1; 03431 } else { 03432 /* Normal lookup / EID query */ 03433 pass = has_permission(&p->include, dr->dcontext); 03434 allowconnect = p->model & DUNDI_MODEL_OUTBOUND; 03435 } 03436 if (skip) { 03437 if (!dundi_eid_cmp(skip, &p->eid)) 03438 pass = 0; 03439 } 03440 if (pass) { 03441 if (p->order <= order) { 03442 /* Check order first, then check cache, regardless of 03443 omissions, this gets us more likely to not have an 03444 affected answer. */ 03445 if((nocache || !(res = cache_lookup(dr, &p->eid, dr->crc32, &dr->expiration)))) { 03446 res = 0; 03447 /* Make sure we haven't already seen it and that it won't 03448 affect our answer */ 03449 for (x=0;avoid[x];x++) { 03450 if (!dundi_eid_cmp(avoid[x], &p->eid) || !dundi_eid_cmp(avoid[x], &p->us_eid)) { 03451 /* If not a direct connection, it affects our answer */ 03452 if (directs && !directs[x]) 03453 ast_clear_flag_nonstd(dr->hmd, DUNDI_HINT_UNAFFECTED); 03454 break; 03455 } 03456 } 03457 /* Make sure we can ask */ 03458 if (allowconnect) { 03459 if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) { 03460 /* Check for a matching or 0 cache entry */ 03461 append_transaction(dr, p, ttl, avoid); 03462 } else 03463 ast_log(LOG_DEBUG, "Avoiding '%s' in transaction\n", dundi_eid_to_str(eid_str, sizeof(eid_str), avoid[x])); 03464 } 03465 } 03466 *foundcache |= res; 03467 } else if (!*skipped || (p->order < *skipped)) 03468 *skipped = p->order; 03469 } 03470 } 03471 AST_LIST_UNLOCK(&peers); 03472 }
static int cache_lookup | ( | struct dundi_request * | req, | |
dundi_eid * | peer_eid, | |||
uint32_t | crc32, | |||
int * | lowexpiration | |||
) | [static] |
Definition at line 1201 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().
01202 { 01203 char key[256]; 01204 char eid_str[20]; 01205 char eidroot_str[20]; 01206 time_t now; 01207 int res=0; 01208 int res2=0; 01209 char eid_str_full[20]; 01210 char tmp[256]=""; 01211 int x; 01212 01213 time(&now); 01214 dundi_eid_to_str_short(eid_str, sizeof(eid_str), peer_eid); 01215 dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); 01216 dundi_eid_to_str(eid_str_full, sizeof(eid_str_full), peer_eid); 01217 snprintf(key, sizeof(key), "%s/%s/%s/e%08x", eid_str, req->number, req->dcontext, crc32); 01218 res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01219 snprintf(key, sizeof(key), "%s/%s/%s/e%08x", eid_str, req->number, req->dcontext, 0); 01220 res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01221 snprintf(key, sizeof(key), "%s/%s/%s/r%s", eid_str, req->number, req->dcontext, eidroot_str); 01222 res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01223 x = 0; 01224 if (!req->respcount) { 01225 while(!res2) { 01226 /* Look and see if we have a hint that would preclude us from looking at this 01227 peer for this number. */ 01228 if (!(tmp[x] = req->number[x])) 01229 break; 01230 x++; 01231 /* Check for hints */ 01232 snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08x", eid_str, tmp, req->dcontext, crc32); 01233 res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01234 snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08x", eid_str, tmp, req->dcontext, 0); 01235 res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01236 snprintf(key, sizeof(key), "hint/%s/%s/%s/r%s", eid_str, tmp, req->dcontext, eidroot_str); 01237 res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01238 if (res2) { 01239 if (strlen(tmp) > strlen(req->hmd->exten)) { 01240 /* Update meta data if appropriate */ 01241 ast_copy_string(req->hmd->exten, tmp, sizeof(req->hmd->exten)); 01242 } 01243 } 01244 } 01245 res |= res2; 01246 } 01247 01248 return res; 01249 }
static int cache_lookup_internal | ( | time_t | now, | |
struct dundi_request * | req, | |||
char * | key, | |||
char * | eid_str_full, | |||
int * | lowexpiration | |||
) | [static] |
Definition at line 1129 of file pbx_dundi.c.
References ast_clear_flag_nonstd, ast_copy_flags, ast_copy_string(), ast_db_del(), ast_db_get(), AST_FLAGS_ALL, ast_get_time_t(), ast_log(), 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, LOG_DEBUG, dundi_request::respcount, dundi_mapping::tech, tech2str(), dundi_result::techint, and dundi_result::weight.
Referenced by cache_lookup().
01130 { 01131 char data[1024]; 01132 char *ptr, *term, *src; 01133 int tech; 01134 struct ast_flags flags; 01135 int weight; 01136 int length; 01137 int z; 01138 char fs[256]; 01139 01140 /* Build request string */ 01141 if (!ast_db_get("dundi/cache", key, data, sizeof(data))) { 01142 time_t timeout; 01143 ptr = data; 01144 if (!ast_get_time_t(ptr, &timeout, 0, &length)) { 01145 int expiration = timeout - now; 01146 if (expiration > 0) { 01147 ast_log(LOG_DEBUG, "Found cache expiring in %d seconds!\n", expiration); 01148 ptr += length + 1; 01149 while((sscanf(ptr, "%30d/%30d/%30d/%n", &(flags.flags), &weight, &tech, &length) == 3)) { 01150 ptr += length; 01151 term = strchr(ptr, '|'); 01152 if (term) { 01153 *term = '\0'; 01154 src = strrchr(ptr, '/'); 01155 if (src) { 01156 *src = '\0'; 01157 src++; 01158 } else 01159 src = ""; 01160 ast_log(LOG_DEBUG, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n", 01161 tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags.flags), eid_str_full); 01162 /* Make sure it's not already there */ 01163 for (z=0;z<req->respcount;z++) { 01164 if ((req->dr[z].techint == tech) && 01165 !strcmp(req->dr[z].dest, ptr)) 01166 break; 01167 } 01168 if (z == req->respcount) { 01169 /* Copy into parent responses */ 01170 ast_copy_flags(&(req->dr[req->respcount]), &flags, AST_FLAGS_ALL); 01171 req->dr[req->respcount].weight = weight; 01172 req->dr[req->respcount].techint = tech; 01173 req->dr[req->respcount].expiration = expiration; 01174 dundi_str_short_to_eid(&req->dr[req->respcount].eid, src); 01175 dundi_eid_to_str(req->dr[req->respcount].eid_str, 01176 sizeof(req->dr[req->respcount].eid_str), &req->dr[req->respcount].eid); 01177 ast_copy_string(req->dr[req->respcount].dest, ptr, 01178 sizeof(req->dr[req->respcount].dest)); 01179 ast_copy_string(req->dr[req->respcount].tech, tech2str(tech), 01180 sizeof(req->dr[req->respcount].tech)); 01181 req->respcount++; 01182 ast_clear_flag_nonstd(req->hmd, DUNDI_HINT_DONT_ASK); 01183 } else if (req->dr[z].weight > weight) 01184 req->dr[z].weight = weight; 01185 ptr = term + 1; 01186 } 01187 } 01188 /* We found *something* cached */ 01189 if (expiration < *lowexpiration) 01190 *lowexpiration = expiration; 01191 return 1; 01192 } else 01193 ast_db_del("dundi/cache", key); 01194 } else 01195 ast_db_del("dundi/cache", key); 01196 } 01197 01198 return 0; 01199 }
static int cache_save | ( | dundi_eid * | eidpeer, | |
struct dundi_request * | req, | |||
int | start, | |||
int | unaffected, | |||
int | expiration, | |||
int | push | |||
) | [static] |
Definition at line 848 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().
00849 { 00850 int x; 00851 char key1[256]; 00852 char key2[256]; 00853 char data[1024]; 00854 char eidpeer_str[20]; 00855 char eidroot_str[20]; 00856 time_t timeout; 00857 00858 if (expiration < 1) 00859 expiration = dundi_cache_time; 00860 00861 /* Keep pushes a little longer, cut pulls a little short */ 00862 if (push) 00863 expiration += 10; 00864 else 00865 expiration -= 10; 00866 if (expiration < 1) 00867 expiration = 1; 00868 dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer); 00869 dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); 00870 snprintf(key1, sizeof(key1), "%s/%s/%s/e%08x", eidpeer_str, req->number, req->dcontext, unaffected ? 0 : req->crc32); 00871 snprintf(key2, sizeof(key2), "%s/%s/%s/r%s", eidpeer_str, req->number, req->dcontext, eidroot_str); 00872 /* Build request string */ 00873 time(&timeout); 00874 timeout += expiration; 00875 snprintf(data, sizeof(data), "%ld|", (long)(timeout)); 00876 for (x=start;x<req->respcount;x++) { 00877 /* Skip anything with an illegal pipe in it */ 00878 if (strchr(req->dr[x].dest, '|')) 00879 continue; 00880 snprintf(data + strlen(data), sizeof(data) - strlen(data), "%d/%d/%d/%s/%s|", 00881 req->dr[x].flags, req->dr[x].weight, req->dr[x].techint, req->dr[x].dest, 00882 dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), &req->dr[x].eid)); 00883 } 00884 ast_db_put("dundi/cache", key1, data); 00885 ast_db_put("dundi/cache", key2, data); 00886 return 0; 00887 }
static int cache_save_hint | ( | dundi_eid * | eidpeer, | |
struct dundi_request * | req, | |||
struct dundi_hint * | hint, | |||
int | expiration | |||
) | [static] |
Definition at line 813 of file pbx_dundi.c.
References ast_db_put(), ast_log(), 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, LOG_DEBUG, and dundi_request::root_eid.
Referenced by handle_command_response().
00814 { 00815 int unaffected; 00816 char key1[256]; 00817 char key2[256]; 00818 char eidpeer_str[20]; 00819 char eidroot_str[20]; 00820 char data[80]; 00821 time_t timeout; 00822 00823 if (expiration < 0) 00824 expiration = dundi_cache_time; 00825 00826 /* Only cache hint if "don't ask" is there... */ 00827 if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK))) 00828 return 0; 00829 00830 unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED)); 00831 00832 dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer); 00833 dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); 00834 snprintf(key1, sizeof(key1), "hint/%s/%s/%s/e%08x", eidpeer_str, hint->data, req->dcontext, unaffected ? 0 : req->crc32); 00835 snprintf(key2, sizeof(key2), "hint/%s/%s/%s/r%s", eidpeer_str, hint->data, req->dcontext, eidroot_str); 00836 00837 time(&timeout); 00838 timeout += expiration; 00839 snprintf(data, sizeof(data), "%ld|", (long)(timeout)); 00840 00841 ast_db_put("dundi/cache", key1, data); 00842 ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key1); 00843 ast_db_put("dundi/cache", key2, data); 00844 ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key2); 00845 return 0; 00846 }
static void cancel_request | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3391 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().
03392 { 03393 struct dundi_transaction *trans; 03394 03395 AST_LIST_LOCK(&peers); 03396 while ((trans = AST_LIST_REMOVE_HEAD(&dr->trans, parentlist))) { 03397 /* Orphan transaction from request */ 03398 trans->parent = NULL; 03399 /* Send final cancel */ 03400 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 03401 } 03402 AST_LIST_UNLOCK(&peers); 03403 }
static int check_key | ( | struct dundi_peer * | peer, | |
unsigned char * | newkey, | |||
unsigned char * | newsig, | |||
uint32_t | keycrc32 | |||
) | [static] |
Definition at line 1452 of file pbx_dundi.c.
References aes_decrypt_key128(), aes_encrypt_key128(), ast_check_signature_bin, 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_DEBUG, LOG_NOTICE, option_debug, dundi_peer::outkey, dundi_peer::rxenckey, dundi_peer::them_dcx, dundi_peer::them_ecx, and dundi_peer::them_keycrc32.
01453 { 01454 unsigned char dst[128]; 01455 int res; 01456 struct ast_key *key, *skey; 01457 char eid_str[20]; 01458 if (option_debug) 01459 ast_log(LOG_DEBUG, "Expected '%08x' got '%08x'\n", peer->them_keycrc32, keycrc32); 01460 if (peer->them_keycrc32 && (peer->them_keycrc32 == keycrc32)) { 01461 /* A match */ 01462 return 1; 01463 } else if (!newkey || !newsig) 01464 return 0; 01465 if (!memcmp(peer->rxenckey, newkey, 128) && 01466 !memcmp(peer->rxenckey + 128, newsig, 128)) { 01467 /* By definition, a match */ 01468 return 1; 01469 } 01470 /* Decrypt key */ 01471 key = ast_key_get(peer->outkey, AST_KEY_PRIVATE); 01472 if (!key) { 01473 ast_log(LOG_NOTICE, "Unable to find key '%s' to decode shared key from '%s'\n", 01474 peer->outkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01475 return -1; 01476 } 01477 01478 skey = ast_key_get(peer->inkey, AST_KEY_PUBLIC); 01479 if (!skey) { 01480 ast_log(LOG_NOTICE, "Unable to find key '%s' to verify shared key from '%s'\n", 01481 peer->inkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01482 return -1; 01483 } 01484 01485 /* First check signature */ 01486 res = ast_check_signature_bin(skey, (char *)newkey, 128, newsig); 01487 if (res) 01488 return 0; 01489 01490 res = ast_decrypt_bin(dst, newkey, sizeof(dst), key); 01491 if (res != 16) { 01492 if (res >= 0) 01493 ast_log(LOG_NOTICE, "Weird, key decoded to the wrong size (%d)\n", res); 01494 return 0; 01495 } 01496 /* Decrypted, passes signature */ 01497 ast_log(LOG_DEBUG, "Wow, new key combo passed signature and decrypt!\n"); 01498 memcpy(peer->rxenckey, newkey, 128); 01499 memcpy(peer->rxenckey + 128, newsig, 128); 01500 peer->them_keycrc32 = crc32(0L, peer->rxenckey, 128); 01501 aes_decrypt_key128(dst, &peer->them_dcx); 01502 aes_encrypt_key128(dst, &peer->them_ecx); 01503 return 1; 01504 }
static void check_password | ( | void | ) | [static] |
Definition at line 2133 of file pbx_dundi.c.
References ast_copy_string(), build_secret(), and save_secret().
Referenced by network_thread().
02134 { 02135 char oldsecret[80]; 02136 time_t now; 02137 02138 time(&now); 02139 #if 0 02140 printf("%ld/%ld\n", now, rotatetime); 02141 #endif 02142 if ((now - rotatetime) >= 0) { 02143 /* Time to rotate keys */ 02144 ast_copy_string(oldsecret, cursecret, sizeof(oldsecret)); 02145 build_secret(cursecret, sizeof(cursecret)); 02146 save_secret(cursecret, oldsecret); 02147 } 02148 }
static int check_request | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3512 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().
03513 { 03514 struct dundi_request *cur; 03515 03516 AST_LIST_LOCK(&peers); 03517 AST_LIST_TRAVERSE(&requests, cur, list) { 03518 if (cur == dr) 03519 break; 03520 } 03521 AST_LIST_UNLOCK(&peers); 03522 03523 return cur ? 1 : 0; 03524 }
static char* complete_peer_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 2361 of file pbx_dundi.c.
References complete_peer_helper().
02362 { 02363 return complete_peer_helper(line, word, pos, state, 3); 02364 }
static char* complete_peer_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 2339 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 complete_peer_4().
02340 { 02341 int which=0, len; 02342 char *ret = NULL; 02343 struct dundi_peer *p; 02344 char eid_str[20]; 02345 02346 if (pos != rpos) 02347 return NULL; 02348 AST_LIST_LOCK(&peers); 02349 len = strlen(word); 02350 AST_LIST_TRAVERSE(&peers, p, list) { 02351 const char *s = dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid); 02352 if (!strncasecmp(word, s, len) && ++which > state) { 02353 ret = ast_strdup(s); 02354 break; 02355 } 02356 } 02357 AST_LIST_UNLOCK(&peers); 02358 return ret; 02359 }
static struct dundi_transaction * create_transaction | ( | struct dundi_peer * | p | ) | [static] |
Definition at line 2870 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().
02871 { 02872 struct dundi_transaction *trans; 02873 int tid; 02874 02875 /* Don't allow creation of transactions to non-registered peers */ 02876 if (p && !p->addr.sin_addr.s_addr) 02877 return NULL; 02878 tid = get_trans_id(); 02879 if (tid < 1) 02880 return NULL; 02881 trans = ast_calloc(1, sizeof(*trans)); 02882 if (trans) { 02883 if (global_storehistory) { 02884 trans->start = ast_tvnow(); 02885 ast_set_flag(trans, FLAG_STOREHIST); 02886 } 02887 trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; 02888 trans->autokillid = -1; 02889 if (p) { 02890 apply_peer(trans, p); 02891 if (!p->sentfullkey) 02892 ast_set_flag(trans, FLAG_SENDFULLKEY); 02893 } 02894 trans->strans = tid; 02895 AST_LIST_INSERT_HEAD(&alltrans, trans, all); 02896 } 02897 return trans; 02898 }
static int decrypt_memcpy | ( | unsigned char * | dst, | |
unsigned char * | src, | |||
int | len, | |||
unsigned char * | iv, | |||
aes_decrypt_ctx * | dcx | |||
) | [static] |
Definition at line 1344 of file pbx_dundi.c.
References aes_decrypt().
Referenced by dundi_decrypt().
01345 { 01346 unsigned char lastblock[16]; 01347 int x; 01348 memcpy(lastblock, iv, sizeof(lastblock)); 01349 while(len > 0) { 01350 aes_decrypt(src, dst, dcx); 01351 for (x=0;x<16;x++) 01352 dst[x] ^= lastblock[x]; 01353 memcpy(lastblock, src, sizeof(lastblock)); 01354 dst += 16; 01355 src += 16; 01356 len -= 16; 01357 } 01358 return 0; 01359 }
static void deep_copy_peer | ( | struct dundi_peer * | peer_dst, | |
const struct dundi_peer * | peer_src | |||
) | [static] |
Definition at line 1506 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().
01507 { 01508 struct permission *cur, *perm; 01509 01510 memcpy(peer_dst, peer_src, sizeof(*peer_dst)); 01511 01512 memset(&peer_dst->permit, 0, sizeof(peer_dst->permit)); 01513 memset(&peer_dst->include, 0, sizeof(peer_dst->permit)); 01514 01515 AST_LIST_TRAVERSE(&peer_src->permit, cur, list) { 01516 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1))) 01517 continue; 01518 01519 perm->allow = cur->allow; 01520 strcpy(perm->name, cur->name); 01521 01522 AST_LIST_INSERT_HEAD(&peer_dst->permit, perm, list); 01523 } 01524 01525 AST_LIST_TRAVERSE(&peer_src->include, cur, list) { 01526 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1))) 01527 continue; 01528 01529 perm->allow = cur->allow; 01530 strcpy(perm->name, cur->name); 01531 01532 AST_LIST_INSERT_HEAD(&peer_dst->include, perm, list); 01533 } 01534 }
static void destroy_map | ( | struct dundi_mapping * | map | ) | [static] |
static void destroy_packet | ( | struct dundi_packet * | pack, | |
int | needfree | |||
) | [static] |
Definition at line 2916 of file pbx_dundi.c.
References AST_LIST_REMOVE, AST_SCHED_DEL, free, dundi_transaction::packets, dundi_packet::parent, dundi_packet::retransid, and sched.
Referenced by ack_trans().
02917 { 02918 if (pack->parent) 02919 AST_LIST_REMOVE(&pack->parent->packets, pack, list); 02920 AST_SCHED_DEL(sched, pack->retransid); 02921 if (needfree) 02922 free(pack); 02923 }
static void destroy_packets | ( | struct packetlist * | p | ) | [static] |
Definition at line 1965 of file pbx_dundi.c.
References AST_LIST_REMOVE_HEAD, AST_SCHED_DEL, free, dundi_packet::list, dundi_packet::retransid, and sched.
Referenced by ack_trans(), and handle_frame().
01966 { 01967 struct dundi_packet *pack; 01968 01969 while ((pack = AST_LIST_REMOVE_HEAD(p, list))) { 01970 AST_SCHED_DEL(sched, pack->retransid); 01971 free(pack); 01972 } 01973 }
static void destroy_peer | ( | struct dundi_peer * | peer | ) | [static] |
Definition at line 3946 of file pbx_dundi.c.
References AST_SCHED_DEL, destroy_permissions(), destroy_trans(), free, dundi_peer::include, dundi_peer::permit, dundi_peer::qualifyid, dundi_peer::registerid, dundi_peer::regtrans, and sched.
Referenced by prune_peers().
03947 { 03948 AST_SCHED_DEL(sched, peer->registerid); 03949 if (peer->regtrans) 03950 destroy_trans(peer->regtrans, 0); 03951 AST_SCHED_DEL(sched, peer->qualifyid); 03952 destroy_permissions(&peer->permit); 03953 destroy_permissions(&peer->include); 03954 free(peer); 03955 }
static void destroy_permissions | ( | struct permissionlist * | permlist | ) | [static] |
Definition at line 3938 of file pbx_dundi.c.
References AST_LIST_REMOVE_HEAD, free, and permission::list.
Referenced by build_peer(), and destroy_peer().
03939 { 03940 struct permission *perm; 03941 03942 while ((perm = AST_LIST_REMOVE_HEAD(permlist, list))) 03943 free(perm); 03944 }
static void destroy_trans | ( | struct dundi_transaction * | trans, | |
int | fromtimeout | |||
) | [static] |
Definition at line 2925 of file pbx_dundi.c.
References 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, free, 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().
02926 { 02927 struct dundi_peer *peer; 02928 int ms; 02929 int x; 02930 int cnt; 02931 char eid_str[20]; 02932 if (ast_test_flag(trans, FLAG_ISREG | FLAG_ISQUAL | FLAG_STOREHIST)) { 02933 AST_LIST_TRAVERSE(&peers, peer, list) { 02934 if (peer->regtrans == trans) 02935 peer->regtrans = NULL; 02936 if (peer->qualtrans == trans) { 02937 if (fromtimeout) { 02938 if (peer->lastms > -1) 02939 ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02940 peer->lastms = -1; 02941 } else { 02942 ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx); 02943 if (ms < 1) 02944 ms = 1; 02945 if (ms < peer->maxms) { 02946 if ((peer->lastms >= peer->maxms) || (peer->lastms < 0)) 02947 ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02948 } else if (peer->lastms < peer->maxms) { 02949 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); 02950 } 02951 peer->lastms = ms; 02952 } 02953 peer->qualtrans = NULL; 02954 } 02955 if (ast_test_flag(trans, FLAG_STOREHIST)) { 02956 if (trans->parent && !ast_strlen_zero(trans->parent->number)) { 02957 if (!dundi_eid_cmp(&trans->them_eid, &peer->eid)) { 02958 peer->avgms = 0; 02959 cnt = 0; 02960 if (peer->lookups[DUNDI_TIMING_HISTORY-1]) 02961 free(peer->lookups[DUNDI_TIMING_HISTORY-1]); 02962 for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) { 02963 peer->lookuptimes[x] = peer->lookuptimes[x-1]; 02964 peer->lookups[x] = peer->lookups[x-1]; 02965 if (peer->lookups[x]) { 02966 peer->avgms += peer->lookuptimes[x]; 02967 cnt++; 02968 } 02969 } 02970 peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start); 02971 peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2); 02972 if (peer->lookups[0]) { 02973 sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext); 02974 peer->avgms += peer->lookuptimes[0]; 02975 cnt++; 02976 } 02977 if (cnt) 02978 peer->avgms /= cnt; 02979 } 02980 } 02981 } 02982 } 02983 } 02984 if (trans->parent) { 02985 /* Unlink from parent if appropriate */ 02986 AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist); 02987 if (AST_LIST_EMPTY(&trans->parent->trans)) { 02988 /* Wake up sleeper */ 02989 if (trans->parent->pfds[1] > -1) { 02990 if (write(trans->parent->pfds[1], "killa!", 6) < 0) { 02991 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 02992 } 02993 } 02994 } 02995 } 02996 /* Unlink from all trans */ 02997 AST_LIST_REMOVE(&alltrans, trans, all); 02998 destroy_packets(&trans->packets); 02999 destroy_packets(&trans->lasttrans); 03000 AST_SCHED_DEL(sched, trans->autokillid); 03001 if (trans->thread) { 03002 /* If used by a thread, mark as dead and be done */ 03003 ast_set_flag(trans, FLAG_DEAD); 03004 } else 03005 free(trans); 03006 }
static int discover_transactions | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3247 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().
03248 { 03249 struct dundi_transaction *trans; 03250 AST_LIST_LOCK(&peers); 03251 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03252 dundi_discover(trans); 03253 } 03254 AST_LIST_UNLOCK(&peers); 03255 return 0; 03256 }
static int do_autokill | ( | const void * | data | ) | [static] |
Definition at line 3102 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().
03103 { 03104 struct dundi_transaction *trans = (struct dundi_transaction *)data; 03105 char eid_str[20]; 03106 ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n", 03107 dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid)); 03108 trans->autokillid = -1; 03109 destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */ 03110 return 0; 03111 }
static int do_qualify | ( | const void * | data | ) | [static] |
Definition at line 4103 of file pbx_dundi.c.
References qualify_peer(), and dundi_peer::qualifyid.
Referenced by qualify_peer().
04104 { 04105 struct dundi_peer *peer = (struct dundi_peer *)data; 04106 peer->qualifyid = -1; 04107 qualify_peer(peer, 0); 04108 return 0; 04109 }
static int do_register | ( | const void * | data | ) | [static] |
Definition at line 4077 of file pbx_dundi.c.
References 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_DEBUG, LOG_NOTICE, dundi_peer::registerid, dundi_peer::regtrans, sched, dundi_transaction::us_eid, and dundi_peer::us_eid.
04078 { 04079 struct dundi_ie_data ied; 04080 struct dundi_peer *peer = (struct dundi_peer *)data; 04081 char eid_str[20]; 04082 char eid_str2[20]; 04083 ast_log(LOG_DEBUG, "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)); 04084 peer->registerid = ast_sched_add(sched, default_expiration * 1000, do_register, data); 04085 /* Destroy old transaction if there is one */ 04086 if (peer->regtrans) 04087 destroy_trans(peer->regtrans, 0); 04088 peer->regtrans = create_transaction(peer); 04089 if (peer->regtrans) { 04090 ast_set_flag(peer->regtrans, FLAG_ISREG); 04091 memset(&ied, 0, sizeof(ied)); 04092 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 04093 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &peer->regtrans->us_eid); 04094 dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, default_expiration); 04095 dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied); 04096 04097 } else 04098 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)); 04099 04100 return 0; 04101 }
static int do_register_expire | ( | const void * | data | ) | [static] |
Definition at line 1278 of file pbx_dundi.c.
References dundi_peer::addr, ast_log(), dundi_eid_to_str(), dundi_peer::eid, dundi_peer::lastms, LOG_DEBUG, and dundi_peer::registerexpire.
Referenced by handle_command_response(), and populate_addr().
01279 { 01280 struct dundi_peer *peer = (struct dundi_peer *)data; 01281 char eid_str[20]; 01282 ast_log(LOG_DEBUG, "Register expired for '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01283 peer->registerexpire = -1; 01284 peer->lastms = 0; 01285 memset(&peer->addr, 0, sizeof(peer->addr)); 01286 return 0; 01287 }
static int dundi_ack | ( | struct dundi_transaction * | trans, | |
int | final | |||
) | [static] |
Definition at line 376 of file pbx_dundi.c.
References DUNDI_COMMAND_ACK, and dundi_send().
Referenced by handle_frame().
00377 { 00378 return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL); 00379 }
static int dundi_answer_entity | ( | struct dundi_transaction * | trans, | |
struct dundi_ies * | ies, | |||
char * | ccontext | |||
) | [static] |
Definition at line 753 of file pbx_dundi.c.
References ast_calloc, ast_copy_string(), ast_log(), ast_pthread_create, 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, free, ies, LOG_DEBUG, LOG_WARNING, dundi_query_state::reqeid, s, dundi_transaction::thread, dundi_query_state::trans, and dundi_query_state::ttl.
Referenced by handle_command_response().
00754 { 00755 struct dundi_query_state *st; 00756 int totallen; 00757 int x; 00758 int skipfirst=0; 00759 struct dundi_ie_data ied; 00760 char eid_str[20]; 00761 char *s; 00762 pthread_t lookupthread; 00763 pthread_attr_t attr; 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_log(LOG_DEBUG, "Answering EID query for '%s@%s'!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), ies->reqeid), ies->called_context); 00789 pthread_attr_init(&attr); 00790 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00791 trans->thread = 1; 00792 if (ast_pthread_create(&lookupthread, &attr, dundi_query_thread, st)) { 00793 trans->thread = 0; 00794 ast_log(LOG_WARNING, "Unable to create thread!\n"); 00795 free(st); 00796 memset(&ied, 0, sizeof(ied)); 00797 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); 00798 dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); 00799 pthread_attr_destroy(&attr); 00800 return -1; 00801 } 00802 pthread_attr_destroy(&attr); 00803 } else { 00804 ast_log(LOG_WARNING, "Out of memory!\n"); 00805 memset(&ied, 0, sizeof(ied)); 00806 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); 00807 dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); 00808 return -1; 00809 } 00810 return 0; 00811 }
static int dundi_answer_query | ( | struct dundi_transaction * | trans, | |
struct dundi_ies * | ies, | |||
char * | ccontext | |||
) | [static] |
Definition at line 1041 of file pbx_dundi.c.
References ast_calloc, ast_copy_string(), AST_LIST_TRAVERSE, ast_log(), ast_pthread_create, 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, free, ies, dundi_mapping::list, permission::list, LOG_DEBUG, 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().
01042 { 01043 struct dundi_query_state *st; 01044 int totallen; 01045 int x; 01046 struct dundi_ie_data ied; 01047 char *s; 01048 struct dundi_mapping *cur; 01049 int mapcount = 0; 01050 int skipfirst = 0; 01051 01052 pthread_t lookupthread; 01053 pthread_attr_t attr; 01054 totallen = sizeof(struct dundi_query_state); 01055 /* Count matching map entries */ 01056 AST_LIST_TRAVERSE(&mappings, cur, list) { 01057 if (!strcasecmp(cur->dcontext, ccontext)) 01058 mapcount++; 01059 } 01060 /* If no maps, return -1 immediately */ 01061 if (!mapcount) 01062 return -1; 01063 01064 if (ies->eidcount > 1) { 01065 /* Since it is a requirement that the first EID is the authenticating host 01066 and the last EID is the root, it is permissible that the first and last EID 01067 could be the same. In that case, we should go ahead copy only the "root" section 01068 since we will not need it for authentication. */ 01069 if (!dundi_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1])) 01070 skipfirst = 1; 01071 } 01072 01073 totallen += mapcount * sizeof(struct dundi_mapping); 01074 totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid); 01075 st = ast_calloc(1, totallen); 01076 if (st) { 01077 ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context)); 01078 ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number)); 01079 st->trans = trans; 01080 st->ttl = ies->ttl - 1; 01081 st->nocache = ies->cbypass; 01082 if (st->ttl < 0) 01083 st->ttl = 0; 01084 s = st->fluffy; 01085 for (x=skipfirst;ies->eids[x];x++) { 01086 st->eids[x-skipfirst] = (dundi_eid *)s; 01087 *st->eids[x-skipfirst] = *ies->eids[x]; 01088 st->directs[x-skipfirst] = ies->eid_direct[x]; 01089 s += sizeof(dundi_eid); 01090 } 01091 /* Append mappings */ 01092 x = 0; 01093 st->maps = (struct dundi_mapping *)s; 01094 AST_LIST_TRAVERSE(&mappings, cur, list) { 01095 if (!strcasecmp(cur->dcontext, ccontext)) { 01096 if (x < mapcount) { 01097 st->maps[x] = *cur; 01098 st->maps[x].list.next = NULL; 01099 x++; 01100 } 01101 } 01102 } 01103 st->nummaps = mapcount; 01104 ast_log(LOG_DEBUG, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context); 01105 pthread_attr_init(&attr); 01106 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 01107 trans->thread = 1; 01108 if (ast_pthread_create(&lookupthread, &attr, dundi_lookup_thread, st)) { 01109 trans->thread = 0; 01110 ast_log(LOG_WARNING, "Unable to create thread!\n"); 01111 free(st); 01112 memset(&ied, 0, sizeof(ied)); 01113 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); 01114 dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); 01115 pthread_attr_destroy(&attr); 01116 return -1; 01117 } 01118 pthread_attr_destroy(&attr); 01119 } else { 01120 ast_log(LOG_WARNING, "Out of memory!\n"); 01121 memset(&ied, 0, sizeof(ied)); 01122 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); 01123 dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); 01124 return -1; 01125 } 01126 return 0; 01127 }
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 4350 of file pbx_dundi.c.
References DUNDI_FLAG_CANMATCH, and dundi_helper().
04351 { 04352 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH); 04353 }
static void dundi_debug_output | ( | const char * | data | ) | [static] |
Definition at line 280 of file pbx_dundi.c.
References ast_verbose().
Referenced by load_module().
00281 { 00282 if (dundidebug) 00283 ast_verbose("%s", data); 00284 }
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 1361 of file pbx_dundi.c.
References ast_log(), dundi_transaction::dcx, decrypt_memcpy(), dundi_encblock::encdata, dundi_encblock::iv, and LOG_DEBUG.
01362 { 01363 int space = *dstlen; 01364 unsigned long bytes; 01365 struct dundi_hdr *h; 01366 unsigned char *decrypt_space; 01367 decrypt_space = alloca(srclen); 01368 if (!decrypt_space) 01369 return NULL; 01370 decrypt_memcpy(decrypt_space, src->encdata, srclen, src->iv, &trans->dcx); 01371 /* Setup header */ 01372 h = (struct dundi_hdr *)dst; 01373 *h = *ohdr; 01374 bytes = space - 6; 01375 if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) { 01376 ast_log(LOG_DEBUG, "Ouch, uncompress failed :(\n"); 01377 return NULL; 01378 } 01379 /* Update length */ 01380 *dstlen = bytes + 6; 01381 /* Return new header */ 01382 return h; 01383 }
static int dundi_discover | ( | struct dundi_transaction * | trans | ) | [static] |
Definition at line 3135 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().
03136 { 03137 struct dundi_ie_data ied; 03138 int x; 03139 if (!trans->parent) { 03140 ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n"); 03141 return -1; 03142 } 03143 memset(&ied, 0, sizeof(ied)); 03144 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 03145 if (!dundi_eid_zero(&trans->us_eid)) 03146 dundi_ie_append_eid(&ied, DUNDI_IE_EID_DIRECT, &trans->us_eid); 03147 for (x=0;x<trans->eidcount;x++) 03148 dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid); 03149 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number); 03150 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); 03151 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); 03152 if (trans->parent->cbypass) 03153 dundi_ie_append(&ied, DUNDI_IE_CACHEBYPASS); 03154 if (trans->autokilltimeout) 03155 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); 03156 return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied); 03157 }
static int dundi_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2256 of file pbx_dundi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02257 { 02258 if (argc != 2) 02259 return RESULT_SHOWUSAGE; 02260 dundidebug = 1; 02261 ast_cli(fd, "DUNDi Debugging Enabled\n"); 02262 return RESULT_SUCCESS; 02263 }
static int dundi_do_lookup | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2383 of file pbx_dundi.c.
References ast_cli(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), dr, dundi_flags2str(), dundi_lookup(), MAX_RESULTS, RESULT_SHOWUSAGE, RESULT_SUCCESS, and sort_results().
02384 { 02385 int res; 02386 char tmp[256]; 02387 char fs[80] = ""; 02388 char *context; 02389 int x; 02390 int bypass = 0; 02391 struct dundi_result dr[MAX_RESULTS]; 02392 struct timeval start; 02393 if ((argc < 3) || (argc > 4)) 02394 return RESULT_SHOWUSAGE; 02395 if (argc > 3) { 02396 if (!strcasecmp(argv[3], "bypass")) 02397 bypass=1; 02398 else 02399 return RESULT_SHOWUSAGE; 02400 } 02401 ast_copy_string(tmp, argv[2], sizeof(tmp)); 02402 context = strchr(tmp, '@'); 02403 if (context) { 02404 *context = '\0'; 02405 context++; 02406 } 02407 start = ast_tvnow(); 02408 res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass); 02409 02410 if (res < 0) 02411 ast_cli(fd, "DUNDi lookup returned error.\n"); 02412 else if (!res) 02413 ast_cli(fd, "DUNDi lookup returned no results.\n"); 02414 else 02415 sort_results(dr, res); 02416 for (x=0;x<res;x++) { 02417 ast_cli(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)); 02418 ast_cli(fd, " from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration); 02419 } 02420 ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start)); 02421 return RESULT_SUCCESS; 02422 }
static int dundi_do_precache | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2424 of file pbx_dundi.c.
References ast_cli(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), dundi_precache(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02425 { 02426 int res; 02427 char tmp[256]; 02428 char *context; 02429 struct timeval start; 02430 if ((argc < 3) || (argc > 3)) 02431 return RESULT_SHOWUSAGE; 02432 ast_copy_string(tmp, argv[2], sizeof(tmp)); 02433 context = strchr(tmp, '@'); 02434 if (context) { 02435 *context = '\0'; 02436 context++; 02437 } 02438 start = ast_tvnow(); 02439 res = dundi_precache(context, tmp); 02440 02441 if (res < 0) 02442 ast_cli(fd, "DUNDi precache returned error.\n"); 02443 else if (!res) 02444 ast_cli(fd, "DUNDi precache returned no error.\n"); 02445 ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start)); 02446 return RESULT_SUCCESS; 02447 }
static int dundi_do_query | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2449 of file pbx_dundi.c.
References ast_cli(), ast_copy_string(), dundi_entity_info::country, dundi_query_eid(), dundi_str_to_eid(), dundi_entity_info::email, dundi_entity_info::ipaddr, dundi_entity_info::locality, dundi_entity_info::org, dundi_entity_info::orgunit, dundi_entity_info::phone, RESULT_SHOWUSAGE, RESULT_SUCCESS, and dundi_entity_info::stateprov.
02450 { 02451 int res; 02452 char tmp[256]; 02453 char *context; 02454 dundi_eid eid; 02455 struct dundi_entity_info dei; 02456 if ((argc < 3) || (argc > 3)) 02457 return RESULT_SHOWUSAGE; 02458 if (dundi_str_to_eid(&eid, argv[2])) { 02459 ast_cli(fd, "'%s' is not a valid EID!\n", argv[2]); 02460 return RESULT_SHOWUSAGE; 02461 } 02462 ast_copy_string(tmp, argv[2], sizeof(tmp)); 02463 context = strchr(tmp, '@'); 02464 if (context) { 02465 *context = '\0'; 02466 context++; 02467 } 02468 res = dundi_query_eid(&dei, context, eid); 02469 if (res < 0) 02470 ast_cli(fd, "DUNDi Query EID returned error.\n"); 02471 else if (!res) 02472 ast_cli(fd, "DUNDi Query EID returned no results.\n"); 02473 else { 02474 ast_cli(fd, "DUNDi Query EID succeeded:\n"); 02475 ast_cli(fd, "Department: %s\n", dei.orgunit); 02476 ast_cli(fd, "Organization: %s\n", dei.org); 02477 ast_cli(fd, "City/Locality: %s\n", dei.locality); 02478 ast_cli(fd, "State/Province: %s\n", dei.stateprov); 02479 ast_cli(fd, "Country: %s\n", dei.country); 02480 ast_cli(fd, "E-mail: %s\n", dei.email); 02481 ast_cli(fd, "Phone: %s\n", dei.phone); 02482 ast_cli(fd, "IP Address: %s\n", dei.ipaddr); 02483 } 02484 return RESULT_SUCCESS; 02485 }
static int dundi_do_store_history | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2265 of file pbx_dundi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02266 { 02267 if (argc != 3) 02268 return RESULT_SHOWUSAGE; 02269 global_storehistory = 1; 02270 ast_cli(fd, "DUNDi History Storage Enabled\n"); 02271 return RESULT_SUCCESS; 02272 }
static int dundi_encrypt | ( | struct dundi_transaction * | trans, | |
struct dundi_packet * | pack | |||
) | [static] |
Definition at line 1385 of file pbx_dundi.c.
References 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_DEBUG, 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().
01386 { 01387 unsigned char *compress_space; 01388 int len; 01389 int res; 01390 unsigned long bytes; 01391 struct dundi_ie_data ied; 01392 struct dundi_peer *peer; 01393 unsigned char iv[16]; 01394 len = pack->datalen + pack->datalen / 100 + 42; 01395 compress_space = alloca(len); 01396 if (compress_space) { 01397 memset(compress_space, 0, len); 01398 /* We care about everthing save the first 6 bytes of header */ 01399 bytes = len; 01400 res = compress(compress_space, &bytes, pack->data + 6, pack->datalen - 6); 01401 if (res != Z_OK) { 01402 ast_log(LOG_DEBUG, "Ouch, compression failed!\n"); 01403 return -1; 01404 } 01405 memset(&ied, 0, sizeof(ied)); 01406 /* Say who we are */ 01407 if (!pack->h->iseqno && !pack->h->oseqno) { 01408 /* Need the key in the first copy */ 01409 if (!(peer = find_peer(&trans->them_eid))) 01410 return -1; 01411 if (update_key(peer)) 01412 return -1; 01413 if (!peer->sentfullkey) 01414 ast_set_flag(trans, FLAG_SENDFULLKEY); 01415 /* Append key data */ 01416 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); 01417 if (ast_test_flag(trans, FLAG_SENDFULLKEY)) { 01418 dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128); 01419 dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128); 01420 } else { 01421 dundi_ie_append_int(&ied, DUNDI_IE_KEYCRC32, peer->us_keycrc32); 01422 } 01423 /* Setup contexts */ 01424 trans->ecx = peer->us_ecx; 01425 trans->dcx = peer->us_dcx; 01426 01427 /* We've sent the full key */ 01428 peer->sentfullkey = 1; 01429 } 01430 /* Build initialization vector */ 01431 build_iv(iv); 01432 /* Add the field, rounded up to 16 bytes */ 01433 dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, iv, NULL, ((bytes + 15) / 16) * 16); 01434 /* Copy the data */ 01435 if ((ied.pos + bytes) >= sizeof(ied.buf)) { 01436 ast_log(LOG_NOTICE, "Final packet too large!\n"); 01437 return -1; 01438 } 01439 encrypt_memcpy(ied.buf + ied.pos, compress_space, bytes, iv, &trans->ecx); 01440 ied.pos += ((bytes + 15) / 16) * 16; 01441 /* Reconstruct header */ 01442 pack->datalen = sizeof(struct dundi_hdr); 01443 pack->h->cmdresp = DUNDI_COMMAND_ENCRYPT; 01444 pack->h->cmdflags = 0; 01445 memcpy(pack->h->ies, ied.buf, ied.pos); 01446 pack->datalen += ied.pos; 01447 return 0; 01448 } 01449 return -1; 01450 }
static void dundi_error_output | ( | const char * | data | ) | [static] |
Definition at line 286 of file pbx_dundi.c.
References ast_log(), and LOG_WARNING.
Referenced by load_module().
00287 { 00288 ast_log(LOG_WARNING, "%s", data); 00289 }
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 4355 of file pbx_dundi.c.
References ast_log(), ast_strlen_zero(), ast_test_flag, DUNDI_FLAG_EXISTS, dundi_lookup(), ast_channel::exten, LOG_NOTICE, ast_channel::macroexten, MAX_RESULTS, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), and sort_results().
04356 { 04357 struct dundi_result results[MAX_RESULTS]; 04358 int res; 04359 int x=0; 04360 char req[1024]; 04361 struct ast_app *dial; 04362 04363 if (!strncasecmp(context, "macro-", 6)) { 04364 if (!chan) { 04365 ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n"); 04366 return -1; 04367 } 04368 /* If done as a macro, use macro extension */ 04369 if (!strcasecmp(exten, "s")) { 04370 exten = pbx_builtin_getvar_helper(chan, "ARG1"); 04371 if (ast_strlen_zero(exten)) 04372 exten = chan->macroexten; 04373 if (ast_strlen_zero(exten)) 04374 exten = chan->exten; 04375 if (ast_strlen_zero(exten)) { 04376 ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n"); 04377 return -1; 04378 } 04379 } 04380 if (ast_strlen_zero(data)) 04381 data = "e164"; 04382 } else { 04383 if (ast_strlen_zero(data)) 04384 data = context; 04385 } 04386 res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0); 04387 if (res > 0) { 04388 sort_results(results, res); 04389 for (x=0;x<res;x++) { 04390 if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) { 04391 if (!--priority) 04392 break; 04393 } 04394 } 04395 } 04396 if (x < res) { 04397 /* Got a hit! */ 04398 snprintf(req, sizeof(req), "%s/%s", results[x].tech, results[x].dest); 04399 dial = pbx_findapp("Dial"); 04400 if (dial) 04401 res = pbx_exec(chan, dial, req); 04402 } else 04403 res = -1; 04404 return res; 04405 }
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 4345 of file pbx_dundi.c.
References DUNDI_FLAG_EXISTS, and dundi_helper().
04346 { 04347 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS); 04348 }
static int dundi_flush | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2274 of file pbx_dundi.c.
References ast_cli(), ast_db_deltree(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_peer::avgms, DUNDI_TIMING_HISTORY, free, dundi_peer::list, dundi_peer::lookups, dundi_peer::lookuptimes, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02275 { 02276 int stats = 0; 02277 if ((argc < 2) || (argc > 3)) 02278 return RESULT_SHOWUSAGE; 02279 if (argc > 2) { 02280 if (!strcasecmp(argv[2], "stats")) 02281 stats = 1; 02282 else 02283 return RESULT_SHOWUSAGE; 02284 } 02285 if (stats) { 02286 /* Flush statistics */ 02287 struct dundi_peer *p; 02288 int x; 02289 AST_LIST_LOCK(&peers); 02290 AST_LIST_TRAVERSE(&peers, p, list) { 02291 for (x = 0;x < DUNDI_TIMING_HISTORY; x++) { 02292 if (p->lookups[x]) 02293 free(p->lookups[x]); 02294 p->lookups[x] = NULL; 02295 p->lookuptimes[x] = 0; 02296 } 02297 p->avgms = 0; 02298 } 02299 AST_LIST_UNLOCK(&peers); 02300 } else { 02301 ast_db_deltree("dundi/cache", NULL); 02302 ast_cli(fd, "DUNDi Cache Flushed\n"); 02303 } 02304 return RESULT_SUCCESS; 02305 }
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 4306 of file pbx_dundi.c.
References ast_log(), ast_strlen_zero(), ast_test_flag, dundi_lookup(), ast_channel::exten, LOG_NOTICE, ast_channel::macroexten, MAX_RESULTS, and pbx_builtin_getvar_helper().
Referenced by dundi_canmatch(), dundi_exists(), and dundi_matchmore().
04307 { 04308 struct dundi_result results[MAX_RESULTS]; 04309 int res; 04310 int x; 04311 int found = 0; 04312 if (!strncasecmp(context, "macro-", 6)) { 04313 if (!chan) { 04314 ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n"); 04315 return -1; 04316 } 04317 /* If done as a macro, use macro extension */ 04318 if (!strcasecmp(exten, "s")) { 04319 exten = pbx_builtin_getvar_helper(chan, "ARG1"); 04320 if (ast_strlen_zero(exten)) 04321 exten = chan->macroexten; 04322 if (ast_strlen_zero(exten)) 04323 exten = chan->exten; 04324 if (ast_strlen_zero(exten)) { 04325 ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n"); 04326 return -1; 04327 } 04328 } 04329 if (ast_strlen_zero(data)) 04330 data = "e164"; 04331 } else { 04332 if (ast_strlen_zero(data)) 04333 data = context; 04334 } 04335 res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0); 04336 for (x=0;x<res;x++) { 04337 if (ast_test_flag(results + x, flag)) 04338 found++; 04339 } 04340 if (found >= priority) 04341 return 1; 04342 return 0; 04343 }
static void dundi_ie_append_eid_appropriately | ( | struct dundi_ie_data * | ied, | |
char * | context, | |||
dundi_eid * | eid, | |||
dundi_eid * | us | |||
) | [static] |
Definition at line 3113 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().
03114 { 03115 struct dundi_peer *p; 03116 if (!dundi_eid_cmp(eid, us)) { 03117 dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid); 03118 return; 03119 } 03120 AST_LIST_LOCK(&peers); 03121 AST_LIST_TRAVERSE(&peers, p, list) { 03122 if (!dundi_eid_cmp(&p->eid, eid)) { 03123 if (has_permission(&p->include, context)) 03124 dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid); 03125 else 03126 dundi_ie_append_eid(ied, DUNDI_IE_EID, eid); 03127 break; 03128 } 03129 } 03130 if (!p) 03131 dundi_ie_append_eid(ied, DUNDI_IE_EID, eid); 03132 AST_LIST_UNLOCK(&peers); 03133 }
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 (or e164 if unspecified) using the given callerid (if specified) and return up to maxret results in the array specified. returns the number of results found or -1 on a hangup of teh channel.
Definition at line 3643 of file pbx_dundi.c.
References DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, and dundi_lookup_internal().
Referenced by dundi_do_lookup(), dundi_exec(), dundi_helper(), and dundifunc_read().
03644 { 03645 struct dundi_hint_metadata hmd; 03646 dundi_eid *avoid[1] = { NULL, }; 03647 int direct[1] = { 0, }; 03648 int expiration = dundi_cache_time; 03649 memset(&hmd, 0, sizeof(hmd)); 03650 hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; 03651 return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct); 03652 }
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 3541 of file pbx_dundi.c.
References ast_channel::_softhangup, abort_request(), ast_copy_string(), AST_LIST_EMPTY, ast_log(), ast_set_flag_nonstd, ast_tvdiff_ms(), ast_tvnow(), ast_waitfor_n_fd(), avoid_crc32(), build_transactions(), cancel_request(), check_request(), discover_transactions(), dr, dundi_eid_cmp(), dundi_eid_to_str(), DUNDI_FLUFF_TIME, DUNDI_HINT_TTL_EXPIRED, DUNDI_TTL_TIME, errno, LOG_DEBUG, 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().
03542 { 03543 int res; 03544 struct dundi_request dr, *pending; 03545 dundi_eid *rooteid=NULL; 03546 int x; 03547 int ttlms; 03548 int ms; 03549 int foundcache; 03550 int skipped=0; 03551 int order=0; 03552 char eid_str[20]; 03553 struct timeval start; 03554 03555 /* Don't do anthing for a hungup channel */ 03556 if (chan && chan->_softhangup) 03557 return 0; 03558 03559 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03560 03561 for (x=0;avoid[x];x++) 03562 rooteid = avoid[x]; 03563 /* Now perform real check */ 03564 memset(&dr, 0, sizeof(dr)); 03565 if (pipe(dr.pfds)) { 03566 ast_log(LOG_WARNING, "pipe failed: %s\n" , strerror(errno)); 03567 return -1; 03568 } 03569 dr.dr = result; 03570 dr.hmd = hmd; 03571 dr.maxcount = maxret; 03572 dr.expiration = *expiration; 03573 dr.cbypass = cbypass; 03574 dr.crc32 = avoid_crc32(avoid); 03575 ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext)); 03576 ast_copy_string(dr.number, number, sizeof(dr.number)); 03577 if (rooteid) 03578 dr.root_eid = *rooteid; 03579 res = register_request(&dr, &pending); 03580 if (res) { 03581 /* Already a request */ 03582 if (rooteid && !dundi_eid_cmp(&dr.root_eid, &pending->root_eid)) { 03583 /* This is on behalf of someone else. Go ahead and close this out since 03584 they'll get their answer anyway. */ 03585 ast_log(LOG_DEBUG, "Oooh, duplicate request for '%s@%s' for '%s'\n", 03586 dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid)); 03587 close(dr.pfds[0]); 03588 close(dr.pfds[1]); 03589 return -2; 03590 } else { 03591 /* Wait for the cache to populate */ 03592 ast_log(LOG_DEBUG, "Waiting for similar request for '%s@%s' for '%s'\n", 03593 dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid)); 03594 start = ast_tvnow(); 03595 while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) { 03596 /* XXX Would be nice to have a way to poll/select here XXX */ 03597 /* XXX this is a busy wait loop!!! */ 03598 usleep(1); 03599 } 03600 /* Continue on as normal, our cache should kick in */ 03601 } 03602 } 03603 /* Create transactions */ 03604 do { 03605 order = skipped; 03606 skipped = 0; 03607 foundcache = 0; 03608 build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct); 03609 } while (skipped && !foundcache && AST_LIST_EMPTY(&dr.trans)); 03610 /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't 03611 do this earlier because we didn't know if we were going to have transactions 03612 or not. */ 03613 if (!ttl) { 03614 ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED); 03615 abort_request(&dr); 03616 unregister_request(&dr); 03617 close(dr.pfds[0]); 03618 close(dr.pfds[1]); 03619 return 0; 03620 } 03621 03622 /* Optimize transactions */ 03623 optimize_transactions(&dr, order); 03624 /* Actually perform transactions */ 03625 discover_transactions(&dr); 03626 /* Wait for transaction to come back */ 03627 start = ast_tvnow(); 03628 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) { 03629 ms = 100; 03630 ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL); 03631 } 03632 if (chan && chan->_softhangup) 03633 ast_log(LOG_DEBUG, "Hrm, '%s' hungup before their query for %s@%s finished\n", chan->name, dr.number, dr.dcontext); 03634 cancel_request(&dr); 03635 unregister_request(&dr); 03636 res = dr.respcount; 03637 *expiration = dr.expiration; 03638 close(dr.pfds[0]); 03639 close(dr.pfds[1]); 03640 return res; 03641 }
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, 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 = map->weight; 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_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), 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, free, LOG_DEBUG, 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_log(LOG_DEBUG, "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_log(LOG_DEBUG, "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 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 4407 of file pbx_dundi.c.
References DUNDI_FLAG_MATCHMORE, and dundi_helper().
04408 { 04409 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE); 04410 }
static int dundi_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2307 of file pbx_dundi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02308 { 02309 if (argc != 3) 02310 return RESULT_SHOWUSAGE; 02311 dundidebug = 0; 02312 ast_cli(fd, "DUNDi Debugging Disabled\n"); 02313 return RESULT_SUCCESS; 02314 }
static int dundi_no_store_history | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2316 of file pbx_dundi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02317 { 02318 if (argc != 4) 02319 return RESULT_SHOWUSAGE; 02320 global_storehistory = 0; 02321 ast_cli(fd, "DUNDi History Storage Disabled\n"); 02322 return RESULT_SUCCESS; 02323 }
int dundi_precache | ( | const char * | context, | |
const char * | number | |||
) |
Pre-cache to push upstream peers.
Definition at line 3790 of file pbx_dundi.c.
References dundi_precache_internal().
Referenced by dundi_do_precache(), and process_precache().
03791 { 03792 dundi_eid *avoid[1] = { NULL, }; 03793 return dundi_precache_internal(context, number, dundi_ttl, avoid); 03794 }
static void dundi_precache_full | ( | void | ) | [static] |
Definition at line 3690 of file pbx_dundi.c.
References ast_get_context_name(), ast_get_extension_name(), AST_LIST_TRAVERSE, ast_lock_context(), ast_log(), 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().
03691 { 03692 struct dundi_mapping *cur; 03693 struct ast_context *con; 03694 struct ast_exten *e; 03695 03696 AST_LIST_TRAVERSE(&mappings, cur, list) { 03697 ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext); 03698 ast_rdlock_contexts(); 03699 con = ast_walk_contexts(NULL); 03700 while (con) { 03701 if (!strcasecmp(cur->lcontext, ast_get_context_name(con))) { 03702 /* Found the match, now queue them all up */ 03703 ast_lock_context(con); 03704 e = ast_walk_context_extensions(con, NULL); 03705 while (e) { 03706 reschedule_precache(ast_get_extension_name(e), cur->dcontext, 0); 03707 e = ast_walk_context_extensions(con, e); 03708 } 03709 ast_unlock_context(con); 03710 } 03711 con = ast_walk_contexts(con); 03712 } 03713 ast_unlock_contexts(); 03714 } 03715 }
static int dundi_precache_internal | ( | const char * | context, | |
const char * | number, | |||
int | ttl, | |||
dundi_eid * | avoids[] | |||
) | [static] |
Definition at line 3717 of file pbx_dundi.c.
References ast_copy_string(), 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_DEBUG, LOG_NOTICE, LOG_WARNING, MAX_RESULTS, optimize_transactions(), precache_transactions(), and reschedule_precache().
Referenced by dundi_precache(), and dundi_precache_thread().
03718 { 03719 struct dundi_request dr; 03720 struct dundi_hint_metadata hmd; 03721 struct dundi_result dr2[MAX_RESULTS]; 03722 struct timeval start; 03723 struct dundi_mapping *maps = NULL, *cur; 03724 int nummaps = 0; 03725 int foundanswers; 03726 int foundcache, skipped, ttlms, ms; 03727 if (!context) 03728 context = "e164"; 03729 ast_log(LOG_DEBUG, "Precache internal (%s@%s)!\n", number, context); 03730 03731 AST_LIST_LOCK(&peers); 03732 AST_LIST_TRAVERSE(&mappings, cur, list) { 03733 if (!strcasecmp(cur->dcontext, context)) 03734 nummaps++; 03735 } 03736 if (nummaps) { 03737 maps = alloca(nummaps * sizeof(*maps)); 03738 nummaps = 0; 03739 if (maps) { 03740 AST_LIST_TRAVERSE(&mappings, cur, list) { 03741 if (!strcasecmp(cur->dcontext, context)) 03742 maps[nummaps++] = *cur; 03743 } 03744 } 03745 } 03746 AST_LIST_UNLOCK(&peers); 03747 if (!nummaps || !maps) 03748 return -1; 03749 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03750 memset(&dr2, 0, sizeof(dr2)); 03751 memset(&dr, 0, sizeof(dr)); 03752 memset(&hmd, 0, sizeof(hmd)); 03753 dr.dr = dr2; 03754 ast_copy_string(dr.number, number, sizeof(dr.number)); 03755 ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext)); 03756 dr.maxcount = MAX_RESULTS; 03757 dr.expiration = dundi_cache_time; 03758 dr.hmd = &hmd; 03759 dr.pfds[0] = dr.pfds[1] = -1; 03760 if (pipe(dr.pfds) < 0) { 03761 ast_log(LOG_WARNING, "pipe() failed: %s\n", strerror(errno)); 03762 return -1; 03763 } 03764 build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL); 03765 optimize_transactions(&dr, 0); 03766 foundanswers = 0; 03767 precache_transactions(&dr, maps, nummaps, &dr.expiration, &foundanswers); 03768 if (foundanswers) { 03769 if (dr.expiration > 0) 03770 reschedule_precache(dr.number, dr.dcontext, dr.expiration); 03771 else 03772 ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext); 03773 } 03774 start = ast_tvnow(); 03775 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) { 03776 if (dr.pfds[0] > -1) { 03777 ms = 100; 03778 ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL); 03779 } else 03780 usleep(1); 03781 } 03782 cancel_request(&dr); 03783 if (dr.pfds[0] > -1) { 03784 close(dr.pfds[0]); 03785 close(dr.pfds[1]); 03786 } 03787 return 0; 03788 }
static void* dundi_precache_thread | ( | void * | data | ) | [static] |
Definition at line 666 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), 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, free, LOG_DEBUG, 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_log(LOG_DEBUG, "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_log(LOG_DEBUG, "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 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 889 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().
00890 { 00891 struct dundi_query_state *st; 00892 int totallen; 00893 int x,z; 00894 struct dundi_ie_data ied; 00895 char *s; 00896 struct dundi_result dr2[MAX_RESULTS]; 00897 struct dundi_request dr; 00898 struct dundi_hint_metadata hmd; 00899 00900 struct dundi_mapping *cur; 00901 int mapcount; 00902 int skipfirst = 0; 00903 00904 pthread_t lookupthread; 00905 pthread_attr_t attr; 00906 00907 memset(&dr2, 0, sizeof(dr2)); 00908 memset(&dr, 0, sizeof(dr)); 00909 memset(&hmd, 0, sizeof(hmd)); 00910 00911 /* Forge request structure to hold answers for cache */ 00912 hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; 00913 dr.dr = dr2; 00914 dr.maxcount = MAX_RESULTS; 00915 dr.expiration = dundi_cache_time; 00916 dr.hmd = &hmd; 00917 dr.pfds[0] = dr.pfds[1] = -1; 00918 trans->parent = &dr; 00919 ast_copy_string(dr.dcontext, ies->called_context ? ies->called_context : "e164", sizeof(dr.dcontext)); 00920 ast_copy_string(dr.number, ies->called_number, sizeof(dr.number)); 00921 00922 for (x=0;x<ies->anscount;x++) { 00923 if (trans->parent->respcount < trans->parent->maxcount) { 00924 /* Make sure it's not already there */ 00925 for (z=0;z<trans->parent->respcount;z++) { 00926 if ((trans->parent->dr[z].techint == ies->answers[x]->protocol) && 00927 !strcmp(trans->parent->dr[z].dest, (char *)ies->answers[x]->data)) 00928 break; 00929 } 00930 if (z == trans->parent->respcount) { 00931 /* Copy into parent responses */ 00932 trans->parent->dr[trans->parent->respcount].flags = ntohs(ies->answers[x]->flags); 00933 trans->parent->dr[trans->parent->respcount].techint = ies->answers[x]->protocol; 00934 trans->parent->dr[trans->parent->respcount].weight = ntohs(ies->answers[x]->weight); 00935 trans->parent->dr[trans->parent->respcount].eid = ies->answers[x]->eid; 00936 if (ies->expiration > 0) 00937 trans->parent->dr[trans->parent->respcount].expiration = ies->expiration; 00938 else 00939 trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time; 00940 dundi_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, 00941 sizeof(trans->parent->dr[trans->parent->respcount].eid_str), 00942 &ies->answers[x]->eid); 00943 ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies->answers[x]->data, 00944 sizeof(trans->parent->dr[trans->parent->respcount].dest)); 00945 ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies->answers[x]->protocol), 00946 sizeof(trans->parent->dr[trans->parent->respcount].tech)); 00947 trans->parent->respcount++; 00948 ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); 00949 } else if (trans->parent->dr[z].weight > ies->answers[x]->weight) { 00950 /* Update weight if appropriate */ 00951 trans->parent->dr[z].weight = ies->answers[x]->weight; 00952 } 00953 } else 00954 ast_log(LOG_NOTICE, "Dropping excessive answers in precache for %s@%s\n", 00955 trans->parent->number, trans->parent->dcontext); 00956 00957 } 00958 /* Save all the results (if any) we had. Even if no results, still cache lookup. */ 00959 cache_save(&trans->them_eid, trans->parent, 0, 0, ies->expiration, 1); 00960 if (ies->hint) 00961 cache_save_hint(&trans->them_eid, trans->parent, ies->hint, ies->expiration); 00962 00963 totallen = sizeof(struct dundi_query_state); 00964 /* Count matching map entries */ 00965 mapcount = 0; 00966 AST_LIST_TRAVERSE(&mappings, cur, list) { 00967 if (!strcasecmp(cur->dcontext, ccontext)) 00968 mapcount++; 00969 } 00970 00971 /* If no maps, return -1 immediately */ 00972 if (!mapcount) 00973 return -1; 00974 00975 if (ies->eidcount > 1) { 00976 /* Since it is a requirement that the first EID is the authenticating host 00977 and the last EID is the root, it is permissible that the first and last EID 00978 could be the same. In that case, we should go ahead copy only the "root" section 00979 since we will not need it for authentication. */ 00980 if (!dundi_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1])) 00981 skipfirst = 1; 00982 } 00983 00984 /* Prepare to run a query and then propagate that as necessary */ 00985 totallen += mapcount * sizeof(struct dundi_mapping); 00986 totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid); 00987 st = ast_calloc(1, totallen); 00988 if (st) { 00989 ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context)); 00990 ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number)); 00991 st->trans = trans; 00992 st->ttl = ies->ttl - 1; 00993 st->nocache = ies->cbypass; 00994 if (st->ttl < 0) 00995 st->ttl = 0; 00996 s = st->fluffy; 00997 for (x=skipfirst;ies->eids[x];x++) { 00998 st->eids[x-skipfirst] = (dundi_eid *)s; 00999 *st->eids[x-skipfirst] = *ies->eids[x]; 01000 st->directs[x-skipfirst] = ies->eid_direct[x]; 01001 s += sizeof(dundi_eid); 01002 } 01003 /* Append mappings */ 01004 x = 0; 01005 st->maps = (struct dundi_mapping *)s; 01006 AST_LIST_TRAVERSE(&mappings, cur, list) { 01007 if (!strcasecmp(cur->dcontext, ccontext)) { 01008 if (x < mapcount) { 01009 st->maps[x] = *cur; 01010 st->maps[x].list.next = NULL; 01011 x++; 01012 } 01013 } 01014 } 01015 st->nummaps = mapcount; 01016 ast_log(LOG_DEBUG, "Forwarding precache for '%s@%s'!\n", ies->called_number, ies->called_context); 01017 pthread_attr_init(&attr); 01018 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 01019 trans->thread = 1; 01020 if (ast_pthread_create(&lookupthread, &attr, dundi_precache_thread, st)) { 01021 trans->thread = 0; 01022 ast_log(LOG_WARNING, "Unable to create thread!\n"); 01023 free(st); 01024 memset(&ied, 0, sizeof(ied)); 01025 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); 01026 dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied); 01027 pthread_attr_destroy(&attr); 01028 return -1; 01029 } 01030 pthread_attr_destroy(&attr); 01031 } else { 01032 ast_log(LOG_WARNING, "Out of memory!\n"); 01033 memset(&ied, 0, sizeof(ied)); 01034 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); 01035 dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied); 01036 return -1; 01037 } 01038 return 0; 01039 }
static int dundi_query | ( | struct dundi_transaction * | trans | ) | [static] |
Definition at line 3225 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().
03226 { 03227 struct dundi_ie_data ied; 03228 int x; 03229 if (!trans->parent) { 03230 ast_log(LOG_WARNING, "Tried to query a transaction with no parent?!?\n"); 03231 return -1; 03232 } 03233 memset(&ied, 0, sizeof(ied)); 03234 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 03235 if (!dundi_eid_zero(&trans->us_eid)) 03236 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); 03237 for (x=0;x<trans->eidcount;x++) 03238 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]); 03239 dundi_ie_append_eid(&ied, DUNDI_IE_REQEID, &trans->parent->query_eid); 03240 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); 03241 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); 03242 if (trans->autokilltimeout) 03243 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); 03244 return dundi_send(trans, DUNDI_COMMAND_EIDQUERY, 0, 0, &ied); 03245 }
int dundi_query_eid | ( | struct dundi_entity_info * | dei, | |
const char * | dcontext, | |||
dundi_eid | eid | |||
) |
Retrieve information on a specific EID.
Definition at line 3843 of file pbx_dundi.c.
References dundi_query_eid_internal().
Referenced by dundi_do_query().
03844 { 03845 dundi_eid *avoid[1] = { NULL, }; 03846 struct dundi_hint_metadata hmd; 03847 memset(&hmd, 0, sizeof(hmd)); 03848 return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid); 03849 }
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 3796 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().
03797 { 03798 int res; 03799 struct dundi_request dr; 03800 dundi_eid *rooteid=NULL; 03801 int x; 03802 int ttlms; 03803 int skipped=0; 03804 int foundcache=0; 03805 struct timeval start; 03806 03807 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03808 03809 for (x=0;avoid[x];x++) 03810 rooteid = avoid[x]; 03811 /* Now perform real check */ 03812 memset(&dr, 0, sizeof(dr)); 03813 dr.hmd = hmd; 03814 dr.dei = dei; 03815 dr.pfds[0] = dr.pfds[1] = -1; 03816 ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext)); 03817 memcpy(&dr.query_eid, eid, sizeof(dr.query_eid)); 03818 if (rooteid) 03819 dr.root_eid = *rooteid; 03820 /* Create transactions */ 03821 build_transactions(&dr, ttl, 9999, &foundcache, &skipped, blockempty, 0, 0, NULL, avoid, NULL); 03822 03823 /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't 03824 do this earlier because we didn't know if we were going to have transactions 03825 or not. */ 03826 if (!ttl) { 03827 ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED); 03828 return 0; 03829 } 03830 03831 /* Optimize transactions */ 03832 optimize_transactions(&dr, 9999); 03833 /* Actually perform transactions */ 03834 query_transactions(&dr); 03835 /* Wait for transaction to come back */ 03836 start = ast_tvnow(); 03837 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) 03838 usleep(1); 03839 res = dr.respcount; 03840 return res; 03841 }
static void* dundi_query_thread | ( | void * | data | ) | [static] |
Definition at line 699 of file pbx_dundi.c.
References ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), 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, free, LOG_DEBUG, 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 ast_log(LOG_DEBUG, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, 00708 st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves"); 00709 memset(&ied, 0, sizeof(ied)); 00710 memset(&dei, 0, sizeof(dei)); 00711 memset(&hmd, 0, sizeof(hmd)); 00712 if (!dundi_eid_cmp(&st->trans->us_eid, &st->reqeid)) { 00713 /* Ooh, it's us! */ 00714 ast_log(LOG_DEBUG, "Neat, someone look for us!\n"); 00715 ast_copy_string(dei.orgunit, dept, sizeof(dei.orgunit)); 00716 ast_copy_string(dei.org, org, sizeof(dei.org)); 00717 ast_copy_string(dei.locality, locality, sizeof(dei.locality)); 00718 ast_copy_string(dei.stateprov, stateprov, sizeof(dei.stateprov)); 00719 ast_copy_string(dei.country, country, sizeof(dei.country)); 00720 ast_copy_string(dei.email, email, sizeof(dei.email)); 00721 ast_copy_string(dei.phone, phone, sizeof(dei.phone)); 00722 res = 1; 00723 } else { 00724 /* If we do not have a canonical result, keep looking */ 00725 res = dundi_query_eid_internal(&dei, st->called_context, &st->reqeid, &hmd, st->ttl, 1, st->eids); 00726 } 00727 AST_LIST_LOCK(&peers); 00728 if (ast_test_flag(st->trans, FLAG_DEAD)) { 00729 ast_log(LOG_DEBUG, "Our transaction went away!\n"); 00730 st->trans->thread = 0; 00731 destroy_trans(st->trans, 0); 00732 } else { 00733 if (res) { 00734 dundi_ie_append_str(&ied, DUNDI_IE_DEPARTMENT, dei.orgunit); 00735 dundi_ie_append_str(&ied, DUNDI_IE_ORGANIZATION, dei.org); 00736 dundi_ie_append_str(&ied, DUNDI_IE_LOCALITY, dei.locality); 00737 dundi_ie_append_str(&ied, DUNDI_IE_STATE_PROV, dei.stateprov); 00738 dundi_ie_append_str(&ied, DUNDI_IE_COUNTRY, dei.country); 00739 dundi_ie_append_str(&ied, DUNDI_IE_EMAIL, dei.email); 00740 dundi_ie_append_str(&ied, DUNDI_IE_PHONE, dei.phone); 00741 if (!ast_strlen_zero(dei.ipaddr)) 00742 dundi_ie_append_str(&ied, DUNDI_IE_IPADDR, dei.ipaddr); 00743 } 00744 dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten); 00745 dundi_send(st->trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); 00746 st->trans->thread = 0; 00747 } 00748 AST_LIST_UNLOCK(&peers); 00749 free(st); 00750 return NULL; 00751 }
static void dundi_reject | ( | struct dundi_hdr * | h, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 380 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().
00381 { 00382 struct { 00383 struct dundi_packet pack; 00384 struct dundi_hdr hdr; 00385 } tmp; 00386 struct dundi_transaction trans; 00387 /* Never respond to an INVALID with another INVALID */ 00388 if (h->cmdresp == DUNDI_COMMAND_INVALID) 00389 return; 00390 memset(&tmp, 0, sizeof(tmp)); 00391 memset(&trans, 0, sizeof(trans)); 00392 memcpy(&trans.addr, sin, sizeof(trans.addr)); 00393 tmp.hdr.strans = h->dtrans; 00394 tmp.hdr.dtrans = h->strans; 00395 tmp.hdr.iseqno = h->oseqno; 00396 tmp.hdr.oseqno = h->iseqno; 00397 tmp.hdr.cmdresp = DUNDI_COMMAND_INVALID; 00398 tmp.hdr.cmdflags = 0; 00399 tmp.pack.h = (struct dundi_hdr *)tmp.pack.data; 00400 tmp.pack.datalen = sizeof(struct dundi_hdr); 00401 tmp.pack.parent = &trans; 00402 dundi_xmit(&tmp.pack); 00403 }
static int dundi_rexmit | ( | const void * | data | ) | [static] |
Definition at line 3008 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().
03009 { 03010 struct dundi_packet *pack = (struct dundi_packet *)data; 03011 int res; 03012 AST_LIST_LOCK(&peers); 03013 if (pack->retrans < 1) { 03014 pack->retransid = -1; 03015 if (!ast_test_flag(pack->parent, FLAG_ISQUAL)) 03016 ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n", 03017 ast_inet_ntoa(pack->parent->addr.sin_addr), 03018 ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans)); 03019 destroy_trans(pack->parent, 1); 03020 res = 0; 03021 } else { 03022 /* Decrement retransmission, try again */ 03023 pack->retrans--; 03024 dundi_xmit(pack); 03025 res = 1; 03026 } 03027 AST_LIST_UNLOCK(&peers); 03028 return res; 03029 }
static int dundi_send | ( | struct dundi_transaction * | trans, | |
int | cmdresp, | |||
int | flags, | |||
int | final, | |||
struct dundi_ie_data * | ied | |||
) | [static] |
Definition at line 3031 of file pbx_dundi.c.
References dundi_transaction::addr, dundi_transaction::aseqno, ast_calloc, 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, free, 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().
03032 { 03033 struct dundi_packet *pack; 03034 int res; 03035 int len; 03036 char eid_str[20]; 03037 len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0); 03038 /* Reserve enough space for encryption */ 03039 if (ast_test_flag(trans, FLAG_ENCRYPT)) 03040 len += 384; 03041 pack = ast_calloc(1, len); 03042 if (pack) { 03043 pack->h = (struct dundi_hdr *)(pack->data); 03044 if (cmdresp != DUNDI_COMMAND_ACK) { 03045 pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack); 03046 pack->retrans = DUNDI_DEFAULT_RETRANS - 1; 03047 AST_LIST_INSERT_HEAD(&trans->packets, pack, list); 03048 } 03049 pack->parent = trans; 03050 pack->h->strans = htons(trans->strans); 03051 pack->h->dtrans = htons(trans->dtrans); 03052 pack->h->iseqno = trans->iseqno; 03053 pack->h->oseqno = trans->oseqno; 03054 pack->h->cmdresp = cmdresp; 03055 pack->datalen = sizeof(struct dundi_hdr); 03056 if (ied) { 03057 memcpy(pack->h->ies, ied->buf, ied->pos); 03058 pack->datalen += ied->pos; 03059 } 03060 if (final) { 03061 pack->h->cmdresp |= DUNDI_COMMAND_FINAL; 03062 ast_set_flag(trans, FLAG_FINAL); 03063 } 03064 pack->h->cmdflags = flags; 03065 if (cmdresp != DUNDI_COMMAND_ACK) { 03066 trans->oseqno++; 03067 trans->oseqno = trans->oseqno % 256; 03068 } 03069 trans->aseqno = trans->iseqno; 03070 /* If we have their public key, encrypt */ 03071 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 03072 switch(cmdresp) { 03073 case DUNDI_COMMAND_REGREQ: 03074 case DUNDI_COMMAND_REGRESPONSE: 03075 case DUNDI_COMMAND_DPDISCOVER: 03076 case DUNDI_COMMAND_DPRESPONSE: 03077 case DUNDI_COMMAND_EIDQUERY: 03078 case DUNDI_COMMAND_EIDRESPONSE: 03079 case DUNDI_COMMAND_PRECACHERQ: 03080 case DUNDI_COMMAND_PRECACHERP: 03081 if (dundidebug) 03082 dundi_showframe(pack->h, 2, &trans->addr, pack->datalen - sizeof(struct dundi_hdr)); 03083 res = dundi_encrypt(trans, pack); 03084 break; 03085 default: 03086 res = 0; 03087 } 03088 } else 03089 res = 0; 03090 if (!res) 03091 res = dundi_xmit(pack); 03092 if (res) 03093 ast_log(LOG_NOTICE, "Failed to send packet to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid)); 03094 03095 if (cmdresp == DUNDI_COMMAND_ACK) 03096 free(pack); 03097 return res; 03098 } 03099 return -1; 03100 }
static int dundi_show_entityid | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2655 of file pbx_dundi.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_UNLOCK, dundi_eid_to_str(), global_eid, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02656 { 02657 char eid_str[20]; 02658 if (argc != 3) 02659 return RESULT_SHOWUSAGE; 02660 AST_LIST_LOCK(&peers); 02661 dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid); 02662 AST_LIST_UNLOCK(&peers); 02663 ast_cli(fd, "Global EID for this system is '%s'\n", eid_str); 02664 return RESULT_SUCCESS; 02665 }
static int dundi_show_mappings | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2689 of file pbx_dundi.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), dundi_flags2str(), FORMAT, FORMAT2, dundi_mapping::list, map, RESULT_SHOWUSAGE, RESULT_SUCCESS, and tech2str().
02690 { 02691 #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n" 02692 #define FORMAT "%-12.12s %-7d %-12.12s %-10.10s %-5.5s %-25.25s\n" 02693 struct dundi_mapping *map; 02694 char fs[256]; 02695 if (argc != 3) 02696 return RESULT_SHOWUSAGE; 02697 AST_LIST_LOCK(&peers); 02698 ast_cli(fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination"); 02699 AST_LIST_TRAVERSE(&mappings, map, list) { 02700 ast_cli(fd, FORMAT, map->dcontext, map->weight, 02701 ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext, 02702 dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest); 02703 } 02704 AST_LIST_UNLOCK(&peers); 02705 return RESULT_SUCCESS; 02706 #undef FORMAT 02707 #undef FORMAT2 02708 }
static int dundi_show_peer | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2487 of file pbx_dundi.c.
References dundi_peer::addr, permission::allow, ast_cli(), ast_inet_ntoa(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, ast_strlen_zero(), dundi_peer::avgms, dundi_eid_to_str(), DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, DUNDI_TIMING_HISTORY, dundi_peer::dynamic, dundi_peer::eid, dundi_peer::include, dundi_peer::inkey, permission::list, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::model, model2str(), permission::name, dundi_peer::order, dundi_peer::outkey, dundi_peer::permit, dundi_peer::registerid, and RESULT_SHOWUSAGE.
02488 { 02489 struct dundi_peer *peer; 02490 struct permission *p; 02491 char *order; 02492 char eid_str[20]; 02493 int x, cnt; 02494 02495 if (argc != 4) 02496 return RESULT_SHOWUSAGE; 02497 AST_LIST_LOCK(&peers); 02498 AST_LIST_TRAVERSE(&peers, peer, list) { 02499 if (!strcasecmp(dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), argv[3])) 02500 break; 02501 } 02502 if (peer) { 02503 switch(peer->order) { 02504 case 0: 02505 order = "Primary"; 02506 break; 02507 case 1: 02508 order = "Secondary"; 02509 break; 02510 case 2: 02511 order = "Tertiary"; 02512 break; 02513 case 3: 02514 order = "Quartiary"; 02515 break; 02516 default: 02517 order = "Unknown"; 02518 } 02519 ast_cli(fd, "Peer: %s\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02520 ast_cli(fd, "Model: %s\n", model2str(peer->model)); 02521 ast_cli(fd, "Host: %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>"); 02522 ast_cli(fd, "Port: %d\n", ntohs(peer->addr.sin_port)); 02523 ast_cli(fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no"); 02524 ast_cli(fd, "Reg: %s\n", peer->registerid < 0 ? "No" : "Yes"); 02525 ast_cli(fd, "In Key: %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey); 02526 ast_cli(fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey); 02527 if (!AST_LIST_EMPTY(&peer->include)) 02528 ast_cli(fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)"); 02529 AST_LIST_TRAVERSE(&peer->include, p, list) 02530 ast_cli(fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name); 02531 if (!AST_LIST_EMPTY(&peer->permit)) 02532 ast_cli(fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)"); 02533 AST_LIST_TRAVERSE(&peer->permit, p, list) 02534 ast_cli(fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name); 02535 cnt = 0; 02536 for (x = 0;x < DUNDI_TIMING_HISTORY; x++) { 02537 if (peer->lookups[x]) { 02538 if (!cnt) 02539 ast_cli(fd, "Last few query times:\n"); 02540 ast_cli(fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]); 02541 cnt++; 02542 } 02543 } 02544 if (cnt) 02545 ast_cli(fd, "Average query time: %d ms\n", peer->avgms); 02546 } else 02547 ast_cli(fd, "No such peer '%s'\n", argv[3]); 02548 AST_LIST_UNLOCK(&peers); 02549 return RESULT_SUCCESS; 02550 }
static int dundi_show_peers | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2552 of file pbx_dundi.c.
References dundi_peer::addr, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_peer::avgms, dundi_eid_to_str(), dundi_peer::dynamic, dundi_peer::eid, FORMAT, FORMAT2, dundi_peer::lastms, dundi_peer::list, dundi_peer::maxms, dundi_peer::model, model2str(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02553 { 02554 #define FORMAT2 "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n" 02555 #define FORMAT "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n" 02556 struct dundi_peer *peer; 02557 int registeredonly=0; 02558 char avgms[20]; 02559 char eid_str[20]; 02560 int online_peers = 0; 02561 int offline_peers = 0; 02562 int unmonitored_peers = 0; 02563 int total_peers = 0; 02564 02565 if ((argc != 3) && (argc != 4) && (argc != 5)) 02566 return RESULT_SHOWUSAGE; 02567 if ((argc == 4)) { 02568 if (!strcasecmp(argv[3], "registered")) { 02569 registeredonly = 1; 02570 } else 02571 return RESULT_SHOWUSAGE; 02572 } 02573 AST_LIST_LOCK(&peers); 02574 ast_cli(fd, FORMAT2, "EID", "Host", "Port", "Model", "AvgTime", "Status"); 02575 AST_LIST_TRAVERSE(&peers, peer, list) { 02576 char status[20]; 02577 int print_line = -1; 02578 char srch[2000]; 02579 total_peers++; 02580 if (registeredonly && !peer->addr.sin_addr.s_addr) 02581 continue; 02582 if (peer->maxms) { 02583 if (peer->lastms < 0) { 02584 strcpy(status, "UNREACHABLE"); 02585 offline_peers++; 02586 } 02587 else if (peer->lastms > peer->maxms) { 02588 snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms); 02589 offline_peers++; 02590 } 02591 else if (peer->lastms) { 02592 snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms); 02593 online_peers++; 02594 } 02595 else { 02596 strcpy(status, "UNKNOWN"); 02597 offline_peers++; 02598 } 02599 } else { 02600 strcpy(status, "Unmonitored"); 02601 unmonitored_peers++; 02602 } 02603 if (peer->avgms) 02604 snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms); 02605 else 02606 strcpy(avgms, "Unavail"); 02607 snprintf(srch, sizeof(srch), FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 02608 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 02609 peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status); 02610 02611 if (argc == 5) { 02612 if (!strcasecmp(argv[3],"include") && strstr(srch,argv[4])) { 02613 print_line = -1; 02614 } else if (!strcasecmp(argv[3],"exclude") && !strstr(srch,argv[4])) { 02615 print_line = 1; 02616 } else if (!strcasecmp(argv[3],"begin") && !strncasecmp(srch,argv[4],strlen(argv[4]))) { 02617 print_line = -1; 02618 } else { 02619 print_line = 0; 02620 } 02621 } 02622 02623 if (print_line) { 02624 ast_cli(fd, FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 02625 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 02626 peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status); 02627 } 02628 } 02629 ast_cli(fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers); 02630 AST_LIST_UNLOCK(&peers); 02631 return RESULT_SUCCESS; 02632 #undef FORMAT 02633 #undef FORMAT2 02634 }
static int dundi_show_precache | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2710 of file pbx_dundi.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_precache_queue::context, dundi_precache_queue::expiration, FORMAT, FORMAT2, dundi_precache_queue::list, dundi_precache_queue::number, RESULT_SHOWUSAGE, RESULT_SUCCESS, and s.
02711 { 02712 #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n" 02713 #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n" 02714 struct dundi_precache_queue *qe; 02715 int h,m,s; 02716 time_t now; 02717 02718 if (argc != 3) 02719 return RESULT_SHOWUSAGE; 02720 time(&now); 02721 ast_cli(fd, FORMAT2, "Number", "Context", "Expiration"); 02722 AST_LIST_LOCK(&pcq); 02723 AST_LIST_TRAVERSE(&pcq, qe, list) { 02724 s = qe->expiration - now; 02725 h = s / 3600; 02726 s = s % 3600; 02727 m = s / 60; 02728 s = s % 60; 02729 ast_cli(fd, FORMAT, qe->number, qe->context, h,m,s); 02730 } 02731 AST_LIST_UNLOCK(&pcq); 02732 02733 return RESULT_SUCCESS; 02734 #undef FORMAT 02735 #undef FORMAT2 02736 }
static int dundi_show_requests | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2667 of file pbx_dundi.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_request::dcontext, dundi_eid_to_str(), dundi_eid_zero(), FORMAT, FORMAT2, dundi_request::list, dundi_request::maxcount, dundi_request::number, dundi_request::respcount, RESULT_SHOWUSAGE, RESULT_SUCCESS, and dundi_request::root_eid.
02668 { 02669 #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n" 02670 #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n" 02671 struct dundi_request *req; 02672 char eidstr[20]; 02673 if (argc != 3) 02674 return RESULT_SHOWUSAGE; 02675 AST_LIST_LOCK(&peers); 02676 ast_cli(fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp"); 02677 AST_LIST_TRAVERSE(&requests, req, list) { 02678 ast_cli(fd, FORMAT, req->number, req->dcontext, 02679 dundi_eid_zero(&req->root_eid) ? "<unspecified>" : dundi_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount); 02680 } 02681 AST_LIST_UNLOCK(&peers); 02682 return RESULT_SUCCESS; 02683 #undef FORMAT 02684 #undef FORMAT2 02685 }
static int dundi_show_trans | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2636 of file pbx_dundi.c.
References dundi_transaction::addr, dundi_transaction::all, dundi_transaction::aseqno, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_transaction::dtrans, FORMAT, FORMAT2, dundi_transaction::iseqno, dundi_transaction::oseqno, RESULT_SHOWUSAGE, RESULT_SUCCESS, and dundi_transaction::strans.
02637 { 02638 #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n" 02639 #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n" 02640 struct dundi_transaction *trans; 02641 if (argc != 3) 02642 return RESULT_SHOWUSAGE; 02643 AST_LIST_LOCK(&peers); 02644 ast_cli(fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack"); 02645 AST_LIST_TRAVERSE(&alltrans, trans, all) { 02646 ast_cli(fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr), 02647 ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno); 02648 } 02649 AST_LIST_UNLOCK(&peers); 02650 return RESULT_SUCCESS; 02651 #undef FORMAT 02652 #undef FORMAT2 02653 }
static int dundi_xmit | ( | struct dundi_packet * | pack | ) | [static] |
Definition at line 2900 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().
02901 { 02902 int res; 02903 if (dundidebug) 02904 dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr)); 02905 res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr)); 02906 if (res < 0) { 02907 ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n", 02908 ast_inet_ntoa(pack->parent->addr.sin_addr), 02909 ntohs(pack->parent->addr.sin_port), strerror(errno)); 02910 } 02911 if (res > 0) 02912 res = 0; 02913 return res; 02914 }
static int dundifunc_read | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | num, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 3851 of file pbx_dundi.c.
References ast_log(), ast_module_user_add, ast_module_user_remove, ast_strlen_zero(), ast_test_flag, dundi_result::dest, dr, DUNDI_FLAG_EXISTS, dundi_lookup(), LOG_WARNING, MAX_RESULTS, sort_results(), and dundi_result::tech.
03852 { 03853 char *context; 03854 char *opts; 03855 int results; 03856 int x; 03857 int bypass = 0; 03858 struct ast_module_user *u; 03859 struct dundi_result dr[MAX_RESULTS]; 03860 03861 buf[0] = '\0'; 03862 03863 if (ast_strlen_zero(num)) { 03864 ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n"); 03865 return -1; 03866 } 03867 03868 u = ast_module_user_add(chan); 03869 03870 context = strchr(num, '|'); 03871 if (context) { 03872 *context++ = '\0'; 03873 opts = strchr(context, '|'); 03874 if (opts) { 03875 *opts++ = '\0'; 03876 if (strchr(opts, 'b')) 03877 bypass = 1; 03878 } 03879 } 03880 03881 if (ast_strlen_zero(context)) 03882 context = "e164"; 03883 03884 results = dundi_lookup(dr, MAX_RESULTS, NULL, context, num, bypass); 03885 if (results > 0) { 03886 sort_results(dr, results); 03887 for (x = 0; x < results; x++) { 03888 if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) { 03889 snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest); 03890 break; 03891 } 03892 } 03893 } 03894 03895 ast_module_user_remove(u); 03896 03897 return 0; 03898 }
static int encrypt_memcpy | ( | unsigned char * | dst, | |
unsigned char * | src, | |||
int | len, | |||
unsigned char * | iv, | |||
aes_encrypt_ctx * | ecx | |||
) | [static] |
Definition at line 1328 of file pbx_dundi.c.
References aes_encrypt().
Referenced by dundi_encrypt().
01329 { 01330 unsigned char curblock[16]; 01331 int x; 01332 memcpy(curblock, iv, sizeof(curblock)); 01333 while(len > 0) { 01334 for (x=0;x<16;x++) 01335 curblock[x] ^= src[x]; 01336 aes_encrypt(curblock, dst, ecx); 01337 memcpy(curblock, dst, sizeof(curblock)); 01338 dst += 16; 01339 src += 16; 01340 len -= 16; 01341 } 01342 return 0; 01343 }
static struct dundi_peer* find_peer | ( | dundi_eid * | eid | ) | [static] |
Definition at line 485 of file pbx_dundi.c.
References any_peer, AST_LIST_TRAVERSE, dundi_eid_cmp(), dundi_peer::eid, and empty_eid.
00486 { 00487 struct dundi_peer *cur = NULL; 00488 00489 if (!eid) 00490 eid = &empty_eid; 00491 00492 AST_LIST_TRAVERSE(&peers, cur, list) { 00493 if (!dundi_eid_cmp(&cur->eid,eid)) 00494 break; 00495 } 00496 00497 if (!cur && any_peer) 00498 cur = any_peer; 00499 00500 return cur; 00501 }
static struct dundi_transaction* find_transaction | ( | struct dundi_hdr * | hdr, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 335 of file pbx_dundi.c.
References dundi_transaction::addr, AST_LIST_TRAVERSE, ast_log(), 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(), LOG_WARNING, dundi_hdr::strans, and dundi_transaction::strans.
Referenced by handle_frame().
00336 { 00337 struct dundi_transaction *trans; 00338 00339 /* Look for an exact match first */ 00340 AST_LIST_TRAVERSE(&alltrans, trans, all) { 00341 if (!inaddrcmp(&trans->addr, sin) && 00342 ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ || 00343 ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) { 00344 if (hdr->strans) 00345 trans->dtrans = ntohs(hdr->strans) & 32767; 00346 break; 00347 } 00348 } 00349 if (!trans) { 00350 switch(hdr->cmdresp & 0x7f) { 00351 case DUNDI_COMMAND_DPDISCOVER: 00352 case DUNDI_COMMAND_EIDQUERY: 00353 case DUNDI_COMMAND_PRECACHERQ: 00354 case DUNDI_COMMAND_REGREQ: 00355 case DUNDI_COMMAND_NULL: 00356 case DUNDI_COMMAND_ENCRYPT: 00357 if (hdr->strans) { 00358 /* Create new transaction */ 00359 trans = create_transaction(NULL); 00360 if (trans) { 00361 memcpy(&trans->addr, sin, sizeof(trans->addr)); 00362 trans->dtrans = ntohs(hdr->strans) & 32767; 00363 } else 00364 ast_log(LOG_WARNING, "Out of memory!\n"); 00365 } 00366 break; 00367 default: 00368 break; 00369 } 00370 } 00371 return trans; 00372 }
static int get_trans_id | ( | void | ) | [static] |
Definition at line 450 of file pbx_dundi.c.
References AST_LIST_TRAVERSE, ast_random(), and t.
Referenced by create_transaction(), and reset_transaction().
00451 { 00452 struct dundi_transaction *t; 00453 int stid = (ast_random() % 32766) + 1; 00454 int tid = stid; 00455 00456 do { 00457 AST_LIST_TRAVERSE(&alltrans, t, all) { 00458 if (t->strans == tid) 00459 break; 00460 } 00461 if (!t) 00462 return tid; 00463 tid = (tid % 32766) + 1; 00464 } while (tid != stid); 00465 00466 return 0; 00467 }
static int handle_command_response | ( | struct dundi_transaction * | trans, | |
struct dundi_hdr * | hdr, | |||
int | datalen, | |||
int | encrypted | |||
) | [static] |
Definition at line 1536 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_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_verbose(), 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_DEBUG, LOG_NOTICE, LOG_WARNING, dundi_request::maxcount, dundi_peer::model, dundi_request::number, option_verbose, 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, VERBOSE_PREFIX_3, and dundi_result::weight.
Referenced by handle_frame().
01537 { 01538 /* Handle canonical command / response */ 01539 int final = hdr->cmdresp & 0x80; 01540 int cmd = hdr->cmdresp & 0x7f; 01541 int x,y,z; 01542 int resp; 01543 int res; 01544 int authpass=0; 01545 unsigned char *bufcpy; 01546 #ifdef LOW_MEMORY 01547 struct dundi_ie_data *ied = ast_calloc(1, sizeof(*ied)); 01548 #else 01549 struct dundi_ie_data _ied = { 01550 .pos = 0, 01551 }; 01552 struct dundi_ie_data *ied = &_ied; 01553 #endif 01554 struct dundi_ies ies = { 01555 .eidcount = 0, 01556 }; 01557 struct dundi_peer *peer = NULL; 01558 char eid_str[20]; 01559 char eid_str2[20]; 01560 int retval = -1; 01561 01562 if (!ied) { 01563 return -1; 01564 } 01565 01566 if (datalen) { 01567 bufcpy = alloca(datalen); 01568 if (!bufcpy) { 01569 goto return_cleanup; 01570 } 01571 /* Make a copy for parsing */ 01572 memcpy(bufcpy, hdr->ies, datalen); 01573 ast_log(LOG_DEBUG, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : ""); 01574 if (dundi_parse_ies(&ies, bufcpy, datalen) < 0) { 01575 ast_log(LOG_WARNING, "Failed to parse DUNDI information elements!\n"); 01576 goto return_cleanup; 01577 } 01578 } 01579 switch(cmd) { 01580 case DUNDI_COMMAND_DPDISCOVER: 01581 case DUNDI_COMMAND_EIDQUERY: 01582 case DUNDI_COMMAND_PRECACHERQ: 01583 if (cmd == DUNDI_COMMAND_EIDQUERY) 01584 resp = DUNDI_COMMAND_EIDRESPONSE; 01585 else if (cmd == DUNDI_COMMAND_PRECACHERQ) 01586 resp = DUNDI_COMMAND_PRECACHERP; 01587 else 01588 resp = DUNDI_COMMAND_DPRESPONSE; 01589 /* A dialplan or entity discover -- qualify by highest level entity */ 01590 peer = find_peer(ies.eids[0]); 01591 if (!peer) { 01592 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL); 01593 dundi_send(trans, resp, 0, 1, ied); 01594 } else { 01595 int hasauth = 0; 01596 trans->us_eid = peer->us_eid; 01597 if (strlen(peer->inkey)) { 01598 hasauth = encrypted; 01599 } else 01600 hasauth = 1; 01601 if (hasauth) { 01602 /* Okay we're authentiated and all, now we check if they're authorized */ 01603 if (!ies.called_context) 01604 ies.called_context = "e164"; 01605 if (cmd == DUNDI_COMMAND_EIDQUERY) { 01606 res = dundi_answer_entity(trans, &ies, ies.called_context); 01607 } else { 01608 if (ast_strlen_zero(ies.called_number)) { 01609 /* They're not permitted to access that context */ 01610 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Invalid or missing number/entity"); 01611 dundi_send(trans, resp, 0, 1, ied); 01612 } else if ((cmd == DUNDI_COMMAND_DPDISCOVER) && 01613 (peer->model & DUNDI_MODEL_INBOUND) && 01614 has_permission(&peer->permit, ies.called_context)) { 01615 res = dundi_answer_query(trans, &ies, ies.called_context); 01616 if (res < 0) { 01617 /* There is no such dundi context */ 01618 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context"); 01619 dundi_send(trans, resp, 0, 1, ied); 01620 } 01621 } else if ((cmd = DUNDI_COMMAND_PRECACHERQ) && 01622 (peer->pcmodel & DUNDI_MODEL_INBOUND) && 01623 has_permission(&peer->include, ies.called_context)) { 01624 res = dundi_prop_precache(trans, &ies, ies.called_context); 01625 if (res < 0) { 01626 /* There is no such dundi context */ 01627 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context"); 01628 dundi_send(trans, resp, 0, 1, ied); 01629 } 01630 } else { 01631 /* They're not permitted to access that context */ 01632 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Permission to context denied"); 01633 dundi_send(trans, resp, 0, 1, ied); 01634 } 01635 } 01636 } else { 01637 /* They're not permitted to access that context */ 01638 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unencrypted responses not permitted"); 01639 dundi_send(trans, resp, 0, 1, ied); 01640 } 01641 } 01642 break; 01643 case DUNDI_COMMAND_REGREQ: 01644 /* A register request -- should only have one entity */ 01645 peer = find_peer(ies.eids[0]); 01646 01647 /* if the peer is not found and we have a valid 'any_peer' setting */ 01648 if (any_peer && peer == any_peer) { 01649 /* copy any_peer into a new peer object */ 01650 peer = ast_calloc(1, sizeof(*peer)); 01651 if (peer) { 01652 deep_copy_peer(peer, any_peer); 01653 01654 /* set EID to remote EID */ 01655 peer->eid = *ies.eids[0]; 01656 01657 AST_LIST_LOCK(&peers); 01658 AST_LIST_INSERT_HEAD(&peers, peer, list); 01659 AST_LIST_UNLOCK(&peers); 01660 } 01661 } 01662 01663 if (!peer || !peer->dynamic) { 01664 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL); 01665 dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied); 01666 } else { 01667 int hasauth = 0; 01668 trans->us_eid = peer->us_eid; 01669 if (!ast_strlen_zero(peer->inkey)) { 01670 hasauth = encrypted; 01671 } else 01672 hasauth = 1; 01673 if (hasauth) { 01674 int expire = default_expiration; 01675 char data[256]; 01676 int needqual = 0; 01677 AST_SCHED_DEL(sched, peer->registerexpire); 01678 peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer); 01679 snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(trans->addr.sin_addr), 01680 ntohs(trans->addr.sin_port), expire); 01681 ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data); 01682 if (inaddrcmp(&peer->addr, &trans->addr)) { 01683 if (option_verbose > 2) { 01684 ast_verbose(VERBOSE_PREFIX_3 "Registered DUNDi peer '%s' at '%s:%d'\n", 01685 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 01686 ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port)); 01687 } 01688 needqual = 1; 01689 } 01690 01691 memcpy(&peer->addr, &trans->addr, sizeof(peer->addr)); 01692 dundi_ie_append_short(ied, DUNDI_IE_EXPIRATION, default_expiration); 01693 dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied); 01694 if (needqual) 01695 qualify_peer(peer, 1); 01696 } 01697 } 01698 break; 01699 case DUNDI_COMMAND_DPRESPONSE: 01700 /* A dialplan response, lets see what we got... */ 01701 if (ies.cause < 1) { 01702 /* Success of some sort */ 01703 ast_log(LOG_DEBUG, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount); 01704 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 01705 authpass = encrypted; 01706 } else 01707 authpass = 1; 01708 if (authpass) { 01709 /* Pass back up answers */ 01710 if (trans->parent && trans->parent->dr) { 01711 y = trans->parent->respcount; 01712 for (x=0;x<ies.anscount;x++) { 01713 if (trans->parent->respcount < trans->parent->maxcount) { 01714 /* Make sure it's not already there */ 01715 for (z=0;z<trans->parent->respcount;z++) { 01716 if ((trans->parent->dr[z].techint == ies.answers[x]->protocol) && 01717 !strcmp(trans->parent->dr[z].dest, (char *)ies.answers[x]->data)) 01718 break; 01719 } 01720 if (z == trans->parent->respcount) { 01721 /* Copy into parent responses */ 01722 trans->parent->dr[trans->parent->respcount].flags = ntohs(ies.answers[x]->flags); 01723 trans->parent->dr[trans->parent->respcount].techint = ies.answers[x]->protocol; 01724 trans->parent->dr[trans->parent->respcount].weight = ntohs(ies.answers[x]->weight); 01725 trans->parent->dr[trans->parent->respcount].eid = ies.answers[x]->eid; 01726 if (ies.expiration > 0) 01727 trans->parent->dr[trans->parent->respcount].expiration = ies.expiration; 01728 else 01729 trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time; 01730 dundi_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, 01731 sizeof(trans->parent->dr[trans->parent->respcount].eid_str), 01732 &ies.answers[x]->eid); 01733 ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies.answers[x]->data, 01734 sizeof(trans->parent->dr[trans->parent->respcount].dest)); 01735 ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies.answers[x]->protocol), 01736 sizeof(trans->parent->dr[trans->parent->respcount].tech)); 01737 trans->parent->respcount++; 01738 ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); 01739 } else if (trans->parent->dr[z].weight > ies.answers[x]->weight) { 01740 /* Update weight if appropriate */ 01741 trans->parent->dr[z].weight = ies.answers[x]->weight; 01742 } 01743 } else 01744 ast_log(LOG_NOTICE, "Dropping excessive answers to request for %s@%s\n", 01745 trans->parent->number, trans->parent->dcontext); 01746 } 01747 /* Save all the results (if any) we had. Even if no results, still cache lookup. Let 01748 the cache know if this request was unaffected by our entity list. */ 01749 cache_save(&trans->them_eid, trans->parent, y, 01750 ies.hint ? ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_UNAFFECTED)) : 0, ies.expiration, 0); 01751 if (ies.hint) { 01752 cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration); 01753 if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED))) 01754 ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED); 01755 if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_DONT_ASK))) { 01756 if (strlen((char *)ies.hint->data) > strlen(trans->parent->hmd->exten)) { 01757 ast_copy_string(trans->parent->hmd->exten, (char *)ies.hint->data, 01758 sizeof(trans->parent->hmd->exten)); 01759 } 01760 } else { 01761 ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); 01762 } 01763 } 01764 if (ies.expiration > 0) { 01765 if (trans->parent->expiration > ies.expiration) { 01766 trans->parent->expiration = ies.expiration; 01767 } 01768 } 01769 } 01770 /* Close connection if not final */ 01771 if (!final) 01772 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01773 } 01774 01775 } else { 01776 /* Auth failure, check for data */ 01777 if (!final) { 01778 /* Cancel if they didn't already */ 01779 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01780 } 01781 } 01782 break; 01783 case DUNDI_COMMAND_EIDRESPONSE: 01784 /* A dialplan response, lets see what we got... */ 01785 if (ies.cause < 1) { 01786 /* Success of some sort */ 01787 ast_log(LOG_DEBUG, "Looks like success of some sort (%d)\n", ies.cause); 01788 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 01789 authpass = encrypted; 01790 } else 01791 authpass = 1; 01792 if (authpass) { 01793 /* Pass back up answers */ 01794 if (trans->parent && trans->parent->dei && ies.q_org) { 01795 if (!trans->parent->respcount) { 01796 trans->parent->respcount++; 01797 if (ies.q_dept) 01798 ast_copy_string(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit)); 01799 if (ies.q_org) 01800 ast_copy_string(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org)); 01801 if (ies.q_locality) 01802 ast_copy_string(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality)); 01803 if (ies.q_stateprov) 01804 ast_copy_string(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov)); 01805 if (ies.q_country) 01806 ast_copy_string(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country)); 01807 if (ies.q_email) 01808 ast_copy_string(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email)); 01809 if (ies.q_phone) 01810 ast_copy_string(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone)); 01811 if (ies.q_ipaddr) 01812 ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr)); 01813 if (!dundi_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) { 01814 /* If it's them, update our address */ 01815 ast_copy_string(trans->parent->dei->ipaddr, ast_inet_ntoa(trans->addr.sin_addr), sizeof(trans->parent->dei->ipaddr)); 01816 } 01817 } 01818 if (ies.hint) { 01819 if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED))) 01820 ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED); 01821 } 01822 } 01823 /* Close connection if not final */ 01824 if (!final) 01825 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01826 } 01827 01828 } else { 01829 /* Auth failure, check for data */ 01830 if (!final) { 01831 /* Cancel if they didn't already */ 01832 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01833 } 01834 } 01835 break; 01836 case DUNDI_COMMAND_REGRESPONSE: 01837 /* A dialplan response, lets see what we got... */ 01838 if (ies.cause < 1) { 01839 int hasauth; 01840 /* Success of some sort */ 01841 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 01842 hasauth = encrypted; 01843 } else 01844 hasauth = 1; 01845 01846 if (!hasauth) { 01847 ast_log(LOG_NOTICE, "Reponse to register not authorized!\n"); 01848 if (!final) { 01849 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Improper signature in answer"); 01850 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, ied); 01851 } 01852 } else { 01853 ast_log(LOG_DEBUG, "Yay, we've registered as '%s' to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->us_eid), 01854 dundi_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid)); 01855 /* Close connection if not final */ 01856 if (!final) 01857 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01858 } 01859 } else { 01860 /* Auth failure, cancel if they didn't for some reason */ 01861 if (!final) { 01862 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01863 } 01864 } 01865 break; 01866 case DUNDI_COMMAND_INVALID: 01867 case DUNDI_COMMAND_NULL: 01868 case DUNDI_COMMAND_PRECACHERP: 01869 /* Do nothing special */ 01870 if (!final) 01871 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01872 break; 01873 case DUNDI_COMMAND_ENCREJ: 01874 if ((ast_test_flag(trans, FLAG_SENDFULLKEY)) || AST_LIST_EMPTY(&trans->lasttrans) || !(peer = find_peer(&trans->them_eid))) { 01875 /* No really, it's over at this point */ 01876 if (!final) 01877 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01878 } else { 01879 /* Send with full key */ 01880 ast_set_flag(trans, FLAG_SENDFULLKEY); 01881 if (final) { 01882 /* Ooops, we got a final message, start by sending ACK... */ 01883 dundi_ack(trans, hdr->cmdresp & 0x80); 01884 trans->aseqno = trans->iseqno; 01885 /* Now, we gotta create a new transaction */ 01886 if (!reset_transaction(trans)) { 01887 /* Make sure handle_frame doesn't destroy us */ 01888 hdr->cmdresp &= 0x7f; 01889 /* Parse the message we transmitted */ 01890 memset(&ies, 0, sizeof(ies)); 01891 dundi_parse_ies(&ies, (AST_LIST_FIRST(&trans->lasttrans))->h->ies, (AST_LIST_FIRST(&trans->lasttrans))->datalen - sizeof(struct dundi_hdr)); 01892 /* Reconstruct outgoing encrypted packet */ 01893 memset(ied, 0, sizeof(*ied)); 01894 dundi_ie_append_eid(ied, DUNDI_IE_EID, &trans->us_eid); 01895 dundi_ie_append_raw(ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128); 01896 dundi_ie_append_raw(ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128); 01897 if (ies.encblock) 01898 dundi_ie_append_encdata(ied, DUNDI_IE_ENCDATA, ies.encblock->iv, ies.encblock->encdata, ies.enclen); 01899 dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, (AST_LIST_FIRST(&trans->lasttrans))->h->cmdresp & 0x80, ied); 01900 peer->sentfullkey = 1; 01901 } 01902 } 01903 } 01904 break; 01905 case DUNDI_COMMAND_ENCRYPT: 01906 if (!encrypted) { 01907 /* No nested encryption! */ 01908 if ((trans->iseqno == 1) && !trans->oseqno) { 01909 if (!ies.eids[0] || !(peer = find_peer(ies.eids[0])) || 01910 ((!ies.encsharedkey || !ies.encsig) && !ies.keycrc32) || 01911 (check_key(peer, ies.encsharedkey, ies.encsig, ies.keycrc32) < 1)) { 01912 if (!final) { 01913 dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL); 01914 } 01915 break; 01916 } 01917 apply_peer(trans, peer); 01918 /* Key passed, use new contexts for this session */ 01919 trans->ecx = peer->them_ecx; 01920 trans->dcx = peer->them_dcx; 01921 } 01922 if (ast_test_flag(trans, FLAG_ENCRYPT) && ies.encblock && ies.enclen) { 01923 struct dundi_hdr *dhdr; 01924 unsigned char decoded[MAX_PACKET_SIZE]; 01925 int ddatalen; 01926 ddatalen = sizeof(decoded); 01927 dhdr = dundi_decrypt(trans, decoded, &ddatalen, hdr, ies.encblock, ies.enclen); 01928 if (dhdr) { 01929 /* Handle decrypted response */ 01930 if (dundidebug) 01931 dundi_showframe(dhdr, 3, &trans->addr, ddatalen - sizeof(struct dundi_hdr)); 01932 handle_command_response(trans, dhdr, ddatalen - sizeof(struct dundi_hdr), 1); 01933 /* Carry back final flag */ 01934 hdr->cmdresp |= dhdr->cmdresp & 0x80; 01935 break; 01936 } else 01937 ast_log(LOG_DEBUG, "Ouch, decrypt failed :(\n"); 01938 } 01939 } 01940 if (!final) { 01941 /* Turn off encryption */ 01942 ast_clear_flag(trans, FLAG_ENCRYPT); 01943 dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL); 01944 } 01945 break; 01946 default: 01947 /* Send unknown command if we don't know it, with final flag IFF it's the 01948 first command in the dialog and only if we haven't recieved final notification */ 01949 if (!final) { 01950 dundi_ie_append_byte(ied, DUNDI_IE_UNKNOWN, cmd); 01951 dundi_send(trans, DUNDI_COMMAND_UNKNOWN, 0, !hdr->oseqno, ied); 01952 } 01953 } 01954 01955 retval = 0; 01956 01957 return_cleanup: 01958 #ifdef LOW_MEMORY 01959 ast_free(ied); 01960 #endif 01961 return retval; 01962 }
static int handle_frame | ( | struct dundi_hdr * | h, | |
struct sockaddr_in * | sin, | |||
int | datalen | |||
) | [static] |
Definition at line 1997 of file pbx_dundi.c.
References ack_trans(), dundi_transaction::aseqno, ast_log(), 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, LOG_DEBUG, dundi_transaction::oiseqno, and dundi_hdr::oseqno.
01998 { 01999 struct dundi_transaction *trans; 02000 trans = find_transaction(h, sin); 02001 if (!trans) { 02002 dundi_reject(h, sin); 02003 return 0; 02004 } 02005 /* Got a transaction, see where this header fits in */ 02006 if (h->oseqno == trans->iseqno) { 02007 /* Just what we were looking for... Anything but ack increments iseqno */ 02008 if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) { 02009 /* If final, we're done */ 02010 destroy_trans(trans, 0); 02011 return 0; 02012 } 02013 if (h->cmdresp != DUNDI_COMMAND_ACK) { 02014 trans->oiseqno = trans->iseqno; 02015 trans->iseqno++; 02016 handle_command_response(trans, h, datalen, 0); 02017 } 02018 if (trans->aseqno != trans->iseqno) { 02019 dundi_ack(trans, h->cmdresp & 0x80); 02020 trans->aseqno = trans->iseqno; 02021 } 02022 /* Delete any saved last transmissions */ 02023 destroy_packets(&trans->lasttrans); 02024 if (h->cmdresp & 0x80) { 02025 /* Final -- destroy now */ 02026 destroy_trans(trans, 0); 02027 } 02028 } else if (h->oseqno == trans->oiseqno) { 02029 /* Last incoming sequence number -- send ACK without processing */ 02030 dundi_ack(trans, 0); 02031 } else { 02032 /* Out of window -- simply drop */ 02033 ast_log(LOG_DEBUG, "Dropping packet out of window!\n"); 02034 } 02035 return 0; 02036 }
static int has_permission | ( | struct permissionlist * | permlist, | |
char * | cont | |||
) | [static] |
Definition at line 291 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().
00292 { 00293 struct permission *perm; 00294 int res = 0; 00295 00296 AST_LIST_TRAVERSE(permlist, perm, list) { 00297 if (!strcasecmp(perm->name, "all") || !strcasecmp(perm->name, cont)) 00298 res = perm->allow; 00299 } 00300 00301 return res; 00302 }
static int load_module | ( | void | ) | [static] |
Definition at line 4622 of file pbx_dundi.c.
References ast_cli_register_multiple(), ast_custom_function_register(), ast_inet_ntoa(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_switch(), ast_verbose(), cli_dundi, dundi_debug_output(), dundi_error_output(), dundi_function, DUNDI_PORT, dundi_set_error(), dundi_set_output(), dundi_switch, errno, io, io_context_create(), LOG_ERROR, option_verbose, sched, sched_context_create(), set_config(), start_network_thread(), and VERBOSE_PREFIX_2.
04623 { 04624 int res = 0; 04625 struct sockaddr_in sin; 04626 04627 dundi_set_output(dundi_debug_output); 04628 dundi_set_error(dundi_error_output); 04629 04630 sin.sin_family = AF_INET; 04631 sin.sin_port = ntohs(DUNDI_PORT); 04632 sin.sin_addr.s_addr = INADDR_ANY; 04633 04634 /* Make a UDP socket */ 04635 io = io_context_create(); 04636 sched = sched_context_create(); 04637 04638 if (!io || !sched) { 04639 ast_log(LOG_ERROR, "Out of memory\n"); 04640 return AST_MODULE_LOAD_DECLINE; 04641 } 04642 04643 if(set_config("dundi.conf",&sin)) 04644 return AST_MODULE_LOAD_DECLINE; 04645 04646 netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 04647 04648 if (netsocket < 0) { 04649 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 04650 return AST_MODULE_LOAD_DECLINE; 04651 } 04652 if (bind(netsocket,(struct sockaddr *)&sin, sizeof(sin))) { 04653 ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), strerror(errno)); 04654 return AST_MODULE_LOAD_DECLINE; 04655 } 04656 04657 if (option_verbose > 1) 04658 ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos); 04659 04660 if (setsockopt(netsocket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) 04661 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 04662 04663 res = start_network_thread(); 04664 if (res) { 04665 ast_log(LOG_ERROR, "Unable to start network thread\n"); 04666 close(netsocket); 04667 return AST_MODULE_LOAD_DECLINE; 04668 } 04669 04670 if (option_verbose > 1) 04671 ast_verbose(VERBOSE_PREFIX_2 "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 04672 04673 ast_cli_register_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(struct ast_cli_entry)); 04674 if (ast_register_switch(&dundi_switch)) 04675 ast_log(LOG_ERROR, "Unable to register DUNDi switch\n"); 04676 ast_custom_function_register(&dundi_function); 04677 04678 return AST_MODULE_LOAD_SUCCESS; 04679 }
static void load_password | ( | void | ) | [static] |
Definition at line 2094 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().
02095 { 02096 char *current=NULL; 02097 char *last=NULL; 02098 char tmp[256]; 02099 time_t expired; 02100 02101 ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp)); 02102 if (!ast_get_time_t(tmp, &expired, 0, NULL)) { 02103 ast_db_get(secretpath, "secret", tmp, sizeof(tmp)); 02104 current = strchr(tmp, ';'); 02105 if (!current) 02106 current = tmp; 02107 else { 02108 *current = '\0'; 02109 current++; 02110 }; 02111 if ((time(NULL) - expired) < 0) { 02112 if ((expired - time(NULL)) > DUNDI_SECRET_TIME) 02113 expired = time(NULL) + DUNDI_SECRET_TIME; 02114 } else if ((time(NULL) - (expired + DUNDI_SECRET_TIME)) < 0) { 02115 last = current; 02116 current = NULL; 02117 } else { 02118 last = NULL; 02119 current = NULL; 02120 } 02121 } 02122 if (current) { 02123 /* Current key is still valid, just setup rotatation properly */ 02124 ast_copy_string(cursecret, current, sizeof(cursecret)); 02125 rotatetime = expired; 02126 } else { 02127 /* Current key is out of date, rotate or eliminate all together */ 02128 build_secret(cursecret, sizeof(cursecret)); 02129 save_secret(cursecret, last); 02130 } 02131 }
static void mark_mappings | ( | void | ) | [static] |
Definition at line 3927 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().
03928 { 03929 struct dundi_mapping *map; 03930 03931 AST_LIST_LOCK(&peers); 03932 AST_LIST_TRAVERSE(&mappings, map, list) { 03933 map->dead = 1; 03934 } 03935 AST_LIST_UNLOCK(&peers); 03936 }
static void mark_peers | ( | void | ) | [static] |
Definition at line 3917 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().
03918 { 03919 struct dundi_peer *peer; 03920 AST_LIST_LOCK(&peers); 03921 AST_LIST_TRAVERSE(&peers, peer, list) { 03922 peer->dead = 1; 03923 } 03924 AST_LIST_UNLOCK(&peers); 03925 }
static char* model2str | ( | int | model | ) | [static] |
Definition at line 2325 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().
02326 { 02327 switch(model) { 02328 case DUNDI_MODEL_INBOUND: 02329 return "Inbound"; 02330 case DUNDI_MODEL_OUTBOUND: 02331 return "Outbound"; 02332 case DUNDI_MODEL_SYMMETRIC: 02333 return "Symmetric"; 02334 default: 02335 return "Unknown"; 02336 } 02337 }
static void* network_thread | ( | void * | ignore | ) | [static] |
Definition at line 2150 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().
02151 { 02152 /* Our job is simple: Send queued messages, retrying if necessary. Read frames 02153 from the network, and queue them for delivery to the channels */ 02154 int res; 02155 /* Establish I/O callback for socket read */ 02156 ast_io_add(io, netsocket, socket_read, AST_IO_IN, NULL); 02157 02158 while (!dundi_shutdown) { 02159 res = ast_sched_wait(sched); 02160 if ((res > 1000) || (res < 0)) 02161 res = 1000; 02162 res = ast_io_wait(io, res); 02163 if (res >= 0) { 02164 AST_LIST_LOCK(&peers); 02165 ast_sched_runq(sched); 02166 AST_LIST_UNLOCK(&peers); 02167 } 02168 check_password(); 02169 } 02170 02171 netthreadid = AST_PTHREADT_NULL; 02172 02173 return NULL; 02174 }
static int optimize_transactions | ( | struct dundi_request * | dr, | |
int | order | |||
) | [static] |
Definition at line 3306 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().
03307 { 03308 /* Minimize the message propagation through DUNDi by 03309 alerting the network to hops which should be not be considered */ 03310 struct dundi_transaction *trans; 03311 struct dundi_peer *peer; 03312 dundi_eid tmp; 03313 int x; 03314 int needpush; 03315 03316 AST_LIST_LOCK(&peers); 03317 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03318 /* Pop off the true root */ 03319 if (trans->eidcount) { 03320 tmp = trans->eids[--trans->eidcount]; 03321 needpush = 1; 03322 } else { 03323 tmp = trans->us_eid; 03324 needpush = 0; 03325 } 03326 03327 AST_LIST_TRAVERSE(&peers, peer, list) { 03328 if (has_permission(&peer->include, dr->dcontext) && 03329 dundi_eid_cmp(&peer->eid, &trans->them_eid) && 03330 (peer->order <= order)) { 03331 /* For each other transaction, make sure we don't 03332 ask this EID about the others if they're not 03333 already in the list */ 03334 if (!dundi_eid_cmp(&tmp, &peer->eid)) 03335 x = -1; 03336 else { 03337 for (x=0;x<trans->eidcount;x++) { 03338 if (!dundi_eid_cmp(&trans->eids[x], &peer->eid)) 03339 break; 03340 } 03341 } 03342 if (x == trans->eidcount) { 03343 /* Nope not in the list, if needed, add us at the end since we're the source */ 03344 if (trans->eidcount < DUNDI_MAX_STACK - needpush) { 03345 trans->eids[trans->eidcount++] = peer->eid; 03346 /* Need to insert the real root (or us) at the bottom now as 03347 a requirement now. */ 03348 needpush = 1; 03349 } 03350 } 03351 } 03352 } 03353 /* If necessary, push the true root back on the end */ 03354 if (needpush) 03355 trans->eids[trans->eidcount++] = tmp; 03356 } 03357 AST_LIST_UNLOCK(&peers); 03358 03359 return 0; 03360 }
static void populate_addr | ( | struct dundi_peer * | peer, | |
dundi_eid * | eid | |||
) | [static] |
Definition at line 4134 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, dundi_peer::registerexpire, and sched.
Referenced by build_peer().
04135 { 04136 char data[256]; 04137 char *c; 04138 int port, expire; 04139 char eid_str[20]; 04140 dundi_eid_to_str(eid_str, sizeof(eid_str), eid); 04141 if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) { 04142 c = strchr(data, ':'); 04143 if (c) { 04144 *c = '\0'; 04145 c++; 04146 if (sscanf(c, "%5d:%30d", &port, &expire) == 2) { 04147 /* Got it! */ 04148 inet_aton(data, &peer->addr.sin_addr); 04149 peer->addr.sin_family = AF_INET; 04150 peer->addr.sin_port = htons(port); 04151 peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer); 04152 } 04153 } 04154 } 04155 }
static int precache_trans | ( | struct dundi_transaction * | trans, | |
struct dundi_mapping * | maps, | |||
int | mapcount, | |||
int * | minexp, | |||
int * | foundanswers | |||
) | [static] |
Definition at line 3159 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().
03160 { 03161 struct dundi_ie_data ied; 03162 int x, res; 03163 int max = 999999; 03164 int expiration = dundi_cache_time; 03165 int ouranswers=0; 03166 dundi_eid *avoid[1] = { NULL, }; 03167 int direct[1] = { 0, }; 03168 struct dundi_result dr[MAX_RESULTS]; 03169 struct dundi_hint_metadata hmd; 03170 if (!trans->parent) { 03171 ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n"); 03172 return -1; 03173 } 03174 memset(&hmd, 0, sizeof(hmd)); 03175 memset(&dr, 0, sizeof(dr)); 03176 /* Look up the answers we're going to include */ 03177 for (x=0;x<mapcount;x++) 03178 ouranswers = dundi_lookup_local(dr, maps + x, trans->parent->number, &trans->us_eid, ouranswers, &hmd); 03179 if (ouranswers < 0) 03180 ouranswers = 0; 03181 for (x=0;x<ouranswers;x++) { 03182 if (dr[x].weight < max) 03183 max = dr[x].weight; 03184 } 03185 if (max) { 03186 /* If we do not have a canonical result, keep looking */ 03187 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); 03188 if (res > 0) { 03189 /* Append answer in result */ 03190 ouranswers += res; 03191 } 03192 } 03193 03194 if (ouranswers > 0) { 03195 *foundanswers += ouranswers; 03196 memset(&ied, 0, sizeof(ied)); 03197 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 03198 if (!dundi_eid_zero(&trans->us_eid)) 03199 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); 03200 for (x=0;x<trans->eidcount;x++) 03201 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]); 03202 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number); 03203 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); 03204 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); 03205 for (x=0;x<ouranswers;x++) { 03206 /* Add answers */ 03207 if (dr[x].expiration && (expiration > dr[x].expiration)) 03208 expiration = dr[x].expiration; 03209 dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest); 03210 } 03211 dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten); 03212 dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration); 03213 if (trans->autokilltimeout) 03214 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); 03215 if (expiration < *minexp) 03216 *minexp = expiration; 03217 return dundi_send(trans, DUNDI_COMMAND_PRECACHERQ, 0, 0, &ied); 03218 } else { 03219 /* Oops, nothing to send... */ 03220 destroy_trans(trans, 0); 03221 return 0; 03222 } 03223 }
static int precache_transactions | ( | struct dundi_request * | dr, | |
struct dundi_mapping * | maps, | |||
int | mapcount, | |||
int * | expiration, | |||
int * | foundanswers | |||
) | [static] |
Definition at line 3258 of file pbx_dundi.c.
References 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_DEBUG, LOG_WARNING, dundi_transaction::parentlist, precache_trans(), and dundi_transaction::thread.
Referenced by dundi_precache_internal().
03259 { 03260 struct dundi_transaction *trans; 03261 03262 /* Mark all as "in thread" so they don't disappear */ 03263 AST_LIST_LOCK(&peers); 03264 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03265 if (trans->thread) 03266 ast_log(LOG_WARNING, "This shouldn't happen, really...\n"); 03267 trans->thread = 1; 03268 } 03269 AST_LIST_UNLOCK(&peers); 03270 03271 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03272 if (!ast_test_flag(trans, FLAG_DEAD)) 03273 precache_trans(trans, maps, mapcount, expiration, foundanswers); 03274 } 03275 03276 /* Cleanup any that got destroyed in the mean time */ 03277 AST_LIST_LOCK(&peers); 03278 AST_LIST_TRAVERSE_SAFE_BEGIN(&dr->trans, trans, parentlist) { 03279 trans->thread = 0; 03280 if (ast_test_flag(trans, FLAG_DEAD)) { 03281 ast_log(LOG_DEBUG, "Our transaction went away!\n"); 03282 /* This is going to remove the transaction from the dundi_request's list, as well 03283 * as the global transactions list */ 03284 destroy_trans(trans, 0); 03285 } 03286 } 03287 AST_LIST_TRAVERSE_SAFE_END 03288 AST_LIST_UNLOCK(&peers); 03289 03290 return 0; 03291 }
static void* process_clearcache | ( | void * | ignore | ) | [static] |
Definition at line 2176 of file pbx_dundi.c.
References ast_db_del(), ast_db_freetree(), ast_db_gettree(), ast_get_time_t(), ast_log(), ast_db_entry::data, expiry, ast_db_entry::key, LOG_DEBUG, ast_db_entry::next, and option_debug.
Referenced by start_network_thread().
02177 { 02178 struct ast_db_entry *db_entry, *db_tree; 02179 int striplen = sizeof("/dundi/cache"); 02180 time_t now; 02181 02182 while (!dundi_shutdown) { 02183 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); 02184 02185 time(&now); 02186 02187 db_entry = db_tree = ast_db_gettree("dundi/cache", NULL); 02188 for (; db_entry; db_entry = db_entry->next) { 02189 time_t expiry; 02190 02191 if (!ast_get_time_t(db_entry->data, &expiry, 0, NULL)) { 02192 if (expiry < now) { 02193 if (option_debug) 02194 ast_log(LOG_DEBUG, "clearing expired DUNDI cache entry: %s\n", db_entry->key); 02195 ast_db_del("dundi/cache", db_entry->key + striplen); 02196 } 02197 } 02198 } 02199 ast_db_freetree(db_tree); 02200 02201 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 02202 pthread_testcancel(); 02203 sleep(60); 02204 pthread_testcancel(); 02205 } 02206 02207 clearcachethreadid = AST_PTHREADT_NULL; 02208 return NULL; 02209 }
static void* process_precache | ( | void * | ign | ) | [static] |
Definition at line 2211 of file pbx_dundi.c.
References ast_copy_string(), 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, free, dundi_precache_queue::list, and dundi_precache_queue::number.
Referenced by start_network_thread().
02212 { 02213 struct dundi_precache_queue *qe; 02214 time_t now; 02215 char context[256]; 02216 char number[256]; 02217 int run; 02218 02219 while (!dundi_shutdown) { 02220 time(&now); 02221 run = 0; 02222 AST_LIST_LOCK(&pcq); 02223 if ((qe = AST_LIST_FIRST(&pcq))) { 02224 if (!qe->expiration) { 02225 /* Gone... Remove... */ 02226 AST_LIST_REMOVE_HEAD(&pcq, list); 02227 free(qe); 02228 } else if (qe->expiration < now) { 02229 /* Process this entry */ 02230 qe->expiration = 0; 02231 ast_copy_string(context, qe->context, sizeof(context)); 02232 ast_copy_string(number, qe->number, sizeof(number)); 02233 run = 1; 02234 } 02235 } 02236 AST_LIST_UNLOCK(&pcq); 02237 if (run) { 02238 dundi_precache(context, number); 02239 } else 02240 sleep(1); 02241 } 02242 02243 precachethreadid = AST_PTHREADT_NULL; 02244 02245 return NULL; 02246 }
static void prune_mappings | ( | void | ) | [static] |
Definition at line 3977 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().
03978 { 03979 struct dundi_mapping *map; 03980 03981 AST_LIST_LOCK(&peers); 03982 AST_LIST_TRAVERSE_SAFE_BEGIN(&mappings, map, list) { 03983 if (map->dead) { 03984 AST_LIST_REMOVE_CURRENT(&mappings, list); 03985 destroy_map(map); 03986 } 03987 } 03988 AST_LIST_TRAVERSE_SAFE_END 03989 AST_LIST_UNLOCK(&peers); 03990 }
static void prune_peers | ( | void | ) | [static] |
Definition at line 3962 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.
03963 { 03964 struct dundi_peer *peer; 03965 03966 AST_LIST_LOCK(&peers); 03967 AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, list) { 03968 if (peer->dead) { 03969 AST_LIST_REMOVE_CURRENT(&peers, list); 03970 destroy_peer(peer); 03971 } 03972 } 03973 AST_LIST_TRAVERSE_SAFE_END 03974 AST_LIST_UNLOCK(&peers); 03975 }
static void qualify_peer | ( | struct dundi_peer * | peer, | |
int | schedonly | |||
) | [static] |
Definition at line 4111 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().
04112 { 04113 int when; 04114 AST_SCHED_DEL(sched, peer->qualifyid); 04115 if (peer->qualtrans) 04116 destroy_trans(peer->qualtrans, 0); 04117 peer->qualtrans = NULL; 04118 if (peer->maxms > 0) { 04119 when = 60000; 04120 if (peer->lastms < 0) 04121 when = 10000; 04122 if (schedonly) 04123 when = 5000; 04124 peer->qualifyid = ast_sched_add(sched, when, do_qualify, peer); 04125 if (!schedonly) 04126 peer->qualtrans = create_transaction(peer); 04127 if (peer->qualtrans) { 04128 peer->qualtx = ast_tvnow(); 04129 ast_set_flag(peer->qualtrans, FLAG_ISQUAL); 04130 dundi_send(peer->qualtrans, DUNDI_COMMAND_NULL, 0, 1, NULL); 04131 } 04132 } 04133 }
static int query_transactions | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3293 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().
03294 { 03295 struct dundi_transaction *trans; 03296 03297 AST_LIST_LOCK(&peers); 03298 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03299 dundi_query(trans); 03300 } 03301 AST_LIST_UNLOCK(&peers); 03302 03303 return 0; 03304 }
static int register_request | ( | struct dundi_request * | dr, | |
struct dundi_request ** | pending | |||
) | [static] |
Definition at line 3474 of file pbx_dundi.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), dundi_request::crc32, dundi_request::dcontext, dr, dundi_eid_cmp(), dundi_eid_to_str(), dundi_request::list, LOG_DEBUG, dundi_request::number, option_debug, and dundi_request::root_eid.
Referenced by dundi_lookup_internal().
03475 { 03476 struct dundi_request *cur; 03477 int res=0; 03478 char eid_str[20]; 03479 AST_LIST_LOCK(&peers); 03480 AST_LIST_TRAVERSE(&requests, cur, list) { 03481 if (option_debug) 03482 ast_log(LOG_DEBUG, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number, 03483 dr->dcontext, dr->number); 03484 if (!strcasecmp(cur->dcontext, dr->dcontext) && 03485 !strcasecmp(cur->number, dr->number) && 03486 (!dundi_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) { 03487 ast_log(LOG_DEBUG, "Found existing query for '%s@%s' for '%s' crc '%08x'\n", 03488 cur->dcontext, cur->number, dundi_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32); 03489 *pending = cur; 03490 res = 1; 03491 break; 03492 } 03493 } 03494 if (!res) { 03495 ast_log(LOG_DEBUG, "Registering request for '%s@%s' on behalf of '%s' crc '%08x'\n", 03496 dr->number, dr->dcontext, dundi_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32); 03497 /* Go ahead and link us in since nobody else is searching for this */ 03498 AST_LIST_INSERT_HEAD(&requests, dr, list); 03499 *pending = NULL; 03500 } 03501 AST_LIST_UNLOCK(&peers); 03502 return res; 03503 }
static int reload | ( | void | ) | [static] |
Definition at line 4615 of file pbx_dundi.c.
References set_config().
04616 { 04617 struct sockaddr_in sin; 04618 set_config("dundi.conf",&sin); 04619 return 0; 04620 }
static void reschedule_precache | ( | const char * | number, | |
const char * | context, | |||
int | expiration | |||
) | [static] |
Definition at line 3654 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().
03655 { 03656 int len; 03657 struct dundi_precache_queue *qe, *prev; 03658 03659 AST_LIST_LOCK(&pcq); 03660 AST_LIST_TRAVERSE_SAFE_BEGIN(&pcq, qe, list) { 03661 if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) { 03662 AST_LIST_REMOVE_CURRENT(&pcq, list); 03663 break; 03664 } 03665 } 03666 AST_LIST_TRAVERSE_SAFE_END 03667 if (!qe) { 03668 len = sizeof(*qe); 03669 len += strlen(number) + 1; 03670 len += strlen(context) + 1; 03671 if (!(qe = ast_calloc(1, len))) { 03672 AST_LIST_UNLOCK(&pcq); 03673 return; 03674 } 03675 strcpy(qe->number, number); 03676 qe->context = qe->number + strlen(number) + 1; 03677 strcpy(qe->context, context); 03678 } 03679 time(&qe->expiration); 03680 qe->expiration += expiration; 03681 if ((prev = AST_LIST_FIRST(&pcq))) { 03682 while (AST_LIST_NEXT(prev, list) && ((AST_LIST_NEXT(prev, list))->expiration <= qe->expiration)) 03683 prev = AST_LIST_NEXT(prev, list); 03684 AST_LIST_INSERT_AFTER(&pcq, prev, qe, list); 03685 } else 03686 AST_LIST_INSERT_HEAD(&pcq, qe, list); 03687 AST_LIST_UNLOCK(&pcq); 03688 }
static int rescomp | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 2366 of file pbx_dundi.c.
References dundi_result::weight.
Referenced by sort_results().
02367 { 02368 const struct dundi_result *resa, *resb; 02369 resa = a; 02370 resb = b; 02371 if (resa->weight < resb->weight) 02372 return -1; 02373 if (resa->weight > resb->weight) 02374 return 1; 02375 return 0; 02376 }
static void reset_global_eid | ( | void | ) | [static] |
Definition at line 405 of file pbx_dundi.c.
References ast_log(), dundi_eid_to_str(), _dundi_eid::eid, global_eid, LOG_DEBUG, and s.
Referenced by set_config().
00406 { 00407 #if defined(SIOCGIFHWADDR) 00408 int x,s; 00409 char eid_str[20]; 00410 struct ifreq ifr; 00411 00412 s = socket(AF_INET, SOCK_STREAM, 0); 00413 if (s > 0) { 00414 x = 0; 00415 for(x=0;x<10;x++) { 00416 memset(&ifr, 0, sizeof(ifr)); 00417 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth%d", x); 00418 if (!ioctl(s, SIOCGIFHWADDR, &ifr)) { 00419 memcpy(&global_eid, ((unsigned char *)&ifr.ifr_hwaddr) + 2, sizeof(global_eid)); 00420 ast_log(LOG_DEBUG, "Seeding global EID '%s' from '%s' using 'siocgifhwaddr'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid), ifr.ifr_name); 00421 close(s); 00422 return; 00423 } 00424 } 00425 close(s); 00426 } 00427 #else 00428 #if defined(ifa_broadaddr) && !defined(SOLARIS) 00429 char eid_str[20]; 00430 struct ifaddrs *ifap; 00431 00432 if (getifaddrs(&ifap) == 0) { 00433 struct ifaddrs *p; 00434 for (p = ifap; p; p = p->ifa_next) { 00435 if ((p->ifa_addr->sa_family == AF_LINK) && !(p->ifa_flags & IFF_LOOPBACK) && (p->ifa_flags & IFF_RUNNING)) { 00436 struct sockaddr_dl* sdp = (struct sockaddr_dl*) p->ifa_addr; 00437 memcpy(&(global_eid.eid), sdp->sdl_data + sdp->sdl_nlen, 6); 00438 ast_log(LOG_DEBUG, "Seeding global EID '%s' from '%s' using 'getifaddrs'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid), p->ifa_name); 00439 freeifaddrs(ifap); 00440 return; 00441 } 00442 } 00443 freeifaddrs(ifap); 00444 } 00445 #endif 00446 #endif 00447 ast_log(LOG_NOTICE, "No ethernet interface found for seeding global EID. You will have to set it manually.\n"); 00448 }
static int reset_transaction | ( | struct dundi_transaction * | trans | ) | [static] |
Definition at line 469 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.
00470 { 00471 int tid; 00472 tid = get_trans_id(); 00473 if (tid < 1) 00474 return -1; 00475 trans->strans = tid; 00476 trans->dtrans = 0; 00477 trans->iseqno = 0; 00478 trans->oiseqno = 0; 00479 trans->oseqno = 0; 00480 trans->aseqno = 0; 00481 ast_clear_flag(trans, FLAG_FINAL); 00482 return 0; 00483 }
static void save_secret | ( | const char * | newkey, | |
const char * | oldkey | |||
) | [static] |
Definition at line 2081 of file pbx_dundi.c.
References ast_db_put(), and DUNDI_SECRET_TIME.
Referenced by check_password(), and load_password().
02082 { 02083 char tmp[256]; 02084 if (oldkey) 02085 snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey); 02086 else 02087 snprintf(tmp, sizeof(tmp), "%s", newkey); 02088 rotatetime = time(NULL) + DUNDI_SECRET_TIME; 02089 ast_db_put(secretpath, "secret", tmp); 02090 snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime); 02091 ast_db_put(secretpath, "secretexpiry", tmp); 02092 }
static int set_config | ( | char * | config_file, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 4422 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_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(), format, global_eid, hp, IPTOS_MINCOST, ast_variable::lineno, load_password(), LOG_ERROR, LOG_NOTICE, mark_mappings(), mark_peers(), ast_variable::name, ast_variable::next, prune_mappings(), prune_peers(), reset_global_eid(), and ast_variable::value.
04423 { 04424 struct ast_config *cfg; 04425 struct ast_variable *v; 04426 char *cat; 04427 int format; 04428 int x; 04429 char hn[MAXHOSTNAMELEN] = ""; 04430 struct ast_hostent he; 04431 struct hostent *hp; 04432 struct sockaddr_in sin2; 04433 static int last_port = 0; 04434 int globalpcmodel = 0; 04435 dundi_eid testeid; 04436 04437 dundi_ttl = DUNDI_DEFAULT_TTL; 04438 dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME; 04439 any_peer = NULL; 04440 04441 cfg = ast_config_load(config_file); 04442 04443 if (!cfg) { 04444 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); 04445 return -1; 04446 } 04447 ipaddr[0] = '\0'; 04448 if (!gethostname(hn, sizeof(hn)-1)) { 04449 hp = ast_gethostbyname(hn, &he); 04450 if (hp) { 04451 memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr)); 04452 ast_copy_string(ipaddr, ast_inet_ntoa(sin2.sin_addr), sizeof(ipaddr)); 04453 } else 04454 ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn); 04455 } else 04456 ast_log(LOG_WARNING, "Unable to get host name!\n"); 04457 AST_LIST_LOCK(&peers); 04458 reset_global_eid(); 04459 global_storehistory = 0; 04460 ast_copy_string(secretpath, "dundi", sizeof(secretpath)); 04461 v = ast_variable_browse(cfg, "general"); 04462 while(v) { 04463 if (!strcasecmp(v->name, "port")){ 04464 sin->sin_port = ntohs(atoi(v->value)); 04465 if(last_port==0){ 04466 last_port=sin->sin_port; 04467 } else if(sin->sin_port != last_port) 04468 ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n"); 04469 } else if (!strcasecmp(v->name, "bindaddr")) { 04470 struct hostent *hp; 04471 struct ast_hostent he; 04472 hp = ast_gethostbyname(v->value, &he); 04473 if (hp) { 04474 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 04475 } else 04476 ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value); 04477 } else if (!strcasecmp(v->name, "authdebug")) { 04478 authdebug = ast_true(v->value); 04479 } else if (!strcasecmp(v->name, "ttl")) { 04480 if ((sscanf(v->value, "%30d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) { 04481 dundi_ttl = x; 04482 } else { 04483 ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n", 04484 v->value, v->lineno, DUNDI_DEFAULT_TTL); 04485 } 04486 } else if (!strcasecmp(v->name, "autokill")) { 04487 if (sscanf(v->value, "%30d", &x) == 1) { 04488 if (x >= 0) 04489 global_autokilltimeout = x; 04490 else 04491 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); 04492 } else if (ast_true(v->value)) { 04493 global_autokilltimeout = DEFAULT_MAXMS; 04494 } else { 04495 global_autokilltimeout = 0; 04496 } 04497 } else if (!strcasecmp(v->name, "entityid")) { 04498 if (!dundi_str_to_eid(&testeid, v->value)) 04499 global_eid = testeid; 04500 else 04501 ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno); 04502 } else if (!strcasecmp(v->name, "tos")) { 04503 if (sscanf(v->value, "%30d", &format) == 1) 04504 tos = format & 0xff; 04505 else if (!strcasecmp(v->value, "lowdelay")) 04506 tos = IPTOS_LOWDELAY; 04507 else if (!strcasecmp(v->value, "throughput")) 04508 tos = IPTOS_THROUGHPUT; 04509 else if (!strcasecmp(v->value, "reliability")) 04510 tos = IPTOS_RELIABILITY; 04511 #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS) 04512 else if (!strcasecmp(v->value, "mincost")) 04513 tos = IPTOS_MINCOST; 04514 #endif 04515 else if (!strcasecmp(v->value, "none")) 04516 tos = 0; 04517 else 04518 #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS) 04519 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno); 04520 #else 04521 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', or 'none'\n", v->lineno); 04522 #endif 04523 } else if (!strcasecmp(v->name, "department")) { 04524 ast_copy_string(dept, v->value, sizeof(dept)); 04525 } else if (!strcasecmp(v->name, "organization")) { 04526 ast_copy_string(org, v->value, sizeof(org)); 04527 } else if (!strcasecmp(v->name, "locality")) { 04528 ast_copy_string(locality, v->value, sizeof(locality)); 04529 } else if (!strcasecmp(v->name, "stateprov")) { 04530 ast_copy_string(stateprov, v->value, sizeof(stateprov)); 04531 } else if (!strcasecmp(v->name, "country")) { 04532 ast_copy_string(country, v->value, sizeof(country)); 04533 } else if (!strcasecmp(v->name, "email")) { 04534 ast_copy_string(email, v->value, sizeof(email)); 04535 } else if (!strcasecmp(v->name, "phone")) { 04536 ast_copy_string(phone, v->value, sizeof(phone)); 04537 } else if (!strcasecmp(v->name, "storehistory")) { 04538 global_storehistory = ast_true(v->value); 04539 } else if (!strcasecmp(v->name, "cachetime")) { 04540 if ((sscanf(v->value, "%30d", &x) == 1)) { 04541 dundi_cache_time = x; 04542 } else { 04543 ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n", 04544 v->value, v->lineno, DUNDI_DEFAULT_CACHE_TIME); 04545 } 04546 } 04547 v = v->next; 04548 } 04549 AST_LIST_UNLOCK(&peers); 04550 mark_mappings(); 04551 v = ast_variable_browse(cfg, "mappings"); 04552 while(v) { 04553 build_mapping(v->name, v->value); 04554 v = v->next; 04555 } 04556 prune_mappings(); 04557 mark_peers(); 04558 cat = ast_category_browse(cfg, NULL); 04559 while(cat) { 04560 if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) { 04561 /* Entries */ 04562 if (!dundi_str_to_eid(&testeid, cat)) 04563 build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel); 04564 else if (!strcasecmp(cat, "*")) { 04565 build_peer(&empty_eid, ast_variable_browse(cfg, cat), &globalpcmodel); 04566 any_peer = find_peer(NULL); 04567 } else 04568 ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat); 04569 } 04570 cat = ast_category_browse(cfg, cat); 04571 } 04572 prune_peers(); 04573 ast_config_destroy(cfg); 04574 load_password(); 04575 if (globalpcmodel & DUNDI_MODEL_OUTBOUND) 04576 dundi_precache_full(); 04577 return 0; 04578 }
static int socket_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 2038 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), dundi_showframe(), errno, handle_frame(), len(), LOG_WARNING, and MAX_PACKET_SIZE.
02039 { 02040 struct sockaddr_in sin; 02041 int res; 02042 struct dundi_hdr *h; 02043 char buf[MAX_PACKET_SIZE]; 02044 socklen_t len; 02045 len = sizeof(sin); 02046 res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len); 02047 if (res < 0) { 02048 if (errno != ECONNREFUSED) 02049 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); 02050 return 1; 02051 } 02052 if (res < sizeof(struct dundi_hdr)) { 02053 ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct dundi_hdr)); 02054 return 1; 02055 } 02056 buf[res] = '\0'; 02057 h = (struct dundi_hdr *)buf; 02058 if (dundidebug) 02059 dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr)); 02060 AST_LIST_LOCK(&peers); 02061 handle_frame(h, &sin, res - sizeof(struct dundi_hdr)); 02062 AST_LIST_UNLOCK(&peers); 02063 return 1; 02064 }
static void sort_results | ( | struct dundi_result * | results, | |
int | count | |||
) | [static] |
Definition at line 2378 of file pbx_dundi.c.
References rescomp().
Referenced by dundi_do_lookup(), dundi_exec(), and dundifunc_read().
02379 { 02380 qsort(results, count, sizeof(results[0]), rescomp); 02381 }
static int start_network_thread | ( | void | ) | [static] |
Definition at line 2248 of file pbx_dundi.c.
References ast_pthread_create_background, network_thread(), process_clearcache(), and process_precache().
02249 { 02250 ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); 02251 ast_pthread_create_background(&precachethreadid, NULL, process_precache, NULL); 02252 ast_pthread_create_background(&clearcachethreadid, NULL, process_clearcache, NULL); 02253 return 0; 02254 }
static int str2tech | ( | char * | str | ) | [static] |
Definition at line 320 of file pbx_dundi.c.
References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, and DUNDI_PROTO_SIP.
Referenced by build_mapping().
00321 { 00322 if (!strcasecmp(str, "IAX") || !strcasecmp(str, "IAX2")) 00323 return DUNDI_PROTO_IAX; 00324 else if (!strcasecmp(str, "SIP")) 00325 return DUNDI_PROTO_SIP; 00326 else if (!strcasecmp(str, "H323")) 00327 return DUNDI_PROTO_H323; 00328 else 00329 return -1; 00330 }
static char* tech2str | ( | int | tech | ) | [static] |
Definition at line 304 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().
00305 { 00306 switch(tech) { 00307 case DUNDI_PROTO_NONE: 00308 return "None"; 00309 case DUNDI_PROTO_IAX: 00310 return "IAX2"; 00311 case DUNDI_PROTO_SIP: 00312 return "SIP"; 00313 case DUNDI_PROTO_H323: 00314 return "H323"; 00315 default: 00316 return "Unknown"; 00317 } 00318 }
static int unload_module | ( | void | ) | [static] |
Definition at line 4580 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_switch, io, io_context_destroy(), mark_mappings(), mark_peers(), prune_mappings(), prune_peers(), sched, and sched_context_destroy().
04581 { 04582 pthread_t previous_netthreadid = netthreadid, previous_precachethreadid = precachethreadid, previous_clearcachethreadid = clearcachethreadid; 04583 ast_module_user_hangup_all(); 04584 04585 /* Stop all currently running threads */ 04586 dundi_shutdown = 1; 04587 if (previous_netthreadid != AST_PTHREADT_NULL) { 04588 pthread_kill(previous_netthreadid, SIGURG); 04589 pthread_join(previous_netthreadid, NULL); 04590 } 04591 if (previous_precachethreadid != AST_PTHREADT_NULL) { 04592 pthread_kill(previous_precachethreadid, SIGURG); 04593 pthread_join(previous_precachethreadid, NULL); 04594 } 04595 if (previous_clearcachethreadid != AST_PTHREADT_NULL) { 04596 pthread_cancel(previous_clearcachethreadid); 04597 pthread_join(previous_clearcachethreadid, NULL); 04598 } 04599 04600 ast_cli_unregister_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(struct ast_cli_entry)); 04601 ast_unregister_switch(&dundi_switch); 04602 ast_custom_function_unregister(&dundi_function); 04603 close(netsocket); 04604 io_context_destroy(io); 04605 sched_context_destroy(sched); 04606 04607 mark_mappings(); 04608 prune_mappings(); 04609 mark_peers(); 04610 prune_peers(); 04611 04612 return 0; 04613 }
static void unregister_request | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3505 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().
03506 { 03507 AST_LIST_LOCK(&peers); 03508 AST_LIST_REMOVE(&requests, dr, list); 03509 AST_LIST_UNLOCK(&peers); 03510 }
static int update_key | ( | struct dundi_peer * | peer | ) | [static] |
Definition at line 1289 of file pbx_dundi.c.
References aes_decrypt_key128(), aes_encrypt_key128(), 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().
01290 { 01291 unsigned char key[16]; 01292 struct ast_key *ekey, *skey; 01293 char eid_str[20]; 01294 int res; 01295 if (!peer->keyexpire || (peer->keyexpire < time(NULL))) { 01296 build_iv(key); 01297 aes_encrypt_key128(key, &peer->us_ecx); 01298 aes_decrypt_key128(key, &peer->us_dcx); 01299 ekey = ast_key_get(peer->inkey, AST_KEY_PUBLIC); 01300 if (!ekey) { 01301 ast_log(LOG_NOTICE, "No such key '%s' for creating RSA encrypted shared key for '%s'!\n", 01302 peer->inkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01303 return -1; 01304 } 01305 skey = ast_key_get(peer->outkey, AST_KEY_PRIVATE); 01306 if (!skey) { 01307 ast_log(LOG_NOTICE, "No such key '%s' for signing RSA encrypted shared key for '%s'!\n", 01308 peer->outkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01309 return -1; 01310 } 01311 if ((res = ast_encrypt_bin(peer->txenckey, key, sizeof(key), ekey)) != 128) { 01312 ast_log(LOG_NOTICE, "Whoa, got a weird encrypt size (%d != %d)!\n", res, 128); 01313 return -1; 01314 } 01315 if ((res = ast_sign_bin(skey, (char *)peer->txenckey, 128, peer->txenckey + 128))) { 01316 ast_log(LOG_NOTICE, "Failed to sign key (%d)!\n", res); 01317 return -1; 01318 } 01319 peer->us_keycrc32 = crc32(0L, peer->txenckey, 128); 01320 peer->sentfullkey = 0; 01321 /* Looks good */ 01322 time(&peer->keyexpire); 01323 peer->keyexpire += dundi_key_ttl; 01324 } 01325 return 0; 01326 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 4685 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 276 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 4685 of file pbx_dundi.c.
int authdebug = 0 [static] |
Definition at line 118 of file pbx_dundi.c.
pthread_t clearcachethreadid = AST_PTHREADT_NULL [static] |
Definition at line 115 of file pbx_dundi.c.
struct ast_cli_entry cli_dundi[] [static] |
char country[80] [static] |
Definition at line 130 of file pbx_dundi.c.
Referenced by handle_mfcr2_show_variants(), and ind_load_module().
char cursecret[80] [static] |
Definition at line 134 of file pbx_dundi.c.
char debug_usage[] [static] |
Initial value:
"Usage: dundi debug\n" " Enables dumping of DUNDi packets for debugging purposes\n"
Definition at line 2738 of file pbx_dundi.c.
int default_expiration = 60 [static] |
Definition at line 124 of file pbx_dundi.c.
char dept[80] [static] |
Definition at line 126 of file pbx_dundi.c.
int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME [static] |
Definition at line 121 of file pbx_dundi.c.
int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE [static] |
Definition at line 120 of file pbx_dundi.c.
int dundi_shutdown = 0 [static] |
Definition at line 138 of file pbx_dundi.c.
struct ast_switch dundi_switch [static] |
int dundi_ttl = DUNDI_DEFAULT_TTL [static] |
Definition at line 119 of file pbx_dundi.c.
int dundidebug = 0 [static] |
Definition at line 117 of file pbx_dundi.c.
char email[80] [static] |
Definition at line 131 of file pbx_dundi.c.
char flush_usage[] [static] |
Initial value:
"Usage: dundi flush [stats]\n" " Flushes DUNDi answer cache, used primarily for debug. If\n" "'stats' is present, clears timer statistics instead of normal\n" "operation.\n"
Definition at line 2802 of file pbx_dundi.c.
int global_autokilltimeout = 0 [static] |
Definition at line 122 of file pbx_dundi.c.
dundi_eid global_eid [static] |
Definition at line 123 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 125 of file pbx_dundi.c.
struct io_context* io [static] |
Definition at line 110 of file pbx_dundi.c.
char ipaddr[80] [static] |
char locality[80] [static] |
Definition at line 128 of file pbx_dundi.c.
char lookup_usage[] [static] |
Initial value:
"Usage: dundi lookup <number>[@context] [bypass]\n" " Lookup the given number within the given DUNDi context\n" "(or e164 if none is specified). Bypasses cache if 'bypass'\n" "keyword is specified.\n"
Definition at line 2784 of file pbx_dundi.c.
int netsocket = -1 [static] |
Definition at line 112 of file pbx_dundi.c.
Referenced by ast_netsock_bindaddr(), and handle_error().
pthread_t netthreadid = AST_PTHREADT_NULL [static] |
Definition at line 113 of file pbx_dundi.c.
char no_debug_usage[] [static] |
Initial value:
"Usage: dundi no debug\n" " Disables dumping of DUNDi packets for debugging purposes\n"
Definition at line 2742 of file pbx_dundi.c.
char no_store_history_usage[] [static] |
Initial value:
"Usage: dundi no store history\n" " Disables storing of DUNDi requests and times for debugging\n" "purposes\n"
Definition at line 2751 of file pbx_dundi.c.
char org[80] [static] |
char phone[80] [static] |
char precache_usage[] [static] |
Initial value:
"Usage: dundi precache <number>[@context]\n" " Lookup the given number within the given DUNDi context\n" "(or e164 if none is specified) and precaches the results to any\n" "upstream DUNDi push servers.\n"
Definition at line 2790 of file pbx_dundi.c.
pthread_t precachethreadid = AST_PTHREADT_NULL [static] |
Definition at line 114 of file pbx_dundi.c.
char query_usage[] [static] |
Initial value:
"Usage: dundi query <entity>[@context]\n" " Attempts to retrieve contact information for a specific\n" "DUNDi entity identifier (EID) within a given DUNDi context (or\n" "e164 if none is specified).\n"
Definition at line 2796 of file pbx_dundi.c.
time_t rotatetime [static] |
Definition at line 136 of file pbx_dundi.c.
struct sched_context* sched [static] |
Definition at line 111 of file pbx_dundi.c.
char secretpath[80] [static] |
Definition at line 133 of file pbx_dundi.c.
char show_entityid_usage[] [static] |
Initial value:
"Usage: dundi show entityid\n" " Displays the global entityid for this host.\n"
Definition at line 2772 of file pbx_dundi.c.
char show_mappings_usage[] [static] |
Initial value:
"Usage: dundi show mappings\n" " Lists all known DUNDi mappings.\n"
Definition at line 2764 of file pbx_dundi.c.
char show_peer_usage[] [static] |
Initial value:
"Usage: dundi show peer [peer]\n" " Provide a detailed description of a specifid DUNDi peer.\n"
Definition at line 2776 of file pbx_dundi.c.
char show_peers_usage[] [static] |
Initial value:
"Usage: dundi show peers\n" " Lists all known DUNDi peers.\n"
Definition at line 2756 of file pbx_dundi.c.
char show_precache_usage[] [static] |
Initial value:
"Usage: dundi show precache\n" " Lists all known DUNDi scheduled precache updates.\n"
Definition at line 2768 of file pbx_dundi.c.
char show_requests_usage[] [static] |
Initial value:
"Usage: dundi show requests\n" " Lists all known pending DUNDi requests.\n"
Definition at line 2780 of file pbx_dundi.c.
char show_trans_usage[] [static] |
Initial value:
"Usage: dundi show trans\n" " Lists all known DUNDi transactions.\n"
Definition at line 2760 of file pbx_dundi.c.
char stateprov[80] [static] |
Definition at line 129 of file pbx_dundi.c.
char store_history_usage[] [static] |
Initial value:
"Usage: dundi store history\n" " Enables storing of DUNDi requests and times for debugging\n" "purposes\n"
Definition at line 2746 of file pbx_dundi.c.
int tos = 0 [static] |
Definition at line 116 of file pbx_dundi.c.