Mon Sep 18 09:15:30 2006

Asterisk developer's documentation


pbx_dundi.c File Reference

Distributed Universal Number Discovery (DUNDi). More...

#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.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/md5.h"
#include "asterisk/dundi.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/utils.h"
#include "asterisk/crypto.h"
#include "asterisk/astdb.h"
#include "asterisk/acl.h"
#include "asterisk/aes.h"
#include "dundi-parser.h"

Go to the source code of this file.

Data Structures

struct  dundi_hint_metadata
struct  dundi_mapping
struct  dundi_packet
struct  dundi_peer
struct  dundi_precache_queue
struct  dundi_query_state
struct  dundi_request
struct  dundi_transaction
struct  permission

Defines

#define DUNDI_FLAG_INTERNAL_NOPARTIAL   (1 << 17)
#define DUNDI_MODEL_INBOUND   (1 << 0)
#define DUNDI_MODEL_OUTBOUND   (1 << 1)
#define DUNDI_MODEL_SYMMETRIC   (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)
#define DUNDI_SECRET_TIME   DUNDI_DEFAULT_CACHE_TIME
#define DUNDI_TIMING_HISTORY   10
#define FLAG_DEAD   (1 << 1)
#define FLAG_ENCRYPT   (1 << 4)
#define FLAG_FINAL   (1 << 2)
#define FLAG_ISQUAL   (1 << 3)
#define FLAG_ISREG   (1 << 0)
#define FLAG_SENDFULLKEY   (1 << 5)
#define FLAG_STOREHIST   (1 << 6)
#define FORMAT   "%-12.12s %-12.12s %02d:%02d:%02d\n"
#define FORMAT   "%-12.12s %-7d %-12.12s %-10.10s %-5.5s %-25.25s\n"
#define FORMAT   "%-15s %-15s %-15s %-3.3d %-3.3d\n"
#define FORMAT   "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
#define FORMAT   "%-20.20s %-15.15s %s %-10.10s %-8.8s %-15.15s\n"
#define FORMAT2   "%-12.12s %-12.12s %-10.10s\n"
#define FORMAT2   "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
#define FORMAT2   "%-15s %-15s %-15s %-3.3s %-3.3s\n"
#define FORMAT2   "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
#define FORMAT2   "%-20.20s %-15.15s %-10.10s %-8.8s %-15.15s\n"
#define KEY_IN   1
#define KEY_OUT   0
#define MAX_OPTS   128
#define MAX_PACKET_SIZE   8192
#define MAX_RESULTS   64

Functions

static void abort_request (struct dundi_request *dr)
static int ack_trans (struct dundi_transaction *trans, int iseqno)
static struct permissionappend_permission (struct permission *p, 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)
 AST_MUTEX_DEFINE_STATIC (pclock)
 AST_MUTEX_DEFINE_STATIC (peerlock)
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 (char *line, char *word, int pos, int state)
static char * complete_peer_helper (char *line, char *word, int pos, int state, int rpos)
static struct dundi_transactioncreate_transaction (struct dundi_peer *p)
static int decrypt_memcpy (unsigned char *dst, unsigned char *src, int len, unsigned char *iv, aes_decrypt_ctx *dcx)
char * description (void)
 Provides a description of the module.
static void destroy_map (struct dundi_mapping *map)
static void destroy_packet (struct dundi_packet *pack, int needfree)
static void destroy_packets (struct dundi_packet *p)
static void destroy_peer (struct dundi_peer *peer)
static void destroy_permissions (struct permission *p)
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_hdrdundi_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, int newstack, 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_exec (struct ast_channel *chan, void *data)
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 char * dundifunc_read (struct ast_channel *chan, char *cmd, char *data, 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_peerfind_peer (dundi_eid *eid)
static struct dundi_transactionfind_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 permission *ps, char *cont)
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
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)
int reload (void)
 Reload stuff.
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)
int unload_module (void)
 Cleanup all module structures, sockets, etc.
static void unregister_request (struct dundi_request *dr)
static int update_key (struct dundi_peer *peer)
int usecount (void)
 Provides a usecount.

Variables

dundi_transactionalltrans
static char * app = "DUNDiLookup"
char ast_config_AST_KEY_DIR []
static int authdebug = 0
static struct ast_cli_entry cli_debug
static struct ast_cli_entry cli_flush
static struct ast_cli_entry cli_lookup
static struct ast_cli_entry cli_no_debug
static struct ast_cli_entry cli_no_store_history
static struct ast_cli_entry cli_precache
static struct ast_cli_entry cli_queryeid
static struct ast_cli_entry cli_show_entityid
static struct ast_cli_entry cli_show_mappings
static struct ast_cli_entry cli_show_peer
static struct ast_cli_entry cli_show_peers
static struct ast_cli_entry cli_show_precache
static struct ast_cli_entry cli_show_requests
static struct ast_cli_entry cli_show_trans
static struct ast_cli_entry cli_store_history
static char country [80]
static char cursecret [80]
static char debug_usage []
static int default_expiration = 60
static char dept [80]
static char * descrip
static int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME
static struct ast_custom_function dundi_function
static int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE
static struct ast_switch dundi_switch
static int dundi_ttl = DUNDI_DEFAULT_TTL
static int dundidebug = 0
static char email [80]
static dundi_eid empty_eid = { { 0, 0, 0, 0, 0, 0 } }
static char flush_usage []
static int global_autokilltimeout = 0
static dundi_eid global_eid
static int global_storehistory = 0
static struct io_contextio
static char ipaddr [80]
 LOCAL_USER_DECL
static char locality [80]
static char lookup_usage []
static struct dundi_mappingmappings
static int netsocket = -1
static pthread_t netthreadid = AST_PTHREADT_NULL
static char no_debug_usage []
static char no_store_history_usage []
static char org [80]
static struct dundi_precache_queuepcq
static struct dundi_peerpeers
static char phone [80]
static char precache_usage []
static pthread_t precachethreadid = AST_PTHREADT_NULL
static char query_usage []
dundi_requestrequests
static time_t rotatetime
static struct sched_contextsched
static char secretpath [80]
static char show_entityid_usage []
static char show_mappings_usage []
static char show_peer_usage []
static char show_peers_usage []
static char show_precache_usage []
static char show_requests_usage []
static char show_trans_usage []
 STANDARD_LOCAL_USER
static char stateprov [80]
static char store_history_usage []
static char * synopsis = "Look up a number with DUNDi"
static char * tdesc = "Distributed Universal Number Discovery (DUNDi)"
static int tos = 0


Detailed Description

Distributed Universal Number Discovery (DUNDi).

Definition in file pbx_dundi.c.


Define Documentation

#define DUNDI_FLAG_INTERNAL_NOPARTIAL   (1 << 17)

Definition at line 111 of file pbx_dundi.c.

Referenced by build_mapping(), and dundi_lookup_local().

#define DUNDI_MODEL_INBOUND   (1 << 0)

Definition at line 96 of file pbx_dundi.c.

Referenced by build_peer(), dundi_show_peer(), handle_command_response(), and model2str().

#define DUNDI_MODEL_OUTBOUND   (1 << 1)

Definition at line 97 of file pbx_dundi.c.

Referenced by build_peer(), build_transactions(), dundi_show_peer(), model2str(), and set_config().

#define DUNDI_MODEL_SYMMETRIC   (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)

Definition at line 98 of file pbx_dundi.c.

Referenced by build_peer(), and model2str().

#define DUNDI_SECRET_TIME   DUNDI_DEFAULT_CACHE_TIME

Definition at line 116 of file pbx_dundi.c.

Referenced by load_password(), and save_secret().

#define DUNDI_TIMING_HISTORY   10

Definition at line 101 of file pbx_dundi.c.

Referenced by destroy_trans(), dundi_flush(), and dundi_show_peer().

#define FLAG_DEAD   (1 << 1)

Definition at line 104 of file pbx_dundi.c.

Referenced by dundi_lookup_thread(), dundi_precache_thread(), dundi_query_thread(), and precache_transactions().

#define FLAG_ENCRYPT   (1 << 4)

Definition at line 107 of file pbx_dundi.c.

Referenced by apply_peer(), dundi_send(), and handle_command_response().

#define FLAG_FINAL   (1 << 2)

Definition at line 105 of file pbx_dundi.c.

Referenced by dundi_send(), handle_frame(), and reset_transaction().

#define FLAG_ISQUAL   (1 << 3)

Definition at line 106 of file pbx_dundi.c.

Referenced by destroy_trans(), dundi_rexmit(), and qualify_peer().

#define FLAG_ISREG   (1 << 0)

Definition at line 103 of file pbx_dundi.c.

Referenced by destroy_trans(), and do_register().

#define FLAG_SENDFULLKEY   (1 << 5)

Definition at line 108 of file pbx_dundi.c.

Referenced by create_transaction(), and dundi_encrypt().

#define FLAG_STOREHIST   (1 << 6)

Definition at line 109 of file pbx_dundi.c.

Referenced by create_transaction(), and destroy_trans().

#define FORMAT   "%-12.12s %-12.12s %02d:%02d:%02d\n"

#define FORMAT   "%-12.12s %-7d %-12.12s %-10.10s %-5.5s %-25.25s\n"

#define FORMAT   "%-15s %-15s %-15s %-3.3d %-3.3d\n"

#define FORMAT   "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"

#define FORMAT   "%-20.20s %-15.15s %s %-10.10s %-8.8s %-15.15s\n"

#define FORMAT2   "%-12.12s %-12.12s %-10.10s\n"

#define FORMAT2   "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"

#define FORMAT2   "%-15s %-15s %-15s %-3.3s %-3.3s\n"

#define FORMAT2   "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"

#define FORMAT2   "%-20.20s %-15.15s %-10.10s %-8.8s %-15.15s\n"

#define KEY_IN   1

Definition at line 120 of file pbx_dundi.c.

#define KEY_OUT   0

Definition at line 119 of file pbx_dundi.c.

#define MAX_OPTS   128

Definition at line 4118 of file pbx_dundi.c.

Referenced by build_mapping().

#define MAX_PACKET_SIZE   8192

Definition at line 76 of file pbx_dundi.c.

Referenced by socket_read().

#define MAX_RESULTS   64

Definition at line 74 of file pbx_dundi.c.

Referenced by dundi_do_lookup(), dundi_exec(), dundi_helper(), dundi_lookup_exec(), dundi_lookup_thread(), dundi_precache_internal(), dundi_prop_precache(), dundifunc_read(), and precache_trans().


Function Documentation

static void abort_request ( struct dundi_request dr  )  [static]

Definition at line 3380 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), destroy_trans(), and dr.

Referenced by dundi_lookup_internal().

03381 {
03382    ast_mutex_lock(&peerlock);
03383    while(dr->trans) 
03384       destroy_trans(dr->trans, 0);
03385    ast_mutex_unlock(&peerlock);
03386 }

static int ack_trans ( struct dundi_transaction trans,
int  iseqno 
) [static]

Definition at line 1918 of file pbx_dundi.c.

References ast_log(), ast_sched_del(), dundi_transaction::autokillid, destroy_packet(), destroy_packets(), dundi_packet::h, dundi_transaction::lasttrans, LOG_WARNING, dundi_packet::next, dundi_hdr::oseqno, and dundi_transaction::packets.

Referenced by handle_frame().

01919 {
01920    /* Ack transmitted packet corresponding to iseqno */
01921    struct dundi_packet *pack;
01922    pack = trans->packets;
01923    while(pack) {
01924       if ((pack->h->oseqno + 1) % 255 == iseqno) {
01925          destroy_packet(pack, 0);
01926          if (trans->lasttrans) {
01927             ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n");
01928             destroy_packets(trans->lasttrans);
01929          }
01930          trans->lasttrans = pack;
01931          if (trans->autokillid > -1)
01932             ast_sched_del(sched, trans->autokillid);
01933          trans->autokillid = -1;
01934          return 1;
01935       }
01936       pack = pack->next;
01937    }
01938    return 0;
01939 }

static struct permission* append_permission ( struct permission p,
char *  s,
int  allow 
) [static]

Definition at line 4096 of file pbx_dundi.c.

References malloc, and permission::next.

Referenced by build_peer().

04097 {
04098    struct permission *start;
04099    start = p;
04100    if (p) {
04101       while(p->next)
04102          p = p->next;
04103    }
04104    if (p) {
04105       p->next = malloc(sizeof(struct permission) + strlen(s) + 1);
04106       p = p->next;
04107    } else {
04108       p = malloc(sizeof(struct permission) + strlen(s) + 1);
04109    }
04110    if (p) {
04111       memset(p, 0, sizeof(struct permission));
04112       memcpy(p->name, s, strlen(s) + 1);
04113       p->allow = allow;
04114    }
04115    return start ? start : p;
04116 }

static int append_transaction ( struct dundi_request dr,
struct dundi_peer p,
int  ttl,
dundi_eid avoid[] 
) [static]

Definition at line 3333 of file pbx_dundi.c.

References dundi_peer::addr, ast_log(), ast_strlen_zero(), create_transaction(), dr, dundi_eid_to_str(), DUNDI_MAX_STACK, dundi_peer::eid, dundi_transaction::eidcount, dundi_transaction::eids, dundi_peer::lastms, LOG_DEBUG, dundi_peer::maxms, dundi_transaction::next, dundi_transaction::parent, and dundi_transaction::ttl.

Referenced by build_transactions().

03334 {
03335    struct dundi_transaction *trans;
03336    int x;
03337    char eid_str[20];
03338    char eid_str2[20];
03339    /* Ignore if not registered */
03340    if (!p->addr.sin_addr.s_addr)
03341       return 0;
03342    if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms)))
03343       return 0;
03344    if (ast_strlen_zero(dr->number))
03345       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);
03346    else
03347       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);
03348    trans = create_transaction(p);
03349    if (!trans)
03350       return -1;
03351    trans->next = dr->trans;
03352    trans->parent = dr;
03353    trans->ttl = ttl;
03354    for (x=0;avoid[x] && (x <DUNDI_MAX_STACK);x++)
03355       trans->eids[x] = *avoid[x];
03356    trans->eidcount = x;
03357    dr->trans = trans;
03358    return 0;
03359 }

static void apply_peer ( struct dundi_transaction trans,
struct dundi_peer p 
) [static]

Definition at line 1261 of file pbx_dundi.c.

References dundi_peer::addr, dundi_transaction::addr, ast_set_flag, ast_strlen_zero(), dundi_transaction::autokilltimeout, DUNDI_DEFAULT_RETRANS_TIMER, dundi_peer::eid, FLAG_ENCRYPT, global_autokilltimeout, dundi_peer::inkey, dundi_peer::lastms, dundi_peer::maxms, dundi_transaction::retranstimer, dundi_transaction::them_eid, dundi_peer::us_eid, and dundi_transaction::us_eid.

Referenced by create_transaction().

01262 {
01263    if (!trans->addr.sin_addr.s_addr)
01264       memcpy(&trans->addr, &p->addr, sizeof(trans->addr));
01265    trans->us_eid = p->us_eid;
01266    trans->them_eid = p->eid;
01267    /* Enable encryption if appropriate */
01268    if (!ast_strlen_zero(p->inkey))
01269       ast_set_flag(trans, FLAG_ENCRYPT);  
01270    if (p->maxms) {
01271       trans->autokilltimeout = p->maxms;
01272       trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
01273       if (p->lastms > 1) {
01274          trans->retranstimer = p->lastms * 2;
01275          /* Keep it from being silly */
01276          if (trans->retranstimer < 150)
01277             trans->retranstimer = 150;
01278       }
01279       if (trans->retranstimer > DUNDI_DEFAULT_RETRANS_TIMER)
01280          trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
01281    } else
01282       trans->autokilltimeout = global_autokilltimeout;
01283 }

AST_MUTEX_DEFINE_STATIC ( pclock   ) 

AST_MUTEX_DEFINE_STATIC ( peerlock   ) 

static unsigned long avoid_crc32 ( dundi_eid avoid[]  )  [static]

Definition at line 3518 of file pbx_dundi.c.

References dundi_request::crc32.

Referenced by dundi_lookup_internal().

03519 {
03520    /* Idea is that we're calculating a checksum which is independent of
03521       the order that the EID's are listed in */
03522    unsigned long acrc32 = 0;
03523    int x;
03524    for (x=0;avoid[x];x++) {
03525       /* Order doesn't matter */
03526       if (avoid[x+1]) {
03527          acrc32 ^= crc32(0L, (unsigned char *)avoid[x], sizeof(dundi_eid));
03528       }
03529    }
03530    return acrc32;
03531 }

static void build_iv ( unsigned char *  iv  )  [static]

Definition at line 503 of file pbx_dundi.c.

Referenced by build_secret(), dundi_encrypt(), and update_key().

00504 {
00505    /* XXX Would be nice to be more random XXX */
00506    unsigned int *fluffy;
00507    int x;
00508    fluffy = (unsigned int *)(iv);
00509    for (x=0;x<4;x++)
00510       fluffy[x] = rand();
00511 }

static void build_mapping ( char *  name,
char *  value 
) [static]

Definition at line 4120 of file pbx_dundi.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), dundi_mapping::dead, DUNDI_FLAG_COMMERCIAL, DUNDI_FLAG_INTERNAL_NOPARTIAL, DUNDI_FLAG_MOBILE, DUNDI_FLAG_NOCOMUNSOLICIT, DUNDI_FLAG_NOUNSOLICITED, DUNDI_FLAG_RESIDENTIAL, LOG_WARNING, malloc, map, mappings, MAX_OPTS, str2tech(), and t.

Referenced by set_config().

04121 {
04122    char *t, *fields[MAX_OPTS];
04123    struct dundi_mapping *map;
04124    int x;
04125    int y;
04126    t = ast_strdupa(value);
04127    if (t) {
04128       map = mappings;
04129       while(map) {
04130          /* Find a double match */
04131          if (!strcasecmp(map->dcontext, name) && 
04132             (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) && 
04133               (!value[strlen(map->lcontext)] || 
04134                (value[strlen(map->lcontext)] == ','))))
04135             break;
04136          map = map->next;
04137       }
04138       if (!map) {
04139          map = malloc(sizeof(struct dundi_mapping));
04140          if (map) {
04141             memset(map, 0, sizeof(struct dundi_mapping));
04142             map->next = mappings;
04143             mappings = map;
04144             map->dead = 1;
04145          }
04146       }
04147       if (map) {
04148          map->options = 0;
04149          memset(fields, 0, sizeof(fields));
04150          x = 0;
04151          while(t && x < MAX_OPTS) {
04152             fields[x++] = t;
04153             t = strchr(t, ',');
04154             if (t) {
04155                *t = '\0';
04156                t++;
04157             }
04158          } /* Russell was here, arrrr! */
04159          if ((x == 1) && ast_strlen_zero(fields[0])) {
04160             /* Placeholder mapping */
04161             ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
04162             map->dead = 0;
04163          } else if (x >= 4) {
04164             ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
04165             ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext));
04166             if ((sscanf(fields[1], "%d", &map->weight) == 1) && (map->weight >= 0) && (map->weight < 60000)) {
04167                ast_copy_string(map->dest, fields[3], sizeof(map->dest));
04168                if ((map->tech = str2tech(fields[2]))) {
04169                   map->dead = 0;
04170                }
04171             } else {
04172                ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext);
04173             }
04174             for (y=4;y<x;y++) {
04175                if (!strcasecmp(fields[y], "nounsolicited"))
04176                   map->options |= DUNDI_FLAG_NOUNSOLICITED;
04177                else if (!strcasecmp(fields[y], "nocomunsolicit"))
04178                   map->options |= DUNDI_FLAG_NOCOMUNSOLICIT;
04179                else if (!strcasecmp(fields[y], "residential"))
04180                   map->options |= DUNDI_FLAG_RESIDENTIAL;
04181                else if (!strcasecmp(fields[y], "commercial"))
04182                   map->options |= DUNDI_FLAG_COMMERCIAL;
04183                else if (!strcasecmp(fields[y], "mobile"))
04184                   map->options |= DUNDI_FLAG_MOBILE;
04185                else if (!strcasecmp(fields[y], "nopartial"))
04186                   map->options |= DUNDI_FLAG_INTERNAL_NOPARTIAL;
04187                else
04188                   ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]);
04189             }
04190          } else 
04191             ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x);
04192       }
04193    }
04194 }

static void build_peer ( dundi_eid eid,
struct ast_variable v,
int *  globalpcmode 
) [static]

Definition at line 4281 of file pbx_dundi.c.

References dundi_peer::addr, append_permission(), ast_gethostbyname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), ast_true(), dundi_peer::dead, DEFAULT_MAXMS, destroy_permissions(), do_register(), dundi_eid_cmp(), dundi_eid_to_str(), DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, DUNDI_MODEL_SYMMETRIC, DUNDI_PORT, dundi_str_to_eid(), dundi_peer::dynamic, dundi_peer::eid, global_eid, hp, dundi_peer::include, dundi_peer::inkey, ast_variable::lineno, LOG_WARNING, malloc, dundi_peer::maxms, dundi_peer::model, ast_variable::name, ast_variable::next, dundi_peer::next, dundi_peer::order, dundi_peer::outkey, dundi_peer::pcmodel, peers, dundi_peer::permit, populate_addr(), qualify_peer(), dundi_peer::registerid, dundi_peer::us_eid, and ast_variable::value.

04282 {
04283    struct dundi_peer *peer;
04284    struct ast_hostent he;
04285    struct hostent *hp;
04286    dundi_eid testeid;
04287    int needregister=0;
04288    char eid_str[20];
04289 
04290    ast_mutex_lock(&peerlock);
04291    peer = peers;
04292    while(peer) {
04293       if (!dundi_eid_cmp(&peer->eid, eid)) { 
04294          break;
04295       }
04296       peer = peer->next;
04297    }
04298    if (!peer) {
04299       /* Add us into the list */
04300       peer = malloc(sizeof(struct dundi_peer));
04301       if (peer) {
04302          memset(peer, 0, sizeof(struct dundi_peer));
04303          peer->registerid = -1;
04304          peer->registerexpire = -1;
04305          peer->qualifyid = -1;
04306          peer->addr.sin_family = AF_INET;
04307          peer->addr.sin_port = htons(DUNDI_PORT);
04308          populate_addr(peer, eid);
04309          peer->next = peers;
04310          peers = peer;
04311       }
04312    }
04313    if (peer) {
04314       peer->dead = 0;
04315       peer->eid = *eid;
04316       peer->us_eid = global_eid;
04317       destroy_permissions(peer->permit);
04318       destroy_permissions(peer->include);
04319       peer->permit = NULL;
04320       peer->include = NULL;
04321       if (peer->registerid > -1)
04322          ast_sched_del(sched, peer->registerid);
04323       peer->registerid = -1;
04324       while(v) {
04325          if (!strcasecmp(v->name, "inkey")) {
04326             ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey));
04327          } else if (!strcasecmp(v->name, "outkey")) {
04328             ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));
04329          } else if (!strcasecmp(v->name, "host")) {
04330             if (!strcasecmp(v->value, "dynamic")) {
04331                peer->dynamic = 1;
04332             } else {
04333                hp = ast_gethostbyname(v->value, &he);
04334                if (hp) {
04335                   memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));
04336                   peer->dynamic = 0;
04337                } else {
04338                   ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
04339                   peer->dead = 1;
04340                }
04341             }
04342          } else if (!strcasecmp(v->name, "ustothem")) {
04343             if (!dundi_str_to_eid(&testeid, v->value))
04344                peer->us_eid = testeid;
04345             else
04346                ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno);
04347          } else if (!strcasecmp(v->name, "include")) {
04348             peer->include = append_permission(peer->include, v->value, 1);
04349          } else if (!strcasecmp(v->name, "permit")) {
04350             peer->permit = append_permission(peer->permit, v->value, 1);
04351          } else if (!strcasecmp(v->name, "noinclude")) {
04352             peer->include = append_permission(peer->include, v->value, 0);
04353          } else if (!strcasecmp(v->name, "deny")) {
04354             peer->permit = append_permission(peer->permit, v->value, 0);
04355          } else if (!strcasecmp(v->name, "register")) {
04356             needregister = ast_true(v->value);
04357          } else if (!strcasecmp(v->name, "order")) {
04358             if (!strcasecmp(v->value, "primary"))
04359                peer->order = 0;
04360             else if (!strcasecmp(v->value, "secondary"))
04361                peer->order = 1;
04362             else if (!strcasecmp(v->value, "tertiary"))
04363                peer->order = 2;
04364             else if (!strcasecmp(v->value, "quartiary"))
04365                peer->order = 3;
04366             else {
04367                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);
04368             }
04369          } else if (!strcasecmp(v->name, "qualify")) {
04370             if (!strcasecmp(v->value, "no")) {
04371                peer->maxms = 0;
04372             } else if (!strcasecmp(v->value, "yes")) {
04373                peer->maxms = DEFAULT_MAXMS;
04374             } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
04375                ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n", 
04376                   dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno);
04377                peer->maxms = 0;
04378             }
04379          } else if (!strcasecmp(v->name, "model")) {
04380             if (!strcasecmp(v->value, "inbound"))
04381                peer->model = DUNDI_MODEL_INBOUND;
04382             else if (!strcasecmp(v->value, "outbound")) 
04383                peer->model = DUNDI_MODEL_OUTBOUND;
04384             else if (!strcasecmp(v->value, "symmetric"))
04385                peer->model = DUNDI_MODEL_SYMMETRIC;
04386             else if (!strcasecmp(v->value, "none"))
04387                peer->model = 0;
04388             else {
04389                ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 
04390                   v->value, v->lineno);
04391             }
04392          } else if (!strcasecmp(v->name, "precache")) {
04393             if (!strcasecmp(v->value, "inbound"))
04394                peer->pcmodel = DUNDI_MODEL_INBOUND;
04395             else if (!strcasecmp(v->value, "outbound")) 
04396                peer->pcmodel = DUNDI_MODEL_OUTBOUND;
04397             else if (!strcasecmp(v->value, "symmetric"))
04398                peer->pcmodel = DUNDI_MODEL_SYMMETRIC;
04399             else if (!strcasecmp(v->value, "none"))
04400                peer->pcmodel = 0;
04401             else {
04402                ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 
04403                   v->value, v->lineno);
04404             }
04405          }
04406          v = v->next;
04407       }
04408       (*globalpcmode) |= peer->pcmodel;
04409       if (!peer->model && !peer->pcmodel) {
04410          ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n", 
04411             dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
04412          peer->dead = 1;
04413       } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
04414          ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n", 
04415             dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
04416          peer->dead = 1;
04417       } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) {
04418          ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n", 
04419             dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
04420          peer->dead = 1;
04421       } else if (peer->include && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) {
04422          ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n", 
04423             dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
04424       } else if (peer->permit && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
04425          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", 
04426             dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
04427       } else { 
04428          if (needregister) {
04429             peer->registerid = ast_sched_add(sched, 2000, do_register, peer);
04430          }
04431          qualify_peer(peer, 1);
04432       }
04433    }
04434    ast_mutex_unlock(&peerlock);
04435 }

static void build_secret ( char *  secret,
int  seclen 
) [static]

Definition at line 2011 of file pbx_dundi.c.

References ast_base64encode(), build_iv(), and s.

Referenced by check_password(), and load_password().

02012 {
02013    unsigned char tmp[16];
02014    char *s;
02015    build_iv(tmp);
02016    secret[0] = '\0';
02017    ast_base64encode(secret, tmp, sizeof(tmp), seclen);
02018    /* Eliminate potential bad characters */
02019    while((s = strchr(secret, ';'))) *s = '+';
02020    while((s = strchr(secret, '/'))) *s = '+';
02021    while((s = strchr(secret, ':'))) *s = '+';
02022    while((s = strchr(secret, '@'))) *s = '+';
02023 }

