Wed Feb 11 12:00:29 2009

Asterisk developer's documentation


pbx_dundi.c File Reference

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

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <netinet/ip.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <zlib.h>
#include <sys/signal.h>
#include <pthread.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/md5.h"
#include "asterisk/dundi.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/utils.h"
#include "asterisk/crypto.h"
#include "asterisk/astdb.h"
#include "asterisk/acl.h"
#include "asterisk/aes.h"
#include "dundi-parser.h"

Go to the source code of this file.

Data Structures

struct  alltrans
struct  dundi_hint_metadata
struct  dundi_mapping
struct  dundi_packet
struct  dundi_peer
struct  dundi_peer::permissionlist
struct  dundi_precache_queue
struct  dundi_query_state
struct  dundi_request
struct  dundi_transaction
struct  dundi_transaction::packetlist
struct  mappings
struct  pcq
struct  peers
struct  permission
struct  requests

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 __reg_module (void)
static void __unreg_module (void)
static void abort_request (struct dundi_request *dr)
static int ack_trans (struct dundi_transaction *trans, int iseqno)
static void append_permission (struct permissionlist *permlist, char *s, int allow)
static int append_transaction (struct dundi_request *dr, struct dundi_peer *p, int ttl, dundi_eid *avoid[])
static void apply_peer (struct dundi_transaction *trans, struct dundi_peer *p)
static 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, uint32_t 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, uint32_t keycrc32)
static void check_password (void)
static int check_request (struct dundi_request *dr)
static char * complete_peer_4 (const char *line, const char *word, int pos, int state)
static char * complete_peer_helper (const char *line, const char *word, int pos, int state, int rpos)
static struct dundi_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)
static void deep_copy_peer (struct dundi_peer *peer_dst, const struct dundi_peer *peer_src)
static void destroy_map (struct dundi_mapping *map)
static void destroy_packet (struct dundi_packet *pack, int needfree)
static void destroy_packets (struct packetlist *p)
static void destroy_peer (struct dundi_peer *peer)
static void destroy_permissions (struct permissionlist *permlist)
static void destroy_trans (struct dundi_transaction *trans, int fromtimeout)
static int discover_transactions (struct dundi_request *dr)
static int do_autokill (const void *data)
static int do_qualify (const void *data)
static int do_register (const void *data)
static int do_register_expire (const void *data)
static int dundi_ack (struct dundi_transaction *trans, int final)
static int dundi_answer_entity (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
static int dundi_answer_query (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
static int dundi_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static void dundi_debug_output (const char *data)
static struct dundi_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, const char *data)
static int dundi_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static int dundi_flush (int fd, int argc, char *argv[])
static int dundi_helper (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *data, int flag)
static void dundi_ie_append_eid_appropriately (struct dundi_ie_data *ied, char *context, dundi_eid *eid, dundi_eid *us)
int dundi_lookup (struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int cbypass)
 Lookup the given number in the given dundi context (or e164 if unspecified) using the given callerid (if specified) and return up to maxret results in the array specified. returns the number of results found or -1 on a hangup of teh channel.
static int dundi_lookup_internal (struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *md, int *expiration, int cybpass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[])
static int dundi_lookup_local (struct dundi_result *dr, struct dundi_mapping *map, char *called_number, dundi_eid *us_eid, int anscnt, struct dundi_hint_metadata *hmd)
static void * dundi_lookup_thread (void *data)
static int dundi_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static int dundi_no_debug (int fd, int argc, char *argv[])
static int dundi_no_store_history (int fd, int argc, char *argv[])
int dundi_precache (const char *context, const char *number)
 Pre-cache to push upstream peers.
static void dundi_precache_full (void)
static int dundi_precache_internal (const char *context, const char *number, int ttl, dundi_eid *avoids[])
static void * dundi_precache_thread (void *data)
static int dundi_prop_precache (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
static int dundi_query (struct dundi_transaction *trans)
int dundi_query_eid (struct dundi_entity_info *dei, const char *dcontext, dundi_eid eid)
 Retrieve information on a specific EID.
static int dundi_query_eid_internal (struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[])
static void * dundi_query_thread (void *data)
static void dundi_reject (struct dundi_hdr *h, struct sockaddr_in *sin)
static int dundi_rexmit (const void *data)
static int dundi_send (struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
static int dundi_show_entityid (int fd, int argc, char *argv[])
static int dundi_show_mappings (int fd, int argc, char *argv[])
static int dundi_show_peer (int fd, int argc, char *argv[])
static int dundi_show_peers (int fd, int argc, char *argv[])
static int dundi_show_precache (int fd, int argc, char *argv[])
static int dundi_show_requests (int fd, int argc, char *argv[])
static int dundi_show_trans (int fd, int argc, char *argv[])
static int dundi_xmit (struct dundi_packet *pack)
static int dundifunc_read (struct ast_channel *chan, char *cmd, char *num, char *buf, size_t len)
static int encrypt_memcpy (unsigned char *dst, unsigned char *src, int len, unsigned char *iv, aes_encrypt_ctx *ecx)
static struct dundi_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 permissionlist *permlist, char *cont)
static int load_module (void)
static void load_password (void)
static void mark_mappings (void)
static void mark_peers (void)
static char * model2str (int model)
static void * network_thread (void *ignore)
static int optimize_transactions (struct dundi_request *dr, int order)
static void populate_addr (struct dundi_peer *peer, dundi_eid *eid)
static int precache_trans (struct dundi_transaction *trans, struct dundi_mapping *maps, int mapcount, int *minexp, int *foundanswers)
static int precache_transactions (struct dundi_request *dr, struct dundi_mapping *maps, int mapcount, int *expiration, int *foundanswers)
static void * process_clearcache (void *ignore)
static void * process_precache (void *ign)
static void prune_mappings (void)
static void prune_peers (void)
static void qualify_peer (struct dundi_peer *peer, int schedonly)
static int query_transactions (struct dundi_request *dr)
static int register_request (struct dundi_request *dr, struct dundi_request **pending)
static int reload (void)
static void reschedule_precache (const char *number, const char *context, int expiration)
static int rescomp (const void *a, const void *b)
static void reset_global_eid (void)
static int reset_transaction (struct dundi_transaction *trans)
static void save_secret (const char *newkey, const char *oldkey)
static int set_config (char *config_file, struct sockaddr_in *sin)
static int socket_read (int *id, int fd, short events, void *cbdata)
static void sort_results (struct dundi_result *results, int count)
static int start_network_thread (void)
static int str2tech (char *str)
static char * tech2str (int tech)
static int unload_module (void)
static void unregister_request (struct dundi_request *dr)
static int update_key (struct dundi_peer *peer)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Distributed Universal Number Discovery (DUNDi)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct dundi_peerany_peer
 Wildcard peer.
static const struct ast_module_infoast_module_info = &__mod_info
static int authdebug = 0
static pthread_t clearcachethreadid = AST_PTHREADT_NULL
static struct ast_cli_entry cli_dundi []
static char country [80]
static char cursecret [80]
static char debug_usage []
static int default_expiration = 60
static char dept [80]
static int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME
static struct ast_custom_function dundi_function
static int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE
static int dundi_shutdown = 0
static struct ast_switch dundi_switch
static int dundi_ttl = DUNDI_DEFAULT_TTL
static int dundidebug = 0
static char email [80]
static dundi_eid empty_eid = { { 0, 0, 0, 0, 0, 0 } }
static char flush_usage []
static int global_autokilltimeout = 0
static dundi_eid global_eid
static int global_storehistory = 0
static struct io_contextio
static char ipaddr [80]
static char locality [80]
static char lookup_usage []
static int netsocket = -1
static pthread_t netthreadid = AST_PTHREADT_NULL
static char no_debug_usage []
static char no_store_history_usage []
static char org [80]
static char phone [80]
static char precache_usage []
static pthread_t precachethreadid = AST_PTHREADT_NULL
static char query_usage []
static time_t rotatetime
static struct sched_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 []
static char stateprov [80]
static char store_history_usage []
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 98 of file pbx_dundi.c.

Referenced by build_mapping(), and dundi_lookup_local().

#define DUNDI_MODEL_INBOUND   (1 << 0)

Definition at line 83 of file pbx_dundi.c.

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

#define DUNDI_MODEL_OUTBOUND   (1 << 1)

Definition at line 84 of file pbx_dundi.c.

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

#define DUNDI_MODEL_SYMMETRIC   (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)

Definition at line 85 of file pbx_dundi.c.

Referenced by model2str().

#define DUNDI_SECRET_TIME   DUNDI_DEFAULT_CACHE_TIME

Definition at line 103 of file pbx_dundi.c.

Referenced by load_password(), and save_secret().

#define DUNDI_TIMING_HISTORY   10

Keep times of last 10 lookups

Definition at line 88 of file pbx_dundi.c.

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

#define FLAG_DEAD   (1 << 1)

Transaction is dead

Definition at line 91 of file pbx_dundi.c.

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

#define FLAG_ENCRYPT   (1 << 4)

Transaction is encrypted wiht ECX/DCX

Definition at line 94 of file pbx_dundi.c.

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

#define FLAG_FINAL   (1 << 2)

Transaction has final message sent

Definition at line 92 of file pbx_dundi.c.

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

#define FLAG_ISQUAL   (1 << 3)

Transaction is a qualification

Definition at line 93 of file pbx_dundi.c.

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

#define FLAG_ISREG   (1 << 0)

Transaction is register request

Definition at line 90 of file pbx_dundi.c.

Referenced by destroy_trans(), and do_register().

#define FLAG_SENDFULLKEY   (1 << 5)

Send full key on transaction

Definition at line 95 of file pbx_dundi.c.

Referenced by create_transaction(), and dundi_encrypt().

#define FLAG_STOREHIST   (1 << 6)

Record historic performance

Definition at line 96 of file pbx_dundi.c.

Referenced by create_transaction(), and destroy_trans().

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

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

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

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

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

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

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

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

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

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

#define KEY_IN   1

Definition at line 107 of file pbx_dundi.c.

#define KEY_OUT   0

Definition at line 106 of file pbx_dundi.c.

#define MAX_OPTS   128

Definition at line 4003 of file pbx_dundi.c.

Referenced by build_mapping().

#define MAX_PACKET_SIZE   8192

Definition at line 81 of file pbx_dundi.c.

Referenced by socket_read().

#define MAX_RESULTS   64

Definition at line 79 of file pbx_dundi.c.

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 4681 of file pbx_dundi.c.

static void __unreg_module ( void   )  [static]

Definition at line 4681 of file pbx_dundi.c.

static void abort_request ( struct dundi_request dr  )  [static]

Definition at line 3403 of file pbx_dundi.c.

References AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, destroy_trans(), and dr.

Referenced by dundi_lookup_internal().

03404 {
03405    struct dundi_transaction *trans;
03406 
03407    AST_LIST_LOCK(&peers);
03408    while ((trans = AST_LIST_FIRST(&dr->trans))) {
03409       /* This will remove the transaction from the list */
03410       destroy_trans(trans, 0);
03411    }
03412    AST_LIST_UNLOCK(&peers);
03413 }

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

Definition at line 1975 of file pbx_dundi.c.

References AST_LIST_EMPTY, AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_log(), AST_SCHED_DEL, dundi_transaction::autokillid, destroy_packet(), destroy_packets(), dundi_packet::h, dundi_transaction::lasttrans, dundi_packet::list, LOG_WARNING, dundi_hdr::oseqno, dundi_transaction::packets, and sched.

Referenced by handle_frame().

01976 {
01977    struct dundi_packet *pack;
01978 
01979    /* Ack transmitted packet corresponding to iseqno */
01980    AST_LIST_TRAVERSE(&trans->packets, pack, list) {
01981       if ((pack->h->oseqno + 1) % 255 == iseqno) {
01982          destroy_packet(pack, 0);
01983          if (!AST_LIST_EMPTY(&trans->lasttrans)) {
01984             ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n");
01985             destroy_packets(&trans->lasttrans);
01986          }
01987          AST_LIST_INSERT_HEAD(&trans->lasttrans, pack, list);
01988          AST_SCHED_DEL(sched, trans->autokillid);
01989          return 1;
01990       }
01991    }
01992 
01993    return 0;
01994 }

static void append_permission ( struct permissionlist *  permlist,
char *  s,
int  allow 
) [static]

Definition at line 3990 of file pbx_dundi.c.

References ast_calloc, AST_LIST_INSERT_TAIL, and permission::list.

03991 {
03992    struct permission *perm;
03993 
03994    if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(s) + 1)))
03995       return;
03996 
03997    strcpy(perm->name, s);
03998    perm->allow = allow;
03999 
04000    AST_LIST_INSERT_TAIL(permlist, perm, list);
04001 }

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

Definition at line 3360 of file pbx_dundi.c.

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

Referenced by build_transactions().

03361 {
03362    struct dundi_transaction *trans;
03363    int x;
03364    char eid_str[20];
03365    char eid_str2[20];
03366 
03367    /* Ignore if not registered */
03368    if (!p->addr.sin_addr.s_addr)
03369       return 0;
03370    if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms)))
03371       return 0;
03372    if (ast_strlen_zero(dr->number))
03373       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);
03374    else
03375       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);
03376    trans = create_transaction(p);
03377    if (!trans)
03378       return -1;
03379    trans->parent = dr;
03380    trans->ttl = ttl;
03381    for (x = 0; avoid[x] && (x < DUNDI_MAX_STACK); x++)
03382       trans->eids[x] = *avoid[x];
03383    trans->eidcount = x;
03384    AST_LIST_INSERT_HEAD(&dr->trans, trans, parentlist);
03385    
03386    return 0;
03387 }

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

Definition at line 1252 of file pbx_dundi.c.

References dundi_peer::addr, dundi_transaction::addr, ast_set_flag, ast_strlen_zero(), dundi_transaction::autokilltimeout, DUNDI_DEFAULT_RETRANS_TIMER, dundi_peer::eid, FLAG_ENCRYPT, dundi_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().

01253 {
01254    if (!trans->addr.sin_addr.s_addr)
01255       memcpy(&trans->addr, &p->addr, sizeof(trans->addr));
01256    trans->us_eid = p->us_eid;
01257    trans->them_eid = p->eid;
01258    /* Enable encryption if appropriate */
01259    if (!ast_strlen_zero(p->inkey))
01260       ast_set_flag(trans, FLAG_ENCRYPT);  
01261    if (p->maxms) {
01262       trans->autokilltimeout = p->maxms;
01263       trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
01264       if (p->lastms > 1) {
01265          trans->retranstimer = p->lastms * 2;
01266          /* Keep it from being silly */
01267          if (trans->retranstimer < 150)
01268             trans->retranstimer = 150;
01269       }
01270       if (trans->retranstimer > DUNDI_DEFAULT_RETRANS_TIMER)
01271          trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
01272    } else
01273       trans->autokilltimeout = global_autokilltimeout;
01274 }

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

Definition at line 3524 of file pbx_dundi.c.

References dundi_request::crc32.

Referenced by dundi_lookup_internal().

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

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

Definition at line 502 of file pbx_dundi.c.

References ast_random().

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

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

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

Definition at line 4005 of file pbx_dundi.c.

