Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:49:10 2009

## Asterisk developer's documentation

# pbx_dundi.c File Reference

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

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

Include dependency graph for pbx_dundi.c:

Go to the source code of this file.

## Data Structures

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

## Defines

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

## Functions

static void | abort_request (struct dundi_request *dr)
static int | ack_trans (struct dundi_transaction *trans, int iseqno)
static struct permission * | append_permission (struct permission *p, char *s, int allow)
static int | append_transaction (struct dundi_request *dr, struct dundi_peer *p, int ttl, dundi_eid *avoid[])
static void | apply_peer (struct dundi_transaction *trans, struct dundi_peer *p)
| AST_MUTEX_DEFINE_STATIC (pclock)
| AST_MUTEX_DEFINE_STATIC (peerlock)
static unsigned long | avoid_crc32 (dundi_eid *avoid[])
static void | build_iv (unsigned char *iv)
static void | build_mapping (char *name, char *value)
static void | build_peer (dundi_eid *eid, struct ast_variable *v, int *globalpcmode)
static void | build_secret (char *secret, int seclen)
static void | build_transactions (struct dundi_request *dr, int ttl, int order, int *foundcache, int *skipped, int blockempty, int nocache, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int directs[])
static int | cache_lookup (struct dundi_request *req, dundi_eid *peer_eid, unsigned long crc32, int *lowexpiration)
static int | cache_lookup_internal (time_t now, struct dundi_request *req, char *key, char *eid_str_full, int *lowexpiration)
static int | cache_save (dundi_eid *eidpeer, struct dundi_request *req, int start, int unaffected, int expiration, int push)
static int | cache_save_hint (dundi_eid *eidpeer, struct dundi_request *req, struct dundi_hint *hint, int expiration)
static void | cancel_request (struct dundi_request *dr)
static int | check_key (struct dundi_peer *peer, unsigned char *newkey, unsigned char *newsig, unsigned long keycrc32)
static void | check_password (void)
static int | check_request (struct dundi_request *dr)
static char * | complete_peer_4 (char *line, char *word, int pos, int state)
static char * | complete_peer_helper (char *line, char *word, int pos, int state, int rpos)
static struct dundi_transaction * | create_transaction (struct dundi_peer *p)
static int | decrypt_memcpy (unsigned char *dst, unsigned char *src, int len, unsigned char *iv, aes_decrypt_ctx *dcx)
char * | description (void)
| Provides a description of the module.
static void | destroy_map (struct dundi_mapping *map)
static void | destroy_packet (struct dundi_packet *pack, int needfree)
static void | destroy_packets (struct dundi_packet *p)
static void | destroy_peer (struct dundi_peer *peer)
static void | destroy_permissions (struct permission *p)
static void | destroy_trans (struct dundi_transaction *trans, int fromtimeout)
static int | discover_transactions (struct dundi_request *dr)
static int | do_autokill (void *data)
static int | do_qualify (void *data)
static int | do_register (void *data)
static int | do_register_expire (void *data)
static int | dundi_ack (struct dundi_transaction *trans, int final)
static int | dundi_answer_entity (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
static int | dundi_answer_query (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
static int | dundi_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static void | dundi_debug_output (const char *data)
static struct dundi_hdr * | dundi_decrypt (struct dundi_transaction *trans, unsigned char *dst, int *dstlen, struct dundi_hdr *ohdr, struct dundi_encblock *src, int srclen)
static int | dundi_discover (struct dundi_transaction *trans)
static int | dundi_do_debug (int fd, int argc, char *argv[])
static int | dundi_do_lookup (int fd, int argc, char *argv[])
static int | dundi_do_precache (int fd, int argc, char *argv[])
static int | dundi_do_query (int fd, int argc, char *argv[])
static int | dundi_do_store_history (int fd, int argc, char *argv[])
static int | dundi_encrypt (struct dundi_transaction *trans, struct dundi_packet *pack)
static void | dundi_error_output (const char *data)
static int | dundi_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, const char *data)
static int | dundi_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static int | dundi_flush (int fd, int argc, char *argv[])
static int | dundi_helper (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *data, int flag)
static void | dundi_ie_append_eid_appropriately (struct dundi_ie_data *ied, char *context, dundi_eid *eid, dundi_eid *us)
int | dundi_lookup (struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int cbypass)
| Lookup the given number in the given dundi context (or e164 if unspecified) using the given callerid (if specified) and return up to maxret results in the array specified. returns the number of results found or -1 on a hangup of teh channel.
static int | dundi_lookup_exec (struct ast_channel *chan, void *data)
static int | dundi_lookup_internal (struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *md, int *expiration, int cybpass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[])
static int | dundi_lookup_local (struct dundi_result *dr, struct dundi_mapping *map, char *called_number, dundi_eid *us_eid, int anscnt, struct dundi_hint_metadata *hmd)
static void * | dundi_lookup_thread (void *data)
static int | dundi_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static int | dundi_no_debug (int fd, int argc, char *argv[])
static int | dundi_no_store_history (int fd, int argc, char *argv[])
int | dundi_precache (const char *context, const char *number)
| Pre-cache to push upstream peers.
static void | dundi_precache_full (void)
static int | dundi_precache_internal (const char *context, const char *number, int ttl, dundi_eid *avoids[])
static void * | dundi_precache_thread (void *data)
static int | dundi_prop_precache (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
static int | dundi_query (struct dundi_transaction *trans)
int | dundi_query_eid (struct dundi_entity_info *dei, const char *dcontext, dundi_eid eid)
| Retrieve information on a specific EID.
static int | dundi_query_eid_internal (struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[])
static void * | dundi_query_thread (void *data)
static void | dundi_reject (struct dundi_hdr *h, struct sockaddr_in *sin)
static int | dundi_rexmit (void *data)
static int | dundi_send (struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
static int | dundi_show_entityid (int fd, int argc, char *argv[])
static int | dundi_show_mappings (int fd, int argc, char *argv[])
static int | dundi_show_peer (int fd, int argc, char *argv[])
static int | dundi_show_peers (int fd, int argc, char *argv[])
static int | dundi_show_precache (int fd, int argc, char *argv[])
static int | dundi_show_requests (int fd, int argc, char *argv[])
static int | dundi_show_trans (int fd, int argc, char *argv[])
static int | dundi_xmit (struct dundi_packet *pack)
static char * | dundifunc_read (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
static int | encrypt_memcpy (unsigned char *dst, unsigned char *src, int len, unsigned char *iv, aes_encrypt_ctx *ecx)
static struct dundi_peer * | find_peer (dundi_eid *eid)
static struct dundi_transaction * | find_transaction (struct dundi_hdr *hdr, struct sockaddr_in *sin)
static int | get_trans_id (void)
static int | handle_command_response (struct dundi_transaction *trans, struct dundi_hdr *hdr, int datalen, int encrypted)
static int | handle_frame (struct dundi_hdr *h, struct sockaddr_in *sin, int datalen)
static int | has_permission (struct permission *ps, char *cont)
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module (void)
| Initialize the module.
static void | load_password (void)
static void | mark_mappings (void)
static void | mark_peers (void)
static char * | model2str (int model)
static void * | network_thread (void *ignore)
static int | optimize_transactions (struct dundi_request *dr, int order)
static void | populate_addr (struct dundi_peer *peer, dundi_eid *eid)
static int | precache_trans (struct dundi_transaction *trans, struct dundi_mapping *maps, int mapcount, int *minexp, int *foundanswers)
static int | precache_transactions (struct dundi_request *dr, struct dundi_mapping *maps, int mapcount, int *expiration, int *foundanswers)
static void * | process_precache (void *ign)
static void | prune_mappings (void)
static void | prune_peers (void)
static void | qualify_peer (struct dundi_peer *peer, int schedonly)
static int | query_transactions (struct dundi_request *dr)
static int | register_request (struct dundi_request *dr, struct dundi_request **pending)
int | reload (void)
| Reload stuff.
static void | reschedule_precache (const char *number, const char *context, int expiration)
static int | rescomp (const void *a, const void *b)
static void | reset_global_eid (void)
static int | reset_transaction (struct dundi_transaction *trans)
static void | save_secret (const char *newkey, const char *oldkey)
static int | set_config (char *config_file, struct sockaddr_in *sin)
static int | socket_read (int *id, int fd, short events, void *cbdata)
static void | sort_results (struct dundi_result *results, int count)
static int | start_network_thread (void)
static int | str2tech (char *str)
static char * | tech2str (int tech)
int | unload_module (void)
| Cleanup all module structures, sockets, etc.
static void | unregister_request (struct dundi_request *dr)
static int | update_key (struct dundi_peer *peer)
int | usecount (void)
| Provides a usecount.

## Variables

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

## Detailed Description

Distributed Universal Number Discovery (DUNDi).

Definition in file pbx_dundi.c.

## Define Documentation

#define DUNDI_FLAG_INTERNAL_NOPARTIAL (1 << 17)

Definition at line 111 of file pbx_dundi.c.

Referenced by build_mapping(), and dundi_lookup_local().

#define DUNDI_MODEL_INBOUND (1 << 0)

Definition at line 96 of file pbx_dundi.c.

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

#define DUNDI_MODEL_OUTBOUND (1 << 1)

Definition at line 97 of file pbx_dundi.c.

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

#define DUNDI_MODEL_SYMMETRIC (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)

Definition at line 98 of file pbx_dundi.c.

Referenced by build_peer(), and model2str().

#define DUNDI_SECRET_TIME DUNDI_DEFAULT_CACHE_TIME

Definition at line 116 of file pbx_dundi.c.

Referenced by load_password(), and save_secret().

#define DUNDI_TIMING_HISTORY 10

Definition at line 101 of file pbx_dundi.c.

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

#define FLAG_DEAD (1 << 1)

Definition at line 104 of file pbx_dundi.c.

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

#define FLAG_ENCRYPT (1 << 4)

Definition at line 107 of file pbx_dundi.c.

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

#define FLAG_FINAL (1 << 2)

Definition at line 105 of file pbx_dundi.c.

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

#define FLAG_ISQUAL (1 << 3)

Definition at line 106 of file pbx_dundi.c.

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

#define FLAG_ISREG (1 << 0)

Definition at line 103 of file pbx_dundi.c.

Referenced by destroy_trans(), and do_register().

#define FLAG_SENDFULLKEY (1 << 5)

Definition at line 108 of file pbx_dundi.c.

Referenced by create_transaction(), dundi_encrypt(), and handle_command_response().

#define FLAG_STOREHIST (1 << 6)

Definition at line 109 of file pbx_dundi.c.

Referenced by create_transaction(), and destroy_trans().

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

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

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

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

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

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

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

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

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

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

#define KEY_IN 1

Definition at line 120 of file pbx_dundi.c.

#define KEY_OUT 0

Definition at line 119 of file pbx_dundi.c.

#define MAX_OPTS 128

Definition at line 4124 of file pbx_dundi.c.

Referenced by build_mapping().

#define MAX_PACKET_SIZE 8192

Definition at line 76 of file pbx_dundi.c.

Referenced by handle_command_response(), and socket_read().

#define MAX_RESULTS 64

Definition at line 74 of file pbx_dundi.c.

## Function Documentation

static void abort_request | ( | struct dundi_request * | dr | ) | `[static]`

Definition at line 3386 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), destroy_trans(), and dundi_request::trans.

Referenced by dundi_lookup_internal().

    03387 {
    03388    ast_mutex_lock(&peerlock);
    03389    while(dr->trans)
    03390       destroy_trans(dr->trans, 0);
    03391    ast_mutex_unlock(&peerlock);
    03392 }

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

Definition at line 1924 of file pbx_dundi.c.

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

Referenced by handle_frame().

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

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

Definition at line 4102 of file pbx_dundi.c.

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

Referenced by build_peer().

    04103 {
    04104    struct permission *start;
    04105    start = p;
    04106    if (p) {
    04107       while(p->next)
    04108          p = p->next;
    04109    }
    04110    if (p) {
    04111       p->next = malloc(sizeof(struct permission) + strlen(s) + 1);
    04112       p = p->next;
    04113    } else {
    04114       p = malloc(sizeof(struct permission) + strlen(s) + 1);
    04115    }
    04116    if (p) {
    04117       memset(p, 0, sizeof(struct permission));
    04118       memcpy(p->name, s, strlen(s) + 1);
    04119       p->allow = allow;
    04120    }
    04121    return start ? start : p;
    04122 }

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

Definition at line 3339 of file pbx_dundi.c.

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

Referenced by build_transactions().

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

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

Definition at line 1267 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(), and handle_command_response().

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

AST_MUTEX_DEFINE_STATIC | ( | pclock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | peerlock |  | ) |

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    unsigned long 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 503 of file pbx_dundi.c.

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

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

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

Definition at line 4126 of file pbx_dundi.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), dundi_mapping::dcontext, dundi_mapping::dead, dundi_mapping::dest, DUNDI_FLAG_COMMERCIAL, DUNDI_FLAG_INTERNAL_NOPARTIAL, DUNDI_FLAG_MOBILE, DUNDI_FLAG_NOCOMUNSOLICIT, DUNDI_FLAG_NOUNSOLICITED, DUNDI_FLAG_RESIDENTIAL, dundi_mapping::lcontext, LOG_WARNING, malloc, map, mappings, MAX_OPTS, dundi_mapping::next, dundi_mapping::options, str2tech(), t, dundi_mapping::tech, and dundi_mapping::weight.

Referenced by set_config().

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

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

Definition at line 4287 of file pbx_dundi.c.

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

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

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

Definition at line 2017 of file pbx_dundi.c.

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

Referenced by check_password(), and load_password().

    02018 {
    02019    unsigned char tmp[16];
    02020    char *s;
    02021    build_iv(tmp);
    02022    secret[0] = '\0';
    02023    ast_base64encode(secret, tmp, sizeof(tmp), seclen);
    02024    /* Eliminate potential bad characters */
    02025    while((s = strchr(secret, ';'))) *s = '+';
    02026    while((s = strchr(secret, '/'))) *s = '+';
    02027    while((s = strchr(secret, ':'))) *s = '+';
    02028    while((s = strchr(secret, '@'))) *s = '+';
    02029 }

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

References append_transaction(), ast_clear_flag_nonstd, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), cache_lookup(), dundi_request::crc32, dundi_request::dcontext, dundi_eid_cmp(), dundi_eid_to_str(), dundi_eid_zero(), DUNDI_HINT_UNAFFECTED, DUNDI_MODEL_OUTBOUND, dundi_peer::eid, dundi_request::expiration, has_permission(), dundi_request::hmd, dundi_peer::include, LOG_DEBUG, dundi_peer::model, dundi_peer::next, dundi_peer::order, pass, dundi_peer::pcmodel, peers, dundi_peer::permit, and dundi_peer::us_eid.

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

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

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

Definition at line 1215 of file pbx_dundi.c.

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

Referenced by build_transactions().

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

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

Definition at line 1143 of file pbx_dundi.c.

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

Referenced by cache_lookup().

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

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

Definition at line 851 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 dundi_prop_precache(), and handle_command_response().

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

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

Definition at line 816 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 dundi_prop_precache(), and handle_command_response().

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

static void cancel_request | ( | struct dundi_request * | dr | ) | `[static]`

Definition at line 3367 of file pbx_dundi.c.

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

Referenced by dundi_lookup_internal(), and dundi_precache_internal().

    03368 {
    03369    struct dundi_transaction *trans, *next;
    03370
    03371    ast_mutex_lock(&peerlock);
    03372    trans = dr->trans;
    03373
    03374    while(trans) {
    03375       next = trans->next;
    03376       /* Orphan transaction from request */
    03377       trans->parent = NULL;
    03378       trans->next = NULL;
    03379       /* Send final cancel */
    03380       dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
    03381       trans = next;
    03382    }
    03383    ast_mutex_unlock(&peerlock);
    03384 }

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

Definition at line 1466 of file pbx_dundi.c.

References aes_decrypt_key128(), aes_encrypt_key128(), ast_check_signature_bin, ast_decrypt_bin, ast_key_get, AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log(), dundi_eid_to_str(), dundi_peer::eid, dundi_peer::inkey, key(), LOG_DEBUG, LOG_NOTICE, option_debug, dundi_peer::outkey, dundi_peer::rxenckey, dundi_peer::them_dcx, dundi_peer::them_ecx, and dundi_peer::them_keycrc32.

Referenced by handle_command_response().

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

static void check_password | ( | void |  | ) | `[static]`

Definition at line 2084 of file pbx_dundi.c.

References build_secret(), and save_secret().

Referenced by network_thread().

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

static int check_request | ( | struct dundi_request * | dr | ) | `[static]`

Definition at line 3507 of file pbx_dundi.c.

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

Referenced by dundi_lookup_internal().

    03508 {
    03509    struct dundi_request *cur;
    03510    int res = 0;
    03511    ast_mutex_lock(&peerlock);
    03512    cur = requests;
    03513    while(cur) {
    03514       if (cur == dr) {
    03515          res = 1;
    03516          break;
    03517       }
    03518       cur = cur->next;
    03519    }
    03520    ast_mutex_unlock(&peerlock);
    03521    return res;
    03522 }

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

Definition at line 2274 of file pbx_dundi.c.

References complete_peer_helper().

    02275 {
    02276    return complete_peer_helper(line, word, pos, state, 3);
    02277 }

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

Definition at line 2249 of file pbx_dundi.c.

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

Referenced by complete_peer_4().

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

static struct dundi_transaction * create_transaction | ( | struct dundi_peer * | p | ) | `[static, read]`

Definition at line 2782 of file pbx_dundi.c.

References dundi_peer::addr, dundi_transaction::allnext, alltrans, apply_peer(), ast_set_flag, dundi_transaction::autokillid, DUNDI_DEFAULT_RETRANS_TIMER, FLAG_SENDFULLKEY, FLAG_STOREHIST, get_trans_id(), malloc, dundi_transaction::retranstimer, dundi_peer::sentfullkey, dundi_transaction::start, and dundi_transaction::strans.

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

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

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

Definition at line 1358 of file pbx_dundi.c.

References aes_decrypt().

Referenced by dundi_decrypt().

    01359 {
    01360    unsigned char lastblock[16];
    01361    int x;
    01362    memcpy(lastblock, iv, sizeof(lastblock));
    01363    while(len > 0) {
    01364       aes_decrypt(src, dst, dcx);
    01365       for (x=0;x<16;x++)
    01366          dst[x] ^= lastblock[x];
    01367       memcpy(lastblock, src, sizeof(lastblock));
    01368       dst += 16;
    01369       src += 16;
    01370       len -= 16;
    01371    }
    01372    return 0;
    01373 }

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 4820 of file pbx_dundi.c.

    04821 {
    04822    return tdesc;
    04823 }

static void destroy_map | ( | struct dundi_mapping * | map | ) | `[static]`

Definition at line 4055 of file pbx_dundi.c.

References free.

Referenced by prune_mappings().

    04056 {
    04057    free(map);
    04058 }

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

Definition at line 2831 of file pbx_dundi.c.

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

Referenced by ack_trans().

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

static void destroy_packets | ( | struct dundi_packet * | p | ) | `[static]`

Definition at line 1911 of file pbx_dundi.c.

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

Referenced by ack_trans(), destroy_trans(), and handle_frame().

    01912 {
    01913    struct dundi_packet *prev;
    01914    while(p) {
    01915       prev = p;
    01916       p = p->next;
    01917       if (prev->retransid > -1)
    01918          ast_sched_del(sched, prev->retransid);
    01919       free(prev);
    01920    }
    01921 }

static void destroy_peer | ( | struct dundi_peer * | peer | ) | `[static]`

Definition at line 4040 of file pbx_dundi.c.

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

    04041 {
    04042    if (peer->registerid > -1)
    04043       ast_sched_del(sched, peer->registerid);
    04044    if (peer->regtrans)
    04045       destroy_trans(peer->regtrans, 0);
    04046    if (peer->keypending)
    04047       destroy_trans(peer->keypending, 0);
    04048    if (peer->qualifyid > -1)
    04049       ast_sched_del(sched, peer->qualifyid);
    04050    destroy_permissions(peer->permit);
    04051    destroy_permissions(peer->include);
    04052    free(peer);
    04053 }

static void destroy_permissions | ( | struct permission * | p | ) | `[static]`

Definition at line 4030 of file pbx_dundi.c.

References free, and permission::next.

Referenced by build_peer(), and destroy_peer().

    04031 {
    04032    struct permission *prev;
    04033    while(p) {
    04034       prev = p;
    04035       p = p->next;
    04036       free(prev);
    04037    }
    04038 }

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

Definition at line 2859 of file pbx_dundi.c.

References dundi_transaction::allnext, alltrans, ast_log(), ast_sched_del(), ast_set_flag, ast_strlen_zero(), ast_test_flag, dundi_transaction::autokillid, dundi_peer::avgms, dundi_request::dcontext, destroy_packets(), dundi_eid_cmp(), dundi_eid_to_str(), DUNDI_TIMING_HISTORY, dundi_peer::eid, FLAG_DEAD, FLAG_ISQUAL, FLAG_ISREG, FLAG_STOREHIST, free, dundi_peer::keypending, dundi_peer::lastms, dundi_transaction::lasttrans, LOG_NOTICE, dundi_peer::lookups, dundi_peer::lookuptimes, malloc, dundi_peer::maxms, dundi_transaction::next, dundi_peer::next, dundi_request::number, dundi_transaction::packets, dundi_transaction::parent, peers, dundi_request::pfds, dundi_peer::qualtrans, dundi_peer::qualtx, dundi_peer::regtrans, dundi_transaction::start, dundi_transaction::them_eid, dundi_transaction::thread, and dundi_request::trans.

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().

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

static int discover_transactions | ( | struct dundi_request * | dr | ) | `[static]`

Definition at line 3218 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dundi_discover(), dundi_transaction::next, and dundi_request::trans.

Referenced by dundi_lookup_internal().

    03219 {
    03220    struct dundi_transaction *trans;
    03221    ast_mutex_lock(&peerlock);
    03222    trans = dr->trans;
    03223    while(trans) {
    03224       dundi_discover(trans);
    03225       trans = trans->next;
    03226    }
    03227    ast_mutex_unlock(&peerlock);
    03228    return 0;
    03229 }

static int do_autokill | ( | void * | data | ) | `[static]`

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

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

static int do_qualify | ( | void * | data | ) | `[static]`

Definition at line 4229 of file pbx_dundi.c.

References qualify_peer(), and dundi_peer::qualifyid.

Referenced by qualify_peer().

    04230 {
    04231    struct dundi_peer *peer;
    04232    peer = data;
    04233    peer->qualifyid = -1;
    04234    qualify_peer(peer, 0);
    04235    return 0;
    04236 }

static int do_register | ( | void * | data | ) | `[static]`

Definition at line 4202 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, dundi_transaction::us_eid, and dundi_peer::us_eid.

Referenced by build_peer().

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

static int do_register_expire | ( | void * | data | ) | `[static]`

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

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

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

Definition at line 378 of file pbx_dundi.c.

References DUNDI_COMMAND_ACK, and dundi_send().

Referenced by handle_command_response(), and handle_frame().

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

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

Definition at line 755 of file pbx_dundi.c.

References ast_log(), ast_pthread_create, dundi_ies::called_context, 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_ies::eidcount, dundi_query_state::eids, dundi_ies::eids, dundi_query_state::fluffy, free, LOG_DEBUG, LOG_WARNING, malloc, dundi_ies::reqeid, dundi_query_state::reqeid, s, dundi_transaction::thread, dundi_query_state::trans, dundi_ies::ttl, and dundi_query_state::ttl.

Referenced by handle_command_response().

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

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

Definition at line 1049 of file pbx_dundi.c.

References ast_log(), ast_pthread_create, dundi_ies::called_context, dundi_query_state::called_context, dundi_ies::called_number, dundi_query_state::called_number, dundi_ies::cbypass, 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_ies::eid_direct, dundi_ies::eidcount, dundi_query_state::eids, dundi_ies::eids, dundi_query_state::fluffy, free, LOG_DEBUG, LOG_WARNING, malloc, mappings, dundi_query_state::maps, dundi_mapping::next, dundi_query_state::nocache, dundi_query_state::nummaps, s, dundi_transaction::thread, dundi_query_state::trans, dundi_ies::ttl, and dundi_query_state::ttl.

Referenced by handle_command_response().

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

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

References DUNDI_FLAG_CANMATCH, and dundi_helper().

    04488 {
    04489    return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH);
    04490 }

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

