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