References ast_calloc, ast_copy_string(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_log(), ast_strdupa, ast_strlen_zero(), DUNDI_FLAG_COMMERCIAL, DUNDI_FLAG_INTERNAL_NOPARTIAL, DUNDI_FLAG_MOBILE, DUNDI_FLAG_NOCOMUNSOLICIT, DUNDI_FLAG_NOUNSOLICITED, DUNDI_FLAG_RESIDENTIAL, dundi_mapping::list, LOG_WARNING, map, MAX_OPTS, str2tech(), and t.

Referenced by set_config().

04006 {
04007    char *t, *fields[MAX_OPTS];
04008    struct dundi_mapping *map;
04009    int x;
04010    int y;
04011 
04012    t = ast_strdupa(value);
04013       
04014    AST_LIST_TRAVERSE(&mappings, map, list) {
04015       /* Find a double match */
04016       if (!strcasecmp(map->dcontext, name) && 
04017          (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) && 
04018            (!value[strlen(map->lcontext)] || 
04019             (value[strlen(map->lcontext)] == ','))))
04020          break;
04021    }
04022    if (!map) {
04023       if (!(map = ast_calloc(1, sizeof(*map))))
04024          return;
04025       AST_LIST_INSERT_HEAD(&mappings, map, list);
04026       map->dead = 1;
04027    }
04028    map->options = 0;
04029    memset(fields, 0, sizeof(fields));
04030    x = 0;
04031    while (t && x < MAX_OPTS) {
04032       fields[x++] = t;
04033       t = strchr(t, ',');
04034       if (t) {
04035          *t = '\0';
04036          t++;
04037       }
04038    } /* Russell was here, arrrr! */
04039    if ((x == 1) && ast_strlen_zero(fields[0])) {
04040       /* Placeholder mapping */
04041       ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
04042       map->dead = 0;
04043    } else if (x >= 4) {
04044       ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
04045       ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext));
04046       if ((sscanf(fields[1], "%d", &map->weight) == 1) && (map->weight >= 0) && (map->weight < 60000)) {
04047          ast_copy_string(map->dest, fields[3], sizeof(map->dest));
04048          if ((map->tech = str2tech(fields[2]))) {
04049             map->dead = 0;
04050          }
04051       } else {
04052          ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext);
04053       }
04054       for (y = 4;y < x; y++) {
04055          if (!strcasecmp(fields[y], "nounsolicited"))
04056             map->options |= DUNDI_FLAG_NOUNSOLICITED;
04057          else if (!strcasecmp(fields[y], "nocomunsolicit"))
04058             map->options |= DUNDI_FLAG_NOCOMUNSOLICIT;
04059          else if (!strcasecmp(fields[y], "residential"))
04060             map->options |= DUNDI_FLAG_RESIDENTIAL;
04061          else if (!strcasecmp(fields[y], "commercial"))
04062             map->options |= DUNDI_FLAG_COMMERCIAL;
04063          else if (!strcasecmp(fields[y], "mobile"))
04064             map->options |= DUNDI_FLAG_MOBILE;
04065          else if (!strcasecmp(fields[y], "nopartial"))
04066             map->options |= DUNDI_FLAG_INTERNAL_NOPARTIAL;
04067          else
04068             ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]);
04069       }
04070    } else 
04071       ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x);
04072 }

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

Definition at line 4156 of file pbx_dundi.c.

References ast_calloc, ast_copy_string(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_SCHED_DEL, dundi_peer::dead, destroy_permissions(), dundi_eid_cmp(), DUNDI_PORT, dundi_peer::eid, global_eid, hp, dundi_peer::include, dundi_peer::inkey, ast_variable::name, ast_variable::next, dundi_peer::outkey, dundi_peer::permit, populate_addr(), dundi_peer::registerid, sched, dundi_peer::us_eid, and ast_variable::value.

04157 {
04158    struct dundi_peer *peer;
04159    struct ast_hostent he;
04160    struct hostent *hp;
04161    dundi_eid testeid;
04162    int needregister=0;
04163    char eid_str[20];
04164 
04165    AST_LIST_LOCK(&peers);
04166    AST_LIST_TRAVERSE(&peers, peer, list) {
04167       if (!dundi_eid_cmp(&peer->eid, eid)) { 
04168          break;
04169       }
04170    }
04171    if (!peer) {
04172       /* Add us into the list */
04173       if (!(peer = ast_calloc(1, sizeof(*peer)))) {
04174          AST_LIST_UNLOCK(&peers);
04175          return;
04176       }
04177       peer->registerid = -1;
04178       peer->registerexpire = -1;
04179       peer->qualifyid = -1;
04180       peer->addr.sin_family = AF_INET;
04181       peer->addr.sin_port = htons(DUNDI_PORT);
04182       populate_addr(peer, eid);
04183       AST_LIST_INSERT_HEAD(&peers, peer, list);
04184    }
04185    peer->dead = 0;
04186    peer->eid = *eid;
04187    peer->us_eid = global_eid;
04188    destroy_permissions(&peer->permit);
04189    destroy_permissions(&peer->include);
04190    AST_SCHED_DEL(sched, peer->registerid);
04191    for (; v; v = v->next) {
04192       if (!strcasecmp(v->name, "inkey")) {
04193          ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey));
04194       } else if (!strcasecmp(v->name, "outkey")) {
04195          ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));
04196       } else if (!strcasecmp(v->name, "host")) {
04197          if (!strcasecmp(v->value, "dynamic")) {
04198             peer->dynamic = 1;
04199          } else {
04200             hp = ast_gethostbyname(v->value, &he);
04201             if (hp) {
04202                memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));
04203                peer->dynamic = 0;
04204             } else {
04205                ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
04206                peer->dead = 1;
04207             }
04208          }
04209       } else if (!strcasecmp(v->name, "ustothem")) {
04210          if (!dundi_str_to_eid(&testeid, v->value))
04211             peer->us_eid = testeid;
04212          else
04213             ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno);
04214       } else if (!strcasecmp(v->name, "include")) {
04215          append_permission(&peer->include, v->value, 1);
04216       } else if (!strcasecmp(v->name, "permit")) {
04217          append_permission(&peer->permit, v->value, 1);
04218       } else if (!strcasecmp(v->name, "noinclude")) {
04219          append_permission(&peer->include, v->value, 0);
04220       } else if (!strcasecmp(v->name, "deny")) {
04221          append_permission(&peer->permit, v->value, 0);
04222       } else if (!strcasecmp(v->name, "register")) {
04223          needregister = ast_true(v->value);
04224       } else if (!strcasecmp(v->name, "order")) {
04225          if (!strcasecmp(v->value, "primary"))
04226             peer->order = 0;
04227          else if (!strcasecmp(v->value, "secondary"))
04228             peer->order = 1;
04229          else if (!strcasecmp(v->value, "tertiary"))
04230             peer->order = 2;
04231          else if (!strcasecmp(v->value, "quartiary"))
04232             peer->order = 3;
04233          else {
04234             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);
04235          }
04236       } else if (!strcasecmp(v->name, "qualify")) {
04237          if (!strcasecmp(v->value, "no")) {
04238             peer->maxms = 0;
04239          } else if (!strcasecmp(v->value, "yes")) {
04240             peer->maxms = DEFAULT_MAXMS;
04241          } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
04242             ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n", 
04243                dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno);
04244             peer->maxms = 0;
04245          }
04246       } else if (!strcasecmp(v->name, "model")) {
04247          if (!strcasecmp(v->value, "inbound"))
04248             peer->model = DUNDI_MODEL_INBOUND;
04249          else if (!strcasecmp(v->value, "outbound")) 
04250             peer->model = DUNDI_MODEL_OUTBOUND;
04251          else if (!strcasecmp(v->value, "symmetric"))
04252             peer->model = DUNDI_MODEL_SYMMETRIC;
04253          else if (!strcasecmp(v->value, "none"))
04254             peer->model = 0;
04255          else {
04256             ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 
04257                v->value, v->lineno);
04258          }
04259       } else if (!strcasecmp(v->name, "precache")) {
04260          if (!strcasecmp(v->value, "inbound"))
04261             peer->pcmodel = DUNDI_MODEL_INBOUND;
04262          else if (!strcasecmp(v->value, "outbound")) 
04263             peer->pcmodel = DUNDI_MODEL_OUTBOUND;
04264          else if (!strcasecmp(v->value, "symmetric"))
04265             peer->pcmodel = DUNDI_MODEL_SYMMETRIC;
04266          else if (!strcasecmp(v->value, "none"))
04267             peer->pcmodel = 0;
04268          else {
04269             ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 
04270                v->value, v->lineno);
04271          }
04272       }
04273    }
04274    (*globalpcmode) |= peer->pcmodel;
04275    if (!peer->model && !peer->pcmodel) {
04276       ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n", 
04277          dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
04278       peer->dead = 1;
04279    } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
04280       ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n", 
04281          dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
04282       peer->dead = 1;
04283    } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) {
04284       ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n", 
04285          dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
04286       peer->dead = 1;
04287    } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) {
04288       ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n", 
04289          dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
04290    } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
04291       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", 
04292          dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
04293    } else { 
04294       if (needregister) {
04295          peer->registerid = ast_sched_add(sched, 2000, do_register, peer);
04296       }
04297       qualify_peer(peer, 1);
04298    }
04299    AST_LIST_UNLOCK(&peers);
04300 }

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

Definition at line 2065 of file pbx_dundi.c.

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

Referenced by check_password(), and load_password().

02066 {
02067    unsigned char tmp[16];
02068    char *s;
02069    build_iv(tmp);
02070    secret[0] = '\0';
02071    ast_base64encode(secret, tmp, sizeof(tmp), seclen);
02072    /* Eliminate potential bad characters */
02073    while((s = strchr(secret, ';'))) *s = '+';
02074    while((s = strchr(secret, '/'))) *s = '+';
02075    while((s = strchr(secret, ':'))) *s = '+';
02076    while((s = strchr(secret, '@'))) *s = '+';
02077 }

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 3415 of file pbx_dundi.c.

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

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

03416 {
03417    struct dundi_peer *p;
03418    int x;
03419    int res;
03420    int pass;
03421    int allowconnect;
03422    char eid_str[20];
03423    AST_LIST_LOCK(&peers);
03424    AST_LIST_TRAVERSE(&peers, p, list) {
03425       if (modeselect == 1) {
03426          /* Send the precache to push upstreams only! */
03427          pass = has_permission(&p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND);
03428          allowconnect = 1;
03429       } else {
03430          /* Normal lookup / EID query */
03431          pass = has_permission(&p->include, dr->dcontext);
03432          allowconnect = p->model & DUNDI_MODEL_OUTBOUND;
03433       }
03434       if (skip) {
03435          if (!dundi_eid_cmp(skip, &p->eid))
03436             pass = 0;
03437       }
03438       if (pass) {
03439          if (p->order <= order) {
03440             /* Check order first, then check cache, regardless of
03441                omissions, this gets us more likely to not have an
03442                affected answer. */
03443             if((nocache || !(res = cache_lookup(dr, &p->eid, dr->crc32, &dr->expiration)))) {
03444                res = 0;
03445                /* Make sure we haven't already seen it and that it won't
03446                   affect our answer */
03447                for (x=0;avoid[x];x++) {
03448                   if (!dundi_eid_cmp(avoid[x], &p->eid) || !dundi_eid_cmp(avoid[x], &p->us_eid)) {
03449                      /* If not a direct connection, it affects our answer */
03450                      if (directs && !directs[x]) 
03451                         ast_clear_flag_nonstd(dr->hmd, DUNDI_HINT_UNAFFECTED);
03452                      break;
03453                   }
03454                }
03455                /* Make sure we can ask */
03456                if (allowconnect) {
03457                   if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) {
03458                      /* Check for a matching or 0 cache entry */
03459                      append_transaction(dr, p, ttl, avoid);
03460                   } else
03461                      ast_log(LOG_DEBUG, "Avoiding '%s' in transaction\n", dundi_eid_to_str(eid_str, sizeof(eid_str), avoid[x]));
03462                }
03463             }
03464             *foundcache |= res;
03465          } else if (!*skipped || (p->order < *skipped))
03466             *skipped = p->order;
03467       }
03468    }
03469    AST_LIST_UNLOCK(&peers);
03470 }

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

Definition at line 1200 of file pbx_dundi.c.

References ast_copy_string(), cache_lookup_internal(), dundi_request::dcontext, dundi_eid_to_str(), dundi_eid_to_str_short(), dundi_hint_metadata::exten, dundi_request::hmd, dundi_request::number, dundi_request::respcount, and dundi_request::root_eid.

Referenced by build_transactions().

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

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

Definition at line 1128 of file pbx_dundi.c.

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

Referenced by cache_lookup().

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

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

Definition at line 847 of file pbx_dundi.c.

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

Referenced by handle_command_response().

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

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

Definition at line 812 of file pbx_dundi.c.

References ast_db_put(), ast_log(), ast_test_flag_nonstd, dundi_request::crc32, dundi_hint::data, dundi_request::dcontext, dundi_eid_to_str_short(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, LOG_DEBUG, and dundi_request::root_eid.

Referenced by handle_command_response().

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

static void cancel_request ( struct dundi_request dr  )  [static]

Definition at line 3389 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, dr, DUNDI_COMMAND_CANCEL, dundi_send(), dundi_transaction::parent, and dundi_transaction::parentlist.

Referenced by dundi_lookup_internal(), and dundi_precache_internal().

03390 {
03391    struct dundi_transaction *trans;
03392 
03393    AST_LIST_LOCK(&peers);
03394    while ((trans = AST_LIST_REMOVE_HEAD(&dr->trans, parentlist))) {
03395       /* Orphan transaction from request */
03396       trans->parent = NULL;
03397       /* Send final cancel */
03398       dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
03399    }
03400    AST_LIST_UNLOCK(&peers);
03401 }

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

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

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

static void check_password ( void   )  [static]

Definition at line 2132 of file pbx_dundi.c.

References ast_copy_string(), build_secret(), and save_secret().

Referenced by network_thread().

02133 {
02134    char oldsecret[80];
02135    time_t now;
02136    
02137    time(&now); 
02138 #if 0
02139    printf("%ld/%ld\n", now, rotatetime);
02140 #endif
02141    if ((now - rotatetime) >= 0) {
02142       /* Time to rotate keys */
02143       ast_copy_string(oldsecret, cursecret, sizeof(oldsecret));
02144       build_secret(cursecret, sizeof(cursecret));
02145       save_secret(cursecret, oldsecret);
02146    }
02147 }

static int check_request ( struct dundi_request dr  )  [static]

Definition at line 3510 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dr, and dundi_request::list.

Referenced by dundi_lookup_internal().

03511 {
03512    struct dundi_request *cur;
03513 
03514    AST_LIST_LOCK(&peers);
03515    AST_LIST_TRAVERSE(&requests, cur, list) {
03516       if (cur == dr)
03517          break;
03518    }
03519    AST_LIST_UNLOCK(&peers);
03520    
03521    return cur ? 1 : 0;
03522 }

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

Definition at line 2360 of file pbx_dundi.c.

References complete_peer_helper().

02361 {
02362    return complete_peer_helper(line, word, pos, state, 3);
02363 }

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

Definition at line 2338 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, dundi_eid_to_str(), dundi_peer::eid, len(), dundi_peer::list, and s.

Referenced by complete_peer_4().

02339 {
02340    int which=0, len;
02341    char *ret = NULL;
02342    struct dundi_peer *p;
02343    char eid_str[20];
02344 
02345    if (pos != rpos)
02346       return NULL;
02347    AST_LIST_LOCK(&peers);
02348    len = strlen(word);
02349    AST_LIST_TRAVERSE(&peers, p, list) {
02350       const char *s = dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid);
02351       if (!strncasecmp(word, s, len) && ++which > state) {
02352          ret = ast_strdup(s);
02353          break;
02354       }
02355    }
02356    AST_LIST_UNLOCK(&peers);
02357    return ret;
02358 }

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

Definition at line 2868 of file pbx_dundi.c.