static void build_transactions ( struct dundi_request dr,
int  ttl,
int  order,
int *  foundcache,
int *  skipped,
int  blockempty,
int  nocache,
int  modeselect,
dundi_eid skip,
dundi_eid avoid[],
int  directs[] 
) [static]

Definition at line 3388 of file pbx_dundi.c.

References append_transaction(), ast_clear_flag_nonstd, ast_log(), ast_mutex_lock(), cache_lookup(), dr, dundi_eid_cmp(), dundi_eid_to_str(), dundi_eid_zero(), DUNDI_HINT_UNAFFECTED, DUNDI_MODEL_OUTBOUND, dundi_peer::eid, has_permission(), dundi_peer::include, LOG_DEBUG, dundi_peer::model, dundi_peer::order, pass, dundi_peer::pcmodel, peers, dundi_peer::permit, and dundi_peer::us_eid.

Referenced by dundi_lookup_internal(), dundi_precache_internal(), and dundi_query_eid_internal().

03389 {
03390    struct dundi_peer *p;
03391    int x;
03392    int res;
03393    int pass;
03394    int allowconnect;
03395    char eid_str[20];
03396    ast_mutex_lock(&peerlock);
03397    p = peers;
03398    while(p) {
03399       if (modeselect == 1) {
03400          /* Send the precache to push upstreams only! */
03401          pass = has_permission(p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND);
03402          allowconnect = 1;
03403       } else {
03404          /* Normal lookup / EID query */
03405          pass = has_permission(p->include, dr->dcontext);
03406          allowconnect = p->model & DUNDI_MODEL_OUTBOUND;
03407       }
03408       if (skip) {
03409          if (!dundi_eid_cmp(skip, &p->eid))
03410             pass = 0;
03411       }
03412       if (pass) {
03413          if (p->order <= order) {
03414             /* Check order first, then check cache, regardless of
03415                omissions, this gets us more likely to not have an
03416                affected answer. */
03417             if((nocache || !(res = cache_lookup(dr, &p->eid, dr->crc32, &dr->expiration)))) {
03418                res = 0;
03419                /* Make sure we haven't already seen it and that it won't
03420                   affect our answer */
03421                for (x=0;avoid[x];x++) {
03422                   if (!dundi_eid_cmp(avoid[x], &p->eid) || !dundi_eid_cmp(avoid[x], &p->us_eid)) {
03423                      /* If not a direct connection, it affects our answer */
03424                      if (directs && !directs[x]) 
03425                         ast_clear_flag_nonstd(dr->hmd, DUNDI_HINT_UNAFFECTED);
03426                      break;
03427                   }
03428                }
03429                /* Make sure we can ask */
03430                if (allowconnect) {
03431                   if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) {
03432                      /* Check for a matching or 0 cache entry */
03433                      append_transaction(dr, p, ttl, avoid);
03434                   } else
03435                      ast_log(LOG_DEBUG, "Avoiding '%s' in transaction\n", dundi_eid_to_str(eid_str, sizeof(eid_str), avoid[x]));
03436                }
03437             }
03438             *foundcache |= res;
03439          } else if (!*skipped || (p->order < *skipped))
03440             *skipped = p->order;
03441       }
03442       p = p->next;
03443    }
03444    ast_mutex_unlock(&peerlock);
03445 }

static int cache_lookup ( struct dundi_request req,
dundi_eid peer_eid,
unsigned long  crc32,
int *  lowexpiration 
) [static]

Definition at line 1209 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().

01210 {
01211    char key[256];
01212    char eid_str[20];
01213    char eidroot_str[20];
01214    time_t now;
01215    int res=0;
01216    int res2=0;
01217    char eid_str_full[20];
01218    char tmp[256]="";
01219    int x;
01220 
01221    time(&now);
01222    dundi_eid_to_str_short(eid_str, sizeof(eid_str), peer_eid);
01223    dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
01224    dundi_eid_to_str(eid_str_full, sizeof(eid_str_full), peer_eid);
01225    snprintf(key, sizeof(key), "%s/%s/%s/e%08lx", eid_str, req->number, req->dcontext, crc32);
01226    res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
01227    snprintf(key, sizeof(key), "%s/%s/%s/e%08lx", eid_str, req->number, req->dcontext, 0L);
01228    res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
01229    snprintf(key, sizeof(key), "%s/%s/%s/r%s", eid_str, req->number, req->dcontext, eidroot_str);
01230    res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
01231    x = 0;
01232    if (!req->respcount) {
01233       while(!res2) {
01234          /* Look and see if we have a hint that would preclude us from looking at this
01235             peer for this number. */
01236          if (!(tmp[x] = req->number[x])) 
01237             break;
01238          x++;
01239          /* Check for hints */
01240          snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08lx", eid_str, tmp, req->dcontext, crc32);
01241          res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
01242          snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08lx", eid_str, tmp, req->dcontext, 0L);
01243          res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
01244          snprintf(key, sizeof(key), "hint/%s/%s/%s/r%s", eid_str, tmp, req->dcontext, eidroot_str);
01245          res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
01246          if (res2) {
01247             if (strlen(tmp) > strlen(req->hmd->exten)) {
01248                /* Update meta data if appropriate */
01249                ast_copy_string(req->hmd->exten, tmp, sizeof(req->hmd->exten));
01250             }
01251          }
01252       }
01253       res |= res2;
01254    }
01255 
01256    return res;
01257 }

static int cache_lookup_internal ( time_t  now,
struct dundi_request req,
char *  key,
char *  eid_str_full,
int *  lowexpiration 
) [static]

Definition at line 1137 of file pbx_dundi.c.

References ast_clear_flag_nonstd, ast_copy_flags, ast_db_del(), ast_db_get(), AST_FLAGS_ALL, ast_log(), dundi_result::dest, dundi_request::dr, dundi_eid_to_str(), dundi_flags2str(), DUNDI_HINT_DONT_ASK, dundi_str_short_to_eid(), ast_flags::flags, dundi_request::hmd, LOG_DEBUG, dundi_request::respcount, dundi_mapping::tech, tech2str(), dundi_result::techint, and dundi_result::weight.

Referenced by cache_lookup().

01138 {
01139    char data[1024];
01140    char *ptr, *term, *src;
01141    int tech;
01142    struct ast_flags flags;
01143    int weight;
01144    int length;
01145    int z;
01146    int expiration;
01147    char fs[256];
01148    time_t timeout;
01149    /* Build request string */
01150    if (!ast_db_get("dundi/cache", key, data, sizeof(data))) {
01151       ptr = data;
01152       if (sscanf(ptr, "%d|%n", (int *)&timeout, &length) == 1) {
01153          expiration = timeout - now;
01154          if (expiration > 0) {
01155             ast_log(LOG_DEBUG, "Found cache expiring in %d seconds!\n", (int)(timeout - now));
01156             ptr += length;
01157             while((sscanf(ptr, "%d/%d/%d/%n", &(flags.flags), &weight, &tech, &length) == 3)) {
01158                ptr += length;
01159                term = strchr(ptr, '|');
01160                if (term) {
01161                   *term = '\0';
01162                   src = strrchr(ptr, '/');
01163                   if (src) {
01164                      *src = '\0';
01165                      src++;
01166                   } else
01167                      src = "";
01168                   ast_log(LOG_DEBUG, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n", 
01169                      tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags.flags), eid_str_full);
01170                   /* Make sure it's not already there */
01171                   for (z=0;z<req->respcount;z++) {
01172                      if ((req->dr[z].techint == tech) &&
01173                          !strcmp(req->dr[z].dest, ptr)) 
01174                            break;
01175                   }
01176                   if (z == req->respcount) {
01177                      /* Copy into parent responses */
01178                      ast_copy_flags(&(req->dr[req->respcount]), &flags, AST_FLAGS_ALL);   
01179                      req->dr[req->respcount].weight = weight;
01180                      req->dr[req->respcount].techint = tech;
01181                      req->dr[req->respcount].expiration = expiration;
01182                      dundi_str_short_to_eid(&req->dr[req->respcount].eid, src);
01183                      dundi_eid_to_str(req->dr[req->respcount].eid_str, 
01184                         sizeof(req->dr[req->respcount].eid_str), &req->dr[req->respcount].eid);
01185                      ast_copy_string(req->dr[req->respcount].dest, ptr,
01186                         sizeof(req->dr[req->respcount].dest));
01187                      ast_copy_string(req->dr[req->respcount].tech, tech2str(tech),
01188                         sizeof(req->dr[req->respcount].tech));
01189                      req->respcount++;
01190                      ast_clear_flag_nonstd(req->hmd, DUNDI_HINT_DONT_ASK); 
01191                   } else if (req->dr[z].weight > weight)
01192                      req->dr[z].weight = weight;
01193                   ptr = term + 1;
01194                }
01195             }
01196             /* We found *something* cached */
01197             if (expiration < *lowexpiration)
01198                *lowexpiration = expiration;
01199             return 1;
01200          } else 
01201             ast_db_del("dundi/cache", key);
01202       } else 
01203          ast_db_del("dundi/cache", key);
01204    }
01205       
01206    return 0;
01207 }

static int cache_save ( dundi_eid eidpeer,
struct dundi_request req,
int  start,
int  unaffected,
int  expiration,
int  push 
) [static]

Definition at line 849 of file pbx_dundi.c.

References ast_db_put(), dundi_request::crc32, dundi_request::dcontext, dundi_result::dest, dundi_request::dr, dundi_cache_time, dundi_eid_to_str_short(), dundi_result::eid, dundi_result::flags, dundi_request::number, dundi_request::respcount, dundi_request::root_eid, dundi_result::techint, and dundi_result::weight.

Referenced by handle_command_response().

00850 {
00851    int x;
00852    char key1[256];
00853    char key2[256];
00854    char data[1024];
00855    char eidpeer_str[20];
00856    char eidroot_str[20];
00857    time_t timeout;
00858 
00859    if (expiration < 1)  
00860       expiration = dundi_cache_time;
00861 
00862    /* Keep pushes a little longer, cut pulls a little short */
00863    if (push)
00864       expiration += 10;
00865    else
00866       expiration -= 10;
00867    if (expiration < 1)
00868       expiration = 1;
00869    dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
00870    dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
00871    snprintf(key1, sizeof(key1), "%s/%s/%s/e%08lx", eidpeer_str, req->number, req->dcontext, unaffected ? 0 : req->crc32);
00872    snprintf(key2, sizeof(key2), "%s/%s/%s/r%s", eidpeer_str, req->number, req->dcontext, eidroot_str);
00873    /* Build request string */
00874    time(&timeout);
00875    timeout += expiration;
00876    snprintf(data, sizeof(data), "%ld|", (long)(timeout));
00877    for (x=start;x<req->respcount;x++) {
00878       /* Skip anything with an illegal pipe in it */
00879       if (strchr(req->dr[x].dest, '|'))
00880          continue;
00881       snprintf(data + strlen(data), sizeof(data) - strlen(data), "%d/%d/%d/%s/%s|", 
00882          req->dr[x].flags, req->dr[x].weight, req->dr[x].techint, req->dr[x].dest, 
00883          dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), &req->dr[x].eid));
00884    }
00885    ast_db_put("dundi/cache", key1, data);
00886    ast_db_put("dundi/cache", key2, data);
00887    return 0;
00888 }

static int cache_save_hint ( dundi_eid eidpeer,
struct dundi_request req,
struct dundi_hint hint,
int  expiration 
) [static]

Definition at line 814 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_cache_time, dundi_eid_to_str_short(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, LOG_DEBUG, and dundi_request::root_eid.

Referenced by handle_command_response().

00815 {
00816    int unaffected;
00817    char key1[256];
00818    char key2[256];
00819    char eidpeer_str[20];
00820    char eidroot_str[20];
00821    char data[80];
00822    time_t timeout;
00823 
00824    if (expiration < 0)
00825       expiration = dundi_cache_time;
00826 
00827    /* Only cache hint if "don't ask" is there... */
00828    if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK)))   
00829       return 0;
00830 
00831    unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED));
00832 
00833    dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
00834    dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
00835    snprintf(key1, sizeof(key1), "hint/%s/%s/%s/e%08lx", eidpeer_str, hint->data, req->dcontext, unaffected ? 0 : req->crc32);
00836    snprintf(key2, sizeof(key2), "hint/%s/%s/%s/r%s", eidpeer_str, hint->data, req->dcontext, eidroot_str);
00837 
00838    time(&timeout);
00839    timeout += expiration;
00840    snprintf(data, sizeof(data), "%ld|", (long)(timeout));
00841    
00842    ast_db_put("dundi/cache", key1, data);
00843    ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key1);
00844    ast_db_put("dundi/cache", key2, data);
00845    ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key2);
00846    return 0;
00847 }

static void cancel_request ( struct dundi_request dr  )  [static]

Definition at line 3361 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dr, DUNDI_COMMAND_CANCEL, dundi_send(), dundi_transaction::next, and dundi_transaction::parent.

Referenced by dundi_lookup_internal(), and dundi_precache_internal().

03362 {
03363    struct dundi_transaction *trans, *next;
03364 
03365    ast_mutex_lock(&peerlock);
03366    trans = dr->trans;
03367    
03368    while(trans) {
03369       next = trans->next;
03370       /* Orphan transaction from request */
03371       trans->parent = NULL;
03372       trans->next = NULL;
03373       /* Send final cancel */
03374       dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
03375       trans = next;
03376    }
03377    ast_mutex_unlock(&peerlock);
03378 }

static int check_key ( struct dundi_peer peer,
unsigned char *  newkey,
unsigned char *  newsig,
unsigned long  keycrc32 
) [static]

Definition at line 1460 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, dundi_peer::inkey, key(), LOG_DEBUG, LOG_NOTICE, option_debug, dundi_peer::outkey, dundi_peer::rxenckey, dundi_peer::them_dcx, dundi_peer::them_ecx, and dundi_peer::them_keycrc32.

01461 {
01462    unsigned char dst[128];
01463    int res;
01464    struct ast_key *key, *skey;
01465    char eid_str[20];
01466    if (option_debug)
01467       ast_log(LOG_DEBUG, "Expected '%08lx' got '%08lx'\n", peer->them_keycrc32, keycrc32);
01468    if (peer->them_keycrc32 && (peer->them_keycrc32 == keycrc32)) {
01469       /* A match */
01470       return 1;
01471    } else if (!newkey || !newsig)
01472       return 0;
01473    if (!memcmp(peer->rxenckey, newkey, 128) &&
01474        !memcmp(peer->rxenckey + 128, newsig, 128)) {
01475       /* By definition, a match */
01476       return 1;
01477    }
01478    /* Decrypt key */
01479    key = ast_key_get(peer->outkey, AST_KEY_PRIVATE);
01480    if (!key) {
01481       ast_log(LOG_NOTICE, "Unable to find key '%s' to decode shared key from '%s'\n",
01482          peer->outkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
01483       return -1;
01484    }
01485 
01486    skey = ast_key_get(peer->inkey, AST_KEY_PUBLIC);
01487    if (!skey) {
01488       ast_log(LOG_NOTICE, "Unable to find key '%s' to verify shared key from '%s'\n",
01489          peer->inkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
01490       return -1;
01491    }
01492 
01493    /* First check signature */
01494    res = ast_check_signature_bin(skey, (char *)newkey, 128, newsig);
01495    if (res) 
01496       return 0;
01497 
01498    res = ast_decrypt_bin(dst, newkey, sizeof(dst), key);
01499    if (res != 16) {
01500       if (res >= 0)
01501          ast_log(LOG_NOTICE, "Weird, key decoded to the wrong size (%d)\n", res);
01502       return 0;
01503    }
01504    /* Decrypted, passes signature */
01505    ast_log(LOG_DEBUG, "Wow, new key combo passed signature and decrypt!\n");
01506    memcpy(peer->rxenckey, newkey, 128);
01507    memcpy(peer->rxenckey + 128, newsig, 128);
01508    peer->them_keycrc32 = crc32(0L, peer->rxenckey, 128);
01509    aes_decrypt_key128(dst, &peer->them_dcx);
01510    aes_encrypt_key128(dst, &peer->them_ecx);
01511    return 1;
01512 }

static void check_password ( void   )  [static]

Definition at line 2078 of file pbx_dundi.c.

References build_secret(), cursecret, rotatetime, and save_secret().

Referenced by network_thread().

02079 {
02080    char oldsecret[80];
02081    time_t now;
02082    
02083    time(&now); 
02084 #if 0
02085    printf("%ld/%ld\n", now, rotatetime);
02086 #endif
02087    if ((now - rotatetime) >= 0) {
02088       /* Time to rotate keys */
02089       ast_copy_string(oldsecret, cursecret, sizeof(oldsecret));
02090       build_secret(cursecret, sizeof(cursecret));
02091       save_secret(cursecret, oldsecret);
02092    }
02093 }

static int check_request ( struct dundi_request dr  )  [static]

Definition at line 3501 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dr, dundi_request::next, and requests.

Referenced by dundi_lookup_internal().

03502 {
03503    struct dundi_request *cur;
03504    int res = 0;
03505    ast_mutex_lock(&peerlock);
03506    cur = requests;
03507    while(cur) {
03508       if (cur == dr) {
03509          res = 1;
03510          break;
03511       }
03512       cur = cur->next;
03513    }
03514    ast_mutex_unlock(&peerlock);
03515    return res;
03516 }

static char* complete_peer_4 ( char *  line,
char *  word,
int  pos,
int  state 
) [static]

Definition at line 2268 of file pbx_dundi.c.

References complete_peer_helper().

02269 {
02270    return complete_peer_helper(line, word, pos, state, 3);
02271 }

static char* complete_peer_helper ( char *  line,
char *  word,
int  pos,
int  state,
int  rpos 
) [static]

Definition at line 2243 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dundi_eid_to_str(), dundi_peer::eid, dundi_peer::next, peers, and strdup.

Referenced by complete_peer_4().

02244 {
02245    int which=0;
02246    char *ret;
02247    struct dundi_peer *p;
02248    char eid_str[20];
02249    if (pos != rpos)
02250       return NULL;
02251    ast_mutex_lock(&peerlock);
02252    p = peers;
02253    while(p) {
02254       if (!strncasecmp(word, dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid), strlen(word))) {
02255          if (++which > state)
02256             break;
02257       }
02258       p = p->next;
02259    }
02260    if (p) {
02261       ret = strdup(dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid));
02262    } else
02263       ret = NULL;
02264    ast_mutex_unlock(&peerlock);
02265    return ret;
02266 }

static struct dundi_transaction * create_transaction ( struct dundi_peer p  )  [static]

Definition at line 2776 of file pbx_dundi.c.

References dundi_peer::addr, alltrans, apply_peer(), ast_set_flag, DUNDI_DEFAULT_RETRANS_TIMER, FLAG_SENDFULLKEY, FLAG_STOREHIST, get_trans_id(), global_storehistory, malloc, and dundi_peer::sentfullkey.

Referenced by append_transaction(), do_register(), find_transaction(), and qualify_peer().

02777 {
02778    struct dundi_transaction *trans;
02779    int tid;
02780    
02781    /* Don't allow creation of transactions to non-registered peers */
02782    if (p && !p->addr.sin_addr.s_addr)
02783       return NULL;
02784    tid = get_trans_id();
02785    if (tid < 1)
02786       return NULL;
02787    trans = malloc(sizeof(struct dundi_transaction));
02788    if (trans) {
02789       memset(trans, 0, sizeof(struct dundi_transaction));
02790       if (global_storehistory) {
02791          trans->start = ast_tvnow();
02792          ast_set_flag(trans, FLAG_STOREHIST);
02793       }
02794       trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
02795       trans->autokillid = -1;
02796       if (p) {
02797          apply_peer(trans, p);
02798          if (!p->sentfullkey)
02799             ast_set_flag(trans, FLAG_SENDFULLKEY);
02800       }
02801       trans->strans = tid;
02802       trans->allnext = alltrans;
02803       alltrans = trans;
02804    }
02805    return trans;
02806 }

static int decrypt_memcpy ( unsigned char *  dst,
unsigned char *  src,
int  len,
unsigned char *  iv,
aes_decrypt_ctx dcx 
) [static]

Definition at line 1352 of file pbx_dundi.c.

References aes_decrypt().

Referenced by dundi_decrypt().

01353 {
01354    unsigned char lastblock[16];
01355    int x;
01356    memcpy(lastblock, iv, sizeof(lastblock));
01357    while(len > 0) {
01358       aes_decrypt(src, dst, dcx);
01359       for (x=0;x<16;x++)
01360          dst[x] ^= lastblock[x];
01361       memcpy(lastblock, src, sizeof(lastblock));
01362       dst += 16;
01363       src += 16;
01364       len -= 16;
01365    }
01366    return 0;
01367 }

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 4814 of file pbx_dundi.c.

References tdesc.

04815 {
04816    return tdesc;
04817 }

static void destroy_map ( struct dundi_mapping map  )  [static]

Definition at line 4049 of file pbx_dundi.c.

References free, and map.

Referenced by prune_mappings().

04050 {
04051    free(map);
04052 }

static void destroy_packet ( struct dundi_packet pack,
int  needfree 
) [static]

Definition at line 2825 of file pbx_dundi.c.

References ast_sched_del(), free, dundi_packet::next, dundi_transaction::packets, dundi_packet::parent, and dundi_packet::retransid.

Referenced by ack_trans().

02826 {
02827    struct dundi_packet *prev, *cur;
02828    if (pack->parent) {
02829       prev = NULL;
02830       cur = pack->parent->packets;
02831       while(cur) {
02832          if (cur == pack) {
02833             if (prev)
02834                prev->next = cur->next;
02835             else
02836                pack->parent->packets = cur->next;
02837             break;
02838          }
02839          prev = cur;
02840          cur = cur->next;
02841       }
02842    }
02843    if (pack->retransid > -1)
02844       ast_sched_del(sched, pack->retransid);
02845    if (needfree)
02846       free(pack);
02847    else {
02848       pack->retransid = -1;
02849       pack->next = NULL;
02850    }
02851 }

static void destroy_packets ( struct dundi_packet p  )  [static]

Definition at line 1905 of file pbx_dundi.c.

References ast_sched_del(), free, dundi_packet::next, and dundi_packet::retransid.

Referenced by ack_trans(), and handle_frame().

01906 {
01907    struct dundi_packet *prev;
01908    while(p) {
01909       prev = p;
01910       p = p->next;
01911       if (prev->retransid > -1)
01912          ast_sched_del(sched, prev->retransid);
01913       free(prev);
01914    }
01915 }

static void destroy_peer ( struct dundi_peer peer  )  [static]

Definition at line 4034 of file pbx_dundi.c.

References ast_sched_del(), destroy_permissions(), destroy_trans(), free, dundi_peer::include, dundi_peer::keypending, dundi_peer::permit, dundi_peer::qualifyid, dundi_peer::registerid, and dundi_peer::regtrans.

04035 {
04036    if (peer->registerid > -1)
04037       ast_sched_del(sched, peer->registerid);
04038    if (peer->regtrans)
04039       destroy_trans(peer->regtrans, 0);
04040    if (peer->keypending)
04041       destroy_trans(peer->keypending, 0);
04042    if (peer->qualifyid > -1)
04043       ast_sched_del(sched, peer->qualifyid);
04044    destroy_permissions(peer->permit);
04045    destroy_permissions(peer->include);
04046    free(peer);
04047 }

static void destroy_permissions ( struct permission p  )  [static]

Definition at line 4024 of file pbx_dundi.c.

References free, and permission::next.

Referenced by build_peer(), and destroy_peer().

04025 {
04026    struct permission *prev;
04027    while(p) {
04028       prev = p;
04029       p = p->next;
04030       free(prev);
04031    }
04032 }

static void destroy_trans ( struct dundi_transaction trans,
int  fromtimeout 
) [static]

Definition at line 2853 of file pbx_dundi.c.

References ast_log(), ast_strlen_zero(), ast_test_flag, dundi_peer::avgms, dundi_request::dcontext, dundi_eid_cmp(), dundi_eid_to_str(), DUNDI_TIMING_HISTORY, dundi_peer::eid, FLAG_ISQUAL, FLAG_ISREG, FLAG_STOREHIST, free, dundi_peer::keypending, dundi_peer::lastms, LOG_NOTICE, dundi_peer::lookups, dundi_peer::lookuptimes, malloc, dundi_peer::maxms, dundi_peer::next, dundi_request::number, dundi_transaction::parent, peers, dundi_peer::qualtrans, dundi_peer::qualtx, dundi_peer::regtrans, dundi_transaction::start, and dundi_transaction::them_eid.

Referenced by abort_request(), destroy_peer(), do_autokill(), do_register(), dundi_lookup_thread(), dundi_precache_thread(), dundi_query_thread(), dundi_rexmit(), handle_frame(), precache_trans(), precache_transactions(), and qualify_peer().

02854 {
02855    struct dundi_transaction *cur, *prev;
02856    struct dundi_peer *peer;
02857    int ms;
02858    int x;
02859    int cnt;
02860    char eid_str[20];
02861    if (ast_test_flag(trans, FLAG_ISREG | FLAG_ISQUAL | FLAG_STOREHIST)) {
02862       peer = peers;
02863       while (peer) {
02864          if (peer->regtrans == trans)
02865             peer->regtrans = NULL;
02866          if (peer->keypending == trans)
02867             peer->keypending = NULL;
02868          if (peer->qualtrans == trans) {
02869             if (fromtimeout) {
02870                if (peer->lastms > -1)
02871                   ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
02872                peer->lastms = -1;
02873             } else {
02874                ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx);
02875                if (ms < 1)
02876                   ms = 1;
02877                if (ms < peer->maxms) {
02878                   if ((peer->lastms >= peer->maxms) || (peer->lastms < 0))
02879                      ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
02880                } else if (peer->lastms < peer->maxms) {
02881                   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);
02882                }
02883                peer->lastms = ms;
02884             }
02885             peer->qualtrans = NULL;
02886          }
02887          if (ast_test_flag(trans, FLAG_STOREHIST)) {
02888             if (trans->parent && !ast_strlen_zero(trans->parent->number)) {
02889                if (!dundi_eid_cmp(&trans->them_eid, &peer->eid)) {
02890                   peer->avgms = 0;
02891                   cnt = 0;
02892                   if (peer->lookups[DUNDI_TIMING_HISTORY-1])
02893                      free(peer->lookups[DUNDI_TIMING_HISTORY-1]);
02894                   for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) {
02895                      peer->lookuptimes[x] = peer->lookuptimes[x-1];
02896                      peer->lookups[x] = peer->lookups[x-1];
02897                      if (peer->lookups[x]) {
02898                         peer->avgms += peer->lookuptimes[x];
02899                         cnt++;
02900                      }
02901                   }
02902                   peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start);
02903                   peer->lookups[0] = malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2);
02904                   if (peer->lookups[0]) {
02905                      sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext);
02906                      peer->avgms += peer->lookuptimes[0];
02907                      cnt++;
02908                   }
02909                   if (cnt)
02910                      peer->avgms /= cnt;
02911                }
02912             }
02913          }
02914          peer = peer->next;
02915       }
02916    }
02917    if (trans->parent) {
02918       /* Unlink from parent if appropriate */
02919       prev = NULL;
02920       cur = trans->parent->trans;
02921       while(cur) {
02922          if (cur == trans) {
02923             if (prev)
02924                prev->next = trans->next;
02925             else
02926                trans->parent->trans = trans->next;
02927             break;
02928          }
02929          prev = cur;
02930          cur = cur->next;
02931       }
02932       if (!trans->parent->trans) {
02933          /* Wake up sleeper */
02934          if (trans->parent->pfds[1] > -1) {
02935             write(trans->parent->pfds[1], "killa!", 6);
02936          }
02937       }
02938    }
02939    /* Unlink from all trans */
02940    prev = NULL;
02941    cur = alltrans;
02942    while(cur) {
02943       if (cur == trans) {
02944          if (prev)
02945             prev->allnext = trans->allnext;
02946          else
02947             alltrans = trans->allnext;
02948          break;
02949       }
02950       prev = cur;
02951       cur = cur->allnext;
02952    }
02953    destroy_packets(trans->packets);
02954    destroy_packets(trans->lasttrans);
02955    trans->packets = NULL;
02956    trans->lasttrans = NULL;
02957    if (trans->autokillid > -1)
02958       ast_sched_del(sched, trans->autokillid);
02959    trans->autokillid = -1;
02960    if (trans->thread) {
02961       /* If used by a thread, mark as dead and be done */
02962       ast_set_flag(trans, FLAG_DEAD);
02963    } else
02964       free(trans);
02965 }