Definition at line 283 of file pbx_dundi.c.

References ast_verbose().

Referenced by load_module().

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

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

Definition at line 1375 of file pbx_dundi.c.

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

Referenced by handle_command_response().

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

static int dundi_discover | ( | struct dundi_transaction * | trans | ) | `[static]`

Definition at line 3106 of file pbx_dundi.c.

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

Referenced by discover_transactions().

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

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

Definition at line 2164 of file pbx_dundi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

    02165 {
    02166    if (argc != 2)
    02167       return RESULT_SHOWUSAGE;
    02168    dundidebug = 1;
    02169    ast_cli(fd, "DUNDi Debugging Enabled\n");
    02170    return RESULT_SUCCESS;
    02171 }

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

Definition at line 2296 of file pbx_dundi.c.

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

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

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

Definition at line 2337 of file pbx_dundi.c.

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

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

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

Definition at line 2362 of file pbx_dundi.c.

References ast_cli(), context, dundi_entity_info::country, dundi_query_eid(), dundi_str_to_eid(), dundi_entity_info::email, dundi_entity_info::ipaddr, dundi_entity_info::locality, dundi_entity_info::org, dundi_entity_info::orgunit, dundi_entity_info::phone, RESULT_SHOWUSAGE, RESULT_SUCCESS, and dundi_entity_info::stateprov.

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

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

