![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
pbx_dundi.c File Reference
Definition in file pbx_dundi.c.
#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <netinet/ip.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <zlib.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/md5.h"
#include "asterisk/dundi.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/utils.h"
#include "asterisk/crypto.h"
#include "asterisk/astdb.h"
#include "asterisk/acl.h"
#include "asterisk/aes.h"
#include "dundi-parser.h"
Include dependency graph for pbx_dundi.c:

Go to the source code of this file.
Data Structures | |
| struct | dundi_hint_metadata |
| struct | dundi_mapping |
| struct | dundi_packet |
| struct | dundi_peer |
| struct | dundi_precache_queue |
| struct | dundi_query_state |
| struct | dundi_request |
| struct | dundi_transaction |
| struct | permission |
Defines | |
| #define | DUNDI_FLAG_INTERNAL_NOPARTIAL (1 << 17) |
| #define | DUNDI_MODEL_INBOUND (1 << 0) |
| #define | DUNDI_MODEL_OUTBOUND (1 << 1) |
| #define | DUNDI_MODEL_SYMMETRIC (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND) |
| #define | DUNDI_SECRET_TIME DUNDI_DEFAULT_CACHE_TIME |
| #define | DUNDI_TIMING_HISTORY 10 |
| #define | 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 | MAX_OPTS 128 |
| #define | MAX_PACKET_SIZE 8192 |
| #define | MAX_RESULTS 64 |
Enumerations | |
| enum | { FLAG_ISREG = (1 << 0), FLAG_DEAD = (1 << 1), FLAG_FINAL = (1 << 2), FLAG_ISQUAL = (1 << 3), FLAG_ENCRYPT = (1 << 4), FLAG_SENDFULLKEY = (1 << 5), FLAG_STOREHIST = (1 << 6) } |
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, const 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 const char | debug_usage [] |
| static int | default_expiration = 60 |
| static char | dept [80] |
| static int | dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME |
| static struct ast_custom_function | dundi_function |
| static int | dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE |
| static struct ast_switch | dundi_switch |
| static int | dundi_ttl = DUNDI_DEFAULT_TTL |
| static int | dundidebug = 0 |
| static char | email [80] |
| static dundi_eid | empty_eid = { { 0, 0, 0, 0, 0, 0 } } |
| static const 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 const char | lookup_usage [] |
| static int | netsocket = -1 |
| static pthread_t | netthreadid = AST_PTHREADT_NULL |
| static const char | no_debug_usage [] |
| static const char | no_store_history_usage [] |
| static char | org [80] |
| static char | phone [80] |
| static const char | precache_usage [] |
| static pthread_t | precachethreadid = AST_PTHREADT_NULL |
| static const char | query_usage [] |
| static time_t | rotatetime |
| static struct sched_context * | sched |
| static char | secretpath [80] |
| static const char | show_entityid_usage [] |
| static const char | show_mappings_usage [] |
| static const char | show_peer_usage [] |
| static const char | show_peers_usage [] |
| static const char | show_precache_usage [] |
| static const char | show_requests_usage [] |
| static const char | show_trans_usage [] |
| static char | stateprov [80] |
| static const char | store_history_usage [] |
| static int | tos = 0 |
|
|
Definition at line 99 of file pbx_dundi.c. Referenced by build_mapping(), and dundi_lookup_local(). |
|
|
Definition at line 82 of file pbx_dundi.c. Referenced by dundi_show_peer(), handle_command_response(), and model2str(). |
|
|
Definition at line 83 of file pbx_dundi.c. Referenced by build_transactions(), dundi_show_peer(), model2str(), and set_config(). |
|
|
Definition at line 84 of file pbx_dundi.c. Referenced by model2str(). |
|
|
Definition at line 104 of file pbx_dundi.c. Referenced by load_password(), and save_secret(). |
|
|
Keep times of last 10 lookups Definition at line 87 of file pbx_dundi.c. Referenced by destroy_trans(), dundi_flush(), and dundi_show_peer(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 3914 of file pbx_dundi.c. Referenced by build_mapping(). |
|
|
Definition at line 80 of file pbx_dundi.c. Referenced by socket_read(). |
|
|
Definition at line 78 of file pbx_dundi.c. Referenced by dundi_do_lookup(), dundi_exec(), dundi_helper(), dundi_lookup_thread(), dundi_precache_internal(), dundi_prop_precache(), dundifunc_read(), and precache_trans(). |
|
|
Definition at line 89 of file pbx_dundi.c. 00089 { 00090 FLAG_ISREG = (1 << 0), /*!< Transaction is register request */ 00091 FLAG_DEAD = (1 << 1), /*!< Transaction is dead */ 00092 FLAG_FINAL = (1 << 2), /*!< Transaction has final message sent */ 00093 FLAG_ISQUAL = (1 << 3), /*!< Transaction is a qualification */ 00094 FLAG_ENCRYPT = (1 << 4), /*!< Transaction is encrypted wiht ECX/DCX */ 00095 FLAG_SENDFULLKEY = (1 << 5), /*!< Send full key on transaction */ 00096 FLAG_STOREHIST = (1 << 6), /*!< Record historic performance */ 00097 };
|
|
|
Definition at line 3311 of file pbx_dundi.c. References AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, destroy_trans(), and dr. Referenced by dundi_lookup_internal(). 03312 { 03313 struct dundi_transaction *trans; 03314 03315 AST_LIST_LOCK(&peers); 03316 while ((trans = AST_LIST_FIRST(&dr->trans))) { 03317 /* This will remove the transaction from the list */ 03318 destroy_trans(trans, 0); 03319 } 03320 AST_LIST_UNLOCK(&peers); 03321 }
|
|
||||||||||||
|
Definition at line 1914 of file pbx_dundi.c. References AST_LIST_EMPTY, AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_log(), ast_sched_del(), dundi_transaction::autokillid, destroy_packet(), destroy_packets(), LOG_WARNING, and sched. Referenced by handle_frame(). 01915 { 01916 struct dundi_packet *pack; 01917 01918 /* Ack transmitted packet corresponding to iseqno */ 01919 AST_LIST_TRAVERSE(&trans->packets, pack, list) { 01920 if ((pack->h->oseqno + 1) % 255 == iseqno) { 01921 destroy_packet(pack, 0); 01922 if (!AST_LIST_EMPTY(&trans->lasttrans)) { 01923 ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n"); 01924 destroy_packets(&trans->lasttrans); 01925 } 01926 AST_LIST_INSERT_HEAD(&trans->lasttrans, pack, list); 01927 if (trans->autokillid > -1) 01928 ast_sched_del(sched, trans->autokillid); 01929 trans->autokillid = -1; 01930 return 1; 01931 } 01932 } 01933 01934 return 0; 01935 }
|
|
||||||||||||||||
|
Definition at line 3901 of file pbx_dundi.c. References ast_calloc, and AST_LIST_INSERT_TAIL. 03902 { 03903 struct permission *perm; 03904 03905 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(s) + 1))) 03906 return; 03907 03908 strcpy(perm->name, s); 03909 perm->allow = allow; 03910 03911 AST_LIST_INSERT_TAIL(permlist, perm, list); 03912 }
|
|
||||||||||||||||||||
|
Definition at line 3264 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, option_debug, and dundi_transaction::ttl. Referenced by build_transactions(). 03265 { 03266 struct dundi_transaction *trans; 03267 int x; 03268 char eid_str[20]; 03269 char eid_str2[20]; 03270 03271 /* Ignore if not registered */ 03272 if (!p->addr.sin_addr.s_addr) 03273 return 0; 03274 if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms))) 03275 return 0; 03276 03277 if (option_debug) { 03278 if (ast_strlen_zero(dr->number)) 03279 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); 03280 else 03281 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); 03282 } 03283 03284 trans = create_transaction(p); 03285 if (!trans) 03286 return -1; 03287 trans->parent = dr; 03288 trans->ttl = ttl; 03289 for (x = 0; avoid[x] && (x < DUNDI_MAX_STACK); x++) 03290 trans->eids[x] = *avoid[x]; 03291 trans->eidcount = x; 03292 AST_LIST_INSERT_HEAD(&dr->trans, trans, parentlist); 03293 03294 return 0; 03295 }
|
|
||||||||||||
|
Definition at line 1247 of file pbx_dundi.c. References dundi_peer::addr, dundi_transaction::addr, ast_set_flag, ast_strlen_zero(), dundi_transaction::autokilltimeout, DUNDI_DEFAULT_RETRANS_TIMER, dundi_peer::eid, FLAG_ENCRYPT, dundi_transaction::retranstimer, dundi_transaction::them_eid, and dundi_transaction::us_eid. Referenced by create_transaction(). 01248 { 01249 if (!trans->addr.sin_addr.s_addr) 01250 memcpy(&trans->addr, &p->addr, sizeof(trans->addr)); 01251 trans->us_eid = p->us_eid; 01252 trans->them_eid = p->eid; 01253 /* Enable encryption if appropriate */ 01254 if (!ast_strlen_zero(p->inkey)) 01255 ast_set_flag(trans, FLAG_ENCRYPT); 01256 if (p->maxms) { 01257 trans->autokilltimeout = p->maxms; 01258 trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; 01259 if (p->lastms > 1) { 01260 trans->retranstimer = p->lastms * 2; 01261 /* Keep it from being silly */ 01262 if (trans->retranstimer < 150) 01263 trans->retranstimer = 150; 01264 } 01265 if (trans->retranstimer > DUNDI_DEFAULT_RETRANS_TIMER) 01266 trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; 01267 } else 01268 trans->autokilltimeout = global_autokilltimeout; 01269 }
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||||||||||||||
|
|
|
|
Definition at line 3436 of file pbx_dundi.c. References dundi_request::crc32. Referenced by dundi_lookup_internal(). 03437 { 03438 /* Idea is that we're calculating a checksum which is independent of 03439 the order that the EID's are listed in */ 03440 unsigned long acrc32 = 0; 03441 int x; 03442 for (x=0;avoid[x];x++) { 03443 /* Order doesn't matter */ 03444 if (avoid[x+1]) { 03445 acrc32 ^= crc32(0L, (unsigned char *)avoid[x], sizeof(dundi_eid)); 03446 } 03447 } 03448 return acrc32; 03449 }
|
|
|
Definition at line 488 of file pbx_dundi.c. References ast_random(). Referenced by build_secret(), dundi_encrypt(), and update_key(). 00489 { 00490 /* XXX Would be nice to be more random XXX */ 00491 unsigned int *fluffy; 00492 int x; 00493 fluffy = (unsigned int *)(iv); 00494 for (x=0;x<4;x++) 00495 fluffy[x] = ast_random(); 00496 }
|
|
||||||||||||
|
Definition at line 3916 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, and str2tech(). Referenced by set_config(). 03917 { 03918 char *t, *fields[MAX_OPTS]; 03919 struct dundi_mapping *map; 03920 int x; 03921 int y; 03922 03923 t = ast_strdupa(value); 03924 03925 AST_LIST_TRAVERSE(&mappings, map, list) { 03926 /* Find a double match */ 03927 if (!strcasecmp(map->dcontext, name) && 03928 (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) && 03929 (!value[strlen(map->lcontext)] || 03930 (value[strlen(map->lcontext)] == ',')))) 03931 break; 03932 } 03933 if (!map) { 03934 if (!(map = ast_calloc(1, sizeof(*map)))) 03935 return; 03936 AST_LIST_INSERT_HEAD(&mappings, map, list); 03937 map->dead = 1; 03938 } 03939 map->options = 0; 03940 memset(fields, 0, sizeof(fields)); 03941 x = 0; 03942 while (t && x < MAX_OPTS) { 03943 fields[x++] = t; 03944 t = strchr(t, ','); 03945 if (t) { 03946 *t = '\0'; 03947 t++; 03948 } 03949 } /* Russell was here, arrrr! */ 03950 if ((x == 1) && ast_strlen_zero(fields[0])) { 03951 /* Placeholder mapping */ 03952 ast_copy_string(map->dcontext, name, sizeof(map->dcontext)); 03953 map->dead = 0; 03954 } else if (x >= 4) { 03955 ast_copy_string(map->dcontext, name, sizeof(map->dcontext)); 03956 ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext)); 03957 if ((sscanf(fields[1], "%d", &map->weight) == 1) && (map->weight >= 0) && (map->weight < 60000)) { 03958 ast_copy_string(map->dest, fields[3], sizeof(map->dest)); 03959 if ((map->tech = str2tech(fields[2]))) { 03960 map->dead = 0; 03961 } 03962 } else { 03963 ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext); 03964 } 03965 for (y = 4;y < x; y++) { 03966 if (!strcasecmp(fields[y], "nounsolicited")) 03967 map->options |= DUNDI_FLAG_NOUNSOLICITED; 03968 else if (!strcasecmp(fields[y], "nocomunsolicit")) 03969 map->options |= DUNDI_FLAG_NOCOMUNSOLICIT; 03970 else if (!strcasecmp(fields[y], "residential")) 03971 map->options |= DUNDI_FLAG_RESIDENTIAL; 03972 else if (!strcasecmp(fields[y], "commercial")) 03973 map->options |= DUNDI_FLAG_COMMERCIAL; 03974 else if (!strcasecmp(fields[y], "mobile")) 03975 map->options |= DUNDI_FLAG_MOBILE; 03976 else if (!strcasecmp(fields[y], "nopartial")) 03977 map->options |= DUNDI_FLAG_INTERNAL_NOPARTIAL; 03978 else 03979 ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]); 03980 } 03981 } else 03982 ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x); 03983 }
|
|
||||||||||||||||
|
Definition at line 4071 of file pbx_dundi.c. References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_sched_del(), destroy_permissions(), dundi_eid_cmp(), DUNDI_PORT, dundi_peer::eid, global_eid, hp, ast_variable::name, ast_variable::next, populate_addr(), sched, and ast_variable::value. 04072 { 04073 struct dundi_peer *peer; 04074 struct ast_hostent he; 04075 struct hostent *hp; 04076 dundi_eid testeid; 04077 int needregister=0; 04078 char eid_str[20]; 04079 04080 AST_LIST_LOCK(&peers); 04081 AST_LIST_TRAVERSE(&peers, peer, list) { 04082 if (!dundi_eid_cmp(&peer->eid, eid)) { 04083 break; 04084 } 04085 } 04086 if (!peer) { 04087 /* Add us into the list */ 04088 if (!(peer = ast_calloc(1, sizeof(*peer)))) { 04089 AST_LIST_UNLOCK(&peers); 04090 return; 04091 } 04092 peer->registerid = -1; 04093 peer->registerexpire = -1; 04094 peer->qualifyid = -1; 04095 peer->addr.sin_family = AF_INET; 04096 peer->addr.sin_port = htons(DUNDI_PORT); 04097 populate_addr(peer, eid); 04098 AST_LIST_INSERT_HEAD(&peers, peer, list); 04099 } 04100 peer->dead = 0; 04101 peer->eid = *eid; 04102 peer->us_eid = global_eid; 04103 destroy_permissions(&peer->permit); 04104 destroy_permissions(&peer->include); 04105 if (peer->registerid > -1) 04106 ast_sched_del(sched, peer->registerid); 04107 peer->registerid = -1; 04108 for (; v; v = v->next) { 04109 if (!strcasecmp(v->name, "inkey")) { 04110 ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey)); 04111 } else if (!strcasecmp(v->name, "outkey")) { 04112 ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey)); 04113 } else if (!strcasecmp(v->name, "host")) { 04114 if (!strcasecmp(v->value, "dynamic")) { 04115 peer->dynamic = 1; 04116 } else { 04117 hp = ast_gethostbyname(v->value, &he); 04118 if (hp) { 04119 memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr)); 04120 peer->dynamic = 0; 04121 } else { 04122 ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno); 04123 peer->dead = 1; 04124 } 04125 } 04126 } else if (!strcasecmp(v->name, "ustothem")) { 04127 if (!dundi_str_to_eid(&testeid, v->value)) 04128 peer->us_eid = testeid; 04129 else 04130 ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno); 04131 } else if (!strcasecmp(v->name, "include")) { 04132 append_permission(&peer->include, v->value, 1); 04133 } else if (!strcasecmp(v->name, "permit")) { 04134 append_permission(&peer->permit, v->value, 1); 04135 } else if (!strcasecmp(v->name, "noinclude")) { 04136 append_permission(&peer->include, v->value, 0); 04137 } else if (!strcasecmp(v->name, "deny")) { 04138 append_permission(&peer->permit, v->value, 0); 04139 } else if (!strcasecmp(v->name, "register")) { 04140 needregister = ast_true(v->value); 04141 } else if (!strcasecmp(v->name, "order")) { 04142 if (!strcasecmp(v->value, "primary")) 04143 peer->order = 0; 04144 else if (!strcasecmp(v->value, "secondary")) 04145 peer->order = 1; 04146 else if (!strcasecmp(v->value, "tertiary")) 04147 peer->order = 2; 04148 else if (!strcasecmp(v->value, "quartiary")) 04149 peer->order = 3; 04150 else { 04151 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); 04152 } 04153 } else if (!strcasecmp(v->name, "qualify")) { 04154 if (!strcasecmp(v->value, "no")) { 04155 peer->maxms = 0; 04156 } else if (!strcasecmp(v->value, "yes")) { 04157 peer->maxms = DEFAULT_MAXMS; 04158 } else if (sscanf(v->value, "%d", &peer->maxms) != 1) { 04159 ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n", 04160 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno); 04161 peer->maxms = 0; 04162 } 04163 } else if (!strcasecmp(v->name, "model")) { 04164 if (!strcasecmp(v->value, "inbound")) 04165 peer->model = DUNDI_MODEL_INBOUND; 04166 else if (!strcasecmp(v->value, "outbound")) 04167 peer->model = DUNDI_MODEL_OUTBOUND; 04168 else if (!strcasecmp(v->value, "symmetric")) 04169 peer->model = DUNDI_MODEL_SYMMETRIC; 04170 else if (!strcasecmp(v->value, "none")) 04171 peer->model = 0; 04172 else { 04173 ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 04174 v->value, v->lineno); 04175 } 04176 } else if (!strcasecmp(v->name, "precache")) { 04177 if (!strcasecmp(v->value, "inbound")) 04178 peer->pcmodel = DUNDI_MODEL_INBOUND; 04179 else if (!strcasecmp(v->value, "outbound")) 04180 peer->pcmodel = DUNDI_MODEL_OUTBOUND; 04181 else if (!strcasecmp(v->value, "symmetric")) 04182 peer->pcmodel = DUNDI_MODEL_SYMMETRIC; 04183 else if (!strcasecmp(v->value, "none")) 04184 peer->pcmodel = 0; 04185 else { 04186 ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 04187 v->value, v->lineno); 04188 } 04189 } 04190 } 04191 (*globalpcmode) |= peer->pcmodel; 04192 if (!peer->model && !peer->pcmodel) { 04193 ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n", 04194 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04195 peer->dead = 1; 04196 } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) { 04197 ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n", 04198 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04199 peer->dead = 1; 04200 } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) { 04201 ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n", 04202 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04203 peer->dead = 1; 04204 } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) { 04205 ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n", 04206 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04207 } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) { 04208 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", 04209 dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 04210 } else { 04211 if (needregister) { 04212 peer->registerid = ast_sched_add(sched, 2000, do_register, peer); 04213 } 04214 qualify_peer(peer, 1); 04215 } 04216 AST_LIST_UNLOCK(&peers); 04217 }
|
|
||||||||||||
|
Definition at line 2007 of file pbx_dundi.c. References ast_base64encode(), build_iv(), and s. Referenced by check_password(), and load_password(). 02008 { 02009 unsigned char tmp[16]; 02010 char *s; 02011 build_iv(tmp); 02012 secret[0] = '\0'; 02013 ast_base64encode(secret, tmp, sizeof(tmp), seclen); 02014 /* Eliminate potential bad characters */ 02015 while((s = strchr(secret, ';'))) *s = '+'; 02016 while((s = strchr(secret, '/'))) *s = '+'; 02017 while((s = strchr(secret, ':'))) *s = '+'; 02018 while((s = strchr(secret, '@'))) *s = '+'; 02019 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Definition at line 3323 of file pbx_dundi.c. References append_transaction(), ast_clear_flag_nonstd, AST_LIST_LOCK, AST_LIST_TRAVERSE, ast_log(), cache_lookup(), dr, dundi_eid_cmp(), dundi_eid_to_str(), dundi_eid_zero(), DUNDI_HINT_UNAFFECTED, DUNDI_MODEL_OUTBOUND, dundi_peer::eid, has_permission(), and option_debug. Referenced by dundi_lookup_internal(), dundi_precache_internal(), and dundi_query_eid_internal(). 03324 { 03325 struct dundi_peer *p; 03326 int x; 03327 int res; 03328 int pass; 03329 int allowconnect; 03330 char eid_str[20]; 03331 AST_LIST_LOCK(&peers); 03332 AST_LIST_TRAVERSE(&peers, p, list) { 03333 if (modeselect == 1) { 03334 /* Send the precache to push upstreams only! */ 03335 pass = has_permission(&p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND); 03336 allowconnect = 1; 03337 } else { 03338 /* Normal lookup / EID query */ 03339 pass = has_permission(&p->include, dr->dcontext); 03340 allowconnect = p->model & DUNDI_MODEL_OUTBOUND; 03341 } 03342 if (skip) { 03343 if (!dundi_eid_cmp(skip, &p->eid)) 03344 pass = 0; 03345 } 03346 if (pass) { 03347 if (p->order <= order) { 03348 /* Check order first, then check cache, regardless of 03349 omissions, this gets us more likely to not have an 03350 affected answer. */ 03351 if((nocache || !(res = cache_lookup(dr, &p->eid, dr->crc32, &dr->expiration)))) { 03352 res = 0; 03353 /* Make sure we haven't already seen it and that it won't 03354 affect our answer */ 03355 for (x=0;avoid[x];x++) { 03356 if (!dundi_eid_cmp(avoid[x], &p->eid) || !dundi_eid_cmp(avoid[x], &p->us_eid)) { 03357 /* If not a direct connection, it affects our answer */ 03358 if (directs && !directs[x]) 03359 ast_clear_flag_nonstd(dr->hmd, DUNDI_HINT_UNAFFECTED); 03360 break; 03361 } 03362 } 03363 /* Make sure we can ask */ 03364 if (allowconnect) { 03365 if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) { 03366 /* Check for a matching or 0 cache entry */ 03367 append_transaction(dr, p, ttl, avoid); 03368 } else { 03369 if (option_debug) 03370 ast_log(LOG_DEBUG, "Avoiding '%s' in transaction\n", dundi_eid_to_str(eid_str, sizeof(eid_str), avoid[x])); 03371 } 03372 } 03373 } 03374 *foundcache |= res; 03375 } else if (!*skipped || (p->order < *skipped)) 03376 *skipped = p->order; 03377 } 03378 } 03379 AST_LIST_UNLOCK(&peers); 03380 }
|
|
||||||||||||||||||||
|
Definition at line 1195 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(). 01196 { 01197 char key[256]; 01198 char eid_str[20]; 01199 char eidroot_str[20]; 01200 time_t now; 01201 int res=0; 01202 int res2=0; 01203 char eid_str_full[20]; 01204 char tmp[256]=""; 01205 int x; 01206 01207 time(&now); 01208 dundi_eid_to_str_short(eid_str, sizeof(eid_str), peer_eid); 01209 dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); 01210 dundi_eid_to_str(eid_str_full, sizeof(eid_str_full), peer_eid); 01211 snprintf(key, sizeof(key), "%s/%s/%s/e%08lx", eid_str, req->number, req->dcontext, crc32); 01212 res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01213 snprintf(key, sizeof(key), "%s/%s/%s/e%08lx", eid_str, req->number, req->dcontext, 0L); 01214 res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01215 snprintf(key, sizeof(key), "%s/%s/%s/r%s", eid_str, req->number, req->dcontext, eidroot_str); 01216 res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01217 x = 0; 01218 if (!req->respcount) { 01219 while(!res2) { 01220 /* Look and see if we have a hint that would preclude us from looking at this 01221 peer for this number. */ 01222 if (!(tmp[x] = req->number[x])) 01223 break; 01224 x++; 01225 /* Check for hints */ 01226 snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08lx", eid_str, tmp, req->dcontext, crc32); 01227 res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01228 snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08lx", eid_str, tmp, req->dcontext, 0L); 01229 res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01230 snprintf(key, sizeof(key), "hint/%s/%s/%s/r%s", eid_str, tmp, req->dcontext, eidroot_str); 01231 res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); 01232 if (res2) { 01233 if (strlen(tmp) > strlen(req->hmd->exten)) { 01234 /* Update meta data if appropriate */ 01235 ast_copy_string(req->hmd->exten, tmp, sizeof(req->hmd->exten)); 01236 } 01237 } 01238 } 01239 res |= res2; 01240 } 01241 01242 return res; 01243 }
|
|
||||||||||||||||||||||||
|
Definition at line 1121 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_request::hmd, LOG_DEBUG, option_debug, dundi_request::respcount, tech2str(), dundi_result::techint, and dundi_result::weight. Referenced by cache_lookup(). 01122 { 01123 char data[1024]; 01124 char *ptr, *term, *src; 01125 int tech; 01126 struct ast_flags flags; 01127 int weight; 01128 int length; 01129 int z; 01130 char fs[256]; 01131 01132 /* Build request string */ 01133 if (!ast_db_get("dundi/cache", key, data, sizeof(data))) { 01134 time_t timeout; 01135 ptr = data; 01136 if (!ast_get_time_t(ptr, &timeout, 0, &length)) { 01137 int expiration = timeout - now; 01138 if (expiration > 0) { 01139 if (option_debug) 01140 ast_log(LOG_DEBUG, "Found cache expiring in %d seconds!\n", expiration); 01141 ptr += length + 1; 01142 while((sscanf(ptr, "%d/%d/%d/%n", &(flags.flags), &weight, &tech, &length) == 3)) { 01143 ptr += length; 01144 term = strchr(ptr, '|'); 01145 if (term) { 01146 *term = '\0'; 01147 src = strrchr(ptr, '/'); 01148 if (src) { 01149 *src = '\0'; 01150 src++; 01151 } else 01152 src = ""; 01153 if (option_debug) 01154 ast_log(LOG_DEBUG, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n", 01155 tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags.flags), eid_str_full); 01156 /* Make sure it's not already there */ 01157 for (z=0;z<req->respcount;z++) { 01158 if ((req->dr[z].techint == tech) && 01159 !strcmp(req->dr[z].dest, ptr)) 01160 break; 01161 } 01162 if (z == req->respcount) { 01163 /* Copy into parent responses */ 01164 ast_copy_flags(&(req->dr[req->respcount]), &flags, AST_FLAGS_ALL); 01165 req->dr[req->respcount].weight = weight; 01166 req->dr[req->respcount].techint = tech; 01167 req->dr[req->respcount].expiration = expiration; 01168 dundi_str_short_to_eid(&req->dr[req->respcount].eid, src); 01169 dundi_eid_to_str(req->dr[req->respcount].eid_str, 01170 sizeof(req->dr[req->respcount].eid_str), &req->dr[req->respcount].eid); 01171 ast_copy_string(req->dr[req->respcount].dest, ptr, 01172 sizeof(req->dr[req->respcount].dest)); 01173 ast_copy_string(req->dr[req->respcount].tech, tech2str(tech), 01174 sizeof(req->dr[req->respcount].tech)); 01175 req->respcount++; 01176 ast_clear_flag_nonstd(req->hmd, DUNDI_HINT_DONT_ASK); 01177 } else if (req->dr[z].weight > weight) 01178 req->dr[z].weight = weight; 01179 ptr = term + 1; 01180 } 01181 } 01182 /* We found *something* cached */ 01183 if (expiration < *lowexpiration) 01184 *lowexpiration = expiration; 01185 return 1; 01186 } else 01187 ast_db_del("dundi/cache", key); 01188 } else 01189 ast_db_del("dundi/cache", key); 01190 } 01191 01192 return 0; 01193 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 842 of file pbx_dundi.c. References dundi_request::crc32, dundi_request::dcontext, dundi_result::dest, dundi_request::dr, dundi_eid_to_str_short(), dundi_result::eid, dundi_result::flags, dundi_request::number, dundi_request::respcount, dundi_request::root_eid, dundi_result::techint, and dundi_result::weight. 00843 { 00844 int x; 00845 char key1[256]; 00846 char key2[256]; 00847 char data[1024]; 00848 char eidpeer_str[20]; 00849 char eidroot_str[20]; 00850 time_t timeout; 00851 00852 if (expiration < 1) 00853 expiration = dundi_cache_time; 00854 00855 /* Keep pushes a little longer, cut pulls a little short */ 00856 if (push) 00857 expiration += 10; 00858 else 00859 expiration -= 10; 00860 if (expiration < 1) 00861 expiration = 1; 00862 dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer); 00863 dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); 00864 snprintf(key1, sizeof(key1), "%s/%s/%s/e%08lx", eidpeer_str, req->number, req->dcontext, unaffected ? 0 : req->crc32); 00865 snprintf(key2, sizeof(key2), "%s/%s/%s/r%s", eidpeer_str, req->number, req->dcontext, eidroot_str); 00866 /* Build request string */ 00867 time(&timeout); 00868 timeout += expiration; 00869 snprintf(data, sizeof(data), "%ld|", (long)(timeout)); 00870 for (x=start;x<req->respcount;x++) { 00871 /* Skip anything with an illegal pipe in it */ 00872 if (strchr(req->dr[x].dest, '|')) 00873 continue; 00874 snprintf(data + strlen(data), sizeof(data) - strlen(data), "%d/%d/%d/%s/%s|", 00875 req->dr[x].flags, req->dr[x].weight, req->dr[x].techint, req->dr[x].dest, 00876 dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), &req->dr[x].eid)); 00877 } 00878 ast_db_put("dundi/cache", key1, data); 00879 ast_db_put("dundi/cache", key2, data); 00880 return 0; 00881 }
|
|
||||||||||||||||||||
|
Definition at line 805 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, option_debug, and dundi_request::root_eid. 00806 { 00807 int unaffected; 00808 char key1[256]; 00809 char key2[256]; 00810 char eidpeer_str[20]; 00811 char eidroot_str[20]; 00812 char data[80]; 00813 time_t timeout; 00814 00815 if (expiration < 0) 00816 expiration = dundi_cache_time; 00817 00818 /* Only cache hint if "don't ask" is there... */ 00819 if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK))) 00820 return 0; 00821 00822 unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED)); 00823 00824 dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer); 00825 dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); 00826 snprintf(key1, sizeof(key1), "hint/%s/%s/%s/e%08lx", eidpeer_str, hint->data, req->dcontext, unaffected ? 0 : req->crc32); 00827 snprintf(key2, sizeof(key2), "hint/%s/%s/%s/r%s", eidpeer_str, hint->data, req->dcontext, eidroot_str); 00828 00829 time(&timeout); 00830 timeout += expiration; 00831 snprintf(data, sizeof(data), "%ld|", (long)(timeout)); 00832 00833 ast_db_put("dundi/cache", key1, data); 00834 if (option_debug) 00835 ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key1); 00836 ast_db_put("dundi/cache", key2, data); 00837 if (option_debug) 00838 ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key2); 00839 return 0; 00840 }
|
|
|
Definition at line 3297 of file pbx_dundi.c. References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, dr, DUNDI_COMMAND_CANCEL, and dundi_send(). Referenced by dundi_lookup_internal(), and dundi_precache_internal(). 03298 { 03299 struct dundi_transaction *trans; 03300 03301 AST_LIST_LOCK(&peers); 03302 while ((trans = AST_LIST_REMOVE_HEAD(&dr->trans, parentlist))) { 03303 /* Orphan transaction from request */ 03304 trans->parent = NULL; 03305 /* Send final cancel */ 03306 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); 03307 } 03308 AST_LIST_UNLOCK(&peers); 03309 }
|
|
||||||||||||||||||||
|
Definition at line 1449 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. 01450 { 01451 unsigned char dst[128]; 01452 int res; 01453 struct ast_key *key, *skey; 01454 char eid_str[20]; 01455 if (option_debug) 01456 ast_log(LOG_DEBUG, "Expected '%08lx' got '%08lx'\n", peer->them_keycrc32, keycrc32); 01457 if (peer->them_keycrc32 && (peer->them_keycrc32 == keycrc32)) { 01458 /* A match */ 01459 return 1; 01460 } else if (!newkey || !newsig) 01461 return 0; 01462 if (!memcmp(peer->rxenckey, newkey, 128) && 01463 !memcmp(peer->rxenckey + 128, newsig, 128)) { 01464 /* By definition, a match */ 01465 return 1; 01466 } 01467 /* Decrypt key */ 01468 key = ast_key_get(peer->outkey, AST_KEY_PRIVATE); 01469 if (!key) { 01470 ast_log(LOG_NOTICE, "Unable to find key '%s' to decode shared key from '%s'\n", 01471 peer->outkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01472 return -1; 01473 } 01474 01475 skey = ast_key_get(peer->inkey, AST_KEY_PUBLIC); 01476 if (!skey) { 01477 ast_log(LOG_NOTICE, "Unable to find key '%s' to verify shared key from '%s'\n", 01478 peer->inkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01479 return -1; 01480 } 01481 01482 /* First check signature */ 01483 res = ast_check_signature_bin(skey, (char *)newkey, 128, newsig); 01484 if (res) 01485 return 0; 01486 01487 res = ast_decrypt_bin(dst, newkey, sizeof(dst), key); 01488 if (res != 16) { 01489 if (res >= 0) 01490 ast_log(LOG_NOTICE, "Weird, key decoded to the wrong size (%d)\n", res); 01491 return 0; 01492 } 01493 /* Decrypted, passes signature */ 01494 if (option_debug) 01495 ast_log(LOG_DEBUG, "Wow, new key combo passed signature and decrypt!\n"); 01496 memcpy(peer->rxenckey, newkey, 128); 01497 memcpy(peer->rxenckey + 128, newsig, 128); 01498 peer->them_keycrc32 = crc32(0L, peer->rxenckey, 128); 01499 aes_decrypt_key128(dst, &peer->them_dcx); 01500 aes_encrypt_key128(dst, &peer->them_ecx); 01501 return 1; 01502 }
|
|
|
Definition at line 2074 of file pbx_dundi.c. References build_secret(), and save_secret(). Referenced by network_thread(). 02075 { 02076 char oldsecret[80]; 02077 time_t now; 02078 02079 time(&now); 02080 #if 0 02081 printf("%ld/%ld\n", now, rotatetime); 02082 #endif 02083 if ((now - rotatetime) >= 0) { 02084 /* Time to rotate keys */ 02085 ast_copy_string(oldsecret, cursecret, sizeof(oldsecret)); 02086 build_secret(cursecret, sizeof(cursecret)); 02087 save_secret(cursecret, oldsecret); 02088 } 02089 }
|
|
|
Definition at line 3422 of file pbx_dundi.c. References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and dr. Referenced by dundi_lookup_internal(). 03423 { 03424 struct dundi_request *cur; 03425 03426 AST_LIST_LOCK(&peers); 03427 AST_LIST_TRAVERSE(&requests, cur, list) { 03428 if (cur == dr) 03429 break; 03430 } 03431 AST_LIST_UNLOCK(&peers); 03432 03433 return cur ? 1 : 0; 03434 }
|
|
||||||||||||||||||||
|
Definition at line 2258 of file pbx_dundi.c. References complete_peer_helper(). 02259 { 02260 return complete_peer_helper(line, word, pos, state, 3); 02261 }
|
|
||||||||||||||||||||||||
|
Definition at line 2238 of file pbx_dundi.c. References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, dundi_eid_to_str(), dundi_peer::eid, len, and s. Referenced by complete_peer_4(). 02239 { 02240 int which=0, len; 02241 char *ret = NULL; 02242 struct dundi_peer *p; 02243 char eid_str[20]; 02244 02245 if (pos != rpos) 02246 return NULL; 02247 AST_LIST_LOCK(&peers); 02248 len = strlen(word); 02249 AST_LIST_TRAVERSE(&peers, p, list) { 02250 const char *s = dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid); 02251 if (!strncasecmp(word, s, len) && ++which > state) 02252 ret = ast_strdup(s); 02253 } 02254 AST_LIST_UNLOCK(&peers); 02255 return ret; 02256 }
|
|
|
Definition at line 2766 of file pbx_dundi.c. References dundi_peer::addr, apply_peer(), ast_calloc, AST_LIST_INSERT_HEAD, ast_set_flag, DUNDI_DEFAULT_RETRANS_TIMER, FLAG_SENDFULLKEY, FLAG_STOREHIST, and get_trans_id(). Referenced by append_transaction(), do_register(), find_transaction(), and qualify_peer(). 02767 { 02768 struct dundi_transaction *trans; 02769 int tid; 02770 02771 /* Don't allow creation of transactions to non-registered peers */ 02772 if (p && !p->addr.sin_addr.s_addr) 02773 return NULL; 02774 tid = get_trans_id(); 02775 if (tid < 1) 02776 return NULL; 02777 if (!(trans = ast_calloc(1, sizeof(*trans)))) 02778 return NULL; 02779 02780 if (global_storehistory) { 02781 trans->start = ast_tvnow(); 02782 ast_set_flag(trans, FLAG_STOREHIST); 02783 } 02784 trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; 02785 trans->autokillid = -1; 02786 if (p) { 02787 apply_peer(trans, p); 02788 if (!p->sentfullkey) 02789 ast_set_flag(trans, FLAG_SENDFULLKEY); 02790 } 02791 trans->strans = tid; 02792 AST_LIST_INSERT_HEAD(&alltrans, trans, all); 02793 02794 return trans; 02795 }
|
|
||||||||||||||||||||||||
|
Definition at line 1339 of file pbx_dundi.c. References aes_decrypt(). Referenced by dundi_decrypt(). 01340 { 01341 unsigned char lastblock[16]; 01342 int x; 01343 memcpy(lastblock, iv, sizeof(lastblock)); 01344 while(len > 0) { 01345 aes_decrypt(src, dst, dcx); 01346 for (x=0;x<16;x++) 01347 dst[x] ^= lastblock[x]; 01348 memcpy(lastblock, src, sizeof(lastblock)); 01349 dst += 16; 01350 src += 16; 01351 len -= 16; 01352 } 01353 return 0; 01354 }
|
|
|
Definition at line 3866 of file pbx_dundi.c. Referenced by prune_mappings().
|
|
||||||||||||
|
Definition at line 2813 of file pbx_dundi.c. References AST_LIST_REMOVE, ast_sched_del(), free, and sched. Referenced by ack_trans(). 02814 { 02815 if (pack->parent) 02816 AST_LIST_REMOVE(&pack->parent->packets, pack, list); 02817 if (pack->retransid > -1) 02818 ast_sched_del(sched, pack->retransid); 02819 if (needfree) 02820 free(pack); 02821 else 02822 pack->retransid = -1; 02823 }
|
|
|
Definition at line 1902 of file pbx_dundi.c. References AST_LIST_REMOVE_HEAD, ast_sched_del(), free, and sched. Referenced by ack_trans(), and handle_frame(). 01903 { 01904 struct dundi_packet *pack; 01905 01906 while ((pack = AST_LIST_REMOVE_HEAD(p, list))) { 01907 if (pack->retransid > -1) 01908 ast_sched_del(sched, pack->retransid); 01909 free(pack); 01910 } 01911 }
|
|
|
Definition at line 3853 of file pbx_dundi.c. References ast_sched_del(), destroy_permissions(), destroy_trans(), free, and sched. 03854 { 03855 if (peer->registerid > -1) 03856 ast_sched_del(sched, peer->registerid); 03857 if (peer->regtrans) 03858 destroy_trans(peer->regtrans, 0); 03859 if (peer->qualifyid > -1) 03860 ast_sched_del(sched, peer->qualifyid); 03861 destroy_permissions(&peer->permit); 03862 destroy_permissions(&peer->include); 03863 free(peer); 03864 }
|
|
|
Definition at line 3845 of file pbx_dundi.c. References AST_LIST_REMOVE_HEAD, and free. Referenced by build_peer(), and destroy_peer(). 03846 { 03847 struct permission *perm; 03848 03849 while ((perm = AST_LIST_REMOVE_HEAD(permlist, list))) 03850 free(perm); 03851 }
|
|
||||||||||||
|
Definition at line 2825 of file pbx_dundi.c. References AST_LIST_TRAVERSE, ast_log(), ast_malloc, ast_strlen_zero(), ast_test_flag, dundi_eid_cmp(), dundi_eid_to_str(), DUNDI_TIMING_HISTORY, dundi_peer::eid, FLAG_ISQUAL, FLAG_ISREG, FLAG_STOREHIST, free, LOG_NOTICE, dundi_transaction::start, and dundi_transaction::them_eid. Referenced by abort_request(), destroy_peer(), do_autokill(), do_register(), dundi_precache_thread(), dundi_query_thread(), dundi_rexmit(), handle_frame(), precache_transactions(), and qualify_peer(). 02826 { 02827 struct dundi_peer *peer; 02828 int ms; 02829 int x; 02830 int cnt; 02831 char eid_str[20]; 02832 if (ast_test_flag(trans, FLAG_ISREG | FLAG_ISQUAL | FLAG_STOREHIST)) { 02833 AST_LIST_TRAVERSE(&peers, peer, list) { 02834 if (peer->regtrans == trans) 02835 peer->regtrans = NULL; 02836 if (peer->qualtrans == trans) { 02837 if (fromtimeout) { 02838 if (peer->lastms > -1) 02839 ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02840 peer->lastms = -1; 02841 } else { 02842 ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx); 02843 if (ms < 1) 02844 ms = 1; 02845 if (ms < peer->maxms) { 02846 if ((peer->lastms >= peer->maxms) || (peer->lastms < 0)) 02847 ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 02848 } else if (peer->lastms < peer->maxms) { 02849 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); 02850 } 02851 peer->lastms = ms; 02852 } 02853 peer->qualtrans = NULL; 02854 } 02855 if (ast_test_flag(trans, FLAG_STOREHIST)) { 02856 if (trans->parent && !ast_strlen_zero(trans->parent->number)) { 02857 if (!dundi_eid_cmp(&trans->them_eid, &peer->eid)) { 02858 peer->avgms = 0; 02859 cnt = 0; 02860 if (peer->lookups[DUNDI_TIMING_HISTORY-1]) 02861 free(peer->lookups[DUNDI_TIMING_HISTORY-1]); 02862 for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) { 02863 peer->lookuptimes[x] = peer->lookuptimes[x-1]; 02864 peer->lookups[x] = peer->lookups[x-1]; 02865 if (peer->lookups[x]) { 02866 peer->avgms += peer->lookuptimes[x]; 02867 cnt++; 02868 } 02869 } 02870 peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start); 02871 peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2); 02872 if (peer->lookups[0]) { 02873 sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext); 02874 peer->avgms += peer->lookuptimes[0]; 02875 cnt++; 02876 } 02877 if (cnt) 02878 peer->avgms /= cnt; 02879 } 02880 } 02881 } 02882 } 02883 } 02884 if (trans->parent) { 02885 /* Unlink from parent if appropriate */ 02886 AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist); 02887 if (AST_LIST_EMPTY(&trans->parent->trans)) { 02888 /* Wake up sleeper */ 02889 if (trans->parent->pfds[1] > -1) { 02890 write(trans->parent->pfds[1], "killa!", 6); 02891 } 02892 } 02893 } 02894 /* Unlink from all trans */ 02895 AST_LIST_REMOVE(&alltrans, trans, all); 02896 destroy_packets(&trans->packets); 02897 destroy_packets(&trans->lasttrans); 02898 if (trans->autokillid > -1) 02899 ast_sched_del(sched, trans->autokillid); 02900 trans->autokillid = -1; 02901 if (trans->thread) { 02902 /* If used by a thread, mark as dead and be done */ 02903 ast_set_flag(trans, FLAG_DEAD); 02904 } else 02905 free(trans); 02906 }
|
|
|
Definition at line 3148 of file pbx_dundi.c. References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dr, and dundi_discover(). Referenced by dundi_lookup_internal(). 03149 { 03150 struct dundi_transaction *trans; 03151 AST_LIST_LOCK(&peers); 03152 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { 03153 dundi_discover(trans); 03154 } 03155 AST_LIST_UNLOCK(&peers); 03156 return 0; 03157 }
|
|
|
Definition at line 3003 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(), and dundi_query(). 03004 { 03005 struct dundi_transaction *trans = data; 03006 char eid_str[20]; 03007 ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n", 03008 dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid)); 03009 trans->autokillid = -1; 03010 destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */ 03011 return 0; 03012 }
|
|
|
Definition at line 4013 of file pbx_dundi.c. References qualify_peer(). Referenced by qualify_peer(). 04014 { 04015 struct dundi_peer *peer; 04016 peer = data; 04017 peer->qualifyid = -1; 04018 qualify_peer(peer, 0); 04019 return 0; 04020 }
|
|
|
Definition at line 3986 of file pbx_dundi.c. References ast_log(), ast_sched_add(), ast_set_flag, create_transaction(), destroy_trans(), DUNDI_COMMAND_REGREQ, DUNDI_DEFAULT_VERSION, dundi_eid_to_str(), dundi_ie_append_eid(), dundi_ie_append_short(), DUNDI_IE_EID, DUNDI_IE_EXPIRATION, DUNDI_IE_VERSION, dundi_send(), dundi_peer::eid, FLAG_ISREG, LOG_NOTICE, option_debug, and sched. 03987 { 03988 struct dundi_ie_data ied; 03989 struct dundi_peer *peer = data; 03990 char eid_str[20]; 03991 char eid_str2[20]; 03992 if (option_debug) 03993 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)); 03994 peer->registerid = ast_sched_add(sched, default_expiration * 1000, do_register, data); 03995 /* Destroy old transaction if there is one */ 03996 if (peer->regtrans) 03997 destroy_trans(peer->regtrans, 0); 03998 peer->regtrans = create_transaction(peer); 03999 if (peer->regtrans) { 04000 ast_set_flag(peer->regtrans, FLAG_ISREG); 04001 memset(&ied, 0, sizeof(ied)); 04002 dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); 04003 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &peer->regtrans->us_eid); 04004 dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, default_expiration); 04005 dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied); 04006 04007 } else 04008 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)); 04009 04010 return 0; 04011 }
|
|
|
Definition at line 1272 of file pbx_dundi.c. References dundi_peer::addr, ast_log(), dundi_eid_to_str(), dundi_peer::eid, LOG_DEBUG, and option_debug. Referenced by handle_command_response(), and populate_addr(). 01273 { 01274 struct dundi_peer *peer = data; 01275 char eid_str[20]; 01276 if (option_debug) 01277 ast_log(LOG_DEBUG, "Register expired for '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); 01278 peer->registerexpire = -1; 01279 peer->lastms = 0; 01280 memset(&peer->addr, 0, sizeof(peer->addr)); 01281 return 0; 01282 }
|
|
||||||||||||
|
Definition at line 360 of file pbx_dundi.c. References DUNDI_COMMAND_ACK, and dundi_send(). Referenced by handle_frame(). 00361 { 00362 return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL); 00363 }
|
|
||||||||||||||||
|
Definition at line 746 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, option_debug, dundi_query_state::reqeid, s, dundi_transaction::thread, dundi_query_state::trans, and dundi_query_state::ttl. Referenced by handle_command_response(). 00747 { 00748 struct dundi_query_state *st; 00749 int totallen; 00750 int x; 00751 int skipfirst=0; 00752 struct dundi_ie_data ied; 00753 char eid_str[20]; 00754 char *s; 00755 pthread_t lookupthread; 00756 pthread_attr_t attr; 00757 if (ies->eidcount > 1) { 00758 /* Since it is a requirement that the first EID is the authenticating host 00759 and the last EID is the root, it is permissible that the first and last EID 00760 could be the same. In that case, we should go ahead copy only the "root" section 00761 since we will not need it for authentication. */ 00762 if (!dundi_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1])) 00763 skipfirst = 1; 00764 } 00765 totallen = sizeof(struct dundi_query_state); 00766 totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid); 00767 st = ast_calloc(1, totallen); 00768 if (st) { 00769 ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context)); 00770 memcpy(&st->reqeid, ies->reqeid, sizeof(st->reqeid)); 00771 st->trans = trans; 00772 st->ttl = ies->ttl - 1; 00773 if (st->ttl < 0) 00774 st->ttl = 0; 00775 s = st->fluffy; 00776 for (x=skipfirst;ies->eids[x];x++) { 00777 st->eids[x-skipfirst] = (dundi_eid *)s; 00778 *st->eids[x-skipfirst] = *ies->eids[x]; 00779 s += sizeof(dundi_eid); 00780 } 00781 if (option_debug) 00782 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); 00783 pthread_attr_init(&attr); 00784 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00785 trans->thread = 1; 00786 if (ast_pthread_create(&lookupthread, &attr, dundi_query_thread, st)) { 00787 trans->thread = 0; 00788 ast_log(LOG_WARNING, "Unable to create thread!\n"); 00789 free(st); 00790 memset(&ied, 0, sizeof(ied)); 00791 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); 00792 dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); 00793 return -1; 00794 } 00795 } else { 00796 ast_log(LOG_WARNING, "Out of memory!\n"); 00797 memset(&ied, 0, sizeof(ied)); 00798 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); 00799 dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); 00800 return -1; 00801 } 00802 return 0; 00803 }
|
|
||||||||||||||||
|
Definition at line 1034 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, option_debug, s, dundi_transaction::thread, dundi_query_state::trans, and dundi_query_state::ttl. Referenced by handle_command_response(). 01035 { 01036 struct dundi_query_state *st; 01037 int totallen; 01038 int x; 01039 struct dundi_ie_data ied; 01040 char *s; 01041 struct dundi_mapping *cur; 01042 int mapcount = 0; 01043 int skipfirst = 0; 01044 01045 pthread_t lookupthread; 01046 pthread_attr_t attr; 01047 totallen = sizeof(struct dundi_query_state); 01048 /* Count matching map entries */ 01049 AST_LIST_TRAVERSE(&mappings, cur, list) { 01050 if (!strcasecmp(cur->dcontext, ccontext)) 01051 mapcount++; 01052 } 01053 /* If no maps, return -1 immediately */ 01054 if (!mapcount) 01055 return -1; 01056 01057 if (ies->eidcount > 1) { 01058 /* Since it is a requirement that the first EID is the authenticating host 01059 and the last EID is the root, it is permissible that the first and last EID 01060 could be the same. In that case, we should go ahead copy only the "root" section 01061 since we will not need it for authentication. */ 01062 if (!dundi_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1])) 01063 skipfirst = 1; 01064 } 01065 01066 totallen += mapcount * sizeof(struct dundi_mapping); 01067 totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid); 01068 st = ast_calloc(1, totallen); 01069 if (st) { 01070 ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context)); 01071 ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number)); 01072 st->trans = trans; 01073 st->ttl = ies->ttl - 1; 01074 st->nocache = ies->cbypass; 01075 if (st->ttl < 0) 01076 st->ttl = 0; 01077 s = st->fluffy; 01078 for (x=skipfirst;ies->eids[x];x++) { 01079 st->eids[x-skipfirst] = (dundi_eid *)s; 01080 *st->eids[x-skipfirst] = *ies->eids[x]; 01081 st->directs[x-skipfirst] = ies->eid_direct[x]; 01082 s += sizeof(dundi_eid); 01083 } 01084 /* Append mappings */ 01085 x = 0; 01086 st->maps = (struct dundi_mapping *)s; 01087 AST_LIST_TRAVERSE(&mappings, cur, list) { 01088 if (!strcasecmp(cur->dcontext, ccontext)) { 01089 if (x < mapcount) { 01090 st->maps[x] = *cur; 01091 st->maps[x].list.next = NULL; 01092 x++; 01093 } 01094 } 01095 } 01096 st->nummaps = mapcount; 01097 if (option_debug) 01098 ast_log(LOG_DEBUG, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context); 01099 pthread_attr_init(&attr); 01100 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 01101 trans->thread = 1; 01102 if (ast_pthread_create(&lookupthread, &attr, dundi_lookup_thread, st)) { 01103 trans->thread = 0; 01104 ast_log(LOG_WARNING, "Unable to create thread!\n"); 01105 free(st); 01106 memset(&ied, 0, sizeof(ied)); 01107 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); 01108 dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); 01109 return -1; 01110 } 01111 } else { 01112 ast_log(LOG_WARNING, "Out of memory!\n"); 01113 memset(&ied, 0, sizeof(ied)); 01114 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); 01115 dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); 01116 return -1; 01117 } 01118 return 0; 01119 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 4263 of file pbx_dundi.c. References DUNDI_FLAG_CANMATCH, and dundi_helper(). 04264 { 04265 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH); 04266 }
|
|
|
Definition at line 267 of file pbx_dundi.c. References ast_verbose(). Referenced by load_module(). 00268 { 00269 if (dundidebug) 00270 ast_verbose("%s", data); 00271 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 1356 of file pbx_dundi.c. References ast_log(), dundi_transaction::dcx, decrypt_memcpy(), dundi_encblock::encdata, dundi_encblock::iv, LOG_DEBUG, option_debug, and space. 01357 { 01358 int space = *dstlen; 01359 unsigned long bytes; 01360 struct dundi_hdr *h; 01361 unsigned char *decrypt_space; 01362 decrypt_space = alloca(srclen); 01363 if (!decrypt_space) 01364 return NULL; 01365 decrypt_memcpy(decrypt_space, src->encdata, srclen, src->iv, &trans->dcx); 01366 /* Setup header */ 01367 h = (struct dundi_hdr *)dst; 01368 *h = *ohdr; 01369 bytes = space - 6; 01370 if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) { 01371 if (option_debug) 01372 ast_log(LOG_DEBUG, "Ouch, uncompress failed :(\n"); 01373 return NULL; 01374 } 01375 /* Update length */ 01376 *dstlen = bytes + 6; 01377 /* Return new header */ 01378 return h; 01379 }
|
|
|
||||||||||||||||
|
Definition at line 2155 of file pbx_dundi.c. References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS. 02156 { 02157 if (argc != 2) 02158 return RESULT_SHOWUSAGE; 02159 dundidebug = 1; 02160 ast_cli(fd, "DUNDi Debugging Enabled\n"); 02161 return RESULT_SUCCESS; 02162 }
|
|
||||||||||||||||
|
Definition at line 2280 of file pbx_dundi.c. References ast_cli(), context, dr, dundi_flags2str(), dundi_lookup(), MAX_RESULTS, RESULT_SHOWUSAGE, and sort_results(). 02281 { 02282 int res; 02283 char tmp[256]; 02284 char fs[80] = ""; 02285 char *context; 02286 int x; 02287 int bypass = 0; 02288 struct dundi_result dr[MAX_RESULTS]; 02289 struct timeval start; 02290 if ((argc < 3) || (argc > 4)) 02291 return RESULT_SHOWUSAGE; 02292 if (argc > 3) { 02293 if (!strcasecmp(argv[3], "bypass")) 02294 bypass=1; 02295 else 02296 return RESULT_SHOWUSAGE; 02297 } 02298 ast_copy_string(tmp, argv[2], sizeof(tmp)); 02299 context = strchr(tmp, '@'); 02300 if (context) { 02301 *context = '\0'; 02302 context++; 02303 } 02304 start = ast_tvnow(); 02305 res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass); 02306 02307 if (res < 0) 02308 ast_cli(fd, "DUNDi lookup returned error.\n"); 02309 else if (!res) 02310 ast_cli(fd, "DUNDi lookup returned no results.\n"); 02311 else 02312 sort_results(dr, res); 02313 for (x=0;x<res;x++) { 02314 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)); 02315 ast_cli(fd, " from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration); 02316 } 02317 ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start)); 02318 return RESULT_SUCCESS; 02319 }
|
|
||||||||||||||||
|
Definition at line 2321 of file pbx_dundi.c. References ast_cli(), context, dundi_precache(), RESULT_SHOWUSAGE, and RESULT_SUCCESS. 02322 { 02323 int res; 02324 char tmp[256]; 02325 char *context; 02326 struct timeval start; 02327 if ((argc < 3) || (argc > 3)) 02328 return RESULT_SHOWUSAGE; 02329 ast_copy_string(tmp, argv[2], sizeof(tmp)); 02330 context = strchr(tmp, '@'); 02331 if (context) { 02332 *context = '\0'; 02333 context++; 02334 } 02335 start = ast_tvnow(); 02336 res = dundi_precache(context, tmp); 02337 02338 if (res < 0) 02339 ast_cli(fd, "DUNDi precache returned error.\n"); 02340 else if (!res) 02341 ast_cli(fd, "DUNDi precache returned no error.\n"); 02342 ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start)); 02343 return RESULT_SUCCESS; 02344 }
|
|
||||||||||||||||
|
Definition at line 2346 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. 02347 { 02348 int res; 02349 char tmp[256]; 02350 char *context; 02351 dundi_eid eid; 02352 struct dundi_entity_info dei; 02353 if ((argc < 3) || (argc > 3)) 02354 return RESULT_SHOWUSAGE; 02355 if (dundi_str_to_eid(&eid, argv[2])) { 02356 ast_cli(fd, "'%s' is not a valid EID!\n", argv[2]); 02357 return RESULT_SHOWUSAGE; 02358 } 02359 ast_copy_string(tmp, argv[2], sizeof(tmp)); 02360 context = strchr(tmp, '@'); 02361 if (context) { 02362 *context = '\0'; 02363 context++; 02364 } 02365 res = dundi_query_eid(&dei, context, eid); 02366 if (res < 0) 02367 ast_cli(fd, "DUNDi Query EID returned error.\n"); 02368 else if (!res) 02369 ast_cli(fd, "DUNDi Query EID returned no results.\n"); 02370 else { 02371 ast_cli(fd, "DUNDi Query EID succeeded:\n"); 02372 ast_cli(fd, "Department: %s\n", dei.orgunit); 02373 ast_cli(fd, "Organization: %s\n", dei.org); 02374 ast_cli(fd, "City/Locality: %s\n", dei.locality); 02375 ast_cli(fd, "State/Province: %s\n", dei.stateprov); 02376 ast_cli(fd, "Country: %s\n", dei.country); 02377 ast_cli(fd, "E-mail: %s\n", dei.email); 02378 ast_cli(fd, "Phone: %s\n", dei.phone); 02379 ast_cli(fd, "IP Address: %s\n", dei.ipaddr); 02380 } 02381 return RESULT_SUCCESS; 02382 }
|
|
||||||||||||||||
|
Definition at line 2164 of file pbx_dundi.c. References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS. 02165 { 02166 if (argc != 3) 02167 return RESULT_SHOWUSAGE; 02168 global_storehistory = 1; 02169 ast_cli(fd, "DUNDi History Storage Enabled\n"); 02170 return RESULT_SUCCESS; 02171 }
|
|
||||||||||||
|
Definition at line 1381 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, option_debug, dundi_transaction::them_eid, update_key(), and dundi_transaction::us_eid. Referenced by dundi_send(). 01382 { 01383 unsigned char *compress_space; 01384 int len; 01385 int res; 01386 unsigned long bytes; 01387 struct dundi_ie_data ied; 01388 struct dundi_peer *peer; 01389 unsigned char iv[16]; 01390 len = pack->datalen + pack->datalen / 100 + 42; 01391 compress_space = alloca(len); 01392 if (compress_space) { 01393 memset(compress_space, 0, len); 01394 /* We care about everthing save the first 6 bytes of header */ 01395 bytes = len; 01396 res = compress(compress_space, &bytes, pack->data + 6, pack->datalen - 6); 01397 if (res != Z_OK) { 01398 if (option_debug) 01399 ast_log(LOG_DEBUG, "Ouch, compression failed!\n"); 01400 return -1; 01401 } 01402 memset(&ied, 0, sizeof(ied)); 01403 /* Say who we are */ 01404 if (!pack->h->iseqno && !pack->h->oseqno) { 01405 /* Need the key in the first copy */ 01406 if (!(peer = find_peer(&trans->them_eid))) 01407 return -1; 01408 if (update_key(peer)) 01409 return -1; 01410 if (!peer->sentfullkey) 01411 ast_set_flag(trans, FLAG_SENDFULLKEY); 01412 /* Append key data */ 01413 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); 01414 if (ast_test_flag(trans, FLAG_SENDFULLKEY)) { 01415 dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128); 01416 dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128); 01417 } else { 01418 dundi_ie_append_int(&ied, DUNDI_IE_KEYCRC32, peer->us_keycrc32); 01419 } 01420 /* Setup contexts */ 01421 trans->ecx = peer->us_ecx; 01422 trans->dcx = peer->us_dcx; 01423 01424 /* We've sent the full key */ 01425 peer->sentfullkey = 1; 01426 } 01427 /* Build initialization vector */ 01428 build_iv(iv); 01429 /* Add the field, rounded up to 16 bytes */ 01430 dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, iv, NULL, ((bytes + 15) / 16) * 16); 01431 /* Copy the data */ 01432 if ((ied.pos + bytes) >= sizeof(ied.buf)) { 01433 ast_log(LOG_NOTICE, "Final packet too large!\n"); 01434 return -1; 01435 } 01436 encrypt_memcpy(ied.buf + ied.pos, compress_space, bytes, iv, &trans->ecx); 01437 ied.pos += ((bytes + 15) / 16) * 16; 01438 /* Reconstruct header */ 01439 pack->datalen = sizeof(struct dundi_hdr); 01440 pack->h->cmdresp = DUNDI_COMMAND_ENCRYPT; 01441 pack->h->cmdflags = 0; 01442 memcpy(pack->h->ies, ied.buf, ied.pos); 01443 pack->datalen += ied.pos; 01444 return 0; 01445 } 01446 return -1; 01447 }
|
|
|
Definition at line 273 of file pbx_dundi.c. References ast_log(), and LOG_WARNING. Referenced by load_module(). 00274 { 00275 ast_log(LOG_WARNING, "%s", data); 00276 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 4268 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(), and sort_results(). 04269 { 04270 struct dundi_result results[MAX_RESULTS]; 04271 int res; 04272 int x=0; 04273 char req[1024]; 04274 const char *dundiargs; 04275 struct ast_app *dial; 04276 04277 if (!strncasecmp(context, "macro-", 6)) { 04278 if (!chan) { 04279 ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n"); 04280 return -1; 04281 } 04282 /* If done as a macro, use macro extension */ 04283 if (!strcasecmp(exten, "s")) { 04284 exten = pbx_builtin_getvar_helper(chan, "ARG1"); 04285 if (ast_strlen_zero(exten)) 04286 exten = chan->macroexten; 04287 if (ast_strlen_zero(exten)) 04288 exten = chan->exten; 04289 if (ast_strlen_zero(exten)) { 04290 ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n"); 04291 return -1; 04292 } 04293 } 04294 if (ast_strlen_zero(data)) 04295 data = "e164"; 04296 } else { 04297 if (ast_strlen_zero(data)) 04298 data = context; 04299 } 04300 res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0); 04301 if (res > 0) { 04302 sort_results(results, res); 04303 for (x=0;x<res;x++) { 04304 if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) { 04305 if (!--priority) 04306 break; 04307 } 04308 } 04309 } 04310 if (x < res) { 04311 /* Got a hit! */ 04312 dundiargs = pbx_builtin_getvar_helper(chan, "DUNDIDIALARGS"); 04313 snprintf(req, sizeof(req), "%s/%s||%s", results[x].tech, results[x].dest, 04314 S_OR(dundiargs, "")); 04315 dial = pbx_findapp("Dial"); 04316 if (dial) 04317 res = pbx_exec(chan, dial, req); 04318 } else 04319 res = -1; 04320 return res; 04321 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 4258 of file pbx_dundi.c. References DUNDI_FLAG_EXISTS, and dundi_helper(). 04259 { 04260 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS); 04261 }
|
|
||||||||||||||||
|
Definition at line 2173 of file pbx_dundi.c. References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, DUNDI_TIMING_HISTORY, free, and RESULT_SHOWUSAGE. 02174 { 02175 int stats = 0; 02176 if ((argc < 2) || (argc > 3)) 02177 return RESULT_SHOWUSAGE; 02178 if (argc > 2) { 02179 if (!strcasecmp(argv[2], "stats")) 02180 stats = 1; 02181 else 02182 return RESULT_SHOWUSAGE; 02183 } 02184 if (stats) { 02185 /* Flush statistics */ 02186 struct dundi_peer *p; 02187 int x; 02188 AST_LIST_LOCK(&peers); 02189 AST_LIST_TRAVERSE(&peers, p, list) { 02190 for (x = 0;x < DUNDI_TIMING_HISTORY; x++) { 02191 if (p->lookups[x]) 02192 free(p->lookups[x]); 02193 p->lookups[x] = NULL; 02194 p->lookuptimes[x] = 0; 02195 } 02196 p->avgms = 0; 02197 } 02198 AST_LIST_UNLOCK(&peers); 02199 } else { 02200 ast_db_deltree("dundi/cache", NULL); 02201 ast_cli(fd, "DUNDi Cache Flushed\n"); 02202 } 02203 return RESULT_SUCCESS; 02204 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 4219 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(). 04220 { 04221 struct dundi_result results[MAX_RESULTS]; 04222 int res; 04223 int x; 04224 int found = 0; 04225 if (!strncasecmp(context, "macro-", 6)) { 04226 if (!chan) { 04227 ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n"); 04228 return -1; 04229 } 04230 /* If done as a macro, use macro extension */ 04231 if (!strcasecmp(exten, "s")) { 04232 exten = pbx_builtin_getvar_helper(chan, "ARG1"); 04233 if (ast_strlen_zero(exten)) 04234 exten = chan->macroexten; 04235 if (ast_strlen_zero(exten)) 04236 exten = chan->exten; 04237 if (ast_strlen_zero(exten)) { 04238 ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n"); 04239 return -1; 04240 } 04241 } 04242 if (ast_strlen_zero(data)) 04243 data = "e164"; 04244 } else { 04245 if (ast_strlen_zero(data)) 04246 data = context; 04247 } 04248 res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0); 04249 for (x=0;x<res;x++) { 04250 if (ast_test_flag(results + x, flag)) 04251 found++; 04252 } 04253 if (found >= priority) 04254 return 1; 04255 return 0; 04256 }
|
|
||||||||||||||||||||
|
Definition at line 3014 of file pbx_dundi.c. References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_eid_cmp(), dundi_ie_append_eid(), DUNDI_IE_EID, DUNDI_IE_EID_DIRECT, dundi_peer::eid, and has_permission(). Referenced by dundi_discover(). 03015 { 03016 struct dundi_peer *p; 03017 if (!dundi_eid_cmp(eid, us)) { 03018 dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid); 03019 return; 03020 } 03021 AST_LIST_LOCK(&peers); 03022 AST_LIST_TRAVERSE(&peers, p, list) { 03023 if (!dundi_eid_cmp(&p->eid, eid)) { 03024 if (has_permission(&p->include, context)) 03025 dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid); 03026 else 03027 dundi_ie_append_eid(ied, DUNDI_IE_EID, eid); 03028 break; 03029 } 03030 } 03031 if (!p) 03032 dundi_ie_append_eid(ied, DUNDI_IE_EID, eid); 03033 AST_LIST_UNLOCK(&peers); 03034 }
|
|
||||||||||||||||||||||||||||
|
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 3555 of file pbx_dundi.c. References DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, and dundi_lookup_internal(). Referenced by dundi_do_lookup(), dundi_exec(), dundi_helper(), and dundifunc_read(). 03556 { 03557 struct dundi_hint_metadata hmd; 03558 dundi_eid *avoid[1] = { NULL, }; 03559 int direct[1] = { 0, }; 03560 int expiration = dundi_cache_time; 03561 memset(&hmd, 0, sizeof(hmd)); 03562 hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; 03563 return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct); 03564 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Definition at line 3451 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_WARNING, optimize_transactions(), option_debug, register_request(), dundi_request::root_eid, and unregister_request(). Referenced by dundi_lookup(). 03452 { 03453 int res; 03454 struct dundi_request dr, *pending; 03455 dundi_eid *rooteid=NULL; 03456 int x; 03457 int ttlms; 03458 int ms; 03459 int foundcache; 03460 int skipped=0; 03461 int order=0; 03462 char eid_str[20]; 03463 struct timeval start; 03464 03465 /* Don't do anthing for a hungup channel */ 03466 if (chan && chan->_softhangup) 03467 return 0; 03468 03469 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03470 03471 for (x=0;avoid[x];x++) 03472 rooteid = avoid[x]; 03473 /* Now perform real check */ 03474 memset(&dr, 0, sizeof(dr)); 03475 if (pipe(dr.pfds)) { 03476 ast_log(LOG_WARNING, "pipe failed: %s\n" , strerror(errno)); 03477 return -1; 03478 } 03479 dr.dr = result; 03480 dr.hmd = hmd; 03481 dr.maxcount = maxret; 03482 dr.expiration = *expiration; 03483 dr.cbypass = cbypass; 03484 dr.crc32 = avoid_crc32(avoid); 03485 ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext)); 03486 ast_copy_string(dr.number, number, sizeof(dr.number)); 03487 if (rooteid) 03488 dr.root_eid = *rooteid; 03489 res = register_request(&dr, &pending); 03490 if (res) { 03491 /* Already a request */ 03492 if (rooteid && !dundi_eid_cmp(&dr.root_eid, &pending->root_eid)) { 03493 /* This is on behalf of someone else. Go ahead and close this out since 03494 they'll get their answer anyway. */ 03495 if (option_debug) 03496 ast_log(LOG_DEBUG, "Oooh, duplicate request for '%s@%s' for '%s'\n", 03497 dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid)); 03498 close(dr.pfds[0]); 03499 close(dr.pfds[1]); 03500 return -2; 03501 } else { 03502 /* Wait for the cache to populate */ 03503 if (option_debug) 03504 ast_log(LOG_DEBUG, "Waiting for similar request for '%s@%s' for '%s'\n", 03505 dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid)); 03506 start = ast_tvnow(); 03507 while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) { 03508 /* XXX Would be nice to have a way to poll/select here XXX */ 03509 /* XXX this is a busy wait loop!!! */ 03510 usleep(1); 03511 } 03512 /* Continue on as normal, our cache should kick in */ 03513 } 03514 } 03515 /* Create transactions */ 03516 do { 03517 order = skipped; 03518 skipped = 0; 03519 foundcache = 0; 03520 build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct); 03521 } while (skipped && !foundcache && AST_LIST_EMPTY(&dr.trans)); 03522 /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't 03523 do this earlier because we didn't know if we were going to have transactions 03524 or not. */ 03525 if (!ttl) { 03526 ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED); 03527 abort_request(&dr); 03528 unregister_request(&dr); 03529 close(dr.pfds[0]); 03530 close(dr.pfds[1]); 03531 return 0; 03532 } 03533 03534 /* Optimize transactions */ 03535 optimize_transactions(&dr, order); 03536 /* Actually perform transactions */ 03537 discover_transactions(&dr); 03538 /* Wait for transaction to come back */ 03539 start = ast_tvnow(); 03540 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) { 03541 ms = 100; 03542 ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL); 03543 } 03544 if (chan && chan->_softhangup && option_debug) 03545 ast_log(LOG_DEBUG, "Hrm, '%s' hungup before their query for %s@%s finished\n", chan->name, dr.number, dr.dcontext); 03546 cancel_request(&dr); 03547 unregister_request(&dr); 03548 res = dr.respcount; 03549 *expiration = dr.expiration; 03550 close(dr.pfds[0]); 03551 close(dr.pfds[1]); 03552 return res; 03553 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 514 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(). 00515 { 00516 struct ast_flags flags = {0}; 00517 int x; 00518 if (!ast_strlen_zero(map->lcontext)) { 00519 if (ast_exists_extension(NULL, map->lcontext, called_number, 1, NULL)) 00520 ast_set_flag(&flags, DUNDI_FLAG_EXISTS); 00521 if (ast_canmatch_extension(NULL, map->lcontext, called_number, 1, NULL)) 00522 ast_set_flag(&flags, DUNDI_FLAG_CANMATCH); 00523 if (ast_matchmore_extension(NULL, map->lcontext, called_number, 1, NULL)) 00524 ast_set_flag(&flags, DUNDI_FLAG_MATCHMORE); 00525 if (ast_ignore_pattern(map->lcontext, called_number)) 00526 ast_set_flag(&flags, DUNDI_FLAG_IGNOREPAT); 00527 00528 /* Clearly we can't say 'don't ask' anymore if we found anything... */ 00529 if (ast_test_flag(&flags, AST_FLAGS_ALL)) 00530 ast_clear_flag_nonstd(hmd, DUNDI_HINT_DONT_ASK); 00531 00532 if (map->options & DUNDI_FLAG_INTERNAL_NOPARTIAL) { 00533 /* Skip partial answers */ 00534 ast_clear_flag(&flags, DUNDI_FLAG_MATCHMORE|DUNDI_FLAG_CANMATCH); 00535 } 00536 if (ast_test_flag(&flags, AST_FLAGS_ALL)) { 00537 struct varshead headp; 00538 struct ast_var_t *newvariable; 00539 ast_set_flag(&flags, map->options & 0xffff); 00540 ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL); 00541 dr[anscnt].techint = map->tech; 00542 dr[anscnt].weight = map->weight; 00543 dr[anscnt].expiration = dundi_cache_time; 00544 ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech)); 00545 dr[anscnt].eid = *us_eid; 00546 dundi_eid_to_str(dr[anscnt].eid_str, sizeof(dr[anscnt].eid_str), &dr[anscnt].eid); 00547 if (ast_test_flag(&flags, DUNDI_FLAG_EXISTS)) { 00548 AST_LIST_HEAD_INIT_NOLOCK(&headp); 00549 newvariable = ast_var_assign("NUMBER", called_number); 00550 AST_LIST_INSERT_HEAD(&headp, newvariable, entries); 00551 newvariable = ast_var_assign("EID", dr[anscnt].eid_str); 00552 AST_LIST_INSERT_HEAD(&headp, newvariable, entries); 00553 newvariable = ast_var_assign("SECRET", cursecret); 00554 AST_LIST_INSERT_HEAD(&headp, newvariable, entries); 00555 newvariable = ast_var_assign("IPADDR", ipaddr); 00556 AST_LIST_INSERT_HEAD(&headp, newvariable, entries); 00557 pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest)); 00558 while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries))) 00559 ast_var_delete(newvariable); 00560 } else 00561 dr[anscnt].dest[0] = '\0'; 00562 anscnt++; 00563 } else { 00564 /* No answers... Find the fewest number of digits from the 00565 number for which we have no answer. */ 00566 char tmp[AST_MAX_EXTENSION]; 00567 for (x=0;x<AST_MAX_EXTENSION;x++) { 00568 tmp[x] = called_number[x]; 00569 if (!tmp[x]) 00570 break; 00571 if (!ast_canmatch_extension(NULL, map->lcontext, tmp, 1, NULL)) { 00572 /* Oops found something we can't match. If this is longer 00573 than the running hint, we have to consider it */ 00574 if (strlen(tmp) > strlen(hmd->exten)) { 00575 ast_copy_string(hmd->exten, tmp, sizeof(hmd->exten)); 00576 } 00577 break; 00578 } 00579 } 00580 } 00581 } 00582 return anscnt; 00583 }
|
|
|
Definition at line 587 of file pbx_dundi.c. References ast_log(), dundi_query_state::called_context, dundi_query_state::called_number, dr, dundi_eid_to_str(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, dundi_lookup_local(), dundi_query_state::eids, LOG_DEBUG, dundi_query_state::maps, MAX_RESULTS, dundi_query_state::nummaps, option_debug, dundi_query_state::trans, and dundi_transaction::us_eid. Referenced by dundi_answer_query(). 00588 { 00589 struct dundi_query_state *st = data; 00590 struct dundi_result dr[MAX_RESULTS]; 00591 struct dundi_ie_data ied; 00592 struct dundi_hint_metadata hmd; 00593 char eid_str[20]; 00594 int res, x; 00595 int ouranswers=0; 00596 int max = 999999; 00597 int expiration = dundi_cache_time; 00598 00599 if (option_debug) 00600 ast_log(LOG_DEBUG, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, 00601 st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves"); 00602 memset(&ied, 0, sizeof(ied)); 00603 memset(&dr, 0, sizeof(dr)); 00604 memset(&hmd, 0, sizeof(hmd)); 00605 /* Assume 'don't ask for anything' and 'unaffected', no TTL expired */ 00606 hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; 00607 for (x=0;x<st->nummaps;x++) 00608 ouranswers = dundi_lookup_local(dr, st->maps + x, st->called_number, &st->trans->us_eid, ouranswers, &hmd); 00609 if (ouranswers < 0) 00610 ouranswers = 0; 00611 for (x=0;x<ouranswers;x++) { 00612 if (dr[x].weight < max) 00613 max = dr[x].weight; 00614 } 00615 00616 if (max) { 00617 /* If we do not have a canonical result, keep looking */ 00618 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); 00619 if (res > 0) { 00620 /* Append answer in result */ 00621 ouranswers += res; 00622 } else { 00623 if ((res < -1) && (!ouranswers)) 00624 dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_DUPLICATE, "Duplicate Request Pending"); 00625 } 00626 } 00627 AST_LIST_LOCK(&peers); 00628 /* Truncate if "don't ask" isn't present */ 00629 if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK)) 00630 hmd.exten[0] = '\0'; 00631 if (ast_test_flag(st->trans, FLAG_DEAD)) { 00632 if (option_debug) 00633 ast_log(LOG_DEBUG, "Our transaction went away!\n"); 00634 st->trans->thread = 0; 00635 destroy_trans(st->trans, 0); 00636 } else { 00637 for (x=0;x<ouranswers;x++) { 00638 /* Add answers */ 00639 if (dr[x].expiration && (expiration > dr[x].expiration)) 00640 expiration = dr[x].expiration; 00641 dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest); 00642 } 00643 dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten); 00644 dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration); 00645 dundi_send(st->trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); 00646 st->trans->thread = 0; 00647 } 00648 AST_LIST_UNLOCK(&peers); 00649 free(st); 00650 return NULL; 00651 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 4323 of file pbx_dundi.c. References DUNDI_FLAG_MATCHMORE, and dundi_helper(). 04324 { 04325 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE); 04326 }
|
|
||||||||||||||||
|
Definition at line 2206 of file pbx_dundi.c. References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS. 02207 { 02208 if (argc != 3) 02209 return RESULT_SHOWUSAGE; 02210 dundidebug = 0; 02211 ast_cli(fd, "DUNDi Debugging Disabled\n"); 02212 return RESULT_SUCCESS; 02213 }
|
|
||||||||||||||||
|
Definition at line 2215 of file pbx_dundi.c. References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS. 02216 { 02217 if (argc != 4) 02218 return RESULT_SHOWUSAGE; 02219 global_storehistory = 0; 02220 ast_cli(fd, "DUNDi History Storage Disabled\n"); 02221 return RESULT_SUCCESS; 02222 }
|
|
||||||||||||
|
Pre-cache to push upstream peers.
Definition at line 3697 of file pbx_dundi.c. References dundi_precache_internal(). Referenced by dundi_do_precache(), and process_precache(). 03698 { 03699 dundi_eid *avoid[1] = { NULL, }; 03700 return dundi_precache_internal(context, number, dundi_ttl, avoid); 03701 }
|
|
|
||||||||||||||||||||
|
Definition at line 3626 of file pbx_dundi.c. References AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_waitfor_n_fd(), build_transactions(), cancel_request(), dr, DUNDI_FLUFF_TIME, DUNDI_TTL_TIME, LOG_NOTICE, MAX_RESULTS, optimize_transactions(), option_debug, precache_transactions(), and reschedule_precache(). Referenced by dundi_precache(), and dundi_precache_thread(). 03627 { 03628 struct dundi_request dr; 03629 struct dundi_hint_metadata hmd; 03630 struct dundi_result dr2[MAX_RESULTS]; 03631 struct timeval start; 03632 struct dundi_mapping *maps = NULL, *cur; 03633 int nummaps = 0; 03634 int foundanswers; 03635 int foundcache, skipped, ttlms, ms; 03636 if (!context) 03637 context = "e164"; 03638 if (option_debug) 03639 ast_log(LOG_DEBUG, "Precache internal (%s@%s)!\n", number, context); 03640 03641 AST_LIST_LOCK(&peers); 03642 AST_LIST_TRAVERSE(&mappings, cur, list) { 03643 if (!strcasecmp(cur->dcontext, context)) 03644 nummaps++; 03645 } 03646 if (nummaps) { 03647 maps = alloca(nummaps * sizeof(*maps)); 03648 nummaps = 0; 03649 if (maps) { 03650 AST_LIST_TRAVERSE(&mappings, cur, list) { 03651 if (!strcasecmp(cur->dcontext, context)) 03652 maps[nummaps++] = *cur; 03653 } 03654 } 03655 } 03656 AST_LIST_UNLOCK(&peers); 03657 if (!nummaps || !maps) 03658 return -1; 03659 ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; 03660 memset(&dr2, 0, sizeof(dr2)); 03661 memset(&dr, 0, sizeof(dr)); 03662 memset(&hmd, 0, sizeof(hmd)); 03663 dr.dr = dr2; 03664 ast_copy_string(dr.number, number, sizeof(dr.number)); 03665 ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext)); 03666 dr.maxcount = MAX_RESULTS; 03667 dr.expiration = dundi_cache_time; 03668 dr.hmd = &hmd; 03669 dr.pfds[0] = dr.pfds[1] = -1; 03670 pipe(dr.pfds); 03671 build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL); 03672 optimize_transactions(&dr, 0); 03673 foundanswers = 0; 03674 precache_transactions(&dr, maps, nummaps, &dr.expiration, &foundanswers); 03675 if (foundanswers) { 03676 if (dr.expiration > 0) 03677 reschedule_precache(dr.number, dr.dcontext, dr.expiration); 03678 else 03679 ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext); 03680 } 03681 start = ast_tvnow(); 03682 while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) { 03683 if (dr.pfds[0] > -1) { 03684 ms = 100; 03685 ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL); 03686 } else 03687 usleep(1); 03688 } 03689 cancel_request(&dr); 03690 if (dr.pfds[0] > -1) { 03691 close(dr.pfds[0]); 03692 close(dr.pfds[1]); 03693 } 03694 return 0; 03695 }
|
|
|