#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 3364 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().
03365 { 03366 struct dundi_transaction *trans; 03367 03368 AST_LIST_LOCK(&peers); 03369 while ((trans = AST_LIST_FIRST(&dr->trans))) { 03370 /* This will remove the transaction from the list */ 03371 destroy_trans(trans, 0); 03372 } 03373 AST_LIST_UNLOCK(&peers); 03374 }
static int ack_trans | ( | struct dundi_transaction * | trans, | |
int | iseqno | |||
) | [static] |
Definition at line 1974 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().
01975 { 01976 struct dundi_packet *pack; 01977 01978 /* Ack transmitted packet corresponding to iseqno */ 01979 AST_LIST_TRAVERSE(&trans->packets, pack, list) { 01980 if ((pack->h->oseqno + 1) % 255 == iseqno) { 01981 destroy_packet(pack, 0); 01982 if (!AST_LIST_EMPTY(&trans->lasttrans)) { 01983 ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n"); 01984 destroy_packets(&trans->lasttrans); 01985 } 01986 AST_LIST_INSERT_HEAD(&trans->lasttrans, pack, list); 01987 AST_SCHED_DEL(sched, trans->autokillid); 01988 return 1; 01989 } 01990 } 01991 01992 return 0; 01993 }
static void append_permission | ( | struct permissionlist * | permlist, | |
char * | s, | |||
int | allow | |||
) | [static] |
Definition at line 3948 of file pbx_dundi.c.
References ast_calloc, and AST_LIST_INSERT_TAIL.
03949 { 03950 struct permission *perm; 03951 03952 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(s) + 1))) 03953 return; 03954 03955 strcpy(perm->name, s); 03956 perm->allow = allow; 03957 03958 AST_LIST_INSERT_TAIL(permlist, perm, list); 03959 }
static int append_transaction | ( | struct dundi_request * | dr, | |
struct dundi_peer * | p, | |||
int | ttl, | |||
dundi_eid * | avoid[] | |||
) | [static] |
Definition at line 3321 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().
03322 { 03323 struct dundi_transaction *trans; 03324 int x; 03325 char eid_str[20]; 03326 char eid_str2[20]; 03327 03328 /* Ignore if not registered */ 03329 if (!p->addr.sin_addr.s_addr) 03330 return 0; 03331 if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms))) 03332 return 0; 03333 if (ast_strlen_zero(dr->number)) 03334 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); 03335 else 03336 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); 03337 trans = create_transaction(p); 03338 if (!trans) 03339 return -1; 03340 trans->parent = dr; 03341 trans->ttl = ttl; 03342 for (x = 0; avoid[x] && (x < DUNDI_MAX_STACK); x++) 03343 trans->eids[x] = *avoid[x]; 03344 trans->eidcount = x; 03345 AST_LIST_INSERT_HEAD(&dr->trans, trans, parentlist); 03346 03347 return 0; 03348 }
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 3485 of file pbx_dundi.c.
References dundi_request::crc32.
Referenced by dundi_lookup_internal().
03486 { 03487 /* Idea is that we're calculating a checksum which is independent of 03488 the order that the EID's are listed in */ 03489 unsigned long acrc32 = 0; 03490 int x; 03491 for (x=0;avoid[x];x++) { 03492 /* Order doesn't matter */ 03493 if (avoid[x+1]) { 03494 acrc32 ^= crc32(0L, (unsigned char *)avoid[x], sizeof(dundi_eid)); 03495 } 03496 } 03497 return acrc32; 03498 }
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 3963 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().
03964 { 03965 char *t, *fields[MAX_OPTS]; 03966 struct dundi_mapping *map; 03967 int x; 03968 int y; 03969 03970 t = ast_strdupa(value); 03971 03972 AST_LIST_TRAVERSE(&mappings, map, list) { 03973 /* Find a double match */ 03974 if (!strcasecmp(map->dcontext, name) && 03975 (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) && 03976 (!value[strlen(map->lcontext)] || 03977 (value[strlen(map->lcontext)] == ',')))) 03978 break; 03979 } 03980 if (!map) { 03981 if (!(map = ast_calloc(1, sizeof(*map)))) 03982 return; 03983 AST_LIST_INSERT_HEAD(&mappings, map, list); 03984 map->dead = 1; 03985 } 03986 map->options = 0; 03987 memset(fields, 0, sizeof(fields)); 03988 x = 0; 03989 while (t && x < MAX_OPTS) { 03990 fields[x++] = t; 03991 t = strchr(t, ','); 03992 if (t) { 03993 *t = '\0'; 03994 t++; 03995 } 03996 } /* Russell was here, arrrr! */ 03997 if ((x == 1) && ast_strlen_zero(fields[0])) { 03998 /* Placeholder mapping */ 03999 ast_copy_string(map->dcontext, name, sizeof(map->dcontext)); 04000 map->dead = 0; 04001 } else if (x >= 4) { 04002 ast_copy_string(map->dcontext, name, sizeof(map->dcontext)); 04003 ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext)); 04004 if ((sscanf(fields[1], "%d", &map->weight) == 1) && (map->weight >= 0) && (map->weight < 60000)) { 04005 ast_copy_string(map->dest, fields[3], sizeof(map->dest)); 04006 if ((map->tech = str2tech(fields[2]))) { 04007 map->dead = 0; 04008 } 04009 } else { 04010 ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext); 04011 } 04012 for (y = 4;y < x; y++) { 04013 if (!strcasecmp(fields[y], "nounsolicited")) 04014 map->options |= DUNDI_FLAG_NOUNSOLICITED; 04015 else if (!strcasecmp(fields[y], "nocomunsolicit")) 04016 map->options |= DUNDI_FLAG_NOCOMUNSOLICIT; 04017 else if (!strcasecmp(fields[y], "residential")) 04018 map->options |= DUNDI_FLAG_RESIDENTIAL; 04019 else if (!strcasecmp(fields[y], "commercial")) 04020 map->options |= DUNDI_FLAG_COMMERCIAL; 04021 else if (!strcasecmp(fields[y], "mobile")) 04022 map->options |= DUNDI_FLAG_MOBILE; 04023 else if (!strcasecmp(fields[y], "nopartial")) 04024 map->options |= DUNDI_FLAG_INTERNAL_NOPARTIAL; 04025 else 04026 ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]); 04027 } 04028 } else 04029 ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x); 04030 }
static void build_peer | ( | dundi_eid * | eid, | |
struct ast_variable * | v, | |||
int * | globalpcmode | |||
) | [static] |
Definition at line 4114 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.
04115 { 04116 struct dundi_peer *peer; 04117 struct ast_hostent he; 04118 struct hostent *hp; 04119 dundi_eid testeid; 04120 int needregister=0; 04121 char eid_str[20]; 04122 04123 AST_LIST_LOCK(&peers); 04124 AST_LIST_TRAVERSE(&peers, peer, list) { 04125 if (!dundi_eid_cmp(&peer->eid, eid)) { 04126 break; 04127 } 04128 } 04129 if (!peer) { 04130 /* Add us into the list */ 04131 if (!(peer = ast_calloc(1, sizeof(*peer)))) { 04132 AST_LIST_UNLOCK(&peers); 04133 return; 04134 } 04135 peer->registerid = -1; 04136 peer->registerexpire = -1; 04137 peer->qualifyid = -1; 04138 peer->addr.sin_family = AF_INET; 04139 peer->addr.sin_port = htons(DUNDI_PORT); 04140 populate_addr(peer, eid); 04141 AST_LIST_INSERT_HEAD(&peers, peer, list); 04142 } 04143 peer->dead = 0; 04144 peer->eid = *eid; 04145 peer->us_eid = global_eid; 04146 destroy_permissions(&peer->permit); 04147 destroy_permissions(&peer->include); 04148 AST_SCHED_DEL(sched, peer->registerid); 04149 for (; v; v = v->next) { 04150 if (!strcasecmp(v->name, "inkey")) { 04151 ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey)); 04152 } else if (!strcasecmp(v->name, "outkey")) { 04153 ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey)); 04154 } else if (!strcasecmp(v->name, "host")) { 04155 if (!strcasecmp(v->value, "dynamic")) { 04156 peer->dynamic = 1; 04157 } else { 04158 hp = ast_gethostbyname(v->value, &he); 04159 if (hp) { 04160 memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr)); 04161 peer->dynamic = 0; 04162 } else { 04163 ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno); 04164 peer->dead = 1; 04165 } 04166 } 04167 } else if (!strcasecmp(v->name, "ustothem")) { 04168 if (!dundi_str_to_eid(&testeid, v->value)) 04169 peer->us_eid = testeid; 04170 else 04171 ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno); 04172 } else if (!strcasecmp(v->name, "include")) { 04173 append_permission(&peer->include, v->value, 1); 04174 } else if (!strcasecmp(v->name, "permit")) { 04175 append_permission(&peer->permit, v->value, 1); 04176 } else if (!strcasecmp(v->name, "noinclude")) { 04177 append_permission(&peer->include, v->value, 0); 04178 } else if (!strcasecmp(v->name, "deny")) { 04179 append_permission(&peer->permit, v->value, 0); 04180 } else if (!strcasecmp(v->name, "register")) { 04181 needregister = ast_true(v->value); 04182 } else if (!strcasecmp(v->name, "order")) { 04183 if (!strcasecmp(v->value, "primary")) 04184 peer->order = 0; 04185 else if (!strcasecmp(v->value, "secondary")) 04186 peer->order = 1; 04187 else if (!strcasecmp(v->value, "tertiary")) 04188 peer->order = 2; 04189 else if (!strcasecmp(v->value, "quartiary")) 04190 peer->order = 3; 04191 else { 04192 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); 04193 } 04194 } else if (!strcasecmp(v->name, "qualify")) { 04195 if (!strcasecmp(v->value, "no")) { 04196 peer->maxms = 0; 04197 } else if (!strcasecmp(v->value, "yes")) { 04198 peer->maxms = DEFAULT_MAXMS; 04199 } else if (sscanf(v->value, "%d", &peer->maxms) != 1) { 04200 ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n", 04201 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno); 04202 peer->maxms = 0; 04203 } 04204 } else if (!strcasecmp(v->name, "model")) { 04205 if (!strcasecmp(v->value, "inbound")) 04206 peer->model = DUNDI_MODEL_INBOUND; 04207 else if (!strcasecmp(v->value, "outbound")) 04208 peer->model = DUNDI_MODEL_OUTBOUND; 04209 else if (!strcasecmp(v->value, "symmetric")) 04210 peer->model = DUNDI_MODEL_SYMMETRIC; 04211 else if (!strcasecmp(v->value, "none")) 04212 peer->model = 0; 04213 else { 04214 ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 04215 v->value, v->lineno); 04216 } 04217 } else if (!strcasecmp(v->name, "precache")) { 04218 if (!strcasecmp(v->value, "inbound")) 04219 peer->pcmodel = DUNDI_MODEL_INBOUND; 04220 else if (!strcasecmp(v->value, "outbound")) 04221 peer->pcmodel = DUNDI_MODEL_OUTBOUND; 04222 else if (!strcasecmp(v->value, "symmetric")) 04223 peer->pcmodel = DUNDI_MODEL_SYMMETRIC; 04224 else if (!strcasecmp(v->value, "none")) 04225 peer->pcmodel = 0; 04226 else { 04227 ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 04228 v->value, v->lineno); 04229 } 04230 } 04231 } 04232 (*globalpcmode) |= peer->pcmodel; 04233 if (!peer->model && !peer->pcmodel) { 04234 ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n", 04235 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04236 peer->dead = 1; 04237 } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) { 04238 ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n", 04239 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04240 peer->dead = 1; 04241 } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) { 04242 ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n", 04243 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04244 peer->dead = 1; 04245 } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) { 04246 ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n", 04247 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04248 } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) { 04249 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", 04250 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04251 } else { 04252 if (needregister) { 04253 peer->registerid = ast_sched_add(sched, 2000, do_register, peer); 04254 } 04255 qualify_peer(peer, 1); 04256 } 04257 AST_LIST_UNLOCK(&peers); 04258 }
static void build_secret | ( | char * | secret, | |
int | seclen | |||
) | [static] |
Definition at line 2064 of file pbx_dundi.c.
References ast_base64encode(), build_iv(), and s.
Referenced by check_password(), and load_password().
02065 { 02066 unsigned char tmp[16]; 02067 char *s; 02068 build_iv(tmp); 02069 secret[0] = '\0'; 02070 ast_base64encode(secret, tmp, sizeof(tmp), seclen); 02071 /* Eliminate potential bad characters */ 02072 while((s = strchr(secret, ';'))) *s = '+'; 02073 while((s = strchr(secret, '/'))) *s = '+'; 02074 while((s = strchr(secret, ':'))) *s = '+'; 02075 while((s = strchr(secret, '@'))) *s = '+'; 02076 }
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 3376 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().
03377 { 03378 struct dundi_peer *p; 03379 int x; 03380 int res; 03381 int pass; 03382 int allowconnect; 03383 char eid_str[20]; 03384 AST_LIST_LOCK(&peers); 03385 AST_LIST_TRAVERSE(&peers, p, list) { 03386 if (modeselect == 1) { 03387 /* Send the precache to push upstreams only! */ 03388 pass = has_permission(&p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND); 03389 allowconnect = 1; 03390 } else { 03391 /* Normal lookup / EID query */ 03392 pass = has_permission(&p->include, dr->dcontext); 03393 allowconnect = p->model & DUNDI_MODEL_OUTBOUND; 03394 } 03395 if (skip) { 03396 if (!dundi_eid_cmp(skip, &p->eid)) 03397 pass = 0; 03398 } 03399 if (pass) { 03400 if (p->order <= order) { 03401 /* Check order first, then check cache, regardless of 03402 omissions, this gets us more likely to not have an 03403 affected answer. */ 03404 if((nocache || !(res = cache_lookup(dr, &p->eid, dr->crc32, &dr->expiration)))) { 03405 res = 0; 03406 /* Make sure we haven't already seen it and that it won't 03407 affect our answer */ 03408 for (x=0;avoid[x];x++) { 03409 if (!dundi_eid_cmp(avoid[x], &p->eid) || !dundi_eid_cmp(avoid[x], &p->us_eid)) { 03410 /* If not a direct connection, it affects our answer */ 03411 if (directs && !directs[x]) 03412 ast_clear_flag_nonstd(dr->hmd, DUNDI_HINT_UNAFFECTED); 03413 break; 03414 } 03415 } 03416 /* Make sure we can ask */ 03417 if (allowconnect) { 03418 if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) { 03419 /* Check for a matching or 0 cache entry */ 03420 append_transaction(dr, p, ttl, avoid); 03421 } else 03422 ast_log(LOG_DEBUG, "Avoiding '%s' in transaction\n", dundi_eid_to_str(eid_str, sizeof(eid_str), avoid[x])); 03423 } 03424 } 03425 *foundcache |= res; 03426 } else if (!*skipped || (p->order < *skipped)) 03427 *skipped = p->order; 03428 } 03429 } 03430 AST_LIST_UNLOCK(&peers); 03431 }
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 3350 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().
03351 { 03352 struct dundi_transaction *trans; 03353 03354 AST_LIST_LOCK(&peers); 03355 while ((trans = AST_LIST_REMOVE_HEAD(&dr->trans, parentlist))) { 03356 /* Orphan transaction from request */ 03357 trans->parent = NULL; 03358 /* Send final cancel */ 03359 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 03360 } 03361 AST_LIST_UNLOCK(&peers); 03362 }
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 2131 of file pbx_dundi.c.
References build_secret(), and save_secret().
Referenced by network_thread().
02132 { 02133 char oldsecret[80]; 02134 time_t now; 02135 02136 time(&now); 02137 #if 0 02138 printf("%ld/%ld\n", now, rotatetime); 02139 #endif 02140 if ((now - rotatetime) >= 0) { 02141 /* Time to rotate keys */ 02142 ast_copy_string(oldsecret, cursecret, sizeof(oldsecret)); 02143 build_secret(cursecret, sizeof(cursecret)); 02144 save_secret(cursecret, oldsecret); 02145 } 02146 }
static int check_request | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3471 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dr, and peers.
Referenced by dundi_lookup_internal().
03472 { 03473 struct dundi_request *cur; 03474 03475 AST_LIST_LOCK(&peers); 03476 AST_LIST_TRAVERSE(&requests, cur, list) { 03477 if (cur == dr) 03478 break; 03479 } 03480 AST_LIST_UNLOCK(&peers); 03481 03482 return cur ? 1 : 0; 03483 }
static char* complete_peer_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 2323 of file pbx_dundi.c.
References complete_peer_helper().
02324 { 02325 return complete_peer_helper(line, word, pos, state, 3); 02326 }
static char* complete_peer_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 2301 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().
02302 { 02303 int which=0, len; 02304 char *ret = NULL; 02305 struct dundi_peer *p; 02306 char eid_str[20]; 02307 02308 if (pos != rpos) 02309 return NULL; 02310 AST_LIST_LOCK(&peers); 02311 len = strlen(word); 02312 AST_LIST_TRAVERSE(&peers, p, list) { 02313 const char *s = dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid); 02314 if (!strncasecmp(word, s, len) && ++which > state) { 02315 ret = ast_strdup(s); 02316 break; 02317 } 02318 } 02319 AST_LIST_UNLOCK(&peers); 02320 return ret; 02321 }
static struct dundi_transaction * create_transaction | ( | struct dundi_peer * | p | ) | [static] |
Definition at line 2831 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().
02832 { 02833 struct dundi_transaction *trans; 02834 int tid; 02835 02836 /* Don't allow creation of transactions to non-registered peers */ 02837 if (p && !p->addr.sin_addr.s_addr) 02838 return NULL; 02839 tid = get_trans_id(); 02840 if (tid < 1) 02841 return NULL; 02842 trans = ast_calloc(1, sizeof(*trans)); 02843 if (trans) { 02844 if (global_storehistory) { 02845 trans->start = ast_tvnow(); 02846 ast_set_flag(trans, FLAG_STOREHIST); 02847 } 02848 trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; 02849 trans->autokillid = -1; 02850 if (p) { 02851 apply_peer(trans, p); 02852 if (!p->sentfullkey) 02853 ast_set_flag(trans, FLAG_SENDFULLKEY); 02854 } 02855 trans->strans = tid; 02856 AST_LIST_INSERT_HEAD(&alltrans, trans, all); 02857 } 02858 return trans; 02859 }
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 2877 of file pbx_dundi.c.
References AST_LIST_REMOVE, AST_SCHED_DEL, free, and sched.
Referenced by ack_trans().
02878 { 02879 if (pack->parent) 02880 AST_LIST_REMOVE(&pack->parent->packets, pack, list); 02881 AST_SCHED_DEL(sched, pack->retransid); 02882 if (needfree) 02883 free(pack); 02884 }
static void destroy_packets | ( | struct packetlist * | p | ) | [static] |
Definition at line 1963 of file pbx_dundi.c.
References AST_LIST_REMOVE_HEAD, AST_SCHED_DEL, free, and sched.
Referenced by ack_trans(), and handle_frame().
01964 { 01965 struct dundi_packet *pack; 01966 01967 while ((pack = AST_LIST_REMOVE_HEAD(p, list))) { 01968 AST_SCHED_DEL(sched, pack->retransid); 01969 free(pack); 01970 } 01971 }
static void destroy_peer | ( | struct dundi_peer * | peer | ) | [static] |
Definition at line 3902 of file pbx_dundi.c.
References AST_SCHED_DEL, destroy_permissions(), destroy_trans(), free, and sched.
Referenced by prune_peers().
03903 { 03904 AST_SCHED_DEL(sched, peer->registerid); 03905 if (peer->regtrans) 03906 destroy_trans(peer->regtrans, 0); 03907 AST_SCHED_DEL(sched, peer->qualifyid); 03908 destroy_permissions(&peer->permit); 03909 destroy_permissions(&peer->include); 03910 free(peer); 03911 }
static void destroy_permissions | ( | struct permissionlist * | permlist | ) | [static] |
Definition at line 3894 of file pbx_dundi.c.
References AST_LIST_REMOVE_HEAD, and free.
Referenced by build_peer(), and destroy_peer().
03895 { 03896 struct permission *perm; 03897 03898 while ((perm = AST_LIST_REMOVE_HEAD(permlist, list))) 03899 free(perm); 03900 }
static void destroy_trans | ( | struct dundi_transaction * | trans, | |
int | fromtimeout | |||
) | [static] |
Definition at line 2886 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().
02887 { 02888 struct dundi_peer *peer; 02889 int ms; 02890 int x; 02891 int cnt; 02892 char eid_str[20]; 02893 if (ast_test_flag(trans, FLAG_ISREG | FLAG_ISQUAL | FLAG_STOREHIST)) { 02894 AST_LIST_TRAVERSE(&peers, peer, list) { 02895 if (peer->regtrans == trans) 02896 peer->regtrans = NULL; 02897 if (peer->qualtrans == trans) { 02898 if (fromtimeout) { 02899 if (peer->lastms > -1) 02900 ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02901 peer->lastms = -1; 02902 } else { 02903 ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx); 02904 if (ms < 1) 02905 ms = 1; 02906 if (ms < peer->maxms) { 02907 if ((peer->lastms >= peer->maxms) || (peer->lastms < 0)) 02908 ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02909 } else if (peer->lastms < peer->maxms) { 02910 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); 02911 } 02912 peer->lastms = ms; 02913 } 02914 peer->qualtrans = NULL; 02915 } 02916 if (ast_test_flag(trans, FLAG_STOREHIST)) { 02917 if (trans->parent && !ast_strlen_zero(trans->parent->number)) { 02918 if (!dundi_eid_cmp(&trans->them_eid, &peer->eid)) { 02919 peer->avgms = 0; 02920 cnt = 0; 02921 if (peer->lookups[DUNDI_TIMING_HISTORY-1]) 02922 free(peer->lookups[DUNDI_TIMING_HISTORY-1]); 02923 for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) { 02924 peer->lookuptimes[x] = peer->lookuptimes[x-1]; 02925 peer->lookups[x] = peer->lookups[x-1]; 02926 if (peer->lookups[x]) { 02927 peer->avgms += peer->lookuptimes[x]; 02928 cnt++; 02929 } 02930 } 02931 peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start); 02932 peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2); 02933 if (peer->lookups[0]) { 02934 sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext); 02935 peer->avgms += peer->lookuptimes[0]; 02936 cnt++; 02937 } 02938 if (cnt) 02939 peer->avgms /= cnt; 02940 } 02941 } 02942 } 02943 } 02944 } 02945 if (trans->parent) { 02946 /* Unlink from parent if appropriate */ 02947 AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist); 02948 if (AST_LIST_EMPTY(&trans->parent->trans)) { 02949 /* Wake up sleeper */ 02950 if (trans->parent->pfds[1] > -1) { 02951 write(trans->parent->pfds[1], "killa!", 6); 02952 } 02953 } 02954 } 02955 /* Unlink from all trans */ 02956 AST_LIST_REMOVE(&alltrans, trans, all); 02957 destroy_packets(&trans->packets); 02958 destroy_packets(&trans->lasttrans); 02959 AST_SCHED_DEL(sched, trans->autokillid); 02960 if (trans->thread) { 02961 /* If used by a thread, mark as dead and be done */ 02962 ast_set_flag(trans, FLAG_DEAD); 02963 } else 02964 free(trans); 02965 }
static int discover_transactions | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3206 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().
03207 { 03208 struct dundi_transaction *trans; 03209 AST_LIST_LOCK(&peers); 03210 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03211 dundi_discover(trans); 03212 } 03213 AST_LIST_UNLOCK(&peers); 03214 return 0; 03215 }
static int do_autokill | ( | const void * | data | ) | [static] |
Definition at line 3061 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().
03062 { 03063 struct dundi_transaction *trans = (struct dundi_transaction *)data; 03064 char eid_str[20]; 03065 ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n", 03066 dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid)); 03067 trans->autokillid = -1; 03068 destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */ 03069 return 0; 03070 }
static int do_qualify | ( | const void * | data | ) | [static] |
Definition at line 4059 of file pbx_dundi.c.
References qualify_peer().
Referenced by qualify_peer().
04060 { 04061 struct dundi_peer *peer = (struct dundi_peer *)data; 04062 peer->qualifyid = -1; 04063 qualify_peer(peer, 0); 04064 return 0; 04065 }
static int do_register | ( | const void * | data | ) | [static] |
Definition at line 4033 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.
04034 { 04035 struct dundi_ie_data ied; 04036 struct dundi_peer *peer = (struct dundi_peer *)data; 04037 char eid_str[20]; 04038 char eid_str2[20]; 04039 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)); 04040 peer->registerid = ast_sched_add(sched, default_expiration * 1000, do_register, data); 04041 /* Destroy old transaction if there is one */ 04042 if (peer->regtrans) 04043 destroy_trans(peer->regtrans, 0); 04044 peer->regtrans = create_transaction(peer); 04045 if (peer->regtrans) { 04046 ast_set_flag(peer->regtrans, FLAG_ISREG); 04047 memset(&ied, 0, sizeof(ied)); 04048 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 04049 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &peer->regtrans->us_eid); 04050 dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, default_expiration); 04051 dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied); 04052 04053 } else 04054 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)); 04055 04056 return 0; 04057 }
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 4304 of file pbx_dundi.c.
References DUNDI_FLAG_CANMATCH, and dundi_helper().
04305 { 04306 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH); 04307 }
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 3094 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().
03095 { 03096 struct dundi_ie_data ied; 03097 int x; 03098 if (!trans->parent) { 03099 ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n"); 03100 return -1; 03101 } 03102 memset(&ied, 0, sizeof(ied)); 03103 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 03104 if (!dundi_eid_zero(&trans->us_eid)) 03105 dundi_ie_append_eid(&ied, DUNDI_IE_EID_DIRECT, &trans->us_eid); 03106 for (x=0;x<trans->eidcount;x++) 03107 dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid); 03108 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number); 03109 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); 03110 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); 03111 if (trans->parent->cbypass) 03112 dundi_ie_append(&ied, DUNDI_IE_CACHEBYPASS); 03113 if (trans->autokilltimeout) 03114 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); 03115 return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied); 03116 }
static int dundi_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2218 of file pbx_dundi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02219 { 02220 if (argc != 2) 02221 return RESULT_SHOWUSAGE; 02222 dundidebug = 1; 02223 ast_cli(fd, "DUNDi Debugging Enabled\n"); 02224 return RESULT_SUCCESS; 02225 }
static int dundi_do_lookup | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2345 of file pbx_dundi.c.
References ast_cli(), context, dr, dundi_flags2str(), dundi_lookup(), MAX_RESULTS, RESULT_SHOWUSAGE, RESULT_SUCCESS, and sort_results().
02346 { 02347 int res; 02348 char tmp[256]; 02349 char fs[80] = ""; 02350 char *context; 02351 int x; 02352 int bypass = 0; 02353 struct dundi_result dr[MAX_RESULTS]; 02354 struct timeval start; 02355 if ((argc < 3) || (argc > 4)) 02356 return RESULT_SHOWUSAGE; 02357 if (argc > 3) { 02358 if (!strcasecmp(argv[3], "bypass")) 02359 bypass=1; 02360 else 02361 return RESULT_SHOWUSAGE; 02362 } 02363 ast_copy_string(tmp, argv[2], sizeof(tmp)); 02364 context = strchr(tmp, '@'); 02365 if (context) { 02366 *context = '\0'; 02367 context++; 02368 } 02369 start = ast_tvnow(); 02370 res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass); 02371 02372 if (res < 0) 02373 ast_cli(fd, "DUNDi lookup returned error.\n"); 02374 else if (!res) 02375 ast_cli(fd, "DUNDi lookup returned no results.\n"); 02376 else 02377 sort_results(dr, res); 02378 for (x=0;x<res;x++) { 02379 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)); 02380 ast_cli(fd, " from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration); 02381 } 02382 ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start)); 02383 return RESULT_SUCCESS; 02384 }
static int dundi_do_precache | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2386 of file pbx_dundi.c.
References ast_cli(), context, dundi_precache(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02387 { 02388 int res; 02389 char tmp[256]; 02390 char *context; 02391 struct timeval start; 02392 if ((argc < 3) || (argc > 3)) 02393 return RESULT_SHOWUSAGE; 02394 ast_copy_string(tmp, argv[2], sizeof(tmp)); 02395 context = strchr(tmp, '@'); 02396 if (context) { 02397 *context = '\0'; 02398 context++; 02399 } 02400 start = ast_tvnow(); 02401 res = dundi_precache(context, tmp); 02402 02403 if (res < 0) 02404 ast_cli(fd, "DUNDi precache returned error.\n"); 02405 else if (!res) 02406 ast_cli(fd, "DUNDi precache returned no error.\n"); 02407 ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start)); 02408 return RESULT_SUCCESS; 02409 }
static int dundi_do_query | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2411 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.
02412 { 02413 int res; 02414 char tmp[256]; 02415 char *context; 02416 dundi_eid eid; 02417 struct dundi_entity_info dei; 02418 if ((argc < 3) || (argc > 3)) 02419 return RESULT_SHOWUSAGE; 02420 if (dundi_str_to_eid(&eid, argv[2])) { 02421 ast_cli(fd, "'%s' is not a valid EID!\n", argv[2]); 02422 return RESULT_SHOWUSAGE; 02423 } 02424 ast_copy_string(tmp, argv[2], sizeof(tmp)); 02425 context = strchr(tmp, '@'); 02426 if (context) { 02427 *context = '\0'; 02428 context++; 02429 } 02430 res = dundi_query_eid(&dei, context, eid); 02431 if (res < 0) 02432 ast_cli(fd, "DUNDi Query EID returned error.\n"); 02433 else if (!res) 02434 ast_cli(fd, "DUNDi Query EID returned no results.\n"); 02435 else { 02436 ast_cli(fd, "DUNDi Query EID succeeded:\n"); 02437 ast_cli(fd, "Department: %s\n", dei.orgunit); 02438 ast_cli(fd, "Organization: %s\n", dei.org); 02439 ast_cli(fd, "City/Locality: %s\n", dei.locality); 02440 ast_cli(fd, "State/Province: %s\n", dei.stateprov); 02441 ast_cli(fd, "Country: %s\n", dei.country); 02442 ast_cli(fd, "E-mail: %s\n", dei.email); 02443 ast_cli(fd, "Phone: %s\n", dei.phone); 02444 ast_cli(fd, "IP Address: %s\n", dei.ipaddr); 02445 } 02446 return RESULT_SUCCESS; 02447 }
static int dundi_do_store_history | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2227 of file pbx_dundi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02228 { 02229 if (argc != 3) 02230 return RESULT_SHOWUSAGE; 02231 global_storehistory = 1; 02232 ast_cli(fd, "DUNDi History Storage Enabled\n"); 02233 return RESULT_SUCCESS; 02234 }
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 4309 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().
04310 { 04311 struct dundi_result results[MAX_RESULTS]; 04312 int res; 04313 int x=0; 04314 char req[1024]; 04315 struct ast_app *dial; 04316 04317 if (!strncasecmp(context, "macro-", 6)) { 04318 if (!chan) { 04319 ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n"); 04320 return -1; 04321 } 04322 /* If done as a macro, use macro extension */ 04323 if (!strcasecmp(exten, "s")) { 04324 exten = pbx_builtin_getvar_helper(chan, "ARG1"); 04325 if (ast_strlen_zero(exten)) 04326 exten = chan->macroexten; 04327 if (ast_strlen_zero(exten)) 04328 exten = chan->exten; 04329 if (ast_strlen_zero(exten)) { 04330 ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n"); 04331 return -1; 04332 } 04333 } 04334 if (ast_strlen_zero(data)) 04335 data = "e164"; 04336 } else { 04337 if (ast_strlen_zero(data)) 04338 data = context; 04339 } 04340 res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0); 04341 if (res > 0) { 04342 sort_results(results, res); 04343 for (x=0;x<res;x++) { 04344 if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) { 04345 if (!--priority) 04346 break; 04347 } 04348 } 04349 } 04350 if (x < res) { 04351 /* Got a hit! */ 04352 snprintf(req, sizeof(req), "%s/%s", results[x].tech, results[x].dest); 04353 dial = pbx_findapp("Dial"); 04354 if (dial) 04355 res = pbx_exec(chan, dial, req); 04356 } else 04357 res = -1; 04358 return res; 04359 }
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 4299 of file pbx_dundi.c.
References DUNDI_FLAG_EXISTS, and dundi_helper().
04300 { 04301 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS); 04302 }
static int dundi_flush | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2236 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.
02237 { 02238 int stats = 0; 02239 if ((argc < 2) || (argc > 3)) 02240 return RESULT_SHOWUSAGE; 02241 if (argc > 2) { 02242 if (!strcasecmp(argv[2], "stats")) 02243 stats = 1; 02244 else 02245 return RESULT_SHOWUSAGE; 02246 } 02247 if (stats) { 02248 /* Flush statistics */ 02249 struct dundi_peer *p; 02250 int x; 02251 AST_LIST_LOCK(&peers); 02252 AST_LIST_TRAVERSE(&peers, p, list) { 02253 for (x = 0;x < DUNDI_TIMING_HISTORY; x++) { 02254 if (p->lookups[x]) 02255 free(p->lookups[x]); 02256 p->lookups[x] = NULL; 02257 p->lookuptimes[x] = 0; 02258 } 02259 p->avgms = 0; 02260 } 02261 AST_LIST_UNLOCK(&peers); 02262 } else { 02263 ast_db_deltree("dundi/cache", NULL); 02264 ast_cli(fd, "DUNDi Cache Flushed\n"); 02265 } 02266 return RESULT_SUCCESS; 02267 }
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 4260 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().
04261 { 04262 struct dundi_result results[MAX_RESULTS]; 04263 int res; 04264 int x; 04265 int found = 0; 04266 if (!strncasecmp(context, "macro-", 6)) { 04267 if (!chan) { 04268 ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n"); 04269 return -1; 04270 } 04271 /* If done as a macro, use macro extension */ 04272 if (!strcasecmp(exten, "s")) { 04273 exten = pbx_builtin_getvar_helper(chan, "ARG1"); 04274 if (ast_strlen_zero(exten)) 04275 exten = chan->macroexten; 04276 if (ast_strlen_zero(exten)) 04277 exten = chan->exten; 04278 if (ast_strlen_zero(exten)) { 04279 ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n"); 04280 return -1; 04281 } 04282 } 04283 if (ast_strlen_zero(data)) 04284 data = "e164"; 04285 } else { 04286 if (ast_strlen_zero(data)) 04287 data = context; 04288 } 04289 res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0); 04290 for (x=0;x<res;x++) { 04291 if (ast_test_flag(results + x, flag)) 04292 found++; 04293 } 04294 if (found >= priority) 04295 return 1; 04296 return 0; 04297 }
static void dundi_ie_append_eid_appropriately | ( | struct dundi_ie_data * | ied, | |
char * | context, | |||
dundi_eid * | eid, | |||
dundi_eid * | us | |||
) | [static] |
Definition at line 3072 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().
03073 { 03074 struct dundi_peer *p; 03075 if (!dundi_eid_cmp(eid, us)) { 03076 dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid); 03077 return; 03078 } 03079 AST_LIST_LOCK(&peers); 03080 AST_LIST_TRAVERSE(&peers, p, list) { 03081 if (!dundi_eid_cmp(&p->eid, eid)) { 03082 if (has_permission(&p->include, context)) 03083 dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid); 03084 else 03085 dundi_ie_append_eid(ied, DUNDI_IE_EID, eid); 03086 break; 03087 } 03088 } 03089 if (!p) 03090 dundi_ie_append_eid(ied, DUNDI_IE_EID, eid); 03091 AST_LIST_UNLOCK(&peers); 03092 }
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 3602 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().
03603 { 03604 struct dundi_hint_metadata hmd; 03605 dundi_eid *avoid[1] = { NULL, }; 03606 int direct[1] = { 0, }; 03607 int expiration = dundi_cache_time; 03608 memset(&hmd, 0, sizeof(hmd)); 03609 hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; 03610 return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct); 03611 }
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 3500 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().
03501 { 03502 int res; 03503 struct dundi_request dr, *pending; 03504 dundi_eid *rooteid=NULL; 03505 int x; 03506 int ttlms; 03507 int ms; 03508 int foundcache; 03509 int skipped=0; 03510 int order=0; 03511 char eid_str[20]; 03512 struct timeval start; 03513 03514 /* Don't do anthing for a hungup channel */ 03515 if (chan && chan->_softhangup) 03516 return 0; 03517 03518 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03519 03520 for (x=0;avoid[x];x++) 03521 rooteid = avoid[x]; 03522 /* Now perform real check */ 03523 memset(&dr, 0, sizeof(dr)); 03524 if (pipe(dr.pfds)) { 03525 ast_log(LOG_WARNING, "pipe failed: %s\n" , strerror(errno)); 03526 return -1; 03527 } 03528 dr.dr = result; 03529 dr.hmd = hmd; 03530 dr.maxcount = maxret; 03531 dr.expiration = *expiration; 03532 dr.cbypass = cbypass; 03533 dr.crc32 = avoid_crc32(avoid); 03534 ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext)); 03535 ast_copy_string(dr.number, number, sizeof(dr.number)); 03536 if (rooteid) 03537 dr.root_eid = *rooteid; 03538 res = register_request(&dr, &pending); 03539 if (res) { 03540 /* Already a request */ 03541 if (rooteid && !dundi_eid_cmp(&dr.root_eid, &pending->root_eid)) { 03542 /* This is on behalf of someone else. Go ahead and close this out since 03543 they'll get their answer anyway. */ 03544 ast_log(LOG_DEBUG, "Oooh, duplicate request for '%s@%s' for '%s'\n", 03545 dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid)); 03546 close(dr.pfds[0]); 03547 close(dr.pfds[1]); 03548 return -2; 03549 } else { 03550 /* Wait for the cache to populate */ 03551 ast_log(LOG_DEBUG, "Waiting for similar request for '%s@%s' for '%s'\n", 03552 dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid)); 03553 start = ast_tvnow(); 03554 while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) { 03555 /* XXX Would be nice to have a way to poll/select here XXX */ 03556 /* XXX this is a busy wait loop!!! */ 03557 usleep(1); 03558 } 03559 /* Continue on as normal, our cache should kick in */ 03560 } 03561 } 03562 /* Create transactions */ 03563 do { 03564 order = skipped; 03565 skipped = 0; 03566 foundcache = 0; 03567 build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct); 03568 } while (skipped && !foundcache && AST_LIST_EMPTY(&dr.trans)); 03569 /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't 03570 do this earlier because we didn't know if we were going to have transactions 03571 or not. */ 03572 if (!ttl) { 03573 ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED); 03574 abort_request(&dr); 03575 unregister_request(&dr); 03576 close(dr.pfds[0]); 03577 close(dr.pfds[1]); 03578 return 0; 03579 } 03580 03581 /* Optimize transactions */ 03582 optimize_transactions(&dr, order); 03583 /* Actually perform transactions */ 03584 discover_transactions(&dr); 03585 /* Wait for transaction to come back */ 03586 start = ast_tvnow(); 03587 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) { 03588 ms = 100; 03589 ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL); 03590 } 03591 if (chan && chan->_softhangup) 03592 ast_log(LOG_DEBUG, "Hrm, '%s' hungup before their query for %s@%s finished\n", chan->name, dr.number, dr.dcontext); 03593 cancel_request(&dr); 03594 unregister_request(&dr); 03595 res = dr.respcount; 03596 *expiration = dr.expiration; 03597 close(dr.pfds[0]); 03598 close(dr.pfds[1]); 03599 return res; 03600 }
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 4361 of file pbx_dundi.c.
References DUNDI_FLAG_MATCHMORE, and dundi_helper().
04362 { 04363 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE); 04364 }
static int dundi_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2269 of file pbx_dundi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02270 { 02271 if (argc != 3) 02272 return RESULT_SHOWUSAGE; 02273 dundidebug = 0; 02274 ast_cli(fd, "DUNDi Debugging Disabled\n"); 02275 return RESULT_SUCCESS; 02276 }
static int dundi_no_store_history | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2278 of file pbx_dundi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02279 { 02280 if (argc != 4) 02281 return RESULT_SHOWUSAGE; 02282 global_storehistory = 0; 02283 ast_cli(fd, "DUNDi History Storage Disabled\n"); 02284 return RESULT_SUCCESS; 02285 }
int dundi_precache | ( | const char * | context, | |
const char * | number | |||
) |
Pre-cache to push upstream peers.
Definition at line 3746 of file pbx_dundi.c.
References dundi_precache_internal().
Referenced by dundi_do_precache(), and process_precache().
03747 { 03748 dundi_eid *avoid[1] = { NULL, }; 03749 return dundi_precache_internal(context, number, dundi_ttl, avoid); 03750 }
static void dundi_precache_full | ( | void | ) | [static] |
Definition at line 3649 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().
03650 { 03651 struct dundi_mapping *cur; 03652 struct ast_context *con; 03653 struct ast_exten *e; 03654 03655 AST_LIST_TRAVERSE(&mappings, cur, list) { 03656 ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext); 03657 ast_rdlock_contexts(); 03658 con = ast_walk_contexts(NULL); 03659 while (con) { 03660 if (!strcasecmp(cur->lcontext, ast_get_context_name(con))) { 03661 /* Found the match, now queue them all up */ 03662 ast_lock_context(con); 03663 e = ast_walk_context_extensions(con, NULL); 03664 while (e) { 03665 reschedule_precache(ast_get_extension_name(e), cur->dcontext, 0); 03666 e = ast_walk_context_extensions(con, e); 03667 } 03668 ast_unlock_context(con); 03669 } 03670 con = ast_walk_contexts(con); 03671 } 03672 ast_unlock_contexts(); 03673 } 03674 }
static int dundi_precache_internal | ( | const char * | context, | |
const char * | number, | |||
int | ttl, | |||
dundi_eid * | avoids[] | |||
) | [static] |
Definition at line 3676 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().
03677 { 03678 struct dundi_request dr; 03679 struct dundi_hint_metadata hmd; 03680 struct dundi_result dr2[MAX_RESULTS]; 03681 struct timeval start; 03682 struct dundi_mapping *maps = NULL, *cur; 03683 int nummaps = 0; 03684 int foundanswers; 03685 int foundcache, skipped, ttlms, ms; 03686 if (!context) 03687 context = "e164"; 03688 ast_log(LOG_DEBUG, "Precache internal (%s@%s)!\n", number, context); 03689 03690 AST_LIST_LOCK(&peers); 03691 AST_LIST_TRAVERSE(&mappings, cur, list) { 03692 if (!strcasecmp(cur->dcontext, context)) 03693 nummaps++; 03694 } 03695 if (nummaps) { 03696 maps = alloca(nummaps * sizeof(*maps)); 03697 nummaps = 0; 03698 if (maps) { 03699 AST_LIST_TRAVERSE(&mappings, cur, list) { 03700 if (!strcasecmp(cur->dcontext, context)) 03701 maps[nummaps++] = *cur; 03702 } 03703 } 03704 } 03705 AST_LIST_UNLOCK(&peers); 03706 if (!nummaps || !maps) 03707 return -1; 03708 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03709 memset(&dr2, 0, sizeof(dr2)); 03710 memset(&dr, 0, sizeof(dr)); 03711 memset(&hmd, 0, sizeof(hmd)); 03712 dr.dr = dr2; 03713 ast_copy_string(dr.number, number, sizeof(dr.number)); 03714 ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext)); 03715 dr.maxcount = MAX_RESULTS; 03716 dr.expiration = dundi_cache_time; 03717 dr.hmd = &hmd; 03718 dr.pfds[0] = dr.pfds[1] = -1; 03719 pipe(dr.pfds); 03720 build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL); 03721 optimize_transactions(&dr, 0); 03722 foundanswers = 0; 03723 precache_transactions(&dr, maps, nummaps, &dr.expiration, &foundanswers); 03724 if (foundanswers) { 03725 if (dr.expiration > 0) 03726 reschedule_precache(dr.number, dr.dcontext, dr.expiration); 03727 else 03728 ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext); 03729 } 03730 start = ast_tvnow(); 03731 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) { 03732 if (dr.pfds[0] > -1) { 03733 ms = 100; 03734 ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL); 03735 } else 03736 usleep(1); 03737 } 03738 cancel_request(&dr); 03739 if (dr.pfds[0] > -1) { 03740 close(dr.pfds[0]); 03741 close(dr.pfds[1]); 03742 } 03743 return 0; 03744 }
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 3184 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().
03185 { 03186 struct dundi_ie_data ied; 03187 int x; 03188 if (!trans->parent) { 03189 ast_log(LOG_WARNING, "Tried to query a transaction with no parent?!?\n"); 03190 return -1; 03191 } 03192 memset(&ied, 0, sizeof(ied)); 03193 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 03194 if (!dundi_eid_zero(&trans->us_eid)) 03195 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); 03196 for (x=0;x<trans->eidcount;x++) 03197 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]); 03198 dundi_ie_append_eid(&ied, DUNDI_IE_REQEID, &trans->parent->query_eid); 03199 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); 03200 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); 03201 if (trans->autokilltimeout) 03202 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); 03203 return dundi_send(trans, DUNDI_COMMAND_EIDQUERY, 0, 0, &ied); 03204 }
int dundi_query_eid | ( | struct dundi_entity_info * | dei, | |
const char * | dcontext, | |||
dundi_eid | eid | |||
) |
Retrieve information on a specific EID.
Definition at line 3799 of file pbx_dundi.c.
References dundi_query_eid_internal().
Referenced by dundi_do_query().
03800 { 03801 dundi_eid *avoid[1] = { NULL, }; 03802 struct dundi_hint_metadata hmd; 03803 memset(&hmd, 0, sizeof(hmd)); 03804 return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid); 03805 }
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 3752 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().
03753 { 03754 int res; 03755 struct dundi_request dr; 03756 dundi_eid *rooteid=NULL; 03757 int x; 03758 int ttlms; 03759 int skipped=0; 03760 int foundcache=0; 03761 struct timeval start; 03762 03763 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03764 03765 for (x=0;avoid[x];x++) 03766 rooteid = avoid[x]; 03767 /* Now perform real check */ 03768 memset(&dr, 0, sizeof(dr)); 03769 dr.hmd = hmd; 03770 dr.dei = dei; 03771 dr.pfds[0] = dr.pfds[1] = -1; 03772 ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext)); 03773 memcpy(&dr.query_eid, eid, sizeof(dr.query_eid)); 03774 if (rooteid) 03775 dr.root_eid = *rooteid; 03776 /* Create transactions */ 03777 build_transactions(&dr, ttl, 9999, &foundcache, &skipped, blockempty, 0, 0, NULL, avoid, NULL); 03778 03779 /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't 03780 do this earlier because we didn't know if we were going to have transactions 03781 or not. */ 03782 if (!ttl) { 03783 ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED); 03784 return 0; 03785 } 03786 03787 /* Optimize transactions */ 03788 optimize_transactions(&dr, 9999); 03789 /* Actually perform transactions */ 03790 query_transactions(&dr); 03791 /* Wait for transaction to come back */ 03792 start = ast_tvnow(); 03793 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) 03794 usleep(1); 03795 res = dr.respcount; 03796 return res; 03797 }
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 2967 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().
02968 { 02969 struct dundi_packet *pack = (struct dundi_packet *)data; 02970 int res; 02971 AST_LIST_LOCK(&peers); 02972 if (pack->retrans < 1) { 02973 pack->retransid = -1; 02974 if (!ast_test_flag(pack->parent, FLAG_ISQUAL)) 02975 ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n", 02976 ast_inet_ntoa(pack->parent->addr.sin_addr), 02977 ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans)); 02978 destroy_trans(pack->parent, 1); 02979 res = 0; 02980 } else { 02981 /* Decrement retransmission, try again */ 02982 pack->retrans--; 02983 dundi_xmit(pack); 02984 res = 1; 02985 } 02986 AST_LIST_UNLOCK(&peers); 02987 return res; 02988 }
static int dundi_send | ( | struct dundi_transaction * | trans, | |
int | cmdresp, | |||
int | flags, | |||
int | final, | |||
struct dundi_ie_data * | ied | |||
) | [static] |
Definition at line 2990 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().
02991 { 02992 struct dundi_packet *pack; 02993 int res; 02994 int len; 02995 char eid_str[20]; 02996 len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0); 02997 /* Reserve enough space for encryption */ 02998 if (ast_test_flag(trans, FLAG_ENCRYPT)) 02999 len += 384; 03000 pack = ast_calloc(1, len); 03001 if (pack) { 03002 pack->h = (struct dundi_hdr *)(pack->data); 03003 if (cmdresp != DUNDI_COMMAND_ACK) { 03004 pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack); 03005 pack->retrans = DUNDI_DEFAULT_RETRANS - 1; 03006 AST_LIST_INSERT_HEAD(&trans->packets, pack, list); 03007 } 03008 pack->parent = trans; 03009 pack->h->strans = htons(trans->strans); 03010 pack->h->dtrans = htons(trans->dtrans); 03011 pack->h->iseqno = trans->iseqno; 03012 pack->h->oseqno = trans->oseqno; 03013 pack->h->cmdresp = cmdresp; 03014 pack->datalen = sizeof(struct dundi_hdr); 03015 if (ied) { 03016 memcpy(pack->h->ies, ied->buf, ied->pos); 03017 pack->datalen += ied->pos; 03018 } 03019 if (final) { 03020 pack->h->cmdresp |= DUNDI_COMMAND_FINAL; 03021 ast_set_flag(trans, FLAG_FINAL); 03022 } 03023 pack->h->cmdflags = flags; 03024 if (cmdresp != DUNDI_COMMAND_ACK) { 03025 trans->oseqno++; 03026 trans->oseqno = trans->oseqno % 256; 03027 } 03028 trans->aseqno = trans->iseqno; 03029 /* If we have their public key, encrypt */ 03030 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 03031 switch(cmdresp) { 03032 case DUNDI_COMMAND_REGREQ: 03033 case DUNDI_COMMAND_REGRESPONSE: 03034 case DUNDI_COMMAND_DPDISCOVER: 03035 case DUNDI_COMMAND_DPRESPONSE: 03036 case DUNDI_COMMAND_EIDQUERY: 03037 case DUNDI_COMMAND_EIDRESPONSE: 03038 case DUNDI_COMMAND_PRECACHERQ: 03039 case DUNDI_COMMAND_PRECACHERP: 03040 if (dundidebug) 03041 dundi_showframe(pack->h, 2, &trans->addr, pack->datalen - sizeof(struct dundi_hdr)); 03042 res = dundi_encrypt(trans, pack); 03043 break; 03044 default: 03045 res = 0; 03046 } 03047 } else 03048 res = 0; 03049 if (!res) 03050 res = dundi_xmit(pack); 03051 if (res) 03052 ast_log(LOG_NOTICE, "Failed to send packet to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid)); 03053 03054 if (cmdresp == DUNDI_COMMAND_ACK) 03055 free(pack); 03056 return res; 03057 } 03058 return -1; 03059 }
static int dundi_show_entityid | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2616 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.
02617 { 02618 char eid_str[20]; 02619 if (argc != 3) 02620 return RESULT_SHOWUSAGE; 02621 AST_LIST_LOCK(&peers); 02622 dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid); 02623 AST_LIST_UNLOCK(&peers); 02624 ast_cli(fd, "Global EID for this system is '%s'\n", eid_str); 02625 return RESULT_SUCCESS; 02626 }
static int dundi_show_mappings | ( | 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, ast_strlen_zero(), dundi_flags2str(), FORMAT, FORMAT2, map, peers, RESULT_SHOWUSAGE, RESULT_SUCCESS, and tech2str().
02651 { 02652 #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n" 02653 #define FORMAT "%-12.12s %-7d %-12.12s %-10.10s %-5.5s %-25.25s\n" 02654 struct dundi_mapping *map; 02655 char fs[256]; 02656 if (argc != 3) 02657 return RESULT_SHOWUSAGE; 02658 AST_LIST_LOCK(&peers); 02659 ast_cli(fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination"); 02660 AST_LIST_TRAVERSE(&mappings, map, list) { 02661 ast_cli(fd, FORMAT, map->dcontext, map->weight, 02662 ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext, 02663 dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest); 02664 } 02665 AST_LIST_UNLOCK(&peers); 02666 return RESULT_SUCCESS; 02667 #undef FORMAT 02668 #undef FORMAT2 02669 }
static int dundi_show_peer | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2449 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.
02450 { 02451 struct dundi_peer *peer; 02452 struct permission *p; 02453 char *order; 02454 char eid_str[20]; 02455 int x, cnt; 02456 02457 if (argc != 4) 02458 return RESULT_SHOWUSAGE; 02459 AST_LIST_LOCK(&peers); 02460 AST_LIST_TRAVERSE(&peers, peer, list) { 02461 if (!strcasecmp(dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), argv[3])) 02462 break; 02463 } 02464 if (peer) { 02465 switch(peer->order) { 02466 case 0: 02467 order = "Primary"; 02468 break; 02469 case 1: 02470 order = "Secondary"; 02471 break; 02472 case 2: 02473 order = "Tertiary"; 02474 break; 02475 case 3: 02476 order = "Quartiary"; 02477 break; 02478 default: 02479 order = "Unknown"; 02480 } 02481 ast_cli(fd, "Peer: %s\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02482 ast_cli(fd, "Model: %s\n", model2str(peer->model)); 02483 ast_cli(fd, "Host: %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>"); 02484 ast_cli(fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no"); 02485 ast_cli(fd, "Reg: %s\n", peer->registerid < 0 ? "No" : "Yes"); 02486 ast_cli(fd, "In Key: %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey); 02487 ast_cli(fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey); 02488 if (!AST_LIST_EMPTY(&peer->include)) 02489 ast_cli(fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)"); 02490 AST_LIST_TRAVERSE(&peer->include, p, list) 02491 ast_cli(fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name); 02492 if (!AST_LIST_EMPTY(&peer->permit)) 02493 ast_cli(fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)"); 02494 AST_LIST_TRAVERSE(&peer->permit, p, list) 02495 ast_cli(fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name); 02496 cnt = 0; 02497 for (x = 0;x < DUNDI_TIMING_HISTORY; x++) { 02498 if (peer->lookups[x]) { 02499 if (!cnt) 02500 ast_cli(fd, "Last few query times:\n"); 02501 ast_cli(fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]); 02502 cnt++; 02503 } 02504 } 02505 if (cnt) 02506 ast_cli(fd, "Average query time: %d ms\n", peer->avgms); 02507 } else 02508 ast_cli(fd, "No such peer '%s'\n", argv[3]); 02509 AST_LIST_UNLOCK(&peers); 02510 return RESULT_SUCCESS; 02511 }
static int dundi_show_peers | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2513 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.
02514 { 02515 #define FORMAT2 "%-20.20s %-15.15s %-10.10s %-8.8s %-15.15s\n" 02516 #define FORMAT "%-20.20s %-15.15s %s %-10.10s %-8.8s %-15.15s\n" 02517 struct dundi_peer *peer; 02518 int registeredonly=0; 02519 char avgms[20]; 02520 char eid_str[20]; 02521 int online_peers = 0; 02522 int offline_peers = 0; 02523 int unmonitored_peers = 0; 02524 int total_peers = 0; 02525 02526 if ((argc != 3) && (argc != 4) && (argc != 5)) 02527 return RESULT_SHOWUSAGE; 02528 if ((argc == 4)) { 02529 if (!strcasecmp(argv[3], "registered")) { 02530 registeredonly = 1; 02531 } else 02532 return RESULT_SHOWUSAGE; 02533 } 02534 AST_LIST_LOCK(&peers); 02535 ast_cli(fd, FORMAT2, "EID", "Host", "Model", "AvgTime", "Status"); 02536 AST_LIST_TRAVERSE(&peers, peer, list) { 02537 char status[20]; 02538 int print_line = -1; 02539 char srch[2000]; 02540 total_peers++; 02541 if (registeredonly && !peer->addr.sin_addr.s_addr) 02542 continue; 02543 if (peer->maxms) { 02544 if (peer->lastms < 0) { 02545 strcpy(status, "UNREACHABLE"); 02546 offline_peers++; 02547 } 02548 else if (peer->lastms > peer->maxms) { 02549 snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms); 02550 offline_peers++; 02551 } 02552 else if (peer->lastms) { 02553 snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms); 02554 online_peers++; 02555 } 02556 else { 02557 strcpy(status, "UNKNOWN"); 02558 offline_peers++; 02559 } 02560 } else { 02561 strcpy(status, "Unmonitored"); 02562 unmonitored_peers++; 02563 } 02564 if (peer->avgms) 02565 snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms); 02566 else 02567 strcpy(avgms, "Unavail"); 02568 snprintf(srch, sizeof(srch), FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 02569 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 02570 peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status); 02571 02572 if (argc == 5) { 02573 if (!strcasecmp(argv[3],"include") && strstr(srch,argv[4])) { 02574 print_line = -1; 02575 } else if (!strcasecmp(argv[3],"exclude") && !strstr(srch,argv[4])) { 02576 print_line = 1; 02577 } else if (!strcasecmp(argv[3],"begin") && !strncasecmp(srch,argv[4],strlen(argv[4]))) { 02578 print_line = -1; 02579 } else { 02580 print_line = 0; 02581 } 02582 } 02583 02584 if (print_line) { 02585 ast_cli(fd, FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 02586 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 02587 peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status); 02588 } 02589 } 02590 ast_cli(fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers); 02591 AST_LIST_UNLOCK(&peers); 02592 return RESULT_SUCCESS; 02593 #undef FORMAT 02594 #undef FORMAT2 02595 }
static int dundi_show_precache | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2671 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.
02672 { 02673 #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n" 02674 #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n" 02675 struct dundi_precache_queue *qe; 02676 int h,m,s; 02677 time_t now; 02678 02679 if (argc != 3) 02680 return RESULT_SHOWUSAGE; 02681 time(&now); 02682 ast_cli(fd, FORMAT2, "Number", "Context", "Expiration"); 02683 AST_LIST_LOCK(&pcq); 02684 AST_LIST_TRAVERSE(&pcq, qe, list) { 02685 s = qe->expiration - now; 02686 h = s / 3600; 02687 s = s % 3600; 02688 m = s / 60; 02689 s = s % 60; 02690 ast_cli(fd, FORMAT, qe->number, qe->context, h,m,s); 02691 } 02692 AST_LIST_UNLOCK(&pcq); 02693 02694 return RESULT_SUCCESS; 02695 #undef FORMAT 02696 #undef FORMAT2 02697 }
static int dundi_show_requests | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2628 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.
02629 { 02630 #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n" 02631 #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n" 02632 struct dundi_request *req; 02633 char eidstr[20]; 02634 if (argc != 3) 02635 return RESULT_SHOWUSAGE; 02636 AST_LIST_LOCK(&peers); 02637 ast_cli(fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp"); 02638 AST_LIST_TRAVERSE(&requests, req, list) { 02639 ast_cli(fd, FORMAT, req->number, req->dcontext, 02640 dundi_eid_zero(&req->root_eid) ? "<unspecified>" : dundi_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount); 02641 } 02642 AST_LIST_UNLOCK(&peers); 02643 return RESULT_SUCCESS; 02644 #undef FORMAT 02645 #undef FORMAT2 02646 }
static int dundi_show_trans | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2597 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.
02598 { 02599 #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n" 02600 #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n" 02601 struct dundi_transaction *trans; 02602 if (argc != 3) 02603 return RESULT_SHOWUSAGE; 02604 AST_LIST_LOCK(&peers); 02605 ast_cli(fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack"); 02606 AST_LIST_TRAVERSE(&alltrans, trans, all) { 02607 ast_cli(fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr), 02608 ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno); 02609 } 02610 AST_LIST_UNLOCK(&peers); 02611 return RESULT_SUCCESS; 02612 #undef FORMAT 02613 #undef FORMAT2 02614 }
static int dundi_xmit | ( | struct dundi_packet * | pack | ) | [static] |
Definition at line 2861 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().
02862 { 02863 int res; 02864 if (dundidebug) 02865 dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr)); 02866 res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr)); 02867 if (res < 0) { 02868 ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n", 02869 ast_inet_ntoa(pack->parent->addr.sin_addr), 02870 ntohs(pack->parent->addr.sin_port), strerror(errno)); 02871 } 02872 if (res > 0) 02873 res = 0; 02874 return res; 02875 }
static int dundifunc_read | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | num, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 3807 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.
03808 { 03809 char *context; 03810 char *opts; 03811 int results; 03812 int x; 03813 int bypass = 0; 03814 struct ast_module_user *u; 03815 struct dundi_result dr[MAX_RESULTS]; 03816 03817 buf[0] = '\0'; 03818 03819 if (ast_strlen_zero(num)) { 03820 ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n"); 03821 return -1; 03822 } 03823 03824 u = ast_module_user_add(chan); 03825 03826 context = strchr(num, '|'); 03827 if (context) { 03828 *context++ = '\0'; 03829 opts = strchr(context, '|'); 03830 if (opts) { 03831 *opts++ = '\0'; 03832 if (strchr(opts, 'b')) 03833 bypass = 1; 03834 } 03835 } 03836 03837 if (ast_strlen_zero(context)) 03838 context = "e164"; 03839 03840 results = dundi_lookup(dr, MAX_RESULTS, NULL, context, num, bypass); 03841 if (results > 0) { 03842 sort_results(dr, results); 03843 for (x = 0; x < results; x++) { 03844 if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) { 03845 snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest); 03846 break; 03847 } 03848 } 03849 } 03850 03851 ast_module_user_remove(u); 03852 03853 return 0; 03854 }
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, dundi_ie_data::pos, 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 #ifdef LOW_MEMORY 01545 struct dundi_ie_data *ied = ast_calloc(1, sizeof(*ied)); 01546 #else 01547 struct dundi_ie_data _ied = { 01548 .pos = 0, 01549 }; 01550 struct dundi_ie_data *ied = &_ied; 01551 #endif 01552 struct dundi_ies ies = { 01553 .eidcount = 0, 01554 }; 01555 struct dundi_peer *peer = NULL; 01556 char eid_str[20]; 01557 char eid_str2[20]; 01558 int retval = -1; 01559 01560 if (!ied) { 01561 return -1; 01562 } 01563 01564 if (datalen) { 01565 bufcpy = alloca(datalen); 01566 if (!bufcpy) { 01567 goto return_cleanup; 01568 } 01569 /* Make a copy for parsing */ 01570 memcpy(bufcpy, hdr->ies, datalen); 01571 ast_log(LOG_DEBUG, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : ""); 01572 if (dundi_parse_ies(&ies, bufcpy, datalen) < 0) { 01573 ast_log(LOG_WARNING, "Failed to parse DUNDI information elements!\n"); 01574 goto return_cleanup; 01575 } 01576 } 01577 switch(cmd) { 01578 case DUNDI_COMMAND_DPDISCOVER: 01579 case DUNDI_COMMAND_EIDQUERY: 01580 case DUNDI_COMMAND_PRECACHERQ: 01581 if (cmd == DUNDI_COMMAND_EIDQUERY) 01582 resp = DUNDI_COMMAND_EIDRESPONSE; 01583 else if (cmd == DUNDI_COMMAND_PRECACHERQ) 01584 resp = DUNDI_COMMAND_PRECACHERP; 01585 else 01586 resp = DUNDI_COMMAND_DPRESPONSE; 01587 /* A dialplan or entity discover -- qualify by highest level entity */ 01588 peer = find_peer(ies.eids[0]); 01589 if (!peer) { 01590 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL); 01591 dundi_send(trans, resp, 0, 1, ied); 01592 } else { 01593 int hasauth = 0; 01594 trans->us_eid = peer->us_eid; 01595 if (strlen(peer->inkey)) { 01596 hasauth = encrypted; 01597 } else 01598 hasauth = 1; 01599 if (hasauth) { 01600 /* Okay we're authentiated and all, now we check if they're authorized */ 01601 if (!ies.called_context) 01602 ies.called_context = "e164"; 01603 if (cmd == DUNDI_COMMAND_EIDQUERY) { 01604 res = dundi_answer_entity(trans, &ies, ies.called_context); 01605 } else { 01606 if (ast_strlen_zero(ies.called_number)) { 01607 /* They're not permitted to access that context */ 01608 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Invalid or missing number/entity"); 01609 dundi_send(trans, resp, 0, 1, ied); 01610 } else if ((cmd == DUNDI_COMMAND_DPDISCOVER) && 01611 (peer->model & DUNDI_MODEL_INBOUND) && 01612 has_permission(&peer->permit, ies.called_context)) { 01613 res = dundi_answer_query(trans, &ies, ies.called_context); 01614 if (res < 0) { 01615 /* There is no such dundi context */ 01616 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context"); 01617 dundi_send(trans, resp, 0, 1, ied); 01618 } 01619 } else if ((cmd = DUNDI_COMMAND_PRECACHERQ) && 01620 (peer->pcmodel & DUNDI_MODEL_INBOUND) && 01621 has_permission(&peer->include, ies.called_context)) { 01622 res = dundi_prop_precache(trans, &ies, ies.called_context); 01623 if (res < 0) { 01624 /* There is no such dundi context */ 01625 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context"); 01626 dundi_send(trans, resp, 0, 1, ied); 01627 } 01628 } else { 01629 /* They're not permitted to access that context */ 01630 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Permission to context denied"); 01631 dundi_send(trans, resp, 0, 1, ied); 01632 } 01633 } 01634 } else { 01635 /* They're not permitted to access that context */ 01636 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unencrypted responses not permitted"); 01637 dundi_send(trans, resp, 0, 1, ied); 01638 } 01639 } 01640 break; 01641 case DUNDI_COMMAND_REGREQ: 01642 /* A register request -- should only have one entity */ 01643 peer = find_peer(ies.eids[0]); 01644 01645 /* if the peer is not found and we have a valid 'any_peer' setting */ 01646 if (any_peer && peer == any_peer) { 01647 /* copy any_peer into a new peer object */ 01648 peer = ast_calloc(1, sizeof(*peer)); 01649 if (peer) { 01650 deep_copy_peer(peer, any_peer); 01651 01652 /* set EID to remote EID */ 01653 peer->eid = *ies.eids[0]; 01654 01655 AST_LIST_LOCK(&peers); 01656 AST_LIST_INSERT_HEAD(&peers, peer, list); 01657 AST_LIST_UNLOCK(&peers); 01658 } 01659 } 01660 01661 if (!peer || !peer->dynamic) { 01662 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL); 01663 dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied); 01664 } else { 01665 int hasauth = 0; 01666 trans->us_eid = peer->us_eid; 01667 if (!ast_strlen_zero(peer->inkey)) { 01668 hasauth = encrypted; 01669 } else 01670 hasauth = 1; 01671 if (hasauth) { 01672 int expire = default_expiration; 01673 char data[256]; 01674 int needqual = 0; 01675 AST_SCHED_DEL(sched, peer->registerexpire); 01676 peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer); 01677 snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(trans->addr.sin_addr), 01678 ntohs(trans->addr.sin_port), expire); 01679 ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data); 01680 if (inaddrcmp(&peer->addr, &trans->addr)) { 01681 if (option_verbose > 2) { 01682 ast_verbose(VERBOSE_PREFIX_3 "Registered DUNDi peer '%s' at '%s:%d'\n", 01683 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 01684 ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port)); 01685 } 01686 needqual = 1; 01687 } 01688 01689 memcpy(&peer->addr, &trans->addr, sizeof(peer->addr)); 01690 dundi_ie_append_short(ied, DUNDI_IE_EXPIRATION, default_expiration); 01691 dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied); 01692 if (needqual) 01693 qualify_peer(peer, 1); 01694 } 01695 } 01696 break; 01697 case DUNDI_COMMAND_DPRESPONSE: 01698 /* A dialplan response, lets see what we got... */ 01699 if (ies.cause < 1) { 01700 /* Success of some sort */ 01701 ast_log(LOG_DEBUG, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount); 01702 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 01703 authpass = encrypted; 01704 } else 01705 authpass = 1; 01706 if (authpass) { 01707 /* Pass back up answers */ 01708 if (trans->parent && trans->parent->dr) { 01709 y = trans->parent->respcount; 01710 for (x=0;x<ies.anscount;x++) { 01711 if (trans->parent->respcount < trans->parent->maxcount) { 01712 /* Make sure it's not already there */ 01713 for (z=0;z<trans->parent->respcount;z++) { 01714 if ((trans->parent->dr[z].techint == ies.answers[x]->protocol) && 01715 !strcmp(trans->parent->dr[z].dest, (char *)ies.answers[x]->data)) 01716 break; 01717 } 01718 if (z == trans->parent->respcount) { 01719 /* Copy into parent responses */ 01720 trans->parent->dr[trans->parent->respcount].flags = ntohs(ies.answers[x]->flags); 01721 trans->parent->dr[trans->parent->respcount].techint = ies.answers[x]->protocol; 01722 trans->parent->dr[trans->parent->respcount].weight = ntohs(ies.answers[x]->weight); 01723 trans->parent->dr[trans->parent->respcount].eid = ies.answers[x]->eid; 01724 if (ies.expiration > 0) 01725 trans->parent->dr[trans->parent->respcount].expiration = ies.expiration; 01726 else 01727 trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time; 01728 dundi_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, 01729 sizeof(trans->parent->dr[trans->parent->respcount].eid_str), 01730 &ies.answers[x]->eid); 01731 ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies.answers[x]->data, 01732 sizeof(trans->parent->dr[trans->parent->respcount].dest)); 01733 ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies.answers[x]->protocol), 01734 sizeof(trans->parent->dr[trans->parent->respcount].tech)); 01735 trans->parent->respcount++; 01736 ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); 01737 } else if (trans->parent->dr[z].weight > ies.answers[x]->weight) { 01738 /* Update weight if appropriate */ 01739 trans->parent->dr[z].weight = ies.answers[x]->weight; 01740 } 01741 } else 01742 ast_log(LOG_NOTICE, "Dropping excessive answers to request for %s@%s\n", 01743 trans->parent->number, trans->parent->dcontext); 01744 } 01745 /* Save all the results (if any) we had. Even if no results, still cache lookup. Let 01746 the cache know if this request was unaffected by our entity list. */ 01747 cache_save(&trans->them_eid, trans->parent, y, 01748 ies.hint ? ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_UNAFFECTED)) : 0, ies.expiration, 0); 01749 if (ies.hint) { 01750 cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration); 01751 if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED))) 01752 ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED); 01753 if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_DONT_ASK))) { 01754 if (strlen((char *)ies.hint->data) > strlen(trans->parent->hmd->exten)) { 01755 ast_copy_string(trans->parent->hmd->exten, (char *)ies.hint->data, 01756 sizeof(trans->parent->hmd->exten)); 01757 } 01758 } else { 01759 ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); 01760 } 01761 } 01762 if (ies.expiration > 0) { 01763 if (trans->parent->expiration > ies.expiration) { 01764 trans->parent->expiration = ies.expiration; 01765 } 01766 } 01767 } 01768 /* Close connection if not final */ 01769 if (!final) 01770 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01771 } 01772 01773 } else { 01774 /* Auth failure, check for data */ 01775 if (!final) { 01776 /* Cancel if they didn't already */ 01777 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01778 } 01779 } 01780 break; 01781 case DUNDI_COMMAND_EIDRESPONSE: 01782 /* A dialplan response, lets see what we got... */ 01783 if (ies.cause < 1) { 01784 /* Success of some sort */ 01785 ast_log(LOG_DEBUG, "Looks like success of some sort (%d)\n", ies.cause); 01786 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 01787 authpass = encrypted; 01788 } else 01789 authpass = 1; 01790 if (authpass) { 01791 /* Pass back up answers */ 01792 if (trans->parent && trans->parent->dei && ies.q_org) { 01793 if (!trans->parent->respcount) { 01794 trans->parent->respcount++; 01795 if (ies.q_dept) 01796 ast_copy_string(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit)); 01797 if (ies.q_org) 01798 ast_copy_string(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org)); 01799 if (ies.q_locality) 01800 ast_copy_string(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality)); 01801 if (ies.q_stateprov) 01802 ast_copy_string(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov)); 01803 if (ies.q_country) 01804 ast_copy_string(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country)); 01805 if (ies.q_email) 01806 ast_copy_string(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email)); 01807 if (ies.q_phone) 01808 ast_copy_string(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone)); 01809 if (ies.q_ipaddr) 01810 ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr)); 01811 if (!dundi_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) { 01812 /* If it's them, update our address */ 01813 ast_copy_string(trans->parent->dei->ipaddr, ast_inet_ntoa(trans->addr.sin_addr), sizeof(trans->parent->dei->ipaddr)); 01814 } 01815 } 01816 if (ies.hint) { 01817 if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED))) 01818 ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED); 01819 } 01820 } 01821 /* Close connection if not final */ 01822 if (!final) 01823 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01824 } 01825 01826 } else { 01827 /* Auth failure, check for data */ 01828 if (!final) { 01829 /* Cancel if they didn't already */ 01830 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01831 } 01832 } 01833 break; 01834 case DUNDI_COMMAND_REGRESPONSE: 01835 /* A dialplan response, lets see what we got... */ 01836 if (ies.cause < 1) { 01837 int hasauth; 01838 /* Success of some sort */ 01839 if (ast_test_flag(trans, FLAG_ENCRYPT)) { 01840 hasauth = encrypted; 01841 } else 01842 hasauth = 1; 01843 01844 if (!hasauth) { 01845 ast_log(LOG_NOTICE, "Reponse to register not authorized!\n"); 01846 if (!final) { 01847 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Improper signature in answer"); 01848 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, ied); 01849 } 01850 } else { 01851 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), 01852 dundi_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid)); 01853 /* Close connection if not final */ 01854 if (!final) 01855 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01856 } 01857 } else { 01858 /* Auth failure, cancel if they didn't for some reason */ 01859 if (!final) { 01860 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01861 } 01862 } 01863 break; 01864 case DUNDI_COMMAND_INVALID: 01865 case DUNDI_COMMAND_NULL: 01866 case DUNDI_COMMAND_PRECACHERP: 01867 /* Do nothing special */ 01868 if (!final) 01869 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01870 break; 01871 case DUNDI_COMMAND_ENCREJ: 01872 if ((ast_test_flag(trans, FLAG_SENDFULLKEY)) || AST_LIST_EMPTY(&trans->lasttrans) || !(peer = find_peer(&trans->them_eid))) { 01873 /* No really, it's over at this point */ 01874 if (!final) 01875 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 01876 } else { 01877 /* Send with full key */ 01878 ast_set_flag(trans, FLAG_SENDFULLKEY); 01879 if (final) { 01880 /* Ooops, we got a final message, start by sending ACK... */ 01881 dundi_ack(trans, hdr->cmdresp & 0x80); 01882 trans->aseqno = trans->iseqno; 01883 /* Now, we gotta create a new transaction */ 01884 if (!reset_transaction(trans)) { 01885 /* Make sure handle_frame doesn't destroy us */ 01886 hdr->cmdresp &= 0x7f; 01887 /* Parse the message we transmitted */ 01888 memset(&ies, 0, sizeof(ies)); 01889 dundi_parse_ies(&ies, (AST_LIST_FIRST(&trans->lasttrans))->h->ies, (AST_LIST_FIRST(&trans->lasttrans))->datalen - sizeof(struct dundi_hdr)); 01890 /* Reconstruct outgoing encrypted packet */ 01891 memset(ied, 0, sizeof(*ied)); 01892 dundi_ie_append_eid(ied, DUNDI_IE_EID, &trans->us_eid); 01893 dundi_ie_append_raw(ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128); 01894 dundi_ie_append_raw(ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128); 01895 if (ies.encblock) 01896 dundi_ie_append_encdata(ied, DUNDI_IE_ENCDATA, ies.encblock->iv, ies.encblock->encdata, ies.enclen); 01897 dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, (AST_LIST_FIRST(&trans->lasttrans))->h->cmdresp & 0x80, ied); 01898 peer->sentfullkey = 1; 01899 } 01900 } 01901 } 01902 break; 01903 case DUNDI_COMMAND_ENCRYPT: 01904 if (!encrypted) { 01905 /* No nested encryption! */ 01906 if ((trans->iseqno == 1) && !trans->oseqno) { 01907 if (!ies.eids[0] || !(peer = find_peer(ies.eids[0])) || 01908 ((!ies.encsharedkey || !ies.encsig) && !ies.keycrc32) || 01909 (check_key(peer, ies.encsharedkey, ies.encsig, ies.keycrc32) < 1)) { 01910 if (!final) { 01911 dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL); 01912 } 01913 break; 01914 } 01915 apply_peer(trans, peer); 01916 /* Key passed, use new contexts for this session */ 01917 trans->ecx = peer->them_ecx; 01918 trans->dcx = peer->them_dcx; 01919 } 01920 if (ast_test_flag(trans, FLAG_ENCRYPT) && ies.encblock && ies.enclen) { 01921 struct dundi_hdr *dhdr; 01922 unsigned char decoded[MAX_PACKET_SIZE]; 01923 int ddatalen; 01924 ddatalen = sizeof(decoded); 01925 dhdr = dundi_decrypt(trans, decoded, &ddatalen, hdr, ies.encblock, ies.enclen); 01926 if (dhdr) { 01927 /* Handle decrypted response */ 01928 if (dundidebug) 01929 dundi_showframe(dhdr, 3, &trans->addr, ddatalen - sizeof(struct dundi_hdr)); 01930 handle_command_response(trans, dhdr, ddatalen - sizeof(struct dundi_hdr), 1); 01931 /* Carry back final flag */ 01932 hdr->cmdresp |= dhdr->cmdresp & 0x80; 01933 break; 01934 } else 01935 ast_log(LOG_DEBUG, "Ouch, decrypt failed :(\n"); 01936 } 01937 } 01938 if (!final) { 01939 /* Turn off encryption */ 01940 ast_clear_flag(trans, FLAG_ENCRYPT); 01941 dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL); 01942 } 01943 break; 01944 default: 01945 /* Send unknown command if we don't know it, with final flag IFF it's the 01946 first command in the dialog and only if we haven't recieved final notification */ 01947 if (!final) { 01948 dundi_ie_append_byte(ied, DUNDI_IE_UNKNOWN, cmd); 01949 dundi_send(trans, DUNDI_COMMAND_UNKNOWN, 0, !hdr->oseqno, ied); 01950 } 01951 } 01952 01953 retval = 0; 01954 01955 return_cleanup: 01956 #ifdef LOW_MEMORY 01957 ast_free(ied); 01958 #endif 01959 return retval; 01960 }
static int handle_frame | ( | struct dundi_hdr * | h, | |
struct sockaddr_in * | sin, | |||
int | datalen | |||
) | [static] |
Definition at line 1995 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.
01996 { 01997 struct dundi_transaction *trans; 01998 trans = find_transaction(h, sin); 01999 if (!trans) { 02000 dundi_reject(h, sin); 02001 return 0; 02002 } 02003 /* Got a transaction, see where this header fits in */ 02004 if (h->oseqno == trans->iseqno) { 02005 /* Just what we were looking for... Anything but ack increments iseqno */ 02006 if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) { 02007 /* If final, we're done */ 02008 destroy_trans(trans, 0); 02009 return 0; 02010 } 02011 if (h->cmdresp != DUNDI_COMMAND_ACK) { 02012 trans->oiseqno = trans->iseqno; 02013 trans->iseqno++; 02014 handle_command_response(trans, h, datalen, 0); 02015 } 02016 if (trans->aseqno != trans->iseqno) { 02017 dundi_ack(trans, h->cmdresp & 0x80); 02018 trans->aseqno = trans->iseqno; 02019 } 02020 /* Delete any saved last transmissions */ 02021 destroy_packets(&trans->lasttrans); 02022 if (h->cmdresp & 0x80) { 02023 /* Final -- destroy now */ 02024 destroy_trans(trans, 0); 02025 } 02026 } else if (h->oseqno == trans->oiseqno) { 02027 /* Last incoming sequence number -- send ACK without processing */ 02028 dundi_ack(trans, 0); 02029 } else { 02030 /* Out of window -- simply drop */ 02031 ast_log(LOG_DEBUG, "Dropping packet out of window!\n"); 02032 } 02033 return 0; 02034 }
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 4572 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.
04573 { 04574 int res = 0; 04575 struct sockaddr_in sin; 04576 04577 dundi_set_output(dundi_debug_output); 04578 dundi_set_error(dundi_error_output); 04579 04580 sin.sin_family = AF_INET; 04581 sin.sin_port = ntohs(DUNDI_PORT); 04582 sin.sin_addr.s_addr = INADDR_ANY; 04583 04584 /* Make a UDP socket */ 04585 io = io_context_create(); 04586 sched = sched_context_create(); 04587 04588 if (!io || !sched) { 04589 ast_log(LOG_ERROR, "Out of memory\n"); 04590 return -1; 04591 } 04592 04593 if(set_config("dundi.conf",&sin)) 04594 return AST_MODULE_LOAD_DECLINE; 04595 04596 netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 04597 04598 if (netsocket < 0) { 04599 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 04600 return -1; 04601 } 04602 if (bind(netsocket,(struct sockaddr *)&sin, sizeof(sin))) { 04603 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)); 04604 return -1; 04605 } 04606 04607 if (option_verbose > 1) 04608 ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos); 04609 04610 if (setsockopt(netsocket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) 04611 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 04612 04613 res = start_network_thread(); 04614 if (res) { 04615 ast_log(LOG_ERROR, "Unable to start network thread\n"); 04616 close(netsocket); 04617 return -1; 04618 } 04619 04620 if (option_verbose > 1) 04621 ast_verbose(VERBOSE_PREFIX_2 "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 04622 04623 ast_cli_register_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(struct ast_cli_entry)); 04624 if (ast_register_switch(&dundi_switch)) 04625 ast_log(LOG_ERROR, "Unable to register DUNDi switch\n"); 04626 ast_custom_function_register(&dundi_function); 04627 04628 return res; 04629 }
static void load_password | ( | void | ) | [static] |
Definition at line 2092 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().
02093 { 02094 char *current=NULL; 02095 char *last=NULL; 02096 char tmp[256]; 02097 time_t expired; 02098 02099 ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp)); 02100 if (!ast_get_time_t(tmp, &expired, 0, NULL)) { 02101 ast_db_get(secretpath, "secret", tmp, sizeof(tmp)); 02102 current = strchr(tmp, ';'); 02103 if (!current) 02104 current = tmp; 02105 else { 02106 *current = '\0'; 02107 current++; 02108 }; 02109 if ((time(NULL) - expired) < 0) { 02110 if ((expired - time(NULL)) > DUNDI_SECRET_TIME) 02111 expired = time(NULL) + DUNDI_SECRET_TIME; 02112 } else if ((time(NULL) - (expired + DUNDI_SECRET_TIME)) < 0) { 02113 last = current; 02114 current = NULL; 02115 } else { 02116 last = NULL; 02117 current = NULL; 02118 } 02119 } 02120 if (current) { 02121 /* Current key is still valid, just setup rotatation properly */ 02122 ast_copy_string(cursecret, current, sizeof(cursecret)); 02123 rotatetime = expired; 02124 } else { 02125 /* Current key is out of date, rotate or eliminate all together */ 02126 build_secret(cursecret, sizeof(cursecret)); 02127 save_secret(cursecret, last); 02128 } 02129 }
static void mark_mappings | ( | void | ) | [static] |
Definition at line 3883 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().
03884 { 03885 struct dundi_mapping *map; 03886 03887 AST_LIST_LOCK(&peers); 03888 AST_LIST_TRAVERSE(&mappings, map, list) { 03889 map->dead = 1; 03890 } 03891 AST_LIST_UNLOCK(&peers); 03892 }
static void mark_peers | ( | void | ) | [static] |
Definition at line 3873 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and peers.
Referenced by set_config(), and unload_module().
03874 { 03875 struct dundi_peer *peer; 03876 AST_LIST_LOCK(&peers); 03877 AST_LIST_TRAVERSE(&peers, peer, list) { 03878 peer->dead = 1; 03879 } 03880 AST_LIST_UNLOCK(&peers); 03881 }
static char* model2str | ( | int | model | ) | [static] |
Definition at line 2287 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().
02288 { 02289 switch(model) { 02290 case DUNDI_MODEL_INBOUND: 02291 return "Inbound"; 02292 case DUNDI_MODEL_OUTBOUND: 02293 return "Outbound"; 02294 case DUNDI_MODEL_SYMMETRIC: 02295 return "Symmetric"; 02296 default: 02297 return "Unknown"; 02298 } 02299 }
static void* network_thread | ( | void * | ignore | ) | [static] |
Definition at line 2148 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().
02149 { 02150 /* Our job is simple: Send queued messages, retrying if necessary. Read frames 02151 from the network, and queue them for delivery to the channels */ 02152 int res; 02153 /* Establish I/O callback for socket read */ 02154 ast_io_add(io, netsocket, socket_read, AST_IO_IN, NULL); 02155 02156 while (!dundi_shutdown) { 02157 res = ast_sched_wait(sched); 02158 if ((res > 1000) || (res < 0)) 02159 res = 1000; 02160 res = ast_io_wait(io, res); 02161 if (res >= 0) { 02162 AST_LIST_LOCK(&peers); 02163 ast_sched_runq(sched); 02164 AST_LIST_UNLOCK(&peers); 02165 } 02166 check_password(); 02167 } 02168 02169 netthreadid = AST_PTHREADT_NULL; 02170 02171 return NULL; 02172 }
static int optimize_transactions | ( | struct dundi_request * | dr, | |
int | order | |||
) | [static] |
Definition at line 3265 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().
03266 { 03267 /* Minimize the message propagation through DUNDi by 03268 alerting the network to hops which should be not be considered */ 03269 struct dundi_transaction *trans; 03270 struct dundi_peer *peer; 03271 dundi_eid tmp; 03272 int x; 03273 int needpush; 03274 03275 AST_LIST_LOCK(&peers); 03276 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03277 /* Pop off the true root */ 03278 if (trans->eidcount) { 03279 tmp = trans->eids[--trans->eidcount]; 03280 needpush = 1; 03281 } else { 03282 tmp = trans->us_eid; 03283 needpush = 0; 03284 } 03285 03286 AST_LIST_TRAVERSE(&peers, peer, list) { 03287 if (has_permission(&peer->include, dr->dcontext) && 03288 dundi_eid_cmp(&peer->eid, &trans->them_eid) && 03289 (peer->order <= order)) { 03290 /* For each other transaction, make sure we don't 03291 ask this EID about the others if they're not 03292 already in the list */ 03293 if (!dundi_eid_cmp(&tmp, &peer->eid)) 03294 x = -1; 03295 else { 03296 for (x=0;x<trans->eidcount;x++) { 03297 if (!dundi_eid_cmp(&trans->eids[x], &peer->eid)) 03298 break; 03299 } 03300 } 03301 if (x == trans->eidcount) { 03302 /* Nope not in the list, if needed, add us at the end since we're the source */ 03303 if (trans->eidcount < DUNDI_MAX_STACK - needpush) { 03304 trans->eids[trans->eidcount++] = peer->eid; 03305 /* Need to insert the real root (or us) at the bottom now as 03306 a requirement now. */ 03307 needpush = 1; 03308 } 03309 } 03310 } 03311 } 03312 /* If necessary, push the true root back on the end */ 03313 if (needpush) 03314 trans->eids[trans->eidcount++] = tmp; 03315 } 03316 AST_LIST_UNLOCK(&peers); 03317 03318 return 0; 03319 }
static void populate_addr | ( | struct dundi_peer * | peer, | |
dundi_eid * | eid | |||
) | [static] |
Definition at line 4090 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().
04091 { 04092 char data[256]; 04093 char *c; 04094 int port, expire; 04095 char eid_str[20]; 04096 dundi_eid_to_str(eid_str, sizeof(eid_str), eid); 04097 if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) { 04098 c = strchr(data, ':'); 04099 if (c) { 04100 *c = '\0'; 04101 c++; 04102 if (sscanf(c, "%d:%d", &port, &expire) == 2) { 04103 /* Got it! */ 04104 inet_aton(data, &peer->addr.sin_addr); 04105 peer->addr.sin_family = AF_INET; 04106 peer->addr.sin_port = htons(port); 04107 peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer); 04108 } 04109 } 04110 } 04111 }
static int precache_trans | ( | struct dundi_transaction * | trans, | |
struct dundi_mapping * | maps, | |||
int | mapcount, | |||
int * | minexp, | |||
int * | foundanswers | |||
) | [static] |
Definition at line 3118 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().
03119 { 03120 struct dundi_ie_data ied; 03121 int x, res; 03122 int max = 999999; 03123 int expiration = dundi_cache_time; 03124 int ouranswers=0; 03125 dundi_eid *avoid[1] = { NULL, }; 03126 int direct[1] = { 0, }; 03127 struct dundi_result dr[MAX_RESULTS]; 03128 struct dundi_hint_metadata hmd; 03129 if (!trans->parent) { 03130 ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n"); 03131 return -1; 03132 } 03133 memset(&hmd, 0, sizeof(hmd)); 03134 memset(&dr, 0, sizeof(dr)); 03135 /* Look up the answers we're going to include */ 03136 for (x=0;x<mapcount;x++) 03137 ouranswers = dundi_lookup_local(dr, maps + x, trans->parent->number, &trans->us_eid, ouranswers, &hmd); 03138 if (ouranswers < 0) 03139 ouranswers = 0; 03140 for (x=0;x<ouranswers;x++) { 03141 if (dr[x].weight < max) 03142 max = dr[x].weight; 03143 } 03144 if (max) { 03145 /* If we do not have a canonical result, keep looking */ 03146 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); 03147 if (res > 0) { 03148 /* Append answer in result */ 03149 ouranswers += res; 03150 } 03151 } 03152 03153 if (ouranswers > 0) { 03154 *foundanswers += ouranswers; 03155 memset(&ied, 0, sizeof(ied)); 03156 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 03157 if (!dundi_eid_zero(&trans->us_eid)) 03158 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); 03159 for (x=0;x<trans->eidcount;x++) 03160 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]); 03161 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number); 03162 dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); 03163 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); 03164 for (x=0;x<ouranswers;x++) { 03165 /* Add answers */ 03166 if (dr[x].expiration && (expiration > dr[x].expiration)) 03167 expiration = dr[x].expiration; 03168 dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest); 03169 } 03170 dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten); 03171 dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration); 03172 if (trans->autokilltimeout) 03173 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); 03174 if (expiration < *minexp) 03175 *minexp = expiration; 03176 return dundi_send(trans, DUNDI_COMMAND_PRECACHERQ, 0, 0, &ied); 03177 } else { 03178 /* Oops, nothing to send... */ 03179 destroy_trans(trans, 0); 03180 return 0; 03181 } 03182 }
static int precache_transactions | ( | struct dundi_request * | dr, | |
struct dundi_mapping * | maps, | |||
int | mapcount, | |||
int * | expiration, | |||
int * | foundanswers | |||
) | [static] |
Definition at line 3217 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().
03218 { 03219 struct dundi_transaction *trans; 03220 03221 /* Mark all as "in thread" so they don't disappear */ 03222 AST_LIST_LOCK(&peers); 03223 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03224 if (trans->thread) 03225 ast_log(LOG_WARNING, "This shouldn't happen, really...\n"); 03226 trans->thread = 1; 03227 } 03228 AST_LIST_UNLOCK(&peers); 03229 03230 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03231 if (!ast_test_flag(trans, FLAG_DEAD)) 03232 precache_trans(trans, maps, mapcount, expiration, foundanswers); 03233 } 03234 03235 /* Cleanup any that got destroyed in the mean time */ 03236 AST_LIST_LOCK(&peers); 03237 AST_LIST_TRAVERSE_SAFE_BEGIN(&dr->trans, trans, parentlist) { 03238 trans->thread = 0; 03239 if (ast_test_flag(trans, FLAG_DEAD)) { 03240 ast_log(LOG_DEBUG, "Our transaction went away!\n"); 03241 /* This is going to remove the transaction from the dundi_request's list, as well 03242 * as the global transactions list */ 03243 destroy_trans(trans, 0); 03244 } 03245 } 03246 AST_LIST_TRAVERSE_SAFE_END 03247 AST_LIST_UNLOCK(&peers); 03248 03249 return 0; 03250 }
static void* process_precache | ( | void * | ign | ) | [static] |
Definition at line 2174 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().
02175 { 02176 struct dundi_precache_queue *qe; 02177 time_t now; 02178 char context[256]; 02179 char number[256]; 02180 int run; 02181 02182 while (!dundi_shutdown) { 02183 time(&now); 02184 run = 0; 02185 AST_LIST_LOCK(&pcq); 02186 if ((qe = AST_LIST_FIRST(&pcq))) { 02187 if (!qe->expiration) { 02188 /* Gone... Remove... */ 02189 AST_LIST_REMOVE_HEAD(&pcq, list); 02190 free(qe); 02191 } else if (qe->expiration < now) { 02192 /* Process this entry */ 02193 qe->expiration = 0; 02194 ast_copy_string(context, qe->context, sizeof(context)); 02195 ast_copy_string(number, qe->number, sizeof(number)); 02196 run = 1; 02197 } 02198 } 02199 AST_LIST_UNLOCK(&pcq); 02200 if (run) { 02201 dundi_precache(context, number); 02202 } else 02203 sleep(1); 02204 } 02205 02206 precachethreadid = AST_PTHREADT_NULL; 02207 02208 return NULL; 02209 }
static void prune_mappings | ( | void | ) | [static] |
Definition at line 3933 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().
03934 { 03935 struct dundi_mapping *map; 03936 03937 AST_LIST_LOCK(&peers); 03938 AST_LIST_TRAVERSE_SAFE_BEGIN(&mappings, map, list) { 03939 if (map->dead) { 03940 AST_LIST_REMOVE_CURRENT(&mappings, list); 03941 destroy_map(map); 03942 } 03943 } 03944 AST_LIST_TRAVERSE_SAFE_END 03945 AST_LIST_UNLOCK(&peers); 03946 }
static void prune_peers | ( | void | ) | [static] |
Definition at line 3918 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.
03919 { 03920 struct dundi_peer *peer; 03921 03922 AST_LIST_LOCK(&peers); 03923 AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, list) { 03924 if (peer->dead) { 03925 AST_LIST_REMOVE_CURRENT(&peers, list); 03926 destroy_peer(peer); 03927 } 03928 } 03929 AST_LIST_TRAVERSE_SAFE_END 03930 AST_LIST_UNLOCK(&peers); 03931 }
static void qualify_peer | ( | struct dundi_peer * | peer, | |
int | schedonly | |||
) | [static] |
Definition at line 4067 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().
04068 { 04069 int when; 04070 AST_SCHED_DEL(sched, peer->qualifyid); 04071 if (peer->qualtrans) 04072 destroy_trans(peer->qualtrans, 0); 04073 peer->qualtrans = NULL; 04074 if (peer->maxms > 0) { 04075 when = 60000; 04076 if (peer->lastms < 0) 04077 when = 10000; 04078 if (schedonly) 04079 when = 5000; 04080 peer->qualifyid = ast_sched_add(sched, when, do_qualify, peer); 04081 if (!schedonly) 04082 peer->qualtrans = create_transaction(peer); 04083 if (peer->qualtrans) { 04084 peer->qualtx = ast_tvnow(); 04085 ast_set_flag(peer->qualtrans, FLAG_ISQUAL); 04086 dundi_send(peer->qualtrans, DUNDI_COMMAND_NULL, 0, 1, NULL); 04087 } 04088 } 04089 }
static int query_transactions | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3252 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().
03253 { 03254 struct dundi_transaction *trans; 03255 03256 AST_LIST_LOCK(&peers); 03257 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03258 dundi_query(trans); 03259 } 03260 AST_LIST_UNLOCK(&peers); 03261 03262 return 0; 03263 }
static int register_request | ( | struct dundi_request * | dr, | |
struct dundi_request ** | pending | |||
) | [static] |
Definition at line 3433 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().
03434 { 03435 struct dundi_request *cur; 03436 int res=0; 03437 char eid_str[20]; 03438 AST_LIST_LOCK(&peers); 03439 AST_LIST_TRAVERSE(&requests, cur, list) { 03440 if (option_debug) 03441 ast_log(LOG_DEBUG, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number, 03442 dr->dcontext, dr->number); 03443 if (!strcasecmp(cur->dcontext, dr->dcontext) && 03444 !strcasecmp(cur->number, dr->number) && 03445 (!dundi_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) { 03446 ast_log(LOG_DEBUG, "Found existing query for '%s@%s' for '%s' crc '%08lx'\n", 03447 cur->dcontext, cur->number, dundi_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32); 03448 *pending = cur; 03449 res = 1; 03450 break; 03451 } 03452 } 03453 if (!res) { 03454 ast_log(LOG_DEBUG, "Registering request for '%s@%s' on behalf of '%s' crc '%08lx'\n", 03455 dr->number, dr->dcontext, dundi_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32); 03456 /* Go ahead and link us in since nobody else is searching for this */ 03457 AST_LIST_INSERT_HEAD(&requests, dr, list); 03458 *pending = NULL; 03459 } 03460 AST_LIST_UNLOCK(&peers); 03461 return res; 03462 }
static int reload | ( | void | ) | [static] |
Definition at line 4565 of file pbx_dundi.c.
References set_config().
04566 { 04567 struct sockaddr_in sin; 04568 set_config("dundi.conf",&sin); 04569 return 0; 04570 }
static void reschedule_precache | ( | const char * | number, | |
const char * | context, | |||
int | expiration | |||
) | [static] |
Definition at line 3613 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().
03614 { 03615 int len; 03616 struct dundi_precache_queue *qe, *prev; 03617 03618 AST_LIST_LOCK(&pcq); 03619 AST_LIST_TRAVERSE_SAFE_BEGIN(&pcq, qe, list) { 03620 if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) { 03621 AST_LIST_REMOVE_CURRENT(&pcq, list); 03622 break; 03623 } 03624 } 03625 AST_LIST_TRAVERSE_SAFE_END 03626 if (!qe) { 03627 len = sizeof(*qe); 03628 len += strlen(number) + 1; 03629 len += strlen(context) + 1; 03630 if (!(qe = ast_calloc(1, len))) { 03631 AST_LIST_UNLOCK(&pcq); 03632 return; 03633 } 03634 strcpy(qe->number, number); 03635 qe->context = qe->number + strlen(number) + 1; 03636 strcpy(qe->context, context); 03637 } 03638 time(&qe->expiration); 03639 qe->expiration += expiration; 03640 if ((prev = AST_LIST_FIRST(&pcq))) { 03641 while (AST_LIST_NEXT(prev, list) && ((AST_LIST_NEXT(prev, list))->expiration <= qe->expiration)) 03642 prev = AST_LIST_NEXT(prev, list); 03643 AST_LIST_INSERT_AFTER(&pcq, prev, qe, list); 03644 } else 03645 AST_LIST_INSERT_HEAD(&pcq, qe, list); 03646 AST_LIST_UNLOCK(&pcq); 03647 }
static int rescomp | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 2328 of file pbx_dundi.c.
References dundi_result::weight.
Referenced by sort_results().
02329 { 02330 const struct dundi_result *resa, *resb; 02331 resa = a; 02332 resb = b; 02333 if (resa->weight < resb->weight) 02334 return -1; 02335 if (resa->weight > resb->weight) 02336 return 1; 02337 return 0; 02338 }
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 2079 of file pbx_dundi.c.
References ast_db_put(), and DUNDI_SECRET_TIME.
Referenced by check_password(), and load_password().
02080 { 02081 char tmp[256]; 02082 if (oldkey) 02083 snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey); 02084 else 02085 snprintf(tmp, sizeof(tmp), "%s", newkey); 02086 rotatetime = time(NULL) + DUNDI_SECRET_TIME; 02087 ast_db_put(secretpath, "secret", tmp); 02088 snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime); 02089 ast_db_put(secretpath, "secretexpiry", tmp); 02090 }
static int set_config | ( | char * | config_file, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 4376 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.
04377 { 04378 struct ast_config *cfg; 04379 struct ast_variable *v; 04380 char *cat; 04381 int format; 04382 int x; 04383 char hn[MAXHOSTNAMELEN] = ""; 04384 struct ast_hostent he; 04385 struct hostent *hp; 04386 struct sockaddr_in sin2; 04387 static int last_port = 0; 04388 int globalpcmodel = 0; 04389 dundi_eid testeid; 04390 04391 dundi_ttl = DUNDI_DEFAULT_TTL; 04392 dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME; 04393 any_peer = NULL; 04394 04395 cfg = ast_config_load(config_file); 04396 04397 if (!cfg) { 04398 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); 04399 return -1; 04400 } 04401 ipaddr[0] = '\0'; 04402 if (!gethostname(hn, sizeof(hn)-1)) { 04403 hp = ast_gethostbyname(hn, &he); 04404 if (hp) { 04405 memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr)); 04406 ast_copy_string(ipaddr, ast_inet_ntoa(sin2.sin_addr), sizeof(ipaddr)); 04407 } else 04408 ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn); 04409 } else 04410 ast_log(LOG_WARNING, "Unable to get host name!\n"); 04411 AST_LIST_LOCK(&peers); 04412 reset_global_eid(); 04413 global_storehistory = 0; 04414 ast_copy_string(secretpath, "dundi", sizeof(secretpath)); 04415 v = ast_variable_browse(cfg, "general"); 04416 while(v) { 04417 if (!strcasecmp(v->name, "port")){ 04418 sin->sin_port = ntohs(atoi(v->value)); 04419 if(last_port==0){ 04420 last_port=sin->sin_port; 04421 } else if(sin->sin_port != last_port) 04422 ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n"); 04423 } else if (!strcasecmp(v->name, "bindaddr")) { 04424 struct hostent *hp; 04425 struct ast_hostent he; 04426 hp = ast_gethostbyname(v->value, &he); 04427 if (hp) { 04428 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 04429 } else 04430 ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value); 04431 } else if (!strcasecmp(v->name, "authdebug")) { 04432 authdebug = ast_true(v->value); 04433 } else if (!strcasecmp(v->name, "ttl")) { 04434 if ((sscanf(v->value, "%d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) { 04435 dundi_ttl = x; 04436 } else { 04437 ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n", 04438 v->value, v->lineno, DUNDI_DEFAULT_TTL); 04439 } 04440 } else if (!strcasecmp(v->name, "autokill")) { 04441 if (sscanf(v->value, "%d", &x) == 1) { 04442 if (x >= 0) 04443 global_autokilltimeout = x; 04444 else 04445 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); 04446 } else if (ast_true(v->value)) { 04447 global_autokilltimeout = DEFAULT_MAXMS; 04448 } else { 04449 global_autokilltimeout = 0; 04450 } 04451 } else if (!strcasecmp(v->name, "entityid")) { 04452 if (!dundi_str_to_eid(&testeid, v->value)) 04453 global_eid = testeid; 04454 else 04455 ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno); 04456 } else if (!strcasecmp(v->name, "tos")) { 04457 if (sscanf(v->value, "%d", &format) == 1) 04458 tos = format & 0xff; 04459 else if (!strcasecmp(v->value, "lowdelay")) 04460 tos = IPTOS_LOWDELAY; 04461 else if (!strcasecmp(v->value, "throughput")) 04462 tos = IPTOS_THROUGHPUT; 04463 else if (!strcasecmp(v->value, "reliability")) 04464 tos = IPTOS_RELIABILITY; 04465 #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS) 04466 else if (!strcasecmp(v->value, "mincost")) 04467 tos = IPTOS_MINCOST; 04468 #endif 04469 else if (!strcasecmp(v->value, "none")) 04470 tos = 0; 04471 else 04472 #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS) 04473 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno); 04474 #else 04475 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', or 'none'\n", v->lineno); 04476 #endif 04477 } else if (!strcasecmp(v->name, "department")) { 04478 ast_copy_string(dept, v->value, sizeof(dept)); 04479 } else if (!strcasecmp(v->name, "organization")) { 04480 ast_copy_string(org, v->value, sizeof(org)); 04481 } else if (!strcasecmp(v->name, "locality")) { 04482 ast_copy_string(locality, v->value, sizeof(locality)); 04483 } else if (!strcasecmp(v->name, "stateprov")) { 04484 ast_copy_string(stateprov, v->value, sizeof(stateprov)); 04485 } else if (!strcasecmp(v->name, "country")) { 04486 ast_copy_string(country, v->value, sizeof(country)); 04487 } else if (!strcasecmp(v->name, "email")) { 04488 ast_copy_string(email, v->value, sizeof(email)); 04489 } else if (!strcasecmp(v->name, "phone")) { 04490 ast_copy_string(phone, v->value, sizeof(phone)); 04491 } else if (!strcasecmp(v->name, "storehistory")) { 04492 global_storehistory = ast_true(v->value); 04493 } else if (!strcasecmp(v->name, "cachetime")) { 04494 if ((sscanf(v->value, "%d", &x) == 1)) { 04495 dundi_cache_time = x; 04496 } else { 04497 ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n", 04498 v->value, v->lineno, DUNDI_DEFAULT_CACHE_TIME); 04499 } 04500 } 04501 v = v->next; 04502 } 04503 AST_LIST_UNLOCK(&peers); 04504 mark_mappings(); 04505 v = ast_variable_browse(cfg, "mappings"); 04506 while(v) { 04507 build_mapping(v->name, v->value); 04508 v = v->next; 04509 } 04510 prune_mappings(); 04511 mark_peers(); 04512 cat = ast_category_browse(cfg, NULL); 04513 while(cat) { 04514 if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) { 04515 /* Entries */ 04516 if (!dundi_str_to_eid(&testeid, cat)) 04517 build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel); 04518 else if (!strcasecmp(cat, "*")) { 04519 build_peer(&empty_eid, ast_variable_browse(cfg, cat), &globalpcmodel); 04520 any_peer = find_peer(NULL); 04521 } else 04522 ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat); 04523 } 04524 cat = ast_category_browse(cfg, cat); 04525 } 04526 prune_peers(); 04527 ast_config_destroy(cfg); 04528 load_password(); 04529 if (globalpcmodel & DUNDI_MODEL_OUTBOUND) 04530 dundi_precache_full(); 04531 return 0; 04532 }
static int socket_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 2036 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.
02037 { 02038 struct sockaddr_in sin; 02039 int res; 02040 struct dundi_hdr *h; 02041 char buf[MAX_PACKET_SIZE]; 02042 socklen_t len; 02043 len = sizeof(sin); 02044 res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len); 02045 if (res < 0) { 02046 if (errno != ECONNREFUSED) 02047 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); 02048 return 1; 02049 } 02050 if (res < sizeof(struct dundi_hdr)) { 02051 ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct dundi_hdr)); 02052 return 1; 02053 } 02054 buf[res] = '\0'; 02055 h = (struct dundi_hdr *)buf; 02056 if (dundidebug) 02057 dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr)); 02058 AST_LIST_LOCK(&peers); 02059 handle_frame(h, &sin, res - sizeof(struct dundi_hdr)); 02060 AST_LIST_UNLOCK(&peers); 02061 return 1; 02062 }
static void sort_results | ( | struct dundi_result * | results, | |
int | count | |||
) | [static] |
Definition at line 2340 of file pbx_dundi.c.
References rescomp().
Referenced by dundi_do_lookup(), dundi_exec(), and dundifunc_read().
02341 { 02342 qsort(results, count, sizeof(results[0]), rescomp); 02343 }
static int start_network_thread | ( | void | ) | [static] |
Definition at line 2211 of file pbx_dundi.c.
References ast_pthread_create_background, network_thread(), and process_precache().
02212 { 02213 ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); 02214 ast_pthread_create_background(&precachethreadid, NULL, process_precache, NULL); 02215 return 0; 02216 }
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 4534 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().
04535 { 04536 pthread_t previous_netthreadid = netthreadid, previous_precachethreadid = precachethreadid; 04537 ast_module_user_hangup_all(); 04538 04539 /* Stop all currently running threads */ 04540 dundi_shutdown = 1; 04541 if (previous_netthreadid != AST_PTHREADT_NULL) { 04542 pthread_kill(previous_netthreadid, SIGURG); 04543 pthread_join(previous_netthreadid, NULL); 04544 } 04545 if (previous_precachethreadid != AST_PTHREADT_NULL) { 04546 pthread_kill(previous_precachethreadid, SIGURG); 04547 pthread_join(previous_precachethreadid, NULL); 04548 } 04549 04550 ast_cli_unregister_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(struct ast_cli_entry)); 04551 ast_unregister_switch(&dundi_switch); 04552 ast_custom_function_unregister(&dundi_function); 04553 close(netsocket); 04554 io_context_destroy(io); 04555 sched_context_destroy(sched); 04556 04557 mark_mappings(); 04558 prune_mappings(); 04559 mark_peers(); 04560 prune_peers(); 04561 04562 return 0; 04563 }
static void unregister_request | ( | struct dundi_request * | dr | ) | [static] |
Definition at line 3464 of file pbx_dundi.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, dr, and peers.
Referenced by dundi_lookup_internal().
03465 { 03466 AST_LIST_LOCK(&peers); 03467 AST_LIST_REMOVE(&requests, dr, list); 03468 AST_LIST_UNLOCK(&peers); 03469 }
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 2699 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 2763 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 2745 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 2703 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 2712 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 2751 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 2757 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 2733 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 2725 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 2737 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 2717 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 2729 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 2741 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 2721 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 2707 of file pbx_dundi.c.
int tos = 0 [static] |
Definition at line 114 of file pbx_dundi.c.