Definition at line 2173 of file pbx_dundi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

    02174 {
    02175    if (argc != 3)
    02176       return RESULT_SHOWUSAGE;
    02177    global_storehistory = 1;
    02178    ast_cli(fd, "DUNDi History Storage Enabled\n");
    02179    return RESULT_SUCCESS;
    02180 }

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

Definition at line 1399 of file pbx_dundi.c.

References ast_log(), ast_set_flag, ast_test_flag, dundi_ie_data::buf, build_iv(), dundi_hdr::cmdflags, dundi_hdr::cmdresp, dundi_packet::data, dundi_packet::datalen, dundi_transaction::dcx, DUNDI_COMMAND_ENCRYPT, dundi_ie_append_eid(), dundi_ie_append_encdata(), dundi_ie_append_int(), dundi_ie_append_raw(), DUNDI_IE_EID, DUNDI_IE_ENCDATA, DUNDI_IE_KEYCRC32, DUNDI_IE_SHAREDKEY, DUNDI_IE_SIGNATURE, dundi_transaction::ecx, encrypt_memcpy(), find_peer(), FLAG_SENDFULLKEY, dundi_packet::h, dundi_hdr::ies, dundi_hdr::iseqno, LOG_DEBUG, LOG_NOTICE, dundi_hdr::oseqno, dundi_ie_data::pos, 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().

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

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