static int discover_transactions ( struct dundi_request dr  )  [static]

Definition at line 3212 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dr, and dundi_discover().

Referenced by dundi_lookup_internal().

03213 {
03214    struct dundi_transaction *trans;
03215    ast_mutex_lock(&peerlock);
03216    trans = dr->trans;
03217    while(trans) {
03218       dundi_discover(trans);
03219       trans = trans->next;
03220    }
03221    ast_mutex_unlock(&peerlock);
03222    return 0;
03223 }

static int do_autokill ( void *  data  )  [static]

Definition at line 3065 of file pbx_dundi.c.

References ast_log(), dundi_transaction::autokillid, destroy_trans(), dundi_eid_to_str(), LOG_NOTICE, and dundi_transaction::them_eid.

Referenced by dundi_discover(), dundi_query(), and precache_trans().

03066 {
03067    struct dundi_transaction *trans = data;
03068    char eid_str[20];
03069    ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n", 
03070       dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
03071    trans->autokillid = -1;
03072    destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */
03073    return 0;
03074 }

static int do_qualify ( void *  data  )  [static]

Definition at line 4223 of file pbx_dundi.c.

References qualify_peer(), and dundi_peer::qualifyid.

Referenced by qualify_peer().

04224 {
04225    struct dundi_peer *peer;
04226    peer = data;
04227    peer->qualifyid = -1;
04228    qualify_peer(peer, 0);
04229    return 0;
04230 }

static int do_register ( void *  data  )  [static]

Definition at line 4196 of file pbx_dundi.c.

References ast_log(), ast_sched_add(), ast_set_flag, create_transaction(), default_expiration, destroy_trans(), DUNDI_COMMAND_REGREQ, DUNDI_DEFAULT_VERSION, dundi_eid_to_str(), dundi_ie_append_eid(), dundi_ie_append_short(), DUNDI_IE_EID, DUNDI_IE_EXPIRATION, DUNDI_IE_VERSION, dundi_send(), dundi_peer::eid, FLAG_ISREG, LOG_DEBUG, LOG_NOTICE, dundi_peer::registerid, dundi_peer::regtrans, dundi_transaction::us_eid, and dundi_peer::us_eid.

Referenced by build_peer().

04197 {
04198    struct dundi_ie_data ied;
04199    struct dundi_peer *peer = data;
04200    char eid_str[20];
04201    char eid_str2[20];
04202    /* Called with peerlock already held */
04203    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));
04204    peer->registerid = ast_sched_add(sched, default_expiration * 1000, do_register, data);
04205    /* Destroy old transaction if there is one */
04206    if (peer->regtrans)
04207       destroy_trans(peer->regtrans, 0);
04208    peer->regtrans = create_transaction(peer);
04209    if (peer->regtrans) {
04210       ast_set_flag(peer->regtrans, FLAG_ISREG);
04211       memset(&ied, 0, sizeof(ied));
04212       dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
04213       dundi_ie_append_eid(&ied, DUNDI_IE_EID, &peer->regtrans->us_eid);
04214       dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, default_expiration);
04215       dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied);
04216       
04217    } else
04218       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));
04219 
04220    return 0;
04221 }

static int do_register_expire ( void *  data  )  [static]

Definition at line 1285 of file pbx_dundi.c.

References dundi_peer::addr, ast_log(), dundi_eid_to_str(), dundi_peer::eid, dundi_peer::lastms, LOG_DEBUG, and dundi_peer::registerexpire.

Referenced by handle_command_response(), and populate_addr().

01286 {
01287    struct dundi_peer *peer = data;
01288    char eid_str[20];
01289    /* Called with peerlock already held */
01290    ast_log(LOG_DEBUG, "Register expired for '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
01291    peer->registerexpire = -1;
01292    peer->lastms = 0;
01293    memset(&peer->addr, 0, sizeof(peer->addr));
01294    return 0;
01295 }

static int dundi_ack ( struct dundi_transaction trans,
int  final 
) [static]

Definition at line 378 of file pbx_dundi.c.

References DUNDI_COMMAND_ACK, and dundi_send().

Referenced by handle_frame().

00379 {
00380    return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL);
00381 }

static int dundi_answer_entity ( struct dundi_transaction trans,
struct dundi_ies ies,
char *  ccontext 
) [static]

Definition at line 755 of file pbx_dundi.c.

References ast_log(), ast_pthread_create, 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(), free, ies, LOG_DEBUG, LOG_WARNING, malloc, s, dundi_transaction::thread, dundi_query_state::trans, and dundi_transaction::ttl.

Referenced by handle_command_response().

00756 {
00757    struct dundi_query_state *st;
00758    int totallen;
00759    int x;
00760    int skipfirst=0;
00761    struct dundi_ie_data ied;
00762    char eid_str[20];
00763    char *s;
00764    pthread_t lookupthread;
00765    pthread_attr_t attr;
00766    if (ies->eidcount > 1) {
00767       /* Since it is a requirement that the first EID is the authenticating host
00768          and the last EID is the root, it is permissible that the first and last EID
00769          could be the same.  In that case, we should go ahead copy only the "root" section
00770          since we will not need it for authentication. */
00771       if (!dundi_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
00772          skipfirst = 1;
00773    }
00774    totallen = sizeof(struct dundi_query_state);
00775    totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
00776    st = malloc(totallen);
00777    if (st) {
00778       memset(st, 0, totallen);
00779       ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context));
00780       memcpy(&st->reqeid, ies->reqeid, sizeof(st->reqeid));
00781       st->trans = trans;
00782       st->ttl = ies->ttl - 1;
00783       if (st->ttl < 0)
00784          st->ttl = 0;
00785       s = st->fluffy;
00786       for (x=skipfirst;ies->eids[x];x++) {
00787          st->eids[x-skipfirst] = (dundi_eid *)s;
00788          *st->eids[x-skipfirst] = *ies->eids[x];
00789          s += sizeof(dundi_eid);
00790       }
00791       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);
00792       pthread_attr_init(&attr);
00793       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00794       trans->thread = 1;
00795       if (ast_pthread_create(&lookupthread, &attr, dundi_query_thread, st)) {
00796          trans->thread = 0;
00797          ast_log(LOG_WARNING, "Unable to create thread!\n");
00798          free(st);
00799          memset(&ied, 0, sizeof(ied));
00800          dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
00801          dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
00802          return -1;
00803       }
00804    } else {
00805       ast_log(LOG_WARNING, "Out of memory!\n");
00806       memset(&ied, 0, sizeof(ied));
00807       dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
00808       dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
00809       return -1;
00810    }
00811    return 0;
00812 }

static int dundi_answer_query ( struct dundi_transaction trans,
struct dundi_ies ies,
char *  ccontext 
) [static]

Definition at line 1045 of file pbx_dundi.c.

References ast_log(), ast_pthread_create, dundi_mapping::dcontext, DUNDI_CAUSE_GENERAL, DUNDI_COMMAND_DPRESPONSE, dundi_eid_cmp(), dundi_ie_append_cause(), DUNDI_IE_CAUSE, dundi_lookup_thread(), dundi_send(), free, ies, LOG_DEBUG, LOG_WARNING, malloc, mappings, dundi_mapping::next, dundi_query_state::nummaps, s, dundi_transaction::thread, and dundi_transaction::ttl.

Referenced by handle_command_response().

01046 {
01047    struct dundi_query_state *st;
01048    int totallen;
01049    int x;
01050    struct dundi_ie_data ied;
01051    char *s;
01052    struct dundi_mapping *cur;
01053    int mapcount;
01054    int skipfirst = 0;
01055    
01056    pthread_t lookupthread;
01057    pthread_attr_t attr;
01058    totallen = sizeof(struct dundi_query_state);
01059    /* Count matching map entries */
01060    mapcount = 0;
01061    cur = mappings;
01062    while(cur) {
01063       if (!strcasecmp(cur->dcontext, ccontext))
01064          mapcount++;
01065       cur = cur->next;
01066    }
01067    /* If no maps, return -1 immediately */
01068    if (!mapcount)
01069       return -1;
01070 
01071    if (ies->eidcount > 1) {
01072       /* Since it is a requirement that the first EID is the authenticating host
01073          and the last EID is the root, it is permissible that the first and last EID
01074          could be the same.  In that case, we should go ahead copy only the "root" section
01075          since we will not need it for authentication. */
01076       if (!dundi_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
01077          skipfirst = 1;
01078    }
01079 
01080    totallen += mapcount * sizeof(struct dundi_mapping);
01081    totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
01082    st = malloc(totallen);
01083    if (st) {
01084       memset(st, 0, totallen);
01085       ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context));
01086       ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
01087       st->trans = trans;
01088       st->ttl = ies->ttl - 1;
01089       st->nocache = ies->cbypass;
01090       if (st->ttl < 0)
01091          st->ttl = 0;
01092       s = st->fluffy;
01093       for (x=skipfirst;ies->eids[x];x++) {
01094          st->eids[x-skipfirst] = (dundi_eid *)s;
01095          *st->eids[x-skipfirst] = *ies->eids[x];
01096          st->directs[x-skipfirst] = ies->eid_direct[x];
01097          s += sizeof(dundi_eid);
01098       }
01099       /* Append mappings */
01100       x = 0;
01101       st->maps = (struct dundi_mapping *)s;
01102       cur = mappings;
01103       while(cur) {
01104          if (!strcasecmp(cur->dcontext, ccontext)) {
01105             if (x < mapcount) {
01106                st->maps[x] = *cur;
01107                st->maps[x].next = NULL;
01108                x++;
01109             }
01110          }
01111          cur = cur->next;
01112       }
01113       st->nummaps = mapcount;
01114       ast_log(LOG_DEBUG, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context);
01115       pthread_attr_init(&attr);
01116       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01117       trans->thread = 1;
01118       if (ast_pthread_create(&lookupthread, &attr, dundi_lookup_thread, st)) {
01119          trans->thread = 0;
01120          ast_log(LOG_WARNING, "Unable to create thread!\n");
01121          free(st);
01122          memset(&ied, 0, sizeof(ied));
01123          dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
01124          dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
01125          return -1;
01126       }
01127    } else {
01128       ast_log(LOG_WARNING, "Out of memory!\n");
01129       memset(&ied, 0, sizeof(ied));
01130       dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
01131       dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
01132       return -1;
01133    }
01134    return 0;
01135 }

static int dundi_canmatch ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 4481 of file pbx_dundi.c.

References DUNDI_FLAG_CANMATCH, and dundi_helper().

04482 {
04483    return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH);
04484 }

static void dundi_debug_output ( const char *  data  )  [static]

Definition at line 283 of file pbx_dundi.c.

References ast_verbose().

Referenced by load_module().

00284 {
00285    if (dundidebug)
00286       ast_verbose("%s", data);
00287 }

static struct dundi_hdr* dundi_decrypt ( struct dundi_transaction trans,
unsigned char *  dst,
int *  dstlen,
struct dundi_hdr ohdr,
struct dundi_encblock src,
int  srclen 
) [static]

Definition at line 1369 of file pbx_dundi.c.

References ast_log(), dundi_transaction::dcx, decrypt_memcpy(), dundi_encblock::encdata, dundi_encblock::iv, LOG_DEBUG, and space.

01370 {
01371    int space = *dstlen;
01372    unsigned long bytes;
01373    struct dundi_hdr *h;
01374    unsigned char *decrypt_space;
01375    decrypt_space = alloca(srclen);
01376    if (!decrypt_space)
01377       return NULL;
01378    decrypt_memcpy(decrypt_space, src->encdata, srclen, src->iv, &trans->dcx);
01379    /* Setup header */
01380    h = (struct dundi_hdr *)dst;
01381    *h = *ohdr;
01382    bytes = space - 6;
01383    if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) {
01384       ast_log(LOG_DEBUG, "Ouch, uncompress failed :(\n");
01385       return NULL;
01386    }
01387    /* Update length */
01388    *dstlen = bytes + 6;
01389    /* Return new header */
01390    return h;
01391 }

static int dundi_discover ( struct dundi_transaction trans  )  [static]

Definition at line 3100 of file pbx_dundi.c.

References ast_log(), ast_sched_add(), dundi_transaction::autokillid, dundi_transaction::autokilltimeout, dundi_request::cbypass, dundi_request::dcontext, do_autokill(), DUNDI_COMMAND_DPDISCOVER, DUNDI_DEFAULT_VERSION, dundi_eid_zero(), dundi_ie_append(), dundi_ie_append_eid(), dundi_ie_append_eid_appropriately(), dundi_ie_append_short(), dundi_ie_append_str(), DUNDI_IE_CACHEBYPASS, DUNDI_IE_CALLED_CONTEXT, DUNDI_IE_CALLED_NUMBER, DUNDI_IE_EID_DIRECT, DUNDI_IE_TTL, DUNDI_IE_VERSION, dundi_send(), dundi_transaction::eidcount, dundi_transaction::eids, LOG_WARNING, dundi_request::number, dundi_transaction::parent, dundi_transaction::ttl, and dundi_transaction::us_eid.

Referenced by discover_transactions().

03101 {
03102    struct dundi_ie_data ied;
03103    int x;
03104    if (!trans->parent) {
03105       ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
03106       return -1;
03107    }
03108    memset(&ied, 0, sizeof(ied));
03109    dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
03110    if (!dundi_eid_zero(&trans->us_eid))
03111       dundi_ie_append_eid(&ied, DUNDI_IE_EID_DIRECT, &trans->us_eid);
03112    for (x=0;x<trans->eidcount;x++)
03113       dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid);
03114    dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number);
03115    dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext);
03116    dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
03117    if (trans->parent->cbypass)
03118       dundi_ie_append(&ied, DUNDI_IE_CACHEBYPASS);
03119    if (trans->autokilltimeout)
03120       trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
03121    return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied);
03122 }

static int dundi_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2158 of file pbx_dundi.c.

References ast_cli(), dundidebug, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02159 {
02160    if (argc != 2)
02161       return RESULT_SHOWUSAGE;
02162    dundidebug = 1;
02163    ast_cli(fd, "DUNDi Debugging Enabled\n");
02164    return RESULT_SUCCESS;
02165 }

static int dundi_do_lookup ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2290 of file pbx_dundi.c.

References ast_cli(), context, dr, dundi_flags2str(), dundi_lookup(), MAX_RESULTS, RESULT_SHOWUSAGE, RESULT_SUCCESS, and sort_results().

02291 {
02292    int res;
02293    char tmp[256];
02294    char fs[80] = "";
02295    char *context;
02296    int x;
02297    int bypass = 0;
02298    struct dundi_result dr[MAX_RESULTS];
02299    struct timeval start;
02300    if ((argc < 3) || (argc > 4))
02301       return RESULT_SHOWUSAGE;
02302    if (argc > 3) {
02303       if (!strcasecmp(argv[3], "bypass"))
02304          bypass=1;
02305       else
02306          return RESULT_SHOWUSAGE;
02307    }
02308    ast_copy_string(tmp, argv[2], sizeof(tmp));
02309    context = strchr(tmp, '@');
02310    if (context) {
02311       *context = '\0';
02312       context++;
02313    }
02314    start = ast_tvnow();
02315    res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
02316    
02317    if (res < 0) 
02318       ast_cli(fd, "DUNDi lookup returned error.\n");
02319    else if (!res) 
02320       ast_cli(fd, "DUNDi lookup returned no results.\n");
02321    else
02322       sort_results(dr, res);
02323    for (x=0;x<res;x++) {
02324       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));
02325       ast_cli(fd, "     from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration);
02326    }
02327    ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
02328    return RESULT_SUCCESS;
02329 }

static int dundi_do_precache ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2331 of file pbx_dundi.c.

References ast_cli(), context, dundi_precache(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02332 {
02333    int res;
02334    char tmp[256];
02335    char *context;
02336    struct timeval start;
02337    if ((argc < 3) || (argc > 3))
02338       return RESULT_SHOWUSAGE;
02339    ast_copy_string(tmp, argv[2], sizeof(tmp));
02340    context = strchr(tmp, '@');
02341    if (context) {
02342       *context = '\0';
02343       context++;
02344    }
02345    start = ast_tvnow();
02346    res = dundi_precache(context, tmp);
02347    
02348    if (res < 0) 
02349       ast_cli(fd, "DUNDi precache returned error.\n");
02350    else if (!res) 
02351       ast_cli(fd, "DUNDi precache returned no error.\n");
02352    ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
02353    return RESULT_SUCCESS;
02354 }

static int dundi_do_query ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2356 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.

02357 {
02358    int res;
02359    char tmp[256];
02360    char *context;
02361    dundi_eid eid;
02362    struct dundi_entity_info dei;
02363    if ((argc < 3) || (argc > 3))
02364       return RESULT_SHOWUSAGE;
02365    if (dundi_str_to_eid(&eid, argv[2])) {
02366       ast_cli(fd, "'%s' is not a valid EID!\n", argv[2]);
02367       return RESULT_SHOWUSAGE;
02368    }
02369    ast_copy_string(tmp, argv[2], sizeof(tmp));
02370    context = strchr(tmp, '@');
02371    if (context) {
02372       *context = '\0';
02373       context++;
02374    }
02375    res = dundi_query_eid(&dei, context, eid);
02376    if (res < 0) 
02377       ast_cli(fd, "DUNDi Query EID returned error.\n");
02378    else if (!res) 
02379       ast_cli(fd, "DUNDi Query EID returned no results.\n");
02380    else {
02381       ast_cli(fd, "DUNDi Query EID succeeded:\n");
02382       ast_cli(fd, "Department:      %s\n", dei.orgunit);
02383       ast_cli(fd, "Organization:    %s\n", dei.org);
02384       ast_cli(fd, "City/Locality:   %s\n", dei.locality);
02385       ast_cli(fd, "State/Province:  %s\n", dei.stateprov);
02386       ast_cli(fd, "Country:         %s\n", dei.country);
02387       ast_cli(fd, "E-mail:          %s\n", dei.email);
02388       ast_cli(fd, "Phone:           %s\n", dei.phone);
02389       ast_cli(fd, "IP Address:      %s\n", dei.ipaddr);
02390    }
02391    return RESULT_SUCCESS;
02392 }

static int dundi_do_store_history ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2167 of file pbx_dundi.c.

References ast_cli(), global_storehistory, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02168 {
02169    if (argc != 3)
02170       return RESULT_SHOWUSAGE;
02171    global_storehistory = 1;
02172    ast_cli(fd, "DUNDi History Storage Enabled\n");
02173    return RESULT_SUCCESS;
02174 }

static int dundi_encrypt ( struct dundi_transaction trans,
struct dundi_packet pack 
) [static]

Definition at line 1393 of file pbx_dundi.c.

References ast_log(), ast_set_flag, ast_test_flag, build_iv(), dundi_hdr::cmdflags, dundi_hdr::cmdresp, dundi_packet::data, dundi_packet::datalen, 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, dundi_packet::h, dundi_hdr::ies, dundi_hdr::iseqno, LOG_DEBUG, LOG_NOTICE, dundi_hdr::oseqno, dundi_peer::sentfullkey, dundi_transaction::them_eid, dundi_peer::txenckey, update_key(), dundi_peer::us_dcx, dundi_peer::us_ecx, dundi_transaction::us_eid, and dundi_peer::us_keycrc32.

Referenced by dundi_send().

01394 {
01395    unsigned char *compress_space;
01396    int len;
01397    int res;
01398    unsigned long bytes;
01399    struct dundi_ie_data ied;
01400    struct dundi_peer *peer;
01401    unsigned char iv[16];
01402    len = pack->datalen + pack->datalen / 100 + 42;
01403    compress_space = alloca(len);
01404    if (compress_space) {
01405       memset(compress_space, 0, len);
01406       /* We care about everthing save the first 6 bytes of header */
01407       bytes = len;
01408       res = compress(compress_space, &bytes, pack->data + 6, pack->datalen - 6);
01409       if (res != Z_OK) {
01410          ast_log(LOG_DEBUG, "Ouch, compression failed!\n");
01411          return -1;
01412       }
01413       memset(&ied, 0, sizeof(ied));
01414       /* Say who we are */
01415       if (!pack->h->iseqno && !pack->h->oseqno) {
01416          /* Need the key in the first copy */
01417          if (!(peer = find_peer(&trans->them_eid))) 
01418             return -1;
01419          if (update_key(peer))
01420             return -1;
01421          if (!peer->sentfullkey)
01422             ast_set_flag(trans, FLAG_SENDFULLKEY); 
01423          /* Append key data */
01424          dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
01425          if (ast_test_flag(trans, FLAG_SENDFULLKEY)) {
01426             dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128);
01427             dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
01428          } else {
01429             dundi_ie_append_int(&ied, DUNDI_IE_KEYCRC32, peer->us_keycrc32);
01430          }
01431          /* Setup contexts */
01432          trans->ecx = peer->us_ecx;
01433          trans->dcx = peer->us_dcx;
01434 
01435          /* We've sent the full key */
01436          peer->sentfullkey = 1;
01437       }
01438       /* Build initialization vector */
01439       build_iv(iv);
01440       /* Add the field, rounded up to 16 bytes */
01441       dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, iv, NULL, ((bytes + 15) / 16) * 16);
01442       /* Copy the data */
01443       if ((ied.pos + bytes) >= sizeof(ied.buf)) {
01444          ast_log(LOG_NOTICE, "Final packet too large!\n");
01445          return -1;
01446       }
01447       encrypt_memcpy(ied.buf + ied.pos, compress_space, bytes, iv, &trans->ecx);
01448       ied.pos += ((bytes + 15) / 16) * 16;
01449       /* Reconstruct header */
01450       pack->datalen = sizeof(struct dundi_hdr);
01451       pack->h->cmdresp = DUNDI_COMMAND_ENCRYPT;
01452       pack->h->cmdflags = 0;
01453       memcpy(pack->h->ies, ied.buf, ied.pos);
01454       pack->datalen += ied.pos;
01455       return 0;
01456    }
01457    return -1;
01458 }

static void dundi_error_output ( const char *  data  )  [static]

Definition at line 289 of file pbx_dundi.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

00290 {
00291    ast_log(LOG_WARNING, "%s", data);
00292 }

static int dundi_exec ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
int  newstack,
const char *  data 
) [static]

Definition at line 4486 of file pbx_dundi.c.

References ast_log(), ast_strlen_zero(), ast_test_flag, DUNDI_FLAG_EXISTS, dundi_lookup(), ast_channel::exten, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, MAX_RESULTS, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), and sort_results().

04487 {
04488    struct dundi_result results[MAX_RESULTS];
04489    int res;
04490    int x=0;
04491    char req[1024];
04492    struct ast_app *dial;
04493    
04494    if (!strncasecmp(context, "macro-", 6)) {
04495       if (!chan) {   
04496          ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
04497          return -1;
04498       }
04499       /* If done as a macro, use macro extension */
04500       if (!strcasecmp(exten, "s")) {
04501          exten = pbx_builtin_getvar_helper(chan, "ARG1");
04502          if (ast_strlen_zero(exten))
04503             exten = chan->macroexten;
04504          if (ast_strlen_zero(exten))
04505             exten = chan->exten;
04506          if (ast_strlen_zero(exten)) { 
04507             ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
04508             return -1;
04509          }
04510       }
04511       if (ast_strlen_zero(data))
04512          data = "e164";
04513    } else {
04514       if (ast_strlen_zero(data))
04515          data = context;
04516    }
04517    res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
04518    if (res > 0) {
04519       sort_results(results, res);
04520       for (x=0;x<res;x++) {
04521          if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) {
04522             if (!--priority)
04523                break;
04524          }
04525       }
04526    }
04527    if (x < res) {
04528       /* Got a hit! */
04529       snprintf(req, sizeof(req), "%s/%s", results[x].tech, results[x].dest);
04530       dial = pbx_findapp("Dial");
04531       if (dial)
04532          res = pbx_exec(chan, dial, req, newstack);
04533    } else
04534       res = -1;
04535    return res;
04536 }

static int dundi_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 4476 of file pbx_dundi.c.

References DUNDI_FLAG_EXISTS, and dundi_helper().

04477 {
04478    return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS);
04479 }

static int dundi_flush ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2176 of file pbx_dundi.c.

References ast_cli(), ast_db_deltree(), ast_mutex_lock(), ast_mutex_unlock(), dundi_peer::avgms, DUNDI_TIMING_HISTORY, free, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::next, peers, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02177 {
02178    int stats=0;
02179    if ((argc < 2) || (argc > 3))
02180       return RESULT_SHOWUSAGE;
02181    if (argc > 2) {
02182       if (!strcasecmp(argv[2], "stats"))
02183          stats = 1;
02184       else
02185          return RESULT_SHOWUSAGE;
02186    }
02187    if (stats) {
02188       /* Flush statistics */
02189       struct dundi_peer *p;
02190       int x;
02191       ast_mutex_lock(&peerlock);
02192       p = peers;
02193       while(p) {
02194          for (x=0;x<DUNDI_TIMING_HISTORY;x++) {
02195             if (p->lookups[x])
02196                free(p->lookups[x]);
02197             p->lookups[x] = NULL;
02198             p->lookuptimes[x] = 0;
02199          }
02200          p->avgms = 0;
02201          p = p->next;
02202       }
02203       ast_mutex_unlock(&peerlock);
02204    } else {
02205       ast_db_deltree("dundi/cache", NULL);
02206       ast_cli(fd, "DUNDi Cache Flushed\n");
02207    }
02208    return RESULT_SUCCESS;
02209 }

static int dundi_helper ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  data,
int  flag 
) [static]

Definition at line 4437 of file pbx_dundi.c.

References ast_log(), ast_strlen_zero(), ast_test_flag, dundi_lookup(), ast_channel::exten, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, MAX_RESULTS, and pbx_builtin_getvar_helper().

Referenced by dundi_canmatch(), dundi_exists(), and dundi_matchmore().

04438 {
04439    struct dundi_result results[MAX_RESULTS];
04440    int res;
04441    int x;
04442    int found = 0;
04443    if (!strncasecmp(context, "macro-", 6)) {
04444       if (!chan) {   
04445          ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
04446          return -1;
04447       }
04448       /* If done as a macro, use macro extension */
04449       if (!strcasecmp(exten, "s")) {
04450          exten = pbx_builtin_getvar_helper(chan, "ARG1");
04451          if (ast_strlen_zero(exten))
04452             exten = chan->macroexten;
04453          if (ast_strlen_zero(exten))
04454             exten = chan->exten;
04455          if (ast_strlen_zero(exten)) { 
04456             ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
04457             return -1;
04458          }
04459       }
04460       if (ast_strlen_zero(data))
04461          data = "e164";
04462    } else {
04463       if (ast_strlen_zero(data))
04464          data = context;
04465    }
04466    res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
04467    for (x=0;x<res;x++) {
04468       if (ast_test_flag(results + x, flag))
04469          found++;
04470    }
04471    if (found >= priority)
04472       return 1;
04473    return 0;
04474 }