References dundi_peer::addr, dundi_transaction::all, apply_peer(), ast_calloc, AST_LIST_INSERT_HEAD, ast_set_flag, ast_tvnow(), DUNDI_DEFAULT_RETRANS_TIMER, FLAG_SENDFULLKEY, FLAG_STOREHIST, get_trans_id(), and dundi_peer::sentfullkey.

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

02869 {
02870    struct dundi_transaction *trans;
02871    int tid;
02872    
02873    /* Don't allow creation of transactions to non-registered peers */
02874    if (p && !p->addr.sin_addr.s_addr)
02875       return NULL;
02876    tid = get_trans_id();
02877    if (tid < 1)
02878       return NULL;
02879    trans = ast_calloc(1, sizeof(*trans));
02880    if (trans) {
02881       if (global_storehistory) {
02882          trans->start = ast_tvnow();
02883          ast_set_flag(trans, FLAG_STOREHIST);
02884       }
02885       trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
02886       trans->autokillid = -1;
02887       if (p) {
02888          apply_peer(trans, p);
02889          if (!p->sentfullkey)
02890             ast_set_flag(trans, FLAG_SENDFULLKEY);
02891       }
02892       trans->strans = tid;
02893       AST_LIST_INSERT_HEAD(&alltrans, trans, all);
02894    }
02895    return trans;
02896 }

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

Definition at line 1343 of file pbx_dundi.c.

References aes_decrypt().

Referenced by dundi_decrypt().

01344 {
01345    unsigned char lastblock[16];
01346    int x;
01347    memcpy(lastblock, iv, sizeof(lastblock));
01348    while(len > 0) {
01349       aes_decrypt(src, dst, dcx);
01350       for (x=0;x<16;x++)
01351          dst[x] ^= lastblock[x];
01352       memcpy(lastblock, src, sizeof(lastblock));
01353       dst += 16;
01354       src += 16;
01355       len -= 16;
01356    }
01357    return 0;
01358 }

static void deep_copy_peer ( struct dundi_peer peer_dst,
const struct dundi_peer peer_src 
) [static]

Definition at line 1505 of file pbx_dundi.c.

References permission::allow, ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, dundi_peer::include, permission::list, permission::name, and dundi_peer::permit.

Referenced by handle_command_response().

01506 {
01507    struct permission *cur, *perm;
01508 
01509    memcpy(peer_dst, peer_src, sizeof(*peer_dst));
01510    
01511    memset(&peer_dst->permit, 0, sizeof(peer_dst->permit));
01512    memset(&peer_dst->include, 0, sizeof(peer_dst->permit));
01513 
01514    AST_LIST_TRAVERSE(&peer_src->permit, cur, list) {
01515       if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1)))
01516          continue;
01517 
01518       perm->allow = cur->allow;
01519       strcpy(perm->name, cur->name);
01520 
01521       AST_LIST_INSERT_HEAD(&peer_dst->permit, perm, list);
01522    }
01523 
01524    AST_LIST_TRAVERSE(&peer_src->include, cur, list) {
01525       if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1)))
01526          continue;
01527 
01528       perm->allow = cur->allow;
01529       strcpy(perm->name, cur->name);
01530 
01531       AST_LIST_INSERT_HEAD(&peer_dst->include, perm, list);
01532    }
01533 }

static void destroy_map ( struct dundi_mapping map  )  [static]

Definition at line 3955 of file pbx_dundi.c.

References free, and map.

Referenced by prune_mappings().

03956 {
03957    free(map);
03958 }

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

Definition at line 2914 of file pbx_dundi.c.

References AST_LIST_REMOVE, AST_SCHED_DEL, free, dundi_transaction::packets, dundi_packet::parent, dundi_packet::retransid, and sched.

Referenced by ack_trans().

02915 {
02916    if (pack->parent)
02917       AST_LIST_REMOVE(&pack->parent->packets, pack, list);
02918    AST_SCHED_DEL(sched, pack->retransid);
02919    if (needfree)
02920       free(pack);
02921 }

static void destroy_packets ( struct packetlist *  p  )  [static]

Definition at line 1964 of file pbx_dundi.c.

References AST_LIST_REMOVE_HEAD, AST_SCHED_DEL, free, dundi_packet::list, dundi_packet::retransid, and sched.

Referenced by ack_trans(), and handle_frame().

01965 {
01966    struct dundi_packet *pack;
01967    
01968    while ((pack = AST_LIST_REMOVE_HEAD(p, list))) {
01969       AST_SCHED_DEL(sched, pack->retransid);
01970       free(pack);
01971    }
01972 }

static void destroy_peer ( struct dundi_peer peer  )  [static]

Definition at line 3944 of file pbx_dundi.c.

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

Referenced by prune_peers().

03945 {
03946    AST_SCHED_DEL(sched, peer->registerid);
03947    if (peer->regtrans)
03948       destroy_trans(peer->regtrans, 0);
03949    AST_SCHED_DEL(sched, peer->qualifyid);
03950    destroy_permissions(&peer->permit);
03951    destroy_permissions(&peer->include);
03952    free(peer);
03953 }

static void destroy_permissions ( struct permissionlist *  permlist  )  [static]

Definition at line 3936 of file pbx_dundi.c.

References AST_LIST_REMOVE_HEAD, free, and permission::list.

Referenced by build_peer(), and destroy_peer().

03937 {
03938    struct permission *perm;
03939 
03940    while ((perm = AST_LIST_REMOVE_HEAD(permlist, list)))
03941       free(perm);
03942 }

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

Definition at line 2923 of file pbx_dundi.c.

References AST_LIST_TRAVERSE, ast_log(), ast_malloc, ast_strlen_zero(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), 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::lastms, dundi_peer::list, LOG_NOTICE, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::maxms, dundi_request::number, dundi_transaction::parent, 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().

02924 {
02925    struct dundi_peer *peer;
02926    int ms;
02927    int x;
02928    int cnt;
02929    char eid_str[20];
02930    if (ast_test_flag(trans, FLAG_ISREG | FLAG_ISQUAL | FLAG_STOREHIST)) {
02931       AST_LIST_TRAVERSE(&peers, peer, list) {
02932          if (peer->regtrans == trans)
02933             peer->regtrans = NULL;
02934          if (peer->qualtrans == trans) {
02935             if (fromtimeout) {
02936                if (peer->lastms > -1)
02937                   ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
02938                peer->lastms = -1;
02939             } else {
02940                ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx);
02941                if (ms < 1)
02942                   ms = 1;
02943                if (ms < peer->maxms) {
02944                   if ((peer->lastms >= peer->maxms) || (peer->lastms < 0))
02945                      ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
02946                } else if (peer->lastms < peer->maxms) {
02947                   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);
02948                }
02949                peer->lastms = ms;
02950             }
02951             peer->qualtrans = NULL;
02952          }
02953          if (ast_test_flag(trans, FLAG_STOREHIST)) {
02954             if (trans->parent && !ast_strlen_zero(trans->parent->number)) {
02955                if (!dundi_eid_cmp(&trans->them_eid, &peer->eid)) {
02956                   peer->avgms = 0;
02957                   cnt = 0;
02958                   if (peer->lookups[DUNDI_TIMING_HISTORY-1])
02959                      free(peer->lookups[DUNDI_TIMING_HISTORY-1]);
02960                   for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) {
02961                      peer->lookuptimes[x] = peer->lookuptimes[x-1];
02962                      peer->lookups[x] = peer->lookups[x-1];
02963                      if (peer->lookups[x]) {
02964                         peer->avgms += peer->lookuptimes[x];
02965                         cnt++;
02966                      }
02967                   }
02968                   peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start);
02969                   peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2);
02970                   if (peer->lookups[0]) {
02971                      sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext);
02972                      peer->avgms += peer->lookuptimes[0];
02973                      cnt++;
02974                   }
02975                   if (cnt)
02976                      peer->avgms /= cnt;
02977                }
02978             }
02979          }
02980       }
02981    }
02982    if (trans->parent) {
02983       /* Unlink from parent if appropriate */
02984       AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist);
02985       if (AST_LIST_EMPTY(&trans->parent->trans)) {
02986          /* Wake up sleeper */
02987          if (trans->parent->pfds[1] > -1) {
02988             if (write(trans->parent->pfds[1], "killa!", 6) < 0) {
02989                ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
02990             }
02991          }
02992       }
02993    }
02994    /* Unlink from all trans */
02995    AST_LIST_REMOVE(&alltrans, trans, all);
02996    destroy_packets(&trans->packets);
02997    destroy_packets(&trans->lasttrans);
02998    AST_SCHED_DEL(sched, trans->autokillid);
02999    if (trans->thread) {
03000       /* If used by a thread, mark as dead and be done */
03001       ast_set_flag(trans, FLAG_DEAD);
03002    } else
03003       free(trans);
03004 }

static int discover_transactions ( struct dundi_request dr  )  [static]

Definition at line 3245 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dr, dundi_discover(), and dundi_transaction::parentlist.

Referenced by dundi_lookup_internal().

03246 {
03247    struct dundi_transaction *trans;
03248    AST_LIST_LOCK(&peers);
03249    AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
03250       dundi_discover(trans);
03251    }
03252    AST_LIST_UNLOCK(&peers);
03253    return 0;
03254 }

static int do_autokill ( const void *  data  )  [static]

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

03101 {
03102    struct dundi_transaction *trans = (struct dundi_transaction *)data;
03103    char eid_str[20];
03104    ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n", 
03105       dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
03106    trans->autokillid = -1;
03107    destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */
03108    return 0;
03109 }

static int do_qualify ( const void *  data  )  [static]

Definition at line 4101 of file pbx_dundi.c.

References qualify_peer(), and dundi_peer::qualifyid.

Referenced by qualify_peer().

04102 {
04103    struct dundi_peer *peer = (struct dundi_peer *)data;
04104    peer->qualifyid = -1;
04105    qualify_peer(peer, 0);
04106    return 0;
04107 }

static int do_register ( const void *  data  )  [static]

Definition at line 4075 of file pbx_dundi.c.

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

04076 {
04077    struct dundi_ie_data ied;
04078    struct dundi_peer *peer = (struct dundi_peer *)data;
04079    char eid_str[20];
04080    char eid_str2[20];
04081    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));
04082    peer->registerid = ast_sched_add(sched, default_expiration * 1000, do_register, data);
04083    /* Destroy old transaction if there is one */
04084    if (peer->regtrans)
04085       destroy_trans(peer->regtrans, 0);
04086    peer->regtrans = create_transaction(peer);
04087    if (peer->regtrans) {
04088       ast_set_flag(peer->regtrans, FLAG_ISREG);
04089       memset(&ied, 0, sizeof(ied));
04090       dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
04091       dundi_ie_append_eid(&ied, DUNDI_IE_EID, &peer->regtrans->us_eid);
04092       dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, default_expiration);
04093       dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied);
04094       
04095    } else
04096       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));
04097 
04098    return 0;
04099 }

static int do_register_expire ( const void *  data  )  [static]

Note:
Called with the peers list already locked

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

01278 {
01279    struct dundi_peer *peer = (struct dundi_peer *)data;
01280    char eid_str[20];
01281    ast_log(LOG_DEBUG, "Register expired for '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
01282    peer->registerexpire = -1;
01283    peer->lastms = 0;
01284    memset(&peer->addr, 0, sizeof(peer->addr));
01285    return 0;
01286 }

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

Definition at line 375 of file pbx_dundi.c.

References DUNDI_COMMAND_ACK, and dundi_send().

Referenced by handle_frame().

00376 {
00377    return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL);
00378 }

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

Definition at line 752 of file pbx_dundi.c.

References ast_calloc, ast_copy_string(), ast_log(), ast_pthread_create, dundi_query_state::called_context, DUNDI_CAUSE_GENERAL, DUNDI_COMMAND_EIDRESPONSE, dundi_eid_cmp(), dundi_eid_to_str(), dundi_ie_append_cause(), DUNDI_IE_CAUSE, dundi_query_thread(), dundi_send(), dundi_query_state::eids, dundi_query_state::fluffy, free, ies, LOG_DEBUG, LOG_WARNING, dundi_query_state::reqeid, s, dundi_transaction::thread, dundi_query_state::trans, and dundi_query_state::ttl.

Referenced by handle_command_response().

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

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

Definition at line 1040 of file pbx_dundi.c.

References ast_calloc, ast_copy_string(), AST_LIST_TRAVERSE, ast_log(), ast_pthread_create, dundi_query_state::called_context, dundi_query_state::called_number, dundi_mapping::dcontext, dundi_query_state::directs, DUNDI_CAUSE_GENERAL, DUNDI_COMMAND_DPRESPONSE, dundi_eid_cmp(), dundi_ie_append_cause(), DUNDI_IE_CAUSE, dundi_lookup_thread(), dundi_send(), dundi_query_state::eids, dundi_query_state::fluffy, free, ies, dundi_mapping::list, permission::list, LOG_DEBUG, LOG_WARNING, dundi_query_state::maps, dundi_mapping::next, dundi_query_state::nocache, dundi_query_state::nummaps, s, dundi_transaction::thread, dundi_query_state::trans, and dundi_query_state::ttl.

Referenced by handle_command_response().

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

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 4346 of file pbx_dundi.c.

References DUNDI_FLAG_CANMATCH, and dundi_helper().

04347 {
04348    return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH);
04349 }

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

Definition at line 279 of file pbx_dundi.c.

References ast_verbose().

Referenced by load_module().

00280 {
00281    if (dundidebug)
00282       ast_verbose("%s", data);
00283 }

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 1360 of file pbx_dundi.c.

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

01361 {
01362    int space = *dstlen;
01363    unsigned long bytes;
01364    struct dundi_hdr *h;
01365    unsigned char *decrypt_space;
01366    decrypt_space = alloca(srclen);
01367    if (!decrypt_space)
01368       return NULL;
01369    decrypt_memcpy(decrypt_space, src->encdata, srclen, src->iv, &trans->dcx);
01370    /* Setup header */
01371    h = (struct dundi_hdr *)dst;
01372    *h = *ohdr;
01373    bytes = space - 6;
01374    if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) {
01375       ast_log(LOG_DEBUG, "Ouch, uncompress failed :(\n");
01376       return NULL;
01377    }
01378    /* Update length */
01379    *dstlen = bytes + 6;
01380    /* Return new header */
01381    return h;
01382 }

static int dundi_discover ( struct dundi_transaction trans  )  [static]

Definition at line 3133 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, sched, dundi_transaction::ttl, and dundi_transaction::us_eid.

Referenced by discover_transactions().

03134 {
03135    struct dundi_ie_data ied;
03136    int x;
03137    if (!trans->parent) {
03138       ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
03139       return -1;
03140    }
03141    memset(&ied, 0, sizeof(ied));
03142    dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
03143    if (!dundi_eid_zero(&trans->us_eid))
03144       dundi_ie_append_eid(&ied, DUNDI_IE_EID_DIRECT, &trans->us_eid);
03145    for (x=0;x<trans->eidcount;x++)
03146       dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid);
03147    dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number);
03148    dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext);
03149    dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
03150    if (trans->parent->cbypass)
03151       dundi_ie_append(&ied, DUNDI_IE_CACHEBYPASS);
03152    if (trans->autokilltimeout)
03153       trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
03154    return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied);
03155 }

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

Definition at line 2255 of file pbx_dundi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02256 {
02257    if (argc != 2)
02258       return RESULT_SHOWUSAGE;
02259    dundidebug = 1;
02260    ast_cli(fd, "DUNDi Debugging Enabled\n");
02261    return RESULT_SUCCESS;
02262 }

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