Definition at line 289 of file pbx_dundi.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

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

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

Definition at line 4492 of file pbx_dundi.c.

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

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

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

References DUNDI_FLAG_EXISTS, and dundi_helper().

    04483 {
    04484    return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS);
    04485 }

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

Definition at line 2182 of file pbx_dundi.c.

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

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

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

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

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

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

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

Definition at line 3082 of file pbx_dundi.c.

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

Referenced by dundi_discover().

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

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, dundi_lookup_internal(), and dundi_hint_metadata::flags.

Referenced by dundi_do_lookup(), dundi_exec(), dundi_helper(), dundi_lookup_exec(), 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_log(), ast_set_flag_nonstd, ast_waitfor_n_fd(), avoid_crc32(), build_transactions(), cancel_request(), dundi_request::cbypass, check_request(), dundi_request::crc32, dundi_request::dcontext, discover_transactions(), dundi_request::dr, dundi_eid_cmp(), dundi_eid_to_str(), DUNDI_FLUFF_TIME, DUNDI_HINT_TTL_EXPIRED, DUNDI_TTL_TIME, dundi_request::expiration, dundi_request::hmd, LOG_DEBUG, LOG_WARNING, dundi_request::maxcount, ast_channel::name, dundi_request::number, optimize_transactions(), dundi_request::pfds, register_request(), dundi_request::respcount, dundi_request::root_eid, dundi_request::trans, 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 && !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(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 529 of file pbx_dundi.c.

References ast_canmatch_extension(), ast_clear_flag, ast_clear_flag_nonstd, ast_copy_flags, ast_exists_extension(), AST_FLAGS_ALL, ast_ignore_pattern(), AST_LIST_EMPTY, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_matchmore_extension(), AST_MAX_EXTENSION, ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_var_assign(), ast_var_delete(), dundi_result::dest, dundi_mapping::dest, dundi_eid_to_str(), DUNDI_FLAG_CANMATCH, DUNDI_FLAG_EXISTS, DUNDI_FLAG_IGNOREPAT, DUNDI_FLAG_INTERNAL_NOPARTIAL, DUNDI_FLAG_MATCHMORE, DUNDI_HINT_DONT_ASK, dundi_result::eid, dundi_result::expiration, dundi_hint_metadata::exten, dundi_mapping::lcontext, dundi_mapping::options, pbx_substitute_variables_varshead(), dundi_result::tech, dundi_mapping::tech, tech2str(), dundi_result::techint, dundi_mapping::weight, and dundi_result::weight.

Referenced by dundi_lookup_thread(), and precache_trans().

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

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

Definition at line 604 of file pbx_dundi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_test_flag_nonstd, dundi_query_state::called_context, dundi_query_state::called_number, destroy_trans(), dundi_query_state::directs, 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, dundi_result::expiration, dundi_hint_metadata::exten, FLAG_DEAD, dundi_hint_metadata::flags, free, LOG_DEBUG, dundi_query_state::maps, dundi_query_state::nocache, dundi_query_state::nummaps, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, dundi_transaction::us_eid, and dundi_result::weight.

Referenced by dundi_answer_query().

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

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

Definition at line 4544 of file pbx_dundi.c.

References DUNDI_FLAG_MATCHMORE, and dundi_helper().

    04545 {
    04546    return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE);
    04547 }

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