static void dundi_ie_append_eid_appropriately ( struct dundi_ie_data ied,
char *  context,
dundi_eid eid,
dundi_eid us 
) [static]

Definition at line 3076 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dundi_eid_cmp(), dundi_ie_append_eid(), DUNDI_IE_EID, DUNDI_IE_EID_DIRECT, dundi_peer::eid, has_permission(), dundi_peer::include, dundi_peer::next, and peers.

Referenced by dundi_discover().

03077 {
03078    struct dundi_peer *p;
03079    if (!dundi_eid_cmp(eid, us)) {
03080       dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid);
03081       return;
03082    }
03083    ast_mutex_lock(&peerlock);
03084    p = peers;
03085    while(p) {
03086       if (!dundi_eid_cmp(&p->eid, eid)) {
03087          if (has_permission(p->include, context))
03088             dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid);
03089          else
03090             dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
03091          break;
03092       }
03093       p = p->next;
03094    }
03095    if (!p)
03096       dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
03097    ast_mutex_unlock(&peerlock);
03098 }

int dundi_lookup ( struct dundi_result result,
int  maxret,
struct ast_channel chan,
const char *  dcontext,
const char *  number,
int  cbypass 
)

Lookup the given number in the given dundi context (or e164 if unspecified) using the given callerid (if specified) and return up to maxret results in the array specified. returns the number of results found or -1 on a hangup of teh channel.

Definition at line 3635 of file pbx_dundi.c.

References dundi_cache_time, DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, dundi_lookup_internal(), dundi_ttl, and result.

Referenced by dundi_do_lookup(), dundi_exec(), dundi_helper(), dundi_lookup_exec(), and dundifunc_read().

03636 {
03637    struct dundi_hint_metadata hmd;
03638    dundi_eid *avoid[1] = { NULL, };
03639    int direct[1] = { 0, };
03640    int expiration = dundi_cache_time;
03641    memset(&hmd, 0, sizeof(hmd));
03642    hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED;
03643    return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct);
03644 }

static int dundi_lookup_internal ( struct dundi_result result,
int  maxret,
struct ast_channel chan,
const char *  dcontext,
const char *  number,
int  ttl,
int  blockempty,
struct dundi_hint_metadata md,
int *  expiration,
int  cybpass,
int  modeselect,
dundi_eid skip,
dundi_eid avoid[],
int  direct[] 
) [static]

Definition at line 3533 of file pbx_dundi.c.

References ast_channel::_softhangup, abort_request(), ast_log(), ast_set_flag_nonstd, ast_waitfor_n_fd(), avoid_crc32(), build_transactions(), cancel_request(), check_request(), discover_transactions(), dr, dundi_eid_cmp(), dundi_eid_to_str(), DUNDI_FLUFF_TIME, DUNDI_HINT_TTL_EXPIRED, DUNDI_TTL_TIME, LOG_DEBUG, LOG_WARNING, ast_channel::name, optimize_transactions(), register_request(), result, dundi_request::root_eid, and unregister_request().

Referenced by dundi_lookup(), dundi_lookup_thread(), and precache_trans().

03534 {
03535    int res;
03536    struct dundi_request dr, *pending;
03537    dundi_eid *rooteid=NULL;
03538    int x;
03539    int ttlms;
03540    int ms;
03541    int foundcache;
03542    int skipped=0;
03543    int order=0;
03544    char eid_str[20];
03545    struct timeval start;
03546    
03547    /* Don't do anthing for a hungup channel */
03548    if (chan && chan->_softhangup)
03549       return 0;
03550 
03551    ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
03552 
03553    for (x=0;avoid[x];x++)
03554       rooteid = avoid[x];
03555    /* Now perform real check */
03556    memset(&dr, 0, sizeof(dr));
03557    if (pipe(dr.pfds)) {
03558       ast_log(LOG_WARNING, "pipe failed: %s\n" , strerror(errno));
03559       return -1;
03560    }
03561    dr.dr = result;
03562    dr.hmd = hmd;
03563    dr.maxcount = maxret;
03564    dr.expiration = *expiration;
03565    dr.cbypass = cbypass;
03566    dr.crc32 = avoid_crc32(avoid);
03567    ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
03568    ast_copy_string(dr.number, number, sizeof(dr.number));
03569    if (rooteid)
03570       dr.root_eid = *rooteid;
03571    res = register_request(&dr, &pending);
03572    if (res) {
03573       /* Already a request */
03574       if (rooteid && !dundi_eid_cmp(&dr.root_eid, &pending->root_eid)) {
03575          /* This is on behalf of someone else.  Go ahead and close this out since
03576             they'll get their answer anyway. */
03577          ast_log(LOG_DEBUG, "Oooh, duplicate request for '%s@%s' for '%s'\n",
03578             dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid));
03579          close(dr.pfds[0]);
03580          close(dr.pfds[1]);
03581          return -2;
03582       } else {
03583          /* Wait for the cache to populate */
03584          ast_log(LOG_DEBUG, "Waiting for similar request for '%s@%s' for '%s'\n",
03585             dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid));
03586          start = ast_tvnow();
03587          while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) {
03588             /* XXX Would be nice to have a way to poll/select here XXX */
03589             /* XXX this is a busy wait loop!!! */
03590             usleep(1);
03591          }
03592          /* Continue on as normal, our cache should kick in */
03593       }
03594    }
03595    /* Create transactions */
03596    do {
03597       order = skipped;
03598       skipped = 0;
03599       foundcache = 0;
03600       build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct);
03601    } while (skipped && !foundcache && !dr.trans);
03602    /* If no TTL, abort and return 0 now after setting TTL expired hint.  Couldn't
03603       do this earlier because we didn't know if we were going to have transactions
03604       or not. */
03605    if (!ttl) {
03606       ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED);
03607       abort_request(&dr);
03608       unregister_request(&dr);
03609       close(dr.pfds[0]);
03610       close(dr.pfds[1]);
03611       return 0;
03612    }
03613       
03614    /* Optimize transactions */
03615    optimize_transactions(&dr, order);
03616    /* Actually perform transactions */
03617    discover_transactions(&dr);
03618    /* Wait for transaction to come back */
03619    start = ast_tvnow();
03620    while(dr.trans && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) {
03621       ms = 100;
03622       ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
03623    }
03624    if (chan && chan->_softhangup)
03625       ast_log(LOG_DEBUG, "Hrm, '%s' hungup before their query for %s@%s finished\n", chan->name, dr.number, dr.dcontext);
03626    cancel_request(&dr);
03627    unregister_request(&dr);
03628    res = dr.respcount;
03629    *expiration = dr.expiration;
03630    close(dr.pfds[0]);
03631    close(dr.pfds[1]);
03632    return res;
03633 }

static int dundi_lookup_local ( struct dundi_result dr,
struct dundi_mapping map,
char *  called_number,
dundi_eid us_eid,
int  anscnt,
struct dundi_hint_metadata hmd 
) [static]

Definition at line 529 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_EMPTY, 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(), cursecret, dr, dundi_cache_time, dundi_eid_to_str(), DUNDI_FLAG_CANMATCH, DUNDI_FLAG_EXISTS, DUNDI_FLAG_IGNOREPAT, DUNDI_FLAG_INTERNAL_NOPARTIAL, DUNDI_FLAG_MATCHMORE, DUNDI_HINT_DONT_ASK, ast_flags::flags, ipaddr, map, pbx_substitute_variables_varshead(), and tech2str().

Referenced by dundi_lookup_thread(), and precache_trans().

00530 {
00531    struct ast_flags flags = {0};
00532    int x;
00533    if (!ast_strlen_zero(map->lcontext)) {
00534       if (ast_exists_extension(NULL, map->lcontext, called_number, 1, NULL))
00535          ast_set_flag(&flags, DUNDI_FLAG_EXISTS);
00536       if (ast_canmatch_extension(NULL, map->lcontext, called_number, 1, NULL))
00537          ast_set_flag(&flags, DUNDI_FLAG_CANMATCH);
00538       if (ast_matchmore_extension(NULL, map->lcontext, called_number, 1, NULL))
00539          ast_set_flag(&flags, DUNDI_FLAG_MATCHMORE);
00540       if (ast_ignore_pattern(map->lcontext, called_number))
00541          ast_set_flag(&flags, DUNDI_FLAG_IGNOREPAT);
00542 
00543       /* Clearly we can't say 'don't ask' anymore if we found anything... */
00544       if (ast_test_flag(&flags, AST_FLAGS_ALL)) 
00545          ast_clear_flag_nonstd(hmd, DUNDI_HINT_DONT_ASK);
00546 
00547       if (map->options & DUNDI_FLAG_INTERNAL_NOPARTIAL) {
00548          /* Skip partial answers */
00549          ast_clear_flag(&flags, DUNDI_FLAG_MATCHMORE|DUNDI_FLAG_CANMATCH);
00550       }
00551       if (ast_test_flag(&flags, AST_FLAGS_ALL)) {
00552          struct varshead headp;
00553          struct ast_var_t *newvariable;
00554          ast_set_flag(&flags, map->options & 0xffff);
00555          ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL);
00556          dr[anscnt].techint = map->tech;
00557          dr[anscnt].weight = map->weight;
00558          dr[anscnt].expiration = dundi_cache_time;
00559          ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech));
00560          dr[anscnt].eid = *us_eid;
00561          dundi_eid_to_str(dr[anscnt].eid_str, sizeof(dr[anscnt].eid_str), &dr[anscnt].eid);
00562          if (ast_test_flag(&flags, DUNDI_FLAG_EXISTS)) {
00563             AST_LIST_HEAD_INIT_NOLOCK(&headp);
00564             newvariable = ast_var_assign("NUMBER", called_number);
00565             AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00566             newvariable = ast_var_assign("EID", dr[anscnt].eid_str);
00567             AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00568             newvariable = ast_var_assign("SECRET", cursecret);
00569             AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00570             newvariable = ast_var_assign("IPADDR", ipaddr);
00571             AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00572             pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest));
00573             while (!AST_LIST_EMPTY(&headp)) {           /* List Deletion. */
00574                newvariable = AST_LIST_REMOVE_HEAD(&headp, entries);
00575                ast_var_delete(newvariable);
00576             }
00577          } else
00578             dr[anscnt].dest[0] = '\0';
00579          anscnt++;
00580       } else {
00581          /* No answers...  Find the fewest number of digits from the
00582             number for which we have no answer. */
00583          char tmp[AST_MAX_EXTENSION];
00584          for (x=0;x<AST_MAX_EXTENSION;x++) {
00585             tmp[x] = called_number[x];
00586             if (!tmp[x])
00587                break;
00588             if (!ast_canmatch_extension(NULL, map->lcontext, tmp, 1, NULL)) {
00589                /* Oops found something we can't match.  If this is longer
00590                   than the running hint, we have to consider it */
00591                if (strlen(tmp) > strlen(hmd->exten)) {
00592                   ast_copy_string(hmd->exten, tmp, sizeof(hmd->exten));
00593                }
00594                break;
00595             }
00596          }
00597       }
00598    }
00599    return anscnt;
00600 }

static void* dundi_lookup_thread ( void *  data  )  [static]

Definition at line 604 of file pbx_dundi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_test_flag_nonstd, dundi_query_state::called_context, dundi_query_state::called_number, destroy_trans(), dundi_query_state::directs, dr, dundi_cache_time, DUNDI_CAUSE_DUPLICATE, DUNDI_COMMAND_DPRESPONSE, dundi_eid_to_str(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, DUNDI_IE_ANSWER, dundi_ie_append_answer(), dundi_ie_append_cause(), dundi_ie_append_hint(), dundi_ie_append_short(), DUNDI_IE_CAUSE, DUNDI_IE_EXPIRATION, DUNDI_IE_HINT, dundi_lookup_internal(), dundi_lookup_local(), dundi_send(), dundi_query_state::eids, FLAG_DEAD, dundi_hint_metadata::flags, free, LOG_DEBUG, dundi_query_state::maps, MAX_RESULTS, dundi_query_state::nocache, dundi_query_state::nummaps, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, and dundi_transaction::us_eid.

Referenced by dundi_answer_query().

00605 {
00606    struct dundi_query_state *st = data;
00607    struct dundi_result dr[MAX_RESULTS];
00608    struct dundi_ie_data ied;
00609    struct dundi_hint_metadata hmd;
00610    char eid_str[20];
00611    int res, x;
00612    int ouranswers=0;
00613    int max = 999999;
00614    int expiration = dundi_cache_time;
00615 
00616    ast_log(LOG_DEBUG, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, 
00617       st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) :  "ourselves");
00618    memset(&ied, 0, sizeof(ied));
00619    memset(&dr, 0, sizeof(dr));
00620    memset(&hmd, 0, sizeof(hmd));
00621    /* Assume 'don't ask for anything' and 'unaffected', no TTL expired */
00622    hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED;
00623    for (x=0;x<st->nummaps;x++)
00624       ouranswers = dundi_lookup_local(dr, st->maps + x, st->called_number, &st->trans->us_eid, ouranswers, &hmd);
00625    if (ouranswers < 0)
00626       ouranswers = 0;
00627    for (x=0;x<ouranswers;x++) {
00628       if (dr[x].weight < max)
00629          max = dr[x].weight;
00630    }
00631       
00632    if (max) {
00633       /* If we do not have a canonical result, keep looking */
00634       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);
00635       if (res > 0) {
00636          /* Append answer in result */
00637          ouranswers += res;
00638       } else {
00639          if ((res < -1) && (!ouranswers))
00640             dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_DUPLICATE, "Duplicate Request Pending");
00641       }
00642    }
00643    ast_mutex_lock(&peerlock);
00644    /* Truncate if "don't ask" isn't present */
00645    if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK))
00646       hmd.exten[0] = '\0';
00647    if (ast_test_flag(st->trans, FLAG_DEAD)) {
00648       ast_log(LOG_DEBUG, "Our transaction went away!\n");
00649       st->trans->thread = 0;
00650       destroy_trans(st->trans, 0);
00651    } else {
00652       for (x=0;x<ouranswers;x++) {
00653          /* Add answers */
00654          if (dr[x].expiration && (expiration > dr[x].expiration))
00655             expiration = dr[x].expiration;
00656          dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
00657       }
00658       dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
00659       dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
00660       dundi_send(st->trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
00661       st->trans->thread = 0;
00662    }
00663    ast_mutex_unlock(&peerlock);
00664    free(st);
00665    return NULL;   
00666 }

static int dundi_matchmore ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 4538 of file pbx_dundi.c.

References DUNDI_FLAG_MATCHMORE, and dundi_helper().

04539 {
04540    return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE);
04541 }

static int dundi_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2211 of file pbx_dundi.c.

References ast_cli(), dundidebug, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02212 {
02213    if (argc != 3)
02214       return RESULT_SHOWUSAGE;
02215    dundidebug = 0;
02216    ast_cli(fd, "DUNDi Debugging Disabled\n");
02217    return RESULT_SUCCESS;
02218 }

static int dundi_no_store_history ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2220 of file pbx_dundi.c.

References ast_cli(), global_storehistory, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02221 {
02222    if (argc != 4)
02223       return RESULT_SHOWUSAGE;
02224    global_storehistory = 0;
02225    ast_cli(fd, "DUNDi History Storage Disabled\n");
02226    return RESULT_SUCCESS;
02227 }

int dundi_precache ( const char *  context,
const char *  number 
)

Pre-cache to push upstream peers.

Definition at line 3793 of file pbx_dundi.c.

References dundi_precache_internal(), and dundi_ttl.

Referenced by dundi_do_precache(), and process_precache().

03794 {
03795    dundi_eid *avoid[1] = { NULL, };
03796    return dundi_precache_internal(context, number, dundi_ttl, avoid);
03797 }

static void dundi_precache_full ( void   )  [static]

Definition at line 3690 of file pbx_dundi.c.

References ast_get_context_name(), ast_get_extension_name(), ast_lock_context(), ast_lock_contexts(), ast_log(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), dundi_mapping::dcontext, dundi_mapping::lcontext, LOG_NOTICE, mappings, dundi_mapping::next, and reschedule_precache().

Referenced by set_config().

03691 {
03692    struct dundi_mapping *cur;
03693    struct ast_context *con;
03694    struct ast_exten *e;
03695    cur = mappings;
03696    while(cur) {
03697       ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext);
03698       ast_lock_contexts();
03699       con = ast_walk_contexts(NULL);
03700       while(con) {
03701          if (!strcasecmp(cur->lcontext, ast_get_context_name(con))) {
03702             /* Found the match, now queue them all up */
03703             ast_lock_context(con);
03704             e = ast_walk_context_extensions(con, NULL);
03705             while(e) {
03706                reschedule_precache(ast_get_extension_name(e), cur->dcontext, 0);
03707                e = ast_walk_context_extensions(con, e);
03708             }
03709             ast_unlock_context(con);
03710          }
03711          con = ast_walk_contexts(con);
03712       }
03713       ast_unlock_contexts();
03714       cur = cur->next;
03715    }
03716 }

static int dundi_precache_internal ( const char *  context,
const char *  number,
int  ttl,
dundi_eid avoids[] 
) [static]

Definition at line 3718 of file pbx_dundi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_waitfor_n_fd(), build_transactions(), cancel_request(), dr, dundi_cache_time, DUNDI_FLUFF_TIME, DUNDI_TTL_TIME, LOG_DEBUG, LOG_NOTICE, mappings, MAX_RESULTS, dundi_mapping::next, optimize_transactions(), precache_transactions(), and reschedule_precache().

Referenced by dundi_precache(), and dundi_precache_thread().

03719 {
03720    struct dundi_request dr;
03721    struct dundi_hint_metadata hmd;
03722    struct dundi_result dr2[MAX_RESULTS];
03723    struct timeval start;
03724    struct dundi_mapping *maps=NULL, *cur;
03725    int nummaps;
03726    int foundanswers;
03727    int foundcache, skipped, ttlms, ms;
03728    if (!context)
03729       context = "e164";
03730    ast_log(LOG_DEBUG, "Precache internal (%s@%s)!\n", number, context);
03731 
03732    ast_mutex_lock(&peerlock);
03733    nummaps = 0;
03734    cur = mappings;
03735    while(cur) {
03736       if (!strcasecmp(cur->dcontext, context))
03737          nummaps++;
03738       cur = cur->next;
03739    }
03740    if (nummaps) {
03741       maps = alloca(nummaps * sizeof(struct dundi_mapping));
03742       nummaps = 0;
03743       if (maps) {
03744          cur = mappings;
03745          while(cur) {
03746             if (!strcasecmp(cur->dcontext, context))
03747                maps[nummaps++] = *cur;
03748             cur = cur->next;
03749          }
03750       }
03751    }
03752    ast_mutex_unlock(&peerlock);
03753    if (!nummaps || !maps)
03754       return -1;
03755    ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
03756    memset(&dr2, 0, sizeof(dr2));
03757    memset(&dr, 0, sizeof(dr));
03758    memset(&hmd, 0, sizeof(hmd));
03759    dr.dr = dr2;
03760    ast_copy_string(dr.number, number, sizeof(dr.number));
03761    ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext));
03762    dr.maxcount = MAX_RESULTS;
03763    dr.expiration = dundi_cache_time;
03764    dr.hmd = &hmd;
03765    dr.pfds[0] = dr.pfds[1] = -1;
03766    pipe(dr.pfds);
03767    build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL);
03768    optimize_transactions(&dr, 0);
03769    foundanswers = 0;
03770    precache_transactions(&dr, maps, nummaps, &dr.expiration, &foundanswers);
03771    if (foundanswers) {
03772       if (dr.expiration > 0) 
03773          reschedule_precache(dr.number, dr.dcontext, dr.expiration);
03774       else
03775          ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext);
03776    }
03777    start = ast_tvnow();
03778    while(dr.trans && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) {
03779       if (dr.pfds[0] > -1) {
03780          ms = 100;
03781          ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
03782       } else
03783          usleep(1);
03784    }
03785    cancel_request(&dr);
03786    if (dr.pfds[0] > -1) {
03787       close(dr.pfds[0]);
03788       close(dr.pfds[1]);
03789    }
03790    return 0;
03791 }

static void* dundi_precache_thread ( void *  data  )  [static]

Definition at line 668 of file pbx_dundi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_test_flag_nonstd, dundi_query_state::called_context, dundi_query_state::called_number, destroy_trans(), DUNDI_COMMAND_PRECACHERP, dundi_eid_to_str(), DUNDI_HINT_DONT_ASK, dundi_precache_internal(), dundi_send(), dundi_query_state::eids, dundi_hint_metadata::exten, FLAG_DEAD, free, LOG_DEBUG, dundi_transaction::thread, dundi_query_state::trans, and dundi_query_state::ttl.

00669 {
00670    struct dundi_query_state *st = data;
00671    struct dundi_ie_data ied;
00672    struct dundi_hint_metadata hmd;
00673    char eid_str[20];
00674 
00675    ast_log(LOG_DEBUG, "Whee, precaching '%s@%s' for '%s'\n", st->called_number, st->called_context, 
00676       st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) :  "ourselves");
00677    memset(&ied, 0, sizeof(ied));
00678 
00679    /* Now produce precache */
00680    dundi_precache_internal(st->called_context, st->called_number, st->ttl, st->eids);
00681 
00682    ast_mutex_lock(&peerlock);
00683    /* Truncate if "don't ask" isn't present */
00684    if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK))
00685       hmd.exten[0] = '\0';
00686    if (ast_test_flag(st->trans, FLAG_DEAD)) {
00687       ast_log(LOG_DEBUG, "Our transaction went away!\n");
00688       st->trans->thread = 0;
00689       destroy_trans(st->trans, 0);
00690    } else {
00691       dundi_send(st->trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
00692       st->trans->thread = 0;
00693    }
00694    ast_mutex_unlock(&peerlock);
00695    free(st);
00696    return NULL;   
00697 }

static int dundi_prop_precache ( struct dundi_transaction trans,
struct dundi_ies ies,
char *  ccontext 
) [static]

Definition at line 890 of file pbx_dundi.c.

References ast_clear_flag_nonstd, dundi_result::dest, dundi_request::dr, dr, dundi_cache_time, dundi_eid_to_str(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, dundi_request::hmd, ies, MAX_RESULTS, dundi_request::maxcount, dundi_transaction::parent, dundi_request::respcount, s, tech2str(), dundi_result::techint, and dundi_result::weight.

Referenced by handle_command_response().

00891 {
00892    struct dundi_query_state *st;
00893    int totallen;
00894    int x,z;
00895    struct dundi_ie_data ied;
00896    char *s;
00897    struct dundi_result dr2[MAX_RESULTS];
00898    struct dundi_request dr;
00899    struct dundi_hint_metadata hmd;
00900 
00901    struct dundi_mapping *cur;
00902    int mapcount;
00903    int skipfirst = 0;
00904    
00905    pthread_t lookupthread;
00906    pthread_attr_t attr;
00907 
00908    memset(&dr2, 0, sizeof(dr2));
00909    memset(&dr, 0, sizeof(dr));
00910    memset(&hmd, 0, sizeof(hmd));
00911    
00912    /* Forge request structure to hold answers for cache */
00913    hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED;
00914    dr.dr = dr2;
00915    dr.maxcount = MAX_RESULTS;
00916    dr.expiration = dundi_cache_time;
00917    dr.hmd = &hmd;
00918    dr.pfds[0] = dr.pfds[1] = -1;
00919    trans->parent = &dr;
00920    ast_copy_string(dr.dcontext, ies->called_context ? ies->called_context : "e164", sizeof(dr.dcontext));
00921    ast_copy_string(dr.number, ies->called_number, sizeof(dr.number));
00922    
00923    for (x=0;x<ies->anscount;x++) {
00924       if (trans->parent->respcount < trans->parent->maxcount) {
00925          /* Make sure it's not already there */
00926          for (z=0;z<trans->parent->respcount;z++) {
00927             if ((trans->parent->dr[z].techint == ies->answers[x]->protocol) &&
00928                 !strcmp(trans->parent->dr[z].dest, (char *)ies->answers[x]->data)) 
00929                   break;
00930          }
00931          if (z == trans->parent->respcount) {
00932             /* Copy into parent responses */
00933             trans->parent->dr[trans->parent->respcount].flags = ntohs(ies->answers[x]->flags);
00934             trans->parent->dr[trans->parent->respcount].techint = ies->answers[x]->protocol;
00935             trans->parent->dr[trans->parent->respcount].weight = ntohs(ies->answers[x]->weight);
00936             trans->parent->dr[trans->parent->respcount].eid = ies->answers[x]->eid;
00937             if (ies->expiration > 0)
00938                trans->parent->dr[trans->parent->respcount].expiration = ies->expiration;
00939             else
00940                trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time;
00941             dundi_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, 
00942                sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
00943                &ies->answers[x]->eid);
00944             ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies->answers[x]->data,
00945                sizeof(trans->parent->dr[trans->parent->respcount].dest));
00946                ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies->answers[x]->protocol),
00947                sizeof(trans->parent->dr[trans->parent->respcount].tech));
00948             trans->parent->respcount++;
00949             ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK);   
00950          } else if (trans->parent->dr[z].weight > ies->answers[x]->weight) {
00951             /* Update weight if appropriate */
00952             trans->parent->dr[z].weight = ies->answers[x]->weight;
00953          }
00954       } else
00955          ast_log(LOG_NOTICE, "Dropping excessive answers in precache for %s@%s\n",
00956             trans->parent->number, trans->parent->dcontext);
00957 
00958    }
00959    /* Save all the results (if any) we had.  Even if no results, still cache lookup. */
00960    cache_save(&trans->them_eid, trans->parent, 0, 0, ies->expiration, 1);
00961    if (ies->hint)
00962       cache_save_hint(&trans->them_eid, trans->parent, ies->hint, ies->expiration);
00963 
00964    totallen = sizeof(struct dundi_query_state);
00965    /* Count matching map entries */
00966    mapcount = 0;
00967    cur = mappings;
00968    while(cur) {
00969       if (!strcasecmp(cur->dcontext, ccontext))
00970          mapcount++;
00971       cur = cur->next;
00972    }
00973    
00974    /* If no maps, return -1 immediately */
00975    if (!mapcount)
00976       return -1;
00977 
00978    if (ies->eidcount > 1) {
00979       /* Since it is a requirement that the first EID is the authenticating host
00980          and the last EID is the root, it is permissible that the first and last EID
00981          could be the same.  In that case, we should go ahead copy only the "root" section
00982          since we will not need it for authentication. */
00983       if (!dundi_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
00984          skipfirst = 1;
00985    }
00986 
00987    /* Prepare to run a query and then propagate that as necessary */
00988    totallen += mapcount * sizeof(struct dundi_mapping);
00989    totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
00990    st = malloc(totallen);
00991    if (st) {
00992       memset(st, 0, totallen);
00993       ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context));
00994       ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
00995       st->trans = trans;
00996       st->ttl = ies->ttl - 1;
00997       st->nocache = ies->cbypass;
00998       if (st->ttl < 0)
00999          st->ttl = 0;
01000       s = st->fluffy;
01001       for (x=skipfirst;ies->eids[x];x++) {
01002          st->eids[x-skipfirst] = (dundi_eid *)s;
01003          *st->eids[x-skipfirst] = *ies->eids[x];
01004          st->directs[x-skipfirst] = ies->eid_direct[x];
01005          s += sizeof(dundi_eid);
01006       }
01007       /* Append mappings */
01008       x = 0;
01009       st->maps = (struct dundi_mapping *)s;
01010       cur = mappings;
01011       while(cur) {
01012          if (!strcasecmp(cur->dcontext, ccontext)) {
01013             if (x < mapcount) {
01014                st->maps[x] = *cur;
01015                st->maps[x].next = NULL;
01016                x++;
01017             }
01018          }
01019          cur = cur->next;
01020       }
01021       st->nummaps = mapcount;
01022       ast_log(LOG_DEBUG, "Forwarding precache for '%s@%s'!\n", ies->called_number, ies->called_context);
01023       pthread_attr_init(&attr);
01024       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01025       trans->thread = 1;
01026       if (ast_pthread_create(&lookupthread, &attr, dundi_precache_thread, st)) {
01027          trans->thread = 0;
01028          ast_log(LOG_WARNING, "Unable to create thread!\n");
01029          free(st);
01030          memset(&ied, 0, sizeof(ied));
01031          dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
01032          dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
01033          return -1;
01034       }
01035    } else {
01036       ast_log(LOG_WARNING, "Out of memory!\n");
01037       memset(&ied, 0, sizeof(ied));
01038       dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
01039       dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
01040       return -1;
01041    }
01042    return 0;
01043 }