Definition at line 2382 of file pbx_dundi.c.

References ast_cli(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), dr, dundi_flags2str(), dundi_lookup(), MAX_RESULTS, RESULT_SHOWUSAGE, RESULT_SUCCESS, and sort_results().

02383 {
02384    int res;
02385    char tmp[256];
02386    char fs[80] = "";
02387    char *context;
02388    int x;
02389    int bypass = 0;
02390    struct dundi_result dr[MAX_RESULTS];
02391    struct timeval start;
02392    if ((argc < 3) || (argc > 4))
02393       return RESULT_SHOWUSAGE;
02394    if (argc > 3) {
02395       if (!strcasecmp(argv[3], "bypass"))
02396          bypass=1;
02397       else
02398          return RESULT_SHOWUSAGE;
02399    }
02400    ast_copy_string(tmp, argv[2], sizeof(tmp));
02401    context = strchr(tmp, '@');
02402    if (context) {
02403       *context = '\0';
02404       context++;
02405    }
02406    start = ast_tvnow();
02407    res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
02408    
02409    if (res < 0) 
02410       ast_cli(fd, "DUNDi lookup returned error.\n");
02411    else if (!res) 
02412       ast_cli(fd, "DUNDi lookup returned no results.\n");
02413    else
02414       sort_results(dr, res);
02415    for (x=0;x<res;x++) {
02416       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));
02417       ast_cli(fd, "     from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration);
02418    }
02419    ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
02420    return RESULT_SUCCESS;
02421 }

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

Definition at line 2423 of file pbx_dundi.c.

References ast_cli(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), dundi_precache(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02424 {
02425    int res;
02426    char tmp[256];
02427    char *context;
02428    struct timeval start;
02429    if ((argc < 3) || (argc > 3))
02430       return RESULT_SHOWUSAGE;
02431    ast_copy_string(tmp, argv[2], sizeof(tmp));
02432    context = strchr(tmp, '@');
02433    if (context) {
02434       *context = '\0';
02435       context++;
02436    }
02437    start = ast_tvnow();
02438    res = dundi_precache(context, tmp);
02439    
02440    if (res < 0) 
02441       ast_cli(fd, "DUNDi precache returned error.\n");
02442    else if (!res) 
02443       ast_cli(fd, "DUNDi precache returned no error.\n");
02444    ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
02445    return RESULT_SUCCESS;
02446 }

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

Definition at line 2448 of file pbx_dundi.c.

References ast_cli(), ast_copy_string(), 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.

02449 {
02450    int res;
02451    char tmp[256];
02452    char *context;
02453    dundi_eid eid;
02454    struct dundi_entity_info dei;
02455    if ((argc < 3) || (argc > 3))
02456       return RESULT_SHOWUSAGE;
02457    if (dundi_str_to_eid(&eid, argv[2])) {
02458       ast_cli(fd, "'%s' is not a valid EID!\n", argv[2]);
02459       return RESULT_SHOWUSAGE;
02460    }
02461    ast_copy_string(tmp, argv[2], sizeof(tmp));
02462    context = strchr(tmp, '@');
02463    if (context) {
02464       *context = '\0';
02465       context++;
02466    }
02467    res = dundi_query_eid(&dei, context, eid);
02468    if (res < 0) 
02469       ast_cli(fd, "DUNDi Query EID returned error.\n");
02470    else if (!res) 
02471       ast_cli(fd, "DUNDi Query EID returned no results.\n");
02472    else {
02473       ast_cli(fd, "DUNDi Query EID succeeded:\n");
02474       ast_cli(fd, "Department:      %s\n", dei.orgunit);
02475       ast_cli(fd, "Organization:    %s\n", dei.org);
02476       ast_cli(fd, "City/Locality:   %s\n", dei.locality);
02477       ast_cli(fd, "State/Province:  %s\n", dei.stateprov);
02478       ast_cli(fd, "Country:         %s\n", dei.country);
02479       ast_cli(fd, "E-mail:          %s\n", dei.email);
02480       ast_cli(fd, "Phone:           %s\n", dei.phone);
02481       ast_cli(fd, "IP Address:      %s\n", dei.ipaddr);
02482    }
02483    return RESULT_SUCCESS;
02484 }

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

Definition at line 2264 of file pbx_dundi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02265 {
02266    if (argc != 3)
02267       return RESULT_SHOWUSAGE;
02268    global_storehistory = 1;
02269    ast_cli(fd, "DUNDi History Storage Enabled\n");
02270    return RESULT_SUCCESS;
02271 }

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

Definition at line 1384 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, len(), 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().

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

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

Definition at line 285 of file pbx_dundi.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

00286 {
00287    ast_log(LOG_WARNING, "%s", data);
00288 }

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

Definition at line 4351 of file pbx_dundi.c.

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

04352 {
04353    struct dundi_result results[MAX_RESULTS];
04354    int res;
04355    int x=0;
04356    char req[1024];
04357    struct ast_app *dial;
04358    
04359    if (!strncasecmp(context, "macro-", 6)) {
04360       if (!chan) {   
04361          ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
04362          return -1;
04363       }
04364       /* If done as a macro, use macro extension */
04365       if (!strcasecmp(exten, "s")) {
04366          exten = pbx_builtin_getvar_helper(chan, "ARG1");
04367          if (ast_strlen_zero(exten))
04368             exten = chan->macroexten;
04369          if (ast_strlen_zero(exten))
04370             exten = chan->exten;
04371          if (ast_strlen_zero(exten)) { 
04372             ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
04373             return -1;
04374          }
04375       }
04376       if (ast_strlen_zero(data))
04377          data = "e164";
04378    } else {
04379       if (ast_strlen_zero(data))
04380          data = context;
04381    }
04382    res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
04383    if (res > 0) {
04384       sort_results(results, res);
04385       for (x=0;x<res;x++) {
04386          if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) {
04387             if (!--priority)
04388                break;
04389          }
04390       }
04391    }
04392    if (x < res) {
04393       /* Got a hit! */
04394       snprintf(req, sizeof(req), "%s/%s", results[x].tech, results[x].dest);
04395       dial = pbx_findapp("Dial");
04396       if (dial)
04397          res = pbx_exec(chan, dial, req);
04398    } else
04399       res = -1;
04400    return res;
04401 }

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 4341 of file pbx_dundi.c.

References DUNDI_FLAG_EXISTS, and dundi_helper().

04342 {
04343    return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS);
04344 }

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

Definition at line 2273 of file pbx_dundi.c.

References ast_cli(), ast_db_deltree(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_peer::avgms, DUNDI_TIMING_HISTORY, free, dundi_peer::list, dundi_peer::lookups, dundi_peer::lookuptimes, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02274 {
02275    int stats = 0;
02276    if ((argc < 2) || (argc > 3))
02277       return RESULT_SHOWUSAGE;
02278    if (argc > 2) {
02279       if (!strcasecmp(argv[2], "stats"))
02280          stats = 1;
02281       else
02282          return RESULT_SHOWUSAGE;
02283    }
02284    if (stats) {
02285       /* Flush statistics */
02286       struct dundi_peer *p;
02287       int x;
02288       AST_LIST_LOCK(&peers);
02289       AST_LIST_TRAVERSE(&peers, p, list) {
02290          for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
02291             if (p->lookups[x])
02292                free(p->lookups[x]);
02293             p->lookups[x] = NULL;
02294             p->lookuptimes[x] = 0;
02295          }
02296          p->avgms = 0;
02297       }
02298       AST_LIST_UNLOCK(&peers);
02299    } else {
02300       ast_db_deltree("dundi/cache", NULL);
02301       ast_cli(fd, "DUNDi Cache Flushed\n");
02302    }
02303    return RESULT_SUCCESS;
02304 }

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 4302 of file pbx_dundi.c.

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

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

04303 {
04304    struct dundi_result results[MAX_RESULTS];
04305    int res;
04306    int x;
04307    int found = 0;
04308    if (!strncasecmp(context, "macro-", 6)) {
04309       if (!chan) {   
04310          ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
04311          return -1;
04312       }
04313       /* If done as a macro, use macro extension */
04314       if (!strcasecmp(exten, "s")) {
04315          exten = pbx_builtin_getvar_helper(chan, "ARG1");
04316          if (ast_strlen_zero(exten))
04317             exten = chan->macroexten;
04318          if (ast_strlen_zero(exten))
04319             exten = chan->exten;
04320          if (ast_strlen_zero(exten)) { 
04321             ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
04322             return -1;
04323          }
04324       }
04325       if (ast_strlen_zero(data))
04326          data = "e164";
04327    } else {
04328       if (ast_strlen_zero(data))
04329          data = context;
04330    }
04331    res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
04332    for (x=0;x<res;x++) {
04333       if (ast_test_flag(results + x, flag))
04334          found++;
04335    }
04336    if (found >= priority)
04337       return 1;
04338    return 0;
04339 }

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

Definition at line 3111 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_eid_cmp(), dundi_ie_append_eid(), DUNDI_IE_EID, DUNDI_IE_EID_DIRECT, dundi_peer::eid, has_permission(), dundi_peer::include, and dundi_peer::list.

Referenced by dundi_discover().

03112 {
03113    struct dundi_peer *p;
03114    if (!dundi_eid_cmp(eid, us)) {
03115       dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid);
03116       return;
03117    }
03118    AST_LIST_LOCK(&peers);
03119    AST_LIST_TRAVERSE(&peers, p, list) {
03120       if (!dundi_eid_cmp(&p->eid, eid)) {
03121          if (has_permission(&p->include, context))
03122             dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid);
03123          else
03124             dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
03125          break;
03126       }
03127    }
03128    if (!p)
03129       dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
03130    AST_LIST_UNLOCK(&peers);
03131 }

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 3641 of file pbx_dundi.c.

References DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, and dundi_lookup_internal().

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

03642 {
03643    struct dundi_hint_metadata hmd;
03644    dundi_eid *avoid[1] = { NULL, };
03645    int direct[1] = { 0, };
03646    int expiration = dundi_cache_time;
03647    memset(&hmd, 0, sizeof(hmd));
03648    hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED;
03649    return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct);
03650 }

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 3539 of file pbx_dundi.c.

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

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

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

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 528 of file pbx_dundi.c.

References ast_canmatch_extension(), ast_clear_flag, ast_clear_flag_nonstd, ast_copy_flags, ast_copy_string(), ast_exists_extension(), AST_FLAGS_ALL, ast_ignore_pattern(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_matchmore_extension(), AST_MAX_EXTENSION, ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_var_assign(), ast_var_delete(), dr, dundi_eid_to_str(), DUNDI_FLAG_CANMATCH, DUNDI_FLAG_EXISTS, DUNDI_FLAG_IGNOREPAT, DUNDI_FLAG_INTERNAL_NOPARTIAL, DUNDI_FLAG_MATCHMORE, DUNDI_HINT_DONT_ASK, ast_var_t::entries, ast_flags::flags, map, pbx_substitute_variables_varshead(), and tech2str().

Referenced by dundi_lookup_thread(), and precache_trans().

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

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

Definition at line 601 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_test_flag, ast_test_flag_nonstd, dundi_query_state::called_context, dundi_query_state::called_number, destroy_trans(), dundi_query_state::directs, dr, DUNDI_CAUSE_DUPLICATE, DUNDI_COMMAND_DPRESPONSE, dundi_eid_to_str(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, DUNDI_IE_ANSWER, dundi_ie_append_answer(), dundi_ie_append_cause(), dundi_ie_append_hint(), dundi_ie_append_short(), DUNDI_IE_CAUSE, DUNDI_IE_EXPIRATION, DUNDI_IE_HINT, dundi_lookup_internal(), dundi_lookup_local(), dundi_send(), dundi_query_state::eids, FLAG_DEAD, 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().

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

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 4403 of file pbx_dundi.c.

References DUNDI_FLAG_MATCHMORE, and dundi_helper().

04404 {
04405    return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE);
04406 }

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

Definition at line 2306 of file pbx_dundi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02307 {
02308    if (argc != 3)
02309       return RESULT_SHOWUSAGE;
02310    dundidebug = 0;
02311    ast_cli(fd, "DUNDi Debugging Disabled\n");
02312    return RESULT_SUCCESS;
02313 }

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

Definition at line 2315 of file pbx_dundi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02316 {
02317    if (argc != 4)
02318       return RESULT_SHOWUSAGE;
02319    global_storehistory = 0;
02320    ast_cli(fd, "DUNDi History Storage Disabled\n");
02321    return RESULT_SUCCESS;
02322 }

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

Pre-cache to push upstream peers.

Definition at line 3788 of file pbx_dundi.c.

References dundi_precache_internal().

Referenced by dundi_do_precache(), and process_precache().

03789 {
03790    dundi_eid *avoid[1] = { NULL, };
03791    return dundi_precache_internal(context, number, dundi_ttl, avoid);
03792 }

static void dundi_precache_full ( void   )  [static]

Definition at line 3688 of file pbx_dundi.c.

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

Referenced by set_config().

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

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

Definition at line 3715 of file pbx_dundi.c.

References ast_copy_string(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor_n_fd(), build_transactions(), cancel_request(), dr, DUNDI_FLUFF_TIME, DUNDI_TTL_TIME, errno, dundi_mapping::list, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, MAX_RESULTS, optimize_transactions(), precache_transactions(), and reschedule_precache().

Referenced by dundi_precache(), and dundi_precache_thread().

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

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

Definition at line 665 of file pbx_dundi.c.

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

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

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

Definition at line 888 of file pbx_dundi.c.

References ast_clear_flag_nonstd, ast_copy_string(), dundi_result::dest, dundi_request::dr, dr, 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().

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

static int dundi_query ( struct dundi_transaction trans  )  [static]

Definition at line 3223 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, sched, dundi_transaction::ttl, and dundi_transaction::us_eid.

Referenced by query_transactions().

03224 {
03225    struct dundi_ie_data ied;
03226    int x;
03227    if (!trans->parent) {
03228       ast_log(LOG_WARNING, "Tried to query a transaction with no parent?!?\n");
03229       return -1;
03230    }
03231    memset(&ied, 0, sizeof(ied));
03232    dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
03233    if (!dundi_eid_zero(&trans->us_eid))
03234       dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
03235    for (x=0;x<trans->eidcount;x++)
03236       dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
03237    dundi_ie_append_eid(&ied, DUNDI_IE_REQEID, &trans->parent->query_eid);
03238    dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext);
03239    dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
03240    if (trans->autokilltimeout)
03241       trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
03242    return dundi_send(trans, DUNDI_COMMAND_EIDQUERY, 0, 0, &ied);
03243 }

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

Retrieve information on a specific EID.

Definition at line 3841 of file pbx_dundi.c.

References dundi_query_eid_internal().

Referenced by dundi_do_query().

03842 {
03843    dundi_eid *avoid[1] = { NULL, };
03844    struct dundi_hint_metadata hmd;
03845    memset(&hmd, 0, sizeof(hmd));
03846    return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid);
03847 }

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 3794 of file pbx_dundi.c.

References ast_copy_string(), AST_LIST_EMPTY, ast_set_flag_nonstd, ast_tvdiff_ms(), ast_tvnow(), 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().

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

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

Definition at line 698 of file pbx_dundi.c.

References ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_strlen_zero(), ast_test_flag, dundi_query_state::called_context, dundi_query_state::called_number, destroy_trans(), DUNDI_COMMAND_EIDRESPONSE, dundi_eid_cmp(), dundi_eid_to_str(), dundi_ie_append_hint(), dundi_ie_append_str(), DUNDI_IE_COUNTRY, DUNDI_IE_DEPARTMENT, DUNDI_IE_EMAIL, DUNDI_IE_HINT, DUNDI_IE_IPADDR, DUNDI_IE_LOCALITY, DUNDI_IE_ORGANIZATION, DUNDI_IE_PHONE, DUNDI_IE_STATE_PROV, dundi_query_eid_internal(), dundi_send(), dundi_query_state::eids, FLAG_DEAD, free, LOG_DEBUG, dundi_query_state::reqeid, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, and dundi_transaction::us_eid.

Referenced by dundi_answer_entity().

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

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

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

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

static int dundi_rexmit ( const void *  data  )  [static]

Definition at line 3006 of file pbx_dundi.c.

References dundi_transaction::addr, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), 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().

03007 {
03008    struct dundi_packet *pack = (struct dundi_packet *)data;
03009    int res;
03010    AST_LIST_LOCK(&peers);
03011    if (pack->retrans < 1) {
03012       pack->retransid = -1;
03013       if (!ast_test_flag(pack->parent, FLAG_ISQUAL))
03014          ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n", 
03015             ast_inet_ntoa(pack->parent->addr.sin_addr), 
03016             ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans));
03017       destroy_trans(pack->parent, 1);
03018       res = 0;
03019    } else {
03020       /* Decrement retransmission, try again */
03021       pack->retrans--;
03022       dundi_xmit(pack);
03023       res = 1;
03024    }
03025    AST_LIST_UNLOCK(&peers);
03026    return res;
03027 }

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

Definition at line 3029 of file pbx_dundi.c.

References dundi_transaction::addr, dundi_transaction::aseqno, ast_calloc, AST_LIST_INSERT_HEAD, ast_log(), ast_sched_add(), ast_set_flag, ast_test_flag, dundi_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(), FLAG_ENCRYPT, FLAG_FINAL, free, dundi_packet::h, dundi_hdr::ies, dundi_transaction::iseqno, dundi_hdr::iseqno, len(), dundi_packet::list, LOG_NOTICE, dundi_transaction::oseqno, dundi_hdr::oseqno, dundi_transaction::packets, dundi_packet::parent, dundi_packet::retrans, dundi_packet::retransid, dundi_transaction::retranstimer, sched, 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().

03030 {
03031    struct dundi_packet *pack;
03032    int res;
03033    int len;
03034    char eid_str[20];
03035    len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0);
03036    /* Reserve enough space for encryption */
03037    if (ast_test_flag(trans, FLAG_ENCRYPT))
03038       len += 384;
03039    pack = ast_calloc(1, len);
03040    if (pack) {
03041       pack->h = (struct dundi_hdr *)(pack->data);
03042       if (cmdresp != DUNDI_COMMAND_ACK) {
03043          pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack);
03044          pack->retrans = DUNDI_DEFAULT_RETRANS - 1;
03045          AST_LIST_INSERT_HEAD(&trans->packets, pack, list);
03046       }
03047       pack->parent = trans;
03048       pack->h->strans = htons(trans->strans);
03049       pack->h->dtrans = htons(trans->dtrans);
03050       pack->h->iseqno = trans->iseqno;
03051       pack->h->oseqno = trans->oseqno;
03052       pack->h->cmdresp = cmdresp;
03053       pack->datalen = sizeof(struct dundi_hdr);
03054       if (ied) {
03055          memcpy(pack->h->ies, ied->buf, ied->pos);
03056          pack->datalen += ied->pos;
03057       } 
03058       if (final) {
03059          pack->h->cmdresp |= DUNDI_COMMAND_FINAL;
03060          ast_set_flag(trans, FLAG_FINAL);
03061       }
03062       pack->h->cmdflags = flags;
03063       if (cmdresp != DUNDI_COMMAND_ACK) {
03064          trans->oseqno++;
03065          trans->oseqno = trans->oseqno % 256;
03066       }
03067       trans->aseqno = trans->iseqno;
03068       /* If we have their public key, encrypt */
03069       if (ast_test_flag(trans, FLAG_ENCRYPT)) {
03070          switch(cmdresp) {
03071          case DUNDI_COMMAND_REGREQ:
03072          case DUNDI_COMMAND_REGRESPONSE:
03073          case DUNDI_COMMAND_DPDISCOVER:
03074          case DUNDI_COMMAND_DPRESPONSE:
03075          case DUNDI_COMMAND_EIDQUERY:
03076          case DUNDI_COMMAND_EIDRESPONSE:
03077          case DUNDI_COMMAND_PRECACHERQ:
03078          case DUNDI_COMMAND_PRECACHERP:
03079             if (dundidebug)
03080                dundi_showframe(pack->h, 2, &trans->addr, pack->datalen - sizeof(struct dundi_hdr));
03081             res = dundi_encrypt(trans, pack);
03082             break;
03083          default:
03084             res = 0;
03085          }
03086       } else 
03087          res = 0;
03088       if (!res) 
03089          res = dundi_xmit(pack);
03090       if (res)
03091          ast_log(LOG_NOTICE, "Failed to send packet to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
03092             
03093       if (cmdresp == DUNDI_COMMAND_ACK)
03094          free(pack);
03095       return res;
03096    }
03097    return -1;
03098 }

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

Definition at line 2653 of file pbx_dundi.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_UNLOCK, dundi_eid_to_str(), global_eid, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02654 {
02655    char eid_str[20];
02656    if (argc != 3)
02657       return RESULT_SHOWUSAGE;
02658    AST_LIST_LOCK(&peers);
02659    dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid);
02660    AST_LIST_UNLOCK(&peers);
02661    ast_cli(fd, "Global EID for this system is '%s'\n", eid_str);
02662    return RESULT_SUCCESS;
02663 }

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

Definition at line 2687 of file pbx_dundi.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), dundi_flags2str(), FORMAT, FORMAT2, dundi_mapping::list, map, RESULT_SHOWUSAGE, RESULT_SUCCESS, and tech2str().

02688 {
02689 #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
02690 #define FORMAT "%-12.12s %-7d %-12.12s %-10.10s %-5.5s %-25.25s\n"
02691    struct dundi_mapping *map;
02692    char fs[256];
02693    if (argc != 3)
02694       return RESULT_SHOWUSAGE;
02695    AST_LIST_LOCK(&peers);
02696    ast_cli(fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination");
02697    AST_LIST_TRAVERSE(&mappings, map, list) {
02698       ast_cli(fd, FORMAT, map->dcontext, map->weight, 
02699          ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext, 
02700          dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest);
02701    }
02702    AST_LIST_UNLOCK(&peers);
02703    return RESULT_SUCCESS;
02704 #undef FORMAT
02705 #undef FORMAT2
02706 }

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

Definition at line 2486 of file pbx_dundi.c.

References dundi_peer::addr, permission::allow, ast_cli(), ast_inet_ntoa(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, 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, permission::list, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::model, model2str(), permission::name, dundi_peer::order, dundi_peer::outkey, dundi_peer::permit, dundi_peer::registerid, and RESULT_SHOWUSAGE.

02487 {
02488    struct dundi_peer *peer;
02489    struct permission *p;
02490    char *order;
02491    char eid_str[20];
02492    int x, cnt;
02493    
02494    if (argc != 4)
02495       return RESULT_SHOWUSAGE;
02496    AST_LIST_LOCK(&peers);
02497    AST_LIST_TRAVERSE(&peers, peer, list) {
02498       if (!strcasecmp(dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), argv[3]))
02499          break;
02500    }
02501    if (peer) {
02502       switch(peer->order) {
02503       case 0:
02504          order = "Primary";
02505          break;
02506       case 1:
02507          order = "Secondary";
02508          break;
02509       case 2:
02510          order = "Tertiary";
02511          break;
02512       case 3:
02513          order = "Quartiary";
02514          break;
02515       default:
02516          order = "Unknown";
02517       }
02518       ast_cli(fd, "Peer:    %s\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
02519       ast_cli(fd, "Model:   %s\n", model2str(peer->model));
02520       ast_cli(fd, "Host:    %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>");
02521       ast_cli(fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
02522       ast_cli(fd, "Reg:     %s\n", peer->registerid < 0 ? "No" : "Yes");
02523       ast_cli(fd, "In Key:  %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
02524       ast_cli(fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey);
02525       if (!AST_LIST_EMPTY(&peer->include))
02526          ast_cli(fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)");
02527       AST_LIST_TRAVERSE(&peer->include, p, list)
02528          ast_cli(fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name);
02529       if (!AST_LIST_EMPTY(&peer->permit))
02530          ast_cli(fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)");
02531       AST_LIST_TRAVERSE(&peer->permit, p, list)
02532          ast_cli(fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name);
02533       cnt = 0;
02534       for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
02535          if (peer->lookups[x]) {
02536             if (!cnt)
02537                ast_cli(fd, "Last few query times:\n");
02538             ast_cli(fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]);
02539             cnt++;
02540          }
02541       }
02542       if (cnt)
02543          ast_cli(fd, "Average query time: %d ms\n", peer->avgms);
02544    } else
02545       ast_cli(fd, "No such peer '%s'\n", argv[3]);
02546    AST_LIST_UNLOCK(&peers);
02547    return RESULT_SUCCESS;
02548 }

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

Definition at line 2550 of file pbx_dundi.c.

References dundi_peer::addr, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_peer::avgms, dundi_eid_to_str(), dundi_peer::dynamic, dundi_peer::eid, FORMAT, FORMAT2, dundi_peer::lastms, dundi_peer::list, dundi_peer::maxms, dundi_peer::model, model2str(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02551 {
02552 #define FORMAT2 "%-20.20s %-15.15s     %-10.10s %-8.8s %-15.15s\n"
02553 #define FORMAT "%-20.20s %-15.15s %s %-10.10s %-8.8s %-15.15s\n"
02554    struct dundi_peer *peer;
02555    int registeredonly=0;
02556    char avgms[20];
02557    char eid_str[20];
02558    int online_peers = 0;
02559    int offline_peers = 0;
02560    int unmonitored_peers = 0;
02561    int total_peers = 0;
02562 
02563    if ((argc != 3) && (argc != 4) && (argc != 5))
02564       return RESULT_SHOWUSAGE;
02565    if ((argc == 4)) {
02566       if (!strcasecmp(argv[3], "registered")) {
02567          registeredonly = 1;
02568       } else
02569          return RESULT_SHOWUSAGE;
02570    }
02571    AST_LIST_LOCK(&peers);
02572    ast_cli(fd, FORMAT2, "EID", "Host", "Model", "AvgTime", "Status");
02573    AST_LIST_TRAVERSE(&peers, peer, list) {
02574       char status[20];
02575       int print_line = -1;
02576       char srch[2000];
02577       total_peers++;
02578       if (registeredonly && !peer->addr.sin_addr.s_addr)
02579          continue;
02580       if (peer->maxms) {
02581          if (peer->lastms < 0) {
02582             strcpy(status, "UNREACHABLE");
02583             offline_peers++;
02584          }
02585          else if (peer->lastms > peer->maxms) {
02586             snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms);
02587             offline_peers++;
02588          }
02589          else if (peer->lastms) {
02590             snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms);
02591             online_peers++;
02592          }
02593          else {
02594             strcpy(status, "UNKNOWN");
02595             offline_peers++;
02596          }
02597       } else {
02598          strcpy(status, "Unmonitored");
02599          unmonitored_peers++;
02600       }
02601       if (peer->avgms) 
02602          snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms);
02603       else
02604          strcpy(avgms, "Unavail");
02605       snprintf(srch, sizeof(srch), FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
02606                peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
02607                peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
02608 
02609                 if (argc == 5) {
02610                   if (!strcasecmp(argv[3],"include") && strstr(srch,argv[4])) {
02611                         print_line = -1;
02612                    } else if (!strcasecmp(argv[3],"exclude") && !strstr(srch,argv[4])) {
02613                         print_line = 1;
02614                    } else if (!strcasecmp(argv[3],"begin") && !strncasecmp(srch,argv[4],strlen(argv[4]))) {
02615                         print_line = -1;
02616                    } else {
02617                         print_line = 0;
02618                   }
02619                 }
02620       
02621         if (print_line) {
02622          ast_cli(fd, FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
02623                peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
02624                peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
02625       }
02626    }
02627    ast_cli(fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
02628    AST_LIST_UNLOCK(&peers);
02629    return RESULT_SUCCESS;
02630 #undef FORMAT
02631 #undef FORMAT2
02632 }

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

Definition at line 2708 of file pbx_dundi.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_precache_queue::context, dundi_precache_queue::expiration, FORMAT, FORMAT2, dundi_precache_queue::list, dundi_precache_queue::number, RESULT_SHOWUSAGE, RESULT_SUCCESS, and s.

02709 {
02710 #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n"
02711 #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n"
02712    struct dundi_precache_queue *qe;
02713    int h,m,s;
02714    time_t now;
02715    
02716    if (argc != 3)
02717       return RESULT_SHOWUSAGE;
02718    time(&now);
02719    ast_cli(fd, FORMAT2, "Number", "Context", "Expiration");
02720    AST_LIST_LOCK(&pcq);
02721    AST_LIST_TRAVERSE(&pcq, qe, list) {
02722       s = qe->expiration - now;
02723       h = s / 3600;
02724       s = s % 3600;
02725       m = s / 60;
02726       s = s % 60;
02727       ast_cli(fd, FORMAT, qe->number, qe->context, h,m,s);
02728    }
02729    AST_LIST_UNLOCK(&pcq);
02730    
02731    return RESULT_SUCCESS;
02732 #undef FORMAT
02733 #undef FORMAT2
02734 }

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

Definition at line 2665 of file pbx_dundi.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_request::dcontext, dundi_eid_to_str(), dundi_eid_zero(), FORMAT, FORMAT2, dundi_request::list, dundi_request::maxcount, dundi_request::number, dundi_request::respcount, RESULT_SHOWUSAGE, RESULT_SUCCESS, and dundi_request::root_eid.

02666 {
02667 #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n"
02668 #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n"
02669    struct dundi_request *req;
02670    char eidstr[20];
02671    if (argc != 3)
02672       return RESULT_SHOWUSAGE;
02673    AST_LIST_LOCK(&peers);
02674    ast_cli(fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp");
02675    AST_LIST_TRAVERSE(&requests, req, list) {
02676       ast_cli(fd, FORMAT, req->number, req->dcontext,
02677          dundi_eid_zero(&req->root_eid) ? "<unspecified>" : dundi_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount);
02678    }
02679    AST_LIST_UNLOCK(&peers);
02680    return RESULT_SUCCESS;
02681 #undef FORMAT
02682 #undef FORMAT2
02683 }

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

Definition at line 2634 of file pbx_dundi.c.

References dundi_transaction::addr, dundi_transaction::all, dundi_transaction::aseqno, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_transaction::dtrans, FORMAT, FORMAT2, dundi_transaction::iseqno, dundi_transaction::oseqno, RESULT_SHOWUSAGE, RESULT_SUCCESS, and dundi_transaction::strans.

02635 {
02636 #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
02637 #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
02638    struct dundi_transaction *trans;
02639    if (argc != 3)
02640       return RESULT_SHOWUSAGE;
02641    AST_LIST_LOCK(&peers);
02642    ast_cli(fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
02643    AST_LIST_TRAVERSE(&alltrans, trans, all) {
02644       ast_cli(fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr), 
02645          ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
02646    }
02647    AST_LIST_UNLOCK(&peers);
02648    return RESULT_SUCCESS;
02649 #undef FORMAT
02650 #undef FORMAT2
02651 }

static int dundi_xmit ( struct dundi_packet pack  )  [static]

Definition at line 2898 of file pbx_dundi.c.

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

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

02899 {
02900    int res;
02901    if (dundidebug)
02902       dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));
02903    res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr));
02904    if (res < 0) {
02905       ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n", 
02906          ast_inet_ntoa(pack->parent->addr.sin_addr),
02907          ntohs(pack->parent->addr.sin_port), strerror(errno));
02908    }
02909    if (res > 0)
02910       res = 0;
02911    return res;
02912 }

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