Definition at line 2217 of file pbx_dundi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

    02218 {
    02219    if (argc != 3)
    02220       return RESULT_SHOWUSAGE;
    02221    dundidebug = 0;
    02222    ast_cli(fd, "DUNDi Debugging Disabled\n");
    02223    return RESULT_SUCCESS;
    02224 }

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

Definition at line 2226 of file pbx_dundi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

    02227 {
    02228    if (argc != 4)
    02229       return RESULT_SHOWUSAGE;
    02230    global_storehistory = 0;
    02231    ast_cli(fd, "DUNDi History Storage Disabled\n");
    02232    return RESULT_SUCCESS;
    02233 }

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

Pre-cache to push upstream peers.

Definition at line 3799 of file pbx_dundi.c.

References dundi_precache_internal().

Referenced by dundi_do_precache(), and process_precache().

    03800 {
    03801    dundi_eid *avoid[1] = { NULL, };
    03802    return dundi_precache_internal(context, number, dundi_ttl, avoid);
    03803 }

static void dundi_precache_full | ( | void |  | ) | `[static]`

Definition at line 3696 of file pbx_dundi.c.

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

Referenced by set_config().

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

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

Definition at line 3724 of file pbx_dundi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_waitfor_n_fd(), build_transactions(), cancel_request(), dundi_request::dcontext, dundi_request::dr, DUNDI_FLUFF_TIME, DUNDI_TTL_TIME, dundi_request::expiration, dundi_request::hmd, LOG_DEBUG, LOG_NOTICE, mappings, dundi_request::maxcount, dundi_mapping::next, dundi_request::number, optimize_transactions(), dundi_request::pfds, precache_transactions(), reschedule_precache(), and dundi_request::trans.

Referenced by dundi_precache(), and dundi_precache_thread().

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

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

Definition at line 668 of file pbx_dundi.c.

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

Referenced by dundi_prop_precache().

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

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

Definition at line 892 of file pbx_dundi.c.

References dundi_ies::anscount, dundi_ies::answers, ast_clear_flag_nonstd, ast_log(), ast_pthread_create, cache_save(), cache_save_hint(), dundi_query_state::called_context, dundi_ies::called_context, dundi_query_state::called_number, dundi_ies::called_number, dundi_ies::cbypass, dundi_answer::data, dundi_mapping::dcontext, dundi_request::dcontext, dundi_result::dest, dundi_query_state::directs, dundi_request::dr, DUNDI_CAUSE_GENERAL, DUNDI_COMMAND_PRECACHERP, dundi_eid_cmp(), dundi_eid_to_str(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, dundi_ie_append_cause(), DUNDI_IE_CAUSE, dundi_precache_thread(), dundi_send(), dundi_answer::eid, dundi_result::eid, dundi_ies::eid_direct, dundi_result::eid_str, dundi_ies::eidcount, dundi_query_state::eids, dundi_ies::eids, dundi_result::expiration, dundi_ies::expiration, dundi_request::expiration, dundi_answer::flags, dundi_result::flags, dundi_hint_metadata::flags, dundi_query_state::fluffy, free, dundi_ies::hint, dundi_request::hmd, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, malloc, mappings, dundi_query_state::maps, dundi_request::maxcount, dundi_mapping::next, dundi_query_state::nocache, dundi_request::number, dundi_query_state::nummaps, dundi_transaction::parent, dundi_request::pfds, dundi_answer::protocol, dundi_request::respcount, s, dundi_result::tech, tech2str(), dundi_result::techint, dundi_transaction::them_eid, dundi_transaction::thread, dundi_query_state::trans, dundi_ies::ttl, dundi_query_state::ttl, dundi_answer::weight, and dundi_result::weight.

Referenced by handle_command_response().

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

static int dundi_query | ( | struct dundi_transaction * | trans | ) | `[static]`

Definition at line 3196 of file pbx_dundi.c.

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

Referenced by query_transactions().

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

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

Retrieve information on a specific EID.

Definition at line 3852 of file pbx_dundi.c.

References dundi_query_eid_internal().

Referenced by dundi_do_query().

    03853 {
    03854    dundi_eid *avoid[1] = { NULL, };
    03855    struct dundi_hint_metadata hmd;
    03856    memset(&hmd, 0, sizeof(hmd));
    03857    return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid);
    03858 }

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

References ast_set_flag_nonstd, build_transactions(), dundi_request::dcontext, dundi_request::dei, DUNDI_FLUFF_TIME, DUNDI_HINT_TTL_EXPIRED, DUNDI_TTL_TIME, dundi_request::hmd, optimize_transactions(), dundi_request::pfds, dundi_request::query_eid, query_transactions(), dundi_request::respcount, dundi_request::root_eid, and dundi_request::trans.

Referenced by dundi_query_eid(), and dundi_query_thread().

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

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

Definition at line 701 of file pbx_dundi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_test_flag, dundi_query_state::called_context, dundi_query_state::called_number, dundi_entity_info::country, 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, dundi_entity_info::email, dundi_hint_metadata::exten, FLAG_DEAD, dundi_hint_metadata::flags, free, dundi_entity_info::ipaddr, dundi_entity_info::locality, LOG_DEBUG, dundi_entity_info::org, dundi_entity_info::orgunit, dundi_entity_info::phone, dundi_query_state::reqeid, dundi_entity_info::stateprov, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, and dundi_transaction::us_eid.

Referenced by dundi_answer_entity().

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

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

Definition at line 382 of file pbx_dundi.c.

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

Referenced by handle_frame().

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

static int dundi_rexmit | ( | void * | data | ) | `[static]`

Definition at line 2973 of file pbx_dundi.c.

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

Referenced by dundi_send().

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

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

Definition at line 2998 of file pbx_dundi.c.

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

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

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

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

Definition at line 2581 of file pbx_dundi.c.

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

    02582 {
    02583    char eid_str[20];
    02584    if (argc != 3)
    02585       return RESULT_SHOWUSAGE;
    02586    ast_mutex_lock(&peerlock);
    02587    dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid);
    02588    ast_mutex_unlock(&peerlock);
    02589    ast_cli(fd, "Global EID for this system is '%s'\n", eid_str);
    02590    return RESULT_SUCCESS;
    02591 }

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

Definition at line 2615 of file pbx_dundi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dundi_mapping::dcontext, dundi_mapping::dest, dundi_flags2str(), FORMAT, FORMAT2, dundi_mapping::lcontext, map, mappings, dundi_mapping::next, dundi_mapping::options, RESULT_SHOWUSAGE, RESULT_SUCCESS, dundi_mapping::tech, tech2str(), and dundi_mapping::weight.

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

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

Definition at line 2400 of file pbx_dundi.c.

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

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

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

Definition at line 2476 of file pbx_dundi.c.

References dundi_peer::addr, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), dundi_peer::avgms, dundi_eid_to_str(), dundi_peer::dynamic, dundi_peer::eid, FORMAT, FORMAT2, dundi_peer::lastms, dundi_peer::maxms, dundi_peer::model, model2str(), dundi_peer::next, peers, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 2636 of file pbx_dundi.c.

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

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

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

Definition at line 2593 of file pbx_dundi.c.

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

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

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

Definition at line 2561 of file pbx_dundi.c.

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

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

static int dundi_xmit | ( | struct dundi_packet * | pack | ) | `[static]`

Definition at line 2814 of file pbx_dundi.c.

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

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

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

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

Definition at line 3929 of file pbx_dundi.c.

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

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

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

Definition at line 1342 of file pbx_dundi.c.

References aes_encrypt().

Referenced by dundi_encrypt().

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

static struct dundi_peer* find_peer | ( | dundi_eid * | eid | ) | `[static, read]`

Definition at line 489 of file pbx_dundi.c.

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

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

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

Definition at line 336 of file pbx_dundi.c.

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

Referenced by handle_frame().

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

static int get_trans_id | ( | void |  | ) | `[static]`