static int dundi_query ( struct dundi_transaction trans  )  [static]

Definition at line 3190 of file pbx_dundi.c.

References ast_log(), ast_sched_add(), dundi_transaction::autokillid, dundi_transaction::autokilltimeout, dundi_request::dcontext, do_autokill(), DUNDI_COMMAND_EIDQUERY, DUNDI_DEFAULT_VERSION, dundi_eid_zero(), dundi_ie_append_eid(), dundi_ie_append_short(), dundi_ie_append_str(), DUNDI_IE_CALLED_CONTEXT, DUNDI_IE_EID, DUNDI_IE_REQEID, DUNDI_IE_TTL, DUNDI_IE_VERSION, dundi_send(), dundi_transaction::eidcount, dundi_transaction::eids, LOG_WARNING, dundi_transaction::parent, dundi_request::query_eid, dundi_transaction::ttl, and dundi_transaction::us_eid.

Referenced by query_transactions().

03191 {
03192    struct dundi_ie_data ied;
03193    int x;
03194    if (!trans->parent) {
03195       ast_log(LOG_WARNING, "Tried to query a transaction with no parent?!?\n");
03196       return -1;
03197    }
03198    memset(&ied, 0, sizeof(ied));
03199    dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
03200    if (!dundi_eid_zero(&trans->us_eid))
03201       dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
03202    for (x=0;x<trans->eidcount;x++)
03203       dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
03204    dundi_ie_append_eid(&ied, DUNDI_IE_REQEID, &trans->parent->query_eid);
03205    dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext);
03206    dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
03207    if (trans->autokilltimeout)
03208       trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
03209    return dundi_send(trans, DUNDI_COMMAND_EIDQUERY, 0, 0, &ied);
03210 }

int dundi_query_eid ( struct dundi_entity_info dei,
const char *  dcontext,
dundi_eid  eid 
)

Retrieve information on a specific EID.

Definition at line 3846 of file pbx_dundi.c.

References dundi_query_eid_internal(), and dundi_ttl.

Referenced by dundi_do_query().

03847 {
03848    dundi_eid *avoid[1] = { NULL, };
03849    struct dundi_hint_metadata hmd;
03850    memset(&hmd, 0, sizeof(hmd));
03851    return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid);
03852 }

static int dundi_query_eid_internal ( struct dundi_entity_info dei,
const char *  dcontext,
dundi_eid eid,
struct dundi_hint_metadata hmd,
int  ttl,
int  blockempty,
dundi_eid avoid[] 
) [static]

Definition at line 3799 of file pbx_dundi.c.

References ast_set_flag_nonstd, build_transactions(), dr, DUNDI_FLUFF_TIME, DUNDI_HINT_TTL_EXPIRED, DUNDI_TTL_TIME, optimize_transactions(), and query_transactions().

Referenced by dundi_query_eid(), and dundi_query_thread().

03800 {
03801    int res;
03802    struct dundi_request dr;
03803    dundi_eid *rooteid=NULL;
03804    int x;
03805    int ttlms;
03806    int skipped=0;
03807    int foundcache=0;
03808    struct timeval start;
03809    
03810    ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
03811 
03812    for (x=0;avoid[x];x++)
03813       rooteid = avoid[x];
03814    /* Now perform real check */
03815    memset(&dr, 0, sizeof(dr));
03816    dr.hmd = hmd;
03817    dr.dei = dei;
03818    dr.pfds[0] = dr.pfds[1] = -1;
03819    ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
03820    memcpy(&dr.query_eid, eid, sizeof(dr.query_eid));
03821    if (rooteid)
03822       dr.root_eid = *rooteid;
03823    /* Create transactions */
03824    build_transactions(&dr, ttl, 9999, &foundcache, &skipped, blockempty, 0, 0, NULL, avoid, NULL);
03825 
03826    /* If no TTL, abort and return 0 now after setting TTL expired hint.  Couldn't
03827       do this earlier because we didn't know if we were going to have transactions
03828       or not. */
03829    if (!ttl) {
03830       ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED);
03831       return 0;
03832    }
03833       
03834    /* Optimize transactions */
03835    optimize_transactions(&dr, 9999);
03836    /* Actually perform transactions */
03837    query_transactions(&dr);
03838    /* Wait for transaction to come back */
03839    start = ast_tvnow();
03840    while(dr.trans && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms))
03841       usleep(1);
03842    res = dr.respcount;
03843    return res;
03844 }

static void* dundi_query_thread ( void *  data  )  [static]

Definition at line 701 of file pbx_dundi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_test_flag, dundi_query_state::called_context, dundi_query_state::called_number, country, dept, destroy_trans(), DUNDI_COMMAND_EIDRESPONSE, dundi_eid_cmp(), dundi_eid_to_str(), dundi_ie_append_hint(), dundi_ie_append_str(), DUNDI_IE_COUNTRY, DUNDI_IE_DEPARTMENT, DUNDI_IE_EMAIL, DUNDI_IE_HINT, DUNDI_IE_IPADDR, DUNDI_IE_LOCALITY, DUNDI_IE_ORGANIZATION, DUNDI_IE_PHONE, DUNDI_IE_STATE_PROV, dundi_query_eid_internal(), dundi_send(), dundi_query_state::eids, email, FLAG_DEAD, free, locality, LOG_DEBUG, org, phone, dundi_query_state::reqeid, stateprov, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, and dundi_transaction::us_eid.

Referenced by dundi_answer_entity().

00702 {
00703    struct dundi_query_state *st = data;
00704    struct dundi_entity_info dei;
00705    struct dundi_ie_data ied;
00706    struct dundi_hint_metadata hmd;
00707    char eid_str[20];
00708    int res;
00709    ast_log(LOG_DEBUG, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, 
00710       st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) :  "ourselves");
00711    memset(&ied, 0, sizeof(ied));
00712    memset(&dei, 0, sizeof(dei));
00713    memset(&hmd, 0, sizeof(hmd));
00714    if (!dundi_eid_cmp(&st->trans->us_eid, &st->reqeid)) {
00715       /* Ooh, it's us! */
00716       ast_log(LOG_DEBUG, "Neat, someone look for us!\n");
00717       ast_copy_string(dei.orgunit, dept, sizeof(dei.orgunit));
00718       ast_copy_string(dei.org, org, sizeof(dei.org));
00719       ast_copy_string(dei.locality, locality, sizeof(dei.locality));
00720       ast_copy_string(dei.stateprov, stateprov, sizeof(dei.stateprov));
00721       ast_copy_string(dei.country, country, sizeof(dei.country));
00722       ast_copy_string(dei.email, email, sizeof(dei.email));
00723       ast_copy_string(dei.phone, phone, sizeof(dei.phone));
00724       res = 1;
00725    } else {
00726       /* If we do not have a canonical result, keep looking */
00727       res = dundi_query_eid_internal(&dei, st->called_context, &st->reqeid, &hmd, st->ttl, 1, st->eids);
00728    }
00729    ast_mutex_lock(&peerlock);
00730    if (ast_test_flag(st->trans, FLAG_DEAD)) {
00731       ast_log(LOG_DEBUG, "Our transaction went away!\n");
00732       st->trans->thread = 0;
00733       destroy_trans(st->trans, 0);
00734    } else {
00735       if (res) {
00736          dundi_ie_append_str(&ied, DUNDI_IE_DEPARTMENT, dei.orgunit);
00737          dundi_ie_append_str(&ied, DUNDI_IE_ORGANIZATION, dei.org);
00738          dundi_ie_append_str(&ied, DUNDI_IE_LOCALITY, dei.locality);
00739          dundi_ie_append_str(&ied, DUNDI_IE_STATE_PROV, dei.stateprov);
00740          dundi_ie_append_str(&ied, DUNDI_IE_COUNTRY, dei.country);
00741          dundi_ie_append_str(&ied, DUNDI_IE_EMAIL, dei.email);
00742          dundi_ie_append_str(&ied, DUNDI_IE_PHONE, dei.phone);
00743          if (!ast_strlen_zero(dei.ipaddr))
00744             dundi_ie_append_str(&ied, DUNDI_IE_IPADDR, dei.ipaddr);
00745       }
00746       dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
00747       dundi_send(st->trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
00748       st->trans->thread = 0;
00749    }
00750    ast_mutex_unlock(&peerlock);
00751    free(st);
00752    return NULL;   
00753 }

static void dundi_reject ( struct dundi_hdr h,
struct sockaddr_in *  sin 
) [static]

Definition at line 382 of file pbx_dundi.c.

References dundi_hdr::cmdresp, dundi_hdr::dtrans, DUNDI_COMMAND_INVALID, dundi_xmit(), dundi_hdr::iseqno, dundi_hdr::oseqno, and dundi_hdr::strans.

Referenced by handle_frame().

00383 {
00384    struct {
00385       struct dundi_packet pack;
00386       struct dundi_hdr hdr;
00387    } tmp;
00388    struct dundi_transaction trans;
00389    /* Never respond to an INVALID with another INVALID */
00390    if (h->cmdresp == DUNDI_COMMAND_INVALID)
00391       return;
00392    memset(&tmp, 0, sizeof(tmp));
00393    memset(&trans, 0, sizeof(trans));
00394    memcpy(&trans.addr, sin, sizeof(trans.addr));
00395    tmp.hdr.strans = h->dtrans;
00396    tmp.hdr.dtrans = h->strans;
00397    tmp.hdr.iseqno = h->oseqno;
00398    tmp.hdr.oseqno = h->iseqno;
00399    tmp.hdr.cmdresp = DUNDI_COMMAND_INVALID;
00400    tmp.hdr.cmdflags = 0;
00401    tmp.pack.h = (struct dundi_hdr *)tmp.pack.data;
00402    tmp.pack.datalen = sizeof(struct dundi_hdr);
00403    tmp.pack.parent = &trans;
00404    dundi_xmit(&tmp.pack);
00405 }

static int dundi_rexmit ( void *  data  )  [static]

Definition at line 2967 of file pbx_dundi.c.

References dundi_transaction::addr, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, destroy_trans(), dundi_xmit(), FLAG_ISQUAL, dundi_packet::h, LOG_NOTICE, dundi_hdr::oseqno, dundi_packet::parent, dundi_packet::retrans, dundi_packet::retransid, and dundi_hdr::strans.

Referenced by dundi_send().

02968 {
02969    struct dundi_packet *pack;
02970    char iabuf[INET_ADDRSTRLEN];
02971    int res;
02972    ast_mutex_lock(&peerlock);
02973    pack = data;
02974    if (pack->retrans < 1) {
02975       pack->retransid = -1;
02976       if (!ast_test_flag(pack->parent, FLAG_ISQUAL))
02977          ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n", 
02978             ast_inet_ntoa(iabuf, sizeof(iabuf), pack->parent->addr.sin_addr), 
02979             ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans));
02980       destroy_trans(pack->parent, 1);
02981       res = 0;
02982    } else {
02983       /* Decrement retransmission, try again */
02984       pack->retrans--;
02985       dundi_xmit(pack);
02986       res = 1;
02987    }
02988    ast_mutex_unlock(&peerlock);
02989    return res;
02990 }

static int dundi_send ( struct dundi_transaction trans,
int  cmdresp,
int  flags,
int  final,
struct dundi_ie_data ied 
) [static]

Definition at line 2992 of file pbx_dundi.c.

References dundi_transaction::addr, dundi_transaction::aseqno, ast_log(), ast_sched_add(), ast_set_flag, ast_test_flag, dundi_hdr::cmdflags, dundi_hdr::cmdresp, dundi_packet::data, dundi_packet::datalen, dundi_transaction::dtrans, dundi_hdr::dtrans, DUNDI_COMMAND_ACK, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_DPRESPONSE, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_EIDRESPONSE, DUNDI_COMMAND_FINAL, DUNDI_COMMAND_PRECACHERP, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, DUNDI_COMMAND_REGRESPONSE, DUNDI_DEFAULT_RETRANS, dundi_eid_to_str(), dundi_encrypt(), dundi_rexmit(), dundi_showframe(), dundi_xmit(), dundidebug, FLAG_ENCRYPT, FLAG_FINAL, free, dundi_packet::h, dundi_hdr::ies, dundi_transaction::iseqno, dundi_hdr::iseqno, LOG_NOTICE, malloc, dundi_packet::next, dundi_transaction::oseqno, dundi_hdr::oseqno, dundi_transaction::packets, dundi_packet::parent, dundi_packet::retrans, dundi_packet::retransid, dundi_transaction::retranstimer, dundi_transaction::strans, dundi_hdr::strans, and dundi_transaction::them_eid.

Referenced by cancel_request(), do_register(), dundi_ack(), dundi_answer_entity(), dundi_answer_query(), dundi_discover(), dundi_lookup_thread(), dundi_precache_thread(), dundi_query(), dundi_query_thread(), handle_command_response(), precache_trans(), and qualify_peer().

02993 {
02994    struct dundi_packet *pack;
02995    int res;
02996    int len;
02997    char eid_str[20];
02998    len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0);
02999    /* Reserve enough space for encryption */
03000    if (ast_test_flag(trans, FLAG_ENCRYPT))
03001       len += 384;
03002    pack = malloc(len);
03003    if (pack) {
03004       memset(pack, 0, len);
03005       pack->h = (struct dundi_hdr *)(pack->data);
03006       if (cmdresp != DUNDI_COMMAND_ACK) {
03007          pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack);
03008          pack->retrans = DUNDI_DEFAULT_RETRANS - 1;
03009          pack->next = trans->packets;
03010          trans->packets = pack;
03011       }
03012       pack->parent = trans;
03013       pack->h->strans = htons(trans->strans);
03014       pack->h->dtrans = htons(trans->dtrans);
03015       pack->h->iseqno = trans->iseqno;
03016       pack->h->oseqno = trans->oseqno;
03017       pack->h->cmdresp = cmdresp;
03018       pack->datalen = sizeof(struct dundi_hdr);
03019       if (ied) {
03020          memcpy(pack->h->ies, ied->buf, ied->pos);
03021          pack->datalen += ied->pos;
03022       } 
03023       if (final) {
03024          pack->h->cmdresp |= DUNDI_COMMAND_FINAL;
03025          ast_set_flag(trans, FLAG_FINAL);
03026       }
03027       pack->h->cmdflags = flags;
03028       if (cmdresp != DUNDI_COMMAND_ACK) {
03029          trans->oseqno++;
03030          trans->oseqno = trans->oseqno % 256;
03031       }
03032       trans->aseqno = trans->iseqno;
03033       /* If we have their public key, encrypt */
03034       if (ast_test_flag(trans, FLAG_ENCRYPT)) {
03035          switch(cmdresp) {
03036          case DUNDI_COMMAND_REGREQ:
03037          case DUNDI_COMMAND_REGRESPONSE:
03038          case DUNDI_COMMAND_DPDISCOVER:
03039          case DUNDI_COMMAND_DPRESPONSE:
03040          case DUNDI_COMMAND_EIDQUERY:
03041          case DUNDI_COMMAND_EIDRESPONSE:
03042          case DUNDI_COMMAND_PRECACHERQ:
03043          case DUNDI_COMMAND_PRECACHERP:
03044             if (dundidebug)
03045                dundi_showframe(pack->h, 2, &trans->addr, pack->datalen - sizeof(struct dundi_hdr));
03046             res = dundi_encrypt(trans, pack);
03047             break;
03048          default:
03049             res = 0;
03050          }
03051       } else 
03052          res = 0;
03053       if (!res) 
03054          res = dundi_xmit(pack);
03055       if (res)
03056          ast_log(LOG_NOTICE, "Failed to send packet to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
03057             
03058       if (cmdresp == DUNDI_COMMAND_ACK)
03059          free(pack);
03060       return res;
03061    }
03062    return -1;
03063 }

static int dundi_show_entityid ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2575 of file pbx_dundi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dundi_eid_to_str(), global_eid, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02576 {
02577    char eid_str[20];
02578    if (argc != 3)
02579       return RESULT_SHOWUSAGE;
02580    ast_mutex_lock(&peerlock);
02581    dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid);
02582    ast_mutex_unlock(&peerlock);
02583    ast_cli(fd, "Global EID for this system is '%s'\n", eid_str);
02584    return RESULT_SUCCESS;
02585 }

static int dundi_show_mappings ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2609 of file pbx_dundi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dundi_flags2str(), FORMAT, FORMAT2, map, mappings, RESULT_SHOWUSAGE, RESULT_SUCCESS, and tech2str().

02610 {
02611 #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
02612 #define FORMAT "%-12.12s %-7d %-12.12s %-10.10s %-5.5s %-25.25s\n"
02613    struct dundi_mapping *map;
02614    char fs[256];
02615    if (argc != 3)
02616       return RESULT_SHOWUSAGE;
02617    ast_mutex_lock(&peerlock);
02618    ast_cli(fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination");
02619    for (map = mappings;map;map = map->next) {
02620          ast_cli(fd, FORMAT, map->dcontext, map->weight, 
02621                              ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext, 
02622                         dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest);
02623    }
02624    ast_mutex_unlock(&peerlock);
02625    return RESULT_SUCCESS;
02626 #undef FORMAT
02627 #undef FORMAT2
02628 }

static int dundi_show_peer ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2394 of file pbx_dundi.c.

References dundi_peer::addr, permission::allow, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), ast_strlen_zero(), dundi_peer::avgms, dundi_eid_to_str(), DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, DUNDI_TIMING_HISTORY, dundi_peer::dynamic, dundi_peer::eid, dundi_peer::include, dundi_peer::inkey, dundi_peer::keypending, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::model, model2str(), permission::name, permission::next, dundi_peer::next, dundi_peer::order, dundi_peer::outkey, peers, dundi_peer::permit, dundi_peer::registerid, and RESULT_SHOWUSAGE.

02395 {
02396    struct dundi_peer *peer;
02397    struct permission *p;
02398    char *order;
02399    char iabuf[INET_ADDRSTRLEN];
02400    char eid_str[20];
02401    int x, cnt;
02402    
02403    if (argc != 4)
02404       return RESULT_SHOWUSAGE;
02405    ast_mutex_lock(&peerlock);
02406    peer = peers;
02407    while(peer) {
02408       if (!strcasecmp(dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), argv[3]))
02409          break;
02410       peer = peer->next;
02411    }
02412    if (peer) {
02413       switch(peer->order) {
02414       case 0:
02415          order = "Primary";
02416          break;
02417       case 1:
02418          order = "Secondary";
02419          break;
02420       case 2:
02421          order = "Tertiary";
02422          break;
02423       case 3:
02424          order = "Quartiary";
02425          break;
02426       default:
02427          order = "Unknown";
02428       }
02429       ast_cli(fd, "Peer:    %s\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
02430       ast_cli(fd, "Model:   %s\n", model2str(peer->model));
02431       ast_cli(fd, "Host:    %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "<Unspecified>");
02432       ast_cli(fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
02433       ast_cli(fd, "KeyPend: %s\n", peer->keypending ? "yes" : "no");
02434       ast_cli(fd, "Reg:     %s\n", peer->registerid < 0 ? "No" : "Yes");
02435       ast_cli(fd, "In Key:  %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
02436       ast_cli(fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey);
02437       if (peer->include) {
02438          ast_cli(fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)");
02439       }
02440       p = peer->include;
02441       while(p) {
02442          ast_cli(fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name);
02443          p = p->next;
02444       }
02445       if (peer->permit) {
02446          ast_cli(fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)");
02447       }
02448       p = peer->permit;
02449       while(p) {
02450          ast_cli(fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name);
02451          p = p->next;
02452       }
02453       cnt = 0;
02454       for (x=0;x<DUNDI_TIMING_HISTORY;x++) {
02455          if (peer->lookups[x]) {
02456             if (!cnt)
02457                ast_cli(fd, "Last few query times:\n");
02458             ast_cli(fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]);
02459             cnt++;
02460          }
02461       }
02462       if (cnt)
02463          ast_cli(fd, "Average query time: %d ms\n", peer->avgms);
02464    } else
02465       ast_cli(fd, "No such peer '%s'\n", argv[3]);
02466    ast_mutex_unlock(&peerlock);
02467    return RESULT_SUCCESS;
02468 }

static int dundi_show_peers ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2470 of file pbx_dundi.c.

References dundi_peer::addr, ast_cli(), ast_mutex_lock(), dundi_peer::avgms, FORMAT2, dundi_peer::lastms, dundi_peer::maxms, dundi_peer::next, peers, and RESULT_SHOWUSAGE.

02471 {
02472 #define FORMAT2 "%-20.20s %-15.15s     %-10.10s %-8.8s %-15.15s\n"
02473 #define FORMAT "%-20.20s %-15.15s %s %-10.10s %-8.8s %-15.15s\n"
02474    struct dundi_peer *peer;
02475    char iabuf[INET_ADDRSTRLEN];
02476    int registeredonly=0;
02477    char avgms[20];
02478    char eid_str[20];
02479    int online_peers = 0;
02480    int offline_peers = 0;
02481    int unmonitored_peers = 0;
02482    int total_peers = 0;
02483 
02484    if ((argc != 3) && (argc != 4) && (argc != 5))
02485       return RESULT_SHOWUSAGE;
02486    if ((argc == 4)) {
02487       if (!strcasecmp(argv[3], "registered")) {
02488          registeredonly = 1;
02489       } else
02490          return RESULT_SHOWUSAGE;
02491    }
02492    ast_mutex_lock(&peerlock);
02493    ast_cli(fd, FORMAT2, "EID", "Host", "Model", "AvgTime", "Status");
02494    for (peer = peers;peer;peer = peer->next) {
02495       char status[20];
02496       int print_line = -1;
02497       char srch[2000];
02498       total_peers++;
02499       if (registeredonly && !peer->addr.sin_addr.s_addr)
02500          continue;
02501       if (peer->maxms) {
02502          if (peer->lastms < 0) {
02503             strcpy(status, "UNREACHABLE");
02504             offline_peers++;
02505          }
02506          else if (peer->lastms > peer->maxms) {
02507             snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms);
02508             offline_peers++;
02509          }
02510          else if (peer->lastms) {
02511             snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms);
02512             online_peers++;
02513          }
02514          else {
02515             strcpy(status, "UNKNOWN");
02516             offline_peers++;
02517          }
02518       } else {
02519          strcpy(status, "Unmonitored");
02520          unmonitored_peers++;
02521       }
02522       if (peer->avgms) 
02523          snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms);
02524       else
02525          strcpy(avgms, "Unavail");
02526       snprintf(srch, sizeof(srch), FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
02527                peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
02528                peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
02529 
02530                 if (argc == 5) {
02531                   if (!strcasecmp(argv[3],"include") && strstr(srch,argv[4])) {
02532                         print_line = -1;
02533                    } else if (!strcasecmp(argv[3],"exclude") && !strstr(srch,argv[4])) {
02534                         print_line = 1;
02535                    } else if (!strcasecmp(argv[3],"begin") && !strncasecmp(srch,argv[4],strlen(argv[4]))) {
02536                         print_line = -1;
02537                    } else {
02538                         print_line = 0;
02539                   }
02540                 }
02541       
02542         if (print_line) {
02543          ast_cli(fd, FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
02544                peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
02545                peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
02546       }
02547    }
02548    ast_cli(fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
02549    ast_mutex_unlock(&peerlock);
02550    return RESULT_SUCCESS;
02551 #undef FORMAT
02552 #undef FORMAT2
02553 }

static int dundi_show_precache ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2630 of file pbx_dundi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dundi_precache_queue::context, dundi_precache_queue::expiration, FORMAT, FORMAT2, dundi_precache_queue::next, dundi_precache_queue::number, pcq, RESULT_SHOWUSAGE, RESULT_SUCCESS, and s.

02631 {
02632 #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n"
02633 #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n"
02634    struct dundi_precache_queue *qe;
02635    int h,m,s;
02636    time_t now;
02637    
02638    if (argc != 3)
02639       return RESULT_SHOWUSAGE;
02640    time(&now);
02641    ast_mutex_lock(&pclock);
02642    ast_cli(fd, FORMAT2, "Number", "Context", "Expiration");
02643    for (qe = pcq;qe;qe = qe->next) {
02644       s = qe->expiration - now;
02645       h = s / 3600;
02646       s = s % 3600;
02647       m = s / 60;
02648       s = s % 60;
02649       ast_cli(fd, FORMAT, qe->number, qe->context, h,m,s);
02650    }
02651    ast_mutex_unlock(&pclock);
02652    return RESULT_SUCCESS;
02653 #undef FORMAT
02654 #undef FORMAT2
02655 }

static int dundi_show_requests ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2587 of file pbx_dundi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dundi_request::dcontext, dundi_eid_to_str(), dundi_eid_zero(), FORMAT, FORMAT2, dundi_request::maxcount, dundi_request::next, dundi_request::number, requests, dundi_request::respcount, RESULT_SHOWUSAGE, RESULT_SUCCESS, and dundi_request::root_eid.

02588 {
02589 #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n"
02590 #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n"
02591    struct dundi_request *req;
02592    char eidstr[20];
02593    if (argc != 3)
02594       return RESULT_SHOWUSAGE;
02595    ast_mutex_lock(&peerlock);
02596    ast_cli(fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp");
02597    for (req = requests;req;req = req->next) {
02598          ast_cli(fd, FORMAT, req->number, req->dcontext,
02599                   dundi_eid_zero(&req->root_eid) ? "<unspecified>" : dundi_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount);
02600    }
02601    ast_mutex_unlock(&peerlock);
02602    return RESULT_SUCCESS;
02603 #undef FORMAT
02604 #undef FORMAT2
02605 }

static int dundi_show_trans ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2555 of file pbx_dundi.c.

References dundi_transaction::addr, dundi_transaction::allnext, alltrans, dundi_transaction::aseqno, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), dundi_transaction::dtrans, FORMAT, FORMAT2, dundi_transaction::iseqno, dundi_transaction::oseqno, RESULT_SHOWUSAGE, RESULT_SUCCESS, and dundi_transaction::strans.

02556 {
02557 #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
02558 #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
02559    struct dundi_transaction *trans;
02560    char iabuf[INET_ADDRSTRLEN];
02561    if (argc != 3)
02562       return RESULT_SHOWUSAGE;
02563    ast_mutex_lock(&peerlock);
02564    ast_cli(fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
02565    for (trans = alltrans;trans;trans = trans->allnext) {
02566          ast_cli(fd, FORMAT, ast_inet_ntoa(iabuf, sizeof(iabuf), trans->addr.sin_addr), 
02567                ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
02568    }
02569    ast_mutex_unlock(&peerlock);
02570    return RESULT_SUCCESS;
02571 #undef FORMAT
02572 #undef FORMAT2
02573 }

static int dundi_xmit ( struct dundi_packet pack  )  [static]

Definition at line 2808 of file pbx_dundi.c.

References dundi_transaction::addr, ast_inet_ntoa(), ast_log(), dundi_packet::data, dundi_packet::datalen, dundi_showframe(), dundidebug, dundi_packet::h, LOG_WARNING, netsocket, and dundi_packet::parent.

Referenced by dundi_reject(), dundi_rexmit(), and dundi_send().

02809 {
02810    int res;
02811    char iabuf[INET_ADDRSTRLEN];
02812    if (dundidebug)
02813       dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));
02814    res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr));
02815    if (res < 0) {
02816       ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n", 
02817          ast_inet_ntoa(iabuf, sizeof(iabuf), pack->parent->addr.sin_addr),
02818          ntohs(pack->parent->addr.sin_port), strerror(errno));
02819    }
02820    if (res > 0)
02821       res = 0;
02822    return res;
02823 }

