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