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