static char* dundifunc_read ( struct ast_channel chan,
char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 3923 of file pbx_dundi.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, context, dundi_result::dest, dr, DUNDI_FLAG_EXISTS, dundi_lookup(), LOCAL_USER_ACF_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_WARNING, MAX_RESULTS, sort_results(), and dundi_result::tech.

03924 {
03925    char *num;
03926    char *context;
03927    char *opts;
03928    int results;
03929    int x;
03930    int bypass = 0;
03931    struct localuser *u;
03932    struct dundi_result dr[MAX_RESULTS];
03933 
03934    LOCAL_USER_ACF_ADD(u);
03935 
03936    buf[0] = '\0';
03937 
03938    if (ast_strlen_zero(data)) {
03939       ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n");
03940       LOCAL_USER_REMOVE(u);
03941       return buf;
03942    }
03943 
03944    num = ast_strdupa(data);
03945    if (!num) {
03946       ast_log(LOG_ERROR, "Out of memory!\n");
03947       LOCAL_USER_REMOVE(u);
03948       return buf;
03949    }
03950 
03951    context = strchr(num, '|');
03952    if (context) {
03953       *context = '\0';
03954       context++;
03955       opts = strchr(context, '|');
03956       if (opts) {
03957          *opts = '\0';
03958          opts++;
03959          if (strchr(opts, 'b'))
03960             bypass = 1;
03961       }
03962    }
03963 
03964    if (ast_strlen_zero(context))
03965       context = "e164";
03966    
03967    results = dundi_lookup(dr, MAX_RESULTS, NULL, context, num, bypass);
03968    if (results > 0) {
03969       sort_results(dr, results);
03970       for (x = 0; x < results; x++) {
03971          if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) {
03972             snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest);
03973             break;
03974          }
03975       }
03976    }
03977 
03978    LOCAL_USER_REMOVE(u);
03979 
03980    return buf;
03981 }

static int encrypt_memcpy ( unsigned char *  dst,
unsigned char *  src,
int  len,
unsigned char *  iv,
aes_encrypt_ctx ecx 
) [static]

Definition at line 1336 of file pbx_dundi.c.

References aes_encrypt().

Referenced by dundi_encrypt().

01337 {
01338    unsigned char curblock[16];
01339    int x;
01340    memcpy(curblock, iv, sizeof(curblock));
01341    while(len > 0) {
01342       for (x=0;x<16;x++)
01343          curblock[x] ^= src[x];
01344       aes_encrypt(curblock, dst, ecx);
01345       memcpy(curblock, dst, sizeof(curblock)); 
01346       dst += 16;
01347       src += 16;
01348       len -= 16;
01349    }
01350    return 0;
01351 }

static struct dundi_peer* find_peer ( dundi_eid eid  )  [static]

Definition at line 489 of file pbx_dundi.c.

References dundi_eid_cmp(), dundi_peer::eid, empty_eid, dundi_peer::next, and peers.

00490 {
00491    struct dundi_peer *cur;
00492    if (!eid)
00493       eid = &empty_eid;
00494    cur = peers;
00495    while(cur) {
00496       if (!dundi_eid_cmp(&cur->eid,eid))
00497          return cur;
00498       cur = cur->next;
00499    }
00500    return NULL;
00501 }

static struct dundi_transaction* find_transaction ( struct dundi_hdr hdr,
struct sockaddr_in *  sin 
) [static]

Definition at line 336 of file pbx_dundi.c.

References dundi_transaction::addr, dundi_transaction::allnext, alltrans, ast_log(), dundi_hdr::cmdresp, create_transaction(), dundi_transaction::dtrans, dundi_hdr::dtrans, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_ENCRYPT, DUNDI_COMMAND_NULL, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, inaddrcmp(), LOG_WARNING, dundi_hdr::strans, and dundi_transaction::strans.

Referenced by handle_frame().

00337 {
00338    /* Look for an exact match first */
00339    struct dundi_transaction *trans;
00340    trans = alltrans;
00341    while(trans) {
00342       if (!inaddrcmp(&trans->addr, sin) && 
00343            ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ ||
00344            ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) {
00345            if (hdr->strans)
00346               trans->dtrans = ntohs(hdr->strans) & 32767;
00347            break;
00348       }
00349       trans = trans->allnext;
00350    }
00351    if (!trans) {
00352       switch(hdr->cmdresp & 0x7f) {
00353       case DUNDI_COMMAND_DPDISCOVER:
00354       case DUNDI_COMMAND_EIDQUERY:
00355       case DUNDI_COMMAND_PRECACHERQ:
00356       case DUNDI_COMMAND_REGREQ:
00357       case DUNDI_COMMAND_NULL:
00358       case DUNDI_COMMAND_ENCRYPT:
00359          if (hdr->strans) {   
00360             /* Create new transaction */
00361             trans = create_transaction(NULL);
00362             if (trans) {
00363                memcpy(&trans->addr, sin, sizeof(trans->addr));
00364                trans->dtrans = ntohs(hdr->strans) & 32767;
00365             } else
00366                ast_log(LOG_WARNING, "Out of memory!\n");
00367          }
00368          break;
00369       default:
00370          break;
00371       }
00372    }
00373    return trans;
00374 }

static int get_trans_id ( void   )  [static]

Definition at line 454 of file pbx_dundi.c.

References alltrans, and t.

Referenced by create_transaction(), and reset_transaction().

00455 {
00456    struct dundi_transaction *t;
00457    int stid = (rand() % 32766) + 1;
00458    int tid = stid;
00459    do {
00460       t = alltrans;
00461       while(t) {
00462          if (t->strans == tid) 
00463             break;
00464          t = t->allnext;
00465       }
00466       if (!t)
00467          return tid;
00468       tid = (tid % 32766) + 1;
00469    } while (tid != stid);
00470    return 0;
00471 }

static int handle_command_response ( struct dundi_transaction trans,
struct dundi_hdr hdr,
int  datalen,
int  encrypted 
) [static]

Definition at line 1514 of file pbx_dundi.c.

References dundi_peer::addr, dundi_transaction::addr, ast_clear_flag_nonstd, ast_db_put(), ast_inet_ntoa(), ast_log(), ast_sched_add(), ast_sched_del(), ast_set_flag_nonstd, ast_strlen_zero(), ast_test_flag, ast_test_flag_nonstd, ast_verbose(), cache_save(), cache_save_hint(), dundi_hdr::cmdresp, dundi_request::dcontext, default_expiration, dundi_result::dest, do_register_expire(), dundi_request::dr, dundi_answer_entity(), dundi_answer_query(), dundi_cache_time, DUNDI_CAUSE_GENERAL, DUNDI_CAUSE_NOAUTH, DUNDI_COMMAND_CANCEL, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_DPRESPONSE, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_EIDRESPONSE, DUNDI_COMMAND_PRECACHERP, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, DUNDI_COMMAND_REGRESPONSE, dundi_eid_to_str(), dundi_eid_to_str_short(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_TTL_EXPIRED, DUNDI_HINT_UNAFFECTED, dundi_ie_append_cause(), dundi_ie_append_short(), DUNDI_IE_CAUSE, DUNDI_IE_EXPIRATION, DUNDI_MODEL_INBOUND, dundi_parse_ies(), dundi_prop_precache(), dundi_send(), dundi_peer::dynamic, dundi_peer::eid, dundi_request::expiration, dundi_hint_metadata::exten, find_peer(), FLAG_ENCRYPT, has_permission(), dundi_request::hmd, dundi_hdr::ies, ies, inaddrcmp(), dundi_peer::include, dundi_peer::inkey, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dundi_request::maxcount, dundi_peer::model, dundi_request::number, option_verbose, dundi_hdr::oseqno, dundi_transaction::parent, dundi_peer::pcmodel, dundi_peer::permit, qualify_peer(), dundi_peer::registerexpire, dundi_request::respcount, tech2str(), dundi_result::techint, dundi_transaction::them_eid, dundi_peer::us_eid, dundi_transaction::us_eid, VERBOSE_PREFIX_3, and dundi_result::weight.

Referenced by handle_frame().

01515 {
01516    /* Handle canonical command / response */
01517    int final = hdr->cmdresp & 0x80;
01518    int cmd = hdr->cmdresp & 0x7f;
01519    int x,y,z;
01520    int resp;
01521    int res;
01522    int authpass=0;
01523    unsigned char *bufcpy;
01524    struct dundi_ie_data ied;
01525    struct dundi_ies ies;
01526    struct dundi_peer *peer;
01527    char eid_str[20];
01528    char eid_str2[20];
01529    memset(&ied, 0, sizeof(ied));
01530    memset(&ies, 0, sizeof(ies));
01531    if (datalen) {
01532       bufcpy = alloca(datalen);
01533       if (!bufcpy)
01534          return -1;
01535       /* Make a copy for parsing */
01536       memcpy(bufcpy, hdr->ies, datalen);
01537       ast_log(LOG_DEBUG, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : "");
01538       if (dundi_parse_ies(&ies, bufcpy, datalen) < 0) {
01539          ast_log(LOG_WARNING, "Failed to parse DUNDI information elements!\n");
01540          return -1;
01541       }
01542    }
01543    switch(cmd) {
01544    case DUNDI_COMMAND_DPDISCOVER:
01545    case DUNDI_COMMAND_EIDQUERY:
01546    case DUNDI_COMMAND_PRECACHERQ:
01547       if (cmd == DUNDI_COMMAND_EIDQUERY)
01548          resp = DUNDI_COMMAND_EIDRESPONSE;
01549       else if (cmd == DUNDI_COMMAND_PRECACHERQ)
01550          resp = DUNDI_COMMAND_PRECACHERP;
01551       else
01552          resp = DUNDI_COMMAND_DPRESPONSE;
01553       /* A dialplan or entity discover -- qualify by highest level entity */
01554       peer = find_peer(ies.eids[0]);
01555       if (!peer) {
01556          dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL);
01557          dundi_send(trans, resp, 0, 1, &ied);
01558       } else {
01559          int hasauth = 0;
01560          trans->us_eid = peer->us_eid;
01561          if (strlen(peer->inkey)) {
01562             hasauth = encrypted;
01563          } else 
01564             hasauth = 1;
01565          if (hasauth) {
01566             /* Okay we're authentiated and all, now we check if they're authorized */
01567             if (!ies.called_context)
01568                ies.called_context = "e164";
01569             if (cmd == DUNDI_COMMAND_EIDQUERY) {
01570                res = dundi_answer_entity(trans, &ies, ies.called_context);
01571             } else {
01572                if (ast_strlen_zero(ies.called_number)) {
01573                   /* They're not permitted to access that context */
01574                   dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Invalid or missing number/entity");
01575                   dundi_send(trans, resp, 0, 1, &ied);
01576                } else if ((cmd == DUNDI_COMMAND_DPDISCOVER) && 
01577                           (peer->model & DUNDI_MODEL_INBOUND) && 
01578                         has_permission(peer->permit, ies.called_context)) {
01579                   res = dundi_answer_query(trans, &ies, ies.called_context);
01580                   if (res < 0) {
01581                      /* There is no such dundi context */
01582                      dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context");
01583                      dundi_send(trans, resp, 0, 1, &ied);
01584                   }
01585                } else if ((cmd = DUNDI_COMMAND_PRECACHERQ) && 
01586                           (peer->pcmodel & DUNDI_MODEL_INBOUND) && 
01587                         has_permission(peer->include, ies.called_context)) {
01588                   res = dundi_prop_precache(trans, &ies, ies.called_context);
01589                   if (res < 0) {
01590                      /* There is no such dundi context */
01591                      dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context");
01592                      dundi_send(trans, resp, 0, 1, &ied);
01593                   }
01594                } else {
01595                   /* They're not permitted to access that context */
01596                   dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Permission to context denied");
01597                   dundi_send(trans, resp, 0, 1, &ied);
01598                }
01599             }
01600          } else {
01601             /* They're not permitted to access that context */
01602             dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unencrypted responses not permitted");
01603             dundi_send(trans, resp, 0, 1, &ied);
01604          }
01605       }
01606       break;
01607    case DUNDI_COMMAND_REGREQ:
01608       /* A register request -- should only have one entity */
01609       peer = find_peer(ies.eids[0]);
01610       if (!peer || !peer->dynamic) {
01611          dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL);
01612          dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, &ied);
01613       } else {
01614          int hasauth = 0;
01615          trans->us_eid = peer->us_eid;
01616          if (!ast_strlen_zero(peer->inkey)) {
01617             hasauth = encrypted;
01618          } else
01619             hasauth = 1;
01620          if (hasauth) {
01621             int expire = default_expiration;
01622             char iabuf[INET_ADDRSTRLEN];
01623             char data[256];
01624             int needqual = 0;
01625             if (peer->registerexpire > -1)
01626                ast_sched_del(sched, peer->registerexpire);
01627             peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
01628             ast_inet_ntoa(iabuf, sizeof(iabuf), trans->addr.sin_addr);
01629             snprintf(data, sizeof(data), "%s:%d:%d", iabuf, ntohs(trans->addr.sin_port), expire);
01630             ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data);
01631             if (inaddrcmp(&peer->addr, &trans->addr)) {
01632                if (option_verbose > 2)
01633                   ast_verbose(VERBOSE_PREFIX_3 "Registered DUNDi peer '%s' at '%s:%d'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), iabuf, ntohs(trans->addr.sin_port));
01634                needqual = 1;
01635             }
01636                
01637             memcpy(&peer->addr, &trans->addr, sizeof(peer->addr));
01638             dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, default_expiration);
01639             dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, &ied);
01640             if (needqual)
01641                qualify_peer(peer, 1);
01642          }
01643       }
01644       break;
01645    case DUNDI_COMMAND_DPRESPONSE:
01646       /* A dialplan response, lets see what we got... */
01647       if (ies.cause < 1) {
01648          /* Success of some sort */
01649          ast_log(LOG_DEBUG, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount);
01650          if (ast_test_flag(trans, FLAG_ENCRYPT)) {
01651             authpass = encrypted;
01652          } else 
01653             authpass = 1;
01654          if (authpass) {
01655             /* Pass back up answers */
01656             if (trans->parent && trans->parent->dr) {
01657                y = trans->parent->respcount;
01658                for (x=0;x<ies.anscount;x++) {
01659                   if (trans->parent->respcount < trans->parent->maxcount) {
01660                      /* Make sure it's not already there */
01661                      for (z=0;z<trans->parent->respcount;z++) {
01662                         if ((trans->parent->dr[z].techint == ies.answers[x]->protocol) &&
01663                             !strcmp(trans->parent->dr[z].dest, (char *)ies.answers[x]->data)) 
01664                               break;
01665                      }
01666                      if (z == trans->parent->respcount) {
01667                         /* Copy into parent responses */
01668                         trans->parent->dr[trans->parent->respcount].flags = ntohs(ies.answers[x]->flags);
01669                         trans->parent->dr[trans->parent->respcount].techint = ies.answers[x]->protocol;
01670                         trans->parent->dr[trans->parent->respcount].weight = ntohs(ies.answers[x]->weight);
01671                         trans->parent->dr[trans->parent->respcount].eid = ies.answers[x]->eid;
01672                         if (ies.expiration > 0)
01673                            trans->parent->dr[trans->parent->respcount].expiration = ies.expiration;
01674                         else
01675                            trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time;
01676                         dundi_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, 
01677                            sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
01678                            &ies.answers[x]->eid);
01679                         ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies.answers[x]->data,
01680                            sizeof(trans->parent->dr[trans->parent->respcount].dest));
01681                         ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies.answers[x]->protocol),
01682                            sizeof(trans->parent->dr[trans->parent->respcount].tech));
01683                         trans->parent->respcount++;
01684                         ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK);
01685                      } else if (trans->parent->dr[z].weight > ies.answers[x]->weight) {
01686                         /* Update weight if appropriate */
01687                         trans->parent->dr[z].weight = ies.answers[x]->weight;
01688                      }
01689                   } else
01690                      ast_log(LOG_NOTICE, "Dropping excessive answers to request for %s@%s\n",
01691                         trans->parent->number, trans->parent->dcontext);
01692                }
01693                /* Save all the results (if any) we had.  Even if no results, still cache lookup.  Let
01694                   the cache know if this request was unaffected by our entity list. */
01695                cache_save(&trans->them_eid, trans->parent, y, 
01696                      ies.hint ? ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_UNAFFECTED)) : 0, ies.expiration, 0);
01697                if (ies.hint) {
01698                   cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration);
01699                   if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED)))
01700                      ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED);
01701                   if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_DONT_ASK))) { 
01702                      if (strlen((char *)ies.hint->data) > strlen(trans->parent->hmd->exten)) {
01703                         ast_copy_string(trans->parent->hmd->exten, (char *)ies.hint->data, 
01704                            sizeof(trans->parent->hmd->exten));
01705                      }
01706                   } else {
01707                      ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK);
01708                   }
01709                }
01710                if (ies.expiration > 0) {
01711                   if (trans->parent->expiration > ies.expiration) {
01712                      trans->parent->expiration = ies.expiration;
01713                   }
01714                }
01715             }
01716             /* Close connection if not final */
01717             if (!final) 
01718                dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
01719          }
01720          
01721       } else {
01722          /* Auth failure, check for data */
01723          if (!final) {
01724             /* Cancel if they didn't already */
01725             dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
01726          }
01727       }
01728       break;
01729    case DUNDI_COMMAND_EIDRESPONSE:
01730       /* A dialplan response, lets see what we got... */
01731       if (ies.cause < 1) {
01732          /* Success of some sort */
01733          ast_log(LOG_DEBUG, "Looks like success of some sort (%d)\n", ies.cause);
01734          if (ast_test_flag(trans, FLAG_ENCRYPT)) {
01735             authpass = encrypted;
01736          } else 
01737             authpass = 1;
01738          if (authpass) {
01739             /* Pass back up answers */
01740             if (trans->parent && trans->parent->dei && ies.q_org) {
01741                if (!trans->parent->respcount) {
01742                   trans->parent->respcount++;
01743                   if (ies.q_dept)
01744                      ast_copy_string(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit));
01745                   if (ies.q_org)
01746                      ast_copy_string(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org));
01747                   if (ies.q_locality)
01748                      ast_copy_string(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality));
01749                   if (ies.q_stateprov)
01750                      ast_copy_string(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov));
01751                   if (ies.q_country)
01752                      ast_copy_string(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country));
01753                   if (ies.q_email)
01754                      ast_copy_string(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email));
01755                   if (ies.q_phone)
01756                      ast_copy_string(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone));
01757                   if (ies.q_ipaddr)
01758                      ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr));
01759                   if (!dundi_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) {
01760                      /* If it's them, update our address */
01761                      ast_inet_ntoa(trans->parent->dei->ipaddr, sizeof(trans->parent->dei->ipaddr),
01762                         trans->addr.sin_addr);
01763                   }
01764                }
01765                if (ies.hint) {
01766                   if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED)))
01767                      ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED);
01768                }
01769             }
01770             /* Close connection if not final */
01771             if (!final) 
01772                dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
01773          }
01774          
01775       } else {
01776          /* Auth failure, check for data */
01777          if (!final) {
01778             /* Cancel if they didn't already */
01779             dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
01780          }
01781       }
01782       break;
01783    case DUNDI_COMMAND_REGRESPONSE:
01784       /* A dialplan response, lets see what we got... */
01785       if (ies.cause < 1) {
01786          int hasauth;
01787          /* Success of some sort */
01788          if (ast_test_flag(trans, FLAG_ENCRYPT)) {
01789             hasauth = encrypted;
01790          } else 
01791             hasauth = 1;
01792          
01793          if (!hasauth) {
01794             ast_log(LOG_NOTICE, "Reponse to register not authorized!\n");
01795             if (!final) {
01796                dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Improper signature in answer");
01797                dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, &ied);
01798             }
01799          } else {
01800             ast_log(LOG_DEBUG, "Yay, we've registered as '%s' to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->us_eid),
01801                      dundi_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid));
01802             /* Close connection if not final */
01803             if (!final) 
01804                dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
01805          }
01806       } else {
01807          /* Auth failure, cancel if they didn't for some reason */
01808          if (!final) {
01809             dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
01810          }
01811       }
01812       break;
01813    case DUNDI_COMMAND_INVALID:
01814    case DUNDI_COMMAND_NULL:
01815    case DUNDI_COMMAND_PRECACHERP:
01816       /* Do nothing special */
01817       if (!final) 
01818          dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
01819       break;
01820    case DUNDI_COMMAND_ENCREJ:
01821       if ((ast_test_flag(trans, FLAG_SENDFULLKEY)) || !trans->lasttrans || !(peer = find_peer(&trans->them_eid))) {
01822          /* No really, it's over at this point */
01823          if (!final) 
01824             dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
01825       } else {
01826          /* Send with full key */
01827          ast_set_flag(trans, FLAG_SENDFULLKEY);
01828          if (final) {
01829             /* Ooops, we got a final message, start by sending ACK... */
01830             dundi_ack(trans, hdr->cmdresp & 0x80);
01831             trans->aseqno = trans->iseqno;
01832             /* Now, we gotta create a new transaction */
01833             if (!reset_transaction(trans)) {
01834                /* Make sure handle_frame doesn't destroy us */
01835                hdr->cmdresp &= 0x7f;
01836                /* Parse the message we transmitted */
01837                memset(&ies, 0, sizeof(ies));
01838                dundi_parse_ies(&ies, trans->lasttrans->h->ies, trans->lasttrans->datalen - sizeof(struct dundi_hdr));
01839                /* Reconstruct outgoing encrypted packet */
01840                memset(&ied, 0, sizeof(ied));
01841                dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
01842                dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128);
01843                dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
01844                if (ies.encblock) 
01845                   dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, ies.encblock->iv, ies.encblock->encdata, ies.enclen);
01846                dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, trans->lasttrans->h->cmdresp & 0x80, &ied);
01847                peer->sentfullkey = 1;
01848             }
01849          }
01850       }
01851       break;
01852    case DUNDI_COMMAND_ENCRYPT:
01853       if (!encrypted) {
01854          /* No nested encryption! */
01855          if ((trans->iseqno == 1) && !trans->oseqno) {
01856             if (!ies.eids[0] || !(peer = find_peer(ies.eids[0])) || 
01857                ((!ies.encsharedkey || !ies.encsig) && !ies.keycrc32) || 
01858                (check_key(peer, ies.encsharedkey, ies.encsig, ies.keycrc32) < 1)) {
01859                if (!final) {
01860                   dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
01861                }
01862                break;
01863             }
01864             apply_peer(trans, peer);
01865             /* Key passed, use new contexts for this session */
01866             trans->ecx = peer->them_ecx;
01867             trans->dcx = peer->them_dcx;
01868          }
01869          if (ast_test_flag(trans, FLAG_ENCRYPT) && ies.encblock && ies.enclen) {
01870             struct dundi_hdr *dhdr;
01871             unsigned char decoded[MAX_PACKET_SIZE];
01872             int ddatalen;
01873             ddatalen = sizeof(decoded);
01874             dhdr = dundi_decrypt(trans, decoded, &ddatalen, hdr, ies.encblock, ies.enclen);
01875             if (dhdr) {
01876                /* Handle decrypted response */
01877                if (dundidebug)
01878                   dundi_showframe(dhdr, 3, &trans->addr, ddatalen - sizeof(struct dundi_hdr));
01879                handle_command_response(trans, dhdr, ddatalen - sizeof(struct dundi_hdr), 1);
01880                /* Carry back final flag */
01881                hdr->cmdresp |= dhdr->cmdresp & 0x80;
01882                break;
01883             } else
01884                ast_log(LOG_DEBUG, "Ouch, decrypt failed :(\n");
01885          }
01886       }
01887       if (!final) {
01888          /* Turn off encryption */
01889          ast_clear_flag(trans, FLAG_ENCRYPT);
01890          dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
01891       }
01892       break;
01893    default:
01894       /* Send unknown command if we don't know it, with final flag IFF it's the
01895          first command in the dialog and only if we haven't recieved final notification */
01896       if (!final) {
01897          dundi_ie_append_byte(&ied, DUNDI_IE_UNKNOWN, cmd);
01898          dundi_send(trans, DUNDI_COMMAND_UNKNOWN, 0, !hdr->oseqno, &ied);
01899       }
01900    }
01901    return 0;
01902 }

static int handle_frame ( struct dundi_hdr h,
struct sockaddr_in *  sin,
int  datalen 
) [static]

Definition at line 1941 of file pbx_dundi.c.

References ack_trans(), dundi_transaction::aseqno, ast_log(), ast_test_flag, dundi_hdr::cmdresp, destroy_packets(), destroy_trans(), dundi_ack(), DUNDI_COMMAND_ACK, dundi_reject(), find_transaction(), FLAG_FINAL, handle_command_response(), dundi_hdr::iseqno, dundi_transaction::iseqno, dundi_transaction::lasttrans, LOG_DEBUG, dundi_transaction::oiseqno, and dundi_hdr::oseqno.

Referenced by socket_read().

01942 {
01943    struct dundi_transaction *trans;
01944    trans = find_transaction(h, sin);
01945    if (!trans) {
01946       dundi_reject(h, sin);
01947       return 0;
01948    }
01949    /* Got a transaction, see where this header fits in */
01950    if (h->oseqno == trans->iseqno) {
01951       /* Just what we were looking for...  Anything but ack increments iseqno */
01952       if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) {
01953          /* If final, we're done */
01954          destroy_trans(trans, 0);
01955          return 0;
01956       }
01957       if (h->cmdresp != DUNDI_COMMAND_ACK) {
01958          trans->oiseqno = trans->iseqno;
01959          trans->iseqno++;
01960          handle_command_response(trans, h, datalen, 0);
01961       }
01962       if (trans->aseqno != trans->iseqno) {
01963          dundi_ack(trans, h->cmdresp & 0x80);
01964          trans->aseqno = trans->iseqno;
01965       }
01966       /* Delete any saved last transmissions */
01967       destroy_packets(trans->lasttrans);
01968       trans->lasttrans = NULL;
01969       if (h->cmdresp & 0x80) {
01970          /* Final -- destroy now */
01971          destroy_trans(trans, 0);
01972       }
01973    } else if (h->oseqno == trans->oiseqno) {
01974       /* Last incoming sequence number -- send ACK without processing */
01975       dundi_ack(trans, 0);
01976    } else {
01977       /* Out of window -- simply drop */
01978       ast_log(LOG_DEBUG, "Dropping packet out of window!\n");
01979    }
01980    return 0;
01981 }