Definition at line 3849 of file pbx_dundi.c.

References ast_log(), ast_module_user_add, ast_module_user_remove, ast_strlen_zero(), ast_test_flag, dundi_result::dest, dr, DUNDI_FLAG_EXISTS, dundi_lookup(), LOG_WARNING, MAX_RESULTS, sort_results(), and dundi_result::tech.

03850 {
03851    char *context;
03852    char *opts;
03853    int results;
03854    int x;
03855    int bypass = 0;
03856    struct ast_module_user *u;
03857    struct dundi_result dr[MAX_RESULTS];
03858 
03859    buf[0] = '\0';
03860 
03861    if (ast_strlen_zero(num)) {
03862       ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n");
03863       return -1;
03864    }
03865 
03866    u = ast_module_user_add(chan);
03867 
03868    context = strchr(num, '|');
03869    if (context) {
03870       *context++ = '\0';
03871       opts = strchr(context, '|');
03872       if (opts) {
03873          *opts++ = '\0';
03874          if (strchr(opts, 'b'))
03875             bypass = 1;
03876       }
03877    }
03878 
03879    if (ast_strlen_zero(context))
03880       context = "e164";
03881    
03882    results = dundi_lookup(dr, MAX_RESULTS, NULL, context, num, bypass);
03883    if (results > 0) {
03884       sort_results(dr, results);
03885       for (x = 0; x < results; x++) {
03886          if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) {
03887             snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest);
03888             break;
03889          }
03890       }
03891    }
03892 
03893    ast_module_user_remove(u);
03894 
03895    return 0;
03896 }

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

Definition at line 1327 of file pbx_dundi.c.

References aes_encrypt().

Referenced by dundi_encrypt().

01328 {
01329    unsigned char curblock[16];
01330    int x;
01331    memcpy(curblock, iv, sizeof(curblock));
01332    while(len > 0) {
01333       for (x=0;x<16;x++)
01334          curblock[x] ^= src[x];
01335       aes_encrypt(curblock, dst, ecx);
01336       memcpy(curblock, dst, sizeof(curblock)); 
01337       dst += 16;
01338       src += 16;
01339       len -= 16;
01340    }
01341    return 0;
01342 }

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

Definition at line 484 of file pbx_dundi.c.

References any_peer, AST_LIST_TRAVERSE, dundi_eid_cmp(), dundi_peer::eid, and empty_eid.

00485 {
00486    struct dundi_peer *cur = NULL;
00487 
00488    if (!eid)
00489       eid = &empty_eid;
00490    
00491    AST_LIST_TRAVERSE(&peers, cur, list) {
00492       if (!dundi_eid_cmp(&cur->eid,eid))
00493          break;
00494    }
00495 
00496    if (!cur && any_peer)
00497       cur = any_peer;
00498 
00499    return cur;
00500 }

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

Definition at line 334 of file pbx_dundi.c.

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

Referenced by handle_frame().

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

static int get_trans_id ( void   )  [static]

Definition at line 449 of file pbx_dundi.c.

References AST_LIST_TRAVERSE, ast_random(), and t.

Referenced by create_transaction(), and reset_transaction().

00450 {
00451    struct dundi_transaction *t;
00452    int stid = (ast_random() % 32766) + 1;
00453    int tid = stid;
00454 
00455    do {
00456       AST_LIST_TRAVERSE(&alltrans, t, all) {
00457          if (t->strans == tid) 
00458             break;
00459       }
00460       if (!t)
00461          return tid;
00462       tid = (tid % 32766) + 1;
00463    } while (tid != stid);
00464 
00465    return 0;
00466 }

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

Definition at line 1535 of file pbx_dundi.c.

References dundi_peer::addr, dundi_transaction::addr, any_peer, ast_calloc, ast_clear_flag_nonstd, ast_copy_string(), ast_db_put(), ast_inet_ntoa(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_sched_add(), AST_SCHED_DEL, ast_set_flag_nonstd, ast_strlen_zero(), ast_test_flag, ast_test_flag_nonstd, ast_verbose(), cache_save(), cache_save_hint(), dundi_hdr::cmdresp, dundi_request::dcontext, deep_copy_peer(), dundi_result::dest, do_register_expire(), dundi_request::dr, dundi_answer_entity(), dundi_answer_query(), DUNDI_CAUSE_GENERAL, DUNDI_CAUSE_NOAUTH, DUNDI_COMMAND_CANCEL, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_DPRESPONSE, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_EIDRESPONSE, DUNDI_COMMAND_PRECACHERP, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, DUNDI_COMMAND_REGRESPONSE, dundi_eid_to_str(), dundi_eid_to_str_short(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_TTL_EXPIRED, DUNDI_HINT_UNAFFECTED, dundi_ie_append_cause(), dundi_ie_append_short(), DUNDI_IE_CAUSE, DUNDI_IE_EXPIRATION, DUNDI_MODEL_INBOUND, dundi_parse_ies(), dundi_prop_precache(), dundi_send(), dundi_peer::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, permission::list, 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, dundi_ie_data::pos, qualify_peer(), dundi_peer::registerexpire, dundi_request::respcount, sched, 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().

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

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

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

01997 {
01998    struct dundi_transaction *trans;
01999    trans = find_transaction(h, sin);
02000    if (!trans) {
02001       dundi_reject(h, sin);
02002       return 0;
02003    }
02004    /* Got a transaction, see where this header fits in */
02005    if (h->oseqno == trans->iseqno) {
02006       /* Just what we were looking for...  Anything but ack increments iseqno */
02007       if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) {
02008          /* If final, we're done */
02009          destroy_trans(trans, 0);
02010          return 0;
02011       }
02012       if (h->cmdresp != DUNDI_COMMAND_ACK) {
02013          trans->oiseqno = trans->iseqno;
02014          trans->iseqno++;
02015          handle_command_response(trans, h, datalen, 0);
02016       }
02017       if (trans->aseqno != trans->iseqno) {
02018          dundi_ack(trans, h->cmdresp & 0x80);
02019          trans->aseqno = trans->iseqno;
02020       }
02021       /* Delete any saved last transmissions */
02022       destroy_packets(&trans->lasttrans);
02023       if (h->cmdresp & 0x80) {
02024          /* Final -- destroy now */
02025          destroy_trans(trans, 0);
02026       }
02027    } else if (h->oseqno == trans->oiseqno) {
02028       /* Last incoming sequence number -- send ACK without processing */
02029       dundi_ack(trans, 0);
02030    } else {
02031       /* Out of window -- simply drop */
02032       ast_log(LOG_DEBUG, "Dropping packet out of window!\n");
02033    }
02034    return 0;
02035 }

static int has_permission ( struct permissionlist *  permlist,
char *  cont 
) [static]

Definition at line 290 of file pbx_dundi.c.

References permission::allow, AST_LIST_TRAVERSE, permission::list, and permission::name.

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

00291 {
00292    struct permission *perm;
00293    int res = 0;
00294 
00295    AST_LIST_TRAVERSE(permlist, perm, list) {
00296       if (!strcasecmp(perm->name, "all") || !strcasecmp(perm->name, cont))
00297          res = perm->allow;
00298    }
00299 
00300    return res;
00301 }

static int load_module ( void   )  [static]

Definition at line 4618 of file pbx_dundi.c.

References ast_cli_register_multiple(), ast_custom_function_register(), ast_inet_ntoa(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_register_switch(), ast_verbose(), cli_dundi, dundi_debug_output(), dundi_error_output(), dundi_function, DUNDI_PORT, dundi_set_error(), dundi_set_output(), dundi_switch, errno, io, io_context_create(), LOG_ERROR, option_verbose, sched, sched_context_create(), set_config(), start_network_thread(), and VERBOSE_PREFIX_2.

04619 {
04620    int res = 0;
04621    struct sockaddr_in sin;
04622 
04623    dundi_set_output(dundi_debug_output);
04624    dundi_set_error(dundi_error_output);
04625    
04626    sin.sin_family = AF_INET;
04627    sin.sin_port = ntohs(DUNDI_PORT);
04628    sin.sin_addr.s_addr = INADDR_ANY;
04629 
04630    /* Make a UDP socket */
04631    io = io_context_create();
04632    sched = sched_context_create();
04633    
04634    if (!io || !sched) {
04635       ast_log(LOG_ERROR, "Out of memory\n");
04636       return -1;
04637    }
04638 
04639    if(set_config("dundi.conf",&sin))
04640       return AST_MODULE_LOAD_DECLINE;
04641 
04642    netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
04643    
04644    if (netsocket < 0) {
04645       ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
04646       return -1;
04647    }
04648    if (bind(netsocket,(struct sockaddr *)&sin, sizeof(sin))) {
04649       ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), strerror(errno));
04650       return -1;
04651    }
04652 
04653    if (option_verbose > 1)
04654       ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
04655 
04656    if (setsockopt(netsocket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) 
04657       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
04658    
04659    res = start_network_thread();
04660    if (res) {
04661       ast_log(LOG_ERROR, "Unable to start network thread\n");
04662       close(netsocket);
04663       return -1;
04664    }
04665 
04666    if (option_verbose > 1)
04667       ast_verbose(VERBOSE_PREFIX_2 "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
04668 
04669    ast_cli_register_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(struct ast_cli_entry));
04670    if (ast_register_switch(&dundi_switch))
04671       ast_log(LOG_ERROR, "Unable to register DUNDi switch\n");
04672    ast_custom_function_register(&dundi_function); 
04673    
04674    return res;
04675 }

static void load_password ( void   )  [static]

Definition at line 2093 of file pbx_dundi.c.

References ast_copy_string(), ast_db_get(), ast_get_time_t(), build_secret(), DUNDI_SECRET_TIME, last, and save_secret().

Referenced by set_config().

02094 {
02095    char *current=NULL;
02096    char *last=NULL;
02097    char tmp[256];
02098    time_t expired;
02099    
02100    ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp));
02101    if (!ast_get_time_t(tmp, &expired, 0, NULL)) {
02102       ast_db_get(secretpath, "secret", tmp, sizeof(tmp));
02103       current = strchr(tmp, ';');
02104       if (!current)
02105          current = tmp;
02106       else {
02107          *current = '\0';
02108          current++;
02109       };
02110       if ((time(NULL) - expired) < 0) {
02111          if ((expired - time(NULL)) > DUNDI_SECRET_TIME)
02112             expired = time(NULL) + DUNDI_SECRET_TIME;
02113       } else if ((time(NULL) - (expired + DUNDI_SECRET_TIME)) < 0) {
02114          last = current;
02115          current = NULL;
02116       } else {
02117          last = NULL;
02118          current = NULL;
02119       }
02120    }
02121    if (current) {
02122       /* Current key is still valid, just setup rotatation properly */
02123       ast_copy_string(cursecret, current, sizeof(cursecret));
02124       rotatetime = expired;
02125    } else {
02126       /* Current key is out of date, rotate or eliminate all together */
02127       build_secret(cursecret, sizeof(cursecret));
02128       save_secret(cursecret, last);
02129    }
02130 }

static void mark_mappings ( void   )  [static]

Definition at line 3925 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_mapping::list, and map.

Referenced by set_config(), and unload_module().

03926 {
03927    struct dundi_mapping *map;
03928    
03929    AST_LIST_LOCK(&peers);
03930    AST_LIST_TRAVERSE(&mappings, map, list) {
03931       map->dead = 1;
03932    }
03933    AST_LIST_UNLOCK(&peers);
03934 }

static void mark_peers ( void   )  [static]

Definition at line 3915 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_peer::dead, and dundi_peer::list.

Referenced by set_config(), and unload_module().

03916 {
03917    struct dundi_peer *peer;
03918    AST_LIST_LOCK(&peers);
03919    AST_LIST_TRAVERSE(&peers, peer, list) {
03920       peer->dead = 1;
03921    }
03922    AST_LIST_UNLOCK(&peers);
03923 }

static char* model2str ( int  model  )  [static]

Definition at line 2324 of file pbx_dundi.c.

References DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, and DUNDI_MODEL_SYMMETRIC.

Referenced by dundi_show_peer(), and dundi_show_peers().

02325 {
02326    switch(model) {
02327    case DUNDI_MODEL_INBOUND:
02328       return "Inbound";
02329    case DUNDI_MODEL_OUTBOUND:
02330       return "Outbound";
02331    case DUNDI_MODEL_SYMMETRIC:
02332       return "Symmetric";
02333    default:
02334       return "Unknown";
02335    }
02336 }

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

Definition at line 2149 of file pbx_dundi.c.

References ast_io_add(), AST_IO_IN, ast_io_wait(), AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, ast_sched_runq(), ast_sched_wait(), check_password(), io, sched, and socket_read().

02150 {
02151    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
02152       from the network, and queue them for delivery to the channels */
02153    int res;
02154    /* Establish I/O callback for socket read */
02155    ast_io_add(io, netsocket, socket_read, AST_IO_IN, NULL);
02156    
02157    while (!dundi_shutdown) {
02158       res = ast_sched_wait(sched);
02159       if ((res > 1000) || (res < 0))
02160          res = 1000;
02161       res = ast_io_wait(io, res);
02162       if (res >= 0) {
02163          AST_LIST_LOCK(&peers);
02164          ast_sched_runq(sched);
02165          AST_LIST_UNLOCK(&peers);
02166       }
02167       check_password();
02168    }
02169 
02170    netthreadid = AST_PTHREADT_NULL;
02171    
02172    return NULL;
02173 }

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

Definition at line 3304 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, dr, dundi_eid_cmp(), DUNDI_MAX_STACK, dundi_peer::eid, dundi_transaction::eidcount, dundi_transaction::eids, has_permission(), dundi_peer::include, dundi_peer::list, dundi_peer::order, dundi_transaction::them_eid, and dundi_transaction::us_eid.

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

03305 {
03306    /* Minimize the message propagation through DUNDi by
03307       alerting the network to hops which should be not be considered */
03308    struct dundi_transaction *trans;
03309    struct dundi_peer *peer;
03310    dundi_eid tmp;
03311    int x;
03312    int needpush;
03313 
03314    AST_LIST_LOCK(&peers);
03315    AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
03316       /* Pop off the true root */
03317       if (trans->eidcount) {
03318          tmp = trans->eids[--trans->eidcount];
03319          needpush = 1;
03320       } else {
03321          tmp = trans->us_eid;
03322          needpush = 0;
03323       }
03324 
03325       AST_LIST_TRAVERSE(&peers, peer, list) {
03326          if (has_permission(&peer->include, dr->dcontext) && 
03327              dundi_eid_cmp(&peer->eid, &trans->them_eid) &&
03328             (peer->order <= order)) {
03329             /* For each other transaction, make sure we don't
03330                ask this EID about the others if they're not
03331                already in the list */
03332             if (!dundi_eid_cmp(&tmp, &peer->eid)) 
03333                x = -1;
03334             else {
03335                for (x=0;x<trans->eidcount;x++) {
03336                   if (!dundi_eid_cmp(&trans->eids[x], &peer->eid))
03337                      break;
03338                }
03339             }
03340             if (x == trans->eidcount) {
03341                /* Nope not in the list, if needed, add us at the end since we're the source */
03342                if (trans->eidcount < DUNDI_MAX_STACK - needpush) {
03343                   trans->eids[trans->eidcount++] = peer->eid;
03344                   /* Need to insert the real root (or us) at the bottom now as
03345                      a requirement now.  */
03346                   needpush = 1;
03347                }
03348             }
03349          }
03350       }
03351       /* If necessary, push the true root back on the end */
03352       if (needpush)
03353          trans->eids[trans->eidcount++] = tmp;
03354    }
03355    AST_LIST_UNLOCK(&peers);
03356 
03357    return 0;
03358 }

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