Definition at line 454 of file pbx_dundi.c.

References dundi_transaction::allnext, alltrans, dundi_transaction::strans, and t.

Referenced by create_transaction(), and reset_transaction().

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

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

Definition at line 1520 of file pbx_dundi.c.

References dundi_peer::addr, dundi_transaction::addr, dundi_ies::anscount, dundi_ies::answers, apply_peer(), dundi_transaction::aseqno, ast_clear_flag, ast_clear_flag_nonstd, ast_db_put(), ast_inet_ntoa(), ast_log(), ast_sched_add(), ast_sched_del(), ast_set_flag, ast_set_flag_nonstd, ast_strlen_zero(), ast_test_flag, ast_test_flag_nonstd, ast_verbose(), cache_save(), cache_save_hint(), dundi_ies::called_context, dundi_ies::called_number, dundi_ies::cause, check_key(), dundi_hdr::cmdresp, dundi_entity_info::country, dundi_hint::data, dundi_answer::data, dundi_packet::datalen, dundi_request::dcontext, dundi_transaction::dcx, dundi_request::dei, dundi_result::dest, do_register_expire(), dundi_request::dr, dundi_ack(), 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_ENCREJ, DUNDI_COMMAND_ENCRYPT, DUNDI_COMMAND_INVALID, DUNDI_COMMAND_NULL, DUNDI_COMMAND_PRECACHERP, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, DUNDI_COMMAND_REGRESPONSE, DUNDI_COMMAND_UNKNOWN, dundi_decrypt(), dundi_eid_cmp(), dundi_eid_to_str(), dundi_eid_to_str_short(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_TTL_EXPIRED, DUNDI_HINT_UNAFFECTED, dundi_ie_append_byte(), dundi_ie_append_cause(), dundi_ie_append_eid(), dundi_ie_append_encdata(), dundi_ie_append_raw(), dundi_ie_append_short(), DUNDI_IE_CAUSE, DUNDI_IE_EID, DUNDI_IE_ENCDATA, DUNDI_IE_EXPIRATION, DUNDI_IE_SHAREDKEY, DUNDI_IE_SIGNATURE, DUNDI_IE_UNKNOWN, DUNDI_MODEL_INBOUND, dundi_parse_ies(), dundi_prop_precache(), dundi_send(), dundi_showframe(), dundi_peer::dynamic, dundi_transaction::ecx, dundi_answer::eid, dundi_result::eid, dundi_peer::eid, dundi_result::eid_str, dundi_ies::eids, dundi_entity_info::email, dundi_ies::encblock, dundi_encblock::encdata, dundi_ies::enclen, dundi_ies::encsharedkey, dundi_ies::encsig, dundi_request::expiration, dundi_result::expiration, dundi_ies::expiration, dundi_hint_metadata::exten, find_peer(), FLAG_ENCRYPT, FLAG_SENDFULLKEY, dundi_answer::flags, dundi_result::flags, dundi_packet::h, has_permission(), dundi_ies::hint, dundi_request::hmd, dundi_hdr::ies, inaddrcmp(), dundi_peer::include, dundi_peer::inkey, dundi_entity_info::ipaddr, dundi_transaction::iseqno, dundi_encblock::iv, dundi_ies::keycrc32, dundi_transaction::lasttrans, dundi_entity_info::locality, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, MAX_PACKET_SIZE, dundi_request::maxcount, dundi_peer::model, dundi_request::number, option_verbose, dundi_entity_info::org, dundi_entity_info::orgunit, dundi_transaction::oseqno, dundi_hdr::oseqno, dundi_transaction::parent, dundi_peer::pcmodel, dundi_peer::permit, dundi_entity_info::phone, dundi_answer::protocol, dundi_ies::q_country, dundi_ies::q_dept, dundi_ies::q_email, dundi_ies::q_ipaddr, dundi_ies::q_locality, dundi_ies::q_org, dundi_ies::q_phone, dundi_ies::q_stateprov, qualify_peer(), dundi_request::query_eid, dundi_peer::registerexpire, reset_transaction(), dundi_request::respcount, dundi_peer::sentfullkey, dundi_entity_info::stateprov, dundi_result::tech, tech2str(), dundi_result::techint, dundi_peer::them_dcx, dundi_peer::them_ecx, dundi_transaction::them_eid, dundi_peer::txenckey, dundi_peer::us_eid, dundi_transaction::us_eid, VERBOSE_PREFIX_3, dundi_answer::weight, and dundi_result::weight.

Referenced by handle_frame().

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

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

Definition at line 1947 of file pbx_dundi.c.

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

Referenced by socket_read().

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

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

Definition at line 294 of file pbx_dundi.c.

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

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

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

char* key | ( | void |  | ) |

Returns the ASTERISK_GPL_KEY.

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

     char *key(void) {
             return ASTERISK_GPL_KEY;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 4834 of file pbx_dundi.c.

References ASTERISK_GPL_KEY.

    04835 {
    04836    return ASTERISK_GPL_KEY;
    04837 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

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

Returns:
  int Always 0.

TE STUFF END

Definition at line 4746 of file pbx_dundi.c.

References ast_cli_register(), ast_custom_function_register(), ast_inet_ntoa(), ast_log(), ast_register_application(), ast_register_switch(), ast_verbose(), dundi_debug_output(), dundi_error_output(), dundi_lookup_exec(), DUNDI_PORT, dundi_set_error(), dundi_set_output(), io_context_create(), LOG_ERROR, LOG_WARNING, option_verbose, sched_context_create(), set_config(), start_network_thread(), and VERBOSE_PREFIX_2.

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

static void load_password | ( | void |  | ) | `[static]`

Definition at line 2045 of file pbx_dundi.c.

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

Referenced by set_config().

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

static void mark_mappings | ( | void |  | ) | `[static]`

Definition at line 4018 of file pbx_dundi.c.

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

Referenced by set_config().

    04019 {
    04020    struct dundi_mapping *map;
    04021    ast_mutex_lock(&peerlock);
    04022    map = mappings;
    04023    while(map) {
    04024       map->dead = 1;
    04025       map = map->next;
    04026    }
    04027    ast_mutex_unlock(&peerlock);
    04028 }

static void mark_peers | ( | void |  | ) | `[static]`

Definition at line 4006 of file pbx_dundi.c.

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

Referenced by set_config().

    04007 {
    04008    struct dundi_peer *peer;
    04009    ast_mutex_lock(&peerlock);
    04010    peer = peers;
    04011    while(peer) {
    04012       peer->dead = 1;
    04013       peer = peer->next;
    04014    }
    04015    ast_mutex_unlock(&peerlock);
    04016 }

static char* model2str | ( | int | model | ) | `[static]`

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

    02236 {
    02237    switch(model) {
    02238    case DUNDI_MODEL_INBOUND:
    02239       return "Inbound";
    02240    case DUNDI_MODEL_OUTBOUND:
    02241       return "Outbound";
    02242    case DUNDI_MODEL_SYMMETRIC:
    02243       return "Symmetric";
    02244    default:
    02245       return "Unknown";
    02246    }
    02247 }

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

Definition at line 2101 of file pbx_dundi.c.

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

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

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

Definition at line 3281 of file pbx_dundi.c.

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

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

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

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

Definition at line 4263 of file pbx_dundi.c.

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

Referenced by build_peer().

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

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

Definition at line 3130 of file pbx_dundi.c.

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

Referenced by precache_transactions().

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

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

Definition at line 3231 of file pbx_dundi.c.

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

Referenced by dundi_precache_internal().

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

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

Definition at line 2123 of file pbx_dundi.c.

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

Referenced by start_network_thread().

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

static void prune_mappings | ( | void |  | ) | `[static]`

Definition at line 4081 of file pbx_dundi.c.

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

Referenced by set_config().

    04082 {
    04083    struct dundi_mapping *map, *prev, *next;
    04084    ast_mutex_lock(&peerlock);
    04085    map = mappings;
    04086    prev = NULL;
    04087    while(map) {
    04088       next = map->next;
    04089       if (map->dead) {
    04090          if (prev)
    04091             prev->next = map->next;
    04092          else
    04093             mappings = map->next;
    04094          destroy_map(map);
    04095       } else
    04096          prev = map;
    04097       map = next;
    04098    }
    04099    ast_mutex_unlock(&peerlock);
    04100 }

static void prune_peers | ( | void |  | ) | `[static]`

Definition at line 4060 of file pbx_dundi.c.

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

    04061 {
    04062    struct dundi_peer *peer, *prev, *next;
    04063    ast_mutex_lock(&peerlock);
    04064    peer = peers;
    04065    prev = NULL;
    04066    while(peer) {
    04067       next = peer->next;
    04068       if (peer->dead) {
    04069          if (prev)
    04070             prev->next = peer->next;
    04071          else
    04072             peers = peer->next;
    04073          destroy_peer(peer);
    04074       } else
    04075          prev = peer;
    04076       peer = next;
    04077    }
    04078    ast_mutex_unlock(&peerlock);
    04079 }

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

Definition at line 4238 of file pbx_dundi.c.

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

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

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

static int query_transactions | ( | struct dundi_request * | dr | ) | `[static]`

Definition at line 3268 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dundi_query(), dundi_transaction::next, and dundi_request::trans.

Referenced by dundi_query_eid_internal().

    03269 {
    03270    struct dundi_transaction *trans;
    03271    ast_mutex_lock(&peerlock);
    03272    trans = dr->trans;
    03273    while(trans) {
    03274       dundi_query(trans);
    03275       trans = trans->next;
    03276    }
    03277    ast_mutex_unlock(&peerlock);
    03278    return 0;
    03279 }

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

Definition at line 3453 of file pbx_dundi.c.

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

Referenced by dundi_lookup_internal().

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

int reload | ( | void |  | ) |

Reload stuff.

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

Returns:
  The return value is not used.

Definition at line 4739 of file pbx_dundi.c.

References set_config().

    04740 {
    04741    struct sockaddr_in sin;
    04742    set_config("dundi.conf",&sin);
    04743    return 0;
    04744 }

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

Definition at line 3652 of file pbx_dundi.c.

References ast_mutex_lock(), ast_mutex_unlock(), dundi_precache_queue::context, dundi_precache_queue::expiration, malloc, dundi_precache_queue::next, 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=NULL;
    03656    ast_mutex_lock(&pclock);
    03657    qe = pcq;
    03658    while(qe) {
    03659       if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) {
    03660          if (prev)
    03661             prev->next = qe->next;
    03662          else
    03663             pcq = qe->next;
    03664          qe->next = NULL;
    03665          break;
    03666       }
    03667       prev = qe;
    03668       qe = qe->next;
    03669    };
    03670    if (!qe) {
    03671       len = sizeof(struct dundi_precache_queue);
    03672       len += strlen(number) + 1;
    03673       len += strlen(context) + 1;
    03674       qe = malloc(len);
    03675       if (qe) {
    03676          memset(qe, 0, len);
    03677          strcpy(qe->number, number);
    03678          qe->context = qe->number + strlen(number) + 1;
    03679          strcpy(qe->context, context);
    03680       }
    03681    }
    03682    time(&qe->expiration);
    03683    qe->expiration += expiration;
    03684    prev = pcq;
    03685    if (prev) {
    03686       while(prev->next && (prev->next->expiration <= qe->expiration))
    03687          prev = prev->next;
    03688       qe->next = prev->next;
    03689       prev->next = qe;
    03690    } else
    03691       pcq = qe;
    03692    ast_mutex_unlock(&pclock);
    03693
    03694 }

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

Definition at line 2279 of file pbx_dundi.c.

References dundi_result::weight.

Referenced by sort_results().

    02280 {
    02281    const struct dundi_result *resa, *resb;
    02282    resa = a;
    02283    resb = b;
    02284    if (resa->weight < resb->weight)
    02285       return -1;
    02286    if (resa->weight > resb->weight)
    02287       return 1;
    02288    return 0;
    02289 }

static void reset_global_eid | ( | void |  | ) | `[static]`

Definition at line 407 of file pbx_dundi.c.

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

Referenced by set_config().

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

static int reset_transaction | ( | struct dundi_transaction * | trans | ) | `[static]`

Definition at line 473 of file pbx_dundi.c.

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

Referenced by handle_command_response().

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

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

Definition at line 2032 of file pbx_dundi.c.

References ast_db_put(), and DUNDI_SECRET_TIME.

Referenced by check_password(), and load_password().

    02033 {
    02034    char tmp[256];
    02035    if (oldkey)
    02036       snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey);
    02037    else
    02038       snprintf(tmp, sizeof(tmp), "%s", newkey);
    02039    rotatetime = time(NULL) + DUNDI_SECRET_TIME;
    02040    ast_db_put(secretpath, "secret", tmp);
    02041    snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime);
    02042    ast_db_put(secretpath, "secretexpiry", tmp);
    02043 }

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