static int has_permission ( struct permission ps,
char *  cont 
) [static]

Definition at line 294 of file pbx_dundi.c.

References permission::allow, permission::name, and permission::next.

Referenced by build_transactions(), dundi_ie_append_eid_appropriately(), handle_command_response(), and optimize_transactions().

00295 {
00296    int res=0;
00297    while(ps) {
00298       if (!strcasecmp(ps->name, "all") || !strcasecmp(ps->name, cont))
00299          res = ps->allow;
00300       ps = ps->next;
00301    }
00302    return res;
00303 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 4828 of file pbx_dundi.c.

References ASTERISK_GPL_KEY.

04829 {
04830    return ASTERISK_GPL_KEY;
04831 }

int load_module ( void   ) 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 4740 of file pbx_dundi.c.

References app, ast_cli_register(), ast_custom_function_register(), ast_inet_ntoa(), ast_log(), ast_register_application(), ast_register_switch(), ast_verbose(), cli_debug, cli_flush, cli_lookup, cli_no_debug, cli_no_store_history, cli_precache, cli_queryeid, cli_show_entityid, cli_show_mappings, cli_show_peer, cli_show_peers, cli_show_precache, cli_show_requests, cli_show_trans, cli_store_history, descrip, dundi_debug_output(), dundi_error_output(), dundi_function, dundi_lookup_exec(), DUNDI_PORT, dundi_set_error(), dundi_set_output(), dundi_switch, io, io_context_create(), LOG_ERROR, LOG_WARNING, netsocket, option_verbose, sched_context_create(), set_config(), start_network_thread(), synopsis, tos, and VERBOSE_PREFIX_2.

04741 {
04742    int res = 0;
04743    struct sockaddr_in sin;
04744    char iabuf[INET_ADDRSTRLEN];
04745    
04746    dundi_set_output(dundi_debug_output);
04747    dundi_set_error(dundi_error_output);
04748    
04749    sin.sin_family = AF_INET;
04750    sin.sin_port = ntohs(DUNDI_PORT);
04751    sin.sin_addr.s_addr = INADDR_ANY;
04752 
04753    /* Make a UDP socket */
04754    io = io_context_create();
04755    sched = sched_context_create();
04756    
04757    if (!io || !sched) {
04758       ast_log(LOG_ERROR, "Out of memory\n");
04759       return -1;
04760    }
04761 
04762    set_config("dundi.conf",&sin);
04763 
04764    netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
04765    
04766    if (netsocket < 0) {
04767       ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
04768       return -1;
04769    }
04770    if (bind(netsocket,(struct sockaddr *)&sin, sizeof(sin))) {
04771       ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), strerror(errno));
04772       return -1;
04773    }
04774 
04775    if (option_verbose > 1)
04776       ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
04777 
04778    if (setsockopt(netsocket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) 
04779       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
04780    
04781    res = start_network_thread();
04782    if (res) {
04783       ast_log(LOG_ERROR, "Unable to start network thread\n");
04784       close(netsocket);
04785       return -1;
04786    }
04787 
04788    if (option_verbose > 1)
04789       ast_verbose(VERBOSE_PREFIX_2 "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
04790 
04791    ast_cli_register(&cli_debug);
04792    ast_cli_register(&cli_store_history);
04793    ast_cli_register(&cli_flush);
04794    ast_cli_register(&cli_no_debug);
04795    ast_cli_register(&cli_no_store_history);
04796    ast_cli_register(&cli_show_peers);
04797    ast_cli_register(&cli_show_entityid);
04798    ast_cli_register(&cli_show_trans);
04799    ast_cli_register(&cli_show_requests);
04800    ast_cli_register(&cli_show_mappings);
04801    ast_cli_register(&cli_show_precache);
04802    ast_cli_register(&cli_show_peer);
04803    ast_cli_register(&cli_lookup);
04804    ast_cli_register(&cli_precache);
04805    ast_cli_register(&cli_queryeid);
04806    if (ast_register_switch(&dundi_switch))
04807       ast_log(LOG_ERROR, "Unable to register DUNDi switch\n");
04808    ast_register_application(app, dundi_lookup_exec, synopsis, descrip);
04809    ast_custom_function_register(&dundi_function); 
04810    
04811    return res;
04812 }

static void load_password ( void   )  [static]

Definition at line 2039 of file pbx_dundi.c.

References ast_db_get(), build_secret(), cursecret, DUNDI_SECRET_TIME, last, rotatetime, save_secret(), and secretpath.

Referenced by set_config().

02040 {
02041    char *current=NULL;
02042    char *last=NULL;
02043    char tmp[256];
02044    time_t expired;
02045    
02046    ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp));
02047    if (sscanf(tmp, "%d", (int *)&expired) == 1) {
02048       ast_db_get(secretpath, "secret", tmp, sizeof(tmp));
02049       current = strchr(tmp, ';');
02050       if (!current)
02051          current = tmp;
02052       else {
02053          *current = '\0';
02054          current++;
02055       };
02056       if ((time(NULL) - expired) < 0) {
02057          if ((expired - time(NULL)) > DUNDI_SECRET_TIME)
02058             expired = time(NULL) + DUNDI_SECRET_TIME;
02059       } else if ((time(NULL) - (expired + DUNDI_SECRET_TIME)) < 0) {
02060          last = current;
02061          current = NULL;
02062       } else {
02063          last = NULL;
02064          current = NULL;
02065       }
02066    }
02067    if (current) {
02068       /* Current key is still valid, just setup rotatation properly */
02069       ast_copy_string(cursecret, current, sizeof(cursecret));
02070       rotatetime = expired;
02071    } else {
02072       /* Current key is out of date, rotate or eliminate all together */
02073       build_secret(cursecret, sizeof(cursecret));
02074       save_secret(cursecret, last);
02075    }
02076 }

static void mark_mappings ( void   )  [static]

Definition at line 4012 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), map, and mappings.

Referenced by set_config().

04013 {
04014    struct dundi_mapping *map;
04015    ast_mutex_lock(&peerlock);
04016    map = mappings;
04017    while(map) {
04018       map->dead = 1;
04019       map = map->next;
04020    }
04021    ast_mutex_unlock(&peerlock);
04022 }

static void mark_peers ( void   )  [static]

Definition at line 4000 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dundi_peer::dead, dundi_peer::next, and peers.

Referenced by set_config().

04001 {
04002    struct dundi_peer *peer;
04003    ast_mutex_lock(&peerlock);
04004    peer = peers;
04005    while(peer) {
04006       peer->dead = 1;
04007       peer = peer->next;
04008    }
04009    ast_mutex_unlock(&peerlock);
04010 }

static char* model2str ( int  model  )  [static]

Definition at line 2229 of file pbx_dundi.c.

References DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, and DUNDI_MODEL_SYMMETRIC.

Referenced by dundi_show_peer().

02230 {
02231    switch(model) {
02232    case DUNDI_MODEL_INBOUND:
02233       return "Inbound";
02234    case DUNDI_MODEL_OUTBOUND:
02235       return "Outbound";
02236    case DUNDI_MODEL_SYMMETRIC:
02237       return "Symmetric";
02238    default:
02239       return "Unknown";
02240    }
02241 }

static void* network_thread ( void *  ignore  )  [static]

Definition at line 2095 of file pbx_dundi.c.

References ast_io_add(), AST_IO_IN, ast_io_wait(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), check_password(), io, netsocket, and socket_read().

02096 {
02097    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
02098       from the network, and queue them for delivery to the channels */
02099    int res;
02100    /* Establish I/O callback for socket read */
02101    ast_io_add(io, netsocket, socket_read, AST_IO_IN, NULL);
02102    for(;;) {
02103       res = ast_sched_wait(sched);
02104       if ((res > 1000) || (res < 0))
02105          res = 1000;
02106       res = ast_io_wait(io, res);
02107       if (res >= 0) {
02108          ast_mutex_lock(&peerlock);
02109          ast_sched_runq(sched);
02110          ast_mutex_unlock(&peerlock);
02111       }
02112       check_password();
02113    }
02114    return NULL;
02115 }

static int optimize_transactions ( struct dundi_request dr,
int  order 
) [static]

Definition at line 3275 of file pbx_dundi.c.

References ast_mutex_lock(), dr, dundi_eid_cmp(), DUNDI_MAX_STACK, dundi_peer::eid, dundi_transaction::eidcount, dundi_transaction::eids, has_permission(), dundi_peer::include, dundi_peer::next, dundi_peer::order, peers, dundi_transaction::them_eid, and dundi_transaction::us_eid.

Referenced by dundi_lookup_internal(), dundi_precache_internal(), and dundi_query_eid_internal().

03276 {
03277    /* Minimize the message propagation through DUNDi by
03278       alerting the network to hops which should be not be considered */
03279    struct dundi_transaction *trans;
03280    struct dundi_peer *peer;
03281    dundi_eid tmp;
03282    int x;
03283    int needpush;
03284    ast_mutex_lock(&peerlock);
03285    trans = dr->trans;
03286    while(trans) {
03287       /* Pop off the true root */
03288       if (trans->eidcount) {
03289          tmp = trans->eids[--trans->eidcount];
03290          needpush = 1;
03291       } else {
03292          tmp = trans->us_eid;
03293          needpush = 0;
03294       }
03295 
03296       peer = peers;
03297       while(peer) {
03298          if (has_permission(peer->include, dr->dcontext) && 
03299              dundi_eid_cmp(&peer->eid, &trans->them_eid) &&
03300             (peer->order <= order)) {
03301             /* For each other transaction, make sure we don't
03302                ask this EID about the others if they're not
03303                already in the list */
03304             if (!dundi_eid_cmp(&tmp, &peer->eid)) 
03305                x = -1;
03306             else {
03307                for (x=0;x<trans->eidcount;x++) {
03308                   if (!dundi_eid_cmp(&trans->eids[x], &peer->eid))
03309                      break;
03310                }
03311             }
03312             if (x == trans->eidcount) {
03313                /* Nope not in the list, if needed, add us at the end since we're the source */
03314                if (trans->eidcount < DUNDI_MAX_STACK - needpush) {
03315                   trans->eids[trans->eidcount++] = peer->eid;
03316                   /* Need to insert the real root (or us) at the bottom now as
03317                      a requirement now.  */
03318                   needpush = 1;
03319                }
03320             }
03321          }
03322          peer = peer->next;
03323       }
03324       /* If necessary, push the true root back on the end */
03325       if (needpush)
03326          trans->eids[trans->eidcount++] = tmp;
03327       trans = trans->next;
03328    }
03329    ast_mutex_unlock(&peerlock);
03330    return 0;
03331 }

static void populate_addr ( struct dundi_peer peer,
dundi_eid eid 
) [static]

Definition at line 4257 of file pbx_dundi.c.

References dundi_peer::addr, ast_db_get(), ast_sched_add(), do_register_expire(), dundi_eid_to_str(), dundi_peer::eid, and dundi_peer::registerexpire.

Referenced by build_peer().

04258 {
04259    char data[256];
04260    char *c;
04261    int port, expire;
04262    char eid_str[20];
04263    dundi_eid_to_str(eid_str, sizeof(eid_str), eid);
04264    if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) {
04265       c = strchr(data, ':');
04266       if (c) {
04267          *c = '\0';
04268          c++;
04269          if (sscanf(c, "%d:%d", &port, &expire) == 2) {
04270             /* Got it! */
04271             inet_aton(data, &peer->addr.sin_addr);
04272             peer->addr.sin_family = AF_INET;
04273             peer->addr.sin_port = htons(port);
04274             peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
04275          }
04276       }
04277    }
04278 }

static int precache_trans ( struct dundi_transaction trans,
struct dundi_mapping maps,
int  mapcount,
int *  minexp,
int *  foundanswers 
) [static]

Definition at line 3124 of file pbx_dundi.c.

References ast_log(), ast_sched_add(), dundi_transaction::autokillid, dundi_transaction::autokilltimeout, dundi_request::dcontext, destroy_trans(), do_autokill(), dr, dundi_cache_time, DUNDI_COMMAND_PRECACHERQ, DUNDI_DEFAULT_VERSION, dundi_eid_zero(), DUNDI_IE_ANSWER, dundi_ie_append_answer(), dundi_ie_append_eid(), dundi_ie_append_hint(), dundi_ie_append_short(), dundi_ie_append_str(), DUNDI_IE_CALLED_CONTEXT, DUNDI_IE_CALLED_NUMBER, DUNDI_IE_EID, DUNDI_IE_EXPIRATION, DUNDI_IE_HINT, DUNDI_IE_TTL, DUNDI_IE_VERSION, dundi_lookup_internal(), dundi_lookup_local(), dundi_send(), dundi_transaction::eidcount, dundi_transaction::eids, dundi_hint_metadata::flags, LOG_WARNING, MAX_RESULTS, dundi_request::number, dundi_transaction::parent, dundi_transaction::them_eid, dundi_transaction::ttl, and dundi_transaction::us_eid.

Referenced by precache_transactions().

03125 {
03126    struct dundi_ie_data ied;
03127    int x, res;
03128    int max = 999999;
03129    int expiration = dundi_cache_time;
03130    int ouranswers=0;
03131    dundi_eid *avoid[1] = { NULL, };
03132    int direct[1] = { 0, };
03133    struct dundi_result dr[MAX_RESULTS];
03134    struct dundi_hint_metadata hmd;
03135    if (!trans->parent) {
03136       ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
03137       return -1;
03138    }
03139    memset(&hmd, 0, sizeof(hmd));
03140    memset(&dr, 0, sizeof(dr));
03141    /* Look up the answers we're going to include */
03142    for (x=0;x<mapcount;x++)
03143       ouranswers = dundi_lookup_local(dr, maps + x, trans->parent->number, &trans->us_eid, ouranswers, &hmd);
03144    if (ouranswers < 0)
03145       ouranswers = 0;
03146    for (x=0;x<ouranswers;x++) {
03147       if (dr[x].weight < max)
03148          max = dr[x].weight;
03149    }
03150    if (max) {
03151       /* If we do not have a canonical result, keep looking */
03152       res = dundi_lookup_internal(dr + ouranswers, MAX_RESULTS - ouranswers, NULL, trans->parent->dcontext, trans->parent->number, trans->ttl, 1, &hmd, &expiration, 0, 1, &trans->them_eid, avoid, direct);
03153       if (res > 0) {
03154          /* Append answer in result */
03155          ouranswers += res;
03156       }
03157    }
03158    
03159    if (ouranswers > 0) {
03160       *foundanswers += ouranswers;
03161       memset(&ied, 0, sizeof(ied));
03162       dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
03163       if (!dundi_eid_zero(&trans->us_eid))
03164          dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
03165       for (x=0;x<trans->eidcount;x++)
03166          dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
03167       dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number);
03168       dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext);
03169       dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
03170       for (x=0;x<ouranswers;x++) {
03171          /* Add answers */
03172          if (dr[x].expiration && (expiration > dr[x].expiration))
03173             expiration = dr[x].expiration;
03174          dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
03175       }
03176       dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
03177       dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
03178       if (trans->autokilltimeout)
03179          trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
03180       if (expiration < *minexp)
03181          *minexp = expiration;
03182       return dundi_send(trans, DUNDI_COMMAND_PRECACHERQ, 0, 0, &ied);
03183    } else {
03184       /* Oops, nothing to send... */
03185       destroy_trans(trans, 0);
03186       return 0;
03187    }
03188 }

static int precache_transactions ( struct dundi_request dr,
struct dundi_mapping maps,
int  mapcount,
int *  expiration,
int *  foundanswers 
) [static]

Definition at line 3225 of file pbx_dundi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, destroy_trans(), dr, FLAG_DEAD, LOG_DEBUG, LOG_WARNING, dundi_transaction::next, precache_trans(), and dundi_transaction::thread.

Referenced by dundi_precache_internal().

03226 {
03227    struct dundi_transaction *trans, *transn;
03228    /* Mark all as "in thread" so they don't disappear */
03229    ast_mutex_lock(&peerlock);
03230    trans = dr->trans;
03231    while(trans) {
03232       if (trans->thread)
03233          ast_log(LOG_WARNING, "This shouldn't happen, really...\n");
03234       trans->thread = 1;
03235       trans = trans->next;
03236    }
03237    ast_mutex_unlock(&peerlock);
03238 
03239    trans = dr->trans;
03240    while(trans) {
03241       if (!ast_test_flag(trans, FLAG_DEAD))
03242          precache_trans(trans, maps, mapcount, expiration, foundanswers);
03243       trans = trans->next;
03244    }
03245 
03246    /* Cleanup any that got destroyed in the mean time */
03247    ast_mutex_lock(&peerlock);
03248    trans = dr->trans;
03249    while(trans) {
03250       transn = trans->next;
03251       trans->thread = 0;
03252       if (ast_test_flag(trans, FLAG_DEAD)) {
03253          ast_log(LOG_DEBUG, "Our transaction went away!\n");
03254          destroy_trans(trans, 0);
03255       }
03256       trans = transn;
03257    }
03258    ast_mutex_unlock(&peerlock);
03259    return 0;
03260 }

static void* process_precache ( void *  ign  )  [static]

Definition at line 2117 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dundi_precache_queue::context, context, dundi_precache(), dundi_precache_queue::expiration, free, dundi_precache_queue::next, dundi_precache_queue::number, and pcq.

Referenced by start_network_thread().

02118 {
02119    struct dundi_precache_queue *qe;
02120    time_t now;
02121    char context[256];
02122    char number[256];
02123    int run;
02124    for (;;) {
02125       time(&now);
02126       run = 0;
02127       ast_mutex_lock(&pclock);
02128       if (pcq) {
02129          if (!pcq->expiration) {
02130             /* Gone...  Remove... */
02131             qe = pcq;
02132             pcq = pcq->next;
02133             free(qe);
02134          } else if (pcq->expiration < now) {
02135             /* Process this entry */
02136             pcq->expiration = 0;
02137             ast_copy_string(context, pcq->context, sizeof(context));
02138             ast_copy_string(number, pcq->number, sizeof(number));
02139             run = 1;
02140          }
02141       }
02142       ast_mutex_unlock(&pclock);
02143       if (run) {
02144          dundi_precache(context, number);
02145       } else
02146          sleep(1);
02147    }
02148    return NULL;
02149 }

static void prune_mappings ( void   )  [static]

Definition at line 4075 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), destroy_map(), map, mappings, and dundi_mapping::next.

Referenced by set_config().

04076 {
04077    struct dundi_mapping *map, *prev, *next;
04078    ast_mutex_lock(&peerlock);
04079    map = mappings;
04080    prev = NULL;
04081    while(map) {
04082       next = map->next;
04083       if (map->dead) {
04084          if (prev)
04085             prev->next = map->next;
04086          else
04087             mappings = map->next;
04088          destroy_map(map);
04089       } else
04090          prev = map;
04091       map = next;
04092    }
04093    ast_mutex_unlock(&peerlock);
04094 }

static void prune_peers ( void   )  [static]

Definition at line 4054 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dundi_peer::dead, destroy_peer(), dundi_peer::next, and peers.

04055 {
04056    struct dundi_peer *peer, *prev, *next;
04057    ast_mutex_lock(&peerlock);
04058    peer = peers;
04059    prev = NULL;
04060    while(peer) {
04061       next = peer->next;
04062       if (peer->dead) {
04063          if (prev)
04064             prev->next = peer->next;
04065          else
04066             peers = peer->next;
04067          destroy_peer(peer);
04068       } else
04069          prev = peer;
04070       peer = next;
04071    }
04072    ast_mutex_unlock(&peerlock);
04073 }

static void qualify_peer ( struct dundi_peer peer,
int  schedonly 
) [static]

Definition at line 4232 of file pbx_dundi.c.

References ast_sched_add(), ast_sched_del(), ast_set_flag, create_transaction(), destroy_trans(), do_qualify(), DUNDI_COMMAND_NULL, dundi_send(), FLAG_ISQUAL, dundi_peer::lastms, dundi_peer::maxms, dundi_peer::qualifyid, dundi_peer::qualtrans, and dundi_peer::qualtx.

Referenced by build_peer(), do_qualify(), and handle_command_response().

04233 {
04234    int when;
04235    if (peer->qualifyid > -1)
04236       ast_sched_del(sched, peer->qualifyid);
04237    peer->qualifyid = -1;
04238    if (peer->qualtrans)
04239       destroy_trans(peer->qualtrans, 0);
04240    peer->qualtrans = NULL;
04241    if (peer->maxms > 0) {
04242       when = 60000;
04243       if (peer->lastms < 0)
04244          when = 10000;
04245       if (schedonly)
04246          when = 5000;
04247       peer->qualifyid = ast_sched_add(sched, when, do_qualify, peer);
04248       if (!schedonly)
04249          peer->qualtrans = create_transaction(peer);
04250       if (peer->qualtrans) {
04251          peer->qualtx = ast_tvnow();
04252          ast_set_flag(peer->qualtrans, FLAG_ISQUAL);
04253          dundi_send(peer->qualtrans, DUNDI_COMMAND_NULL, 0, 1, NULL);
04254       }
04255    }
04256 }

static int query_transactions ( struct dundi_request dr  )  [static]

Definition at line 3262 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dr, and dundi_query().

Referenced by dundi_query_eid_internal().

03263 {
03264    struct dundi_transaction *trans;
03265    ast_mutex_lock(&peerlock);
03266    trans = dr->trans;
03267    while(trans) {
03268       dundi_query(trans);
03269       trans = trans->next;
03270    }
03271    ast_mutex_unlock(&peerlock);
03272    return 0;
03273 }

static int register_request ( struct dundi_request dr,
struct dundi_request **  pending 
) [static]

Definition at line 3447 of file pbx_dundi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dundi_request::crc32, dundi_request::dcontext, dr, dundi_eid_cmp(), dundi_eid_to_str(), LOG_DEBUG, dundi_request::next, dundi_request::number, option_debug, requests, and dundi_request::root_eid.

Referenced by dundi_lookup_internal().

03448 {
03449    struct dundi_request *cur;
03450    int res=0;
03451    char eid_str[20];
03452    ast_mutex_lock(&peerlock);
03453    cur = requests;
03454    while(cur) {
03455       if (option_debug)
03456          ast_log(LOG_DEBUG, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number,
03457             dr->dcontext, dr->number);
03458       if (!strcasecmp(cur->dcontext, dr->dcontext) &&
03459           !strcasecmp(cur->number, dr->number) &&
03460          (!dundi_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) {
03461             ast_log(LOG_DEBUG, "Found existing query for '%s@%s' for '%s' crc '%08lx'\n", 
03462                cur->dcontext, cur->number, dundi_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32);
03463             *pending = cur;
03464          res = 1;
03465          break;
03466       }
03467       cur = cur->next;
03468    }
03469    if (!res) {
03470       ast_log(LOG_DEBUG, "Registering request for '%s@%s' on behalf of '%s' crc '%08lx'\n", 
03471             dr->number, dr->dcontext, dundi_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32);
03472       /* Go ahead and link us in since nobody else is searching for this */
03473       dr->next = requests;
03474       requests = dr;
03475       *pending = NULL;
03476    }
03477    ast_mutex_unlock(&peerlock);
03478    return res;
03479 }

int reload ( void   ) 

Reload stuff.

This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.

Returns:
The return value is not used.

Definition at line 4733 of file pbx_dundi.c.

References set_config().

04734 {
04735    struct sockaddr_in sin;
04736    set_config("dundi.conf",&sin);
04737    return 0;
04738 }

static void reschedule_precache ( const char *  number,
const char *  context,
int  expiration 
) [static]

Definition at line 3646 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dundi_precache_queue::context, dundi_precache_queue::expiration, malloc, dundi_precache_queue::next, dundi_precache_queue::number, and pcq.

Referenced by dundi_precache_full(), and dundi_precache_internal().

03647 {
03648    int len;
03649    struct dundi_precache_queue *qe, *prev=NULL;
03650    ast_mutex_lock(&pclock);
03651    qe = pcq;
03652    while(qe) {
03653       if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) {
03654          if (prev)
03655             prev->next = qe->next;
03656          else
03657             pcq = qe->next;
03658          qe->next = NULL;
03659          break;
03660       }
03661       prev = qe;
03662       qe = qe->next;
03663    };
03664    if (!qe) {
03665       len = sizeof(struct dundi_precache_queue);
03666       len += strlen(number) + 1;
03667       len += strlen(context) + 1;
03668       qe = malloc(len);
03669       if (qe) {
03670          memset(qe, 0, len);
03671          strcpy(qe->number, number);
03672          qe->context = qe->number + strlen(number) + 1;
03673          strcpy(qe->context, context);
03674       }
03675    }
03676    time(&qe->expiration);
03677    qe->expiration += expiration;
03678    prev = pcq;
03679    if (prev) {
03680       while(prev->next && (prev->next->expiration <= qe->expiration))
03681          prev = prev->next;
03682       qe->next = prev->next;
03683       prev->next = qe;
03684    } else
03685       pcq = qe;
03686    ast_mutex_unlock(&pclock);
03687    
03688 }

static int rescomp ( const void *  a,
const void *  b 
) [static]

Definition at line 2273 of file pbx_dundi.c.

References dundi_result::weight.

Referenced by sort_results().

02274 {
02275    const struct dundi_result *resa, *resb;
02276    resa = a;
02277    resb = b;
02278    if (resa->weight < resb->weight)
02279       return -1;
02280    if (resa->weight > resb->weight)
02281       return 1;
02282    return 0;
02283 }

static void reset_global_eid ( void   )  [static]

Definition at line 407 of file pbx_dundi.c.

References ast_log(), dundi_eid_to_str(), _dundi_eid::eid, global_eid, LOG_DEBUG, and s.

Referenced by set_config().

