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