Definition at line 4559 of file pbx_dundi.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), ast_variable_browse(), build_mapping(), build_peer(), cfg, DEFAULT_MAXMS, DUNDI_DEFAULT_CACHE_TIME, DUNDI_DEFAULT_TTL, DUNDI_MODEL_OUTBOUND, dundi_precache_full(), dundi_str_to_eid(), format, hp, IPTOS_MINCOST, ast_variable::lineno, load_password(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, mark_mappings(), mark_peers(), ast_variable::name, ast_variable::next, prune_mappings(), prune_peers(), reset_global_eid(), and ast_variable::value.

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

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

Definition at line 1989 of file pbx_dundi.c.

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

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

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

Definition at line 2291 of file pbx_dundi.c.

References rescomp().

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

    02292 {
    02293    qsort(results, count, sizeof(results[0]), rescomp);
    02294 }

static int start_network_thread | ( | void |  | ) | `[static]`

Definition at line 2157 of file pbx_dundi.c.

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

    02158 {
    02159    ast_pthread_create(&netthreadid, NULL, network_thread, NULL);
    02160    ast_pthread_create(&precachethreadid, NULL, process_precache, NULL);
    02161    return 0;
    02162 }

static int str2tech | ( | char * | str | ) | `[static]`

Definition at line 321 of file pbx_dundi.c.

References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, and DUNDI_PROTO_SIP.

Referenced by build_mapping().

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

static char* tech2str | ( | int | tech | ) | `[static]`

Definition at line 305 of file pbx_dundi.c.

References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, DUNDI_PROTO_NONE, and DUNDI_PROTO_SIP.

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

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

int unload_module | ( | void |  | ) |

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
  Zero on success, or non-zero on error.

Standard module functions ...

Definition at line 4713 of file pbx_dundi.c.

References ast_cli_unregister(), ast_custom_function_unregister(), ast_unregister_application(), ast_unregister_switch(), sched_context_destroy(), and STANDARD_HANGUP_LOCALUSERS.

    04714 {
    04715    int res;
    04716    STANDARD_HANGUP_LOCALUSERS;
    04717    ast_cli_unregister(&cli_debug);
    04718    ast_cli_unregister(&cli_store_history);
    04719    ast_cli_unregister(&cli_flush);
    04720    ast_cli_unregister(&cli_no_debug);
    04721    ast_cli_unregister(&cli_no_store_history);
    04722    ast_cli_unregister(&cli_show_peers);
    04723    ast_cli_unregister(&cli_show_entityid);
    04724    ast_cli_unregister(&cli_show_trans);
    04725    ast_cli_unregister(&cli_show_requests);
    04726    ast_cli_unregister(&cli_show_mappings);
    04727    ast_cli_unregister(&cli_show_precache);
    04728    ast_cli_unregister(&cli_show_peer);
    04729    ast_cli_unregister(&cli_lookup);
    04730    ast_cli_unregister(&cli_precache);
    04731    ast_cli_unregister(&cli_queryeid);
    04732    ast_unregister_switch(&dundi_switch);
    04733    ast_custom_function_unregister(&dundi_function);
    04734    res = ast_unregister_application(app);
    04735    sched_context_destroy(sched);
    04736    return res;
    04737 }

static void unregister_request | ( | struct dundi_request * | dr | ) | `[static]`

Definition at line 3487 of file pbx_dundi.c.

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

Referenced by dundi_lookup_internal().

    03488 {
    03489    struct dundi_request *cur, *prev;
    03490    ast_mutex_lock(&peerlock);
    03491    prev = NULL;
    03492    cur = requests;
    03493    while(cur) {
    03494       if (cur == dr) {
    03495          if (prev)
    03496             prev->next = cur->next;
    03497          else
    03498             requests = cur->next;
    03499          break;
    03500       }
    03501       prev = cur;
    03502       cur = cur->next;
    03503    }
    03504    ast_mutex_unlock(&peerlock);
    03505 }

static int update_key | ( | struct dundi_peer * | peer | ) | `[static]`

Definition at line 1303 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, key(), dundi_peer::keyexpire, LOG_NOTICE, dundi_peer::outkey, dundi_peer::sentfullkey, dundi_peer::txenckey, dundi_peer::us_dcx, dundi_peer::us_ecx, and dundi_peer::us_keycrc32.

Referenced by dundi_encrypt().

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

int usecount | ( | void |  | ) |

Provides a usecount.

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

Returns:
  The module's usecount.

Definition at line 4825 of file pbx_dundi.c.

References STANDARD_USECOUNT.

    04826 {
    04827    int res;
    04828    /* XXX DUNDi cannot be unloaded XXX */
    04829    return 1;
    04830    STANDARD_USECOUNT(res);
    04831    return res;
    04832 }

## Variable Documentation

struct dundi_transaction * alltrans

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

char* app = "DUNDiLookup"`[static]`

Definition at line 82 of file pbx_dundi.c.

char ast_config_AST_KEY_DIR[]

Definition at line 221 of file asterisk.c.

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

int authdebug = 0`[static]`

Definition at line 129 of file pbx_dundi.c.

struct ast_cli_entry cli_debug`[static]`

Initial value:

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

Definition at line 2733 of file pbx_dundi.c.

struct ast_cli_entry cli_flush`[static]`

Initial value:

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

Definition at line 2742 of file pbx_dundi.c.

struct ast_cli_entry cli_lookup`[static]`

Initial value:

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

Definition at line 2769 of file pbx_dundi.c.

struct ast_cli_entry cli_no_debug`[static]`

Initial value:

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

Definition at line 2745 of file pbx_dundi.c.

struct ast_cli_entry cli_no_store_history`[static]`

Initial value:

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

Definition at line 2739 of file pbx_dundi.c.

struct ast_cli_entry cli_precache`[static]`

Initial value:

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

Definition at line 2772 of file pbx_dundi.c.

struct ast_cli_entry cli_queryeid`[static]`

Initial value:

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

Definition at line 2775 of file pbx_dundi.c.

struct ast_cli_entry cli_show_entityid`[static]`

Initial value:

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

Definition at line 2754 of file pbx_dundi.c.

struct ast_cli_entry cli_show_mappings`[static]`

Initial value:

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

Definition at line 2757 of file pbx_dundi.c.

struct ast_cli_entry cli_show_peer`[static]`

Initial value:

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

Definition at line 2766 of file pbx_dundi.c.

struct ast_cli_entry cli_show_peers`[static]`

Initial value:

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

Definition at line 2748 of file pbx_dundi.c.

struct ast_cli_entry cli_show_precache`[static]`

Initial value:

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

Definition at line 2760 of file pbx_dundi.c.

struct ast_cli_entry cli_show_requests`[static]`

Initial value:

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

Definition at line 2763 of file pbx_dundi.c.

struct ast_cli_entry cli_show_trans`[static]`

Initial value:

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

Definition at line 2751 of file pbx_dundi.c.

struct ast_cli_entry cli_store_history`[static]`

Initial value:

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

Definition at line 2736 of file pbx_dundi.c.

char country[80]`[static]`

Definition at line 141 of file pbx_dundi.c.

Referenced by ind_load_module().

char cursecret[80]`[static]`

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

int default_expiration = 60`[static]`

Definition at line 135 of file pbx_dundi.c.

char dept[80]`[static]`

Definition at line 137 of file pbx_dundi.c.

char* descrip`[static]`

Definition at line 84 of file pbx_dundi.c.

int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME`[static]`

Definition at line 132 of file pbx_dundi.c.

int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE`[static]`

Definition at line 131 of file pbx_dundi.c.

struct ast_switch dundi_switch`[static]`

Definition at line 4549 of file pbx_dundi.c.

int dundi_ttl = DUNDI_DEFAULT_TTL`[static]`

Definition at line 130 of file pbx_dundi.c.

int dundidebug = 0`[static]`

Definition at line 128 of file pbx_dundi.c.

char email[80]`[static]`

Definition at line 142 of file pbx_dundi.c.

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

Definition at line 148 of file pbx_dundi.c.

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

int global_autokilltimeout = 0`[static]`

Definition at line 133 of file pbx_dundi.c.

dundi_eid global_eid`[static]`

Definition at line 134 of file pbx_dundi.c.

int global_storehistory = 0`[static]`

Definition at line 136 of file pbx_dundi.c.

struct io_context* io`[static]`

Definition at line 122 of file pbx_dundi.c.

char ipaddr[80]`[static]`

Definition at line 146 of file pbx_dundi.c.

Referenced by realtime_update_peer().

LOCAL_USER_DECL

Definition at line 2780 of file pbx_dundi.c.

char locality[80]`[static]`

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

struct dundi_mapping * mappings`[static]`

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

int netsocket = -1`[static]`

Definition at line 124 of file pbx_dundi.c.

Referenced by ast_netsock_bindaddr(), and handle_error().

pthread_t netthreadid = AST_PTHREADT_NULL`[static]`

Definition at line 125 of file pbx_dundi.c.

char no_debug_usage[]`[static]`

Initial value:

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

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

char org[80]`[static]`

Definition at line 138 of file pbx_dundi.c.

struct dundi_precache_queue* pcq`[static]`

Definition at line 276 of file pbx_dundi.c.

struct dundi_peer * peers`[static]`

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

char phone[80]`[static]`

Definition at line 143 of file pbx_dundi.c.

Referenced by 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 2715 of file pbx_dundi.c.

pthread_t precachethreadid = AST_PTHREADT_NULL`[static]`

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

struct dundi_request * requests

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

time_t rotatetime`[static]`

Definition at line 147 of file pbx_dundi.c.

struct sched_context* sched`[static]`

Definition at line 123 of file pbx_dundi.c.

char secretpath[80]`[static]`

Definition at line 144 of file pbx_dundi.c.

char show_entityid_usage[]`[static]`

Initial value:

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

Definition at line 2697 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 2689 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 2701 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 2681 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 2693 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 2705 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 2685 of file pbx_dundi.c.

STANDARD_LOCAL_USER

Definition at line 2778 of file pbx_dundi.c.

char stateprov[80]`[static]`

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

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

Definition at line 83 of file pbx_dundi.c.

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

Definition at line 80 of file pbx_dundi.c.

int tos = 0`[static]`

Definition at line 127 of file pbx_dundi.c.