00408 {
00409 #if defined(SIOCGIFHWADDR)
00410    int x,s;
00411    char eid_str[20];
00412    struct ifreq ifr;
00413 
00414    s = socket(AF_INET, SOCK_STREAM, 0);
00415    if (s > 0) {
00416       x = 0;
00417       for(x=0;x<10;x++) {
00418          memset(&ifr, 0, sizeof(ifr));
00419          snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth%d", x);
00420          if (!ioctl(s, SIOCGIFHWADDR, &ifr)) {
00421             memcpy(&global_eid, ((unsigned char *)&ifr.ifr_hwaddr) + 2, sizeof(global_eid));
00422             ast_log(LOG_DEBUG, "Seeding global EID '%s' from '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid), ifr.ifr_name);
00423             close(s);
00424             return;
00425          }
00426         }
00427       close(s);
00428    }
00429 #else
00430 #if defined(ifa_broadaddr) && !defined(SOLARIS)
00431    char eid_str[20];
00432    struct ifaddrs *ifap;
00433    
00434    if (getifaddrs(&ifap) == 0) {
00435       struct ifaddrs *p;
00436       for (p = ifap; p; p = p->ifa_next) {
00437          if (p->ifa_addr->sa_family == AF_LINK) {
00438             struct sockaddr_dl* sdp = (struct sockaddr_dl*) p->ifa_addr;
00439             memcpy(
00440                &(global_eid.eid),
00441                sdp->sdl_data + sdp->sdl_nlen, 6);
00442             ast_log(LOG_DEBUG, "Seeding global EID '%s' from '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid), ifap->ifa_name);
00443             freeifaddrs(ifap);
00444             return;
00445          }
00446       }
00447       freeifaddrs(ifap);
00448    }
00449 #endif
00450 #endif
00451    ast_log(LOG_NOTICE, "No ethernet interface found for seeding global EID  You will have to set it manually.\n");
00452 }

static int reset_transaction ( struct dundi_transaction trans  )  [static]

Definition at line 473 of file pbx_dundi.c.

References dundi_transaction::aseqno, ast_clear_flag, dundi_transaction::dtrans, FLAG_FINAL, get_trans_id(), dundi_transaction::iseqno, dundi_transaction::oiseqno, dundi_transaction::oseqno, and dundi_transaction::strans.

00474 {
00475    int tid;
00476    tid = get_trans_id();
00477    if (tid < 1)
00478       return -1;
00479    trans->strans = tid;
00480    trans->dtrans = 0;
00481    trans->iseqno = 0;
00482    trans->oiseqno = 0;
00483    trans->oseqno = 0;
00484    trans->aseqno = 0;
00485    ast_clear_flag(trans, FLAG_FINAL);  
00486    return 0;
00487 }

static void save_secret ( const char *  newkey,
const char *  oldkey 
) [static]

Definition at line 2026 of file pbx_dundi.c.

References ast_db_put(), DUNDI_SECRET_TIME, rotatetime, and secretpath.

Referenced by check_password(), and load_password().

02027 {
02028    char tmp[256];
02029    if (oldkey)
02030       snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey);
02031    else
02032       snprintf(tmp, sizeof(tmp), "%s", newkey);
02033    rotatetime = time(NULL) + DUNDI_SECRET_TIME;
02034    ast_db_put(secretpath, "secret", tmp);
02035    snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime);
02036    ast_db_put(secretpath, "secretexpiry", tmp);
02037 }

static int set_config ( char *  config_file,
struct sockaddr_in *  sin 
) [static]

Definition at line 4553 of file pbx_dundi.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), ast_variable_browse(), authdebug, build_mapping(), build_peer(), cfg, country, DEFAULT_MAXMS, dept, dundi_cache_time, DUNDI_DEFAULT_CACHE_TIME, DUNDI_DEFAULT_TTL, DUNDI_MODEL_OUTBOUND, dundi_precache_full(), dundi_str_to_eid(), dundi_ttl, email, format, global_autokilltimeout, global_eid, global_storehistory, hp, ipaddr, IPTOS_MINCOST, ast_variable::lineno, load_password(), locality, LOG_ERROR, LOG_NOTICE, LOG_WARNING, mark_mappings(), mark_peers(), ast_variable::name, ast_variable::next, org, phone, prune_mappings(), prune_peers(), reset_global_eid(), secretpath, stateprov, tos, and ast_variable::value.

04554 {
04555    struct ast_config *cfg;
04556    struct ast_variable *v;
04557    char *cat;
04558    int format;
04559    int x;
04560    char hn[MAXHOSTNAMELEN] = "";
04561    struct ast_hostent he;
04562    struct hostent *hp;
04563    struct sockaddr_in sin2;
04564    static int last_port = 0;
04565    int globalpcmodel = 0;
04566    dundi_eid testeid;
04567 
04568    dundi_ttl = DUNDI_DEFAULT_TTL;
04569    dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME;
04570    cfg = ast_config_load(config_file);
04571    
04572    
04573    if (!cfg) {
04574       ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
04575       return -1;
04576    }
04577    ipaddr[0] = '\0';
04578    if (!gethostname(hn, sizeof(hn)-1)) {
04579       hp = ast_gethostbyname(hn, &he);
04580       if (hp) {
04581          memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr));
04582          ast_inet_ntoa(ipaddr, sizeof(ipaddr), sin2.sin_addr);
04583       } else
04584          ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn);
04585    } else
04586       ast_log(LOG_WARNING, "Unable to get host name!\n");
04587    ast_mutex_lock(&peerlock);
04588    reset_global_eid();
04589    global_storehistory = 0;
04590    ast_copy_string(secretpath, "dundi", sizeof(secretpath));
04591    v = ast_variable_browse(cfg, "general");
04592    while(v) {
04593       if (!strcasecmp(v->name, "port")){ 
04594          sin->sin_port = ntohs(atoi(v->value));
04595          if(last_port==0){
04596             last_port=sin->sin_port;
04597          } else if(sin->sin_port != last_port)
04598             ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
04599       } else if (!strcasecmp(v->name, "bindaddr")) {
04600          struct hostent *hp;
04601          struct ast_hostent he;
04602          hp = ast_gethostbyname(v->value, &he);
04603          if (hp) {
04604             memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
04605          } else
04606             ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
04607       } else if (!strcasecmp(v->name, "authdebug")) {
04608          authdebug = ast_true(v->value);
04609       } else if (!strcasecmp(v->name, "ttl")) {
04610          if ((sscanf(v->value, "%d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) {
04611             dundi_ttl = x;
04612          } else {
04613             ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n",
04614                v->value, v->lineno, DUNDI_DEFAULT_TTL);
04615          }
04616       } else if (!strcasecmp(v->name, "autokill")) {
04617          if (sscanf(v->value, "%d", &x) == 1) {
04618             if (x >= 0)
04619                global_autokilltimeout = x;
04620             else
04621                ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
04622          } else if (ast_true(v->value)) {
04623             global_autokilltimeout = DEFAULT_MAXMS;
04624          } else {
04625             global_autokilltimeout = 0;
04626          }
04627       } else if (!strcasecmp(v->name, "entityid")) {
04628          if (!dundi_str_to_eid(&testeid, v->value))
04629             global_eid = testeid;
04630          else
04631             ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno);
04632       } else if (!strcasecmp(v->name, "tos")) {
04633          if (sscanf(v->value, "%d", &format) == 1)
04634             tos = format & 0xff;
04635          else if (!strcasecmp(v->value, "lowdelay"))
04636             tos = IPTOS_LOWDELAY;
04637          else if (!strcasecmp(v->value, "throughput"))
04638             tos = IPTOS_THROUGHPUT;
04639          else if (!strcasecmp(v->value, "reliability"))
04640             tos = IPTOS_RELIABILITY;
04641 #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS)
04642          else if (!strcasecmp(v->value, "mincost"))
04643             tos = IPTOS_MINCOST;
04644 #endif
04645          else if (!strcasecmp(v->value, "none"))
04646             tos = 0;
04647          else
04648 #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS)
04649             ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
04650 #else
04651             ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', or 'none'\n", v->lineno);
04652 #endif
04653       } else if (!strcasecmp(v->name, "department")) {
04654          ast_copy_string(dept, v->value, sizeof(dept));
04655       } else if (!strcasecmp(v->name, "organization")) {
04656          ast_copy_string(org, v->value, sizeof(org));
04657       } else if (!strcasecmp(v->name, "locality")) {
04658          ast_copy_string(locality, v->value, sizeof(locality));
04659       } else if (!strcasecmp(v->name, "stateprov")) {
04660          ast_copy_string(stateprov, v->value, sizeof(stateprov));
04661       } else if (!strcasecmp(v->name, "country")) {
04662          ast_copy_string(country, v->value, sizeof(country));
04663       } else if (!strcasecmp(v->name, "email")) {
04664          ast_copy_string(email, v->value, sizeof(email));
04665       } else if (!strcasecmp(v->name, "phone")) {
04666          ast_copy_string(phone, v->value, sizeof(phone));
04667       } else if (!strcasecmp(v->name, "storehistory")) {
04668          global_storehistory = ast_true(v->value);
04669       } else if (!strcasecmp(v->name, "cachetime")) {
04670          if ((sscanf(v->value, "%d", &x) == 1)) {
04671             dundi_cache_time = x;
04672          } else {
04673             ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n",
04674                v->value, v->lineno, DUNDI_DEFAULT_CACHE_TIME);
04675          }
04676       }
04677       v = v->next;
04678    }
04679    ast_mutex_unlock(&peerlock);
04680    mark_mappings();
04681    v = ast_variable_browse(cfg, "mappings");
04682    while(v) {
04683       build_mapping(v->name, v->value);
04684       v = v->next;
04685    }
04686    prune_mappings();
04687    mark_peers();
04688    cat = ast_category_browse(cfg, NULL);
04689    while(cat) {
04690       if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) {
04691          /* Entries */
04692          if (!dundi_str_to_eid(&testeid, cat))
04693             build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel);
04694          else
04695             ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat);
04696       }
04697       cat = ast_category_browse(cfg, cat);
04698    }
04699    prune_peers();
04700    ast_config_destroy(cfg);
04701    load_password();
04702    if (globalpcmodel & DUNDI_MODEL_OUTBOUND)
04703       dundi_precache_full();
04704    return 0;
04705 }

static int socket_read ( int *  id,
int  fd,
short  events,
void *  cbdata 
) [static]

Definition at line 1983 of file pbx_dundi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dundi_showframe(), dundidebug, handle_frame(), LOG_WARNING, MAX_PACKET_SIZE, and netsocket.

01984 {
01985    struct sockaddr_in sin;
01986    int res;
01987    struct dundi_hdr *h;
01988    char buf[MAX_PACKET_SIZE];
01989    socklen_t len;
01990    len = sizeof(sin);
01991    res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len);
01992    if (res < 0) {
01993       if (errno != ECONNREFUSED)
01994          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
01995       return 1;
01996    }
01997    if (res < sizeof(struct dundi_hdr)) {
01998       ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct dundi_hdr));
01999       return 1;
02000    }
02001    buf[res] = '\0';
02002    h = (struct dundi_hdr *)buf;
02003    if (dundidebug)
02004       dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr));
02005    ast_mutex_lock(&peerlock);
02006    handle_frame(h, &sin, res - sizeof(struct dundi_hdr));
02007    ast_mutex_unlock(&peerlock);
02008    return 1;
02009 }

static void sort_results ( struct dundi_result results,
int  count 
) [static]

Definition at line 2285 of file pbx_dundi.c.

References rescomp().

Referenced by dundi_do_lookup(), dundi_exec(), dundi_lookup_exec(), and dundifunc_read().

02286 {
02287    qsort(results, count, sizeof(results[0]), rescomp);
02288 }

static int start_network_thread ( void   )  [static]

Definition at line 2151 of file pbx_dundi.c.

References ast_pthread_create, netthreadid, network_thread(), precachethreadid, and process_precache().

02152 {
02153    ast_pthread_create(&netthreadid, NULL, network_thread, NULL);
02154    ast_pthread_create(&precachethreadid, NULL, process_precache, NULL);
02155    return 0;
02156 }

static int str2tech ( char *  str  )  [static]

Definition at line 321 of file pbx_dundi.c.

References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, and DUNDI_PROTO_SIP.

Referenced by build_mapping().

00322 {
00323    if (!strcasecmp(str, "IAX") || !strcasecmp(str, "IAX2")) 
00324       return DUNDI_PROTO_IAX;
00325    else if (!strcasecmp(str, "SIP"))
00326       return DUNDI_PROTO_SIP;
00327    else if (!strcasecmp(str, "H323"))
00328       return DUNDI_PROTO_H323;
00329    else
00330       return -1;
00331 }

static char* tech2str ( int  tech  )  [static]

Definition at line 305 of file pbx_dundi.c.

References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, DUNDI_PROTO_NONE, and DUNDI_PROTO_SIP.

Referenced by cache_lookup_internal(), dundi_lookup_local(), dundi_prop_precache(), dundi_show_mappings(), and handle_command_response().

00306 {
00307    switch(tech) {
00308    case DUNDI_PROTO_NONE:
00309       return "None";
00310    case DUNDI_PROTO_IAX:
00311       return "IAX2";
00312    case DUNDI_PROTO_SIP:
00313       return "SIP";
00314    case DUNDI_PROTO_H323:
00315       return "H323";
00316    default:
00317       return "Unknown";
00318    }
00319 }

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

Standard module functions ...

Definition at line 4707 of file pbx_dundi.c.

References app, ast_cli_unregister(), ast_custom_function_unregister(), ast_unregister_application(), ast_unregister_switch(), cli_debug, cli_flush, cli_lookup, cli_no_debug, cli_no_store_history, cli_precache, cli_queryeid, cli_show_entityid, cli_show_mappings, cli_show_peer, cli_show_peers, cli_show_precache, cli_show_requests, cli_show_trans, cli_store_history, dundi_function, dundi_switch, sched_context_destroy(), and STANDARD_HANGUP_LOCALUSERS.

static void unregister_request ( struct dundi_request dr  )  [static]

Definition at line 3481 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dr, dundi_request::next, and requests.

Referenced by dundi_lookup_internal().

03482 {
03483    struct dundi_request *cur, *prev;
03484    ast_mutex_lock(&peerlock);
03485    prev = NULL;
03486    cur = requests;
03487    while(cur) {
03488       if (cur == dr) {
03489          if (prev)
03490             prev->next = cur->next;
03491          else
03492             requests = cur->next;
03493          break;
03494       }
03495       prev = cur;
03496       cur = cur->next;
03497    }
03498    ast_mutex_unlock(&peerlock);
03499 }

static int update_key ( struct dundi_peer peer  )  [static]

Definition at line 1297 of file pbx_dundi.c.

References aes_decrypt_key128(), aes_encrypt_key128(), ast_encrypt_bin, ast_key_get, AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log(), ast_sign_bin, build_iv(), dundi_eid_to_str(), dundi_key_ttl, dundi_peer::eid, dundi_peer::inkey, key(), dundi_peer::keyexpire, LOG_NOTICE, dundi_peer::outkey, dundi_peer::sentfullkey, dundi_peer::txenckey, dundi_peer::us_dcx, dundi_peer::us_ecx, and dundi_peer::us_keycrc32.

Referenced by dundi_encrypt().

01298 {
01299    unsigned char key[16];
01300    struct ast_key *ekey, *skey;
01301    char eid_str[20];
01302    int res;
01303    if (!peer->keyexpire || (peer->keyexpire < time(NULL))) {
01304       build_iv(key);
01305       aes_encrypt_key128(key, &peer->us_ecx);
01306       aes_decrypt_key128(key, &peer->us_dcx);
01307       ekey = ast_key_get(peer->inkey, AST_KEY_PUBLIC);
01308       if (!ekey) {
01309          ast_log(LOG_NOTICE, "No such key '%s' for creating RSA encrypted shared key for '%s'!\n",
01310             peer->inkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
01311          return -1;
01312       }
01313       skey = ast_key_get(peer->outkey, AST_KEY_PRIVATE);
01314       if (!skey) {
01315          ast_log(LOG_NOTICE, "No such key '%s' for signing RSA encrypted shared key for '%s'!\n",
01316             peer->outkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
01317          return -1;
01318       }
01319       if ((res = ast_encrypt_bin(peer->txenckey, key, sizeof(key), ekey)) != 128) {
01320          ast_log(LOG_NOTICE, "Whoa, got a weird encrypt size (%d != %d)!\n", res, 128);
01321          return -1;
01322       }
01323       if ((res = ast_sign_bin(skey, (char *)peer->txenckey, 128, peer->txenckey + 128))) {
01324          ast_log(LOG_NOTICE, "Failed to sign key (%d)!\n", res);
01325          return -1;
01326       }
01327       peer->us_keycrc32 = crc32(0L, peer->txenckey, 128);
01328       peer->sentfullkey = 0;
01329       /* Looks good */
01330       time(&peer->keyexpire);
01331       peer->keyexpire += dundi_key_ttl;
01332    }
01333    return 0;
01334 }

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 4819 of file pbx_dundi.c.

References STANDARD_USECOUNT.

04820 {
04821    int res;
04822    /* XXX DUNDi cannot be unloaded XXX */
04823    return 1;
04824    STANDARD_USECOUNT(res);
04825    return res;
04826 }


Variable Documentation

struct dundi_transaction * alltrans

Referenced by create_transaction(), dundi_show_trans(), find_transaction(), and get_trans_id().

char* app = "DUNDiLookup" [static]

Definition at line 82 of file pbx_dundi.c.

char ast_config_AST_KEY_DIR[]

Definition at line 221 of file asterisk.c.

Referenced by crypto_load(), init_keys(), and osp_build().

int authdebug = 0 [static]

Definition at line 129 of file pbx_dundi.c.

struct ast_cli_entry cli_debug [static]

Initial value:

   { { "dundi", "debug", NULL }, dundi_do_debug, "Enable DUNDi debugging", debug_usage }

Definition at line 2727 of file pbx_dundi.c.

struct ast_cli_entry cli_flush [static]

Initial value:

   { { "dundi", "flush", NULL }, dundi_flush, "Flush DUNDi cache", flush_usage }

Definition at line 2736 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_lookup [static]

Initial value:

   { { "dundi", "lookup", NULL }, dundi_do_lookup, "Lookup a number in DUNDi", lookup_usage }

Definition at line 2763 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_no_debug [static]

Initial value:

   { { "dundi", "no", "debug", NULL }, dundi_no_debug, "Disable DUNDi debugging", no_debug_usage }

Definition at line 2739 of file pbx_dundi.c.

struct ast_cli_entry cli_no_store_history [static]

Initial value:

   { { "dundi", "no", "store", "history", NULL }, dundi_no_store_history, "Disable DUNDi historic records", no_store_history_usage }

Definition at line 2733 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_precache [static]

Initial value:

   { { "dundi", "precache", NULL }, dundi_do_precache, "Precache a number in DUNDi", precache_usage }

Definition at line 2766 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_queryeid [static]

Initial value:

   { { "dundi", "query", NULL }, dundi_do_query, "Query a DUNDi EID", query_usage }

Definition at line 2769 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_show_entityid [static]

Initial value:

   { { "dundi", "show", "entityid", NULL }, dundi_show_entityid, "Display Global Entity ID", show_entityid_usage }

Definition at line 2748 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_show_mappings [static]

Initial value:

   { { "dundi", "show", "mappings", NULL }, dundi_show_mappings, "Show DUNDi mappings", show_mappings_usage }

Definition at line 2751 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_show_peer [static]

Initial value:

   { { "dundi", "show", "peer", NULL }, dundi_show_peer, "Show info on a specific DUNDi peer", show_peer_usage, complete_peer_4 }

Definition at line 2760 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_show_peers [static]

Initial value:

   { { "dundi", "show", "peers", NULL }, dundi_show_peers, "Show defined DUNDi peers", show_peers_usage }

Definition at line 2742 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_show_precache [static]

Initial value:

   { { "dundi", "show", "precache", NULL }, dundi_show_precache, "Show DUNDi precache", show_precache_usage }

Definition at line 2754 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_show_requests [static]

Initial value:

   { { "dundi", "show", "requests", NULL }, dundi_show_requests, "Show DUNDi requests", show_requests_usage }

Definition at line 2757 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_show_trans [static]

Initial value:

   { { "dundi", "show", "trans", NULL }, dundi_show_trans, "Show active DUNDi transactions", show_trans_usage }

Definition at line 2745 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_store_history [static]

Initial value:

   { { "dundi", "store", "history", NULL }, dundi_do_store_history, "Enable DUNDi historic records", store_history_usage }

Definition at line 2730 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

char country[80] [static]

Definition at line 141 of file pbx_dundi.c.

Referenced by dundi_query_thread(), ind_load_module(), and set_config().

char cursecret[80] [static]

Definition at line 145 of file pbx_dundi.c.

Referenced by check_password(), dundi_lookup_local(), and load_password().

char debug_usage[] [static]

Initial value:

 
"Usage: dundi debug\n"
"       Enables dumping of DUNDi packets for debugging purposes\n"

Definition at line 2657 of file pbx_dundi.c.

int default_expiration = 60 [static]

Definition at line 135 of file pbx_dundi.c.

Referenced by do_register(), and handle_command_response().

char dept[80] [static]

Definition at line 137 of file pbx_dundi.c.

Referenced by dundi_query_thread(), and set_config().

char* descrip [static]

Definition at line 84 of file pbx_dundi.c.

int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME [static]

Definition at line 132 of file pbx_dundi.c.

Referenced by cache_save(), cache_save_hint(), dundi_lookup(), dundi_lookup_local(), dundi_lookup_thread(), dundi_precache_internal(), dundi_prop_precache(), handle_command_response(), precache_trans(), and set_config().

int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE [static]

Definition at line 131 of file pbx_dundi.c.

Referenced by update_key().

struct ast_switch dundi_switch [static]

Definition at line 4543 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

int dundi_ttl = DUNDI_DEFAULT_TTL [static]

Definition at line 130 of file pbx_dundi.c.

Referenced by dundi_lookup(), dundi_precache(), dundi_query_eid(), and set_config().

int dundidebug = 0 [static]

Definition at line 128 of file pbx_dundi.c.

Referenced by dundi_do_debug(), dundi_no_debug(), dundi_send(), dundi_xmit(), and socket_read().

char email[80] [static]

Definition at line 142 of file pbx_dundi.c.

Referenced by dundi_query_thread(), and set_config().

dundi_eid empty_eid = { { 0, 0, 0, 0, 0, 0 } } [static]

Definition at line 148 of file pbx_dundi.c.

Referenced by find_peer().

char flush_usage[] [static]

Initial value:

"Usage: dundi flush [stats]\n"
"       Flushes DUNDi answer cache, used primarily for debug.  If\n"
"'stats' is present, clears timer statistics instead of normal\n"
"operation.\n"

Definition at line 2721 of file pbx_dundi.c.

int global_autokilltimeout = 0 [static]

Definition at line 133 of file pbx_dundi.c.

Referenced by apply_peer(), and set_config().

dundi_eid global_eid [static]

Definition at line 134 of file pbx_dundi.c.

Referenced by build_peer(), dundi_show_entityid(), reset_global_eid(), and set_config().

int global_storehistory = 0 [static]

Definition at line 136 of file pbx_dundi.c.

Referenced by create_transaction(), dundi_do_store_history(), dundi_no_store_history(), and set_config().

struct io_context* io [static]

Definition at line 122 of file pbx_dundi.c.

char ipaddr[80] [static]

Definition at line 146 of file pbx_dundi.c.

Referenced by dundi_lookup_local(), realtime_update_peer(), and set_config().

LOCAL_USER_DECL

Definition at line 2774 of file pbx_dundi.c.

char locality[80] [static]

Definition at line 139 of file pbx_dundi.c.

Referenced by dundi_query_thread(), and set_config().

char lookup_usage[] [static]

Initial value:

"Usage: dundi lookup <number>[@context] [bypass]\n"
"       Lookup the given number within the given DUNDi context\n"
"(or e164 if none is specified).  Bypasses cache if 'bypass'\n"
"keyword is specified.\n"

Definition at line 2703 of file pbx_dundi.c.

struct dundi_mapping * mappings [static]

Referenced by build_mapping(), dundi_answer_query(), dundi_precache_full(), dundi_precache_internal(), dundi_show_mappings(), mark_mappings(), and prune_mappings().

int netsocket = -1 [static]

Definition at line 124 of file pbx_dundi.c.

Referenced by ast_netsock_bindaddr(), dundi_xmit(), handle_error(), load_module(), network_thread(), and socket_read().

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 125 of file pbx_dundi.c.

char no_debug_usage[] [static]

Initial value:

 
"Usage: dundi no debug\n"
"       Disables dumping of DUNDi packets for debugging purposes\n"

Definition at line 2661 of file pbx_dundi.c.

char no_store_history_usage[] [static]

Initial value:

 
"Usage: dundi no store history\n"
"       Disables storing of DUNDi requests and times for debugging\n"
"purposes\n"

Definition at line 2670 of file pbx_dundi.c.

char org[80] [static]

Definition at line 138 of file pbx_dundi.c.

Referenced by dundi_query_thread(), and set_config().

struct dundi_precache_queue* pcq [static]

Definition at line 276 of file pbx_dundi.c.

Referenced by dundi_show_precache(), process_precache(), and reschedule_precache().

struct dundi_peer * peers [static]

Referenced by build_peer(), build_transactions(), chanavail_exec(), complete_peer_helper(), destroy_trans(), dial_exec_full(), dundi_flush(), dundi_ie_append_eid_appropriately(), dundi_show_peer(), dundi_show_peers(), find_peer(), mark_peers(), optimize_transactions(), and prune_peers().

char phone[80] [static]

Definition at line 143 of file pbx_dundi.c.

Referenced by dundi_query_thread(), privacy_exec(), and set_config().

char precache_usage[] [static]

Initial value:

"Usage: dundi precache <number>[@context]\n"
"       Lookup the given number within the given DUNDi context\n"
"(or e164 if none is specified) and precaches the results to any\n"
"upstream DUNDi push servers.\n"

Definition at line 2709 of file pbx_dundi.c.

pthread_t precachethreadid = AST_PTHREADT_NULL [static]

Definition at line 126 of file pbx_dundi.c.

Referenced by start_network_thread().

char query_usage[] [static]

Initial value:

"Usage: dundi query <entity>[@context]\n"
"       Attempts to retrieve contact information for a specific\n"
"DUNDi entity identifier (EID) within a given DUNDi context (or\n"
"e164 if none is specified).\n"

Definition at line 2715 of file pbx_dundi.c.

struct dundi_request * requests

Referenced by check_request(), dundi_show_requests(), register_request(), and unregister_request().

time_t rotatetime [static]

Definition at line 147 of file pbx_dundi.c.

Referenced by check_password(), load_password(), and save_secret().

struct sched_context* sched [static]

Definition at line 123 of file pbx_dundi.c.

char secretpath[80] [static]

Definition at line 144 of file pbx_dundi.c.

Referenced by load_password(), save_secret(), and set_config().

char show_entityid_usage[] [static]

Initial value:

 
"Usage: dundi show entityid\n"
"       Displays the global entityid for this host.\n"

Definition at line 2691 of file pbx_dundi.c.

char show_mappings_usage[] [static]

Initial value:

 
"Usage: dundi show mappings\n"
"       Lists all known DUNDi mappings.\n"

Definition at line 2683 of file pbx_dundi.c.

char show_peer_usage[] [static]

Initial value:

 
"Usage: dundi show peer [peer]\n"
"       Provide a detailed description of a specifid DUNDi peer.\n"

Definition at line 2695 of file pbx_dundi.c.

char show_peers_usage[] [static]

Initial value:

 
"Usage: dundi show peers\n"
"       Lists all known DUNDi peers.\n"

Definition at line 2675 of file pbx_dundi.c.

char show_precache_usage[] [static]

Initial value:

 
"Usage: dundi show precache\n"
"       Lists all known DUNDi scheduled precache updates.\n"

Definition at line 2687 of file pbx_dundi.c.

char show_requests_usage[] [static]

Initial value:

 
"Usage: dundi show requests\n"
"       Lists all known pending DUNDi requests.\n"

Definition at line 2699 of file pbx_dundi.c.

char show_trans_usage[] [static]

Initial value:

 
"Usage: dundi show trans\n"
"       Lists all known DUNDi transactions.\n"

Definition at line 2679 of file pbx_dundi.c.

STANDARD_LOCAL_USER

Definition at line 2772 of file pbx_dundi.c.

char stateprov[80] [static]

Definition at line 140 of file pbx_dundi.c.

Referenced by dundi_query_thread(), and set_config().

char store_history_usage[] [static]

Initial value:

 
"Usage: dundi store history\n"
"       Enables storing of DUNDi requests and times for debugging\n"
"purposes\n"

Definition at line 2665 of file pbx_dundi.c.

char* synopsis = "Look up a number with DUNDi" [static]

Definition at line 83 of file pbx_dundi.c.

char* tdesc = "Distributed Universal Number Discovery (DUNDi)" [static]

Definition at line 80 of file pbx_dundi.c.

int tos = 0 [static]

Definition at line 127 of file pbx_dundi.c.


Generated on Mon Sep 18 09:15:34 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7