Definition at line 4132 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, dundi_peer::registerexpire, and sched.

Referenced by build_peer().

04133 {
04134    char data[256];
04135    char *c;
04136    int port, expire;
04137    char eid_str[20];
04138    dundi_eid_to_str(eid_str, sizeof(eid_str), eid);
04139    if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) {
04140       c = strchr(data, ':');
04141       if (c) {
04142          *c = '\0';
04143          c++;
04144          if (sscanf(c, "%d:%d", &port, &expire) == 2) {
04145             /* Got it! */
04146             inet_aton(data, &peer->addr.sin_addr);
04147             peer->addr.sin_family = AF_INET;
04148             peer->addr.sin_port = htons(port);
04149             peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
04150          }
04151       }
04152    }
04153 }

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

Definition at line 3157 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_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, LOG_WARNING, MAX_RESULTS, dundi_request::number, dundi_transaction::parent, sched, dundi_transaction::them_eid, dundi_transaction::ttl, and dundi_transaction::us_eid.

Referenced by precache_transactions().

03158 {
03159    struct dundi_ie_data ied;
03160    int x, res;
03161    int max = 999999;
03162    int expiration = dundi_cache_time;
03163    int ouranswers=0;
03164    dundi_eid *avoid[1] = { NULL, };
03165    int direct[1] = { 0, };
03166    struct dundi_result dr[MAX_RESULTS];
03167    struct dundi_hint_metadata hmd;
03168    if (!trans->parent) {
03169       ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
03170       return -1;
03171    }
03172    memset(&hmd, 0, sizeof(hmd));
03173    memset(&dr, 0, sizeof(dr));
03174    /* Look up the answers we're going to include */
03175    for (x=0;x<mapcount;x++)
03176       ouranswers = dundi_lookup_local(dr, maps + x, trans->parent->number, &trans->us_eid, ouranswers, &hmd);
03177    if (ouranswers < 0)
03178       ouranswers = 0;
03179    for (x=0;x<ouranswers;x++) {
03180       if (dr[x].weight < max)
03181          max = dr[x].weight;
03182    }
03183    if (max) {
03184       /* If we do not have a canonical result, keep looking */
03185       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);
03186       if (res > 0) {
03187          /* Append answer in result */
03188          ouranswers += res;
03189       }
03190    }
03191    
03192    if (ouranswers > 0) {
03193       *foundanswers += ouranswers;
03194       memset(&ied, 0, sizeof(ied));
03195       dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
03196       if (!dundi_eid_zero(&trans->us_eid))
03197          dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
03198       for (x=0;x<trans->eidcount;x++)
03199          dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
03200       dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number);
03201       dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext);
03202       dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
03203       for (x=0;x<ouranswers;x++) {
03204          /* Add answers */
03205          if (dr[x].expiration && (expiration > dr[x].expiration))
03206             expiration = dr[x].expiration;
03207          dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
03208       }
03209       dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
03210       dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
03211       if (trans->autokilltimeout)
03212          trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
03213       if (expiration < *minexp)
03214          *minexp = expiration;
03215       return dundi_send(trans, DUNDI_COMMAND_PRECACHERQ, 0, 0, &ied);
03216    } else {
03217       /* Oops, nothing to send... */
03218       destroy_trans(trans, 0);
03219       return 0;
03220    }
03221 }

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

Definition at line 3256 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_test_flag, destroy_trans(), dr, FLAG_DEAD, LOG_DEBUG, LOG_WARNING, dundi_transaction::parentlist, precache_trans(), and dundi_transaction::thread.

Referenced by dundi_precache_internal().

03257 {
03258    struct dundi_transaction *trans;
03259 
03260    /* Mark all as "in thread" so they don't disappear */
03261    AST_LIST_LOCK(&peers);
03262    AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
03263       if (trans->thread)
03264          ast_log(LOG_WARNING, "This shouldn't happen, really...\n");
03265       trans->thread = 1;
03266    }
03267    AST_LIST_UNLOCK(&peers);
03268 
03269    AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
03270       if (!ast_test_flag(trans, FLAG_DEAD))
03271          precache_trans(trans, maps, mapcount, expiration, foundanswers);
03272    }
03273 
03274    /* Cleanup any that got destroyed in the mean time */
03275    AST_LIST_LOCK(&peers);
03276    AST_LIST_TRAVERSE_SAFE_BEGIN(&dr->trans, trans, parentlist) {
03277       trans->thread = 0;
03278       if (ast_test_flag(trans, FLAG_DEAD)) {
03279          ast_log(LOG_DEBUG, "Our transaction went away!\n");
03280          /* This is going to remove the transaction from the dundi_request's list, as well
03281           * as the global transactions list */
03282          destroy_trans(trans, 0);
03283       }
03284    }
03285    AST_LIST_TRAVERSE_SAFE_END
03286    AST_LIST_UNLOCK(&peers);
03287 
03288    return 0;
03289 }

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

Definition at line 2175 of file pbx_dundi.c.

References ast_db_del(), ast_db_freetree(), ast_db_gettree(), ast_get_time_t(), ast_log(), ast_db_entry::data, expiry, ast_db_entry::key, LOG_DEBUG, ast_db_entry::next, and option_debug.

Referenced by start_network_thread().

02176 {
02177    struct ast_db_entry *db_entry, *db_tree;
02178    int striplen = sizeof("/dundi/cache");
02179    time_t now;
02180    
02181    while (!dundi_shutdown) {
02182       pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
02183 
02184       time(&now);
02185 
02186       db_entry = db_tree = ast_db_gettree("dundi/cache", NULL);
02187       for (; db_entry; db_entry = db_entry->next) {
02188          time_t expiry;
02189 
02190          if (!ast_get_time_t(db_entry->data, &expiry, 0, NULL)) {
02191             if (expiry < now) {
02192                if (option_debug)
02193                   ast_log(LOG_DEBUG, "clearing expired DUNDI cache entry: %s\n", db_entry->key);
02194                ast_db_del("dundi/cache", db_entry->key + striplen);
02195             }
02196          }
02197       }
02198       ast_db_freetree(db_tree);
02199 
02200       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
02201       pthread_testcancel();
02202       sleep(60);
02203       pthread_testcancel();
02204    }
02205    
02206    clearcachethreadid = AST_PTHREADT_NULL;
02207    return NULL;
02208 }

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

Definition at line 2210 of file pbx_dundi.c.

References ast_copy_string(), AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, AST_PTHREADT_NULL, dundi_precache_queue::context, dundi_precache(), dundi_precache_queue::expiration, free, dundi_precache_queue::list, and dundi_precache_queue::number.

Referenced by start_network_thread().

02211 {
02212    struct dundi_precache_queue *qe;
02213    time_t now;
02214    char context[256];
02215    char number[256];
02216    int run;
02217 
02218    while (!dundi_shutdown) {
02219       time(&now);
02220       run = 0;
02221       AST_LIST_LOCK(&pcq);
02222       if ((qe = AST_LIST_FIRST(&pcq))) {
02223          if (!qe->expiration) {
02224             /* Gone...  Remove... */
02225             AST_LIST_REMOVE_HEAD(&pcq, list);
02226             free(qe);
02227          } else if (qe->expiration < now) {
02228             /* Process this entry */
02229             qe->expiration = 0;
02230             ast_copy_string(context, qe->context, sizeof(context));
02231             ast_copy_string(number, qe->number, sizeof(number));
02232             run = 1;
02233          }
02234       }
02235       AST_LIST_UNLOCK(&pcq);
02236       if (run) {
02237          dundi_precache(context, number);
02238       } else
02239          sleep(1);
02240    }
02241 
02242    precachethreadid = AST_PTHREADT_NULL;
02243 
02244    return NULL;
02245 }

static void prune_mappings ( void   )  [static]

Definition at line 3975 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, destroy_map(), dundi_mapping::list, and map.

Referenced by set_config(), and unload_module().

03976 {
03977    struct dundi_mapping *map;
03978 
03979    AST_LIST_LOCK(&peers);
03980    AST_LIST_TRAVERSE_SAFE_BEGIN(&mappings, map, list) {
03981       if (map->dead) {
03982          AST_LIST_REMOVE_CURRENT(&mappings, list);
03983          destroy_map(map);
03984       }
03985    }
03986    AST_LIST_TRAVERSE_SAFE_END
03987    AST_LIST_UNLOCK(&peers);
03988 }

static void prune_peers ( void   )  [static]

Definition at line 3960 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, dundi_peer::dead, destroy_peer(), and dundi_peer::list.

03961 {
03962    struct dundi_peer *peer;
03963 
03964    AST_LIST_LOCK(&peers);
03965    AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, list) {
03966       if (peer->dead) {
03967          AST_LIST_REMOVE_CURRENT(&peers, list);
03968          destroy_peer(peer);
03969       }
03970    }
03971    AST_LIST_TRAVERSE_SAFE_END
03972    AST_LIST_UNLOCK(&peers);
03973 }

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

Definition at line 4109 of file pbx_dundi.c.

References ast_sched_add(), AST_SCHED_DEL, ast_set_flag, ast_tvnow(), 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, dundi_peer::qualtx, and sched.

Referenced by do_qualify(), and handle_command_response().

04110 {
04111    int when;
04112    AST_SCHED_DEL(sched, peer->qualifyid);
04113    if (peer->qualtrans)
04114       destroy_trans(peer->qualtrans, 0);
04115    peer->qualtrans = NULL;
04116    if (peer->maxms > 0) {
04117       when = 60000;
04118       if (peer->lastms < 0)
04119          when = 10000;
04120       if (schedonly)
04121          when = 5000;
04122       peer->qualifyid = ast_sched_add(sched, when, do_qualify, peer);
04123       if (!schedonly)
04124          peer->qualtrans = create_transaction(peer);
04125       if (peer->qualtrans) {
04126          peer->qualtx = ast_tvnow();
04127          ast_set_flag(peer->qualtrans, FLAG_ISQUAL);
04128          dundi_send(peer->qualtrans, DUNDI_COMMAND_NULL, 0, 1, NULL);
04129       }
04130    }
04131 }

static int query_transactions ( struct dundi_request dr  )  [static]

Definition at line 3291 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dr, dundi_query(), and dundi_transaction::parentlist.

Referenced by dundi_query_eid_internal().

03292 {
03293    struct dundi_transaction *trans;
03294 
03295    AST_LIST_LOCK(&peers);
03296    AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
03297       dundi_query(trans);
03298    }
03299    AST_LIST_UNLOCK(&peers);
03300 
03301    return 0;
03302 }

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

Definition at line 3472 of file pbx_dundi.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), dundi_request::crc32, dundi_request::dcontext, dr, dundi_eid_cmp(), dundi_eid_to_str(), dundi_request::list, LOG_DEBUG, dundi_request::number, option_debug, and dundi_request::root_eid.

Referenced by dundi_lookup_internal().

03473 {
03474    struct dundi_request *cur;
03475    int res=0;
03476    char eid_str[20];
03477    AST_LIST_LOCK(&peers);
03478    AST_LIST_TRAVERSE(&requests, cur, list) {
03479       if (option_debug)
03480          ast_log(LOG_DEBUG, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number,
03481             dr->dcontext, dr->number);
03482       if (!strcasecmp(cur->dcontext, dr->dcontext) &&
03483           !strcasecmp(cur->number, dr->number) &&
03484           (!dundi_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) {
03485          ast_log(LOG_DEBUG, "Found existing query for '%s@%s' for '%s' crc '%08x'\n", 
03486             cur->dcontext, cur->number, dundi_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32);
03487          *pending = cur;
03488          res = 1;
03489          break;
03490       }
03491    }
03492    if (!res) {
03493       ast_log(LOG_DEBUG, "Registering request for '%s@%s' on behalf of '%s' crc '%08x'\n", 
03494             dr->number, dr->dcontext, dundi_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32);
03495       /* Go ahead and link us in since nobody else is searching for this */
03496       AST_LIST_INSERT_HEAD(&requests, dr, list);
03497       *pending = NULL;
03498    }
03499    AST_LIST_UNLOCK(&peers);
03500    return res;
03501 }

static int reload ( void   )  [static]

Definition at line 4611 of file pbx_dundi.c.

References set_config().

04612 {
04613    struct sockaddr_in sin;
04614    set_config("dundi.conf",&sin);
04615    return 0;
04616 }

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

Definition at line 3652 of file pbx_dundi.c.

References ast_calloc, AST_LIST_FIRST, AST_LIST_INSERT_AFTER, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, dundi_precache_queue::context, dundi_precache_queue::expiration, len(), dundi_precache_queue::list, and dundi_precache_queue::number.

Referenced by dundi_precache_full(), and dundi_precache_internal().

03653 {
03654    int len;
03655    struct dundi_precache_queue *qe, *prev;
03656 
03657    AST_LIST_LOCK(&pcq);
03658    AST_LIST_TRAVERSE_SAFE_BEGIN(&pcq, qe, list) {
03659       if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) {
03660          AST_LIST_REMOVE_CURRENT(&pcq, list);
03661          break;
03662       }
03663    }
03664    AST_LIST_TRAVERSE_SAFE_END
03665    if (!qe) {
03666       len = sizeof(*qe);
03667       len += strlen(number) + 1;
03668       len += strlen(context) + 1;
03669       if (!(qe = ast_calloc(1, len))) {
03670          AST_LIST_UNLOCK(&pcq);
03671          return;
03672       }
03673       strcpy(qe->number, number);
03674       qe->context = qe->number + strlen(number) + 1;
03675       strcpy(qe->context, context);
03676    }
03677    time(&qe->expiration);
03678    qe->expiration += expiration;
03679    if ((prev = AST_LIST_FIRST(&pcq))) {
03680       while (AST_LIST_NEXT(prev, list) && ((AST_LIST_NEXT(prev, list))->expiration <= qe->expiration))
03681          prev = AST_LIST_NEXT(prev, list);
03682       AST_LIST_INSERT_AFTER(&pcq, prev, qe, list);
03683    } else
03684       AST_LIST_INSERT_HEAD(&pcq, qe, list);
03685    AST_LIST_UNLOCK(&pcq);
03686 }

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

Definition at line 2365 of file pbx_dundi.c.

References dundi_result::weight.

Referenced by sort_results().

02366 {
02367    const struct dundi_result *resa, *resb;
02368    resa = a;
02369    resb = b;
02370    if (resa->weight < resb->weight)
02371       return -1;
02372    if (resa->weight > resb->weight)
02373       return 1;
02374    return 0;
02375 }

static void reset_global_eid ( void   )  [static]

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

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

static int reset_transaction ( struct dundi_transaction trans  )  [static]

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

00469 {
00470    int tid;
00471    tid = get_trans_id();
00472    if (tid < 1)
00473       return -1;
00474    trans->strans = tid;
00475    trans->dtrans = 0;
00476    trans->iseqno = 0;
00477    trans->oiseqno = 0;
00478    trans->oseqno = 0;
00479    trans->aseqno = 0;
00480    ast_clear_flag(trans, FLAG_FINAL);  
00481    return 0;
00482 }

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

Definition at line 2080 of file pbx_dundi.c.

References ast_db_put(), and DUNDI_SECRET_TIME.

Referenced by check_password(), and load_password().

02081 {
02082    char tmp[256];
02083    if (oldkey)
02084       snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey);
02085    else
02086       snprintf(tmp, sizeof(tmp), "%s", newkey);
02087    rotatetime = time(NULL) + DUNDI_SECRET_TIME;
02088    ast_db_put(secretpath, "secret", tmp);
02089    snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime);
02090    ast_db_put(secretpath, "secretexpiry", tmp);
02091 }

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

Definition at line 4418 of file pbx_dundi.c.

References any_peer, ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_copy_string(), ast_gethostbyname(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_true(), ast_variable_browse(), build_mapping(), build_peer(), DEFAULT_MAXMS, DUNDI_DEFAULT_CACHE_TIME, DUNDI_DEFAULT_TTL, DUNDI_MODEL_OUTBOUND, dundi_precache_full(), dundi_str_to_eid(), empty_eid, find_peer(), format, global_eid, hp, IPTOS_MINCOST, ast_variable::lineno, load_password(), LOG_ERROR, LOG_NOTICE, mark_mappings(), mark_peers(), ast_variable::name, ast_variable::next, prune_mappings(), prune_peers(), reset_global_eid(), and ast_variable::value.

04419 {
04420    struct ast_config *cfg;
04421    struct ast_variable *v;
04422    char *cat;
04423    int format;
04424    int x;
04425    char hn[MAXHOSTNAMELEN] = "";
04426    struct ast_hostent he;
04427    struct hostent *hp;
04428    struct sockaddr_in sin2;
04429    static int last_port = 0;
04430    int globalpcmodel = 0;
04431    dundi_eid testeid;
04432 
04433    dundi_ttl = DUNDI_DEFAULT_TTL;
04434    dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME;
04435    any_peer = NULL;
04436    
04437    cfg = ast_config_load(config_file);
04438    
04439    if (!cfg) {
04440       ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
04441       return -1;
04442    }
04443    ipaddr[0] = '\0';
04444    if (!gethostname(hn, sizeof(hn)-1)) {
04445       hp = ast_gethostbyname(hn, &he);
04446       if (hp) {
04447          memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr));
04448          ast_copy_string(ipaddr, ast_inet_ntoa(sin2.sin_addr), sizeof(ipaddr));
04449       } else
04450          ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn);
04451    } else
04452       ast_log(LOG_WARNING, "Unable to get host name!\n");
04453    AST_LIST_LOCK(&peers);
04454    reset_global_eid();
04455    global_storehistory = 0;
04456    ast_copy_string(secretpath, "dundi", sizeof(secretpath));
04457    v = ast_variable_browse(cfg, "general");
04458    while(v) {
04459       if (!strcasecmp(v->name, "port")){ 
04460          sin->sin_port = ntohs(atoi(v->value));
04461          if(last_port==0){
04462             last_port=sin->sin_port;
04463          } else if(sin->sin_port != last_port)
04464             ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
04465       } else if (!strcasecmp(v->name, "bindaddr")) {
04466          struct hostent *hp;
04467          struct ast_hostent he;
04468          hp = ast_gethostbyname(v->value, &he);
04469          if (hp) {
04470             memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
04471          } else
04472             ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
04473       } else if (!strcasecmp(v->name, "authdebug")) {
04474          authdebug = ast_true(v->value);
04475       } else if (!strcasecmp(v->name, "ttl")) {
04476          if ((sscanf(v->value, "%d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) {
04477             dundi_ttl = x;
04478          } else {
04479             ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n",
04480                v->value, v->lineno, DUNDI_DEFAULT_TTL);
04481          }
04482       } else if (!strcasecmp(v->name, "autokill")) {
04483          if (sscanf(v->value, "%d", &x) == 1) {
04484             if (x >= 0)
04485                global_autokilltimeout = x;
04486             else
04487                ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
04488          } else if (ast_true(v->value)) {
04489             global_autokilltimeout = DEFAULT_MAXMS;
04490          } else {
04491             global_autokilltimeout = 0;
04492          }
04493       } else if (!strcasecmp(v->name, "entityid")) {
04494          if (!dundi_str_to_eid(&testeid, v->value))
04495             global_eid = testeid;
04496          else
04497             ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno);
04498       } else if (!strcasecmp(v->name, "tos")) {
04499          if (sscanf(v->value, "%d", &format) == 1)
04500             tos = format & 0xff;
04501          else if (!strcasecmp(v->value, "lowdelay"))
04502             tos = IPTOS_LOWDELAY;
04503          else if (!strcasecmp(v->value, "throughput"))
04504             tos = IPTOS_THROUGHPUT;
04505          else if (!strcasecmp(v->value, "reliability"))
04506             tos = IPTOS_RELIABILITY;
04507 #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS)
04508          else if (!strcasecmp(v->value, "mincost"))
04509             tos = IPTOS_MINCOST;
04510 #endif
04511          else if (!strcasecmp(v->value, "none"))
04512             tos = 0;
04513          else
04514 #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS)
04515             ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
04516 #else
04517             ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', or 'none'\n", v->lineno);
04518 #endif
04519       } else if (!strcasecmp(v->name, "department")) {
04520          ast_copy_string(dept, v->value, sizeof(dept));
04521       } else if (!strcasecmp(v->name, "organization")) {
04522          ast_copy_string(org, v->value, sizeof(org));
04523       } else if (!strcasecmp(v->name, "locality")) {
04524          ast_copy_string(locality, v->value, sizeof(locality));
04525       } else if (!strcasecmp(v->name, "stateprov")) {
04526          ast_copy_string(stateprov, v->value, sizeof(stateprov));
04527       } else if (!strcasecmp(v->name, "country")) {
04528          ast_copy_string(country, v->value, sizeof(country));
04529       } else if (!strcasecmp(v->name, "email")) {
04530          ast_copy_string(email, v->value, sizeof(email));
04531       } else if (!strcasecmp(v->name, "phone")) {
04532          ast_copy_string(phone, v->value, sizeof(phone));
04533       } else if (!strcasecmp(v->name, "storehistory")) {
04534          global_storehistory = ast_true(v->value);
04535       } else if (!strcasecmp(v->name, "cachetime")) {
04536          if ((sscanf(v->value, "%d", &x) == 1)) {
04537             dundi_cache_time = x;
04538          } else {
04539             ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n",
04540                v->value, v->lineno, DUNDI_DEFAULT_CACHE_TIME);
04541          }
04542       }
04543       v = v->next;
04544    }
04545    AST_LIST_UNLOCK(&peers);
04546    mark_mappings();
04547    v = ast_variable_browse(cfg, "mappings");
04548    while(v) {
04549       build_mapping(v->name, v->value);
04550       v = v->next;
04551    }
04552    prune_mappings();
04553    mark_peers();
04554    cat = ast_category_browse(cfg, NULL);
04555    while(cat) {
04556       if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) {
04557          /* Entries */
04558          if (!dundi_str_to_eid(&testeid, cat))
04559             build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel);
04560          else if (!strcasecmp(cat, "*")) {
04561             build_peer(&empty_eid, ast_variable_browse(cfg, cat), &globalpcmodel);
04562             any_peer = find_peer(NULL);
04563          } else
04564             ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat);
04565       }
04566       cat = ast_category_browse(cfg, cat);
04567    }
04568    prune_peers();
04569    ast_config_destroy(cfg);
04570    load_password();
04571    if (globalpcmodel & DUNDI_MODEL_OUTBOUND)
04572       dundi_precache_full();
04573    return 0;
04574 }

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

Definition at line 2037 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), dundi_showframe(), errno, handle_frame(), len(), LOG_WARNING, and MAX_PACKET_SIZE.

02038 {
02039    struct sockaddr_in sin;
02040    int res;
02041    struct dundi_hdr *h;
02042    char buf[MAX_PACKET_SIZE];
02043    socklen_t len;
02044    len = sizeof(sin);
02045    res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len);
02046    if (res < 0) {
02047       if (errno != ECONNREFUSED)
02048          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
02049       return 1;
02050    }
02051    if (res < sizeof(struct dundi_hdr)) {
02052       ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct dundi_hdr));
02053       return 1;
02054    }
02055    buf[res] = '\0';
02056    h = (struct dundi_hdr *)buf;
02057    if (dundidebug)
02058       dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr));
02059    AST_LIST_LOCK(&peers);
02060    handle_frame(h, &sin, res - sizeof(struct dundi_hdr));
02061    AST_LIST_UNLOCK(&peers);
02062    return 1;
02063 }

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

Definition at line 2377 of file pbx_dundi.c.

References rescomp().

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

02378 {
02379    qsort(results, count, sizeof(results[0]), rescomp);
02380 }

static int start_network_thread ( void   )  [static]

Definition at line 2247 of file pbx_dundi.c.

References ast_pthread_create_background, network_thread(), process_clearcache(), and process_precache().

static int str2tech ( char *  str  )  [static]

Definition at line 319 of file pbx_dundi.c.

References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, and DUNDI_PROTO_SIP.

Referenced by build_mapping().

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

static char* tech2str ( int  tech  )  [static]

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

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

static int unload_module ( void   )  [static]

Definition at line 4576 of file pbx_dundi.c.

References ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_module_user_hangup_all, AST_PTHREADT_NULL, ast_unregister_switch(), cli_dundi, dundi_function, dundi_switch, io, io_context_destroy(), mark_mappings(), mark_peers(), prune_mappings(), prune_peers(), sched, and sched_context_destroy().

04577 {
04578    pthread_t previous_netthreadid = netthreadid, previous_precachethreadid = precachethreadid, previous_clearcachethreadid = clearcachethreadid;
04579    ast_module_user_hangup_all();
04580 
04581    /* Stop all currently running threads */
04582    dundi_shutdown = 1;
04583    if (previous_netthreadid != AST_PTHREADT_NULL) {
04584       pthread_kill(previous_netthreadid, SIGURG);
04585       pthread_join(previous_netthreadid, NULL);
04586    }
04587    if (previous_precachethreadid != AST_PTHREADT_NULL) {
04588       pthread_kill(previous_precachethreadid, SIGURG);
04589       pthread_join(previous_precachethreadid, NULL);
04590    }
04591    if (previous_clearcachethreadid != AST_PTHREADT_NULL) {
04592       pthread_cancel(previous_clearcachethreadid);
04593       pthread_join(previous_clearcachethreadid, NULL);
04594    }
04595    
04596    ast_cli_unregister_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(struct ast_cli_entry));
04597    ast_unregister_switch(&dundi_switch);
04598    ast_custom_function_unregister(&dundi_function);
04599    close(netsocket);
04600    io_context_destroy(io);
04601    sched_context_destroy(sched);
04602 
04603    mark_mappings();
04604    prune_mappings();
04605    mark_peers();
04606    prune_peers();
04607 
04608    return 0;
04609 }

static void unregister_request ( struct dundi_request dr  )  [static]

Definition at line 3503 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, dr, and dundi_request::list.

Referenced by dundi_lookup_internal().

03504 {
03505    AST_LIST_LOCK(&peers);
03506    AST_LIST_REMOVE(&requests, dr, list);
03507    AST_LIST_UNLOCK(&peers);
03508 }

static int update_key ( struct dundi_peer peer  )  [static]

Definition at line 1288 of file pbx_dundi.c.

References aes_decrypt_key128(), aes_encrypt_key128(), ast_encrypt_bin, ast_key_get, AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log(), ast_sign_bin, build_iv(), dundi_eid_to_str(), dundi_peer::eid, dundi_peer::inkey, 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().

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


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Distributed Universal Number Discovery (DUNDi)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 4681 of file pbx_dundi.c.

struct dundi_peer* any_peer [static]

Wildcard peer.

This peer is created if the [*] entry is specified in dundi.conf

Definition at line 275 of file pbx_dundi.c.

Referenced by find_peer(), handle_command_response(), and set_config().

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 4681 of file pbx_dundi.c.

int authdebug = 0 [static]

Definition at line 117 of file pbx_dundi.c.

pthread_t clearcachethreadid = AST_PTHREADT_NULL [static]

Definition at line 114 of file pbx_dundi.c.

struct ast_cli_entry cli_dundi[] [static]

Definition at line 2806 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

char country[80] [static]

Definition at line 129 of file pbx_dundi.c.

Referenced by ind_load_module().

char cursecret[80] [static]

Definition at line 133 of file pbx_dundi.c.

char debug_usage[] [static]

Initial value:

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

Definition at line 2736 of file pbx_dundi.c.

int default_expiration = 60 [static]

Definition at line 123 of file pbx_dundi.c.

char dept[80] [static]

Definition at line 125 of file pbx_dundi.c.

int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME [static]

Definition at line 120 of file pbx_dundi.c.

int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE [static]

Definition at line 119 of file pbx_dundi.c.

int dundi_shutdown = 0 [static]

Definition at line 137 of file pbx_dundi.c.

struct ast_switch dundi_switch [static]

Definition at line 4408 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

int dundi_ttl = DUNDI_DEFAULT_TTL [static]

Definition at line 118 of file pbx_dundi.c.

int dundidebug = 0 [static]

Definition at line 116 of file pbx_dundi.c.

char email[80] [static]

Definition at line 130 of file pbx_dundi.c.

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

Definition at line 136 of file pbx_dundi.c.

Referenced by find_peer(), and set_config().

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 2800 of file pbx_dundi.c.

int global_autokilltimeout = 0 [static]

Definition at line 121 of file pbx_dundi.c.

dundi_eid global_eid [static]

Definition at line 122 of file pbx_dundi.c.

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

int global_storehistory = 0 [static]

Definition at line 124 of file pbx_dundi.c.

struct io_context* io [static]

Definition at line 109 of file pbx_dundi.c.

char ipaddr[80] [static]

Definition at line 134 of file pbx_dundi.c.

Referenced by realtime_update_peer().

char locality[80] [static]

Definition at line 127 of file pbx_dundi.c.

char lookup_usage[] [static]

Initial value:

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

Definition at line 2782 of file pbx_dundi.c.

int netsocket = -1 [static]

Definition at line 111 of file pbx_dundi.c.

Referenced by ast_netsock_bindaddr(), and handle_error().

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 112 of file pbx_dundi.c.

char no_debug_usage[] [static]

Initial value:

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

Definition at line 2740 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 2749 of file pbx_dundi.c.

char org[80] [static]

Definition at line 126 of file pbx_dundi.c.

Referenced by calc_crc().

char phone[80] [static]

Definition at line 131 of file pbx_dundi.c.

Referenced by privacy_exec().

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 2788 of file pbx_dundi.c.

pthread_t precachethreadid = AST_PTHREADT_NULL [static]

Definition at line 113 of file pbx_dundi.c.

char query_usage[] [static]

Initial value:

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

Definition at line 2794 of file pbx_dundi.c.

time_t rotatetime [static]

Definition at line 135 of file pbx_dundi.c.

struct sched_context* sched [static]

Definition at line 110 of file pbx_dundi.c.

char secretpath[80] [static]

Definition at line 132 of file pbx_dundi.c.

char show_entityid_usage[] [static]

Initial value:

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

Definition at line 2770 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 2762 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 2774 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 2754 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 2766 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 2778 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 2758 of file pbx_dundi.c.

char stateprov[80] [static]

Definition at line 128 of file pbx_dundi.c.

char store_history_usage[] [static]

Initial value:

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

Definition at line 2744 of file pbx_dundi.c.

int tos = 0 [static]

Definition at line 115 of file pbx_dundi.c.


Generated on Wed Feb 11 12:00:29 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7